Skip to content

Commit 138699d

Browse files
timkralldez
andauthored
depguard: updates configuration (#2467)
Co-authored-by: Fernandez Ludovic <[email protected]>
1 parent 29eedbf commit 138699d

9 files changed

+226
-79
lines changed

.golangci.example.yml

+13-2
Original file line numberDiff line numberDiff line change
@@ -507,13 +507,24 @@ linters-settings:
507507
disable-all: false
508508

509509
depguard:
510-
list-type: blacklist
510+
list-type: denylist
511511
include-go-root: false
512512
packages:
513513
- github.com/sirupsen/logrus
514514
packages-with-error-message:
515-
# specify an error message to output when a blacklisted package is used
515+
# specify an error message to output when a denied package is used
516516
- github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
517+
# create additional guards that follow the same configuration pattern
518+
# results from all guards are aggregated together
519+
additional-guards:
520+
- list-type: denylist
521+
include-go-root: false
522+
packages:
523+
- github.com/stretchr/testify
524+
# specify rules by which the linter ignores certain files for consideration
525+
ignore-file-rules:
526+
- "**/*_test.go"
527+
- "**/mock/**/*.go"
517528

518529
ifshort:
519530
# Maximum length of variable declaration measured in number of lines, after which linter won't suggest using short syntax.

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
github.com/Antonboom/nilnil v0.1.0
99
github.com/BurntSushi/toml v0.4.1
1010
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24
11-
github.com/OpenPeeDeeP/depguard v1.0.1
11+
github.com/OpenPeeDeeP/depguard v1.1.0
1212
github.com/alexkohler/prealloc v1.0.0
1313
github.com/ashanbrown/forbidigo v1.2.0
1414
github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde

go.sum

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

pkg/config/linters_settings.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,10 @@ type Cyclop struct {
176176
type DepGuardSettings struct {
177177
ListType string `mapstructure:"list-type"`
178178
Packages []string
179-
IncludeGoRoot bool `mapstructure:"include-go-root"`
180-
PackagesWithErrorMessage map[string]string `mapstructure:"packages-with-error-message"`
179+
IncludeGoRoot bool `mapstructure:"include-go-root"`
180+
PackagesWithErrorMessage map[string]string `mapstructure:"packages-with-error-message"`
181+
IgnoreFileRules []string `mapstructure:"ignore-file-rules"`
182+
AdditionalGuards []DepGuardSettings `mapstructure:"additional-guards"`
181183
}
182184

183185
type DecorderSettings struct {

pkg/golinters/depguard.go

+149-69
Original file line numberDiff line numberDiff line change
@@ -9,99 +9,42 @@ import (
99
"golang.org/x/tools/go/analysis"
1010
"golang.org/x/tools/go/loader" //nolint:staticcheck // require changes in github.com/OpenPeeDeeP/depguard
1111

12+
"github.com/golangci/golangci-lint/pkg/config"
1213
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
1314
"github.com/golangci/golangci-lint/pkg/lint/linter"
1415
"github.com/golangci/golangci-lint/pkg/result"
1516
)
1617

17-
func setDepguardListType(dg *depguard.Depguard, lintCtx *linter.Context) error {
18-
listType := lintCtx.Settings().Depguard.ListType
19-
var found bool
20-
dg.ListType, found = depguard.StringToListType[strings.ToLower(listType)]
21-
if !found {
22-
if listType != "" {
23-
return fmt.Errorf("unsure what list type %s is", listType)
24-
}
25-
dg.ListType = depguard.LTBlacklist
26-
}
27-
28-
return nil
29-
}
30-
31-
func setupDepguardPackages(dg *depguard.Depguard, lintCtx *linter.Context) {
32-
if dg.ListType == depguard.LTBlacklist {
33-
// if the list type was a blacklist the packages with error messages should
34-
// be included in the blacklist package list
35-
36-
noMessagePackages := make(map[string]bool)
37-
for _, pkg := range dg.Packages {
38-
noMessagePackages[pkg] = true
39-
}
40-
41-
for pkg := range lintCtx.Settings().Depguard.PackagesWithErrorMessage {
42-
if _, ok := noMessagePackages[pkg]; !ok {
43-
dg.Packages = append(dg.Packages, pkg)
44-
}
45-
}
46-
}
47-
}
18+
const depguardLinterName = "depguard"
4819

4920
func NewDepguard() *goanalysis.Linter {
50-
const linterName = "depguard"
5121
var mu sync.Mutex
5222
var resIssues []goanalysis.Issue
5323

5424
analyzer := &analysis.Analyzer{
55-
Name: linterName,
25+
Name: depguardLinterName,
5626
Doc: goanalysis.TheOnlyanalyzerDoc,
5727
}
5828
return goanalysis.NewLinter(
59-
linterName,
29+
depguardLinterName,
6030
"Go linter that checks if package imports are in a list of acceptable packages",
6131
[]*analysis.Analyzer{analyzer},
6232
nil,
6333
).WithContextSetter(func(lintCtx *linter.Context) {
64-
dgSettings := &lintCtx.Settings().Depguard
65-
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
66-
prog := goanalysis.MakeFakeLoaderProgram(pass)
67-
dg := &depguard.Depguard{
68-
Packages: dgSettings.Packages,
69-
IncludeGoRoot: dgSettings.IncludeGoRoot,
70-
}
71-
if err := setDepguardListType(dg, lintCtx); err != nil {
72-
return nil, err
73-
}
74-
setupDepguardPackages(dg, lintCtx)
34+
dg, err := newDepGuard(&lintCtx.Settings().Depguard)
7535

76-
loadConfig := &loader.Config{
77-
Cwd: "", // fallbacked to os.Getcwd
78-
Build: nil, // fallbacked to build.Default
79-
}
80-
issues, err := dg.Run(loadConfig, prog)
36+
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
8137
if err != nil {
8238
return nil, err
8339
}
84-
if len(issues) == 0 {
85-
return nil, nil
86-
}
87-
msgSuffix := "is in the blacklist"
88-
if dg.ListType == depguard.LTWhitelist {
89-
msgSuffix = "is not in the whitelist"
90-
}
91-
res := make([]goanalysis.Issue, 0, len(issues))
92-
for _, i := range issues {
93-
userSuppliedMsgSuffix := dgSettings.PackagesWithErrorMessage[i.PackageName]
94-
if userSuppliedMsgSuffix != "" {
95-
userSuppliedMsgSuffix = ": " + userSuppliedMsgSuffix
96-
}
97-
res = append(res, goanalysis.NewIssue(&result.Issue{
98-
Pos: i.Position,
99-
Text: fmt.Sprintf("%s %s%s", formatCode(i.PackageName, lintCtx.Cfg), msgSuffix, userSuppliedMsgSuffix),
100-
FromLinter: linterName,
101-
}, pass))
40+
41+
issues, errRun := dg.run(pass)
42+
if errRun != nil {
43+
return nil, errRun
10244
}
45+
10346
mu.Lock()
104-
resIssues = append(resIssues, res...)
47+
resIssues = append(resIssues, issues...)
10548
mu.Unlock()
10649

10750
return nil, nil
@@ -110,3 +53,140 @@ func NewDepguard() *goanalysis.Linter {
11053
return resIssues
11154
}).WithLoadMode(goanalysis.LoadModeTypesInfo)
11255
}
56+
57+
type depGuard struct {
58+
loadConfig *loader.Config
59+
guardians []*guardian
60+
}
61+
62+
func newDepGuard(settings *config.DepGuardSettings) (*depGuard, error) {
63+
ps, err := newGuardian(settings)
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
d := &depGuard{
69+
loadConfig: &loader.Config{
70+
Cwd: "", // fallbacked to os.Getcwd
71+
Build: nil, // fallbacked to build.Default
72+
},
73+
guardians: []*guardian{ps},
74+
}
75+
76+
for _, additional := range settings.AdditionalGuards {
77+
add := additional
78+
ps, err = newGuardian(&add)
79+
if err != nil {
80+
return nil, err
81+
}
82+
83+
d.guardians = append(d.guardians, ps)
84+
}
85+
86+
return d, nil
87+
}
88+
89+
func (d depGuard) run(pass *analysis.Pass) ([]goanalysis.Issue, error) {
90+
prog := goanalysis.MakeFakeLoaderProgram(pass)
91+
92+
var resIssues []goanalysis.Issue
93+
for _, g := range d.guardians {
94+
issues, errRun := g.run(d.loadConfig, prog, pass)
95+
if errRun != nil {
96+
return nil, errRun
97+
}
98+
99+
resIssues = append(resIssues, issues...)
100+
}
101+
102+
return resIssues, nil
103+
}
104+
105+
type guardian struct {
106+
*depguard.Depguard
107+
pkgsWithErrorMessage map[string]string
108+
}
109+
110+
func newGuardian(settings *config.DepGuardSettings) (*guardian, error) {
111+
dg := &depguard.Depguard{
112+
Packages: settings.Packages,
113+
IncludeGoRoot: settings.IncludeGoRoot,
114+
IgnoreFileRules: settings.IgnoreFileRules,
115+
}
116+
117+
var err error
118+
dg.ListType, err = getDepGuardListType(settings.ListType)
119+
if err != nil {
120+
return nil, err
121+
}
122+
123+
// if the list type was a blacklist the packages with error messages should be included in the blacklist package list
124+
if dg.ListType == depguard.LTBlacklist {
125+
noMessagePackages := make(map[string]bool)
126+
for _, pkg := range dg.Packages {
127+
noMessagePackages[pkg] = true
128+
}
129+
130+
for pkg := range settings.PackagesWithErrorMessage {
131+
if _, ok := noMessagePackages[pkg]; !ok {
132+
dg.Packages = append(dg.Packages, pkg)
133+
}
134+
}
135+
}
136+
137+
return &guardian{
138+
Depguard: dg,
139+
pkgsWithErrorMessage: settings.PackagesWithErrorMessage,
140+
}, nil
141+
}
142+
143+
func (g guardian) run(loadConfig *loader.Config, prog *loader.Program, pass *analysis.Pass) ([]goanalysis.Issue, error) {
144+
issues, err := g.Run(loadConfig, prog)
145+
if err != nil {
146+
return nil, err
147+
}
148+
149+
res := make([]goanalysis.Issue, 0, len(issues))
150+
151+
for _, issue := range issues {
152+
res = append(res,
153+
goanalysis.NewIssue(&result.Issue{
154+
Pos: issue.Position,
155+
Text: g.createMsg(issue.PackageName),
156+
FromLinter: depguardLinterName,
157+
}, pass),
158+
)
159+
}
160+
161+
return res, nil
162+
}
163+
164+
func (g guardian) createMsg(pkgName string) string {
165+
msgSuffix := "is in the blacklist"
166+
if g.ListType == depguard.LTWhitelist {
167+
msgSuffix = "is not in the whitelist"
168+
}
169+
170+
var userSuppliedMsgSuffix string
171+
if g.pkgsWithErrorMessage != nil {
172+
userSuppliedMsgSuffix = g.pkgsWithErrorMessage[pkgName]
173+
if userSuppliedMsgSuffix != "" {
174+
userSuppliedMsgSuffix = ": " + userSuppliedMsgSuffix
175+
}
176+
}
177+
178+
return fmt.Sprintf("%s %s%s", formatCode(pkgName, nil), msgSuffix, userSuppliedMsgSuffix)
179+
}
180+
181+
func getDepGuardListType(listType string) (depguard.ListType, error) {
182+
if listType == "" {
183+
return depguard.LTBlacklist, nil
184+
}
185+
186+
listT, found := depguard.StringToListType[strings.ToLower(listType)]
187+
if !found {
188+
return depguard.LTBlacklist, fmt.Errorf("unsure what list type %s is", listType)
189+
}
190+
191+
return listT, nil
192+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
linters-settings:
2+
depguard:
3+
list-type: denylist
4+
include-go-root: true
5+
packages:
6+
- compress/*
7+
packages-with-error-message:
8+
log: "don't use log"
9+
additional-guards:
10+
- list-type: denylist
11+
include-go-root: true
12+
packages:
13+
- fmt
14+
packages-with-error-message:
15+
strings: "disallowed in additional guard"
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
linters-settings:
2+
depguard:
3+
list-type: denylist
4+
include-go-root: true
5+
packages:
6+
- compress/*
7+
packages-with-error-message:
8+
log: "don't use log"
9+
ignore-file-rules:
10+
- "**/*_ignore_file_rules.go"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//args: -Edepguard
2+
//config_path: testdata/configs/depguard_additional_guards.yml
3+
package testdata
4+
5+
import (
6+
"compress/gzip" // ERROR "`compress/gzip` is in the blacklist"
7+
"fmt" // ERROR "`fmt` is in the blacklist"
8+
"log" // ERROR "`log` is in the blacklist: don't use log"
9+
"strings" // ERROR "`strings` is in the blacklist: disallowed in additional guard"
10+
)
11+
12+
func SpewDebugInfo() {
13+
log.Println(gzip.BestCompression)
14+
log.Println(fmt.Sprintf("SpewDebugInfo"))
15+
log.Println(strings.ToLower("SpewDebugInfo"))
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//args: -Edepguard
2+
//config_path: testdata/configs/depguard_ignore_file_rules.yml
3+
package testdata
4+
5+
// NOTE - No lint errors becuase this file is ignored
6+
import (
7+
"compress/gzip"
8+
"log"
9+
)
10+
11+
func SpewDebugInfo() {
12+
log.Println(gzip.BestCompression)
13+
}

0 commit comments

Comments
 (0)