Skip to content

Commit 0370d3a

Browse files
authored
Add thelper linter (#1541)
1 parent d327987 commit 0370d3a

File tree

7 files changed

+122
-0
lines changed

7 files changed

+122
-0
lines changed

.golangci.example.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,17 @@ linters-settings:
300300
testpackage:
301301
# regexp pattern to skip files
302302
skip-regexp: (export|internal)_test\.go
303+
thelper:
304+
# The following configurations enable all checks. It can be omitted because all checks are enabled by default.
305+
# You can enable only required checks deleting unnecessary checks.
306+
test:
307+
first: true
308+
name: true
309+
begin: true
310+
benchmark:
311+
first: true
312+
name: true
313+
begin: true
303314
unparam:
304315
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
305316
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ require (
3030
github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3
3131
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a
3232
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3
33+
github.com/kulti/thelper v0.1.0
3334
github.com/kunwardeep/paralleltest v1.0.2
3435
github.com/kyoh86/exportloopref v0.1.8
3536
github.com/maratori/testpackage v1.0.1

go.sum

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/config/config.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ type LintersSettings struct {
267267
Gofumpt GofumptSettings
268268
ErrorLint ErrorLintSettings
269269
Makezero MakezeroSettings
270+
Thelper ThelperSettings
270271

271272
Custom map[string]CustomLinterSettings
272273
}
@@ -391,6 +392,19 @@ type MakezeroSettings struct {
391392
Always bool
392393
}
393394

395+
type ThelperSettings struct {
396+
Test struct {
397+
First bool `mapstructure:"first"`
398+
Name bool `mapstructure:"name"`
399+
Begin bool `mapstructure:"begin"`
400+
} `mapstructure:"test"`
401+
Benchmark struct {
402+
First bool `mapstructure:"first"`
403+
Name bool `mapstructure:"name"`
404+
Begin bool `mapstructure:"begin"`
405+
} `mapstructure:"benchmark"`
406+
}
407+
394408
var defaultLintersSettings = LintersSettings{
395409
Lll: LllSettings{
396410
LineLength: 120,

pkg/golinters/thelper.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package golinters
2+
3+
import (
4+
"strings"
5+
6+
"github.com/kulti/thelper/pkg/analyzer"
7+
"golang.org/x/tools/go/analysis"
8+
9+
"github.com/golangci/golangci-lint/pkg/config"
10+
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
11+
)
12+
13+
func NewThelper(cfg *config.ThelperSettings) *goanalysis.Linter {
14+
a := analyzer.NewAnalyzer()
15+
16+
cfgMap := map[string]map[string]interface{}{}
17+
if cfg != nil {
18+
var opts []string
19+
20+
if cfg.Test.Name {
21+
opts = append(opts, "t_name")
22+
}
23+
if cfg.Test.Begin {
24+
opts = append(opts, "t_begin")
25+
}
26+
if cfg.Test.First {
27+
opts = append(opts, "t_first")
28+
}
29+
30+
if cfg.Benchmark.Name {
31+
opts = append(opts, "b_name")
32+
}
33+
if cfg.Benchmark.Begin {
34+
opts = append(opts, "b_begin")
35+
}
36+
if cfg.Benchmark.First {
37+
opts = append(opts, "b_first")
38+
}
39+
40+
cfgMap[a.Name] = map[string]interface{}{
41+
"checks": strings.Join(opts, ","),
42+
}
43+
}
44+
45+
return goanalysis.NewLinter(
46+
"thelper",
47+
"thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers",
48+
[]*analysis.Analyzer{a},
49+
cfgMap,
50+
).WithLoadMode(goanalysis.LoadModeTypesInfo)
51+
}

pkg/lint/lintersdb/manager.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,13 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
9191
var testpackageCfg *config.TestpackageSettings
9292
var exhaustiveCfg *config.ExhaustiveSettings
9393
var errorlintCfg *config.ErrorLintSettings
94+
var thelperCfg *config.ThelperSettings
9495
if m.cfg != nil {
9596
govetCfg = &m.cfg.LintersSettings.Govet
9697
testpackageCfg = &m.cfg.LintersSettings.Testpackage
9798
exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive
9899
errorlintCfg = &m.cfg.LintersSettings.ErrorLint
100+
thelperCfg = &m.cfg.LintersSettings.Thelper
99101
}
100102
const megacheckName = "megacheck"
101103
lcs := []*linter.Config{
@@ -313,6 +315,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
313315
WithPresets(linter.PresetStyle).
314316
WithLoadForGoAnalysis().
315317
WithURL("https://github.com/tomarrell/wrapcheck"),
318+
linter.NewConfig(golinters.NewThelper(thelperCfg)).
319+
WithPresets(linter.PresetStyle).
320+
WithLoadForGoAnalysis().
321+
WithURL("https://github.com/kulti/thelper"),
316322
linter.NewConfig(golinters.NewTparallel()).
317323
WithPresets(linter.PresetStyle).
318324
WithLoadForGoAnalysis().

test/testdata/thelper.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//args: -Ethelper
2+
package testdata
3+
4+
import "testing"
5+
6+
func thelperWithHelperAfterAssignment(t *testing.T) { // ERROR "test helper function should start from t.Helper()"
7+
_ = 0
8+
t.Helper()
9+
}
10+
11+
func thelperWithNotFirst(s string, t *testing.T, i int) { // ERROR "parameter \*testing.T should be the first"
12+
t.Helper()
13+
}
14+
15+
func thelperWithIncorrectName(o *testing.T) { // ERROR "parameter \*testing.T should have name t"
16+
o.Helper()
17+
}
18+
19+
func bhelperWithHelperAfterAssignment(b *testing.B) { // ERROR "test helper function should start from b.Helper()"
20+
_ = 0
21+
b.Helper()
22+
}
23+
24+
func bhelperWithNotFirst(s string, b *testing.B, i int) { // ERROR "parameter \*testing.B should be the first"
25+
b.Helper()
26+
}
27+
28+
func bhelperWithIncorrectName(o *testing.B) { // ERROR "parameter \*testing.B should have name b"
29+
o.Helper()
30+
}

0 commit comments

Comments
 (0)