-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Add constructorcheck linter #4937
base: master
Are you sure you want to change the base?
Conversation
Hey, thank you for opening your first Pull Request ! |
In order for a pull request adding a linter to be reviewed, the linter and the PR must follow some requirements.
Pull Request Description
Linter
The Linter Tests Inside Golangci-lint
|
Yeah, looks similar indeed.
|
This code is a major problem.
It's a minor difference and I feel this will lead to wrong suggestions when there are several "constructors". |
BTW, is there a different way to get the list of standard library packages? This hack with calling |
This should never be called at runtime. |
It uses a very strict definition of what is a constructor - it's a function NewT, where T is the name of a type, existing in the same package, that returns only one value of the same type T. You can not have two of them in the same package because every function name must be unique within a package. I don't see a potential for a confusion here. As for the standard library package list - I agree that I need to find a different way to do it. |
I can easily see it: type Foo struct{}
func NewFoo(a string) *Foo { return nil }
func NewFooWithOption(b string) *Foo { return nil } type Bar struct{}
// Deprecated: use NewBarWithOption
func NewBar(a string) *Bar { return nil }
func NewBarWithOption(b string) *Bar { return nil } What will be the constructor suggested by your linter in those 2 cases? In the first case, no constructors must be suggested. Like I already said this is a minor difference. But this difference will lead to false positives and this is something we want to avoid inside golangci-lint. We can also talk about basic package-oriented constructors: type Foo struct{}
func New() *Foo { return nil } It will lead to false negatives. |
You're the first person giving me good feedback :) |
Maybe I misunderstood this part but I'd like to add that it's not uncommon for constructors to be fallible (and if so, sometimes such constructors might have a type Foo struct {}
func NewFoo() (*Foo, error) {
if err := setup(); err != nil {
return nil, err
}
return &Foo{}, nil
}
func MustNewFoo() *Foo {
foo, err := NewFoo()
if err != nil {
panic(err)
}
return foo
} |
Yes, also sometimes constructors return something like this: But I'm much more worried about being misleading and giving false error messages than missing something. The latter makes the linter not 100% efficient, the former makes it unusable. |
Go itself does it all over the place. I will try to dig how the go tool itself does it and see if it makes sense to copy the implementation from there. UPD: fortunately it's quite simple: |
constructorcheck reports places where you create values directly from a type (
T{}
ornew(T)
) ignoring a constructorNewT
defined for this type in the same package as the type.This is useful to avoid skipping initialization/validation for a type.
Types defined in the standard library are excluded from analysis.
The linter doesn't have any parameters at the moment.