Skip to content

Commit 62d837c

Browse files
committed
go/analysis/passes/httpresponse: minor clarification
See discussion in https://go-review.googlesource.com/c/tools/+/405314. Change-Id: Ic5f5182a1cc55b4a2c40f43ebb2250c508388c75 Reviewed-on: https://go-review.googlesource.com/c/tools/+/405537 Reviewed-by: Tim King <[email protected]> Reviewed-by: Nooras Saba‎ <[email protected]> Run-TryBot: Alan Donovan <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 6eb3de2 commit 62d837c

File tree

1 file changed

+17
-24
lines changed

1 file changed

+17
-24
lines changed

go/analysis/passes/httpresponse/httpresponse.go

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,16 @@ func run(pass *analysis.Pass) (interface{}, error) {
6262

6363
// Find the innermost containing block, and get the list
6464
// 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.
7068
return true
7169
}
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
7475
}
7576

7677
asg, ok := stmts[0].(*ast.AssignStmt)
@@ -136,34 +137,26 @@ func isHTTPFuncOrMethodOnClient(info *types.Info, expr *ast.CallExpr) bool {
136137
return ok && isNamedType(ptr.Elem(), "net/http", "Client") // method on *http.Client.
137138
}
138139

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
145145
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-
151146
if b, ok := stack[i].(*ast.BlockStmt); ok {
152147
for j, v := range b.List {
153148
if v == stack[i+1] {
154-
return b.List[j:], false
149+
return b.List[j:], ncalls
155150
}
156151
}
157152
break
158153
}
159154

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++
163157
}
164-
165158
}
166-
return nil, false
159+
return nil, 0
167160
}
168161

169162
// rootIdent finds the root identifier x in a chain of selections x.y.z, or nil if not found.

0 commit comments

Comments
 (0)