From c4057545ae18090bda5686796135f9740e8a37a2 Mon Sep 17 00:00:00 2001 From: Grant Murphy Date: Fri, 4 Nov 2016 11:20:28 -0700 Subject: [PATCH] Add MatchCall helper that utilizes type checker This introduces a helper function that will significantly reduce the number of false positives that occur due to the use of regexp based call matching. It resolves the object related to a CallExpr and checks that against the supplied package and identifier name. If both of these match the returned value is the CallExpr and Object. --- core/helpers.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/core/helpers.go b/core/helpers.go index f5bcd44..b7c6743 100644 --- a/core/helpers.go +++ b/core/helpers.go @@ -18,6 +18,7 @@ import ( "fmt" "go/ast" "go/token" + "go/types" "reflect" "regexp" "strconv" @@ -46,6 +47,32 @@ func MatchCall(n ast.Node, r *regexp.Regexp) *ast.CallExpr { return nil } +// MatchCallByObject ses the type checker to resolve the associated object with a +// particular *ast.CallExpr. This object is used to determine if the +// package and identifier name matches the passed in parameters. +// +// Usage: +// node, obj := MatchCall(n, ctx, "math/rand", "Read") +// +func MatchCallByObject(n ast.Node, c *Context, pkg, name string) (*ast.CallExpr, types.Object) { + var obj types.Object + switch node := n.(type) { + case *ast.CallExpr: + switch fn := node.Fun.(type) { + case *ast.Ident: + obj = c.Info.Uses[fn] + case *ast.SelectorExpr: + obj = c.Info.Uses[fn.Sel] + default: + obj = nil + } + if obj != nil && obj.Pkg().Path() == pkg && obj.Name() == name { + return node, obj + } + } + return nil, nil +} + // MatchCompLit will match an ast.CompositeLit if its string value obays the given regex. func MatchCompLit(n ast.Node, r *regexp.Regexp) *ast.CompositeLit { t := reflect.TypeOf(&ast.CompositeLit{})