feat: add musttag linter (#3386)

Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
This commit is contained in:
Tom 2023-01-21 16:36:35 +04:00 committed by GitHub
parent fb0866a8ba
commit 3cc6373117
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 126 additions and 0 deletions

View File

@ -1209,6 +1209,17 @@ linters-settings:
ignore-words:
- someword
musttag:
# A set of custom functions to check in addition to the builtin ones.
# Default: json, xml, gopkg.in/yaml.v3, BurntSushi/toml, mitchellh/mapstructure
functions:
# The full name of the function, including the package.
- name: github.com/jmoiron/sqlx.Get
# The struct tag whose presence should be ensured.
tag: db
# The position of the argument to check.
arg-pos: 1
nakedret:
# Make an issue if func has more lines of code than this setting, and it has naked returns.
# Default: 30
@ -2037,6 +2048,7 @@ linters:
- makezero
- maligned
- misspell
- musttag
- nakedret
- nestif
- nilerr
@ -2145,6 +2157,7 @@ linters:
- makezero
- maligned
- misspell
- musttag
- nakedret
- nestif
- nilerr

1
go.mod
View File

@ -51,6 +51,7 @@ require (
github.com/jingyugao/rowserrcheck v1.1.1
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af
github.com/julz/importas v0.1.0
github.com/junk1tm/musttag v0.4.1
github.com/kisielk/errcheck v1.6.3
github.com/kkHAIKE/contextcheck v1.1.3
github.com/kulti/thelper v0.6.3

2
go.sum generated
View File

@ -308,6 +308,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY=
github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0=
github.com/junk1tm/musttag v0.4.1 h1:RepN7vE8xObm/AC3WiynRcpFBt8paQR7ztgi09xhTsU=
github.com/junk1tm/musttag v0.4.1/go.mod h1:XkcL/9O6RmD88JBXb+I15nYRl9W4ExhgQeCBEhfMC8U=
github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8=
github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=

View File

@ -179,6 +179,7 @@ type LintersSettings struct {
Makezero MakezeroSettings
Maligned MalignedSettings
Misspell MisspellSettings
MustTag MustTagSettings
Nakedret NakedretSettings
Nestif NestifSettings
NilNil NilNilSettings
@ -538,6 +539,14 @@ type MisspellSettings struct {
IgnoreWords []string `mapstructure:"ignore-words"`
}
type MustTagSettings struct {
Functions []struct {
Name string `mapstructure:"name"`
Tag string `mapstructure:"tag"`
ArgPos int `mapstructure:"arg-pos"`
} `mapstructure:"functions"`
}
type NakedretSettings struct {
MaxFuncLines int `mapstructure:"max-func-lines"`
}

29
pkg/golinters/musttag.go Normal file
View File

@ -0,0 +1,29 @@
package golinters
import (
"github.com/junk1tm/musttag"
"golang.org/x/tools/go/analysis"
"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)
func NewMustTag(setting *config.MustTagSettings) *goanalysis.Linter {
var funcs []musttag.Func
if setting != nil {
for _, fn := range setting.Functions {
funcs = append(funcs, musttag.Func{
Name: fn.Name,
Tag: fn.Tag,
ArgPos: fn.ArgPos,
})
}
}
a := musttag.New(funcs...)
return goanalysis.
NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil).
WithLoadMode(goanalysis.LoadModeTypesInfo)
}

View File

@ -147,6 +147,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
makezeroCfg *config.MakezeroSettings
malignedCfg *config.MalignedSettings
misspellCfg *config.MisspellSettings
musttagCfg *config.MustTagSettings
nakedretCfg *config.NakedretSettings
nestifCfg *config.NestifSettings
nilNilCfg *config.NilNilSettings
@ -224,6 +225,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
makezeroCfg = &m.cfg.LintersSettings.Makezero
malignedCfg = &m.cfg.LintersSettings.Maligned
misspellCfg = &m.cfg.LintersSettings.Misspell
musttagCfg = &m.cfg.LintersSettings.MustTag
nakedretCfg = &m.cfg.LintersSettings.Nakedret
nestifCfg = &m.cfg.LintersSettings.Nestif
nilNilCfg = &m.cfg.LintersSettings.NilNil
@ -632,6 +634,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithAutoFix().
WithURL("https://github.com/client9/misspell"),
linter.NewConfig(golinters.NewMustTag(musttagCfg)).
WithSince("v1.51.0").
WithLoadForGoAnalysis().
WithPresets(linter.PresetStyle, linter.PresetBugs).
WithURL("https://github.com/junk1tm/musttag"),
linter.NewConfig(golinters.NewNakedret(nakedretCfg)).
WithSince("v1.19.0").
WithPresets(linter.PresetStyle).

9
test/testdata/configs/musttag.yml vendored Normal file
View File

@ -0,0 +1,9 @@
linters-settings:
musttag:
functions:
- name: encoding/asn1.Marshal
tag: asn1
arg-pos: 0
- name: encoding/asn1.Unmarshal
tag: asn1
arg-pos: 1

27
test/testdata/musttag.go vendored Normal file
View File

@ -0,0 +1,27 @@
//golangcitest:args -Emusttag
package testdata
import (
"encoding/asn1"
"encoding/json"
)
// builtin functions:
func musttagJSON() {
var user struct { // want `exported fields should be annotated with the "json" tag`
Name string
Email string `json:"email"`
}
json.Marshal(user)
json.Unmarshal(nil, &user)
}
// custom functions from config:
func musttagASN1() {
var user struct {
Name string
Email string `asn1:"email"`
}
asn1.Marshal(user)
asn1.Unmarshal(nil, &user)
}

28
test/testdata/musttag_custom.go vendored Normal file
View File

@ -0,0 +1,28 @@
//golangcitest:args -Emusttag
//golangcitest:config_path testdata/configs/musttag.yml
package testdata
import (
"encoding/asn1"
"encoding/json"
)
// builtin functions:
func musttagJSONCustom() {
var user struct { // want `exported fields should be annotated with the "json" tag`
Name string
Email string `json:"email"`
}
json.Marshal(user)
json.Unmarshal(nil, &user)
}
// custom functions from config:
func musttagASN1Custom() {
var user struct { // want `exported fields should be annotated with the "asn1" tag`
Name string
Email string `asn1:"email"`
}
asn1.Marshal(user)
asn1.Unmarshal(nil, &user)
}