match imports and variables against their canonical name#21
match imports and variables against their canonical name#21ashanbrown merged 4 commits intoashanbrown:masterfrom
Conversation
|
The corresponding change in in golangci-lint is small: diff --git a/pkg/golinters/forbidigo.go b/pkg/golinters/forbidigo.go
index a8c256b9..b7c467f7 100644
--- a/pkg/golinters/forbidigo.go
+++ b/pkg/golinters/forbidigo.go
@@ -64,7 +64,7 @@ func runForbidigo(pass *analysis.Pass, settings *config.ForbidigoSettings) ([]go
var issues []goanalysis.Issue
for _, file := range pass.Files {
- hints, err := forbid.Run(pass.Fset, file)
+ hints, err := forbid.Run(pass, file)
if err != nil {
return nil, errors.Wrapf(err, "forbidigo linter failed on file %q", file.Name.String())
}However, I have only tested that it builds. When running "go test ./..." in golangci-lint I got several unrelated test failures. |
97821fb to
bcd9be6
Compare
|
I tried the modified golangci-lint in Kubernetes and it worked as intended: -> That was with #22, otherwise it would have complained also in non-test code. |
|
Thanks for the proposal. My understanding is that the way this works is to find matches for both the post-alias name of an identifier and the full unaliased package name of the identifier. I think you saw when integrating this with golangci lint that the proposal as it stands may be a breaking change for existing patterns. I think this is a real cause for concern and we should strive not to break existing patterns. Just for reference, it seems to me that there might be three cases we are concerned about: If someone has a pattern like My inclination would be to initially (when we create the linter) split up the patterns into legacy "naive" patterns (without package names or imports considered) and fully-qualified identifiers (i.e. those with package names) and then match each type of pattern against a different set of text values. The proposal to use We might also need a special way to identify standard packages and perhaps that could be done with a leading I am wondering how this with play with the proposal at #22, which was to be able to restrict patterns to specific files. This is an orthogonal concern with package names and something I've typically deferred to meta-linters. I'm wondering if we could use something like angle brackets @pohly I know this is a bit of a change from what you've proposed here and I appreciate all the effort you've put in already. Please let me know what you think. |
Agreed, that was also my thinking.
Is that something that you expect to happen in practice, or is this just a theoretic concern? I agree that it can happen, but it seemed unlikely to me and (when it happens) easy to fix by changing the pattern.
As you noted, just checking for
Then we'll have four kinds of patterns?! That doesn't sound appealing. Let's try something else:
Then we don't need to change how patterns get configured, it's extremely unlikely that someone has written patterns with such subgroup names (i.e. existing patterns work as before), and each pattern gets matched only once (better performance).
True, except that golangci-lint doesn't seem to be on a path towards offering the necessary configuration options. |
|
I like this approach more than the initial one and it works in practice, too - even better! 😄 I've force-pushed an update. The bit set will make more sense with the also updated PR #22. |
|
Thanks for iterating on this, @pohly. The use of named subgroups to prevent breaking changes sounds good to me. I still am fond of the idea of using globs as a way of being able to exclude files, but I don't see that as being incompatible with named subgroups. We could still find a way to add glob-based file filters later. I'll try to finish reviewing this PR this weekend. |
d080f74 to
8dde8a8
Compare
|
One thing I'm not clear on is what should happen if we don't have the type info for an object. I think at the moment we silently don't match it. Are there cases we might want to raise an error? If your pattern expects a package and we don't have type info at all, that feels to me like it should just fail. If we do have type info but the left side of a selector doesn't appear to be a package (maybe it's a variable shadowing a package name), then that does seem like a case where we should just silently not match it. The latter case also seems like a case we could write a test for. |
|
I found that golangci-lint uses viper+mapstructure for parsing its config file, therefore my previous plan for using UnmarshalYAML fell apart. I came up with a different solution. Here's how this will look in golangci-lint (no PR yet, just a diff, include the per-file support): |
|
Thanks for the latest updates. I've created an MR at pohly#2 with a few suggestions. I've also got CI running again and it looks like golangci-lint is failing. Regarding the configuration, my inclination would not be to make our linter config compatible with golangci-lint (i.e. don't add tags for mapstructure). I'd be fine with duplicating code in golangci-lint to populate our structure. I'd prefer that I'd also still favor an alternative name for |
|
BTW, regarding golangci/golangci-lint@master...pohly:forbidigo-update, I don't see that this handles backwards-compatibility with the old string types. I have to admit that I'm not sure if it's even possible to unmarshal into a value that can be either a string or a yaml object. I imagine we could just unmarshal the entire config into an arbitrary object and then parse it from there. |
Okay, then I'll handle this entirely in golangci-lint.
My concern with the original
This is handled by adding |
|
Thanks for the additional changes and the flexibility on the flag name. Let's use So I can't remember if I raised this point before, but, if I understand this current state correctly, |
That sounds good.
That should work. It's covered by the "If we are lucky, the entire selector expression has a known type" part. There's a test case for it in It came out of my observation that trying to deduce the type of the selector entirely myself would have led down a rathole of basically supporting arbitrarily deep AST expressions. I then looked for something simpler and found that It sounds like we are almost done. I'll squash the commits and then do the remaining changes ( |
0db12ac to
7ca3c2e
Compare
|
No code changes in the first force-push. The second one contains the actual changes. |
It was possible to use fmt.Print by importing "fmt" under a different name. Now a pattern can get matched against the full package path instead of the import name. This is also useful to ban items from packages that may get imported under various different names. It was possible to forbid a function in a package, but not a method or field of a certain type in a package. The same approach for replacing the match text can now also be used for those. The only way of debugging was to single-step with a debugger and manually printing variables. This gets tiresome because in particular for the analyzer test, inner functions get called a lot. Debug log output during unit testing helps. Informing the user about text expansion may also be useful, but is not addressed yet.
Otherwise "go install" fails:
# github.com/golangci/golangci-lint/pkg/golinters/goanalysis
pkg/golinters/goanalysis/runner_loadingpackage.go:126:3: unknown field 'Instances' in struct literal of type types.Info
note: module requires Go 1.19
7a0344e to
2621c02
Compare
Python 2 is no longer available: W: https://download.docker.com/linux/ubuntu/dists/jammy/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details. E: Package 'python' has no installation candidate
|
The CI is also happy now. |
|
I've merged your MR! Thanks for keeping at it. These seem like exciting changes. I'll turn my attention to #22 later today. |
It was possible to use fmt.Print by importing "fmt" under a different name. Now a pattern can also get matched against the full package path. This is also useful to ban items from packages that may get imported under various different names.
For variables, the match can be against the type of the variable instead of the (usually) arbitrary variable name.
Fixes #20