Add generated file
This PR adds generated files under pkg/client and vendor folder.
This commit is contained in:
282
vendor/golang.org/x/tools/cmd/guru/what.go
generated
vendored
Normal file
282
vendor/golang.org/x/tools/cmd/guru/what.go
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
// 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/ast"
|
||||
"go/build"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/cmd/guru/serial"
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
)
|
||||
|
||||
// what reports all the information about the query selection that can be
|
||||
// obtained from parsing only its containing source file.
|
||||
// It is intended to be a very low-latency query callable from GUI
|
||||
// tools, e.g. to populate a menu of options of slower queries about
|
||||
// the selected location.
|
||||
//
|
||||
func what(q *Query) error {
|
||||
qpos, err := fastQueryPos(q.Build, q.Pos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// (ignore errors)
|
||||
srcdir, importPath, _ := guessImportPath(qpos.fset.File(qpos.start).Name(), q.Build)
|
||||
|
||||
// Determine which query modes are applicable to the selection.
|
||||
enable := map[string]bool{
|
||||
"describe": true, // any syntax; always enabled
|
||||
}
|
||||
|
||||
if qpos.end > qpos.start {
|
||||
enable["freevars"] = true // nonempty selection?
|
||||
}
|
||||
|
||||
for _, n := range qpos.path {
|
||||
switch n := n.(type) {
|
||||
case *ast.Ident:
|
||||
enable["definition"] = true
|
||||
enable["referrers"] = true
|
||||
enable["implements"] = true
|
||||
case *ast.CallExpr:
|
||||
enable["callees"] = true
|
||||
case *ast.FuncDecl:
|
||||
enable["callers"] = true
|
||||
enable["callstack"] = true
|
||||
case *ast.SendStmt:
|
||||
enable["peers"] = true
|
||||
case *ast.UnaryExpr:
|
||||
if n.Op == token.ARROW {
|
||||
enable["peers"] = true
|
||||
}
|
||||
}
|
||||
|
||||
// For implements, we approximate findInterestingNode.
|
||||
if _, ok := enable["implements"]; !ok {
|
||||
switch n.(type) {
|
||||
case *ast.ArrayType,
|
||||
*ast.StructType,
|
||||
*ast.FuncType,
|
||||
*ast.InterfaceType,
|
||||
*ast.MapType,
|
||||
*ast.ChanType:
|
||||
enable["implements"] = true
|
||||
}
|
||||
}
|
||||
|
||||
// For pointsto and whicherrs, we approximate findInterestingNode.
|
||||
if _, ok := enable["pointsto"]; !ok {
|
||||
switch n.(type) {
|
||||
case ast.Stmt,
|
||||
*ast.ArrayType,
|
||||
*ast.StructType,
|
||||
*ast.FuncType,
|
||||
*ast.InterfaceType,
|
||||
*ast.MapType,
|
||||
*ast.ChanType:
|
||||
// not an expression
|
||||
enable["pointsto"] = false
|
||||
enable["whicherrs"] = false
|
||||
|
||||
case ast.Expr, ast.Decl, *ast.ValueSpec:
|
||||
// an expression, maybe
|
||||
enable["pointsto"] = true
|
||||
enable["whicherrs"] = true
|
||||
|
||||
default:
|
||||
// Comment, Field, KeyValueExpr, etc: ascend.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have an exact selection, disable modes that need one.
|
||||
if !qpos.exact {
|
||||
enable["callees"] = false
|
||||
enable["pointsto"] = false
|
||||
enable["whicherrs"] = false
|
||||
enable["describe"] = false
|
||||
}
|
||||
|
||||
var modes []string
|
||||
for mode := range enable {
|
||||
modes = append(modes, mode)
|
||||
}
|
||||
sort.Strings(modes)
|
||||
|
||||
// Find the object referred to by the selection (if it's an
|
||||
// identifier) and report the position of each identifier
|
||||
// that refers to the same object.
|
||||
//
|
||||
// This may return spurious matches (e.g. struct fields) because
|
||||
// it uses the best-effort name resolution done by go/parser.
|
||||
var sameids []token.Pos
|
||||
var object string
|
||||
if id, ok := qpos.path[0].(*ast.Ident); ok {
|
||||
if id.Obj == nil {
|
||||
// An unresolved identifier is potentially a package name.
|
||||
// Resolve them with a simple importer (adds ~100µs).
|
||||
importer := func(imports map[string]*ast.Object, path string) (*ast.Object, error) {
|
||||
pkg, ok := imports[path]
|
||||
if !ok {
|
||||
pkg = &ast.Object{
|
||||
Kind: ast.Pkg,
|
||||
Name: filepath.Base(path), // a guess
|
||||
}
|
||||
imports[path] = pkg
|
||||
}
|
||||
return pkg, nil
|
||||
}
|
||||
f := qpos.path[len(qpos.path)-1].(*ast.File)
|
||||
ast.NewPackage(qpos.fset, map[string]*ast.File{"": f}, importer, nil)
|
||||
}
|
||||
|
||||
if id.Obj != nil {
|
||||
object = id.Obj.Name
|
||||
decl := qpos.path[len(qpos.path)-1]
|
||||
ast.Inspect(decl, func(n ast.Node) bool {
|
||||
if n, ok := n.(*ast.Ident); ok && n.Obj == id.Obj {
|
||||
sameids = append(sameids, n.Pos())
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
q.Output(qpos.fset, &whatResult{
|
||||
path: qpos.path,
|
||||
srcdir: srcdir,
|
||||
importPath: importPath,
|
||||
modes: modes,
|
||||
object: object,
|
||||
sameids: sameids,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// guessImportPath finds the package containing filename, and returns
|
||||
// its source directory (an element of $GOPATH) and its import path
|
||||
// relative to it.
|
||||
//
|
||||
// TODO(adonovan): what about _test.go files that are not part of the
|
||||
// package?
|
||||
//
|
||||
func guessImportPath(filename string, buildContext *build.Context) (srcdir, importPath string, err error) {
|
||||
absFile, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("can't form absolute path of %s: %v", filename, err)
|
||||
}
|
||||
|
||||
absFileDir := filepath.Dir(absFile)
|
||||
resolvedAbsFileDir, err := filepath.EvalSymlinks(absFileDir)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("can't evaluate symlinks of %s: %v", absFileDir, err)
|
||||
}
|
||||
|
||||
segmentedAbsFileDir := segments(resolvedAbsFileDir)
|
||||
// Find the innermost directory in $GOPATH that encloses filename.
|
||||
minD := 1024
|
||||
for _, gopathDir := range buildContext.SrcDirs() {
|
||||
absDir, err := filepath.Abs(gopathDir)
|
||||
if err != nil {
|
||||
continue // e.g. non-existent dir on $GOPATH
|
||||
}
|
||||
resolvedAbsDir, err := filepath.EvalSymlinks(absDir)
|
||||
if err != nil {
|
||||
continue // e.g. non-existent dir on $GOPATH
|
||||
}
|
||||
|
||||
d := prefixLen(segments(resolvedAbsDir), segmentedAbsFileDir)
|
||||
// If there are multiple matches,
|
||||
// prefer the innermost enclosing directory
|
||||
// (smallest d).
|
||||
if d >= 0 && d < minD {
|
||||
minD = d
|
||||
srcdir = gopathDir
|
||||
importPath = strings.Join(segmentedAbsFileDir[len(segmentedAbsFileDir)-minD:], string(os.PathSeparator))
|
||||
}
|
||||
}
|
||||
if srcdir == "" {
|
||||
return "", "", fmt.Errorf("directory %s is not beneath any of these GOROOT/GOPATH directories: %s",
|
||||
filepath.Dir(absFile), strings.Join(buildContext.SrcDirs(), ", "))
|
||||
}
|
||||
if importPath == "" {
|
||||
// This happens for e.g. $GOPATH/src/a.go, but
|
||||
// "" is not a valid path for (*go/build).Import.
|
||||
return "", "", fmt.Errorf("cannot load package in root of source directory %s", srcdir)
|
||||
}
|
||||
return srcdir, importPath, nil
|
||||
}
|
||||
|
||||
func segments(path string) []string {
|
||||
return strings.Split(path, string(os.PathSeparator))
|
||||
}
|
||||
|
||||
// prefixLen returns the length of the remainder of y if x is a prefix
|
||||
// of y, a negative number otherwise.
|
||||
func prefixLen(x, y []string) int {
|
||||
d := len(y) - len(x)
|
||||
if d >= 0 {
|
||||
for i := range x {
|
||||
if y[i] != x[i] {
|
||||
return -1 // not a prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
type whatResult struct {
|
||||
path []ast.Node
|
||||
modes []string
|
||||
srcdir string
|
||||
importPath string
|
||||
object string
|
||||
sameids []token.Pos
|
||||
}
|
||||
|
||||
func (r *whatResult) PrintPlain(printf printfFunc) {
|
||||
for _, n := range r.path {
|
||||
printf(n, "%s", astutil.NodeDescription(n))
|
||||
}
|
||||
printf(nil, "modes: %s", r.modes)
|
||||
printf(nil, "srcdir: %s", r.srcdir)
|
||||
printf(nil, "import path: %s", r.importPath)
|
||||
for _, pos := range r.sameids {
|
||||
printf(pos, "%s", r.object)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *whatResult) JSON(fset *token.FileSet) []byte {
|
||||
var enclosing []serial.SyntaxNode
|
||||
for _, n := range r.path {
|
||||
enclosing = append(enclosing, serial.SyntaxNode{
|
||||
Description: astutil.NodeDescription(n),
|
||||
Start: fset.Position(n.Pos()).Offset,
|
||||
End: fset.Position(n.End()).Offset,
|
||||
})
|
||||
}
|
||||
|
||||
var sameids []string
|
||||
for _, pos := range r.sameids {
|
||||
sameids = append(sameids, fset.Position(pos).String())
|
||||
}
|
||||
|
||||
return toJSON(&serial.What{
|
||||
Modes: r.modes,
|
||||
SrcDir: r.srcdir,
|
||||
ImportPath: r.importPath,
|
||||
Enclosing: enclosing,
|
||||
Object: r.object,
|
||||
SameIDs: sameids,
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user