Skip to content

Commit

Permalink
internal/lsp/analysis/stubmethods: recognize *ast.CallExpr
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
marwan-at-work authored and findleyr committed May 17, 2022
1 parent facb0d3 commit 13bcb69
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 4 deletions.
55 changes: 53 additions & 2 deletions internal/lsp/analysis/stubmethods/stubmethods.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,59 @@ func GetStubInfo(ti *types.Info, path []ast.Node, pos token.Pos) *StubInfo {
return si
case *ast.AssignStmt:
return fromAssignStmt(ti, n, pos)
case *ast.CallExpr:
// Note that some call expressions don't carry the interface type
// because they don't point to a function or method declaration elsewhere.
// For eaxmple, "var Interface = (*Concrete)(nil)". In that case, continue
// this loop to encounter other possibilities such as *ast.ValueSpec or others.
si := fromCallExpr(ti, pos, n)
if si != nil {
return si
}
}
}
return nil
}

// fromCallExpr tries to find an *ast.CallExpr's function declaration and
// analyzes a function call's signature against the passed in parameter to deduce
// the concrete and interface types.
func fromCallExpr(ti *types.Info, pos token.Pos, ce *ast.CallExpr) *StubInfo {
paramIdx := -1
for i, p := range ce.Args {
if pos >= p.Pos() && pos <= p.End() {
paramIdx = i
break
}
}
if paramIdx == -1 {
return nil
}
p := ce.Args[paramIdx]
concObj, pointer := concreteType(p, ti)
if concObj == nil || concObj.Obj().Pkg() == nil {
return nil
}
tv, ok := ti.Types[ce.Fun]
if !ok {
return nil
}
sig, ok := tv.Type.(*types.Signature)
if !ok {
return nil
}
sigVar := sig.Params().At(paramIdx)
iface := ifaceObjFromType(sigVar.Type())
if iface == nil {
return nil
}
return &StubInfo{
Concrete: concObj,
Pointer: pointer,
Interface: iface,
}
}

// fromReturnStmt analyzes a "return" statement to extract
// a concrete type that is trying to be returned as an interface type.
//
Expand Down Expand Up @@ -290,8 +338,11 @@ func ifaceType(n ast.Expr, ti *types.Info) types.Object {
if !ok {
return nil
}
typ := tv.Type
named, ok := typ.(*types.Named)
return ifaceObjFromType(tv.Type)
}

func ifaceObjFromType(t types.Type) types.Object {
named, ok := t.(*types.Named)
if !ok {
return nil
}
Expand Down
13 changes: 13 additions & 0 deletions internal/lsp/testdata/stub/stub_call_expr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package stub

func main() {
check(&callExpr{}) //@suggestedfix("&", "refactor.rewrite")
}

func check(err error) {
if err != nil {
panic(err)
}
}

type callExpr struct{}
20 changes: 20 additions & 0 deletions internal/lsp/testdata/stub/stub_call_expr.go.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- suggestedfix_stub_call_expr_4_8 --
package stub

func main() {
check(&callExpr{}) //@suggestedfix("&", "refactor.rewrite")
}

func check(err error) {
if err != nil {
panic(err)
}
}

type callExpr struct{}

// Error implements error
func (*callExpr) Error() string {
panic("unimplemented")
}

2 changes: 1 addition & 1 deletion internal/lsp/testdata/summary.txt.golden
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ FoldingRangesCount = 2
FormatCount = 6
ImportCount = 8
SemanticTokenCount = 3
SuggestedFixCount = 62
SuggestedFixCount = 63
FunctionExtractionCount = 25
MethodExtractionCount = 6
DefinitionsCount = 95
Expand Down
2 changes: 1 addition & 1 deletion internal/lsp/testdata/summary_go1.18.txt.golden
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ FoldingRangesCount = 2
FormatCount = 6
ImportCount = 8
SemanticTokenCount = 3
SuggestedFixCount = 63
SuggestedFixCount = 64
FunctionExtractionCount = 25
MethodExtractionCount = 6
DefinitionsCount = 108
Expand Down

0 comments on commit 13bcb69

Please sign in to comment.