本文整理汇总了Golang中golang.org/x/tools/go/callgraph.Graph.DeleteSyntheticNodes方法的典型用法代码示例。如果您正苦于以下问题:Golang Graph.DeleteSyntheticNodes方法的具体用法?Golang Graph.DeleteSyntheticNodes怎么用?Golang Graph.DeleteSyntheticNodes使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类golang.org/x/tools/go/callgraph.Graph
的用法示例。
在下文中一共展示了Graph.DeleteSyntheticNodes方法的5个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: FindNonConstCalls
// FindNonConstCalls returns the set of callsites of the given set of methods
// for which the "query" parameter is not a compile-time constant.
func FindNonConstCalls(cg *callgraph.Graph, qms []*QueryMethod) []ssa.CallInstruction {
cg.DeleteSyntheticNodes()
// package database/sql has a couple helper functions which are thin
// wrappers around other sensitive functions. Instead of handling the
// general case by tracing down callsites of wrapper functions
// recursively, let's just whitelist the functions we're already
// tracking, since it happens to be good enough for our use case.
okFuncs := make(map[*ssa.Function]struct{}, len(qms))
for _, m := range qms {
okFuncs[m.SSA] = struct{}{}
}
bad := make([]ssa.CallInstruction, 0)
for _, m := range qms {
node := cg.CreateNode(m.SSA)
for _, edge := range node.In {
if _, ok := okFuncs[edge.Site.Parent()]; ok {
continue
}
cc := edge.Site.Common()
args := cc.Args
// The first parameter is occasionally the receiver.
if len(args) == m.ArgCount+1 {
args = args[1:]
} else if len(args) != m.ArgCount {
panic("arg count mismatch")
}
v := args[m.Param]
if _, ok := v.(*ssa.Const); !ok {
bad = append(bad, edge.Site)
}
}
}
return bad
}
示例2: doCallgraph
func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []string) error {
conf := loader.Config{
Build: ctxt,
SourceImports: true,
}
if len(args) == 0 {
fmt.Fprintln(os.Stderr, Usage)
return nil
}
// Use the initial packages from the command line.
args, err := conf.FromArgs(args, tests)
if err != nil {
return err
}
// Load, parse and type-check the whole program.
iprog, err := conf.Load()
if err != nil {
return err
}
// Create and build SSA-form program representation.
prog := ssa.Create(iprog, 0)
prog.BuildAll()
// -- call graph construction ------------------------------------------
var cg *callgraph.Graph
switch algo {
case "static":
cg = static.CallGraph(prog)
case "cha":
cg = cha.CallGraph(prog)
case "pta":
main, err := mainPackage(prog, tests)
if err != nil {
return err
}
config := &pointer.Config{
Mains: []*ssa.Package{main},
BuildCallGraph: true,
}
ptares, err := pointer.Analyze(config)
if err != nil {
return err // internal error in pointer analysis
}
cg = ptares.CallGraph
case "rta":
main, err := mainPackage(prog, tests)
if err != nil {
return err
}
roots := []*ssa.Function{
main.Func("init"),
main.Func("main"),
}
rtares := rta.Analyze(roots, true)
cg = rtares.CallGraph
// NB: RTA gives us Reachable and RuntimeTypes too.
default:
return fmt.Errorf("unknown algorithm: %s", algo)
}
cg.DeleteSyntheticNodes()
// -- output------------------------------------------------------------
var before, after string
// Pre-canned formats.
switch format {
case "digraph":
format = `{{printf "%q %q" .Caller .Callee}}`
case "graphviz":
before = "digraph callgraph {\n"
after = "}\n"
format = ` {{printf "%q" .Caller}} -> {{printf "%q" .Callee}}"`
}
tmpl, err := template.New("-format").Parse(format)
if err != nil {
return fmt.Errorf("invalid -format template: %v", err)
}
// Allocate these once, outside the traversal.
var buf bytes.Buffer
data := Edge{fset: prog.Fset}
fmt.Fprint(stdout, before)
if err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error {
data.position.Offset = -1
//.........这里部分代码省略.........
示例3: doCallgraph
// doCallgraph computes the CALLEES and CALLERS relations.
func (a *analysis) doCallgraph(cg *callgraph.Graph) {
log.Print("Deleting synthetic nodes...")
// TODO(adonovan): opt: DeleteSyntheticNodes is asymptotically
// inefficient and can be (unpredictably) slow.
cg.DeleteSyntheticNodes()
log.Print("Synthetic nodes deleted")
// Populate nodes of package call graphs (PCGs).
for _, n := range cg.Nodes {
a.pcgAddNode(n.Func)
}
// Within each PCG, sort funcs by name.
for _, pcg := range a.pcgs {
pcg.sortNodes()
}
calledFuncs := make(map[ssa.CallInstruction]map[*ssa.Function]bool)
callingSites := make(map[*ssa.Function]map[ssa.CallInstruction]bool)
for _, n := range cg.Nodes {
for _, e := range n.Out {
if e.Site == nil {
continue // a call from a synthetic node such as <root>
}
// Add (site pos, callee) to calledFuncs.
// (Dynamic calls only.)
callee := e.Callee.Func
a.pcgAddEdge(n.Func, callee)
if callee.Synthetic != "" {
continue // call of a package initializer
}
if e.Site.Common().StaticCallee() == nil {
// dynamic call
// (CALLEES information for static calls
// is computed using SSA information.)
lparen := e.Site.Common().Pos()
if lparen != token.NoPos {
fns := calledFuncs[e.Site]
if fns == nil {
fns = make(map[*ssa.Function]bool)
calledFuncs[e.Site] = fns
}
fns[callee] = true
}
}
// Add (callee, site) to callingSites.
fns := callingSites[callee]
if fns == nil {
fns = make(map[ssa.CallInstruction]bool)
callingSites[callee] = fns
}
fns[e.Site] = true
}
}
// CALLEES.
log.Print("Callees...")
for site, fns := range calledFuncs {
var funcs funcsByPos
for fn := range fns {
funcs = append(funcs, fn)
}
sort.Sort(funcs)
a.addCallees(site, funcs)
}
// CALLERS
log.Print("Callers...")
for callee, sites := range callingSites {
pos := funcToken(callee)
if pos == token.NoPos {
log.Printf("CALLERS: skipping %s: no pos", callee)
continue
}
var this *types.Package // for relativizing names
if callee.Pkg != nil {
this = callee.Pkg.Pkg
}
// Compute sites grouped by parent, with text and URLs.
sitesByParent := make(map[*ssa.Function]sitesByPos)
for site := range sites {
fn := site.Parent()
sitesByParent[fn] = append(sitesByParent[fn], site)
}
var funcs funcsByPos
for fn := range sitesByParent {
funcs = append(funcs, fn)
}
sort.Sort(funcs)
v := callersJSON{
Callee: callee.String(),
//.........这里部分代码省略.........
示例4: doCallgraph
func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []string) error {
conf := loader.Config{
Build: ctxt,
SourceImports: true,
}
if len(args) == 0 {
fmt.Fprintln(os.Stderr, Usage)
return nil
}
// Use the initial packages from the command line.
args, err := conf.FromArgs(args, tests)
if err != nil {
return err
}
// Load, parse and type-check the whole program.
iprog, err := conf.Load()
if err != nil {
return err
}
// Create and build SSA-form program representation.
prog := ssa.Create(iprog, 0)
prog.BuildAll()
// Determine the main package.
// TODO(adonovan): allow independent control over tests, mains
// and libraries.
// TODO(adonovan): put this logic in a library; we keep reinventing it.
var main *ssa.Package
pkgs := prog.AllPackages()
if tests {
// If -test, use all packages' tests.
if len(pkgs) > 0 {
main = prog.CreateTestMainPackage(pkgs...)
}
if main == nil {
return fmt.Errorf("no tests")
}
} else {
// Otherwise, use main.main.
for _, pkg := range pkgs {
if pkg.Object.Name() == "main" {
main = pkg
if main.Func("main") == nil {
return fmt.Errorf("no func main() in main package")
}
break
}
}
if main == nil {
return fmt.Errorf("no main package")
}
}
// Invariant: main package has a main() function.
// -- call graph construction ------------------------------------------
var cg *callgraph.Graph
switch algo {
case "pta":
config := &pointer.Config{
Mains: []*ssa.Package{main},
BuildCallGraph: true,
}
ptares, err := pointer.Analyze(config)
if err != nil {
return err // internal error in pointer analysis
}
cg = ptares.CallGraph
case "rta":
roots := []*ssa.Function{
main.Func("init"),
main.Func("main"),
}
rtares := rta.Analyze(roots, true)
cg = rtares.CallGraph
// NB: RTA gives us Reachable and RuntimeTypes too.
default:
return fmt.Errorf("unknown algorithm: %s", algo)
}
cg.DeleteSyntheticNodes()
// -- output------------------------------------------------------------
var before, after string
// Pre-canned formats.
switch format {
case "digraph":
format = `{{printf "%q %q" .Caller .Callee}}`
//.........这里部分代码省略.........
示例5: doCallgraph
func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []string) error {
conf := loader.Config{Build: ctxt}
if len(args) == 0 {
fmt.Fprintln(os.Stderr, Usage)
return nil
}
if *fileFlag == "" || *lineFlag == -1 {
fmt.Fprintln(os.Stderr, "Need input file and line")
return nil
}
// Use the initial packages from the command line.
args, err := conf.FromArgs(args, tests)
if err != nil {
return err
}
// Load, parse and type-check the whole program.
iprog, err := conf.Load()
if err != nil {
return err
}
// Create and build SSA-form program representation.
prog := ssautil.CreateProgram(iprog, 0)
prog.Build()
// -- call graph construction ------------------------------------------
var cg *callgraph.Graph
switch algo {
case "static":
cg = static.CallGraph(prog)
case "cha":
cg = cha.CallGraph(prog)
case "pta":
// Set up points-to analysis log file.
var ptalog io.Writer
if *ptalogFlag != "" {
if f, err := os.Create(*ptalogFlag); err != nil {
log.Fatalf("Failed to create PTA log file: %s", err)
} else {
buf := bufio.NewWriter(f)
ptalog = buf
defer func() {
if err := buf.Flush(); err != nil {
log.Printf("flush: %s", err)
}
if err := f.Close(); err != nil {
log.Printf("close: %s", err)
}
}()
}
}
main, err := mainPackage(prog, tests)
if err != nil {
return err
}
config := &pointer.Config{
Mains: []*ssa.Package{main},
BuildCallGraph: true,
Log: ptalog,
}
ptares, err := pointer.Analyze(config)
if err != nil {
return err // internal error in pointer analysis
}
cg = ptares.CallGraph
case "rta":
main, err := mainPackage(prog, tests)
if err != nil {
return err
}
roots := []*ssa.Function{
main.Func("init"),
main.Func("main"),
}
rtares := rta.Analyze(roots, true)
cg = rtares.CallGraph
// NB: RTA gives us Reachable and RuntimeTypes too.
default:
return fmt.Errorf("unknown algorithm: %s", algo)
}
cg.DeleteSyntheticNodes()
// -- output------------------------------------------------------------
file := *fileFlag
line := *lineFlag
depth := *depthFlag
//.........这里部分代码省略.........