From 0573045d91db08a4f0affab7a465cd1006a75051 Mon Sep 17 00:00:00 2001 From: Sasha Melentyev Date: Sat, 30 Jul 2022 14:31:31 +0300 Subject: [PATCH 1/4] feat: add interfacebloat --- .golangci.reference.yml | 5 ++++ go.mod | 1 + go.sum | 2 ++ pkg/golinters/interfacebloat.go | 19 +++++++++++++ pkg/lint/lintersdb/manager.go | 6 +++++ test/testdata/interfacebloat.go | 48 +++++++++++++++++++++++++++++++++ 6 files changed, 81 insertions(+) create mode 100644 pkg/golinters/interfacebloat.go create mode 100644 test/testdata/interfacebloat.go diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 408a3bad2a36..7aa1d8dd089f 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -1074,6 +1074,9 @@ linters-settings: - pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+) alias: $1$2 + interfacebloat: + interface-len: 10 + ireturn: # ireturn allows using `allow` and `reject` settings at the same time. # Both settings are lists of the keywords and regular expressions matched to interface or package names. @@ -1923,6 +1926,7 @@ linters: - ifshort - importas - ineffassign + - interfacebloat - interfacer - ireturn - lll @@ -2025,6 +2029,7 @@ linters: - ifshort - importas - ineffassign + - interfacebloat - interfacer - ireturn - lll diff --git a/go.mod b/go.mod index d94dfebbd95f..d83077dfe348 100644 --- a/go.mod +++ b/go.mod @@ -74,6 +74,7 @@ require ( github.com/ryancurrah/gomodguard v1.2.4 github.com/ryanrolds/sqlclosecheck v0.3.0 github.com/sanposhiho/wastedassign/v2 v2.0.6 + github.com/sashamelentyev/interfacebloat v1.0.0 github.com/sashamelentyev/usestdlibvars v1.13.0 github.com/securego/gosec/v2 v2.13.1 github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c diff --git a/go.sum b/go.sum index 12699238c722..24f5008a4658 100644 --- a/go.sum +++ b/go.sum @@ -459,6 +459,8 @@ github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8 github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/sashamelentyev/interfacebloat v1.0.0 h1:p2qI+0Oj5KbLqpukhkJGP24GSyWPLWd3CgT74F7Tzg4= +github.com/sashamelentyev/interfacebloat v1.0.0/go.mod h1:v46OiPGzx/3fDMyC4gq2h6ecsJBAVdbMMQ854YCl574= github.com/sashamelentyev/usestdlibvars v1.13.0 h1:uObNudVEEHf6JbOJy5bgKJloA1bWjxR9fwgNFpPzKnI= github.com/sashamelentyev/usestdlibvars v1.13.0/go.mod h1:D2Wb7niIYmTB+gB8z7kh8tyP5ccof1dQ+SFk+WW5NtY= github.com/securego/gosec/v2 v2.13.1 h1:7mU32qn2dyC81MH9L2kefnQyRMUarfDER3iQyMHcjYM= diff --git a/pkg/golinters/interfacebloat.go b/pkg/golinters/interfacebloat.go new file mode 100644 index 000000000000..c04eee7091ff --- /dev/null +++ b/pkg/golinters/interfacebloat.go @@ -0,0 +1,19 @@ +package golinters + +import ( + "github.com/sashamelentyev/interfacebloat/pkg/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewInterfaceBloat() *goanalysis.Linter { + a := analyzer.New() + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + nil, + ) +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 4552153c69bd..507eedbc4e2e 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -557,6 +557,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetUnused). WithURL("https://github.com/gordonklaus/ineffassign"), + linter.NewConfig(golinters.NewInterfaceBloat()). + WithSince("v1.48.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/sashamelentyev/interfacebloat"), + linter.NewConfig(golinters.NewInterfacer()). WithSince("v1.0.0"). WithLoadForGoAnalysis(). diff --git a/test/testdata/interfacebloat.go b/test/testdata/interfacebloat.go new file mode 100644 index 000000000000..d562e20ccc19 --- /dev/null +++ b/test/testdata/interfacebloat.go @@ -0,0 +1,48 @@ +//golangcitest:args -Einterfacebloat +package testdata + +type _ interface { // want "length of interface greater than 10" + a() + b() + c() + d() + f() + g() + h() + i() + j() + k() + l() +} + +func _() { + var _ interface { // want "length of interface greater than 10" + a() + b() + c() + d() + f() + g() + h() + i() + j() + k() + l() + } +} + +func __() interface { // want "length of interface greater than 10" + a() + b() + c() + d() + f() + g() + h() + i() + j() + k() + l() +} { + return nil +} From a69f61adfc50ac9d2f17d3d994bc75f7298151bb Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 20 Aug 2022 00:26:49 +0200 Subject: [PATCH 2/4] review --- .golangci.reference.yml | 4 +++- pkg/config/linters_settings.go | 5 +++++ pkg/golinters/interfacebloat.go | 12 ++++++++++-- pkg/lint/lintersdb/manager.go | 7 ++++--- test/testdata/interfacebloat.go | 14 ++++++++------ 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 7aa1d8dd089f..78101994bcd1 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -1075,7 +1075,9 @@ linters-settings: alias: $1$2 interfacebloat: - interface-len: 10 + # The number of allowed methods for an interface. + # Default: 10 + len: 5 ireturn: # ireturn allows using `allow` and `reject` settings at the same time. diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 1e923409a05d..2e5cef9707d2 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -151,6 +151,7 @@ type LintersSettings struct { Grouper GrouperSettings Ifshort IfshortSettings ImportAs ImportAsSettings + InterfaceBloat InterfaceBloatSettings Ireturn IreturnSettings Lll LllSettings MaintIdx MaintIdxSettings @@ -454,6 +455,10 @@ type ImportAsAlias struct { Alias string } +type InterfaceBloatSettings struct { + Len int `mapstructure:"len"` +} + type IreturnSettings struct { Allow []string `mapstructure:"allow"` Reject []string `mapstructure:"reject"` diff --git a/pkg/golinters/interfacebloat.go b/pkg/golinters/interfacebloat.go index c04eee7091ff..709436c7e74a 100644 --- a/pkg/golinters/interfacebloat.go +++ b/pkg/golinters/interfacebloat.go @@ -4,16 +4,24 @@ import ( "github.com/sashamelentyev/interfacebloat/pkg/analyzer" "golang.org/x/tools/go/analysis" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" ) -func NewInterfaceBloat() *goanalysis.Linter { +func NewInterfaceBloat(settings *config.InterfaceBloatSettings) *goanalysis.Linter { a := analyzer.New() + cfgMap := make(map[string]map[string]interface{}) + if settings != nil { + cfgMap[a.Name] = map[string]interface{}{ + analyzer.InterfaceLenFlag: settings.Len, + } + } + return goanalysis.NewLinter( a.Name, a.Doc, []*analysis.Analyzer{a}, nil, - ) + ).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 507eedbc4e2e..4d69aac6f6d2 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -137,6 +137,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { grouperCfg *config.GrouperSettings ifshortCfg *config.IfshortSettings importAsCfg *config.ImportAsSettings + interfaceBloatCfg *config.InterfaceBloatSettings ireturnCfg *config.IreturnSettings lllCfg *config.LllSettings maintIdxCfg *config.MaintIdxSettings @@ -209,6 +210,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { grouperCfg = &m.cfg.LintersSettings.Grouper ifshortCfg = &m.cfg.LintersSettings.Ifshort importAsCfg = &m.cfg.LintersSettings.ImportAs + interfaceBloatCfg = &m.cfg.LintersSettings.InterfaceBloat ireturnCfg = &m.cfg.LintersSettings.Ireturn lllCfg = &m.cfg.LintersSettings.Lll maintIdxCfg = &m.cfg.LintersSettings.MaintIdx @@ -557,9 +559,8 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetUnused). WithURL("https://github.com/gordonklaus/ineffassign"), - linter.NewConfig(golinters.NewInterfaceBloat()). - WithSince("v1.48.0"). - WithLoadForGoAnalysis(). + linter.NewConfig(golinters.NewInterfaceBloat(interfaceBloatCfg)). + WithSince("v1.49.0"). WithPresets(linter.PresetStyle). WithURL("https://github.com/sashamelentyev/interfacebloat"), diff --git a/test/testdata/interfacebloat.go b/test/testdata/interfacebloat.go index d562e20ccc19..696e220b79fd 100644 --- a/test/testdata/interfacebloat.go +++ b/test/testdata/interfacebloat.go @@ -1,8 +1,10 @@ //golangcitest:args -Einterfacebloat package testdata -type _ interface { // want "length of interface greater than 10" - a() +import "time" + +type _ interface { // ERROR "length of interface greater than 10" + a() time.Duration b() c() d() @@ -16,8 +18,8 @@ type _ interface { // want "length of interface greater than 10" } func _() { - var _ interface { // want "length of interface greater than 10" - a() + var _ interface { // ERROR "length of interface greater than 10" + a() time.Duration b() c() d() @@ -31,8 +33,8 @@ func _() { } } -func __() interface { // want "length of interface greater than 10" - a() +func __() interface { // ERROR "length of interface greater than 10" + a() time.Duration b() c() d() From 42c5b545611e9a516e07f88a632c65f8ea364227 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 20 Aug 2022 14:31:30 +0200 Subject: [PATCH 3/4] review --- .golangci.reference.yml | 4 +- go.mod | 2 +- go.sum | 4 +- pkg/config/linters_settings.go | 2 +- pkg/golinters/interfacebloat.go | 2 +- test/testdata/interfacebloat.go | 154 ++++++++++++++++++++++++-------- 6 files changed, 122 insertions(+), 46 deletions(-) diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 78101994bcd1..ac5dedea8183 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -1075,9 +1075,9 @@ linters-settings: alias: $1$2 interfacebloat: - # The number of allowed methods for an interface. + # The maximum number of methods allowed for an interface. # Default: 10 - len: 5 + max: 5 ireturn: # ireturn allows using `allow` and `reject` settings at the same time. diff --git a/go.mod b/go.mod index d83077dfe348..dc598b75d309 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/ryancurrah/gomodguard v1.2.4 github.com/ryanrolds/sqlclosecheck v0.3.0 github.com/sanposhiho/wastedassign/v2 v2.0.6 - github.com/sashamelentyev/interfacebloat v1.0.0 + github.com/sashamelentyev/interfacebloat v1.1.0 github.com/sashamelentyev/usestdlibvars v1.13.0 github.com/securego/gosec/v2 v2.13.1 github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c diff --git a/go.sum b/go.sum index 24f5008a4658..c348e99fe7fc 100644 --- a/go.sum +++ b/go.sum @@ -459,8 +459,8 @@ github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8 github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= -github.com/sashamelentyev/interfacebloat v1.0.0 h1:p2qI+0Oj5KbLqpukhkJGP24GSyWPLWd3CgT74F7Tzg4= -github.com/sashamelentyev/interfacebloat v1.0.0/go.mod h1:v46OiPGzx/3fDMyC4gq2h6ecsJBAVdbMMQ854YCl574= +github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= +github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.13.0 h1:uObNudVEEHf6JbOJy5bgKJloA1bWjxR9fwgNFpPzKnI= github.com/sashamelentyev/usestdlibvars v1.13.0/go.mod h1:D2Wb7niIYmTB+gB8z7kh8tyP5ccof1dQ+SFk+WW5NtY= github.com/securego/gosec/v2 v2.13.1 h1:7mU32qn2dyC81MH9L2kefnQyRMUarfDER3iQyMHcjYM= diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 2e5cef9707d2..242a1de1f3d8 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -456,7 +456,7 @@ type ImportAsAlias struct { } type InterfaceBloatSettings struct { - Len int `mapstructure:"len"` + Max int `mapstructure:"max"` } type IreturnSettings struct { diff --git a/pkg/golinters/interfacebloat.go b/pkg/golinters/interfacebloat.go index 709436c7e74a..f9cf81c8130c 100644 --- a/pkg/golinters/interfacebloat.go +++ b/pkg/golinters/interfacebloat.go @@ -14,7 +14,7 @@ func NewInterfaceBloat(settings *config.InterfaceBloatSettings) *goanalysis.Lint cfgMap := make(map[string]map[string]interface{}) if settings != nil { cfgMap[a.Name] = map[string]interface{}{ - analyzer.InterfaceLenFlag: settings.Len, + analyzer.InterfaceMaxMethodsFlag: settings.Max, } } diff --git a/test/testdata/interfacebloat.go b/test/testdata/interfacebloat.go index 696e220b79fd..bee050ff7458 100644 --- a/test/testdata/interfacebloat.go +++ b/test/testdata/interfacebloat.go @@ -3,48 +3,124 @@ package testdata import "time" -type _ interface { // ERROR "length of interface greater than 10" - a() time.Duration - b() - c() - d() - f() - g() - h() - i() - j() - k() - l() -} - -func _() { - var _ interface { // ERROR "length of interface greater than 10" - a() time.Duration - b() - c() - d() - f() - g() - h() - i() - j() - k() - l() +type InterfaceBloatExample01 interface { // ERROR "the interface has more than 10 methods: 11" + a01() time.Duration + a02() + a03() + a04() + a05() + a06() + a07() + a08() + a09() + a10() + a11() +} + +func InterfaceBloatExample02() { + var _ interface { // ERROR "the interface has more than 10 methods: 11" + a01() time.Duration + a02() + a03() + a04() + a05() + a06() + a07() + a08() + a09() + a10() + a11() + } +} + +func InterfaceBloatExample03() interface { // ERROR "the interface has more than 10 methods: 11" + a01() time.Duration + a02() + a03() + a04() + a05() + a06() + a07() + a08() + a09() + a10() + a11() +} { + return nil +} + +type InterfaceBloatExample04 struct { + Foo interface { // ERROR "the interface has more than 10 methods: 11" + a01() time.Duration + a02() + a03() + a04() + a05() + a06() + a07() + a08() + a09() + a10() + a11() + } +} + +type InterfaceBloatSmall01 interface { + a01() time.Duration + a02() + a03() + a04() + a05() +} + +type InterfaceBloatSmall02 interface { + a06() + a07() + a08() + a09() + a10() + a11() +} + +type InterfaceBloatExample05 interface { + InterfaceBloatSmall01 + InterfaceBloatSmall02 +} + +type InterfaceBloatExample06 interface { + interface { // ERROR "the interface has more than 10 methods: 11" + a01() time.Duration + a02() + a03() + a04() + a05() + a06() + a07() + a08() + a09() + a10() + a11() } } -func __() interface { // ERROR "length of interface greater than 10" - a() time.Duration - b() - c() - d() - f() - g() - h() - i() - j() - k() - l() +type InterfaceBloatTypeGeneric interface { + ~uint8 | ~uint16 | ~uint32 | ~uint64 | uint | + ~int8 | ~int16 | ~int32 | ~int64 | int | + ~float32 | ~float64 | + ~string +} + +func InterfaceBloatExampleNoProblem() interface { + a01() time.Duration + a02() + a03() + a04() + a05() + a06() + a07() + a08() + a09() + a10() } { return nil } From fa3ad6b62f76a0299341fcc99b18104a48e3e28b Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 20 Aug 2022 20:08:18 +0200 Subject: [PATCH 4/4] use new framework --- test/testdata/interfacebloat.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/testdata/interfacebloat.go b/test/testdata/interfacebloat.go index bee050ff7458..e85ebd4a94b8 100644 --- a/test/testdata/interfacebloat.go +++ b/test/testdata/interfacebloat.go @@ -3,7 +3,7 @@ package testdata import "time" -type InterfaceBloatExample01 interface { // ERROR "the interface has more than 10 methods: 11" +type InterfaceBloatExample01 interface { // want "the interface has more than 10 methods: 11" a01() time.Duration a02() a03() @@ -18,7 +18,7 @@ type InterfaceBloatExample01 interface { // ERROR "the interface has more than 1 } func InterfaceBloatExample02() { - var _ interface { // ERROR "the interface has more than 10 methods: 11" + var _ interface { // want "the interface has more than 10 methods: 11" a01() time.Duration a02() a03() @@ -33,7 +33,7 @@ func InterfaceBloatExample02() { } } -func InterfaceBloatExample03() interface { // ERROR "the interface has more than 10 methods: 11" +func InterfaceBloatExample03() interface { // want "the interface has more than 10 methods: 11" a01() time.Duration a02() a03() @@ -50,7 +50,7 @@ func InterfaceBloatExample03() interface { // ERROR "the interface has more than } type InterfaceBloatExample04 struct { - Foo interface { // ERROR "the interface has more than 10 methods: 11" + Foo interface { // want "the interface has more than 10 methods: 11" a01() time.Duration a02() a03() @@ -88,7 +88,7 @@ type InterfaceBloatExample05 interface { } type InterfaceBloatExample06 interface { - interface { // ERROR "the interface has more than 10 methods: 11" + interface { // want "the interface has more than 10 methods: 11" a01() time.Duration a02() a03()