Skip to content

Commit fb746c4

Browse files
authored
depguard: migrate to v2 (#3795)
1 parent cec16b6 commit fb746c4

13 files changed

+129
-272
lines changed

.golangci.reference.yml

Lines changed: 32 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -171,49 +171,38 @@ linters-settings:
171171
disable-dec-num-check: false
172172

173173
depguard:
174-
# Kind of list is passed in.
175-
# Allowed values: allowlist|denylist
176-
# Default: denylist
177-
list-type: allowlist
178-
179-
# Check the list against standard lib.
180-
# Default: false
181-
include-go-root: true
182-
183-
# A list of packages for the list type specified.
184-
# Can accept both string prefixes and string glob patterns.
185-
# Default: []
186-
packages:
187-
- github.com/sirupsen/logrus
188-
- allow/**/pkg
189-
190-
# A list of packages for the list type specified.
191-
# Specify an error message to output when a denied package is used.
192-
# Default: []
193-
packages-with-error-message:
194-
- github.com/sirupsen/logrus: 'logging is allowed only by logutils.Log'
195-
196-
# Specify rules by which the linter ignores certain files for consideration.
197-
# Can accept both string prefixes and string glob patterns.
198-
# The ! character in front of the rule is a special character
199-
# which signals that the linter should negate the rule.
200-
# This allows for more precise control, but it is only available for glob patterns.
201-
# Default: []
202-
ignore-file-rules:
203-
- "ignore/**/*.go"
204-
- "!**/*_test.go"
205-
206-
# Create additional guards that follow the same configuration pattern.
207-
# Results from all guards are aggregated together.
208-
additional-guards:
209-
- list-type: denylist
210-
include-go-root: false
211-
packages:
212-
- github.com/stretchr/testify
213-
# Specify rules by which the linter ignores certain files for consideration.
214-
ignore-file-rules:
215-
- "**/*_test.go"
216-
- "**/mock/**/*.go"
174+
# Rules to apply.
175+
#
176+
# Variables:
177+
# - File Variables
178+
# you can still use and exclamation mark ! in front of a variable to say not to use it.
179+
# Example !$test will match any file that is not a go test file.
180+
#
181+
# `$all` - matches all go files
182+
# `$test` - matches all go test files
183+
#
184+
# - Package Variables
185+
#
186+
# `$gostd` - matches all of go's standard library (Pulled from `GOROOT`)
187+
#
188+
# Default: no rules.
189+
rules:
190+
# Name of a rule.
191+
main:
192+
# List of file globs that will match this list of settings to compare against.
193+
# Default: $all
194+
files:
195+
- "!**/*_a _file.go"
196+
# List of allowed packages.
197+
allow:
198+
- $gostd
199+
- github.com/OpenPeeDeeP
200+
# Packages that are not allowed where the value is a suggestion.
201+
deny:
202+
- pkg: "github.com/sirupsen/logrus"
203+
desc: not allowed
204+
- pkg: "github.com/pkg/errors"
205+
desc: Should be replaced by standard lib errors package
217206

218207
dogsled:
219208
# Checks assignments with too many blank identifiers.

.golangci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
linters-settings:
22
depguard:
3+
# old configuration. TODO(ldez): must be removed
34
list-type: denylist
45
packages:
56
# logging is allowed only by logutils.Log, logrus
67
# is allowed to use only in logutils package
78
- github.com/sirupsen/logrus
89
packages-with-error-message:
910
- github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
11+
# new configuration
12+
rules:
13+
logger:
14+
deny:
15+
# logging is allowed only by logutils.Log,
16+
# logrus is allowed to use only in logutils package.
17+
- pkg: "github.com/sirupsen/logrus"
18+
desc: logging is allowed only by logutils.Log
1019
dupl:
1120
threshold: 100
1221
funlen:

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/BurntSushi/toml v1.2.1
1313
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24
1414
github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0
15-
github.com/OpenPeeDeeP/depguard v1.1.1
15+
github.com/OpenPeeDeeP/depguard/v2 v2.0.1
1616
github.com/alexkohler/nakedret/v2 v2.0.1
1717
github.com/alexkohler/prealloc v1.0.0
1818
github.com/alingse/asasalint v0.0.11

go.sum

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

pkg/commands/run.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,6 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, is
191191
true, "Goconst: ignore when constant is not used as function argument")
192192
hideFlag("goconst.ignore-calls")
193193

194-
// (@dixonwille) These flag is only used for testing purposes.
195-
fs.StringSliceVar(&lsc.Depguard.Packages, "depguard.packages", nil,
196-
"Depguard: packages to add to the list")
197-
hideFlag("depguard.packages")
198-
199-
fs.BoolVar(&lsc.Depguard.IncludeGoRoot, "depguard.include-go-root", false,
200-
"Depguard: check list against standard lib")
201-
hideFlag("depguard.include-go-root")
202-
203194
fs.IntVar(&lsc.Lll.TabWidth, "lll.tab-width", 1,
204195
"Lll: tab width in spaces")
205196
hideFlag("lll.tab-width")

