@@ -62,15 +62,16 @@ func run(pass *analysis.Pass) (interface{}, error) {
62
62
63
63
// Find the innermost containing block, and get the list
64
64
// of statements starting with the one containing call.
65
- stmts , withinAnotherCall := restOfBlock (stack )
66
- if withinAnotherCall {
67
- // We skip cases when the results of a call to http member
68
- // are passed directly to another call, as that later call
69
- // could check err != nil and create false positives (#52661).
65
+ stmts , ncalls := restOfBlock (stack )
66
+ if len (stmts ) < 2 {
67
+ // The call to the http function is the last statement of the block.
70
68
return true
71
69
}
72
- if len (stmts ) < 2 {
73
- return true // the call to the http function is the last statement of the block.
70
+
71
+ // Skip cases in which the call is wrapped by another (#52661).
72
+ // Example: resp, err := checkError(http.Get(url))
73
+ if ncalls > 1 {
74
+ return true
74
75
}
75
76
76
77
asg , ok := stmts [0 ].(* ast.AssignStmt )
@@ -136,34 +137,26 @@ func isHTTPFuncOrMethodOnClient(info *types.Info, expr *ast.CallExpr) bool {
136
137
return ok && isNamedType (ptr .Elem (), "net/http" , "Client" ) // method on *http.Client.
137
138
}
138
139
139
- // restOfBlock, given a traversal stack, checks if the current node
140
- // (the last element of stack) appears as an argument to another call.
141
- // If not, it finds the innermost containing block and returns the
142
- // suffix of its statements starting with the current node. Otherwise,
143
- // returns an empty slice.
144
- func restOfBlock (stack []ast.Node ) ([]ast.Stmt , bool ) {
140
+ // restOfBlock, given a traversal stack, finds the innermost containing
141
+ // block and returns the suffix of its statements starting with the current
142
+ // node, along with the number of call expressions encountered.
143
+ func restOfBlock (stack []ast.Node ) ([]ast.Stmt , int ) {
144
+ var ncalls int
145
145
for i := len (stack ) - 1 ; i >= 0 ; i -- {
146
- // If the current node appears within another call, then
147
- // this has to happen within the same block. We can thus
148
- // immediately return on whichever we see first, a block
149
- // statement or a call statement.
150
-
151
146
if b , ok := stack [i ].(* ast.BlockStmt ); ok {
152
147
for j , v := range b .List {
153
148
if v == stack [i + 1 ] {
154
- return b .List [j :], false
149
+ return b .List [j :], ncalls
155
150
}
156
151
}
157
152
break
158
153
}
159
154
160
- // The call to an http member currently analyzed is at len(stack)-1.
161
- if _ , ok := stack [i ].(* ast.CallExpr ); ok && i != len (stack )- 1 {
162
- return nil , true // e.g. "resp, err := wrap(http.Get(...))"
155
+ if _ , ok := stack [i ].(* ast.CallExpr ); ok {
156
+ ncalls ++
163
157
}
164
-
165
158
}
166
- return nil , false
159
+ return nil , 0
167
160
}
168
161
169
162
// rootIdent finds the root identifier x in a chain of selections x.y.z, or nil if not found.
0 commit comments