oracle: support "referrers" query on package declaration

Added test.

Change-Id: Id7d061b0f74959166b5631a3fde8da4000ffb8d2
Reviewed-on: https://go-review.googlesource.com/9326
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Alan Donovan 2015-04-24 16:57:46 -04:00
parent fb59b33999
commit a9f55c4fa4
6 changed files with 39 additions and 22 deletions

View File

@ -46,7 +46,9 @@ func definition(q *Query) error {
obj := qpos.info.ObjectOf(id) obj := qpos.info.ObjectOf(id)
if obj == nil { if obj == nil {
// Happens for y in "switch y := x.(type)", but I think that's all. // Happens for y in "switch y := x.(type)",
// and the package declaration,
// but I think that's all.
return fmt.Errorf("no object for identifier") return fmt.Errorf("no object for identifier")
} }

View File

@ -18,9 +18,6 @@ import (
"golang.org/x/tools/refactor/importgraph" "golang.org/x/tools/refactor/importgraph"
) )
// TODO(adonovan): use golang.org/x/tools/refactor/importgraph to choose
// the scope automatically.
// Referrers reports all identifiers that resolve to the same object // Referrers reports all identifiers that resolve to the same object
// as the queried identifier, within any package in the analysis scope. // as the queried identifier, within any package in the analysis scope.
func referrers(q *Query) error { func referrers(q *Query) error {
@ -57,20 +54,26 @@ func referrers(q *Query) error {
obj = qpos.info.ObjectOf(id) obj = qpos.info.ObjectOf(id)
if obj == nil { if obj == nil {
// Happens for y in "switch y := x.(type)", but I think that's all. // Happens for y in "switch y := x.(type)",
return fmt.Errorf("no object for identifier") // the package declaration,
// and unresolved identifiers.
if _, ok := qpos.path[1].(*ast.File); ok { // package decl?
pkg := qpos.info.Pkg
obj = types.NewPkgName(id.Pos(), pkg, pkg.Name(), pkg)
} else {
return fmt.Errorf("no object for identifier: %T", qpos.path[1])
}
}
if pass2 {
break
} }
// If the identifier is exported, we must load all packages that // If the identifier is exported, we must load all packages that
// depend transitively upon the package that defines it. // depend transitively upon the package that defines it.
// // Treat PkgNames as exported, even though they're lowercase.
// TODO(adonovan): we should do this for PkgName objects if _, isPkg := obj.(*types.PkgName); !(isPkg || obj.Exported()) {
// too, even though they're lowercase. break // not exported
//
// TODO(adonovan): opt: skip this step if obj.Pkg() is a test or
// main package.
if pass2 || !obj.Exported() {
break
} }
// Scan the workspace and build the import graph. // Scan the workspace and build the import graph.

View File

@ -22,10 +22,10 @@
"testdata/src/imports/main.go:22:9", "testdata/src/imports/main.go:22:9",
"testdata/src/referrers-json/main.go:15:8", "testdata/src/referrers-json/main.go:15:8",
"testdata/src/referrers-json/main.go:16:8", "testdata/src/referrers-json/main.go:16:8",
"testdata/src/referrers/ext_test.go:7:17", "testdata/src/referrers/ext_test.go:10:17",
"testdata/src/referrers/int_test.go:7:17", "testdata/src/referrers/int_test.go:7:17",
"testdata/src/referrers/main.go:15:8", "testdata/src/referrers/main.go:17:8",
"testdata/src/referrers/main.go:16:8" "testdata/src/referrers/main.go:18:8"
] ]
} }
} }

View File

@ -1,8 +1,12 @@
package main_test package main_test
import "lib" import (
"lib"
renamed "referrers" // package has name "main", path "referrers", local name "renamed"
)
func _() { func _() {
// This reference should be found by the ref-method query. // This reference should be found by the ref-method query.
_ = (lib.Type).Method // ref from external test package _ = (lib.Type).Method // ref from external test package
var _ renamed.T
} }

View File

@ -1,4 +1,4 @@
package main package main // @referrers package-decl "main"
// Tests of 'referrers' query. // Tests of 'referrers' query.
// See go.tools/oracle/oracle_test.go for explanation. // See go.tools/oracle/oracle_test.go for explanation.
@ -6,10 +6,12 @@ package main
import "lib" import "lib"
type s struct { // @referrers ref-type " s " type s struct { // @referrers type " s "
f int f int
} }
type T int
func main() { func main() {
var v lib.Type = lib.Const // @referrers ref-package "lib" var v lib.Type = lib.Const // @referrers ref-package "lib"
_ = v.Method // @referrers ref-method "Method" _ = v.Method // @referrers ref-method "Method"

View File

@ -1,10 +1,16 @@
-------- @referrers ref-type -------- -------- @referrers package-decl --------
1 references to package main ("referrers")
var _ renamed.T
-------- @referrers type --------
2 references to type s struct{f int} 2 references to type s struct{f int}
_ = s{}.f // @referrers ref-field "f" _ = s{}.f // @referrers ref-field "f"
var s2 s var s2 s
-------- @referrers ref-package -------- -------- @referrers ref-package --------
2 references to package lib 4 references to package lib
_ = (lib.Type).Method // ref from external test package
_ = (lib.Type).Method // ref from internal test package
var v lib.Type = lib.Const // @referrers ref-package "lib" var v lib.Type = lib.Const // @referrers ref-package "lib"
var v lib.Type = lib.Const // @referrers ref-package "lib" var v lib.Type = lib.Const // @referrers ref-package "lib"