From 89f665c51d4d5cc8a488b4864053e2e621012de3 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Sun, 20 Mar 2022 23:27:07 +0300 Subject: [PATCH 1/7] feat: add `exhaustruct` linter This linter can be called a successor of `exhaustivestruct`, and: - it is at least **2.5+ times faster**, due to better algorithm; - can receive `include` and/or `exclude` patterns; - expects received patterns to be RegExp, therefore this package is not api-compatible with `exhaustivestruct`. Also: deprecate `exhaustivestruct` linter --- .golangci.example.yml | 10 +++ go.mod | 2 + go.sum | 4 + pkg/config/linters_settings.go | 6 ++ pkg/golinters/exhaustruct.go | 32 ++++++++ pkg/lint/lintersdb/manager.go | 11 ++- test/testdata/exhaustruct.go | 40 ++++++++++ test/testdata/exhaustruct_custom.go | 114 ++++++++++++++++++++++++++++ 8 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 pkg/golinters/exhaustruct.go create mode 100644 test/testdata/exhaustruct.go create mode 100644 test/testdata/exhaustruct_custom.go diff --git a/.golangci.example.yml b/.golangci.example.yml index 12f5c2f544d4..9d123f268bc9 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -285,6 +285,16 @@ linters-settings: - '*.Test' - 'example.com/package.ExampleStruct' + exhaustruct: + # List of regular expressions to match struct packages and names. + # If this list is empty, all structs are tested. + include: + - '.*\.Test' + - 'example\.com/package\.ExampleStruct' + # List of regular expressions to exclude struct packages and names from check. + exclude: + - 'cobra\.Command$' + forbidigo: # Forbid the following identifiers (list of regexp). forbid: diff --git a/go.mod b/go.mod index 9e654f3ae67f..037704a956c9 100644 --- a/go.mod +++ b/go.mod @@ -106,6 +106,8 @@ require ( mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5 ) +require github.com/GaijinEntertainment/go-exhaustruct v1.0.0 + require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index bf438564a43e..538e248b53c5 100644 --- a/go.sum +++ b/go.sum @@ -62,6 +62,10 @@ github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/GaijinEntertainment/go-exhaustruct v0.0.0-20220320194800-c73fb34375ae h1:vcGb2Pu07VvKQRgoEM6vq2i48lSFHZHs18lOLGYK+fk= +github.com/GaijinEntertainment/go-exhaustruct v0.0.0-20220320194800-c73fb34375ae/go.mod h1:jXk57htv8oR5kz8IClFCxBykWOwS2VWHRuRT4V+a5Xc= +github.com/GaijinEntertainment/go-exhaustruct v1.0.0 h1:z+MQsgpeFDwmVZqB78E1nig4TX8IAGXr/LczFNbqRPU= +github.com/GaijinEntertainment/go-exhaustruct v1.0.0/go.mod h1:jXk57htv8oR5kz8IClFCxBykWOwS2VWHRuRT4V+a5Xc= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 088223f0db62..cb4095d03aae 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -123,6 +123,7 @@ type LintersSettings struct { ErrorLint ErrorLintSettings Exhaustive ExhaustiveSettings ExhaustiveStruct ExhaustiveStructSettings + Exhaustruct ExhaustructSettings Forbidigo ForbidigoSettings Funlen FunlenSettings Gci GciSettings @@ -255,6 +256,11 @@ type ExhaustiveStructSettings struct { StructPatterns []string `mapstructure:"struct-patterns"` } +type ExhaustructSettings struct { + Include []string `mapstructure:"include"` + Exclude []string `mapstructure:"exclude"` +} + type ForbidigoSettings struct { Forbid []string `mapstructure:"forbid"` ExcludeGodocExamples bool `mapstructure:"exclude-godoc-examples"` diff --git a/pkg/golinters/exhaustruct.go b/pkg/golinters/exhaustruct.go new file mode 100644 index 000000000000..50c065310808 --- /dev/null +++ b/pkg/golinters/exhaustruct.go @@ -0,0 +1,32 @@ +package golinters + +import ( + "strings" + + "github.com/GaijinEntertainment/go-exhaustruct/pkg/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewExhaustruct(settings *config.ExhaustructSettings) *goanalysis.Linter { + a := analyzer.Analyzer + + var cfg map[string]map[string]interface{} + if settings != nil { + cfg = map[string]map[string]interface{}{ + a.Name: { + "include": strings.Join(settings.Include, ","), + "exclude": strings.Join(settings.Exclude, ","), + }, + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfg, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 4c405c0fcf61..0cb9dc073d6d 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -107,6 +107,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { var errorlintCfg *config.ErrorLintSettings var exhaustiveCfg *config.ExhaustiveSettings var exhaustiveStructCfg *config.ExhaustiveStructSettings + var exhaustructCfg *config.ExhaustructSettings var gciCfg *config.GciSettings var goModDirectivesCfg *config.GoModDirectivesSettings var goMndCfg *config.GoMndSettings @@ -140,6 +141,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { errorlintCfg = &m.cfg.LintersSettings.ErrorLint exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive exhaustiveStructCfg = &m.cfg.LintersSettings.ExhaustiveStruct + exhaustructCfg = &m.cfg.LintersSettings.Exhaustruct gciCfg = &m.cfg.LintersSettings.Gci goModDirectivesCfg = &m.cfg.LintersSettings.GoModDirectives goMndCfg = &m.cfg.LintersSettings.Gomnd @@ -281,7 +283,14 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithSince("v1.32.0"). WithPresets(linter.PresetStyle, linter.PresetTest). WithLoadForGoAnalysis(). - WithURL("https://github.com/mbilski/exhaustivestruct"), + WithURL("https://github.com/mbilski/exhaustivestruct"). + Deprecated("Owner seems to abandon linter.", "v1.46.0", "exhaustruct"), + + linter.NewConfig(golinters.NewExhaustruct(exhaustructCfg)). + WithSince("v1.46.0"). + WithPresets(linter.PresetStyle, linter.PresetTest). + WithLoadForGoAnalysis(). + WithURL("https://github.com/GaijinEntertainment/go-exhaustruct"), linter.NewConfig(golinters.NewExportLoopRef()). WithSince("v1.28.0"). diff --git a/test/testdata/exhaustruct.go b/test/testdata/exhaustruct.go new file mode 100644 index 000000000000..2f5d2432ceb7 --- /dev/null +++ b/test/testdata/exhaustruct.go @@ -0,0 +1,40 @@ +//args: -Eexhaustruct +package testdata + +import "time" + +type Test struct { + A string + B int + c bool // private field inside the same package are not ignored + D float64 + E time.Time +} + +var pass = Test{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), +} + +var failPrivate = Test{ // ERROR "c is missing in Test" + A: "a", + B: 0, + D: 1.0, + E: time.Now(), +} + +var fail = Test{ // ERROR "B is missing in Test" + A: "a", + c: false, + D: 1.0, + E: time.Now(), +} + +var failMultiple = Test{ // ERROR "B, D are missing in Test" + A: "a", + c: false, + E: time.Now(), +} diff --git a/test/testdata/exhaustruct_custom.go b/test/testdata/exhaustruct_custom.go new file mode 100644 index 000000000000..52d966511322 --- /dev/null +++ b/test/testdata/exhaustruct_custom.go @@ -0,0 +1,114 @@ +//args: -Eexhaustruct +//config: linters-settings.exhaustruct.include=.*\.Test1$ +//config: linters-settings.exhaustruct.exclude=.*\.Test3$ +package testdata + +import "time" + +type Test1 struct { + A string + B int + c bool // private field inside the same package are not ignored + D float64 + E time.Time +} + +var passTest1 = Test1{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), +} + +var failTest1 = Test1{ // ERROR "B is missing in Test" + A: "a", + c: false, + D: 1.0, + E: time.Now(), +} + +var failMultipleTest1 = Test1{ // ERROR "B, D are missing in Test" + A: "a", + c: false, + E: time.Now(), +} + +var failPrivateTest1 = Test1{ // ERROR "c is missing in Test" + A: "a", + B: 0, + D: 1.0, + E: time.Now(), +} + +type Test2 struct { + A string + B int + c bool // private field inside the same package are not ignored + D float64 + E time.Time +} + +var passTest2 = Test1{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), +} + +var failTest2 = Test2{ + A: "a", + c: false, + D: 1.0, + E: time.Now(), +} + +var failMultipleTest2 = Test2{ + A: "a", + c: false, + E: time.Now(), +} + +var failPrivateTest2 = Test2{ + A: "a", + B: 0, + D: 1.0, + E: time.Now(), +} + +type Test3 struct { + A string + B int + c bool // private field inside the same package are not ignored + D float64 + E time.Time +} + +var passTest3 = Test3{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), +} + +var failTest3 = Test3{ + A: "a", + c: false, + D: 1.0, + E: time.Now(), +} + +var failMultipleTest3 = Test3{ + A: "a", + c: false, + E: time.Now(), +} + +var failPrivateTest3 = Test3{ + A: "a", + B: 0, + D: 1.0, + E: time.Now(), +} From 47ec81a38e59318603b130c139360fa04dfbe4a7 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Wed, 30 Mar 2022 18:43:48 +0200 Subject: [PATCH 2/7] review: tests --- pkg/lint/lintersdb/manager.go | 2 +- test/testdata/configs/exhaustivestruct.yml | 5 + test/testdata/configs/exhaustruct.yml | 4 + test/testdata/exhaustivestruct.go | 56 ++++--- test/testdata/exhaustivestruct_custom.go | 178 +++++++++++--------- test/testdata/exhaustruct.go | 57 ++++--- test/testdata/exhaustruct_custom.go | 183 ++++++++++++--------- 7 files changed, 271 insertions(+), 214 deletions(-) create mode 100644 test/testdata/configs/exhaustivestruct.yml create mode 100644 test/testdata/configs/exhaustruct.yml diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 0cb9dc073d6d..434d435d03c4 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -284,7 +284,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetStyle, linter.PresetTest). WithLoadForGoAnalysis(). WithURL("https://github.com/mbilski/exhaustivestruct"). - Deprecated("Owner seems to abandon linter.", "v1.46.0", "exhaustruct"), + Deprecated("The owner seems to have abandoned the linter.", "v1.46.0", "exhaustruct"), linter.NewConfig(golinters.NewExhaustruct(exhaustructCfg)). WithSince("v1.46.0"). diff --git a/test/testdata/configs/exhaustivestruct.yml b/test/testdata/configs/exhaustivestruct.yml new file mode 100644 index 000000000000..21d69c55dd76 --- /dev/null +++ b/test/testdata/configs/exhaustivestruct.yml @@ -0,0 +1,5 @@ +linters-settings: + exhaustivestruct: + struct-patterns: + - '*.ExhaustiveStructCustom' + - '*.ExhaustiveStructCustom2' diff --git a/test/testdata/configs/exhaustruct.yml b/test/testdata/configs/exhaustruct.yml new file mode 100644 index 000000000000..614c1347717d --- /dev/null +++ b/test/testdata/configs/exhaustruct.yml @@ -0,0 +1,4 @@ +linters-settings: + exhaustruct: + include: ".*\\.ExhaustructCustom$" + exclude: ".*\\.ExhaustructCustom2" diff --git a/test/testdata/exhaustivestruct.go b/test/testdata/exhaustivestruct.go index 49b1ea98639d..fde230dfdce1 100644 --- a/test/testdata/exhaustivestruct.go +++ b/test/testdata/exhaustivestruct.go @@ -1,9 +1,9 @@ -//args: -Eexhaustivestruct +// args: -Eexhaustivestruct --internal-cmd-test package testdata import "time" -type Test struct { +type ExhaustiveStruct struct { A string B int c bool // private field inside the same package are not ignored @@ -11,30 +11,36 @@ type Test struct { E time.Time } -var pass = Test{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), -} +func exhaustiveStruct() { + // pass + _ = ExhaustiveStruct{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), + } -var failPrivate = Test{ // ERROR "c is missing in Test" - A: "a", - B: 0, - D: 1.0, - E: time.Now(), -} + // failPrivate + _ = ExhaustiveStruct{ // ERROR "c is missing in ExhaustiveStruct" + A: "a", + B: 0, + D: 1.0, + E: time.Now(), + } -var fail = Test{ // ERROR "B is missing in Test" - A: "a", - c: false, - D: 1.0, - E: time.Now(), -} + // fail + _ = ExhaustiveStruct{ // ERROR "B is missing in ExhaustiveStruct" + A: "a", + c: false, + D: 1.0, + E: time.Now(), + } -var failMultiple = Test{ // ERROR "B, D are missing in Test" - A: "a", - c: false, - E: time.Now(), + // failMultiple + _ = ExhaustiveStruct{ // ERROR "B, D are missing in ExhaustiveStruct" + A: "a", + c: false, + E: time.Now(), + } } diff --git a/test/testdata/exhaustivestruct_custom.go b/test/testdata/exhaustivestruct_custom.go index f3e1c7fa6fbf..156b7b631552 100644 --- a/test/testdata/exhaustivestruct_custom.go +++ b/test/testdata/exhaustivestruct_custom.go @@ -1,10 +1,10 @@ -//args: -Eexhaustivestruct -//config: linters-settings.exhaustivestruct.struct-patterns=*.Test1,*.Test3 +// args: -Eexhaustivestruct --internal-cmd-test +// config_path: testdata/configs/exhaustivestruct.yml package testdata import "time" -type Test1 struct { +type ExhaustiveStructCustom struct { A string B int c bool // private field inside the same package are not ignored @@ -12,35 +12,42 @@ type Test1 struct { E time.Time } -var passTest1 = Test1{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), -} - -var failTest1 = Test1{ // ERROR "B is missing in Test" - A: "a", - c: false, - D: 1.0, - E: time.Now(), -} - -var failMultipleTest1 = Test1{ // ERROR "B, D are missing in Test" - A: "a", - c: false, - E: time.Now(), -} +func exhaustiveStructCustom() { + // pass + _ = ExhaustiveStructCustom{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), + } + + // fail + _ = ExhaustiveStructCustom{ // ERROR "B is missing in ExhaustiveStructCustom" + A: "a", + c: false, + D: 1.0, + E: time.Now(), + } + + // failMultiple + _ = ExhaustiveStructCustom{ // ERROR "B, D are missing in ExhaustiveStructCustom" + A: "a", + c: false, + E: time.Now(), + } + + // failPrivate + _ = ExhaustiveStructCustom{ // ERROR "c is missing in ExhaustiveStructCustom" + A: "a", + B: 0, + D: 1.0, + E: time.Now(), + } -var failPrivateTest1 = Test1{ // ERROR "c is missing in Test" - A: "a", - B: 0, - D: 1.0, - E: time.Now(), } -type Test2 struct { +type ExhaustiveStructCustom1 struct { A string B int c bool // private field inside the same package are not ignored @@ -48,35 +55,37 @@ type Test2 struct { E time.Time } -var passTest2 = Test1{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), -} - -var failTest2 = Test2{ - A: "a", - c: false, - D: 1.0, - E: time.Now(), -} - -var failMultipleTest2 = Test2{ - A: "a", - c: false, - E: time.Now(), -} - -var failPrivateTest2 = Test2{ - A: "a", - B: 0, - D: 1.0, - E: time.Now(), +func exhaustiveStructCustom1() { + _ = ExhaustiveStructCustom1{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), + } + + _ = ExhaustiveStructCustom1{ + A: "a", + c: false, + D: 1.0, + E: time.Now(), + } + + _ = ExhaustiveStructCustom1{ + A: "a", + c: false, + E: time.Now(), + } + + _ = ExhaustiveStructCustom1{ + A: "a", + B: 0, + D: 1.0, + E: time.Now(), + } } -type Test3 struct { +type ExhaustiveStructCustom2 struct { A string B int c bool // private field inside the same package are not ignored @@ -84,30 +93,37 @@ type Test3 struct { E time.Time } -var passTest3 = Test3{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), -} - -var failTest3 = Test3{ // ERROR "B is missing in Test" - A: "a", - c: false, - D: 1.0, - E: time.Now(), -} - -var failMultipleTest3 = Test3{ // ERROR "B, D are missing in Test" - A: "a", - c: false, - E: time.Now(), -} +func exhaustiveStructCustom2() { + // pass + _ = ExhaustiveStructCustom2{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), + } + + // fail + _ = ExhaustiveStructCustom2{ // ERROR "B is missing in ExhaustiveStructCustom2" + A: "a", + c: false, + D: 1.0, + E: time.Now(), + } + + // failMultiple + _ = ExhaustiveStructCustom2{ // ERROR "B, D are missing in ExhaustiveStructCustom2" + A: "a", + c: false, + E: time.Now(), + } + + // failPrivate + _ = ExhaustiveStructCustom2{ // ERROR "c is missing in ExhaustiveStructCustom2" + A: "a", + B: 0, + D: 1.0, + E: time.Now(), + } -var failPrivateTest3 = Test3{ // ERROR "c is missing in Test" - A: "a", - B: 0, - D: 1.0, - E: time.Now(), } diff --git a/test/testdata/exhaustruct.go b/test/testdata/exhaustruct.go index 2f5d2432ceb7..6860e5e40e20 100644 --- a/test/testdata/exhaustruct.go +++ b/test/testdata/exhaustruct.go @@ -1,9 +1,9 @@ -//args: -Eexhaustruct +// args: -Eexhaustruct package testdata import "time" -type Test struct { +type Exhaustruct struct { A string B int c bool // private field inside the same package are not ignored @@ -11,30 +11,37 @@ type Test struct { E time.Time } -var pass = Test{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), -} +func exhaustruct() { + // pass + _ = Exhaustruct{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), + } -var failPrivate = Test{ // ERROR "c is missing in Test" - A: "a", - B: 0, - D: 1.0, - E: time.Now(), -} + // failPrivate + _ = Exhaustruct{ // ERROR "c is missing in Exhaustruct" + A: "a", + B: 0, + D: 1.0, + E: time.Now(), + } -var fail = Test{ // ERROR "B is missing in Test" - A: "a", - c: false, - D: 1.0, - E: time.Now(), -} + // fail + _ = Exhaustruct{ // ERROR "B is missing in Exhaustruct" + A: "a", + c: false, + D: 1.0, + E: time.Now(), + } + + // failMultiple + _ = Exhaustruct{ // ERROR "B, D are missing in Exhaustruct" + A: "a", + c: false, + E: time.Now(), + } -var failMultiple = Test{ // ERROR "B, D are missing in Test" - A: "a", - c: false, - E: time.Now(), } diff --git a/test/testdata/exhaustruct_custom.go b/test/testdata/exhaustruct_custom.go index 52d966511322..27e7b6a74c22 100644 --- a/test/testdata/exhaustruct_custom.go +++ b/test/testdata/exhaustruct_custom.go @@ -1,11 +1,10 @@ -//args: -Eexhaustruct -//config: linters-settings.exhaustruct.include=.*\.Test1$ -//config: linters-settings.exhaustruct.exclude=.*\.Test3$ +// args: -Eexhaustruct +// config_path: testdata/configs/exhaustruct.yml package testdata import "time" -type Test1 struct { +type ExhaustructCustom struct { A string B int c bool // private field inside the same package are not ignored @@ -13,35 +12,42 @@ type Test1 struct { E time.Time } -var passTest1 = Test1{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), -} - -var failTest1 = Test1{ // ERROR "B is missing in Test" - A: "a", - c: false, - D: 1.0, - E: time.Now(), -} - -var failMultipleTest1 = Test1{ // ERROR "B, D are missing in Test" - A: "a", - c: false, - E: time.Now(), -} +func exhaustructCustom() { + // pass + _ = ExhaustructCustom{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), + } + + // fail + _ = ExhaustructCustom{ // ERROR "B is missing in ExhaustructCustom" + A: "a", + c: false, + D: 1.0, + E: time.Now(), + } + + // failMultiple + _ = ExhaustructCustom{ // ERROR "B, D are missing in ExhaustructCustom" + A: "a", + c: false, + E: time.Now(), + } + + // failPrivate + _ = ExhaustructCustom{ // ERROR "c is missing in ExhaustructCustom" + A: "a", + B: 0, + D: 1.0, + E: time.Now(), + } -var failPrivateTest1 = Test1{ // ERROR "c is missing in Test" - A: "a", - B: 0, - D: 1.0, - E: time.Now(), } -type Test2 struct { +type ExhaustructCustom1 struct { A string B int c bool // private field inside the same package are not ignored @@ -49,35 +55,42 @@ type Test2 struct { E time.Time } -var passTest2 = Test1{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), -} - -var failTest2 = Test2{ - A: "a", - c: false, - D: 1.0, - E: time.Now(), -} - -var failMultipleTest2 = Test2{ - A: "a", - c: false, - E: time.Now(), -} +func exhaustructCustom1() { + // pass + _ = ExhaustructCustom{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), + } + + // fail + _ = ExhaustructCustom1{ + A: "a", + c: false, + D: 1.0, + E: time.Now(), + } + + // failMultiple + _ = ExhaustructCustom1{ + A: "a", + c: false, + E: time.Now(), + } + + // failPrivate + _ = ExhaustructCustom1{ + A: "a", + B: 0, + D: 1.0, + E: time.Now(), + } -var failPrivateTest2 = Test2{ - A: "a", - B: 0, - D: 1.0, - E: time.Now(), } -type Test3 struct { +type ExhaustructCustom2 struct { A string B int c bool // private field inside the same package are not ignored @@ -85,30 +98,36 @@ type Test3 struct { E time.Time } -var passTest3 = Test3{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), -} - -var failTest3 = Test3{ - A: "a", - c: false, - D: 1.0, - E: time.Now(), -} - -var failMultipleTest3 = Test3{ - A: "a", - c: false, - E: time.Now(), -} - -var failPrivateTest3 = Test3{ - A: "a", - B: 0, - D: 1.0, - E: time.Now(), +func exhaustructCustom2() { + // pass + _ = ExhaustructCustom2{ + A: "a", + B: 0, + c: false, + D: 1.0, + E: time.Now(), + } + + // fail + _ = ExhaustructCustom2{ + A: "a", + c: false, + D: 1.0, + E: time.Now(), + } + + // failMultiple + _ = ExhaustructCustom2{ + A: "a", + c: false, + E: time.Now(), + } + + // failPrivate + _ = ExhaustructCustom2{ + A: "a", + B: 0, + D: 1.0, + E: time.Now(), + } } From fa6858d8631564bed2b8f4c4c1eff40f86c97fba Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Wed, 30 Mar 2022 18:48:38 +0200 Subject: [PATCH 3/7] review: fix go.mod and go.sum --- go.mod | 3 +-- go.sum | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 037704a956c9..ddffc8af993a 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/Antonboom/nilnil v0.1.1 github.com/BurntSushi/toml v1.1.0 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 + github.com/GaijinEntertainment/go-exhaustruct v1.0.0 github.com/OpenPeeDeeP/depguard v1.1.0 github.com/alexkohler/prealloc v1.0.0 github.com/ashanbrown/forbidigo v1.3.0 @@ -106,8 +107,6 @@ require ( mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5 ) -require github.com/GaijinEntertainment/go-exhaustruct v1.0.0 - require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index 538e248b53c5..1caf03e634db 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,6 @@ github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct v0.0.0-20220320194800-c73fb34375ae h1:vcGb2Pu07VvKQRgoEM6vq2i48lSFHZHs18lOLGYK+fk= -github.com/GaijinEntertainment/go-exhaustruct v0.0.0-20220320194800-c73fb34375ae/go.mod h1:jXk57htv8oR5kz8IClFCxBykWOwS2VWHRuRT4V+a5Xc= github.com/GaijinEntertainment/go-exhaustruct v1.0.0 h1:z+MQsgpeFDwmVZqB78E1nig4TX8IAGXr/LczFNbqRPU= github.com/GaijinEntertainment/go-exhaustruct v1.0.0/go.mod h1:jXk57htv8oR5kz8IClFCxBykWOwS2VWHRuRT4V+a5Xc= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= From 91ee4cd28a7767a0f243a5966c788b06b2b7e209 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Sun, 10 Apr 2022 16:04:45 +0300 Subject: [PATCH 4/7] feat: update go-exhaustruct to v2 and adapt to API changes --- .golangci.example.yml | 2 +- go.mod | 2 +- go.sum | 2 ++ pkg/golinters/exhaustruct.go | 25 ++++++++----------------- test/testdata/configs/exhaustruct.yml | 6 ++++-- 5 files changed, 16 insertions(+), 21 deletions(-) diff --git a/.golangci.example.yml b/.golangci.example.yml index 9d123f268bc9..a7d20d071fb0 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -290,7 +290,7 @@ linters-settings: # If this list is empty, all structs are tested. include: - '.*\.Test' - - 'example\.com/package\.ExampleStruct' + - 'example\.com/package\.ExampleStruct[\d]{1,2}' # List of regular expressions to exclude struct packages and names from check. exclude: - 'cobra\.Command$' diff --git a/go.mod b/go.mod index ddffc8af993a..6b1e550f6ba3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Antonboom/nilnil v0.1.1 github.com/BurntSushi/toml v1.1.0 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 - github.com/GaijinEntertainment/go-exhaustruct v1.0.0 + github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.1 github.com/OpenPeeDeeP/depguard v1.1.0 github.com/alexkohler/prealloc v1.0.0 github.com/ashanbrown/forbidigo v1.3.0 diff --git a/go.sum b/go.sum index 1caf03e634db..e6c9bcc496ab 100644 --- a/go.sum +++ b/go.sum @@ -64,6 +64,8 @@ github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rW github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct v1.0.0 h1:z+MQsgpeFDwmVZqB78E1nig4TX8IAGXr/LczFNbqRPU= github.com/GaijinEntertainment/go-exhaustruct v1.0.0/go.mod h1:jXk57htv8oR5kz8IClFCxBykWOwS2VWHRuRT4V+a5Xc= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.1 h1:a3kOgrlUghvW/JYGy4t0OVe1VgebwoX0wV85PC2i+VU= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.1/go.mod h1:LGOGuvEgCfCQsy3JF2tRmpGDpzA53iZfyGEWSPwQ6/4= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= diff --git a/pkg/golinters/exhaustruct.go b/pkg/golinters/exhaustruct.go index 50c065310808..caf6ff353d46 100644 --- a/pkg/golinters/exhaustruct.go +++ b/pkg/golinters/exhaustruct.go @@ -1,9 +1,7 @@ package golinters import ( - "strings" - - "github.com/GaijinEntertainment/go-exhaustruct/pkg/analyzer" + "github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" @@ -11,22 +9,15 @@ import ( ) func NewExhaustruct(settings *config.ExhaustructSettings) *goanalysis.Linter { - a := analyzer.Analyzer + include, exclude := []string{}, []string{} - var cfg map[string]map[string]interface{} if settings != nil { - cfg = map[string]map[string]interface{}{ - a.Name: { - "include": strings.Join(settings.Include, ","), - "exclude": strings.Join(settings.Exclude, ","), - }, - } + include = settings.Include + exclude = settings.Exclude } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + a := analyzer.MustNewAnalyzer(include, exclude) + + return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/test/testdata/configs/exhaustruct.yml b/test/testdata/configs/exhaustruct.yml index 614c1347717d..a2cb20f96528 100644 --- a/test/testdata/configs/exhaustruct.yml +++ b/test/testdata/configs/exhaustruct.yml @@ -1,4 +1,6 @@ linters-settings: exhaustruct: - include: ".*\\.ExhaustructCustom$" - exclude: ".*\\.ExhaustructCustom2" + include: + - .*\.ExhaustructCustom + exclude: + - .*\.ExhaustructCustom[\d]{1,2} From 9006f56f14f00c696564b47bf02f79b982558b03 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 30 Apr 2022 11:47:07 +0200 Subject: [PATCH 5/7] review --- go.sum | 2 -- pkg/golinters/exhaustruct.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/go.sum b/go.sum index e6c9bcc496ab..6b123e1703c5 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,6 @@ github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct v1.0.0 h1:z+MQsgpeFDwmVZqB78E1nig4TX8IAGXr/LczFNbqRPU= -github.com/GaijinEntertainment/go-exhaustruct v1.0.0/go.mod h1:jXk57htv8oR5kz8IClFCxBykWOwS2VWHRuRT4V+a5Xc= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.1 h1:a3kOgrlUghvW/JYGy4t0OVe1VgebwoX0wV85PC2i+VU= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.1/go.mod h1:LGOGuvEgCfCQsy3JF2tRmpGDpzA53iZfyGEWSPwQ6/4= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= diff --git a/pkg/golinters/exhaustruct.go b/pkg/golinters/exhaustruct.go index caf6ff353d46..44d0c7201106 100644 --- a/pkg/golinters/exhaustruct.go +++ b/pkg/golinters/exhaustruct.go @@ -9,7 +9,7 @@ import ( ) func NewExhaustruct(settings *config.ExhaustructSettings) *goanalysis.Linter { - include, exclude := []string{}, []string{} + var include, exclude []string if settings != nil { include = settings.Include From d029d109102e0e1fff9dbab80b615466c186d039 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 30 Apr 2022 12:07:28 +0200 Subject: [PATCH 6/7] review: error management --- go.mod | 2 +- go.sum | 4 ++-- pkg/golinters/commons.go | 6 ++++++ pkg/golinters/exhaustruct.go | 5 ++++- 4 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 pkg/golinters/commons.go diff --git a/go.mod b/go.mod index 6b1e550f6ba3..40acf3ca663d 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Antonboom/nilnil v0.1.1 github.com/BurntSushi/toml v1.1.0 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 - github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.1 + github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.2-0.20220410203528-eb118e90b8df github.com/OpenPeeDeeP/depguard v1.1.0 github.com/alexkohler/prealloc v1.0.0 github.com/ashanbrown/forbidigo v1.3.0 diff --git a/go.sum b/go.sum index 6b123e1703c5..bc69da3eb9b8 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.1 h1:a3kOgrlUghvW/JYGy4t0OVe1VgebwoX0wV85PC2i+VU= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.1/go.mod h1:LGOGuvEgCfCQsy3JF2tRmpGDpzA53iZfyGEWSPwQ6/4= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.2-0.20220410203528-eb118e90b8df h1:Zu1ytD+7OiZT/Cs8g5OIdY1lkl1fvjjDKTNwRCJ4zaU= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.2-0.20220410203528-eb118e90b8df/go.mod h1:LGOGuvEgCfCQsy3JF2tRmpGDpzA53iZfyGEWSPwQ6/4= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= diff --git a/pkg/golinters/commons.go b/pkg/golinters/commons.go new file mode 100644 index 000000000000..a4c3913f7e25 --- /dev/null +++ b/pkg/golinters/commons.go @@ -0,0 +1,6 @@ +package golinters + +import "github.com/golangci/golangci-lint/pkg/logutils" + +// linterLogger must be use only when the context logger is not available. +var linterLogger = logutils.NewStderrLog("linter") diff --git a/pkg/golinters/exhaustruct.go b/pkg/golinters/exhaustruct.go index 44d0c7201106..8c843289dd9e 100644 --- a/pkg/golinters/exhaustruct.go +++ b/pkg/golinters/exhaustruct.go @@ -16,7 +16,10 @@ func NewExhaustruct(settings *config.ExhaustructSettings) *goanalysis.Linter { exclude = settings.Exclude } - a := analyzer.MustNewAnalyzer(include, exclude) + a, err := analyzer.NewAnalyzer(include, exclude) + if err != nil { + linterLogger.Fatalf("exhaustruct configuration: %v", err) + } return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). WithLoadMode(goanalysis.LoadModeTypesInfo) From 83571a2399f621abf129af8b2a395badfb4a68c2 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 30 Apr 2022 12:22:26 +0200 Subject: [PATCH 7/7] review: update linter --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 40acf3ca663d..c601093349ca 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Antonboom/nilnil v0.1.1 github.com/BurntSushi/toml v1.1.0 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 - github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.2-0.20220410203528-eb118e90b8df + github.com/GaijinEntertainment/go-exhaustruct/v2 v2.1.0 github.com/OpenPeeDeeP/depguard v1.1.0 github.com/alexkohler/prealloc v1.0.0 github.com/ashanbrown/forbidigo v1.3.0 diff --git a/go.sum b/go.sum index bc69da3eb9b8..0009bb7d8aae 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.2-0.20220410203528-eb118e90b8df h1:Zu1ytD+7OiZT/Cs8g5OIdY1lkl1fvjjDKTNwRCJ4zaU= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.0.2-0.20220410203528-eb118e90b8df/go.mod h1:LGOGuvEgCfCQsy3JF2tRmpGDpzA53iZfyGEWSPwQ6/4= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.1.0 h1:LAPPhJ4KR5Z8aKVZF5S48csJkxL5RMKmE/98fMs1u5M= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.1.0/go.mod h1:LGOGuvEgCfCQsy3JF2tRmpGDpzA53iZfyGEWSPwQ6/4= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=