new-linter: ireturn (checks for function return type) (#2219)
This commit is contained in:
parent
813ba7d953
commit
2ea496f22b
@ -447,6 +447,29 @@ linters-settings:
|
||||
- pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+)
|
||||
alias: $1$2
|
||||
|
||||
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.
|
||||
# keywords:
|
||||
# - `empty` for `interface{}`
|
||||
# - `error` for errors
|
||||
# - `stdlib` for standard library
|
||||
# - `anon` for anonymous interfaces
|
||||
|
||||
# By default, it allows using errors, empty interfaces, anonymous interfaces,
|
||||
# and interfaces provided by the standard library.
|
||||
allow:
|
||||
- anon
|
||||
- error
|
||||
- empty
|
||||
- stdlib
|
||||
# You can specify idiomatic endings for interface
|
||||
- (or|er)$
|
||||
|
||||
# Reject patterns
|
||||
reject:
|
||||
- github.com\/user\/package\/v4\.Type
|
||||
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
|
1
go.mod
1
go.mod
@ -13,6 +13,7 @@ require (
|
||||
github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde
|
||||
github.com/bkielbasa/cyclop v1.2.0
|
||||
github.com/bombsimon/wsl/v3 v3.3.0
|
||||
github.com/butuzov/ireturn v0.1.0
|
||||
github.com/charithe/durationcheck v0.0.8
|
||||
github.com/daixiang0/gci v0.2.9
|
||||
github.com/denis-tingajkin/go-header v0.4.2
|
||||
|
2
go.sum
generated
2
go.sum
generated
@ -95,6 +95,8 @@ github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7
|
||||
github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI=
|
||||
github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM=
|
||||
github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
|
||||
github.com/butuzov/ireturn v0.1.0 h1:fMNgwuKMwsV9qtPNFgI7/NUOF3+CfbdLPGX6ZhDaMgA=
|
||||
github.com/butuzov/ireturn v0.1.0/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
|
@ -110,6 +110,7 @@ type LintersSettings struct {
|
||||
Gosimple StaticCheckSettings
|
||||
Govet GovetSettings
|
||||
Ifshort IfshortSettings
|
||||
Ireturn IreturnSettings
|
||||
ImportAs ImportAsSettings
|
||||
Lll LllSettings
|
||||
Makezero MakezeroSettings
|
||||
@ -186,6 +187,11 @@ type ExhaustiveStructSettings struct {
|
||||
StructPatterns []string `mapstructure:"struct-patterns"`
|
||||
}
|
||||
|
||||
type IreturnSettings struct {
|
||||
Allow []string `mapstructure:"allow"`
|
||||
Reject []string `mapstructure:"reject"`
|
||||
}
|
||||
|
||||
type ForbidigoSettings struct {
|
||||
Forbid []string `mapstructure:"forbid"`
|
||||
ExcludeGodocExamples bool `mapstructure:"exclude-godoc-examples"`
|
||||
|
30
pkg/golinters/ireturn.go
Normal file
30
pkg/golinters/ireturn.go
Normal file
@ -0,0 +1,30 @@
|
||||
package golinters
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/golangci/golangci-lint/pkg/config"
|
||||
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
|
||||
|
||||
"github.com/butuzov/ireturn/analyzer"
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
func NewIreturn(settings *config.IreturnSettings) *goanalysis.Linter {
|
||||
a := analyzer.NewAnalyzer()
|
||||
|
||||
cfg := map[string]map[string]interface{}{}
|
||||
if settings != nil {
|
||||
cfg[a.Name] = map[string]interface{}{
|
||||
"allow": strings.Join(settings.Allow, ","),
|
||||
"reject": strings.Join(settings.Reject, ","),
|
||||
}
|
||||
}
|
||||
|
||||
return goanalysis.NewLinter(
|
||||
a.Name,
|
||||
a.Doc,
|
||||
[]*analysis.Analyzer{a},
|
||||
cfg,
|
||||
).WithLoadMode(goanalysis.LoadModeTypesInfo)
|
||||
}
|
@ -110,6 +110,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
||||
var reviveCfg *config.ReviveSettings
|
||||
var cyclopCfg *config.Cyclop
|
||||
var importAsCfg *config.ImportAsSettings
|
||||
var ireturnCfg *config.IreturnSettings
|
||||
var goModDirectivesCfg *config.GoModDirectivesSettings
|
||||
var tagliatelleCfg *config.TagliatelleSettings
|
||||
var gosecCfg *config.GoSecSettings
|
||||
@ -131,6 +132,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
||||
reviveCfg = &m.cfg.LintersSettings.Revive
|
||||
cyclopCfg = &m.cfg.LintersSettings.Cyclop
|
||||
importAsCfg = &m.cfg.LintersSettings.ImportAs
|
||||
ireturnCfg = &m.cfg.LintersSettings.Ireturn
|
||||
goModDirectivesCfg = &m.cfg.LintersSettings.GoModDirectives
|
||||
tagliatelleCfg = &m.cfg.LintersSettings.Tagliatelle
|
||||
gosecCfg = &m.cfg.LintersSettings.Gosec
|
||||
@ -506,6 +508,11 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
||||
WithLoadForGoAnalysis().
|
||||
WithURL("https://github.com/Antonboom/errname").
|
||||
WithSince("v1.42.0"),
|
||||
linter.NewConfig(golinters.NewIreturn(ireturnCfg)).
|
||||
WithSince("v1.43.0").
|
||||
WithPresets(linter.PresetStyle).
|
||||
WithLoadForGoAnalysis().
|
||||
WithURL("https://github.com/butuzov/ireturn"),
|
||||
|
||||
// nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives
|
||||
linter.NewConfig(golinters.NewNoLintLint()).
|
||||
|
4
test/testdata/configs/ireturn.yml
vendored
Normal file
4
test/testdata/configs/ireturn.yml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
linters-settings:
|
||||
ireturn:
|
||||
allow:
|
||||
- IreturnAllowDoer
|
4
test/testdata/configs/ireturn_stdlib_reject.yml
vendored
Normal file
4
test/testdata/configs/ireturn_stdlib_reject.yml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
linters-settings:
|
||||
ireturn:
|
||||
reject:
|
||||
- stdlib
|
13
test/testdata/ireturn_allow.go
vendored
Normal file
13
test/testdata/ireturn_allow.go
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
// args: -Eireturn
|
||||
// config_path: testdata/configs/ireturn.yml
|
||||
package testdata
|
||||
|
||||
type (
|
||||
IreturnAllowDoer interface{ Do() }
|
||||
ireturnAllowDoer struct{}
|
||||
)
|
||||
|
||||
func NewAllowDoer() IreturnAllowDoer { return new(ireturnAllowDoer) }
|
||||
func (d *ireturnAllowDoer) Do() { /*...*/ }
|
||||
|
||||
func NewerAllowDoer() *ireturnAllowDoer { return new(ireturnAllowDoer) }
|
12
test/testdata/ireturn_default.go
vendored
Normal file
12
test/testdata/ireturn_default.go
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// args: -Eireturn
|
||||
package testdata
|
||||
|
||||
type (
|
||||
IreturnDoer interface{ Do() }
|
||||
ireturnDoer struct{}
|
||||
)
|
||||
|
||||
func New() IreturnDoer { return new(ireturnDoer) } // ERROR `New returns interface \(command-line-arguments.IreturnDoer\)`
|
||||
func (d *ireturnDoer) Do() { /*...*/ }
|
||||
|
||||
func Newer() *ireturnDoer { return new(ireturnDoer) }
|
28
test/testdata/ireturn_reject_stdlib.go
vendored
Normal file
28
test/testdata/ireturn_reject_stdlib.go
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// args: -Eireturn
|
||||
// config_path: testdata/configs/ireturn_stdlib_reject.yml
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
func NewWriter() io.Writer { // ERROR `NewWriter returns interface \(io.Writer\)`
|
||||
var buf bytes.Buffer
|
||||
return &buf
|
||||
}
|
||||
|
||||
func TestError() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Foo interface {
|
||||
Foo()
|
||||
}
|
||||
type foo int
|
||||
|
||||
func (f foo) Foo() {}
|
||||
|
||||
func NewFoo() Foo {
|
||||
return foo(1)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user