From a9f55c4fa4523b12937b7347ac8a4314d6793560 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Fri, 24 Apr 2015 16:57:46 -0400 Subject: [PATCH] oracle: support "referrers" query on package declaration Added test. Change-Id: Id7d061b0f74959166b5631a3fde8da4000ffb8d2 Reviewed-on: https://go-review.googlesource.com/9326 Reviewed-by: David Crawshaw --- oracle/definition.go | 4 ++- oracle/referrers.go | 29 ++++++++++--------- .../testdata/src/referrers-json/main.golden | 6 ++-- oracle/testdata/src/referrers/ext_test.go | 6 +++- oracle/testdata/src/referrers/main.go | 6 ++-- oracle/testdata/src/referrers/main.golden | 10 +++++-- 6 files changed, 39 insertions(+), 22 deletions(-) diff --git a/oracle/definition.go b/oracle/definition.go index b569ba32..a0340c6a 100644 --- a/oracle/definition.go +++ b/oracle/definition.go @@ -46,7 +46,9 @@ func definition(q *Query) error { obj := qpos.info.ObjectOf(id) 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") } diff --git a/oracle/referrers.go b/oracle/referrers.go index b805ba2c..7383d1f4 100644 --- a/oracle/referrers.go +++ b/oracle/referrers.go @@ -18,9 +18,6 @@ import ( "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 // as the queried identifier, within any package in the analysis scope. func referrers(q *Query) error { @@ -57,20 +54,26 @@ func referrers(q *Query) error { obj = qpos.info.ObjectOf(id) if obj == nil { - // Happens for y in "switch y := x.(type)", but I think that's all. - return fmt.Errorf("no object for identifier") + // Happens for y in "switch y := x.(type)", + // 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 // depend transitively upon the package that defines it. - // - // TODO(adonovan): we should do this for PkgName objects - // too, even though they're lowercase. - // - // TODO(adonovan): opt: skip this step if obj.Pkg() is a test or - // main package. - if pass2 || !obj.Exported() { - break + // Treat PkgNames as exported, even though they're lowercase. + if _, isPkg := obj.(*types.PkgName); !(isPkg || obj.Exported()) { + break // not exported } // Scan the workspace and build the import graph. diff --git a/oracle/testdata/src/referrers-json/main.golden b/oracle/testdata/src/referrers-json/main.golden index 239620cc..47a2d01b 100644 --- a/oracle/testdata/src/referrers-json/main.golden +++ b/oracle/testdata/src/referrers-json/main.golden @@ -22,10 +22,10 @@ "testdata/src/imports/main.go:22:9", "testdata/src/referrers-json/main.go:15: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/main.go:15:8", - "testdata/src/referrers/main.go:16:8" + "testdata/src/referrers/main.go:17:8", + "testdata/src/referrers/main.go:18:8" ] } } diff --git a/oracle/testdata/src/referrers/ext_test.go b/oracle/testdata/src/referrers/ext_test.go index d507e805..35e3199a 100644 --- a/oracle/testdata/src/referrers/ext_test.go +++ b/oracle/testdata/src/referrers/ext_test.go @@ -1,8 +1,12 @@ package main_test -import "lib" +import ( + "lib" + renamed "referrers" // package has name "main", path "referrers", local name "renamed" +) func _() { // This reference should be found by the ref-method query. _ = (lib.Type).Method // ref from external test package + var _ renamed.T } diff --git a/oracle/testdata/src/referrers/main.go b/oracle/testdata/src/referrers/main.go index 968c1380..36cdb7a1 100644 --- a/oracle/testdata/src/referrers/main.go +++ b/oracle/testdata/src/referrers/main.go @@ -1,4 +1,4 @@ -package main +package main // @referrers package-decl "main" // Tests of 'referrers' query. // See go.tools/oracle/oracle_test.go for explanation. @@ -6,10 +6,12 @@ package main import "lib" -type s struct { // @referrers ref-type " s " +type s struct { // @referrers type " s " f int } +type T int + func main() { var v lib.Type = lib.Const // @referrers ref-package "lib" _ = v.Method // @referrers ref-method "Method" diff --git a/oracle/testdata/src/referrers/main.golden b/oracle/testdata/src/referrers/main.golden index 3e8629b7..1f04be5b 100644 --- a/oracle/testdata/src/referrers/main.golden +++ b/oracle/testdata/src/referrers/main.golden @@ -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} _ = s{}.f // @referrers ref-field "f" var s2 s -------- @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"