Skip to content

Commit f547cb5

Browse files
Check function literals in unused-param (#966)
1 parent 64dda06 commit f547cb5

File tree

2 files changed

+59
-33
lines changed

2 files changed

+59
-33
lines changed

rule/unused-param.go

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -87,54 +87,64 @@ type lintUnusedParamRule struct {
8787
}
8888

8989
func (w lintUnusedParamRule) Visit(node ast.Node) ast.Visitor {
90+
var (
91+
funcType *ast.FuncType
92+
funcBody *ast.BlockStmt
93+
)
9094
switch n := node.(type) {
95+
case *ast.FuncLit:
96+
funcType = n.Type
97+
funcBody = n.Body
9198
case *ast.FuncDecl:
92-
params := retrieveNamedParams(n.Type.Params)
93-
if len(params) < 1 {
94-
return nil // skip, func without parameters
95-
}
96-
9799
if n.Body == nil {
98100
return nil // skip, is a function prototype
99101
}
100102

101-
// inspect the func body looking for references to parameters
102-
fselect := func(n ast.Node) bool {
103-
ident, isAnID := n.(*ast.Ident)
103+
funcType = n.Type
104+
funcBody = n.Body
105+
default:
106+
return w // skip, not a function
107+
}
104108

105-
if !isAnID {
106-
return false
107-
}
109+
params := retrieveNamedParams(funcType.Params)
110+
if len(params) < 1 {
111+
return w // skip, func without parameters
112+
}
108113

109-
_, isAParam := params[ident.Obj]
110-
if isAParam {
111-
params[ident.Obj] = false // mark as used
112-
}
114+
// inspect the func body looking for references to parameters
115+
fselect := func(n ast.Node) bool {
116+
ident, isAnID := n.(*ast.Ident)
113117

118+
if !isAnID {
114119
return false
115120
}
116-
_ = pick(n.Body, fselect)
117-
118-
for _, p := range n.Type.Params.List {
119-
for _, n := range p.Names {
120-
if w.allowRegex.FindStringIndex(n.Name) != nil {
121-
continue
122-
}
123-
if params[n.Obj] {
124-
w.onFailure(lint.Failure{
125-
Confidence: 1,
126-
Node: n,
127-
Category: "bad practice",
128-
Failure: fmt.Sprintf(w.failureMsg, n.Name),
129-
})
130-
}
131-
}
121+
122+
_, isAParam := params[ident.Obj]
123+
if isAParam {
124+
params[ident.Obj] = false // mark as used
132125
}
133126

134-
return nil // full method body already inspected
127+
return false
128+
}
129+
_ = pick(funcBody, fselect)
130+
131+
for _, p := range funcType.Params.List {
132+
for _, n := range p.Names {
133+
if w.allowRegex.FindStringIndex(n.Name) != nil {
134+
continue
135+
}
136+
if params[n.Obj] {
137+
w.onFailure(lint.Failure{
138+
Confidence: 1,
139+
Node: n,
140+
Category: "bad practice",
141+
Failure: fmt.Sprintf(w.failureMsg, n.Name),
142+
})
143+
}
144+
}
135145
}
136146

137-
return w
147+
return w // full method body was inspected
138148
}
139149

140150
func retrieveNamedParams(params *ast.FieldList) map[*ast.Object]bool {

testdata/unused-param.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,19 @@ func encodeFixed64Rpc(dAtA []byte, offset int, v uint64, i int) int {
166166

167167
return 8
168168
}
169+
170+
func innerAnonymousFunctionWithoutUsage() {
171+
innerFunc := func(a int) {} // MATCH /parameter 'a' seems to be unused, consider removing or renaming it as _/
172+
innerFunc(1)
173+
}
174+
175+
func innerAnonymousFunctionWithUsage() {
176+
innerFunc := func(a int) {
177+
a += 1
178+
}
179+
innerFunc(1)
180+
181+
return someFunc(func(values []int) float64 { // MATCH /parameter 'values' seems to be unused, consider removing or renaming it as _/
182+
return 1.1
183+
})
184+
}

0 commit comments

Comments
 (0)