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.
This commit is contained in:
Grant Murphy 2016-11-04 11:20:28 -07:00
parent 9e2abd500f
commit c4057545ae

View file

@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"go/types"
"reflect" "reflect"
"regexp" "regexp"
"strconv" "strconv"
@ -46,6 +47,32 @@ func MatchCall(n ast.Node, r *regexp.Regexp) *ast.CallExpr {
return nil 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. // MatchCompLit will match an ast.CompositeLit if its string value obays the given regex.
func MatchCompLit(n ast.Node, r *regexp.Regexp) *ast.CompositeLit { func MatchCompLit(n ast.Node, r *regexp.Regexp) *ast.CompositeLit {
t := reflect.TypeOf(&ast.CompositeLit{}) t := reflect.TypeOf(&ast.CompositeLit{})