Skip to content

Commit 8da6405

Browse files
griesemergopherbot
authored andcommitted
go/types, types2: implement Info.PkgNameOf
For #62037. Change-Id: I354f6417232708278d3f2b2d5ea41ff48e08d6b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/541575 Reviewed-by: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> Run-TryBot: Robert Griesemer <[email protected]>
1 parent 3188758 commit 8da6405

File tree

5 files changed

+185
-0
lines changed

5 files changed

+185
-0
lines changed

api/next/62037.txt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pkg go/types, method (*Info) PkgNameOf(*ast.ImportSpec) *PkgName #62037
2+
pkg go/types, method (Checker) PkgNameOf(*ast.ImportSpec) *PkgName #62037

src/cmd/compile/internal/types2/api.go

+17
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,23 @@ func (info *Info) ObjectOf(id *syntax.Name) Object {
342342
return info.Uses[id]
343343
}
344344

345+
// PkgNameOf returns the local package name defined by the import,
346+
// or nil if not found.
347+
//
348+
// For dot-imports, the package name is ".".
349+
//
350+
// Precondition: the Defs and Implicts maps are populated.
351+
func (info *Info) PkgNameOf(imp *syntax.ImportDecl) *PkgName {
352+
var obj Object
353+
if imp.LocalPkgName != nil {
354+
obj = info.Defs[imp.LocalPkgName]
355+
} else {
356+
obj = info.Implicits[imp]
357+
}
358+
pkgname, _ := obj.(*PkgName)
359+
return pkgname
360+
}
361+
345362
// TypeAndValue reports the type and value (for constants)
346363
// of the corresponding expression.
347364
type TypeAndValue struct {

src/cmd/compile/internal/types2/api_test.go

+74
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,80 @@ func TestImplicitsInfo(t *testing.T) {
958958
}
959959
}
960960

