diff --git a/README.md b/README.md index 2af4e3d4d60e..08b10c76ed93 100644 --- a/README.md +++ b/README.md @@ -210,6 +210,7 @@ depguard: Go linter that checks if package imports are in a list of acceptable p dogsled: Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false] dupl: Tool for code clone detection [fast: true, auto-fix: false] funlen: Tool for detection of long functions [fast: true, auto-fix: false] +go-header: Сhecks that the file header matches the patternс [fast: true, auto-fix: false] gochecknoglobals: Checks that no globals are present in Go code [fast: true, auto-fix: false] gochecknoinits: Checks that no init functions are present in Go code [fast: true, auto-fix: false] gocognit: Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false] @@ -492,6 +493,7 @@ golangci-lint help linters - [funlen](https://github.com/ultraware/funlen) - Tool for detection of long functions - [whitespace](https://github.com/ultraware/whitespace) - Tool for detection of leading and trailing whitespace - [wsl](https://github.com/bombsimon/wsl) - Whitespace Linter - Forces you to use empty lines! +- [go-header](https://github.com/denis-tingajkin/go-header) - Сhecks that the file header matches the pattern - [goprintffuncname](https://github.com/jirfag/go-printf-func-name) - Checks that printf-like functions are named with `f` at the end - [gomnd](https://github.com/tommy-muehle/go-mnd) - An analyzer to detect magic numbers. - [goerr113](https://github.com/Djarvur/go-err113) - Golang linter to check the errors handling expressions @@ -810,6 +812,7 @@ linters-settings: enable-all: false disable: - shadow + - go-header disable-all: false depguard: list-type: blacklist @@ -1287,6 +1290,7 @@ Thanks to [alecthomas/gometalinter](https://github.com/alecthomas/gometalinter) Thanks to [bradleyfalzon/revgrep](https://github.com/bradleyfalzon/revgrep) for cool diff tool. Thanks to developers and authors of used linters: +- [denis-tingajkin](https://github.com/denis-tingajkin) - [timakin](https://github.com/timakin) - [kisielk](https://github.com/kisielk) - [golang](https://github.com/golang) diff --git a/go.mod b/go.mod index 27dc139a2ece..a31da52ff2d5 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Djarvur/go-err113 v0.0.0-20200410182137-af658d038157 github.com/OpenPeeDeeP/depguard v1.0.1 github.com/bombsimon/wsl/v3 v3.0.0 - github.com/fatih/color v1.7.0 + github.com/fatih/color v1.9.0 github.com/go-critic/go-critic v0.4.1 github.com/go-lintpack/lintpack v0.5.2 github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b @@ -36,7 +36,7 @@ require ( github.com/ryancurrah/gomodguard v1.0.4 github.com/securego/gosec v0.0.0-20200316084457-7da9f46445fd github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada // v2.19.8 - github.com/sirupsen/logrus v1.4.2 + github.com/sirupsen/logrus v1.6.0 github.com/sourcegraph/go-diff v0.5.1 github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.5 @@ -51,13 +51,16 @@ require ( github.com/uudashr/gocognit v1.0.1 github.com/valyala/quicktemplate v1.2.0 golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e - gopkg.in/yaml.v2 v2.2.8 + gopkg.in/yaml.v2 v2.3.0 mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f ) -// See https://github.com/golangci/golangci-lint/issues/995 -// Update only after mitigating this issue. -// TODO: Enable back tests with skip "Issue955" after update. -require honnef.co/go/tools v0.0.1-2019.2.3 +require ( + github.com/denis-tingajkin/go-header v0.3.1 + // See https://github.com/golangci/golangci-lint/issues/995 + // Update only after mitigating this issue. + // TODO: Enable back tests with skip "Issue955" after update. + honnef.co/go/tools v0.0.1-2019.2.3 +) diff --git a/go.sum b/go.sum index fbacd6db922e..b764697121fd 100644 --- a/go.sum +++ b/go.sum @@ -29,10 +29,14 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denis-tingajkin/go-header v0.3.0 h1:ZYHBJduNgwucu9mxtVVjJ5p+ERyVzL5SPD2O9NiVymE= +github.com/denis-tingajkin/go-header v0.3.0/go.mod h1:sq/2IxMhaZX+RRcgHfCRx/m0M5na0fBt4/CRe7Lrji0= +github.com/denis-tingajkin/go-header v0.3.1 h1:ymEpSiFjeItCy1FOP+x0M2KdCELdEAHUsNa8F+hHc6w= +github.com/denis-tingajkin/go-header v0.3.1/go.mod h1:sq/2IxMhaZX+RRcgHfCRx/m0M5na0fBt4/CRe7Lrji0= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -151,6 +155,8 @@ github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM52 github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -175,6 +181,8 @@ github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaa github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= 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 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= @@ -237,8 +245,8 @@ github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxr github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= @@ -348,6 +356,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -410,6 +419,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/pkg/config/config.go b/pkg/config/config.go index 2315f308c1c0..bb5794b9a496 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -233,6 +233,7 @@ type LintersSettings struct { Dogsled DogsledSettings Gocognit GocognitSettings Godot GodotSettings + Goheader GoHeaderSettings Testpackage TestpackageSettings Nestif NestifSettings NoLintLint NoLintLintSettings @@ -240,6 +241,12 @@ type LintersSettings struct { Custom map[string]CustomLinterSettings } +type GoHeaderSettings struct { + Values map[string]map[string]string `mapstructure:"values"` + Template string `mapstructure:"template"` + TemplatePath string `mapstructure:"template-path"` +} + type GovetSettings struct { CheckShadowing bool `mapstructure:"check-shadowing"` Settings map[string]map[string]interface{} diff --git a/pkg/golinters/goheader.go b/pkg/golinters/goheader.go new file mode 100644 index 000000000000..e72f6f1c2aad --- /dev/null +++ b/pkg/golinters/goheader.go @@ -0,0 +1,74 @@ +package golinters + +import ( + "go/token" + "sync" + + goheader "github.com/denis-tingajkin/go-header" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const goHeaderName = "goheader" + +func NewGoHeader() *goanalysis.Linter { + var mu sync.Mutex + var issues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: goHeaderName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + goHeaderName, + "Checks is file header matches to pattern", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + cfg := lintCtx.Cfg.LintersSettings.Goheader + c := &goheader.Configuration{ + Values: cfg.Values, + Template: cfg.Template, + TemplatePath: cfg.TemplatePath, + } + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + template, err := c.GetTemplate() + if err != nil { + return nil, err + } + values, err := c.GetValues() + if err != nil { + return nil, err + } + a := goheader.New(goheader.WithTemplate(template), goheader.WithValues(values)) + var res []goanalysis.Issue + for _, file := range pass.Files { + i := a.Analyze(file) + issue := result.Issue{ + Pos: token.Position{ + Line: i.Location().Line + 1, + Column: i.Location().Position, + Filename: pass.Fset.Position(file.Pos()).Filename, + }, + Text: i.Message(), + FromLinter: goHeaderName, + } + res = append(res, goanalysis.NewIssue(&issue, pass)) + } + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + issues = append(issues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return issues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 492b92256f6b..c0ebc949e35d 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -192,6 +192,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetFormatting). WithAutoFix(). WithURL("https://godoc.org/golang.org/x/tools/cmd/goimports"), + linter.NewConfig(golinters.NewGoHeader()). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/denis-tingajkin/go-header"), linter.NewConfig(golinters.NewMaligned()). WithLoadForGoAnalysis(). WithPresets(linter.PresetPerformance). diff --git a/test/linters_test.go b/test/linters_test.go index 1f01814af25e..d8511997cd4f 100644 --- a/test/linters_test.go +++ b/test/linters_test.go @@ -178,10 +178,9 @@ func extractRunContextFromComments(t *testing.T, sourcePath string) *runContext scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() - if !strings.HasPrefix(line, "//") { + if strings.HasPrefix(strings.TrimSpace(line), "package") { return rc } - line = strings.TrimPrefix(line, "//") if strings.HasPrefix(line, "args: ") { assert.Nil(t, rc.args) @@ -207,8 +206,6 @@ func extractRunContextFromComments(t *testing.T, sourcePath string) *runContext rc.configPath = configPath continue } - - assert.Fail(t, "invalid prefix of comment line %s", line) } return rc diff --git a/test/testdata/configs/go-header.yml b/test/testdata/configs/go-header.yml new file mode 100644 index 000000000000..c20ed76c196f --- /dev/null +++ b/test/testdata/configs/go-header.yml @@ -0,0 +1,6 @@ +linters-settings: + goheader: + template: MY {{title}} + values: + const: + title: TITLE. diff --git a/test/testdata/go-header.go b/test/testdata/go-header.go new file mode 100644 index 000000000000..17c3099eaa2a --- /dev/null +++ b/test/testdata/go-header.go @@ -0,0 +1,5 @@ +/*MY TITLE!*/ // ERROR "Expected:TITLE., Actual: TITLE!" + +//args: -Egoheader +//config_path: testdata/configs/go-header.yml +package testdata