47 lines
1.3 KiB
Go
47 lines
1.3 KiB
Go
// Copyright 2018 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package typeutil
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/types"
|
|
|
|
"golang.org/x/tools/go/ast/astutil"
|
|
)
|
|
|
|
// Callee returns the named target of a function call, if any:
|
|
// a function, method, builtin, or variable.
|
|
func Callee(info *types.Info, call *ast.CallExpr) types.Object {
|
|
var obj types.Object
|
|
switch fun := astutil.Unparen(call.Fun).(type) {
|
|
case *ast.Ident:
|
|
obj = info.Uses[fun] // type, var, builtin, or declared func
|
|
case *ast.SelectorExpr:
|
|
if sel, ok := info.Selections[fun]; ok {
|
|
obj = sel.Obj() // method or field
|
|
} else {
|
|
obj = info.Uses[fun.Sel] // qualified identifier?
|
|
}
|
|
}
|
|
if _, ok := obj.(*types.TypeName); ok {
|
|
return nil // T(x) is a conversion, not a call
|
|
}
|
|
return obj
|
|
}
|
|
|
|
// StaticCallee returns the target (function or method) of a static
|
|
// function call, if any. It returns nil for calls to builtins.
|
|
func StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func {
|
|
if f, ok := Callee(info, call).(*types.Func); ok && !interfaceMethod(f) {
|
|
return f
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func interfaceMethod(f *types.Func) bool {
|
|
recv := f.Type().(*types.Signature).Recv()
|
|
return recv != nil && types.IsInterface(recv.Type())
|
|
}
|