961+
func TestPkgNameOf(t *testing.T) {
962+
testenv.MustHaveGoBuild(t)
963+
964+
const src = `
965+
package p
966+
967+
import (
968+
. "os"
969+
_ "io"
970+
"math"
971+
"path/filepath"
972+
snort "sort"
973+
)
974+
975+
// avoid imported and not used errors
976+
var (
977+
_ = Open // os.Open
978+
_ = math.Sin
979+
_ = filepath.Abs
980+
_ = snort.Ints
981+
)
982+
`
983+
984+
var tests = []struct {
985+
path string // path string enclosed in "'s
986+
want string
987+
}{
988+
{`"os"`, "."},
989+
{`"io"`, "_"},
990+
{`"math"`, "math"},
991+
{`"path/filepath"`, "filepath"},
992+
{`"sort"`, "snort"},
993+
}
994+
995+
f := mustParse(src)
996+
info := Info{
997+
Defs: make(map[*syntax.Name]Object),
998+
Implicits: make(map[syntax.Node]Object),
999+
}
1000+
var conf Config
1001+
conf.Importer = defaultImporter()
1002+
_, err := conf.Check("p", []*syntax.File{f}, &info)
1003+
if err != nil {
1004+
t.Fatal(err)
1005+
}
1006+
1007+
// map import paths to importDecl
1008+
imports := make(map[string]*syntax.ImportDecl)
1009+
for _, d := range f.DeclList {
1010+
if imp, _ := d.(*syntax.ImportDecl); imp != nil {
1011+
imports[imp.Path.Value] = imp
1012+
}
1013+
}
1014+
1015+
for _, test := range tests {
1016+
imp := imports[test.path]
1017+
if imp == nil {
1018+
t.Fatalf("invalid test case: import path %s not found", test.path)
1019+
}
1020+
got := info.PkgNameOf(imp)
1021+
if got == nil {
1022+
t.Fatalf("import %s: package name not found", test.path)
1023+
}
1024+
if got.Name() != test.want {
1025+
t.Errorf("import %s: got %s; want %s", test.path, got.Name(), test.want)
1026+
}
1027+
}
1028+
1029+
// test non-existing importDecl
1030+
if got := info.PkgNameOf(new(syntax.ImportDecl)); got != nil {
1031+
t.Errorf("got %s for non-existing import declaration", got.Name())
1032+
}
1033+
}
1034+
9611035
func predString(tv TypeAndValue) string {
9621036
var buf strings.Builder
9631037
pred := func(b bool, s string) {

src/go/types/api.go

+17
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,23 @@ func (info *Info) ObjectOf(id *ast.Ident) Object {
331331
return info.Uses[id]
332332
}
333333

334+
// PkgNameOf returns the local package name defined by the import,
335+
// or nil if not found.
336+
//
337+
// For dot-imports, the package name is ".".
338+
//
339+
// Precondition: the Defs and Implicts maps are populated.
340+
func (info *Info) PkgNameOf(imp *ast.ImportSpec) *PkgName {
341+
var obj Object
342+
if imp.Name != nil {
343+
obj = info.Defs[imp.Name]
344+
} else {
345+
obj = info.Implicits[imp]
346+
}
347+
pkgname, _ := obj.(*PkgName)
348+
return pkgname
349+
}
350+
334351
// TypeAndValue reports the type and value (for constants)
335352
// of the corresponding expression.
336353
type TypeAndValue struct {

src/go/types/api_test.go

+75
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,81 @@ func TestImplicitsInfo(t *testing.T) {
960960
}
961961
}
962962

963+
func TestPkgNameOf(t *testing.T) {
964+
testenv.MustHaveGoBuild(t)
965+
966+
const src = `
967+
package p
968+
969+
import (
970+
. "os"
971+
_ "io"
972+
"math"
973+
"path/filepath"
974+
snort "sort"
975+
)
976+
977+
// avoid imported and not used errors
978+
var (
979+
_ = Open // os.Open
980+
_ = math.Sin
981+
_ = filepath.Abs
982+
_ = snort.Ints
983+
)
984+
`
985+
986+
var tests = []struct {
987+
path string // path string enclosed in "'s
988+
want string
989+
}{
990+
{`"os"`, "."},
991+
{`"io"`, "_"},
992+
{`"math"`, "math"},
993+
{`"path/filepath"`, "filepath"},
994+
{`"sort"`, "snort"},
995+
}
996+
997+
fset := token.NewFileSet()
998+
f := mustParse(fset, src)
999+
info := Info{
1000+
Defs: make(map[*ast.Ident]Object),
1001+
Implicits: make(map[ast.Node]Object),
1002+
}
1003+
var conf Config
1004+
conf.Importer = importer.Default()
1005+
_, err := conf.Check("p", fset, []*ast.File{f}, &info)
1006+
if err != nil {
1007+
t.Fatal(err)
1008+
}
1009+
1010+
// map import paths to importDecl
1011+
imports := make(map[string]*ast.ImportSpec)
1012+
for _, s := range f.Decls[0].(*ast.GenDecl).Specs {
1013+
if imp, _ := s.(*ast.ImportSpec); imp != nil {
1014+
imports[imp.Path.Value] = imp
1015+
}
1016+
}
1017+
1018+
for _, test := range tests {
1019+
imp := imports[test.path]
1020+
if imp == nil {
1021+
t.Fatalf("invalid test case: import path %s not found", test.path)
1022+
}
1023+
got := info.PkgNameOf(imp)
1024+
if got == nil {
1025+
t.Fatalf("import %s: package name not found", test.path)
1026+
}
1027+
if got.Name() != test.want {
1028+
t.Errorf("import %s: got %s; want %s", test.path, got.Name(), test.want)
1029+
}
1030+
}
1031+
1032+
// test non-existing importDecl
1033+
if got := info.PkgNameOf(new(ast.ImportSpec)); got != nil {
1034+
t.Errorf("got %s for non-existing import declaration", got.Name())
1035+
}
1036+
}
1037+
9631038
func predString(tv TypeAndValue) string {
9641039
var buf strings.Builder
9651040
pred := func(b bool, s string) {

0 commit comments

Comments
 (0)