Skip to content

Commit 3cc6373

Browse files
tmzaneldez
andauthored
feat: add musttag linter (#3386)
Co-authored-by: Fernandez Ludovic <[email protected]>
1 parent fb0866a commit 3cc6373

File tree

9 files changed

+126
-0
lines changed

9 files changed

+126
-0
lines changed

.golangci.reference.yml

+13
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,17 @@ linters-settings:
12091209
ignore-words:
12101210
- someword
12111211

1212+
musttag:
1213+
# A set of custom functions to check in addition to the builtin ones.
1214+
# Default: json, xml, gopkg.in/yaml.v3, BurntSushi/toml, mitchellh/mapstructure
1215+
functions:
1216+
# The full name of the function, including the package.
1217+
- name: github.com/jmoiron/sqlx.Get
1218+
# The struct tag whose presence should be ensured.
1219+
tag: db
1220+
# The position of the argument to check.
1221+
arg-pos: 1
1222+
12121223
nakedret:
12131224
# Make an issue if func has more lines of code than this setting, and it has naked returns.
12141225
# Default: 30
@@ -2037,6 +2048,7 @@ linters:
20372048
- makezero
20382049
- maligned
20392050
- misspell
2051+
- musttag
20402052
- nakedret
20412053
- nestif
20422054
- nilerr
@@ -2145,6 +2157,7 @@ linters:
21452157
- makezero
21462158
- maligned
21472159
- misspell
2160+
- musttag
21482161
- nakedret
21492162
- nestif
21502163
- nilerr

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ require (
5151
github.com/jingyugao/rowserrcheck v1.1.1
5252
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af
5353
github.com/julz/importas v0.1.0
54+
github.com/junk1tm/musttag v0.4.1
5455
github.com/kisielk/errcheck v1.6.3
5556
github.com/kkHAIKE/contextcheck v1.1.3
5657
github.com/kulti/thelper v0.6.3

go.sum

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/config/linters_settings.go

+9
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ type LintersSettings struct {
179179
Makezero MakezeroSettings
180180
Maligned MalignedSettings
181181
Misspell MisspellSettings
182+
MustTag MustTagSettings
182183
Nakedret NakedretSettings
183184
Nestif NestifSettings
184185
NilNil NilNilSettings
@@ -538,6 +539,14 @@ type MisspellSettings struct {
538539
IgnoreWords []string `mapstructure:"ignore-words"`
539540
}
540541

542+
type MustTagSettings struct {
543+
Functions []struct {
544+
Name string `mapstructure:"name"`
545+
Tag string `mapstructure:"tag"`
546+
ArgPos int `mapstructure:"arg-pos"`
547+
} `mapstructure:"functions"`
548+
}
549+
541550
type NakedretSettings struct {
542551
MaxFuncLines int `mapstructure:"max-func-lines"`
543552
}

pkg/golinters/musttag.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package golinters
2+
3+
import (
4+
"github.com/junk1tm/musttag"
5+
"golang.org/x/tools/go/analysis"
6+
7+
"github.com/golangci/golangci-lint/pkg/config"
8+
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
9+
)
10+
11+
func NewMustTag(setting *config.MustTagSettings) *goanalysis.Linter {
12+
var funcs []musttag.Func
13+
14+
if setting != nil {
15+
for _, fn := range setting.Functions {
16+
funcs = append(funcs, musttag.Func{
17+
Name: fn.Name,
18+
Tag: fn.Tag,
19+
ArgPos: fn.ArgPos,
20+
})
21+
}
22+
}
23+
24+
a := musttag.New(funcs...)
25+
26+
return goanalysis.
27+
NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil).
28+
WithLoadMode(goanalysis.LoadModeTypesInfo)
29+
}

pkg/lint/lintersdb/manager.go

+8
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
147147
makezeroCfg *config.MakezeroSettings
148148
malignedCfg *config.MalignedSettings
149149
misspellCfg *config.MisspellSettings
150+
musttagCfg *config.MustTagSettings
150151
nakedretCfg *config.NakedretSettings
151152
nestifCfg *config.NestifSettings
152153
nilNilCfg *config.NilNilSettings
@@ -224,6 +225,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
224225
makezeroCfg = &m.cfg.LintersSettings.Makezero
225226
malignedCfg = &m.cfg.LintersSettings.Maligned
226227
misspellCfg = &m.cfg.LintersSettings.Misspell
228+
musttagCfg = &m.cfg.LintersSettings.MustTag
227229
nakedretCfg = &m.cfg.LintersSettings.Nakedret
228230
nestifCfg = &m.cfg.LintersSettings.Nestif
229231
nilNilCfg = &m.cfg.LintersSettings.NilNil
@@ -632,6 +634,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
632634
WithAutoFix().
633635
WithURL("https://github.com/client9/misspell"),
634636

637+
linter.NewConfig(golinters.NewMustTag(musttagCfg)).
638+
WithSince("v1.51.0").
639+
WithLoadForGoAnalysis().
640+
WithPresets(linter.PresetStyle, linter.PresetBugs).
641+
WithURL("https://github.com/junk1tm/musttag"),
642+
635643
linter.NewConfig(golinters.NewNakedret(nakedretCfg)).
636644
WithSince("v1.19.0").
637645
WithPresets(linter.PresetStyle).

test/testdata/configs/musttag.yml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
linters-settings:
2+
musttag:
3+
functions:
4+
- name: encoding/asn1.Marshal
5+
tag: asn1
6+
arg-pos: 0
7+
- name: encoding/asn1.Unmarshal
8+
tag: asn1
9+
arg-pos: 1

test/testdata/musttag.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//golangcitest:args -Emusttag
2+
package testdata
3+
4+
import (
5+
"encoding/asn1"
6+
"encoding/json"
7+
)
8+
9+
// builtin functions:
10+
func musttagJSON() {
11+
var user struct { // want `exported fields should be annotated with the "json" tag`
12+
Name string
13+
Email string `json:"email"`
14+
}
15+
json.Marshal(user)
16+
json.Unmarshal(nil, &user)
17+
}
18+
19+
// custom functions from config:
20+
func musttagASN1() {
21+
var user struct {
22+
Name string
23+
Email string `asn1:"email"`
24+
}
25+
asn1.Marshal(user)
26+
asn1.Unmarshal(nil, &user)
27+
}

test/testdata/musttag_custom.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//golangcitest:args -Emusttag
2+
//golangcitest:config_path testdata/configs/musttag.yml
3+
package testdata
4+
5+
import (
6+
"encoding/asn1"
7+
"encoding/json"
8+
)
9+
10+
// builtin functions:
11+
func musttagJSONCustom() {
12+
var user struct { // want `exported fields should be annotated with the "json" tag`
13+
Name string
14+
Email string `json:"email"`
15+
}
16+
json.Marshal(user)
17+
json.Unmarshal(nil, &user)
18+
}
19+
20+
// custom functions from config:
21+
func musttagASN1Custom() {
22+
var user struct { // want `exported fields should be annotated with the "asn1" tag`
23+
Name string
24+
Email string `asn1:"email"`
25+
}
26+
asn1.Marshal(user)
27+
asn1.Unmarshal(nil, &user)
28+
}

0 commit comments

Comments
 (0)