go.tools/go/types: provide package for imported methods
Fixes golang/go#5815. R=adonovan CC=golang-dev https://golang.org/cl/12048043
This commit is contained in:
parent
bb34185432
commit
90aa993096
|
|
@ -425,20 +425,23 @@ func (p *gcParser) parseMapType() Type {
|
|||
|
||||
// Name = identifier | "?" | QualifiedName .
|
||||
//
|
||||
// If materializePkg is set, a package is returned for fully qualified names.
|
||||
// That package may be a fake package (without name, scope, and not in the
|
||||
// p.imports map), created for the sole purpose of providing a package path
|
||||
// for QualifiedNames. Fake packages are created when the package id is not
|
||||
// found in the p.imports map; we cannot create a real package in that case
|
||||
// because we don't have a package name.
|
||||
// If materializePkg is set, the returned package is guaranteed to be set.
|
||||
// For fully qualified names, the returned package may be a fake package
|
||||
// (without name, scope, and not in the p.imports map), created for the
|
||||
// sole purpose of providing a package path. Fake packages are created
|
||||
// when the package id is not found in the p.imports map; in that case
|
||||
// we cannot create a real package because we don't have a package name.
|
||||
// For non-qualified names, the returned package is the imported package.
|
||||
//
|
||||
func (p *gcParser) parseName(materializePkg bool) (pkg *Package, name string) {
|
||||
switch p.tok {
|
||||
case scanner.Ident:
|
||||
pkg = p.imports[p.id]
|
||||
name = p.lit
|
||||
p.next()
|
||||
case '?':
|
||||
// anonymous
|
||||
pkg = p.imports[p.id]
|
||||
p.next()
|
||||
case '@':
|
||||
// exported name prefixed with package path
|
||||
|
|
@ -611,10 +614,6 @@ func (p *gcParser) parseInterfaceType() Type {
|
|||
// TODO(gri) Ideally, we should use a named type here instead of
|
||||
// typ, for less verbose printing of interface method signatures.
|
||||
sig.recv = NewVar(token.NoPos, pkg, "", typ)
|
||||
// TODO(gri): fix: pkg may be nil!
|
||||
if pkg == nil {
|
||||
pkg = p.imports[p.id]
|
||||
}
|
||||
m := NewFunc(token.NoPos, pkg, name, sig)
|
||||
if alt := mset.insert(m); alt != nil {
|
||||
p.errorf("multiple methods named %s.%s", alt.Pkg().name, alt.Name())
|
||||
|
|
@ -902,7 +901,7 @@ func (p *gcParser) parseMethodDecl() {
|
|||
base := typ.(*Named)
|
||||
|
||||
// parse method name, signature, and possibly inlined body
|
||||
pkg, name := p.parseName(true) // unexported method names in imports are qualified with their package.
|
||||
pkg, name := p.parseName(true)
|
||||
sig := p.parseFunc()
|
||||
sig.recv = recv
|
||||
|
||||
|
|
@ -910,10 +909,6 @@ func (p *gcParser) parseMethodDecl() {
|
|||
// and method exists already
|
||||
// TODO(gri) This is a quadratic algorithm - ok for now because method counts are small.
|
||||
if _, m := lookupMethod(base.methods, pkg, name); m == nil {
|
||||
// TODO(gri): fix: pkg may be nil.
|
||||
if pkg == nil {
|
||||
pkg = p.imports[p.id]
|
||||
}
|
||||
base.methods = append(base.methods, NewFunc(token.NoPos, pkg, name, sig))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,3 +79,25 @@ var (
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue5815(t *testing.T) {
|
||||
pkg, err := GcImport(make(map[string]*Package), "strings")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, obj := range pkg.scope.elems {
|
||||
if obj.Pkg() == nil {
|
||||
t.Errorf("no pkg for %s", obj)
|
||||
}
|
||||
if tname, _ := obj.(*TypeName); tname != nil {
|
||||
if named, _ := tname.typ.(*Named); named != nil {
|
||||
for _, m := range named.methods {
|
||||
if m.pkg == nil {
|
||||
t.Errorf("no pkg for %s", m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue