From d249a04dfb9558eb0c118cd54494596c3cbf66dd Mon Sep 17 00:00:00 2001 From: Artem Kusch Date: Mon, 1 Jul 2024 11:47:29 +0300 Subject: [PATCH] Add fparams linter --- .golangci.reference.yml | 11 ++ go.mod | 5 +- go.sum | 3 + pkg/config/linters_settings.go | 6 + pkg/golinters/fparams/fparams.go | 28 +++++ .../fparams/fparams_integration_test.go | 11 ++ .../fparams/testdata/fix/in/fparams.go | 74 +++++++++++ .../fparams/testdata/fix/out/fparams.go | 100 +++++++++++++++ pkg/golinters/fparams/testdata/fparams.go | 117 ++++++++++++++++++ pkg/lint/lintersdb/builder_linter.go | 7 ++ 10 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 pkg/golinters/fparams/fparams.go create mode 100644 pkg/golinters/fparams/fparams_integration_test.go create mode 100644 pkg/golinters/fparams/testdata/fix/in/fparams.go create mode 100644 pkg/golinters/fparams/testdata/fix/out/fparams.go create mode 100644 pkg/golinters/fparams/testdata/fparams.go diff --git a/.golangci.reference.yml b/.golangci.reference.yml index fc9e73f27774..2fd80081ce08 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -427,6 +427,15 @@ linters-settings: # Default: false analyze-types: true + fparams: + # Disable check function params + # Default: false + disableCheckFuncParams: false + + # Disable check function return values + # Default false + disableCheckFuncReturns: false + funlen: # Checks the number of lines in a function. # If lower than 0, disable the check. @@ -2593,6 +2602,7 @@ linters: - fatcontext - forbidigo - forcetypeassert + - fparams - funlen - gci - ginkgolinter @@ -2708,6 +2718,7 @@ linters: - fatcontext - forbidigo - forcetypeassert + - fparams - funlen - gci - ginkgolinter diff --git a/go.mod b/go.mod index 0fedbe42fd83..b7ee7b340af0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/golangci/golangci-lint -go 1.21.0 +go 1.22 + +toolchain go1.22.4 require ( 4d63.com/gocheckcompilerdirectives v1.2.1 @@ -19,6 +21,7 @@ require ( github.com/alexkohler/nakedret/v2 v2.0.4 github.com/alexkohler/prealloc v1.0.0 github.com/alingse/asasalint v0.0.11 + github.com/artemk1337/fparams v1.0.0 github.com/ashanbrown/forbidigo v1.6.0 github.com/ashanbrown/makezero v1.1.1 github.com/bkielbasa/cyclop v1.2.1 diff --git a/go.sum b/go.sum index ad03d4b1f873..8122d04235c4 100644 --- a/go.sum +++ b/go.sum @@ -78,6 +78,9 @@ github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQ github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/artemk1337/fparams v0.0.2 h1:qqRyv+DyNP96l/gjDiTAlZUqkvd/VfyYnRNKNnji3oE= +github.com/artemk1337/fparams v0.0.2/go.mod h1:RAmfVQOF2V1jxm6gwkvRmTHjIfHO718H7z9DKq9QIns= +github.com/artemk1337/fparams v1.0.0/go.mod h1:RAmfVQOF2V1jxm6gwkvRmTHjIfHO718H7z9DKq9QIns= github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index f159db2a96d8..cbe5776804d8 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -212,6 +212,7 @@ type LintersSettings struct { Exhaustive ExhaustiveSettings Exhaustruct ExhaustructSettings Forbidigo ForbidigoSettings + Fparams Fparams Funlen FunlenSettings Gci GciSettings GinkgoLinter GinkgoLinterSettings @@ -455,6 +456,11 @@ func (p *ForbidigoPattern) MarshalString() ([]byte, error) { return yaml.Marshal(p) } +type Fparams struct { + DisableCheckFuncParams bool `mapstructure:"disable-check-params"` + DisableCheckFuncReturns bool `mapstructure:"disable-check-returns"` +} + type FunlenSettings struct { Lines int Statements int diff --git a/pkg/golinters/fparams/fparams.go b/pkg/golinters/fparams/fparams.go new file mode 100644 index 000000000000..fbca0421599e --- /dev/null +++ b/pkg/golinters/fparams/fparams.go @@ -0,0 +1,28 @@ +package fparams + +import ( + "github.com/artemk1337/fparams/pkg/analyzer" + "github.com/golangci/golangci-lint/pkg/config" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/goanalysis" +) + +func New(settings *config.Fparams) *goanalysis.Linter { + a := analyzer.NewAnalyzer() + + cfg := map[string]map[string]any{} + if settings != nil { + cfg[a.Name] = map[string]any{ + "disableCheckFuncParams": settings.DisableCheckFuncParams, + "disableCheckFuncReturns": settings.DisableCheckFuncReturns, + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/fparams/fparams_integration_test.go b/pkg/golinters/fparams/fparams_integration_test.go new file mode 100644 index 000000000000..1d309646cc8a --- /dev/null +++ b/pkg/golinters/fparams/fparams_integration_test.go @@ -0,0 +1,11 @@ +package fparams + +import ( + "testing" + + "github.com/golangci/golangci-lint/test/testshared/integration" +) + +func TestFromTestdata(t *testing.T) { + integration.RunTestdata(t) +} diff --git a/pkg/golinters/fparams/testdata/fix/in/fparams.go b/pkg/golinters/fparams/testdata/fix/in/fparams.go new file mode 100644 index 000000000000..cda2386d4d57 --- /dev/null +++ b/pkg/golinters/fparams/testdata/fix/in/fparams.go @@ -0,0 +1,74 @@ +//golangcitest:args -Efparams +//golangcitest:expected_exitcode 0 +package fparams + +func invalidArgsFuncA(a int, + b string) { + return +} + +func invalidArgsFuncB(a, b int, + c string) { + return +} + +func invalidArgsFuncC(a, + b int, + c string, +) { + return +} + +func invalidArgsFuncD( + a, b int, + c string, +) { + return +} + +func invalidArgsAndResultsFuncA(a int, + b string) (c bool, + d error) { + return false, nil +} + +func invalidArgsAndResultsFuncB(a int, b int, + c string) ( + d bool, + e error) { + return false, nil +} + +func invalidResultsFuncA() (a bool, + b error) { + return false, nil +} + +func invalidResultsFuncB() ( + a bool, + b error) { + return false, nil +} + +func invalidResultsFuncC() ( + a bool, b error) { + return false, nil +} + +func invalidResultsFuncD() ( + a, b bool, + c error) { + return false, false, nil +} + +func invalidResultsFuncE() (bool, bool, + error) { + return false, false, nil +} + +func invalidResultsFuncF() ( + bool, + bool, + error) { + return false, false, nil +} diff --git a/pkg/golinters/fparams/testdata/fix/out/fparams.go b/pkg/golinters/fparams/testdata/fix/out/fparams.go new file mode 100644 index 000000000000..17e2eeb2149f --- /dev/null +++ b/pkg/golinters/fparams/testdata/fix/out/fparams.go @@ -0,0 +1,100 @@ +//golangcitest:args -Efparams +//golangcitest:expected_exitcode 0 +package fparams + +func invalidArgsFuncA( + a int, + b string, +) { + return +} + +func invalidArgsFuncB( + a int, + b int, + c string, +) { + return +} + +func invalidArgsFuncC( + a int, + b int, + c string, +) { + return +} + +func invalidArgsFuncD( + a int, + b int, + c string, +) { + return +} + +func invalidArgsAndResultsFuncA( + a int, + b string, +) ( + c bool, + d error, +) { + return false, nil +} + +func invalidArgsAndResultsFuncB( + a int, + b int, + c string, +) ( + d bool, + e error, +) { + return false, nil +} + +func invalidResultsFuncA() ( + a bool, + b error, +) { + return false, nil +} + +func invalidResultsFuncB() ( + a bool, + b error, +) { + return false, nil +} + +func invalidResultsFuncC() ( + a bool, + b error, +) { + return false, nil +} + +func invalidResultsFuncD() ( + a bool, + b bool, + c error, +) { + return false, false, nil +} + +func invalidResultsFuncE() ( + bool, + bool, + error, +) { + return false, false, nil +} + +func invalidResultsFuncF() ( + bool, + bool, + error, +) { + return false, false, nil +} diff --git a/pkg/golinters/fparams/testdata/fparams.go b/pkg/golinters/fparams/testdata/fparams.go new file mode 100644 index 000000000000..755a49ddae8d --- /dev/null +++ b/pkg/golinters/fparams/testdata/fparams.go @@ -0,0 +1,117 @@ +//golangcitest:args -Efparams +package testdata + +func multiLineFuncA( + a int, + b string, +) ( + c bool, + d error, +) { + return false, nil +} + +func multiLineFuncB( + a int, + b string, +) { + return +} + +func multiLineFuncC() ( + a bool, + b error, +) { + return false, nil +} + +func singleLineFuncA(a int, b string) (c bool, d error) { + return false, nil +} + +func singleLineFuncB(a int) (b bool, c error) { + return false, nil +} + +func singleLineFuncC(a int, b string) (c error) { + return nil +} + +func singleLineFuncD(int, string) error { + return nil +} + +func singleLineFuncE(_ int, _ string) error { + return nil +} + +func invalidArgsFuncA(a int, // want "the parameters of the function \"invalidArgsFuncA\" should be on separate lines" + b string) { + return +} + +func invalidArgsFuncB(a, b int, // want "the parameters of the function \"invalidArgsFuncB\" should be on separate lines" + c string) { + return +} + +func invalidArgsFuncC(a, // want "the parameters of the function \"invalidArgsFuncC\" should be on separate lines" + b int, + c string, +) { + return +} + +func invalidArgsFuncD( // want "the parameters of the function \"invalidArgsFuncD\" should be on separate lines" + a, b int, + c string, +) { + return +} + +func invalidArgsAndResultsFuncA(a int, // want "the parameters and return values of the function \"invalidArgsAndResultsFuncA\" should be on separate lines" + b string) (c bool, + d error) { + return false, nil +} + +func invalidArgsAndResultsFuncB(a int, b int, // want "the parameters and return values of the function \"invalidArgsAndResultsFuncB\" should be on separate lines" + c string) ( + d bool, + e error) { + return false, nil +} + +func invalidResultsFuncA() (a bool, // want "the return values of the function \"invalidResultsFuncA\" should be on separate lines" + b error) { + return false, nil +} + +func invalidResultsFuncB() ( // want "the return values of the function \"invalidResultsFuncB\" should be on separate lines" + a bool, + b error) { + return false, nil +} + +func invalidResultsFuncC() ( // want "the return values of the function \"invalidResultsFuncC\" should be on separate lines" + a bool, b error) { + return false, nil +} + +func invalidResultsFuncD() ( // want "the return values of the function \"invalidResultsFuncD\" should be on separate lines" + a, b bool, + c error) { + return false, false, nil +} + +func invalidResultsFuncE() (bool, bool, // want "the return values of the function \"invalidResultsFuncE\" should be on separate lines" + error) { + return false, false, nil +} + +func invalidResultsFuncF() ( // want "the return values of the function \"invalidResultsFuncF\" should be on separate lines" + bool, + bool, + error) { + return false, false, nil +} diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 7b83a81530a7..fe4e94b07ad5 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -30,6 +30,7 @@ import ( "github.com/golangci/golangci-lint/pkg/golinters/fatcontext" "github.com/golangci/golangci-lint/pkg/golinters/forbidigo" "github.com/golangci/golangci-lint/pkg/golinters/forcetypeassert" + "github.com/golangci/golangci-lint/pkg/golinters/fparams" "github.com/golangci/golangci-lint/pkg/golinters/funlen" "github.com/golangci/golangci-lint/pkg/golinters/gci" "github.com/golangci/golangci-lint/pkg/golinters/ginkgolinter" @@ -301,6 +302,12 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/Crocmagnon/fatcontext"), + linter.NewConfig(fparams.New(&cfg.LintersSettings.Fparams)). + WithSince("1.60.0"). + WithPresets(linter.PresetFormatting). + WithLoadForGoAnalysis(). + WithURL("https://github.com/artemk1337/fparamsx"), + linter.NewConfig(funlen.New(&cfg.LintersSettings.Funlen)). WithSince("v1.18.0"). WithPresets(linter.PresetComplexity).