...

Source file src/golang.org/x/tools/go/types/typeutil/callee.go

Documentation: golang.org/x/tools/go/types/typeutil

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     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  // Callee returns the named target of a function call, if any:
    16  // a function, method, builtin, or variable.
    17  //
    18  // Functions and methods may potentially have type parameters.
    19  func Callee(info *types.Info, call *ast.CallExpr) types.Object {
    20  	fun := astutil.Unparen(call.Fun)
    21  
    22  	// Look through type instantiation if necessary.
    23  	isInstance := false
    24  	switch fun.(type) {
    25  	case *ast.IndexExpr, *typeparams.IndexListExpr:
    26  		// When extracting the callee from an *IndexExpr, we need to check that
    27  		// it is a *types.Func and not a *types.Var.
    28  		// Example: Don't match a slice m within the expression `m[0]()`.
    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] // type, var, builtin, or declared func
    37  	case *ast.SelectorExpr:
    38  		if sel, ok := info.Selections[fun]; ok {
    39  			obj = sel.Obj() // method or field
    40  		} else {
    41  			obj = info.Uses[fun.Sel] // qualified identifier?
    42  		}
    43  	}
    44  	if _, ok := obj.(*types.TypeName); ok {
    45  		return nil // T(x) is a conversion, not a call
    46  	}
    47  	// A Func is required to match instantiations.
    48  	if _, ok := obj.(*types.Func); isInstance && !ok {
    49  		return nil // Was not a Func.
    50  	}
    51  	return obj
    52  }
    53  
    54  // StaticCallee returns the target (function or method) of a static function
    55  // call, if any. It returns nil for calls to builtins.
    56  //
    57  // Note: for calls of instantiated functions and methods, StaticCallee returns
    58  // the corresponding generic function or method on the generic type.
    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