X-Git-Url: https://git.josue.xyz/?p=dotfiles%2F.git;a=blobdiff_plain;f=.config%2Fcoc%2Fextensions%2Fcoc-go-data%2Ftools%2Fpkg%2Fmod%2Fgolang.org%2Fx%2Ftools%40v0.1.1-0.20210319172145-bda8f5cee399%2Fcmd%2Fguru%2Fcallstack.go;fp=.config%2Fcoc%2Fextensions%2Fcoc-go-data%2Ftools%2Fpkg%2Fmod%2Fgolang.org%2Fx%2Ftools%40v0.1.1-0.20210319172145-bda8f5cee399%2Fcmd%2Fguru%2Fcallstack.go;h=10939ddfb8479dafcbd0e48cff9ecb1d68332eb6;hp=0000000000000000000000000000000000000000;hb=3c06164f15bd10aed7d66b6314764a2961a14762;hpb=0e9c3ceb40901f4d44981c1376cb9e23a248e006 diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/cmd/guru/callstack.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/cmd/guru/callstack.go new file mode 100644 index 00000000..10939ddf --- /dev/null +++ b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/cmd/guru/callstack.go @@ -0,0 +1,141 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "go/token" + + "golang.org/x/tools/cmd/guru/serial" + "golang.org/x/tools/go/callgraph" + "golang.org/x/tools/go/callgraph/static" + "golang.org/x/tools/go/loader" + "golang.org/x/tools/go/ssa" + "golang.org/x/tools/go/ssa/ssautil" +) + +// The callstack function displays an arbitrary path from a root of the callgraph +// to the function at the current position. +// +// The information may be misleading in a context-insensitive +// analysis. e.g. the call path X->Y->Z might be infeasible if Y never +// calls Z when it is called from X. TODO(adonovan): think about UI. +// +// TODO(adonovan): permit user to specify a starting point other than +// the analysis root. +// +func callstack(q *Query) error { + fset := token.NewFileSet() + lconf := loader.Config{Fset: fset, Build: q.Build} + + if err := setPTAScope(&lconf, q.Scope); err != nil { + return err + } + + // Load/parse/type-check the program. + lprog, err := loadWithSoftErrors(&lconf) + if err != nil { + return err + } + + qpos, err := parseQueryPos(lprog, q.Pos, false) + if err != nil { + return err + } + + prog := ssautil.CreateProgram(lprog, 0) + + ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection) + if err != nil { + return err + } + + pkg := prog.Package(qpos.info.Pkg) + if pkg == nil { + return fmt.Errorf("no SSA package") + } + + if !ssa.HasEnclosingFunction(pkg, qpos.path) { + return fmt.Errorf("this position is not inside a function") + } + + // Defer SSA construction till after errors are reported. + prog.Build() + + target := ssa.EnclosingFunction(pkg, qpos.path) + if target == nil { + return fmt.Errorf("no SSA function built for this location (dead code?)") + } + + var callpath []*callgraph.Edge + isEnd := func(n *callgraph.Node) bool { return n.Func == target } + + // First, build a callgraph containing only static call edges, + // and search for an arbitrary path from a root to the target function. + // This is quick, and the user wants a static path if one exists. + cg := static.CallGraph(prog) + cg.DeleteSyntheticNodes() + for _, ep := range entryPoints(ptaConfig.Mains) { + callpath = callgraph.PathSearch(cg.CreateNode(ep), isEnd) + if callpath != nil { + break + } + } + + // No fully static path found. + // Run the pointer analysis and build a complete call graph. + if callpath == nil { + ptaConfig.BuildCallGraph = true + cg := ptrAnalysis(ptaConfig).CallGraph + cg.DeleteSyntheticNodes() + callpath = callgraph.PathSearch(cg.Root, isEnd) + if callpath != nil { + callpath = callpath[1:] // remove synthetic edge from + } + } + + q.Output(fset, &callstackResult{ + qpos: qpos, + target: target, + callpath: callpath, + }) + return nil +} + +type callstackResult struct { + qpos *queryPos + target *ssa.Function + callpath []*callgraph.Edge +} + +func (r *callstackResult) PrintPlain(printf printfFunc) { + if r.callpath != nil { + printf(r.qpos, "Found a call path from root to %s", r.target) + printf(r.target, "%s", r.target) + for i := len(r.callpath) - 1; i >= 0; i-- { + edge := r.callpath[i] + printf(edge, "%s from %s", edge.Description(), edge.Caller.Func) + } + } else { + printf(r.target, "%s is unreachable in this analysis scope", r.target) + } +} + +func (r *callstackResult) JSON(fset *token.FileSet) []byte { + var callers []serial.Caller + for i := len(r.callpath) - 1; i >= 0; i-- { // (innermost first) + edge := r.callpath[i] + callers = append(callers, serial.Caller{ + Pos: fset.Position(edge.Pos()).String(), + Caller: edge.Caller.Func.String(), + Desc: edge.Description(), + }) + } + return toJSON(&serial.CallStack{ + Pos: fset.Position(r.target.Pos()).String(), + Target: r.target.String(), + Callers: callers, + }) +}