Skip to content

Commit 13bcb69

Browse files
marwan-at-workfindleyr
authored andcommitted
internal/lsp/analysis/stubmethods: recognize *ast.CallExpr
This change makes it so that the stub methods analysis can recognize errors happening to method and function call expressions that are being passed a concrete type to an interface parameter. This way, a method stub CodeAction will appear at the call site. Updates golang/go#37537 Change-Id: I886d53f06a85b9e5160d882aa742bb2b7fcea139 Reviewed-on: https://go-review.googlesource.com/c/tools/+/404655 gopls-CI: kokoro <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Robert Findley <[email protected]> Reviewed-by: Suzy Mueller <[email protected]> Run-TryBot: Suzy Mueller <[email protected]>
1 parent facb0d3 commit 13bcb69

File tree

5 files changed

+88
-4
lines changed

5 files changed

+88
-4
lines changed

internal/lsp/analysis/stubmethods/stubmethods.go

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,59 @@ func GetStubInfo(ti *types.Info, path []ast.Node, pos token.Pos) *StubInfo {
105105
return si
106106
case *ast.AssignStmt:
107107
return fromAssignStmt(ti, n, pos)
108+
case *ast.CallExpr:
109+
// Note that some call expressions don't carry the interface type
110+
// because they don't point to a function or method declaration elsewhere.
111+
// For eaxmple, "var Interface = (*Concrete)(nil)". In that case, continue
112+
// this loop to encounter other possibilities such as *ast.ValueSpec or others.
113+
si := fromCallExpr(ti, pos, n)
114+
if si != nil {
115+
return si
116+
}
108117
}
109118
}
110119
return nil
111120
}
112121

122+
// fromCallExpr tries to find an *ast.CallExpr's function declaration and
123+
// analyzes a function call's signature against the passed in parameter to deduce
124+
// the concrete and interface types.
125+
func fromCallExpr(ti *types.Info, pos token.Pos, ce *ast.CallExpr) *StubInfo {
126+
paramIdx := -1
127+
for i, p := range ce.Args {
128+
if pos >= p.Pos() && pos <= p.End() {
129+
paramIdx = i
130+
break
131+
}
132+
}
133+
if paramIdx == -1 {
134+
return nil
135+
}
136+
p := ce.Args[paramIdx]
137+
concObj, pointer := concreteType(p, ti)
138+
if concObj == nil || concObj.Obj().Pkg() == nil {
139+
return nil
140+
}
141+
tv, ok := ti.Types[ce.Fun]
142+
if !ok {
143+
return nil
144+
}
145+
sig, ok := tv.Type.(*types.Signature)
146+
if !ok {
147+
return nil
148+
}
149+
sigVar := sig.Params().At(paramIdx)
150+
iface := ifaceObjFromType(sigVar.Type())
151+
if iface == nil {
152+
return nil
153+
}
154+
return &StubInfo{
155+
Concrete: concObj,
156+
Pointer: pointer,
157+
Interface: iface,
158+
}
159+
}
160+
113161
// fromReturnStmt analyzes a "return" statement to extract
114162
// a concrete type that is trying to be returned as an interface type.
115163
//
@@ -290,8 +338,11 @@ func ifaceType(n ast.Expr, ti *types.Info) types.Object {
290338
if !ok {
291339
return nil
292340
}
293-
typ := tv.Type
294-
named, ok := typ.(*types.Named)
341+
return ifaceObjFromType(tv.Type)
342+
}
343+
344+
func ifaceObjFromType(t types.Type) types.Object {
345+
named, ok := t.(*types.Named)
295346
if !ok {
296347
return nil
297348
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package stub
2+
3+
func main() {
4+
check(&callExpr{}) //@suggestedfix("&", "refactor.rewrite")
5+
}
6+
7+
func check(err error) {
8+
if err != nil {
9+
panic(err)
10+
}
11+
}
12+
13+
type callExpr struct{}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- suggestedfix_stub_call_expr_4_8 --
2+
package stub
3+
4+
func main() {
5+
check(&callExpr{}) //@suggestedfix("&", "refactor.rewrite")
6+
}
7+
8+
func check(err error) {
9+
if err != nil {
10+
panic(err)
11+
}
12+
}
13+
14+
type callExpr struct{}
15+
16+
// Error implements error
17+
func (*callExpr) Error() string {
18+
panic("unimplemented")
19+
}
20+

internal/lsp/testdata/summary.txt.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ FoldingRangesCount = 2
1313
FormatCount = 6
1414
ImportCount = 8
1515
SemanticTokenCount = 3
16-
SuggestedFixCount = 62
16+
SuggestedFixCount = 63
1717
FunctionExtractionCount = 25
1818
MethodExtractionCount = 6
1919
DefinitionsCount = 95

internal/lsp/testdata/summary_go1.18.txt.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ FoldingRangesCount = 2
1313
FormatCount = 6
1414
ImportCount = 8
1515
SemanticTokenCount = 3
16-
SuggestedFixCount = 63
16+
SuggestedFixCount = 64
1717
FunctionExtractionCount = 25
1818
MethodExtractionCount = 6
1919
DefinitionsCount = 108

0 commit comments

Comments
 (0)