...
1
2
3
4
5 package typeutil
6
7 import (
8 "go/ast"
9 "go/types"
10
11 "golang.org/x/tools/go/ast/astutil"
12 "golang.org/x/tools/internal/typeparams"
13 )
14
15
16
17
18
19 func Callee(info *types.Info, call *ast.CallExpr) types.Object {
20 fun := astutil.Unparen(call.Fun)
21
22
23 isInstance := false
24 switch fun.(type) {
25 case *ast.IndexExpr, *typeparams.IndexListExpr:
26
27
28
29 isInstance = true
30 fun, _, _, _ = typeparams.UnpackIndexExpr(fun)
31 }
32
33 var obj types.Object
34 switch fun := fun.(type) {
35 case *ast.Ident:
36 obj = info.Uses[fun]
37 case *ast.SelectorExpr:
38 if sel, ok := info.Selections[fun]; ok {
39 obj = sel.Obj()
40 } else {
41 obj = info.Uses[fun.Sel]
42 }
43 }
44 if _, ok := obj.(*types.TypeName); ok {
45 return nil
46 }
47
48 if _, ok := obj.(*types.Func); isInstance && !ok {
49 return nil
50 }
51 return obj
52 }
53
54
55
56
57
58
59 func StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func {
60 if f, ok := Callee(info, call).(*types.Func); ok && !interfaceMethod(f) {
61 return f
62 }
63 return nil
64 }
65
66 func interfaceMethod(f *types.Func) bool {
67 recv := f.Type().(*types.Signature).Recv()
68 return recv != nil && types.IsInterface(recv.Type())
69 }
70
View as plain text