Skip to content

Add thelper linter #1541

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 1 commit into from
Dec 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .golangci.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,17 @@ linters-settings:
testpackage:
# regexp pattern to skip files
skip-regexp: (export|internal)_test\.go
thelper:
# The following configurations enable all checks. It can be omitted because all checks are enabled by default.
# You can enable only required checks deleting unnecessary checks.
test:
first: true
name: true
begin: true
benchmark:
first: true
name: true
begin: true
unparam:
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ require (
github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3
github.com/kulti/thelper v0.1.0
github.com/kunwardeep/paralleltest v1.0.2
github.com/kyoh86/exportloopref v0.1.8
github.com/maratori/testpackage v1.0.1
Expand Down
9 changes: 9 additions & 0 deletions go.sum

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

14 changes: 14 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ type LintersSettings struct {
Gofumpt GofumptSettings
ErrorLint ErrorLintSettings
Makezero MakezeroSettings
Thelper ThelperSettings

Custom map[string]CustomLinterSettings
}
Expand Down Expand Up @@ -391,6 +392,19 @@ type MakezeroSettings struct {
Always bool
}

type ThelperSettings struct {
Test struct {
First bool `mapstructure:"first"`
Name bool `mapstructure:"name"`
Begin bool `mapstructure:"begin"`
} `mapstructure:"test"`
Benchmark struct {
First bool `mapstructure:"first"`
Name bool `mapstructure:"name"`
Begin bool `mapstructure:"begin"`
} `mapstructure:"benchmark"`
}

var defaultLintersSettings = LintersSettings{
Lll: LllSettings{
LineLength: 120,
Expand Down
51 changes: 51 additions & 0 deletions pkg/golinters/thelper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package golinters

import (
"strings"

"github.com/kulti/thelper/pkg/analyzer"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)

func NewThelper(cfg *config.ThelperSettings) *goanalysis.Linter {
a := analyzer.NewAnalyzer()

cfgMap := map[string]map[string]interface{}{}
if cfg != nil {
var opts []string

if cfg.Test.Name {
opts = append(opts, "t_name")
}
if cfg.Test.Begin {
opts = append(opts, "t_begin")
}
if cfg.Test.First {
opts = append(opts, "t_first")
}

if cfg.Benchmark.Name {
opts = append(opts, "b_name")
}
if cfg.Benchmark.Begin {
opts = append(opts, "b_begin")
}
if cfg.Benchmark.First {
opts = append(opts, "b_first")
}

cfgMap[a.Name] = map[string]interface{}{
"checks": strings.Join(opts, ","),
}
}

return goanalysis.NewLinter(
"thelper",
"thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers",
[]*analysis.Analyzer{a},
cfgMap,
).WithLoadMode(goanalysis.LoadModeTypesInfo)
}
6 changes: 6 additions & 0 deletions pkg/lint/lintersdb/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,13 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
var testpackageCfg *config.TestpackageSettings
var exhaustiveCfg *config.ExhaustiveSettings
var errorlintCfg *config.ErrorLintSettings
var thelperCfg *config.ThelperSettings
if m.cfg != nil {
govetCfg = &m.cfg.LintersSettings.Govet
testpackageCfg = &m.cfg.LintersSettings.Testpackage
exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive
errorlintCfg = &m.cfg.LintersSettings.ErrorLint
thelperCfg = &m.cfg.LintersSettings.Thelper
}
const megacheckName = "megacheck"
lcs := []*linter.Config{
Expand Down Expand Up @@ -313,6 +315,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetStyle).
WithLoadForGoAnalysis().
WithURL("https://github.com/tomarrell/wrapcheck"),
linter.NewConfig(golinters.NewThelper(thelperCfg)).
WithPresets(linter.PresetStyle).
WithLoadForGoAnalysis().
WithURL("https://github.com/kulti/thelper"),
linter.NewConfig(golinters.NewTparallel()).
WithPresets(linter.PresetStyle).
WithLoadForGoAnalysis().
Expand Down
30 changes: 30 additions & 0 deletions test/testdata/thelper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//args: -Ethelper
package testdata

import "testing"

func thelperWithHelperAfterAssignment(t *testing.T) { // ERROR "test helper function should start from t.Helper()"
_ = 0
t.Helper()
}

func thelperWithNotFirst(s string, t *testing.T, i int) { // ERROR "parameter \*testing.T should be the first"
t.Helper()
}

func thelperWithIncorrectName(o *testing.T) { // ERROR "parameter \*testing.T should have name t"
o.Helper()
}

func bhelperWithHelperAfterAssignment(b *testing.B) { // ERROR "test helper function should start from b.Helper()"
_ = 0
b.Helper()
}

func bhelperWithNotFirst(s string, b *testing.B, i int) { // ERROR "parameter \*testing.B should be the first"
b.Helper()
}

func bhelperWithIncorrectName(o *testing.B) { // ERROR "parameter \*testing.B should have name b"
o.Helper()
}