-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't allow BasicLit
as error, suggest to make as const
#14
base: master
Are you sure you want to change the base?
Conversation
Thanks for opening this @bombsimon. I always appreciate the thoughtfulness you give to this topic. I'm very much on the fence about this one. While I don't see frequently, it is valid to make a custom error type, then define several variables that have values using that error type. I think the question for me is, if someone has named the variable with an |
This has not been an issue to me at all since it's allowing more than I need. I've very rarely seen custom errors (in a global scope) after error wrapping game along in Go 1.13. If you implement your own error it would usually be to add dynamic data and in that scenario a global error makes little sense to me. As suggested in #5 it would be nice to just ensure that the type implements the error interface but this is not easy. On the other hand the only positive false I can think of would be something describing error management, f.ex. With that in mind, would it be a better solution to just ensure that the value is not a If not, this is not something I feel very strong about so feel free to close this PR if you don't want to restrict the usage of global variables as long as they have the correct prefix. To avoid confusion it might be a good idea to close #5 as well if you decide on that. |
Agreed, but I don't know how we do that. I don't think we can get that from the AST, we'd been the compiler to resolve the types? Which would probably increase the cost of using this tool. I think it's a trade off.
I really like this idea. Independent of errors this ensures as you say that things that can be const are const. I'd need to check, but is a value that is a struct not a |
As far as I know only built in types are |
They can be converted to `cont` which the error message suggests
BasicLit
as error, suggest to make as const
Rebased on master and switched focus, this PR now only targets to disallow |
// myVar is just a bad named global var. | ||
var myVar = 1 // want "myVar is a global variable" | ||
|
||
// ErrNotFound is an error and should be OK. | ||
var ErrNotFound = errors.New("this is error") | ||
|
||
// ErrIsNotErr is an error and should be OK. | ||
var ErrIsNotErr = 1 // want "ErrIsNotErr is a global variable, should be a const" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something I'm noticing here is from the users perspective, knowing little about how we got here, that myVar = 1
and ErrIsNotErr = 1
look awfully alike and yet result in different errors.
I think the suggestion "should be a const" probably applies to any basic literal, not just errors. So instead of introducing it specifically as a feature for errors, we introduce it as a feature that applies to any var, as a suggestion. When a var is detected in this fashion, we don't bother checking the other exclusions, except the go:embed one, because any others can be changed to a const.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, of course! This is in fact already how it works and why I pass both the variable and it's value when doing the check now. We first search for *ast.BasicLit
and then we check the name.
The analyzer test package doesn't require the directive to match exactly, only a subset have to match, that's why the tests passed even though it didn't have the full error message.
I updated the test cases for myVar
, to make this clearer, everything that's assigned to a *ast.BasicLit
will see "should be a const".
@bombsimon I believe that #32 is going to address this issue as well. I'm going to merge it, at which point it should prevent basic literals, unless those basic literals are wrapped in some other type that is in fact an error. Do you agree? |
Super nice with that PR! It will ensure nothing but errors will be assigned to the global variable but it won't give a hint about what can be converted to a const instead. But maybe that's not a part of this linter's responsibility. Feel free to close this PR in favor of #32! |
Ahh yes that's a really good point. I think that's worthwhile because I don't think we want this linter to cause people to remove globals that could be const. I'll look at merging this after #32. |
This PR extends #12 which will only allow global error variables prefixed withErr
if they're assigned fromfmt.Errorf
orerrors.New
.This branch is based onwhitelisted-selectors
which makes the diff towardsmaster
looks bigger than it is. When(/if) #12 is merged I will rebase this branch to visualise the diff better.This PR is a result of #12 (comment) where I got asked to limit the first PR to only add support forregexp.MustCompile
and not touch error handling. I still think this PR is valid since there's a lot of missed errors not caught and since go 1.14 we shouldn't use custom error types if possible to avoid.Only allow global error variables if the're assigned fromfmt.Errorf
anderrors.New
. Relates to #5I know this is probably very opinionated but I'll just leave it here to marinate and use for discussion.Don't allow global vars, even if they're prefixed with
err
orErr
, to be assigned to a*ast.BasicLit
since these can be converted toconst
instead.