Skip to content

new-linter: ireturn (checks for function return type) #2219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 16, 2021
21 changes: 21 additions & 0 deletions .golangci.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,27 @@ linters-settings:
- pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+)
alias: $1$2

ireturn:
# ireturn allows to use either `allow` or `reject` settings at the same time.
# both settings are a lists of the keywords (`empty` for interface{}`,
# `error` for errors, `stdlib` for standard library, `anon` for anonymouse
# interfaces ) and reglar expresssions matched to interfaces or packages.

allow:
# default settings are allow to use errors, empty interfaces, anonymouse
# interfaces, and interfaces provided by standard library.
- anon
- error
- empty
- stdlib
# You can specify idiomatic endings for interface
- (or|er)$


# or you can specify 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
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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.0.0-20210903145654-645c1cbdbffd
github.com/charithe/durationcheck v0.0.8
github.com/daixiang0/gci v0.2.9
github.com/denis-tingajkin/go-header v0.4.2
Expand Down
5 changes: 4 additions & 1 deletion go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ type LintersSettings struct {
Gosimple StaticCheckSettings
Govet GovetSettings
Ifshort IfshortSettings
Ireturn IreturnSettings
ImportAs ImportAsSettings
Lll LllSettings
Makezero MakezeroSettings
Expand Down Expand Up @@ -186,6 +187,11 @@ type ExhaustiveStructSettings struct {
StructPatterns []string `mapstructure:"struct-patterns"`
}

type IreturnSettings struct {
Allow []string `mapstructure:"allow"`
Reject []string `mapstructure:"return"`
}

type ForbidigoSettings struct {
Forbid []string `mapstructure:"forbid"`
ExcludeGodocExamples bool `mapstructure:"exclude-godoc-examples"`
Expand Down
35 changes: 35 additions & 0 deletions pkg/golinters/ireturn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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()

return goanalysis.NewLinter(
a.Name,
a.Doc,
[]*analysis.Analyzer{a},
ireturnSettings(a.Name, settings),
).WithLoadMode(goanalysis.LoadModeTypesInfo)
}

func ireturnSettings(name string, s *config.IreturnSettings) map[string]map[string]interface{} {
if s == nil {
return nil
}

return map[string]map[string]interface{}{
name: {
"allow": strings.Join(s.Allow, ","),
"reject": strings.Join(s.Reject, ","),
},
}
}
8 changes: 8 additions & 0 deletions pkg/lint/lintersdb/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -456,6 +458,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithSince("v1.36.0").
WithPresets(linter.PresetStyle).
WithURL("https://github.com/esimonov/ifshort"),

linter.NewConfig(golinters.NewIreturn(ireturnCfg)).
WithSince("v1.43.0").
WithPresets(linter.PresetStyle).
WithURL("https://github.com/butuzov/ireturn"),

linter.NewConfig(golinters.NewPredeclared(predeclaredCfg)).
WithSince("v1.35.0").
WithPresets(linter.PresetStyle).
Expand Down
13 changes: 13 additions & 0 deletions test/testdata/ireturn_allow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// args: -Eireturn
// config: linters-settings.ireturn.allow=["IreturnAllowDoer"]
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 changes: 12 additions & 0 deletions test/testdata/ireturn_default.go
Original file line number Diff line number Diff line change
@@ -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) }