pkg/config/linters_settings.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,18 @@ type Cyclop struct {
253253
}
254254

255255
type DepGuardSettings struct {
256-
ListType string `mapstructure:"list-type"`
257-
Packages []string
258-
IncludeGoRoot bool `mapstructure:"include-go-root"`
259-
PackagesWithErrorMessage map[string]string `mapstructure:"packages-with-error-message"`
260-
IgnoreFileRules []string `mapstructure:"ignore-file-rules"`
261-
AdditionalGuards []DepGuardSettings `mapstructure:"additional-guards"`
256+
Rules map[string]*DepGuardList `mapstructure:"rules"`
257+
}
258+
259+
type DepGuardList struct {
260+
Files []string `mapstructure:"files"`
261+
Allow []string `mapstructure:"allow"`
262+
Deny []DepGuardDeny `mapstructure:"deny"`
263+
}
264+
265+
type DepGuardDeny struct {
266+
Pkg string `mapstructure:"pkg"`
267+
Desc string `mapstructure:"desc"`
262268
}
263269

264270
type DecorderSettings struct {

pkg/golinters/depguard.go

Lines changed: 24 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -1,200 +1,46 @@
11
package golinters
22

33
import (
4-
"fmt"
5-
"strings"
6-
"sync"
7-
8-
"github.com/OpenPeeDeeP/depguard"
4+
"github.com/OpenPeeDeeP/depguard/v2"
95
"golang.org/x/tools/go/analysis"
10-
"golang.org/x/tools/go/loader" //nolint:staticcheck // require changes in github.com/OpenPeeDeeP/depguard
116

127
"github.com/golangci/golangci-lint/pkg/config"
13-
"github.com/golangci/golangci-lint/pkg/fsutils"
148
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
15-
"github.com/golangci/golangci-lint/pkg/lint/linter"
16-
"github.com/golangci/golangci-lint/pkg/result"
179
)
1810

19-
const depguardName = "depguard"
20-
2111
func NewDepguard(settings *config.DepGuardSettings) *goanalysis.Linter {
22-
var mu sync.Mutex
23-
var resIssues []goanalysis.Issue
24-
25-
analyzer := &analysis.Analyzer{
26-
Name: depguardName,
27-
Doc: goanalysis.TheOnlyanalyzerDoc,
28-
Run: goanalysis.DummyRun,
29-
}
30-
31-
return goanalysis.NewLinter(
32-
depguardName,
33-
"Go linter that checks if package imports are in a list of acceptable packages",
34-
[]*analysis.Analyzer{analyzer},
35-
nil,
36-
).WithContextSetter(func(lintCtx *linter.Context) {
37-
dg, err := newDepGuard(settings)
38-
39-
analyzer.Run = func(pass *analysis.Pass) (any, error) {
40-
if err != nil {
41-
return nil, err
42-
}
12+
conf := depguard.LinterSettings{}
4313

44-
issues, errRun := dg.run(pass)
45-
if errRun != nil {
46-
return nil, errRun
14+
if settings != nil {
15+
for s, rule := range settings.Rules {
16+
list := &depguard.List{
17+
Files: rule.Files,
18+
Allow: rule.Allow,
4719
}
4820

49-
mu.Lock()
50-
resIssues = append(resIssues, issues...)
51-
mu.Unlock()
52-
53-
return nil, nil
54-
}
55-
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
56-
return resIssues
57-
}).WithLoadMode(goanalysis.LoadModeSyntax)
58-
}
59-
60-
type depGuard struct {
61-
loadConfig *loader.Config
62-
guardians []*guardian
63-
}
64-
65-
func newDepGuard(settings *config.DepGuardSettings) (*depGuard, error) {
66-
ps, err := newGuardian(settings)
67-
if err != nil {
68-
return nil, err
69-
}
70-
71-
d := &depGuard{
72-
loadConfig: &loader.Config{
73-
Cwd: "", // fallbacked to os.Getcwd
74-
Build: nil, // fallbacked to build.Default
75-
},
76-
guardians: []*guardian{ps},
77-
}
78-
79-
for _, additional := range settings.AdditionalGuards {
80-
add := additional
81-
ps, err = newGuardian(&add)
82-
if err != nil {
83-
return nil, err
84-
}
85-
86-
d.guardians = append(d.guardians, ps)
87-
}
88-
89-
return d, nil
90-
}
91-
92-
func (d depGuard) run(pass *analysis.Pass) ([]goanalysis.Issue, error) {
93-
prog := goanalysis.MakeFakeLoaderProgram(pass)
94-
95-
var resIssues []goanalysis.Issue
96-
for _, g := range d.guardians {
97-
issues, errRun := g.run(d.loadConfig, prog, pass)
98-
if errRun != nil {
99-
return nil, errRun
100-
}
101-
102-
resIssues = append(resIssues, issues...)
103-
}
104-
105-
return resIssues, nil
106-
}
107-
108-
type guardian struct {
109-
*depguard.Depguard
110-
pkgsWithErrorMessage map[string]string
111-
}
112-
113-
func newGuardian(settings *config.DepGuardSettings) (*guardian, error) {
114-
var ignoreFileRules []string
115-
for _, rule := range settings.IgnoreFileRules {
116-
ignoreFileRules = append(ignoreFileRules, fsutils.NormalizePathInRegex(rule))
117-
}
118-
119-
dg := &depguard.Depguard{
120-
Packages: settings.Packages,
121-
IncludeGoRoot: settings.IncludeGoRoot,
122-
IgnoreFileRules: ignoreFileRules,
123-
}
124-
125-
var err error
126-
dg.ListType, err = getDepGuardListType(settings.ListType)
127-
if err != nil {
128-
return nil, err
129-
}
130-
131-
// if the list type was a denylist the packages with error messages should be included in the denylist package list
132-
if dg.ListType == depguard.LTBlacklist {
133-
noMessagePackages := make(map[string]bool)
134-
for _, pkg := range dg.Packages {
135-
noMessagePackages[pkg] = true
136-
}
21+
// because of bug with Viper parsing (split on dot) we use a list of struct instead of a map.
22+
// https://github.com/spf13/viper/issues/324
23+
// https://github.com/golangci/golangci-lint/issues/3749#issuecomment-1492536630
13724

138-
for pkg := range settings.PackagesWithErrorMessage {
139-
if _, ok := noMessagePackages[pkg]; !ok {
140-
dg.Packages = append(dg.Packages, pkg)
25+
deny := map[string]string{}
26+
for _, r := range rule.Deny {
27+
deny[r.Pkg] = r.Desc
14128
}
142-
}
143-
}
144-
145-
return &guardian{
146-
Depguard: dg,
147-
pkgsWithErrorMessage: settings.PackagesWithErrorMessage,
148-
}, nil
149-
}
150-
151-
func (g guardian) run(loadConfig *loader.Config, prog *loader.Program, pass *analysis.Pass) ([]goanalysis.Issue, error) {
152-
issues, err := g.Run(loadConfig, prog)
153-
if err != nil {
154-
return nil, err
155-
}
156-
157-
res := make([]goanalysis.Issue, 0, len(issues))
158-
159-
for _, issue := range issues {
160-
res = append(res,
161-
goanalysis.NewIssue(&result.Issue{
162-
Pos: issue.Position,
163-
Text: g.createMsg(issue.PackageName),
164-
FromLinter: depguardName,
165-
}, pass),
166-
)
167-
}
168-
169-
return res, nil
170-
}
171-
172-
func (g guardian) createMsg(pkgName string) string {
173-
msgSuffix := "is in the denylist"
174-
if g.ListType == depguard.LTWhitelist {
175-
msgSuffix = "is not in the allowlist"
176-
}
29+
list.Deny = deny
17730

178-
var userSuppliedMsgSuffix string
179-
if g.pkgsWithErrorMessage != nil {
180-
userSuppliedMsgSuffix = g.pkgsWithErrorMessage[pkgName]
181-
if userSuppliedMsgSuffix != "" {
182-
userSuppliedMsgSuffix = ": " + userSuppliedMsgSuffix
31+
conf[s] = list
18332
}
18433
}
18534

186-
return fmt.Sprintf("%s %s%s", formatCode(pkgName, nil), msgSuffix, userSuppliedMsgSuffix)
187-
}
188-
189-
func getDepGuardListType(listType string) (depguard.ListType, error) {
190-
if listType == "" {
191-
return depguard.LTBlacklist, nil
192-
}
193-
194-
listT, found := depguard.StringToListType[strings.ToLower(listType)]
195-
if !found {
196-
return depguard.LTBlacklist, fmt.Errorf("unsure what list type %s is", listType)
35+
a, err := depguard.NewAnalyzer(&conf)
36+
if err != nil {
37+
linterLogger.Fatalf("depguard: create analyzer: %v", err)
19738
}
19839

199-
return listT, nil
40+
return goanalysis.NewLinter(
41+
a.Name,
42+
a.Doc,
43+
[]*analysis.Analyzer{a},
44+
nil,
45+
).WithLoadMode(goanalysis.LoadModeSyntax)
20046
}

0 commit comments

Comments
 (0)