github.com/jujuyuki/gospal@v1.0.1-0.20210215170718-af79fae13b20/ssa/find.go (about) 1 package ssa 2 3 import ( 4 "regexp" 5 "strings" 6 7 "golang.org/x/tools/go/ssa" 8 ) 9 10 // FindFunc parses path (e.g. "github.com/nickng/gospal/ssa".MainPkgs) and 11 // returns Function body in SSA IR. 12 func (info *Info) FindFunc(path string) (*ssa.Function, error) { 13 pkgPath, fnName := parseFuncPath(path) 14 graph, err := info.BuildCallGraph("rta", false) 15 if err != nil { 16 return nil, err 17 } 18 funcs, err := graph.UsedFunctions() 19 if err != nil { 20 return nil, err 21 } 22 for _, f := range funcs { 23 if f.Pkg.Pkg.Path() == pkgPath && f.Name() == fnName { 24 return f, nil 25 } 26 } 27 return nil, nil 28 } 29 30 // parseFuncPath splits path to package and function segments. 31 // Does not handle complex functions with receivers. 32 func parseFuncPath(path string) (pkgPath, fnName string) { 33 if len(path) < 1 { 34 return "", "" 35 } 36 switch path[0] { 37 case '(': 38 regex := regexp.MustCompile(`\((?P<pkg>[^)]+)\).(?P<fn>.+)`) 39 submatches := regex.FindStringSubmatch(path) 40 if len(submatches) >= 3 { 41 return submatches[1], submatches[2] 42 } 43 case '"': 44 regex := regexp.MustCompile(`"(?P<pkg>[^)]+)".(?P<fn>.+)`) 45 submatches := regex.FindStringSubmatch(path) 46 if len(submatches) >= 3 { 47 return submatches[1], submatches[2] 48 } 49 default: 50 parts := strings.Split(path, ".") 51 if len(parts) >= 2 { 52 return parts[0], parts[1] 53 } 54 } 55 return "", path 56 }