summaryrefslogtreecommitdiff
path: root/libgo/go/go/doc/exports.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/go/doc/exports.go')
-rw-r--r--libgo/go/go/doc/exports.go58
1 files changed, 40 insertions, 18 deletions
diff --git a/libgo/go/go/doc/exports.go b/libgo/go/go/doc/exports.go
index 819c030c9bf..671c622205b 100644
--- a/libgo/go/go/doc/exports.go
+++ b/libgo/go/go/doc/exports.go
@@ -79,18 +79,15 @@ func hasExportedName(list []*ast.Ident) bool {
return false
}
-// removeErrorField removes anonymous fields named "error" from an interface.
-// This is called when "error" has been determined to be a local name,
-// not the predeclared type.
-//
-func removeErrorField(ityp *ast.InterfaceType) {
+// removeAnonymousField removes anonymous fields named name from an interface.
+func removeAnonymousField(name string, ityp *ast.InterfaceType) {
list := ityp.Methods.List // we know that ityp.Methods != nil
j := 0
for _, field := range list {
keepField := true
if n := len(field.Names); n == 0 {
// anonymous field
- if fname, _ := baseTypeName(field.Type); fname == "error" {
+ if fname, _ := baseTypeName(field.Type); fname == name {
keepField = false
}
}
@@ -119,16 +116,25 @@ func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp
for _, field := range list {
keepField := false
if n := len(field.Names); n == 0 {
- // anonymous field
+ // anonymous field or embedded type or union element
fname := r.recordAnonymousField(parent, field.Type)
- if token.IsExported(fname) {
- keepField = true
- } else if ityp != nil && fname == "error" {
- // possibly the predeclared error interface; keep
- // it for now but remember this interface so that
- // it can be fixed if error is also defined locally
- keepField = true
- r.remember(ityp)
+ if fname != "" {
+ if token.IsExported(fname) {
+ keepField = true
+ } else if ityp != nil && predeclaredTypes[fname] {
+ // possibly an embedded predeclared type; keep it for now but
+ // remember this interface so that it can be fixed if name is also
+ // defined locally
+ keepField = true
+ r.remember(fname, ityp)
+ }
+ } else {
+ // If we're operating on an interface, assume that this is an embedded
+ // type or union element.
+ //
+ // TODO(rfindley): consider traversing into approximation/unions
+ // elements to see if they are entirely unexported.
+ keepField = ityp != nil
}
} else {
field.Names = filterIdentList(field.Names)
@@ -172,6 +178,17 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) {
// nothing to do
case *ast.ParenExpr:
r.filterType(nil, t.X)
+ case *ast.StarExpr: // possibly an embedded type literal
+ r.filterType(nil, t.X)
+ case *ast.UnaryExpr:
+ if t.Op == token.TILDE { // approximation element
+ r.filterType(nil, t.X)
+ }
+ case *ast.BinaryExpr:
+ if t.Op == token.OR { // union
+ r.filterType(nil, t.X)
+ r.filterType(nil, t.Y)
+ }
case *ast.ArrayType:
r.filterType(nil, t.Elt)
case *ast.StructType:
@@ -179,6 +196,7 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) {
t.Incomplete = true
}
case *ast.FuncType:
+ r.filterParamList(t.TypeParams)
r.filterParamList(t.Params)
r.filterParamList(t.Results)
case *ast.InterfaceType:
@@ -219,12 +237,16 @@ func (r *reader) filterSpec(spec ast.Spec) bool {
}
}
case *ast.TypeSpec:
+ // Don't filter type parameters here, by analogy with function parameters
+ // which are not filtered for top-level function declarations.
if name := s.Name.Name; token.IsExported(name) {
r.filterType(r.lookupType(s.Name.Name), s.Type)
return true
- } else if name == "error" {
- // special case: remember that error is declared locally
- r.errorDecl = true
+ } else if IsPredeclared(name) {
+ if r.shadowedPredecl == nil {
+ r.shadowedPredecl = make(map[string]bool)
+ }
+ r.shadowedPredecl[name] = true
}
}
return false