Skip to content

Commit 9c64206

Browse files
add go-header linter
Signed-off-by: denis-tingajkin <denis.tingajkin@xored.com>
1 parent 49b3993 commit 9c64206

File tree

9 files changed

+126
-15
lines changed

9 files changed

+126
-15
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ depguard: Go linter that checks if package imports are in a list of acceptable p
210210
dogsled: Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
211211
dupl: Tool for code clone detection [fast: true, auto-fix: false]
212212
funlen: Tool for detection of long functions [fast: true, auto-fix: false]
213+
go-header: Сhecks that the file header matches the patternс [fast: true, auto-fix: false]
213214
gochecknoglobals: Checks that no globals are present in Go code [fast: true, auto-fix: false]
214215
gochecknoinits: Checks that no init functions are present in Go code [fast: true, auto-fix: false]
215216
gocognit: Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
@@ -492,6 +493,7 @@ golangci-lint help linters
492493
- [funlen](https://github.com/ultraware/funlen) - Tool for detection of long functions
493494
- [whitespace](https://github.com/ultraware/whitespace) - Tool for detection of leading and trailing whitespace
494495
- [wsl](https://github.com/bombsimon/wsl) - Whitespace Linter - Forces you to use empty lines!
496+
- [go-header](https://github.com/denis-tingajkin/go-header) - Сhecks that the file header matches the pattern
495497
- [goprintffuncname](https://github.com/jirfag/go-printf-func-name) - Checks that printf-like functions are named with `f` at the end
496498
- [gomnd](https://github.com/tommy-muehle/go-mnd) - An analyzer to detect magic numbers.
497499
- [goerr113](https://github.com/Djarvur/go-err113) - Golang linter to check the errors handling expressions
@@ -810,6 +812,7 @@ linters-settings:
810812
enable-all: false
811813
disable:
812814
- shadow
815+
- go-header
813816
disable-all: false
814817
depguard:
815818
list-type: blacklist
@@ -1287,6 +1290,7 @@ Thanks to [alecthomas/gometalinter](https://github.com/alecthomas/gometalinter)
12871290
Thanks to [bradleyfalzon/revgrep](https://github.com/bradleyfalzon/revgrep) for cool diff tool.
12881291
12891292
Thanks to developers and authors of used linters:
1293+
- [denis-tingajkin](https://github.com/denis-tingajkin)
12901294
- [timakin](https://github.com/timakin)
12911295
- [kisielk](https://github.com/kisielk)
12921296
- [golang](https://github.com/golang)

go.mod

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/Djarvur/go-err113 v0.0.0-20200410182137-af658d038157
77
github.com/OpenPeeDeeP/depguard v1.0.1
88
github.com/bombsimon/wsl/v3 v3.0.0
9-
github.com/fatih/color v1.7.0
9+
github.com/fatih/color v1.9.0
1010
github.com/go-critic/go-critic v0.4.1
1111
github.com/go-lintpack/lintpack v0.5.2
1212
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b
@@ -36,7 +36,7 @@ require (
3636
github.com/ryancurrah/gomodguard v1.0.4
3737
github.com/securego/gosec v0.0.0-20200316084457-7da9f46445fd
3838
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada // v2.19.8
39-
github.com/sirupsen/logrus v1.4.2
39+
github.com/sirupsen/logrus v1.6.0
4040
github.com/sourcegraph/go-diff v0.5.1
4141
github.com/spf13/cobra v0.0.5
4242
github.com/spf13/pflag v1.0.5
@@ -51,13 +51,16 @@ require (
5151
github.com/uudashr/gocognit v1.0.1
5252
github.com/valyala/quicktemplate v1.2.0
5353
golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e
54-
gopkg.in/yaml.v2 v2.2.8
54+
gopkg.in/yaml.v2 v2.3.0
5555
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed
5656
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect
5757
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f
5858
)
5959

60-
// See https://github.com/golangci/golangci-lint/issues/995
61-
// Update only after mitigating this issue.
62-
// TODO: Enable back tests with skip "Issue955" after update.
63-
require honnef.co/go/tools v0.0.1-2019.2.3
60+
require (
61+
github.com/denis-tingajkin/go-header v0.3.1
62+
// See https://github.com/golangci/golangci-lint/issues/995
63+
// Update only after mitigating this issue.
64+
// TODO: Enable back tests with skip "Issue955" after update.
65+
honnef.co/go/tools v0.0.1-2019.2.3
66+
)

go.sum

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
2929
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3030
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3131
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
32+
github.com/denis-tingajkin/go-header v0.3.0 h1:ZYHBJduNgwucu9mxtVVjJ5p+ERyVzL5SPD2O9NiVymE=
33+
github.com/denis-tingajkin/go-header v0.3.0/go.mod h1:sq/2IxMhaZX+RRcgHfCRx/m0M5na0fBt4/CRe7Lrji0=
34+
github.com/denis-tingajkin/go-header v0.3.1 h1:ymEpSiFjeItCy1FOP+x0M2KdCELdEAHUsNa8F+hHc6w=
35+
github.com/denis-tingajkin/go-header v0.3.1/go.mod h1:sq/2IxMhaZX+RRcgHfCRx/m0M5na0fBt4/CRe7Lrji0=
3236
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
3337
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
34-
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
35-
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
38+
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
39+
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
3640
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
3741
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
3842
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
151155
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
152156
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
153157
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
158+
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
159+
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
154160
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
155161
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
156162
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
175181
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
176182
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
177183
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
184+
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
185+
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
178186
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
179187
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
180188
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
237245
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc=
238246
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
239247
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
240-
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
241-
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
248+
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
249+
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
242250
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
243251
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
244252
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
348356
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
349357
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
350358
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
359+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
351360
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
352361
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
353362
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=
410419
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
411420
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
412421
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
422+
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
423+
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
413424
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
414425
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
415426
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=

pkg/config/config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,20 @@ type LintersSettings struct {
233233
Dogsled DogsledSettings
234234
Gocognit GocognitSettings
235235
Godot GodotSettings
236+
Goheader GoHeaderSettings
236237
Testpackage TestpackageSettings
237238
Nestif NestifSettings
238239
NoLintLint NoLintLintSettings
239240

240241
Custom map[string]CustomLinterSettings
241242
}
242243

244+
type GoHeaderSettings struct {
245+
Values map[string]map[string]string `mapstructure:"values"`
246+
Template string `mapstructure:"template"`
247+
TemplatePath string `mapstructure:"template-path"`
248+
}
249+
243250
type GovetSettings struct {
244251
CheckShadowing bool `mapstructure:"check-shadowing"`
245252
Settings map[string]map[string]interface{}

pkg/golinters/goheader.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package golinters
2+
3+
import (
4+
"go/token"
5+
"sync"
6+
7+
goheader "github.com/denis-tingajkin/go-header"
8+
"golang.org/x/tools/go/analysis"
9+
10+
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
11+
"github.com/golangci/golangci-lint/pkg/lint/linter"
12+
"github.com/golangci/golangci-lint/pkg/result"
13+
)
14+
15+
const goHeaderName = "goheader"
16+
17+
func NewGoHeader() *goanalysis.Linter {
18+
var mu sync.Mutex
19+
var issues []goanalysis.Issue
20+
21+
analyzer := &analysis.Analyzer{
22+
Name: goHeaderName,
23+
Doc: goanalysis.TheOnlyanalyzerDoc,
24+
}
25+
return goanalysis.NewLinter(
26+
goHeaderName,
27+
"Checks is file header matches to pattern",
28+
[]*analysis.Analyzer{analyzer},
29+
nil,
30+
).WithContextSetter(func(lintCtx *linter.Context) {
31+
cfg := lintCtx.Cfg.LintersSettings.Goheader
32+
c := &goheader.Configuration{
33+
Values: cfg.Values,
34+
Template: cfg.Template,
35+
TemplatePath: cfg.TemplatePath,
36+
}
37+
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
38+
template, err := c.GetTemplate()
39+
if err != nil {
40+
return nil, err
41+
}
42+
values, err := c.GetValues()
43+
if err != nil {
44+
return nil, err
45+
}
46+
a := goheader.New(goheader.WithTemplate(template), goheader.WithValues(values))
47+
var res []goanalysis.Issue
48+
for _, file := range pass.Files {
49+
i := a.Analyze(file)
50+
issue := result.Issue{
51+
Pos: token.Position{
52+
Line: i.Location().Line + 1,
53+
Column: i.Location().Position,
54+
Filename: pass.Fset.Position(file.Pos()).Filename,
55+
},
56+
Text: i.Message(),
57+
FromLinter: goHeaderName,
58+
}
59+
res = append(res, goanalysis.NewIssue(&issue, pass))
60+
}
61+
if len(res) == 0 {
62+
return nil, nil
63+
}
64+
65+
mu.Lock()
66+
issues = append(issues, res...)
67+
mu.Unlock()
68+
69+
return nil, nil
70+
}
71+
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
72+
return issues
73+
}).WithLoadMode(goanalysis.LoadModeSyntax)
74+
}

pkg/lint/lintersdb/manager.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
192192
WithPresets(linter.PresetFormatting).
193193
WithAutoFix().
194194
WithURL("https://godoc.org/golang.org/x/tools/cmd/goimports"),
195+
linter.NewConfig(golinters.NewGoHeader()).
196+
WithPresets(linter.PresetStyle).
197+
WithLoadForGoAnalysis().
198+
WithURL("https://github.com/denis-tingajkin/go-header"),
195199
linter.NewConfig(golinters.NewMaligned()).
196200
WithLoadForGoAnalysis().
197201
WithPresets(linter.PresetPerformance).

test/linters_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,9 @@ func extractRunContextFromComments(t *testing.T, sourcePath string) *runContext
178178
scanner := bufio.NewScanner(f)
179179
for scanner.Scan() {
180180
line := scanner.Text()
181-
if !strings.HasPrefix(line, "//") {
181+
if strings.HasPrefix(strings.TrimSpace(line), "package") {
182182
return rc
183183
}
184-
185184
line = strings.TrimPrefix(line, "//")
186185
if strings.HasPrefix(line, "args: ") {
187186
assert.Nil(t, rc.args)
@@ -207,8 +206,6 @@ func extractRunContextFromComments(t *testing.T, sourcePath string) *runContext
207206
rc.configPath = configPath
208207
continue
209208
}
210-
211-
assert.Fail(t, "invalid prefix of comment line %s", line)
212209
}
213210

214211
return rc

test/testdata/configs/go-header.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
linters-settings:
2+
goheader:
3+
template: MY {{title}}
4+
values:
5+
const:
6+
title: TITLE.

test/testdata/go-header.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/*MY TITLE!*/ // ERROR "Expected:TITLE., Actual: TITLE!"
2+
3+
//args: -Egoheader
4+
//config_path: testdata/configs/go-header.yml
5+
package testdata

0 commit comments

Comments
 (0)