Skip to content

Commit

Permalink
go/types, types2: implement Info.PkgNameOf
Browse files Browse the repository at this point in the history
For golang#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]>
  • Loading branch information
griesemer authored and gopherbot committed Nov 11, 2023
1 parent 3188758 commit 8da6405
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 0 deletions.
2 changes: 2 additions & 0 deletions api/next/62037.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pkg go/types, method (*Info) PkgNameOf(*ast.ImportSpec) *PkgName #62037
pkg go/types, method (Checker) PkgNameOf(*ast.ImportSpec) *PkgName #62037
17 changes: 17 additions & 0 deletions src/cmd/compile/internal/types2/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,23 @@ func (info *Info) ObjectOf(id *syntax.Name) Object {
return info.Uses[id]
}

// PkgNameOf returns the local package name defined by the import,
// or nil if not found.
//
// For dot-imports, the package name is ".".
//
// Precondition: the Defs and Implicts maps are populated.
func (info *Info) PkgNameOf(imp *syntax.ImportDecl) *PkgName {
var obj Object
if imp.LocalPkgName != nil {
obj = info.Defs[imp.LocalPkgName]
} else {
obj = info.Implicits[imp]
}
pkgname, _ := obj.(*PkgName)
return pkgname
}

// TypeAndValue reports the type and value (for constants)
// of the corresponding expression.
type TypeAndValue struct {
Expand Down
74 changes: 74 additions & 0 deletions src/cmd/compile/internal/types2/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,80 @@ func TestImplicitsInfo(t *testing.T) {
}
}

func TestPkgNameOf(t *testing.T) {
testenv.MustHaveGoBuild(t)

const src = `
package p
import (
. "os"
_ "io"
"math"
"path/filepath"
snort "sort"
)
// avoid imported and not used errors
var (
_ = Open // os.Open
_ = math.Sin
_ = filepath.Abs
_ = snort.Ints
)
`

var tests = []struct {
path string // path string enclosed in "'s
want string
}{
{`"os"`, "."},
{`"io"`, "_"},
{`"math"`, "math"},
{`"path/filepath"`, "filepath"},
{`"sort"`, "snort"},
}

f := mustParse(src)
info := Info{
Defs: make(map[*syntax.Name]Object),
Implicits: make(map[syntax.Node]Object),
}
var conf Config
conf.Importer = defaultImporter()
_, err := conf.Check("p", []*syntax.File{f}, &info)
if err != nil {
t.Fatal(err)
}

// map import paths to importDecl
imports := make(map[string]*syntax.ImportDecl)
for _, d := range f.DeclList {
if imp, _ := d.(*syntax.ImportDecl); imp != nil {
imports[imp.Path.Value] = imp
}
}

for _, test := range tests {
imp := imports[test.path]
if imp == nil {
t.Fatalf("invalid test case: import path %s not found", test.path)
}
got := info.PkgNameOf(imp)
if got == nil {
t.Fatalf("import %s: package name not found", test.path)
}
if got.Name() != test.want {
t.Errorf("import %s: got %s; want %s", test.path, got.Name(), test.want)
}
}

// test non-existing importDecl
if got := info.PkgNameOf(new(syntax.ImportDecl)); got != nil {
t.Errorf("got %s for non-existing import declaration", got.Name())
}
}

func predString(tv TypeAndValue) string {
var buf strings.Builder
pred := func(b bool, s string) {
Expand Down
17 changes: 17 additions & 0 deletions src/go/types/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,23 @@ func (info *Info) ObjectOf(id *ast.Ident) Object {
return info.Uses[id]
}

// PkgNameOf returns the local package name defined by the import,
// or nil if not found.
//
// For dot-imports, the package name is ".".
//
// Precondition: the Defs and Implicts maps are populated.
func (info *Info) PkgNameOf(imp *ast.ImportSpec) *PkgName {
var obj Object
if imp.Name != nil {
obj = info.Defs[imp.Name]
} else {
obj = info.Implicits[imp]
}
pkgname, _ := obj.(*PkgName)
return pkgname
}

// TypeAndValue reports the type and value (for constants)
// of the corresponding expression.
type TypeAndValue struct {
Expand Down
75 changes: 75 additions & 0 deletions src/go/types/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,81 @@ func TestImplicitsInfo(t *testing.T) {
}
}

func TestPkgNameOf(t *testing.T) {
testenv.MustHaveGoBuild(t)

const src = `
package p
import (
. "os"
_ "io"
"math"
"path/filepath"
snort "sort"
)
// avoid imported and not used errors
var (
_ = Open // os.Open
_ = math.Sin
_ = filepath.Abs
_ = snort.Ints
)
`

var tests = []struct {
path string // path string enclosed in "'s
want string
}{
{`"os"`, "."},
{`"io"`, "_"},
{`"math"`, "math"},
{`"path/filepath"`, "filepath"},
{`"sort"`, "snort"},
}

fset := token.NewFileSet()
f := mustParse(fset, src)
info := Info{
Defs: make(map[*ast.Ident]Object),
Implicits: make(map[ast.Node]Object),
}
var conf Config
conf.Importer = importer.Default()
_, err := conf.Check("p", fset, []*ast.File{f}, &info)
if err != nil {
t.Fatal(err)
}

// map import paths to importDecl
imports := make(map[string]*ast.ImportSpec)
for _, s := range f.Decls[0].(*ast.GenDecl).Specs {
if imp, _ := s.(*ast.ImportSpec); imp != nil {
imports[imp.Path.Value] = imp
}
}

for _, test := range tests {
imp := imports[test.path]
if imp == nil {
t.Fatalf("invalid test case: import path %s not found", test.path)
}
got := info.PkgNameOf(imp)
if got == nil {
t.Fatalf("import %s: package name not found", test.path)
}
if got.Name() != test.want {
t.Errorf("import %s: got %s; want %s", test.path, got.Name(), test.want)
}
}

// test non-existing importDecl
if got := info.PkgNameOf(new(ast.ImportSpec)); got != nil {
t.Errorf("got %s for non-existing import declaration", got.Name())
}
}

func predString(tv TypeAndValue) string {
var buf strings.Builder
pred := func(b bool, s string) {
Expand Down

0 comments on commit 8da6405

Please sign in to comment.