]> Cypherpunks repositories - gostls13.git/commitdiff
- don't associate factory methods to basic types (which have no explicit declarations)
authorRobert Griesemer <gri@golang.org>
Fri, 28 Aug 2009 18:39:25 +0000 (11:39 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 28 Aug 2009 18:39:25 +0000 (11:39 -0700)
- be more robust in the presence of absent type declarations

R=rsc
DELTA=81  (63 added, 14 deleted, 4 changed)
OCL=34033
CL=34036

src/pkg/go/doc/doc.go

index 21d086f89d230071b572182c5affec3e1f387ec3..2dc292be60ab44c141ee8f192e92fd6b2db09b49 100644 (file)
@@ -65,14 +65,26 @@ func (doc *docReader) addType(decl *ast.GenDecl) {
 }
 
 
-func baseTypeName(typ ast.Expr) string {
-       switch t := typ.(type) {
-       case *ast.Ident:
-               return string(t.Value);
-       case *ast.StarExpr:
-               return baseTypeName(t.X);
-       }
-       return "";
+var predeclaredTypes = map[string]int {
+               // basic types
+               "bool": 0,
+               "byte": 0,
+               "int8": 0,
+               "int16": 0,
+               "int32": 0,
+               "int64": 0,
+               "uint8": 0,
+               "uint16": 0,
+               "uint32": 0,
+               "uint64": 0,
+               "float32": 0,
+               "float64": 0,
+               "string": 0,
+               // convenience types
+               "int": 0,
+               "uint": 0,
+               "uintptr": 0,
+               "float": 0,
 }
 
 
@@ -80,6 +92,9 @@ func (doc *docReader) lookupTypeDoc(name string) *typeDoc {
        if name == "" {
                return nil;  // no type docs for anonymous types
        }
+       if _, found := predeclaredTypes[name]; found {
+               return nil;  // no type docs for prdeclared types
+       }
        if tdoc, found := doc.types[name]; found {
                return tdoc;
        }
@@ -90,6 +105,17 @@ func (doc *docReader) lookupTypeDoc(name string) *typeDoc {
 }
 
 
+func baseTypeName(typ ast.Expr) string {
+       switch t := typ.(type) {
+       case *ast.Ident:
+               return string(t.Value);
+       case *ast.StarExpr:
+               return baseTypeName(t.X);
+       }
+       return "";
+}
+
+
 func (doc *docReader) addFunc(fun *ast.FuncDecl) {
        name := fun.Name.Value;
 
@@ -98,7 +124,8 @@ func (doc *docReader) addFunc(fun *ast.FuncDecl) {
                // method
                typ := doc.lookupTypeDoc(baseTypeName(fun.Recv.Type));
                // typ should always be != nil since receiver base
-               // types must be named - be conservative and check
+               // types must be named and cannot be predeclared -
+               // be conservative and check
                if typ != nil {
                        typ.methods[name] = fun;
                        return;
@@ -113,7 +140,7 @@ func (doc *docReader) addFunc(fun *ast.FuncDecl) {
                        // exactly one (named or anonymous) result type
                        typ := doc.lookupTypeDoc(baseTypeName(res.Type));
                        if typ != nil {
-                               // named result type
+                               // named result type that is not predeclared
                                typ.factories[name] = fun;
                                return;
                        }
@@ -379,7 +406,7 @@ func (p sortTypeDoc) Less(i, j int) bool {
 // NOTE(rsc): This would appear not to be correct for type ( )
 // blocks, but the doc extractor above has split them into
 // individual declarations.
-func makeTypeDocs(m map[string] *typeDoc) []*TypeDoc {
+func (doc *docReader) makeTypeDocs(m map[string] *typeDoc) []*TypeDoc {
        d := make([]*TypeDoc, len(m));
        i := 0;
        for _, old := range m {
@@ -404,6 +431,26 @@ func makeTypeDocs(m map[string] *typeDoc) []*TypeDoc {
                        t.order = i;
                        d[i] = t;
                        i++;
+               } else {
+                       // no corresponding type declaration found - add any associated
+                       // factory functions to the top-level functions lists so they
+                       // are not lost (this should only happen for factory methods
+                       // returning a type that is imported via a "." import such
+                       // that the type name is not a qualified identifier, or if
+                       // the package file containing the type declaration is missing)
+                       for name, f := range old.factories {
+                               doc.funcs[name] = f;
+                       }
+                       // add any associated methods to the top-level functions
+                       // list so they are not lost, but only do it if they don't
+                       // have the same names as existing top-level functions
+                       // (this could happen if a package file containing the type
+                       // declaration is missing)
+                       for name, f := range old.methods {
+                               if _, found := doc.funcs[name]; !found {
+                                       doc.funcs[name] = f;
+                               }
+                       }
                }
        }
        d = d[0 : i];  // some types may have been ignored
@@ -449,7 +496,9 @@ func (doc *docReader) newDoc(pkgname, importpath, filepath string, filenames []s
        p.Doc = astComment(doc.doc);
        p.Consts = makeValueDocs(doc.values, token.CONST);
        p.Vars = makeValueDocs(doc.values, token.VAR);
-       p.Types = makeTypeDocs(doc.types);
+       // makeTypeDocs may extend the list of doc.funcs
+       // and thus should be called before makeFuncDocs
+       p.Types = doc.makeTypeDocs(doc.types);
        p.Funcs = makeFuncDocs(doc.funcs);
        p.Bugs = makeBugDocs(doc.bugs);
        return p;