exhaustivestruct: add missing settings (#1746)

This commit is contained in:
Ludovic Fernandez 2021-02-19 19:20:47 +01:00 committed by GitHub
parent 4b3fb4c64f
commit ea5f479087
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 171 additions and 31 deletions

View File

@ -111,6 +111,12 @@ linters-settings:
# 'default' case is present, even if all enum members aren't listed in the # 'default' case is present, even if all enum members aren't listed in the
# switch # switch
default-signifies-exhaustive: false default-signifies-exhaustive: false
exhaustivestruct:
struct-patterns:
- '*.Test'
- '*.Test2'
- '*.Embedded'
- '*.External'
funlen: funlen:
lines: 60 lines: 60
statements: 40 statements: 40

View File

@ -249,31 +249,32 @@ type LintersSettings struct {
} `mapstructure:"blocked"` } `mapstructure:"blocked"`
} }
WSL WSLSettings WSL WSLSettings
Lll LllSettings Lll LllSettings
Unparam UnparamSettings Unparam UnparamSettings
Nakedret NakedretSettings Nakedret NakedretSettings
Prealloc PreallocSettings Prealloc PreallocSettings
Errcheck ErrcheckSettings Errcheck ErrcheckSettings
Gocritic GocriticSettings Gocritic GocriticSettings
Godox GodoxSettings Godox GodoxSettings
Dogsled DogsledSettings Dogsled DogsledSettings
Gocognit GocognitSettings Gocognit GocognitSettings
Godot GodotSettings Godot GodotSettings
Goheader GoHeaderSettings Goheader GoHeaderSettings
Testpackage TestpackageSettings Testpackage TestpackageSettings
Nestif NestifSettings Nestif NestifSettings
NoLintLint NoLintLintSettings NoLintLint NoLintLintSettings
Exhaustive ExhaustiveSettings Exhaustive ExhaustiveSettings
Gofumpt GofumptSettings ExhaustiveStruct ExhaustiveStructSettings
ErrorLint ErrorLintSettings Gofumpt GofumptSettings
Makezero MakezeroSettings ErrorLint ErrorLintSettings
Revive ReviveSettings Makezero MakezeroSettings
Thelper ThelperSettings Revive ReviveSettings
Forbidigo ForbidigoSettings Thelper ThelperSettings
Ifshort IfshortSettings Forbidigo ForbidigoSettings
Predeclared PredeclaredSettings Ifshort IfshortSettings
Cyclop Cyclop Predeclared PredeclaredSettings
Cyclop Cyclop
Custom map[string]CustomLinterSettings Custom map[string]CustomLinterSettings
} }
@ -387,6 +388,10 @@ type ExhaustiveSettings struct {
DefaultSignifiesExhaustive bool `mapstructure:"default-signifies-exhaustive"` DefaultSignifiesExhaustive bool `mapstructure:"default-signifies-exhaustive"`
} }
type ExhaustiveStructSettings struct {
StructPatterns []string `mapstructure:"struct-patterns"`
}
type GofumptSettings struct { type GofumptSettings struct {
ExtraRules bool `mapstructure:"extra-rules"` ExtraRules bool `mapstructure:"extra-rules"`
} }

View File

@ -1,17 +1,31 @@
package golinters package golinters
import ( import (
"strings"
"github.com/mbilski/exhaustivestruct/pkg/analyzer" "github.com/mbilski/exhaustivestruct/pkg/analyzer"
"golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis"
"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
) )
func NewExhaustiveStruct() *goanalysis.Linter { func NewExhaustiveStruct(settings *config.ExhaustiveStructSettings) *goanalysis.Linter {
a := analyzer.Analyzer
var cfg map[string]map[string]interface{}
if settings != nil {
cfg = map[string]map[string]interface{}{
a.Name: {
"struct_patterns": strings.Join(settings.StructPatterns, ","),
},
}
}
return goanalysis.NewLinter( return goanalysis.NewLinter(
"exhaustivestruct", a.Name,
"Checks if all struct's fields are initialized", a.Doc,
[]*analysis.Analyzer{analyzer.Analyzer}, []*analysis.Analyzer{a},
nil, cfg,
).WithLoadMode(goanalysis.LoadModeTypesInfo) ).WithLoadMode(goanalysis.LoadModeTypesInfo)
} }

View File

@ -92,6 +92,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
var govetCfg *config.GovetSettings var govetCfg *config.GovetSettings
var testpackageCfg *config.TestpackageSettings var testpackageCfg *config.TestpackageSettings
var exhaustiveCfg *config.ExhaustiveSettings var exhaustiveCfg *config.ExhaustiveSettings
var exhaustiveStructCfg *config.ExhaustiveStructSettings
var errorlintCfg *config.ErrorLintSettings var errorlintCfg *config.ErrorLintSettings
var thelperCfg *config.ThelperSettings var thelperCfg *config.ThelperSettings
var predeclaredCfg *config.PredeclaredSettings var predeclaredCfg *config.PredeclaredSettings
@ -102,6 +103,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
govetCfg = &m.cfg.LintersSettings.Govet govetCfg = &m.cfg.LintersSettings.Govet
testpackageCfg = &m.cfg.LintersSettings.Testpackage testpackageCfg = &m.cfg.LintersSettings.Testpackage
exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive
exhaustiveStructCfg = &m.cfg.LintersSettings.ExhaustiveStruct
errorlintCfg = &m.cfg.LintersSettings.ErrorLint errorlintCfg = &m.cfg.LintersSettings.ErrorLint
thelperCfg = &m.cfg.LintersSettings.Thelper thelperCfg = &m.cfg.LintersSettings.Thelper
predeclaredCfg = &m.cfg.LintersSettings.Predeclared predeclaredCfg = &m.cfg.LintersSettings.Predeclared
@ -339,7 +341,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetStyle). WithPresets(linter.PresetStyle).
WithLoadForGoAnalysis(). WithLoadForGoAnalysis().
WithURL("https://github.com/moricho/tparallel"), WithURL("https://github.com/moricho/tparallel"),
linter.NewConfig(golinters.NewExhaustiveStruct()). linter.NewConfig(golinters.NewExhaustiveStruct(exhaustiveStructCfg)).
WithPresets(linter.PresetStyle). WithPresets(linter.PresetStyle).
WithLoadForGoAnalysis(). WithLoadForGoAnalysis().
WithURL("https://github.com/mbilski/exhaustivestruct"), WithURL("https://github.com/mbilski/exhaustivestruct"),

113
test/testdata/exhaustivestruct_custom.go vendored Normal file
View File

@ -0,0 +1,113 @@
//args: -Eexhaustivestruct
//config: linters-settings.exhaustivestruct.struct-patterns=*.Test1,*.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{ // 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(),
}
var failPrivateTest3 = Test3{ // ERROR "c is missing in Test"
A: "a",
B: 0,
D: 1.0,
E: time.Now(),
}