2013-08-27 16:49:13 -06:00
|
|
|
// 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.
|
|
|
|
|
2015-12-29 11:06:30 -07:00
|
|
|
// +build go1.6
|
2016-01-06 12:56:13 -07:00
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
package oracle
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"go/ast"
|
2015-12-29 11:06:30 -07:00
|
|
|
exact "go/constant"
|
2013-08-27 15:58:26 -06:00
|
|
|
"go/token"
|
2015-12-29 11:06:30 -07:00
|
|
|
"go/types"
|
2014-07-11 03:50:09 -06:00
|
|
|
"log"
|
2013-09-03 13:29:02 -06:00
|
|
|
"os"
|
2013-08-27 15:58:26 -06:00
|
|
|
"strings"
|
|
|
|
|
2015-01-08 19:32:51 -07:00
|
|
|
"golang.org/x/tools/go/ast/astutil"
|
2014-11-09 14:50:40 -07:00
|
|
|
"golang.org/x/tools/go/loader"
|
|
|
|
"golang.org/x/tools/go/types/typeutil"
|
|
|
|
"golang.org/x/tools/oracle/serial"
|
2013-08-27 15:58:26 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
// describe describes the syntax node denoted by the query position,
|
|
|
|
// including:
|
|
|
|
// - its syntactic category
|
2013-12-13 08:04:55 -07:00
|
|
|
// - the definition of its referent (for identifiers) [now redundant]
|
2013-08-27 15:58:26 -06:00
|
|
|
// - its type and method set (for an expression or type expression)
|
2013-09-03 13:29:02 -06:00
|
|
|
//
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
func describe(q *Query) error {
|
|
|
|
lconf := loader.Config{Build: q.Build}
|
|
|
|
allowErrors(&lconf)
|
|
|
|
|
2015-12-02 15:19:53 -07:00
|
|
|
if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load/parse/type-check the program.
|
|
|
|
lprog, err := lconf.Load()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
q.Fset = lprog.Fset
|
|
|
|
|
|
|
|
qpos, err := parseQueryPos(lprog, q.Pos, true) // (need exact pos)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
if false { // debugging
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
fprintf(os.Stderr, lprog.Fset, qpos.path[0], "you selected: %s %s",
|
2013-12-13 08:04:55 -07:00
|
|
|
astutil.NodeDescription(qpos.path[0]), pathToString(qpos.path))
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
path, action := findInterestingNode(qpos.info, qpos.path)
|
2013-08-27 15:58:26 -06:00
|
|
|
switch action {
|
|
|
|
case actionExpr:
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
q.result, err = describeValue(qpos, path)
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
case actionType:
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
q.result, err = describeType(qpos, path)
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
case actionPackage:
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
q.result, err = describePackage(qpos, path)
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
case actionStmt:
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
q.result, err = describeStmt(qpos, path)
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
case actionUnknown:
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
q.result = &describeUnknownResult{path[0]}
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
default:
|
|
|
|
panic(action) // unreachable
|
|
|
|
}
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
return err
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type describeUnknownResult struct {
|
|
|
|
node ast.Node
|
|
|
|
}
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
func (r *describeUnknownResult) display(printf printfFunc) {
|
2013-08-27 15:58:26 -06:00
|
|
|
// Nothing much to say about misc syntax.
|
2013-12-09 07:36:29 -07:00
|
|
|
printf(r.node, "%s", astutil.NodeDescription(r.node))
|
2013-09-03 13:29:02 -06:00
|
|
|
}
|
|
|
|
|
2013-09-24 13:08:14 -06:00
|
|
|
func (r *describeUnknownResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
|
|
|
res.Describe = &serial.Describe{
|
2013-12-09 07:36:29 -07:00
|
|
|
Desc: astutil.NodeDescription(r.node),
|
2013-09-03 13:29:02 -06:00
|
|
|
Pos: fset.Position(r.node.Pos()).String(),
|
|
|
|
}
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type action int
|
|
|
|
|
|
|
|
const (
|
|
|
|
actionUnknown action = iota // None of the below
|
|
|
|
actionExpr // FuncDecl, true Expr or Ident(types.{Const,Var})
|
|
|
|
actionType // type Expr or Ident(types.TypeName).
|
|
|
|
actionStmt // Stmt or Ident(types.Label)
|
|
|
|
actionPackage // Ident(types.Package) or ImportSpec
|
|
|
|
)
|
|
|
|
|
|
|
|
// findInterestingNode classifies the syntax node denoted by path as one of:
|
|
|
|
// - an expression, part of an expression or a reference to a constant
|
|
|
|
// or variable;
|
|
|
|
// - a type, part of a type, or a reference to a named type;
|
|
|
|
// - a statement, part of a statement, or a label referring to a statement;
|
|
|
|
// - part of a package declaration or import spec.
|
|
|
|
// - none of the above.
|
|
|
|
// and returns the most "interesting" associated node, which may be
|
|
|
|
// the same node, an ancestor or a descendent.
|
|
|
|
//
|
2014-01-16 07:33:58 -07:00
|
|
|
func findInterestingNode(pkginfo *loader.PackageInfo, path []ast.Node) ([]ast.Node, action) {
|
2013-08-27 15:58:26 -06:00
|
|
|
// TODO(adonovan): integrate with go/types/stdlib_test.go and
|
|
|
|
// apply this to every AST node we can find to make sure it
|
|
|
|
// doesn't crash.
|
|
|
|
|
|
|
|
// TODO(adonovan): audit for ParenExpr safety, esp. since we
|
|
|
|
// traverse up and down.
|
|
|
|
|
|
|
|
// TODO(adonovan): if the users selects the "." in
|
|
|
|
// "fmt.Fprintf()", they'll get an ambiguous selection error;
|
|
|
|
// we won't even reach here. Can we do better?
|
|
|
|
|
|
|
|
// TODO(adonovan): describing a field within 'type T struct {...}'
|
2013-09-03 13:29:02 -06:00
|
|
|
// describes the (anonymous) struct type and concludes "no methods".
|
|
|
|
// We should ascend to the enclosing type decl, if any.
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
for len(path) > 0 {
|
|
|
|
switch n := path[0].(type) {
|
|
|
|
case *ast.GenDecl:
|
|
|
|
if len(n.Specs) == 1 {
|
|
|
|
// Descend to sole {Import,Type,Value}Spec child.
|
|
|
|
path = append([]ast.Node{n.Specs[0]}, path...)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return path, actionUnknown // uninteresting
|
|
|
|
|
|
|
|
case *ast.FuncDecl:
|
|
|
|
// Descend to function name.
|
|
|
|
path = append([]ast.Node{n.Name}, path...)
|
|
|
|
continue
|
|
|
|
|
|
|
|
case *ast.ImportSpec:
|
|
|
|
return path, actionPackage
|
|
|
|
|
|
|
|
case *ast.ValueSpec:
|
|
|
|
if len(n.Names) == 1 {
|
|
|
|
// Descend to sole Ident child.
|
|
|
|
path = append([]ast.Node{n.Names[0]}, path...)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return path, actionUnknown // uninteresting
|
|
|
|
|
|
|
|
case *ast.TypeSpec:
|
|
|
|
// Descend to type name.
|
|
|
|
path = append([]ast.Node{n.Name}, path...)
|
|
|
|
continue
|
|
|
|
|
|
|
|
case ast.Stmt:
|
|
|
|
return path, actionStmt
|
|
|
|
|
|
|
|
case *ast.ArrayType,
|
|
|
|
*ast.StructType,
|
|
|
|
*ast.FuncType,
|
|
|
|
*ast.InterfaceType,
|
|
|
|
*ast.MapType,
|
|
|
|
*ast.ChanType:
|
|
|
|
return path, actionType
|
|
|
|
|
|
|
|
case *ast.Comment, *ast.CommentGroup, *ast.File, *ast.KeyValueExpr, *ast.CommClause:
|
|
|
|
return path, actionUnknown // uninteresting
|
|
|
|
|
|
|
|
case *ast.Ellipsis:
|
|
|
|
// Continue to enclosing node.
|
|
|
|
// e.g. [...]T in ArrayType
|
|
|
|
// f(x...) in CallExpr
|
|
|
|
// f(x...T) in FuncType
|
|
|
|
|
|
|
|
case *ast.Field:
|
|
|
|
// TODO(adonovan): this needs more thought,
|
|
|
|
// since fields can be so many things.
|
|
|
|
if len(n.Names) == 1 {
|
|
|
|
// Descend to sole Ident child.
|
|
|
|
path = append([]ast.Node{n.Names[0]}, path...)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// Zero names (e.g. anon field in struct)
|
|
|
|
// or multiple field or param names:
|
|
|
|
// continue to enclosing field list.
|
|
|
|
|
|
|
|
case *ast.FieldList:
|
|
|
|
// Continue to enclosing node:
|
|
|
|
// {Struct,Func,Interface}Type or FuncDecl.
|
|
|
|
|
|
|
|
case *ast.BasicLit:
|
|
|
|
if _, ok := path[1].(*ast.ImportSpec); ok {
|
|
|
|
return path[1:], actionPackage
|
|
|
|
}
|
|
|
|
return path, actionExpr
|
|
|
|
|
|
|
|
case *ast.SelectorExpr:
|
2014-07-11 03:50:09 -06:00
|
|
|
// TODO(adonovan): use Selections info directly.
|
|
|
|
if pkginfo.Uses[n.Sel] == nil {
|
2013-12-13 08:04:55 -07:00
|
|
|
// TODO(adonovan): is this reachable?
|
2013-08-27 15:58:26 -06:00
|
|
|
return path, actionUnknown
|
|
|
|
}
|
|
|
|
// Descend to .Sel child.
|
|
|
|
path = append([]ast.Node{n.Sel}, path...)
|
|
|
|
continue
|
|
|
|
|
|
|
|
case *ast.Ident:
|
2013-11-14 15:11:43 -07:00
|
|
|
switch pkginfo.ObjectOf(n).(type) {
|
2013-09-13 10:52:57 -06:00
|
|
|
case *types.PkgName:
|
2013-08-27 15:58:26 -06:00
|
|
|
return path, actionPackage
|
|
|
|
|
|
|
|
case *types.Const:
|
|
|
|
return path, actionExpr
|
|
|
|
|
|
|
|
case *types.Label:
|
|
|
|
return path, actionStmt
|
|
|
|
|
|
|
|
case *types.TypeName:
|
|
|
|
return path, actionType
|
|
|
|
|
|
|
|
case *types.Var:
|
|
|
|
// For x in 'struct {x T}', return struct type, for now.
|
|
|
|
if _, ok := path[1].(*ast.Field); ok {
|
|
|
|
_ = path[2].(*ast.FieldList) // assertion
|
|
|
|
if _, ok := path[3].(*ast.StructType); ok {
|
|
|
|
return path[3:], actionType
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return path, actionExpr
|
|
|
|
|
|
|
|
case *types.Func:
|
2013-11-14 15:11:43 -07:00
|
|
|
return path, actionExpr
|
2013-08-27 15:58:26 -06:00
|
|
|
|
2013-11-14 15:11:43 -07:00
|
|
|
case *types.Builtin:
|
2013-08-27 15:58:26 -06:00
|
|
|
// For reference to built-in function, return enclosing call.
|
2013-11-14 15:11:43 -07:00
|
|
|
path = path[1:] // ascend to enclosing function call
|
|
|
|
continue
|
2013-12-13 08:04:55 -07:00
|
|
|
|
|
|
|
case *types.Nil:
|
|
|
|
return path, actionExpr
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// No object.
|
|
|
|
switch path[1].(type) {
|
|
|
|
case *ast.SelectorExpr:
|
|
|
|
// Return enclosing selector expression.
|
|
|
|
return path[1:], actionExpr
|
|
|
|
|
|
|
|
case *ast.Field:
|
|
|
|
// TODO(adonovan): test this.
|
|
|
|
// e.g. all f in:
|
|
|
|
// struct { f, g int }
|
|
|
|
// interface { f() }
|
|
|
|
// func (f T) method(f, g int) (f, g bool)
|
|
|
|
//
|
|
|
|
// switch path[3].(type) {
|
|
|
|
// case *ast.FuncDecl:
|
|
|
|
// case *ast.StructType:
|
|
|
|
// case *ast.InterfaceType:
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// return path[1:], actionExpr
|
|
|
|
//
|
|
|
|
// Unclear what to do with these.
|
|
|
|
// Struct.Fields -- field
|
|
|
|
// Interface.Methods -- field
|
|
|
|
// FuncType.{Params.Results} -- actionExpr
|
|
|
|
// FuncDecl.Recv -- actionExpr
|
|
|
|
|
2013-09-13 10:52:57 -06:00
|
|
|
case *ast.File:
|
|
|
|
// 'package foo'
|
|
|
|
return path, actionPackage
|
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
case *ast.ImportSpec:
|
|
|
|
// TODO(adonovan): fix: why no package object? go/types bug?
|
|
|
|
return path[1:], actionPackage
|
|
|
|
|
|
|
|
default:
|
2014-07-11 03:50:09 -06:00
|
|
|
// e.g. blank identifier
|
|
|
|
// or y in "switch y := x.(type)"
|
2013-12-13 08:04:55 -07:00
|
|
|
// or code in a _test.go file that's not part of the package.
|
2014-07-11 03:50:09 -06:00
|
|
|
log.Printf("unknown reference %s in %T\n", n, path[1])
|
2013-08-27 15:58:26 -06:00
|
|
|
return path, actionUnknown
|
|
|
|
}
|
|
|
|
|
|
|
|
case *ast.StarExpr:
|
2014-07-11 03:50:09 -06:00
|
|
|
if pkginfo.Types[n].IsType() {
|
2013-08-27 15:58:26 -06:00
|
|
|
return path, actionType
|
|
|
|
}
|
|
|
|
return path, actionExpr
|
|
|
|
|
|
|
|
case ast.Expr:
|
|
|
|
// All Expr but {BasicLit,Ident,StarExpr} are
|
|
|
|
// "true" expressions that evaluate to a value.
|
|
|
|
return path, actionExpr
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ascend to parent.
|
|
|
|
path = path[1:]
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, actionUnknown // unreachable
|
|
|
|
}
|
|
|
|
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error) {
|
2013-08-27 15:58:26 -06:00
|
|
|
var expr ast.Expr
|
2013-09-09 19:06:25 -06:00
|
|
|
var obj types.Object
|
2013-08-27 15:58:26 -06:00
|
|
|
switch n := path[0].(type) {
|
|
|
|
case *ast.ValueSpec:
|
|
|
|
// ambiguous ValueSpec containing multiple names
|
2013-09-25 12:34:39 -06:00
|
|
|
return nil, fmt.Errorf("multiple value specification")
|
2013-09-09 19:06:25 -06:00
|
|
|
case *ast.Ident:
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
obj = qpos.info.ObjectOf(n)
|
2013-09-09 19:06:25 -06:00
|
|
|
expr = n
|
2013-08-27 15:58:26 -06:00
|
|
|
case ast.Expr:
|
|
|
|
expr = n
|
|
|
|
default:
|
2013-12-13 08:04:55 -07:00
|
|
|
// TODO(adonovan): is this reachable?
|
2013-09-25 12:34:39 -06:00
|
|
|
return nil, fmt.Errorf("unexpected AST for expr: %T", n)
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
typ := qpos.info.TypeOf(expr)
|
2014-07-11 03:50:09 -06:00
|
|
|
constVal := qpos.info.Types[expr].Value
|
2013-09-09 19:06:25 -06:00
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
return &describeValueResult{
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
qpos: qpos,
|
2013-09-03 13:29:02 -06:00
|
|
|
expr: expr,
|
|
|
|
typ: typ,
|
|
|
|
constVal: constVal,
|
|
|
|
obj: obj,
|
2013-08-27 15:58:26 -06:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type describeValueResult struct {
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
qpos *queryPos
|
2013-12-13 08:04:55 -07:00
|
|
|
expr ast.Expr // query node
|
|
|
|
typ types.Type // type of expression
|
|
|
|
constVal exact.Value // value of expression, if constant
|
|
|
|
obj types.Object // var/func/const object, if expr was Ident
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
func (r *describeValueResult) display(printf printfFunc) {
|
2013-09-04 14:15:41 -06:00
|
|
|
var prefix, suffix string
|
2013-09-03 13:29:02 -06:00
|
|
|
if r.constVal != nil {
|
|
|
|
suffix = fmt.Sprintf(" of constant value %s", r.constVal)
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
2013-09-04 14:15:41 -06:00
|
|
|
switch obj := r.obj.(type) {
|
|
|
|
case *types.Func:
|
|
|
|
if recv := obj.Type().(*types.Signature).Recv(); recv != nil {
|
|
|
|
if _, ok := recv.Type().Underlying().(*types.Interface); ok {
|
|
|
|
prefix = "interface method "
|
|
|
|
} else {
|
|
|
|
prefix = "method "
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
// Describe the expression.
|
|
|
|
if r.obj != nil {
|
|
|
|
if r.obj.Pos() == r.expr.Pos() {
|
|
|
|
// defining ident
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
printf(r.expr, "definition of %s%s%s", prefix, r.qpos.objectString(r.obj), suffix)
|
2013-08-27 15:58:26 -06:00
|
|
|
} else {
|
|
|
|
// referring ident
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
printf(r.expr, "reference to %s%s%s", prefix, r.qpos.objectString(r.obj), suffix)
|
2013-08-27 15:58:26 -06:00
|
|
|
if def := r.obj.Pos(); def != token.NoPos {
|
2013-09-03 13:29:02 -06:00
|
|
|
printf(def, "defined here")
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2013-12-09 07:36:29 -07:00
|
|
|
desc := astutil.NodeDescription(r.expr)
|
2013-08-27 15:58:26 -06:00
|
|
|
if suffix != "" {
|
|
|
|
// constant expression
|
2013-09-03 13:29:02 -06:00
|
|
|
printf(r.expr, "%s%s", desc, suffix)
|
2013-08-27 15:58:26 -06:00
|
|
|
} else {
|
|
|
|
// non-constant expression
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
printf(r.expr, "%s of type %s", desc, r.qpos.typeString(r.typ))
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-24 13:08:14 -06:00
|
|
|
func (r *describeValueResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
2013-12-13 08:04:55 -07:00
|
|
|
var value, objpos string
|
2013-09-03 13:29:02 -06:00
|
|
|
if r.constVal != nil {
|
|
|
|
value = r.constVal.String()
|
|
|
|
}
|
|
|
|
if r.obj != nil {
|
|
|
|
objpos = fset.Position(r.obj.Pos()).String()
|
|
|
|
}
|
|
|
|
|
2013-09-24 13:08:14 -06:00
|
|
|
res.Describe = &serial.Describe{
|
2013-12-09 07:36:29 -07:00
|
|
|
Desc: astutil.NodeDescription(r.expr),
|
2013-09-03 13:29:02 -06:00
|
|
|
Pos: fset.Position(r.expr.Pos()).String(),
|
|
|
|
Detail: "value",
|
2013-09-24 13:08:14 -06:00
|
|
|
Value: &serial.DescribeValue{
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
Type: r.qpos.typeString(r.typ),
|
2013-09-03 13:29:02 -06:00
|
|
|
Value: value,
|
|
|
|
ObjPos: objpos,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
// ---- TYPE ------------------------------------------------------------
|
|
|
|
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
func describeType(qpos *queryPos, path []ast.Node) (*describeTypeResult, error) {
|
2013-08-27 15:58:26 -06:00
|
|
|
var description string
|
|
|
|
var t types.Type
|
|
|
|
switch n := path[0].(type) {
|
|
|
|
case *ast.Ident:
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
t = qpos.info.TypeOf(n)
|
2013-08-27 15:58:26 -06:00
|
|
|
switch t := t.(type) {
|
|
|
|
case *types.Basic:
|
2013-11-15 07:22:16 -07:00
|
|
|
description = "reference to built-in "
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
case *types.Named:
|
|
|
|
isDef := t.Obj().Pos() == n.Pos() // see caveats at isDef above
|
|
|
|
if isDef {
|
2013-11-15 07:22:16 -07:00
|
|
|
description = "definition of "
|
2013-08-27 15:58:26 -06:00
|
|
|
} else {
|
2013-11-15 07:22:16 -07:00
|
|
|
description = "reference to "
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case ast.Expr:
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
t = qpos.info.TypeOf(n)
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
default:
|
|
|
|
// Unreachable?
|
2013-09-25 12:34:39 -06:00
|
|
|
return nil, fmt.Errorf("unexpected AST for type: %T", n)
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
description = description + "type " + qpos.typeString(t)
|
2013-11-20 14:00:23 -07:00
|
|
|
|
|
|
|
// Show sizes for structs and named types (it's fairly obvious for others).
|
|
|
|
switch t.(type) {
|
|
|
|
case *types.Named, *types.Struct:
|
2016-03-25 23:16:12 -06:00
|
|
|
szs := types.StdSizes{WordSize: 8, MaxAlign: 8} // assume amd64
|
2013-11-20 14:00:23 -07:00
|
|
|
description = fmt.Sprintf("%s (size %d, align %d)", description,
|
|
|
|
szs.Sizeof(t), szs.Alignof(t))
|
|
|
|
}
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
return &describeTypeResult{
|
2013-11-15 07:22:16 -07:00
|
|
|
qpos: qpos,
|
2013-09-03 13:29:02 -06:00
|
|
|
node: path[0],
|
2013-11-20 14:00:23 -07:00
|
|
|
description: description,
|
2013-09-03 13:29:02 -06:00
|
|
|
typ: t,
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
methods: accessibleMethods(t, qpos.info.Pkg),
|
2013-09-03 13:29:02 -06:00
|
|
|
}, nil
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type describeTypeResult struct {
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
qpos *queryPos
|
2013-08-27 15:58:26 -06:00
|
|
|
node ast.Node
|
|
|
|
description string
|
|
|
|
typ types.Type
|
2013-09-03 13:29:02 -06:00
|
|
|
methods []*types.Selection
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
func (r *describeTypeResult) display(printf printfFunc) {
|
|
|
|
printf(r.node, "%s", r.description)
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
// Show the underlying type for a reference to a named type.
|
|
|
|
if nt, ok := r.typ.(*types.Named); ok && r.node.Pos() != nt.Obj().Pos() {
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
printf(nt.Obj(), "defined as %s", r.qpos.typeString(nt.Underlying()))
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Print the method set, if the type kind is capable of bearing methods.
|
|
|
|
switch r.typ.(type) {
|
|
|
|
case *types.Interface, *types.Struct, *types.Named:
|
2013-09-03 13:29:02 -06:00
|
|
|
if len(r.methods) > 0 {
|
|
|
|
printf(r.node, "Method set:")
|
|
|
|
for _, meth := range r.methods {
|
2014-11-13 10:34:25 -07:00
|
|
|
// TODO(adonovan): print these relative
|
|
|
|
// to the owning package, not the
|
|
|
|
// query package.
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
printf(meth.Obj(), "\t%s", r.qpos.selectionString(meth))
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
} else {
|
2013-09-03 13:29:02 -06:00
|
|
|
printf(r.node, "No methods.")
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-24 13:08:14 -06:00
|
|
|
func (r *describeTypeResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
2013-09-03 13:29:02 -06:00
|
|
|
var namePos, nameDef string
|
|
|
|
if nt, ok := r.typ.(*types.Named); ok {
|
|
|
|
namePos = fset.Position(nt.Obj().Pos()).String()
|
|
|
|
nameDef = nt.Underlying().String()
|
|
|
|
}
|
2013-09-24 13:08:14 -06:00
|
|
|
res.Describe = &serial.Describe{
|
2013-09-03 13:29:02 -06:00
|
|
|
Desc: r.description,
|
|
|
|
Pos: fset.Position(r.node.Pos()).String(),
|
|
|
|
Detail: "type",
|
2013-09-24 13:08:14 -06:00
|
|
|
Type: &serial.DescribeType{
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
Type: r.qpos.typeString(r.typ),
|
2013-09-03 13:29:02 -06:00
|
|
|
NamePos: namePos,
|
|
|
|
NameDef: nameDef,
|
2013-11-15 10:35:11 -07:00
|
|
|
Methods: methodsToSerial(r.qpos.info.Pkg, r.methods, fset),
|
2013-09-03 13:29:02 -06:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
// ---- PACKAGE ------------------------------------------------------------
|
|
|
|
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
func describePackage(qpos *queryPos, path []ast.Node) (*describePackageResult, error) {
|
2013-08-27 15:58:26 -06:00
|
|
|
var description string
|
2013-09-10 12:19:11 -06:00
|
|
|
var pkg *types.Package
|
2013-08-27 15:58:26 -06:00
|
|
|
switch n := path[0].(type) {
|
|
|
|
case *ast.ImportSpec:
|
2015-12-30 08:37:15 -07:00
|
|
|
var obj types.Object
|
2014-07-11 03:50:09 -06:00
|
|
|
if n.Name != nil {
|
2015-12-30 08:37:15 -07:00
|
|
|
obj = qpos.info.Defs[n.Name]
|
|
|
|
} else {
|
|
|
|
obj = qpos.info.Implicits[n]
|
|
|
|
}
|
|
|
|
pkgname, _ := obj.(*types.PkgName)
|
|
|
|
if pkgname == nil {
|
|
|
|
return nil, fmt.Errorf("can't import package %s", n.Path.Value)
|
2014-07-11 03:50:09 -06:00
|
|
|
}
|
2014-09-02 16:12:08 -06:00
|
|
|
pkg = pkgname.Imported()
|
|
|
|
description = fmt.Sprintf("import of package %q", pkg.Path())
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
case *ast.Ident:
|
|
|
|
if _, isDef := path[1].(*ast.File); isDef {
|
2013-09-06 16:13:57 -06:00
|
|
|
// e.g. package id
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
pkg = qpos.info.Pkg
|
2013-09-10 12:19:11 -06:00
|
|
|
description = fmt.Sprintf("definition of package %q", pkg.Path())
|
2013-08-27 15:58:26 -06:00
|
|
|
} else {
|
2014-07-11 03:50:09 -06:00
|
|
|
// e.g. import id "..."
|
2013-09-06 16:13:57 -06:00
|
|
|
// or id.F()
|
2014-09-02 16:12:08 -06:00
|
|
|
pkg = qpos.info.ObjectOf(n).(*types.PkgName).Imported()
|
2013-09-10 12:19:11 -06:00
|
|
|
description = fmt.Sprintf("reference to package %q", pkg.Path())
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Unreachable?
|
2013-09-25 12:34:39 -06:00
|
|
|
return nil, fmt.Errorf("unexpected AST for package: %T", n)
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
var members []*describeMember
|
2013-09-10 12:19:11 -06:00
|
|
|
// NB: "unsafe" has no types.Package
|
2013-09-06 16:13:57 -06:00
|
|
|
if pkg != nil {
|
2013-09-10 12:19:11 -06:00
|
|
|
// Enumerate the accessible package members
|
|
|
|
// in lexicographic order.
|
|
|
|
for _, name := range pkg.Scope().Names() {
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
if pkg == qpos.info.Pkg || ast.IsExported(name) {
|
2013-09-10 12:19:11 -06:00
|
|
|
mem := pkg.Scope().Lookup(name)
|
|
|
|
var methods []*types.Selection
|
|
|
|
if mem, ok := mem.(*types.TypeName); ok {
|
go.tools/oracle: refactor Oracle API to allow repeated queries on same scope.
The existing standalone Query function builds an importer, ssa.Program, oracle,
and query position, executes the query and returns the result.
For clients (such as Frederik Zipp's web-based github.com/fzipp/pythia tool)
that wish to load the program once and make several queries, we now expose
these as separate operations too. Here's a client, in pseudocode:
o := oracle.New(...)
for ... {
qpos := o.ParseQueryPos(...)
res := o.Query(mode, qpos)
print result
}
NB: this is a slight deoptimisation in the one-shot case since we have to
build the entire SSA program with debug info, not just the query package,
since we now don't know the query package at that time.
The 'exact' param to ParseQueryPos needs more thought since its
ideal value is a function of the query mode. This will do for now.
Details:
- expose Oracle type, New() func and Query() method.
- expose QueryPos type and ParseQueryPos func.
- improved package doc comment.
- un-exposed the "needs" bits.
- added test.
R=crawshaw
CC=frederik.zipp, golang-dev
https://golang.org/cl/13810043
2013-09-23 13:02:18 -06:00
|
|
|
methods = accessibleMethods(mem.Type(), qpos.info.Pkg)
|
2013-09-10 12:19:11 -06:00
|
|
|
}
|
|
|
|
members = append(members, &describeMember{
|
|
|
|
mem,
|
|
|
|
methods,
|
|
|
|
})
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-27 15:58:26 -06:00
|
|
|
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
return &describePackageResult{qpos.fset, path[0], description, pkg, members}, nil
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type describePackageResult struct {
|
2013-09-03 13:29:02 -06:00
|
|
|
fset *token.FileSet
|
2013-08-27 15:58:26 -06:00
|
|
|
node ast.Node
|
|
|
|
description string
|
2013-09-10 12:19:11 -06:00
|
|
|
pkg *types.Package
|
2013-09-03 13:29:02 -06:00
|
|
|
members []*describeMember // in lexicographic name order
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
type describeMember struct {
|
2013-09-10 12:19:11 -06:00
|
|
|
obj types.Object
|
2013-09-03 13:29:02 -06:00
|
|
|
methods []*types.Selection // in types.MethodSet order
|
|
|
|
}
|
2013-08-27 15:58:26 -06:00
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
func (r *describePackageResult) display(printf printfFunc) {
|
|
|
|
printf(r.node, "%s", r.description)
|
2013-08-27 15:58:26 -06:00
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
// Compute max width of name "column".
|
|
|
|
maxname := 0
|
|
|
|
for _, mem := range r.members {
|
2013-09-10 12:19:11 -06:00
|
|
|
if l := len(mem.obj.Name()); l > maxname {
|
2013-09-03 13:29:02 -06:00
|
|
|
maxname = l
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
2013-09-03 13:29:02 -06:00
|
|
|
}
|
2013-08-27 15:58:26 -06:00
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
for _, mem := range r.members {
|
2013-09-10 12:19:11 -06:00
|
|
|
printf(mem.obj, "\t%s", formatMember(mem.obj, maxname))
|
2013-09-03 13:29:02 -06:00
|
|
|
for _, meth := range mem.methods {
|
2015-06-26 14:11:46 -06:00
|
|
|
printf(meth.Obj(), "\t\t%s", types.SelectionString(meth, types.RelativeTo(r.pkg)))
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-10 12:19:11 -06:00
|
|
|
func formatMember(obj types.Object, maxname int) string {
|
2015-06-26 14:11:46 -06:00
|
|
|
qualifier := types.RelativeTo(obj.Pkg())
|
2013-08-27 15:58:26 -06:00
|
|
|
var buf bytes.Buffer
|
2013-09-10 12:19:11 -06:00
|
|
|
fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name())
|
|
|
|
switch obj := obj.(type) {
|
|
|
|
case *types.Const:
|
2015-06-26 14:11:46 -06:00
|
|
|
fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Type(), qualifier), obj.Val().String())
|
2013-08-27 15:58:26 -06:00
|
|
|
|
2013-09-10 12:19:11 -06:00
|
|
|
case *types.Func:
|
2015-06-26 14:11:46 -06:00
|
|
|
fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
|
2013-08-27 15:58:26 -06:00
|
|
|
|
2013-09-10 12:19:11 -06:00
|
|
|
case *types.TypeName:
|
2013-08-27 15:58:26 -06:00
|
|
|
// Abbreviate long aggregate type names.
|
|
|
|
var abbrev string
|
2013-09-10 12:19:11 -06:00
|
|
|
switch t := obj.Type().Underlying().(type) {
|
2013-08-27 15:58:26 -06:00
|
|
|
case *types.Interface:
|
|
|
|
if t.NumMethods() > 1 {
|
|
|
|
abbrev = "interface{...}"
|
|
|
|
}
|
|
|
|
case *types.Struct:
|
|
|
|
if t.NumFields() > 1 {
|
|
|
|
abbrev = "struct{...}"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if abbrev == "" {
|
2015-06-26 14:11:46 -06:00
|
|
|
fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type().Underlying(), qualifier))
|
2013-08-27 15:58:26 -06:00
|
|
|
} else {
|
|
|
|
fmt.Fprintf(&buf, " %s", abbrev)
|
|
|
|
}
|
|
|
|
|
2013-09-10 12:19:11 -06:00
|
|
|
case *types.Var:
|
2015-06-26 14:11:46 -06:00
|
|
|
fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
return buf.String()
|
|
|
|
}
|
|
|
|
|
2013-09-24 13:08:14 -06:00
|
|
|
func (r *describePackageResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
|
|
|
var members []*serial.DescribeMember
|
2013-09-03 13:29:02 -06:00
|
|
|
for _, mem := range r.members {
|
2013-09-10 12:19:11 -06:00
|
|
|
typ := mem.obj.Type()
|
2013-09-03 13:29:02 -06:00
|
|
|
var val string
|
2013-09-10 12:19:11 -06:00
|
|
|
switch mem := mem.obj.(type) {
|
|
|
|
case *types.Const:
|
|
|
|
val = mem.Val().String()
|
|
|
|
case *types.TypeName:
|
2013-09-03 13:29:02 -06:00
|
|
|
typ = typ.Underlying()
|
|
|
|
}
|
2013-09-24 13:08:14 -06:00
|
|
|
members = append(members, &serial.DescribeMember{
|
2013-09-10 12:19:11 -06:00
|
|
|
Name: mem.obj.Name(),
|
2013-09-03 13:29:02 -06:00
|
|
|
Type: typ.String(),
|
|
|
|
Value: val,
|
2013-09-10 12:19:11 -06:00
|
|
|
Pos: fset.Position(mem.obj.Pos()).String(),
|
|
|
|
Kind: tokenOf(mem.obj),
|
2013-11-15 10:35:11 -07:00
|
|
|
Methods: methodsToSerial(r.pkg, mem.methods, fset),
|
2013-09-03 13:29:02 -06:00
|
|
|
})
|
|
|
|
}
|
2013-09-24 13:08:14 -06:00
|
|
|
res.Describe = &serial.Describe{
|
2013-09-03 13:29:02 -06:00
|
|
|
Desc: r.description,
|
|
|
|
Pos: fset.Position(r.node.Pos()).String(),
|
|
|
|
Detail: "package",
|
2013-09-24 13:08:14 -06:00
|
|
|
Package: &serial.DescribePackage{
|
2013-09-10 12:19:11 -06:00
|
|
|
Path: r.pkg.Path(),
|
2013-09-03 13:29:02 -06:00
|
|
|
Members: members,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-10 12:19:11 -06:00
|
|
|
func tokenOf(o types.Object) string {
|
|
|
|
switch o.(type) {
|
|
|
|
case *types.Func:
|
|
|
|
return "func"
|
|
|
|
case *types.Var:
|
|
|
|
return "var"
|
|
|
|
case *types.TypeName:
|
|
|
|
return "type"
|
|
|
|
case *types.Const:
|
|
|
|
return "const"
|
2013-09-13 10:52:57 -06:00
|
|
|
case *types.PkgName:
|
2013-09-10 12:19:11 -06:00
|
|
|
return "package"
|
2016-02-02 14:27:46 -07:00
|
|
|
case *types.Builtin:
|
|
|
|
return "builtin" // e.g. when describing package "unsafe"
|
|
|
|
case *types.Nil:
|
|
|
|
return "nil"
|
|
|
|
case *types.Label:
|
|
|
|
return "label"
|
2013-09-10 12:19:11 -06:00
|
|
|
}
|
|
|
|
panic(o)
|
|
|
|
}
|
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
// ---- STATEMENT ------------------------------------------------------------
|
|
|
|
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
func describeStmt(qpos *queryPos, path []ast.Node) (*describeStmtResult, error) {
|
2013-08-27 15:58:26 -06:00
|
|
|
var description string
|
|
|
|
switch n := path[0].(type) {
|
|
|
|
case *ast.Ident:
|
2014-07-11 03:50:09 -06:00
|
|
|
if qpos.info.Defs[n] != nil {
|
2013-08-27 15:58:26 -06:00
|
|
|
description = "labelled statement"
|
|
|
|
} else {
|
|
|
|
description = "reference to labelled statement"
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Nothing much to say about statements.
|
2013-12-09 07:36:29 -07:00
|
|
|
description = astutil.NodeDescription(n)
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
oracle: several major improvements
Features:
More robust: silently ignore type errors in modes that don't need
SSA form: describe, referrers, implements, freevars, description.
This makes the tool much more robust for everyday queries.
Less configuration: don't require a scope argument for all queries.
Only queries that do pointer analysis need it.
For the rest, the initial position is enough for
importQueryPackage to deduce the scope.
It now works for queries in GoFiles, TestGoFiles, or XTestGoFiles.
(It no longer works for ad-hoc main packages like
$GOROOT/src/net/http/triv.go)
More complete: "referrers" computes the scope automatically by
scanning the import graph of the entire workspace, using gorename's
refactor/importgraph package. This requires two passes at loading.
Faster: simplified start-up logic avoids unnecessary package loading
and SSA construction (a consequence of bad abstraction) in many
cases.
"callgraph": remove it. Unlike all the other commands it isn't
related to the current selection, and we have
golang.org/x/tools/cmdcallgraph now.
Internals:
Drop support for long-running clients (i.e., Pythia), since
godoc -analysis supports all the same features except "pointsto",
and precomputes all the results so latency is much lower.
Get rid of various unhelpful abstractions introduced to support
long-running clients. Expand out the set-up logic for each
subcommand. This is simpler, easier to read, and gives us more
control, at a small cost in duplication---the familiar story of
abstractions.
Discard PTA warnings. We weren't showing them (nor should we).
Split tests into separate directories (so that importgraph works).
Change-Id: I55d46b3ab33cdf7ac22436fcc2148fe04c901237
Reviewed-on: https://go-review.googlesource.com/8243
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2015-03-30 09:21:48 -06:00
|
|
|
return &describeStmtResult{qpos.fset, path[0], description}, nil
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type describeStmtResult struct {
|
2013-09-03 13:29:02 -06:00
|
|
|
fset *token.FileSet
|
2013-08-27 15:58:26 -06:00
|
|
|
node ast.Node
|
|
|
|
description string
|
|
|
|
}
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
func (r *describeStmtResult) display(printf printfFunc) {
|
|
|
|
printf(r.node, "%s", r.description)
|
|
|
|
}
|
|
|
|
|
2013-09-24 13:08:14 -06:00
|
|
|
func (r *describeStmtResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
|
|
|
res.Describe = &serial.Describe{
|
2013-09-03 13:29:02 -06:00
|
|
|
Desc: r.description,
|
|
|
|
Pos: fset.Position(r.node.Pos()).String(),
|
|
|
|
Detail: "unknown",
|
|
|
|
}
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------- Utilities -------------------
|
|
|
|
|
|
|
|
// pathToString returns a string containing the concrete types of the
|
|
|
|
// nodes in path.
|
2013-12-13 08:04:55 -07:00
|
|
|
func pathToString(path []ast.Node) string {
|
2013-08-27 15:58:26 -06:00
|
|
|
var buf bytes.Buffer
|
|
|
|
fmt.Fprint(&buf, "[")
|
|
|
|
for i, n := range path {
|
|
|
|
if i > 0 {
|
|
|
|
fmt.Fprint(&buf, " ")
|
|
|
|
}
|
|
|
|
fmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast."))
|
|
|
|
}
|
|
|
|
fmt.Fprint(&buf, "]")
|
|
|
|
return buf.String()
|
|
|
|
}
|
2013-09-03 13:29:02 -06:00
|
|
|
|
|
|
|
func accessibleMethods(t types.Type, from *types.Package) []*types.Selection {
|
|
|
|
var methods []*types.Selection
|
2014-02-19 11:32:36 -07:00
|
|
|
for _, meth := range typeutil.IntuitiveMethodSet(t, nil) {
|
2013-09-03 13:29:02 -06:00
|
|
|
if isAccessibleFrom(meth.Obj(), from) {
|
|
|
|
methods = append(methods, meth)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return methods
|
|
|
|
}
|
|
|
|
|
|
|
|
func isAccessibleFrom(obj types.Object, pkg *types.Package) bool {
|
|
|
|
return ast.IsExported(obj.Name()) || obj.Pkg() == pkg
|
|
|
|
}
|
|
|
|
|
2013-11-15 10:35:11 -07:00
|
|
|
func methodsToSerial(this *types.Package, methods []*types.Selection, fset *token.FileSet) []serial.DescribeMethod {
|
2015-06-26 14:11:46 -06:00
|
|
|
qualifier := types.RelativeTo(this)
|
2013-09-24 13:08:14 -06:00
|
|
|
var jmethods []serial.DescribeMethod
|
2013-09-03 13:29:02 -06:00
|
|
|
for _, meth := range methods {
|
2015-02-24 16:02:49 -07:00
|
|
|
var ser serial.DescribeMethod
|
|
|
|
if meth != nil { // may contain nils when called by implements (on a method)
|
|
|
|
ser = serial.DescribeMethod{
|
2015-06-26 14:11:46 -06:00
|
|
|
Name: types.SelectionString(meth, qualifier),
|
2015-02-24 16:02:49 -07:00
|
|
|
Pos: fset.Position(meth.Obj().Pos()).String(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
jmethods = append(jmethods, ser)
|
2013-09-03 13:29:02 -06:00
|
|
|
}
|
|
|
|
return jmethods
|
|
|
|
}
|