diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index a384ea6b7028..827e1c3aec1a 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -516,6 +516,11 @@ linters-settings: # Default: false forbid-spec-pollution: true + gochecksumtype: + # Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed. + # Default: true + default-signifies-exhaustive: false + gocognit: # Minimal code complexity to report. # Default: 30 (but we recommend 10-20) diff --git a/go.mod b/go.mod index 3e416bfd29aa..46c33e42fe2d 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 github.com/OpenPeeDeeP/depguard/v2 v2.2.0 - github.com/alecthomas/go-check-sumtype v0.1.4 + github.com/alecthomas/go-check-sumtype v0.2.0 github.com/alexkohler/nakedret/v2 v2.0.4 github.com/alexkohler/prealloc v1.0.0 github.com/alingse/asasalint v0.0.11 diff --git a/go.sum b/go.sum index e2eec3e663e7..e817e11cef0d 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJP github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= -github.com/alecthomas/go-check-sumtype v0.1.4 h1:WCvlB3l5Vq5dZQTFmodqL2g68uHiSwwlWcT5a2FGK0c= -github.com/alecthomas/go-check-sumtype v0.1.4/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= +github.com/alecthomas/go-check-sumtype v0.2.0 h1:Bo+e4DFf3rs7ME9w/0SU/g6nmzJaphduP8Cjiz0gbwY= +github.com/alecthomas/go-check-sumtype v0.2.0/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 2ad65b0db9c0..511eadedfecd 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -1174,6 +1174,17 @@ } } }, + "gochecksumtype": { + "type": "object", + "additionalProperties": false, + "properties": { + "default-signifies-exhaustive": { + "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.", + "type": "boolean", + "default": true + } + } + }, "gocognit": { "type": "object", "additionalProperties": false, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 109de42431e1..e1a777ea8127 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -47,6 +47,9 @@ var defaultLintersSettings = LintersSettings{ Sections: []string{"standard", "default"}, SkipGenerated: true, }, + GoChecksumType: GoChecksumTypeSettings{ + DefaultSignifiesExhaustive: true, + }, Gocognit: GocognitSettings{ MinComplexity: 30, }, @@ -216,6 +219,7 @@ type LintersSettings struct { Gci GciSettings GinkgoLinter GinkgoLinterSettings Gocognit GocognitSettings + GoChecksumType GoChecksumTypeSettings Goconst GoConstSettings Gocritic GoCriticSettings Gocyclo GoCycloSettings @@ -485,6 +489,10 @@ type GinkgoLinterSettings struct { ForbidSpecPollution bool `mapstructure:"forbid-spec-pollution"` } +type GoChecksumTypeSettings struct { + DefaultSignifiesExhaustive bool `mapstructure:"default-signifies-exhaustive"` +} + type GocognitSettings struct { MinComplexity int `mapstructure:"min-complexity"` } diff --git a/pkg/golinters/exhaustruct/testdata/exhaustruct_custom.go b/pkg/golinters/exhaustruct/testdata/exhaustruct_custom.go index 6e79856a2f62..b1c46e9066e8 100644 --- a/pkg/golinters/exhaustruct/testdata/exhaustruct_custom.go +++ b/pkg/golinters/exhaustruct/testdata/exhaustruct_custom.go @@ -1,5 +1,5 @@ //golangcitest:args -Eexhaustruct -//golangcitest:config_path testdata/exhaustruct.yml +//golangcitest:config_path testdata/exhaustruct_custom.yml package testdata import "time" diff --git a/pkg/golinters/exhaustruct/testdata/exhaustruct.yml b/pkg/golinters/exhaustruct/testdata/exhaustruct_custom.yml similarity index 100% rename from pkg/golinters/exhaustruct/testdata/exhaustruct.yml rename to pkg/golinters/exhaustruct/testdata/exhaustruct_custom.yml diff --git a/pkg/golinters/gochecksumtype/gochecksumtype.go b/pkg/golinters/gochecksumtype/gochecksumtype.go index 446f0e564f07..7aab0efebbae 100644 --- a/pkg/golinters/gochecksumtype/gochecksumtype.go +++ b/pkg/golinters/gochecksumtype/gochecksumtype.go @@ -8,6 +8,7 @@ import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/packages" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" "github.com/golangci/golangci-lint/pkg/result" @@ -15,7 +16,7 @@ import ( const linterName = "gochecksumtype" -func New() *goanalysis.Linter { +func New(settings *config.GoChecksumTypeSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue @@ -23,7 +24,7 @@ func New() *goanalysis.Linter { Name: linterName, Doc: goanalysis.TheOnlyanalyzerDoc, Run: func(pass *analysis.Pass) (any, error) { - issues, err := runGoCheckSumType(pass) + issues, err := runGoCheckSumType(pass, settings) if err != nil { return nil, err } @@ -50,7 +51,7 @@ func New() *goanalysis.Linter { }).WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runGoCheckSumType(pass *analysis.Pass) ([]goanalysis.Issue, error) { +func runGoCheckSumType(pass *analysis.Pass, settings *config.GoChecksumTypeSettings) ([]goanalysis.Issue, error) { var resIssues []goanalysis.Issue pkg := &packages.Package{ @@ -61,7 +62,8 @@ func runGoCheckSumType(pass *analysis.Pass) ([]goanalysis.Issue, error) { } var unknownError error - errors := gochecksumtype.Run([]*packages.Package{pkg}) + errors := gochecksumtype.Run([]*packages.Package{pkg}, + gochecksumtype.Config{DefaultSignifiesExhaustive: settings.DefaultSignifiesExhaustive}) for _, err := range errors { err, ok := err.(gochecksumtype.Error) if !ok { diff --git a/pkg/golinters/gochecksumtype/testdata/gochecksumtype.go b/pkg/golinters/gochecksumtype/testdata/gochecksumtype.go index 47ae3b9a90d1..000f1410d6b8 100644 --- a/pkg/golinters/gochecksumtype/testdata/gochecksumtype.go +++ b/pkg/golinters/gochecksumtype/testdata/gochecksumtype.go @@ -29,6 +29,12 @@ func sumTypeTest() { panic("??") } + switch sum.(type) { + case *One: + default: + log.Println("legit catch all goes here") + } + log.Println("??") switch sum.(type) { diff --git a/pkg/golinters/gochecksumtype/testdata/gochecksumtype_custom.go b/pkg/golinters/gochecksumtype/testdata/gochecksumtype_custom.go new file mode 100644 index 000000000000..77a0696efcf8 --- /dev/null +++ b/pkg/golinters/gochecksumtype/testdata/gochecksumtype_custom.go @@ -0,0 +1,45 @@ +//golangcitest:args -Egochecksumtype +//golangcitest:config_path testdata/gochecksumtype_custom.yml +package testdata + +import ( + "log" +) + +//sumtype:decl +type SumType interface{ isSumType() } + +//sumtype:decl +type One struct{} // want "type 'One' is not an interface" + +func (One) isSumType() {} + +type Two struct{} + +func (Two) isSumType() {} + +func sumTypeTest() { + var sum SumType = One{} + switch sum.(type) { // want "exhaustiveness check failed for sum type.*SumType.*missing cases for Two" + case One: + } + + switch sum.(type) { // want "exhaustiveness check failed for sum type.*SumType.*missing cases for Two" + case One: + default: + panic("??") + } + + switch sum.(type) { // want "exhaustiveness check failed for sum type.*SumType.*missing cases for Two" + case *One: + default: + log.Println("legit catch all goes here") + } + + log.Println("??") + + switch sum.(type) { + case One: + case Two: + } +} diff --git a/pkg/golinters/gochecksumtype/testdata/gochecksumtype_custom.yml b/pkg/golinters/gochecksumtype/testdata/gochecksumtype_custom.yml new file mode 100644 index 000000000000..361ba1f94dfa --- /dev/null +++ b/pkg/golinters/gochecksumtype/testdata/gochecksumtype_custom.yml @@ -0,0 +1,3 @@ +linters-settings: + gochecksumtype: + default-signifies-exhaustive: false diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 50d9cc154461..f7c226d69212 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -335,7 +335,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithSince("v1.12.0"). WithPresets(linter.PresetStyle), - linter.NewConfig(gochecksumtype.New()). + linter.NewConfig(gochecksumtype.New(&cfg.LintersSettings.GoChecksumType)). WithSince("v1.55.0"). WithPresets(linter.PresetBugs). WithLoadForGoAnalysis().