Skip to content

Commit 92168d0

Browse files
tpoundsjirfag
authored andcommitted
Add dogsled linter. (golangci#705)
1 parent 6a979fb commit 92168d0

File tree

8 files changed

+147
-0
lines changed

8 files changed

+147
-0
lines changed

.golangci.example.yml

+3
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ linters-settings:
201201
- NOTE
202202
- OPTIMIZE # marks code that should be optimized before merging
203203
- HACK # marks hack-arounds that should be removed before merging
204+
dogsled:
205+
# checks assignments with too many blank identifiers; default is 2
206+
max-blank-identifiers: 2
204207

205208
linters:
206209
enable:

.golangci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ linters:
4949
- bodyclose
5050
- deadcode
5151
- depguard
52+
# - dogsled - TODO: enable it when golangci.com will support it.
5253
- dupl
5354
- errcheck
5455
# - funlen - TODO: enable it when golangci.com will support it.

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ $ golangci-lint help linters
195195
Disabled by default linters:
196196
bodyclose: checks whether HTTP response body is closed successfully [fast: false, auto-fix: false]
197197
depguard: Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]
198+
dogsled: Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
198199
dupl: Tool for code clone detection [fast: true, auto-fix: false]
199200
funlen: Tool for detection of long functions [fast: true, auto-fix: false]
200201
gochecknoglobals: Checks that no globals are present in Go code [fast: true, auto-fix: false]
@@ -454,6 +455,7 @@ golangci-lint help linters
454455
- [misspell](https://github.com/client9/misspell) - Finds commonly misspelled English words in comments
455456
- [lll](https://github.com/walle/lll) - Reports long lines
456457
- [unparam](https://github.com/mvdan/unparam) - Reports unused function parameters
458+
- [dogsled](https://github.com/alexkohler/dogsled) - Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
457459
- [nakedret](https://github.com/alexkohler/nakedret) - Finds naked returns in functions greater than a specified function length
458460
- [prealloc](https://github.com/alexkohler/prealloc) - Finds slice declarations that could potentially be preallocated
459461
- [scopelint](https://github.com/kyoh86/scopelint) - Scopelint checks for unpinned variables in go programs
@@ -783,6 +785,9 @@ linters-settings:
783785
- NOTE
784786
- OPTIMIZE # marks code that should be optimized before merging
785787
- HACK # marks hack-arounds that should be removed before merging
788+
dogsled:
789+
# checks assignments with too many blank identifiers; default is 2
790+
max-blank-identifiers: 2
786791
787792
linters:
788793
enable:
@@ -916,6 +921,7 @@ linters:
916921
- bodyclose
917922
- deadcode
918923
- depguard
924+
# - dogsled - TODO: enable it when golangci.com will support it.
919925
- dupl
920926
- errcheck
921927
# - funlen - TODO: enable it when golangci.com will support it.

pkg/config/config.go

+8
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ type LintersSettings struct {
178178
Errcheck ErrcheckSettings
179179
Gocritic GocriticSettings
180180
Godox GodoxSettings
181+
Dogsled DogsledSettings
181182
}
182183

183184
type GovetSettings struct {
@@ -234,6 +235,10 @@ type GodoxSettings struct {
234235
Keywords []string
235236
}
236237

238+
type DogsledSettings struct {
239+
MaxBlankIdentifiers int `mapstructure:"max-blank-identifiers"`
240+
}
241+
237242
var defaultLintersSettings = LintersSettings{
238243
Lll: LllSettings{
239244
LineLength: 120,
@@ -256,6 +261,9 @@ var defaultLintersSettings = LintersSettings{
256261
Godox: GodoxSettings{
257262
Keywords: []string{},
258263
},
264+
Dogsled: DogsledSettings{
265+
MaxBlankIdentifiers: 2,
266+
},
259267
}
260268

261269
type Linters struct {

pkg/golinters/dogsled.go

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package golinters
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"go/ast"
7+
"go/token"
8+
9+
"github.com/golangci/golangci-lint/pkg/lint/linter"
10+
"github.com/golangci/golangci-lint/pkg/result"
11+
)
12+
13+
type Dogsled struct{}
14+
15+
func (Dogsled) Name() string {
16+
return "dogsled"
17+
}
18+
19+
func (Dogsled) Desc() string {
20+
return "Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())"
21+
}
22+
23+
func (d Dogsled) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
24+
25+
var res []result.Issue
26+
for _, f := range lintCtx.ASTCache.GetAllValidFiles() {
27+
v := returnsVisitor{
28+
maxBlanks: lintCtx.Settings().Dogsled.MaxBlankIdentifiers,
29+
f: f.Fset,
30+
}
31+
ast.Walk(&v, f.F)
32+
res = append(res, v.issues...)
33+
}
34+
35+
return res, nil
36+
}
37+
38+
type returnsVisitor struct {
39+
f *token.FileSet
40+
maxBlanks int
41+
issues []result.Issue
42+
}
43+
44+
func (v *returnsVisitor) Visit(node ast.Node) ast.Visitor {
45+
funcDecl, ok := node.(*ast.FuncDecl)
46+
if !ok {
47+
return v
48+
}
49+
if funcDecl.Body == nil {
50+
return v
51+
}
52+
53+
for _, expr := range funcDecl.Body.List {
54+
assgnStmt, ok := expr.(*ast.AssignStmt)
55+
if !ok {
56+
continue
57+
}
58+
59+
numBlank := 0
60+
for _, left := range assgnStmt.Lhs {
61+
ident, ok := left.(*ast.Ident)
62+
if !ok {
63+
continue
64+
}
65+
if ident.Name == "_" {
66+
numBlank++
67+
}
68+
}
69+
70+
if numBlank > v.maxBlanks {
71+
v.issues = append(v.issues, result.Issue{
72+
FromLinter: Dogsled{}.Name(),
73+
Text: fmt.Sprintf("declaration has %v blank identifiers", numBlank),
74+
Pos: v.f.Position(assgnStmt.Pos()),
75+
})
76+
}
77+
}
78+
return v
79+
}

pkg/lint/lintersdb/manager.go

+4
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
215215
WithLoadDepsTypeInfo().
216216
WithSSA().
217217
WithURL("https://github.com/mvdan/unparam"),
218+
linter.NewConfig(golinters.Dogsled{}).
219+
WithPresets(linter.PresetStyle).
220+
WithSpeed(10).
221+
WithURL("https://github.com/alexkohler/dogsled"),
218222
linter.NewConfig(golinters.Nakedret{}).
219223
WithPresets(linter.PresetComplexity).
220224
WithSpeed(10).

test/testdata/dogsled.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//args: -Edogsled
2+
package testdata
3+
4+
func Dogsled() {
5+
_ = ret1()
6+
_, _ = ret2()
7+
_, _, _ = ret3() // ERROR "declaration has 3 blank identifiers"
8+
_, _, _, _ = ret4() // ERROR "declaration has 4 blank identifiers"
9+
}
10+
11+
func ret1() (a int) {
12+
return 1
13+
}
14+
15+
func ret2() (a, b int) {
16+
return 1, 2
17+
}
18+
19+
func ret3() (a, b, c int) {
20+
return 1, 2, 3
21+
}
22+
23+
func ret4() (a, b, c, d int) {
24+
return 1, 2, 3, 4
25+
}

third_party/dogsled/LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Alex Kohler
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)