mirror of https://github.com/golang/go.git
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 <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Suzy Mueller <suzmue@golang.org> Run-TryBot: Suzy Mueller <suzmue@golang.org>
This commit is contained in:
parent
facb0d30e9
commit
13bcb69cfa
|
|
@ -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.
|
||||
//
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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{}
|
||||
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ FoldingRangesCount = 2
|
|||
FormatCount = 6
|
||||
ImportCount = 8
|
||||
SemanticTokenCount = 3
|
||||
SuggestedFixCount = 62
|
||||
SuggestedFixCount = 63
|
||||
FunctionExtractionCount = 25
|
||||
MethodExtractionCount = 6
|
||||
DefinitionsCount = 95
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ FoldingRangesCount = 2
|
|||
FormatCount = 6
|
||||
ImportCount = 8
|
||||
SemanticTokenCount = 3
|
||||
SuggestedFixCount = 63
|
||||
SuggestedFixCount = 64
|
||||
FunctionExtractionCount = 25
|
||||
MethodExtractionCount = 6
|
||||
DefinitionsCount = 108
|
||||
|
|
|
|||
Loading…
Reference in New Issue