From a35a96f05d7cc183cd7d6520f26e05175cc0acc6 Mon Sep 17 00:00:00 2001 From: Sebastian Spaink Date: Wed, 10 Feb 2021 14:43:56 -0600 Subject: [PATCH 1/5] Add revive as plugin --- .golangci.example.yml | 6 + go.mod | 5 +- go.sum | 18 ++- pkg/config/config.go | 18 +++ pkg/golinters/revive.go | 183 +++++++++++++++++++++++++++++++ pkg/lint/lintersdb/manager.go | 4 + test/testdata/configs/revive.yml | 7 ++ test/testdata/revive.go | 11 ++ 8 files changed, 246 insertions(+), 6 deletions(-) create mode 100644 pkg/golinters/revive.go create mode 100644 test/testdata/configs/revive.yml create mode 100644 test/testdata/revive.go diff --git a/.golangci.example.yml b/.golangci.example.yml index 752ad4b4274e..96a9928ca6ff 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -350,6 +350,12 @@ linters-settings: rowserrcheck: packages: - github.com/jmoiron/sqlx + revive: + ignore-generated-header: true + severity: warning + rules: + - name: indent-error-flow + severity: warning testpackage: # regexp pattern to skip files skip-regexp: (export|internal)_test\.go diff --git a/go.mod b/go.mod index db1ed3326b34..99cd1c20a75d 100644 --- a/go.mod +++ b/go.mod @@ -39,6 +39,8 @@ require ( github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb // v1.0 github.com/mattn/go-colorable v0.1.8 github.com/mbilski/exhaustivestruct v1.2.0 + github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 + github.com/mgechev/revive v1.0.3 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-ps v1.0.0 github.com/moricho/tparallel v0.2.1 @@ -69,9 +71,8 @@ require ( github.com/ultraware/whitespace v0.0.4 github.com/uudashr/gocognit v1.0.1 github.com/valyala/quicktemplate v1.6.3 - golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 // indirect golang.org/x/text v0.3.4 // indirect - golang.org/x/tools v0.0.0-20210105210202-9ed45478a130 + golang.org/x/tools v0.1.0 gopkg.in/yaml.v2 v2.4.0 honnef.co/go/tools v0.0.1-2020.1.6 mvdan.cc/gofumpt v0.1.0 diff --git a/go.sum b/go.sum index 25a3338cbf96..a29345cd893a 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -255,12 +257,18 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= +github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 h1:QASJXOGm2RZ5Ardbc86qNFvby9AqkLDibfChMtAg5QM= +github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/revive v1.0.3 h1:z3FL6IFFN3JKzHYHD8O1ExH9g/4lAGJ5x1+9rPZgsFg= +github.com/mgechev/revive v1.0.3/go.mod h1:POGGZagSo/0frdr7VeAifzS5Uka0d0GPiM35MsTO8nE= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -293,6 +301,8 @@ github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= +github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M= @@ -522,8 +532,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM= -golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -582,8 +592,8 @@ golang.org/x/tools v0.0.0-20201118003311-bd56c0adb394/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210102185154-773b96fafca2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105210202-9ed45478a130 h1:8qSBr5nyKsEgkP918Pu5FFDZpTtLIjXSo6mrtdVOFfk= -golang.org/x/tools v0.0.0-20210105210202-9ed45478a130/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/config/config.go b/pkg/config/config.go index 4fcf427300fc..2a0050a2e6d1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -268,6 +268,7 @@ type LintersSettings struct { Gofumpt GofumptSettings ErrorLint ErrorLintSettings Makezero MakezeroSettings + Revive ReviveSettings Thelper ThelperSettings Forbidigo ForbidigoSettings Ifshort IfshortSettings @@ -397,6 +398,23 @@ type MakezeroSettings struct { Always bool } +type ReviveSettings struct { + IgnoreGeneratedHeader bool `mapstructure:"ignore-generated-header"` + Confidence float64 + Severity string + Rules []struct { + Name string + Arguments []interface{} + Severity string + } + ErrorCode int `mapstructure:"error-code"` + WarningCode int `mapstructure:"warning-code"` + Directives []struct { + Name string + Severity string + } +} + type ThelperSettings struct { Test struct { First bool `mapstructure:"first"` diff --git a/pkg/golinters/revive.go b/pkg/golinters/revive.go new file mode 100644 index 000000000000..7b588c457051 --- /dev/null +++ b/pkg/golinters/revive.go @@ -0,0 +1,183 @@ +package golinters + +import ( + "encoding/json" + "fmt" + "go/token" + "io/ioutil" + "strings" + + "github.com/mgechev/dots" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" + + reviveConfig "github.com/mgechev/revive/config" + "github.com/mgechev/revive/lint" + "golang.org/x/tools/go/analysis" +) + +const ( + reviveName = "revive" +) + +// jsonObject defines a JSON object of an failure +type jsonObject struct { + Severity lint.Severity + lint.Failure `json:",inline"` +} + +// NewNewRevive returns a new Revive linter. +func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter { + var ( + issues []goanalysis.Issue + analyzer = &analysis.Analyzer{ + Name: goanalysis.TheOnlyAnalyzerName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + ) + + return goanalysis.NewLinter( + reviveName, + "Fast, configurable, extensible, flexible, and beautiful linter for Go", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var ( + files = []string{} + ) + + for _, file := range pass.Files { + files = append(files, pass.Fset.PositionFor(file.Pos(), false).Filename) + } + + conf, err := SetReviveConfig(cfg) + if err != nil { + return nil, err + } + + formatter, err := reviveConfig.GetFormatter("json") + if err != nil { + return nil, err + } + + revive := lint.New(ioutil.ReadFile) + + lintingRules, err := reviveConfig.GetLintingRules(conf) + if err != nil { + return nil, err + } + + packages, err := dots.ResolvePackages(files, normalizeSplit([]string{})) + if err != nil { + return nil, err + } + + failures, err := revive.Lint(packages, lintingRules, *conf) + if err != nil { + return nil, err + } + + formatChan := make(chan lint.Failure) + exitChan := make(chan bool) + + var output string + go (func() { + output, _ = formatter.Format(formatChan, *conf) + exitChan <- true + })() + + for f := range failures { + if f.Confidence < conf.Confidence { + continue + } + + formatChan <- f + } + + close(formatChan) + <-exitChan + + var results []jsonObject + err = json.Unmarshal([]byte(output), &results) + if err != nil { + return nil, err + } + + for i := range results { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + Severity: string(results[i].Severity), + Text: fmt.Sprintf("%q", results[i].Failure.Failure), + Pos: token.Position{ + Filename: results[i].Position.Start.Filename, + Line: results[i].Position.Start.Line, + Offset: results[i].Position.Start.Offset, + Column: results[i].Position.Start.Column, + }, + LineRange: &result.Range{ + From: results[i].Position.Start.Line, + To: results[i].Position.End.Line, + }, + FromLinter: reviveName, + }, pass)) + } + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return issues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} + +func normalizeSplit(strs []string) []string { + res := []string{} + for _, s := range strs { + t := strings.Trim(s, " \t") + if len(t) > 0 { + res = append(res, t) + } + } + return res +} + +func SetReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) { + // Get revive default configuration + conf, err := reviveConfig.GetConfig("") + if err != nil { + return nil, err + } + + // Default is false + conf.IgnoreGeneratedHeader = cfg.IgnoreGeneratedHeader + + if cfg.Severity != "" { + conf.Severity = lint.Severity(cfg.Severity) + } + + if cfg.Confidence != 0 { + conf.Confidence = cfg.Confidence + } + + if len(cfg.Rules) != 0 { + // Clear default rules, only use rules defined in config + conf.Rules = map[string]lint.RuleConfig{} + } + for _, r := range cfg.Rules { + conf.Rules[r.Name] = lint.RuleConfig{Arguments: r.Arguments, Severity: lint.Severity(r.Severity)} + } + + conf.ErrorCode = cfg.ErrorCode + conf.WarningCode = cfg.WarningCode + + if len(cfg.Directives) != 0 { + // Clear default Directives, only use Directives defined in config + conf.Directives = map[string]lint.DirectiveConfig{} + } + for _, d := range cfg.Directives { + conf.Directives[d.Name] = lint.DirectiveConfig{Severity: lint.Severity(d.Severity)} + } + + return conf, nil +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index b8f4ed880df7..e8598702ea52 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -96,6 +96,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { var thelperCfg *config.ThelperSettings var predeclaredCfg *config.PredeclaredSettings var ifshortCfg *config.IfshortSettings + var reviveCfg *config.ReviveSettings if m.cfg != nil { govetCfg = &m.cfg.LintersSettings.Govet testpackageCfg = &m.cfg.LintersSettings.Testpackage @@ -104,6 +105,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { thelperCfg = &m.cfg.LintersSettings.Thelper predeclaredCfg = &m.cfg.LintersSettings.Predeclared ifshortCfg = &m.cfg.LintersSettings.Ifshort + reviveCfg = &m.cfg.LintersSettings.Revive } const megacheckName = "megacheck" lcs := []*linter.Config{ @@ -352,6 +354,8 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { linter.NewConfig(golinters.NewPredeclared(predeclaredCfg)). WithPresets(linter.PresetStyle). WithURL("https://github.com/nishanths/predeclared"), + linter.NewConfig(golinters.NewRevive(reviveCfg)). + WithURL("https://github.com/mgechev/revive"), // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives linter.NewConfig(golinters.NewNoLintLint()). diff --git a/test/testdata/configs/revive.yml b/test/testdata/configs/revive.yml new file mode 100644 index 000000000000..0752b75baf57 --- /dev/null +++ b/test/testdata/configs/revive.yml @@ -0,0 +1,7 @@ +linters-settings: + revive: + ignore-generated-header: true + severity: warning + rules: + - name: indent-error-flow + severity: warning \ No newline at end of file diff --git a/test/testdata/revive.go b/test/testdata/revive.go new file mode 100644 index 000000000000..79e33c4d8a7a --- /dev/null +++ b/test/testdata/revive.go @@ -0,0 +1,11 @@ +//args: -Erevive +//config_path: testdata/configs/revive.yml +package testdata + +func testRevive(t string) error { + if t == "" { + return nil + } else { // ERROR "if block ends with a return statement, so drop this else and outdent its block" + return nil + } +} From f0dd9bc13e73d6833b2d3c78ce1ac62914a7694a Mon Sep 17 00:00:00 2001 From: Sebastian Spaink Date: Wed, 10 Feb 2021 15:47:56 -0600 Subject: [PATCH 2/5] Ignore exported Assume disabled by default --- .golangci.yml | 1 + pkg/golinters/revive.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 830b3f405c3b..d8806b143a0e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -117,6 +117,7 @@ linters: # - nestif # - prealloc # - testpackage + # - revive # - wsl issues: diff --git a/pkg/golinters/revive.go b/pkg/golinters/revive.go index 7b588c457051..c161a4659c0a 100644 --- a/pkg/golinters/revive.go +++ b/pkg/golinters/revive.go @@ -160,6 +160,10 @@ func SetReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) { conf.Confidence = cfg.Confidence } + // By default golangci-lint ignores missing doc comments, follow same convention by removing this default rule + // Relevant issue: https://github.com/golangci/golangci-lint/issues/456 + delete(conf.Rules, "exported") + if len(cfg.Rules) != 0 { // Clear default rules, only use rules defined in config conf.Rules = map[string]lint.RuleConfig{} From da374f72b24adb8203c66eda2d81a8161e2643ba Mon Sep 17 00:00:00 2001 From: Sebastian Spaink Date: Sat, 13 Feb 2021 15:58:59 -0600 Subject: [PATCH 3/5] Update with suggested changes --- pkg/golinters/revive.go | 33 +++++++++----------------------- test/testdata/configs/revive.yml | 2 +- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/pkg/golinters/revive.go b/pkg/golinters/revive.go index c161a4659c0a..159605faa1b4 100644 --- a/pkg/golinters/revive.go +++ b/pkg/golinters/revive.go @@ -5,18 +5,16 @@ import ( "fmt" "go/token" "io/ioutil" - "strings" "github.com/mgechev/dots" + reviveConfig "github.com/mgechev/revive/config" + "github.com/mgechev/revive/lint" + "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/lint/linter" "github.com/golangci/golangci-lint/pkg/result" - - reviveConfig "github.com/mgechev/revive/config" - "github.com/mgechev/revive/lint" - "golang.org/x/tools/go/analysis" ) const ( @@ -46,15 +44,13 @@ func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter { nil, ).WithContextSetter(func(lintCtx *linter.Context) { analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { - var ( - files = []string{} - ) + var files []string for _, file := range pass.Files { files = append(files, pass.Fset.PositionFor(file.Pos(), false).Filename) } - conf, err := SetReviveConfig(cfg) + conf, err := setReviveConfig(cfg) if err != nil { return nil, err } @@ -71,7 +67,7 @@ func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter { return nil, err } - packages, err := dots.ResolvePackages(files, normalizeSplit([]string{})) + packages, err := dots.ResolvePackages(files, []string{}) if err != nil { return nil, err } @@ -131,18 +127,7 @@ func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter { }).WithLoadMode(goanalysis.LoadModeSyntax) } -func normalizeSplit(strs []string) []string { - res := []string{} - for _, s := range strs { - t := strings.Trim(s, " \t") - if len(t) > 0 { - res = append(res, t) - } - } - return res -} - -func SetReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) { +func setReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) { // Get revive default configuration conf, err := reviveConfig.GetConfig("") if err != nil { @@ -166,7 +151,7 @@ func SetReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) { if len(cfg.Rules) != 0 { // Clear default rules, only use rules defined in config - conf.Rules = map[string]lint.RuleConfig{} + conf.Rules = make(map[string]lint.RuleConfig, len(cfg.Rules)) } for _, r := range cfg.Rules { conf.Rules[r.Name] = lint.RuleConfig{Arguments: r.Arguments, Severity: lint.Severity(r.Severity)} @@ -177,7 +162,7 @@ func SetReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) { if len(cfg.Directives) != 0 { // Clear default Directives, only use Directives defined in config - conf.Directives = map[string]lint.DirectiveConfig{} + conf.Directives = make(map[string]lint.DirectiveConfig, len(cfg.Directives)) } for _, d := range cfg.Directives { conf.Directives[d.Name] = lint.DirectiveConfig{Severity: lint.Severity(d.Severity)} diff --git a/test/testdata/configs/revive.yml b/test/testdata/configs/revive.yml index 0752b75baf57..7f7ac0b3a346 100644 --- a/test/testdata/configs/revive.yml +++ b/test/testdata/configs/revive.yml @@ -4,4 +4,4 @@ linters-settings: severity: warning rules: - name: indent-error-flow - severity: warning \ No newline at end of file + severity: warning From ff356365a8fd2acf1e8dc2ffcdc36debaf769222 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sun, 14 Feb 2021 13:41:08 +0100 Subject: [PATCH 4/5] review: minor changes. --- pkg/golinters/revive.go | 29 +++++++++++++++-------------- pkg/lint/lintersdb/manager.go | 1 + test/testdata/revive.go | 6 ++++-- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/pkg/golinters/revive.go b/pkg/golinters/revive.go index 159605faa1b4..377ad946b07d 100644 --- a/pkg/golinters/revive.go +++ b/pkg/golinters/revive.go @@ -17,9 +17,7 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) -const ( - reviveName = "revive" -) +const reviveName = "revive" // jsonObject defines a JSON object of an failure type jsonObject struct { @@ -29,17 +27,16 @@ type jsonObject struct { // NewNewRevive returns a new Revive linter. func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter { - var ( - issues []goanalysis.Issue - analyzer = &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, - } - ) + var issues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: goanalysis.TheOnlyAnalyzerName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } return goanalysis.NewLinter( reviveName, - "Fast, configurable, extensible, flexible, and beautiful linter for Go", + "Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.", []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { @@ -81,10 +78,13 @@ func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter { exitChan := make(chan bool) var output string - go (func() { - output, _ = formatter.Format(formatChan, *conf) + go func() { + output, err = formatter.Format(formatChan, *conf) + if err != nil { + lintCtx.Log.Errorf("Format error: %v", err) + } exitChan <- true - })() + }() for f := range failures { if f.Confidence < conf.Confidence { @@ -120,6 +120,7 @@ func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter { FromLinter: reviveName, }, pass)) } + return nil, nil } }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index e8598702ea52..f2d392f18b8e 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -355,6 +355,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetStyle). WithURL("https://github.com/nishanths/predeclared"), linter.NewConfig(golinters.NewRevive(reviveCfg)). + WithPresets(linter.PresetStyle). WithURL("https://github.com/mgechev/revive"), // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives diff --git a/test/testdata/revive.go b/test/testdata/revive.go index 79e33c4d8a7a..224880b36524 100644 --- a/test/testdata/revive.go +++ b/test/testdata/revive.go @@ -2,8 +2,10 @@ //config_path: testdata/configs/revive.yml package testdata -func testRevive(t string) error { - if t == "" { +import "time" + +func testRevive(t *time.Duration) error { + if t == nil { return nil } else { // ERROR "if block ends with a return statement, so drop this else and outdent its block" return nil From 1e1ef0082811f706b03fd2d1578f457e70413204 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sun, 14 Feb 2021 13:51:14 +0100 Subject: [PATCH 5/5] review: add rules link. --- .golangci.example.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.example.yml b/.golangci.example.yml index 96a9928ca6ff..8e8c8ba7e486 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -351,6 +351,7 @@ linters-settings: packages: - github.com/jmoiron/sqlx revive: + # see https://github.com/mgechev/revive#available-rules for details. ignore-generated-header: true severity: warning rules: