mirror of
https://github.com/golang/go
synced 2024-11-22 11:24:49 -07:00
associate const and var declarations with a type where possible
R=rsc DELTA=105 (87 added, 7 deleted, 11 changed) OCL=34062 CL=34119
This commit is contained in:
parent
c62b9d8f2a
commit
3dc7b382f9
@ -48,6 +48,14 @@
|
|||||||
<h2>type <a href="{Decl|link}">{Type.Name|html}</a></h2>
|
<h2>type <a href="{Decl|link}">{Type.Name|html}</a></h2>
|
||||||
{Doc|html-comment}
|
{Doc|html-comment}
|
||||||
<p><pre>{Decl|html}</pre></p>
|
<p><pre>{Decl|html}</pre></p>
|
||||||
|
{.repeated section Consts}
|
||||||
|
{Doc|html-comment}
|
||||||
|
<pre>{Decl|html}</pre>
|
||||||
|
{.end}
|
||||||
|
{.repeated section Vars}
|
||||||
|
{Doc|html-comment}
|
||||||
|
<pre>{Decl|html}</pre>
|
||||||
|
{.end}
|
||||||
{.repeated section Factories}
|
{.repeated section Factories}
|
||||||
<h3>func <a href="{Decl|link}">{Name|html}</a></h3>
|
<h3>func <a href="{Decl|link}">{Name|html}</a></h3>
|
||||||
<p><code>{Decl|html}</code></p>
|
<p><code>{Decl|html}</code></p>
|
||||||
|
@ -48,6 +48,14 @@ TYPES
|
|||||||
{.repeated section @}
|
{.repeated section @}
|
||||||
{Decl}
|
{Decl}
|
||||||
{Doc}
|
{Doc}
|
||||||
|
{.repeated section Consts}
|
||||||
|
{Decl}
|
||||||
|
{Doc}
|
||||||
|
{.end}
|
||||||
|
{.repeated section Vars}
|
||||||
|
{Decl}
|
||||||
|
{Doc}
|
||||||
|
{.end}
|
||||||
{.repeated section Factories}
|
{.repeated section Factories}
|
||||||
{Decl}
|
{Decl}
|
||||||
{Doc}
|
{Doc}
|
||||||
|
@ -22,7 +22,8 @@ type typeDoc struct {
|
|||||||
// len(decl.Specs) == 1, and the element type is *ast.TypeSpec
|
// len(decl.Specs) == 1, and the element type is *ast.TypeSpec
|
||||||
// if the type declaration hasn't been seen yet, decl is nil
|
// if the type declaration hasn't been seen yet, decl is nil
|
||||||
decl *ast.GenDecl;
|
decl *ast.GenDecl;
|
||||||
// factory functions and methods associated with the type
|
// values, factory functions, and methods associated with the type
|
||||||
|
values *vector.Vector; // list of *ast.GenDecl (consts and vars)
|
||||||
factories map[string] *ast.FuncDecl;
|
factories map[string] *ast.FuncDecl;
|
||||||
methods map[string] *ast.FuncDecl;
|
methods map[string] *ast.FuncDecl;
|
||||||
}
|
}
|
||||||
@ -93,13 +94,13 @@ func (doc *docReader) lookupTypeDoc(name string) *typeDoc {
|
|||||||
return nil; // no type docs for anonymous types
|
return nil; // no type docs for anonymous types
|
||||||
}
|
}
|
||||||
if _, found := predeclaredTypes[name]; found {
|
if _, found := predeclaredTypes[name]; found {
|
||||||
return nil; // no type docs for prdeclared types
|
return nil; // no type docs for predeclared types
|
||||||
}
|
}
|
||||||
if tdoc, found := doc.types[name]; found {
|
if tdoc, found := doc.types[name]; found {
|
||||||
return tdoc;
|
return tdoc;
|
||||||
}
|
}
|
||||||
// type wasn't found - add one without declaration
|
// type wasn't found - add one without declaration
|
||||||
tdoc := &typeDoc{nil, make(map[string] *ast.FuncDecl), make(map[string] *ast.FuncDecl)};
|
tdoc := &typeDoc{nil, vector.New(0), make(map[string] *ast.FuncDecl), make(map[string] *ast.FuncDecl)};
|
||||||
doc.types[name] = tdoc;
|
doc.types[name] = tdoc;
|
||||||
return tdoc;
|
return tdoc;
|
||||||
}
|
}
|
||||||
@ -116,6 +117,64 @@ func baseTypeName(typ ast.Expr) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (doc *docReader) addValue(decl *ast.GenDecl) {
|
||||||
|
// determine if decl should be associated with a type
|
||||||
|
// Heuristic: Collect all types and determine the most frequent type.
|
||||||
|
// If it is "dominant enough" the decl is associated with
|
||||||
|
// that type.
|
||||||
|
|
||||||
|
// determine type frequencies
|
||||||
|
freq := make(map[string]int);
|
||||||
|
prev := "";
|
||||||
|
for _, s := range decl.Specs {
|
||||||
|
if v, ok := s.(*ast.ValueSpec); ok {
|
||||||
|
name := "";
|
||||||
|
switch {
|
||||||
|
case v.Type != nil:
|
||||||
|
// a type is present; determine it's name
|
||||||
|
name = baseTypeName(v.Type);
|
||||||
|
case decl.Tok == token.CONST:
|
||||||
|
// no type is present but we have a constant declaration;
|
||||||
|
// use the previous type name (w/o more type information
|
||||||
|
// we cannot handle the case of unnamed variables with
|
||||||
|
// initializer expressions except for some trivial cases)
|
||||||
|
name = prev;
|
||||||
|
}
|
||||||
|
if name != "" {
|
||||||
|
// increase freq count for name
|
||||||
|
f := 0;
|
||||||
|
if f0, found := freq[name]; found {
|
||||||
|
f = f0;
|
||||||
|
}
|
||||||
|
freq[name] = f+1;
|
||||||
|
}
|
||||||
|
prev = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine most common type
|
||||||
|
domName, domFreq := "", 0;
|
||||||
|
for name, f := range freq {
|
||||||
|
if f > domFreq {
|
||||||
|
domName, domFreq = name, f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine values list
|
||||||
|
const threshold = 0.75;
|
||||||
|
values := doc.values;
|
||||||
|
if domFreq >= int(float(len(decl.Specs)) * threshold) {
|
||||||
|
// most common type is "dominant enough"
|
||||||
|
typ := doc.lookupTypeDoc(domName);
|
||||||
|
if typ != nil {
|
||||||
|
values = typ.values; // associate with that type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
values.Push(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (doc *docReader) addFunc(fun *ast.FuncDecl) {
|
func (doc *docReader) addFunc(fun *ast.FuncDecl) {
|
||||||
name := fun.Name.Value;
|
name := fun.Name.Value;
|
||||||
|
|
||||||
@ -160,7 +219,7 @@ func (doc *docReader) addDecl(decl ast.Decl) {
|
|||||||
switch d.Tok {
|
switch d.Tok {
|
||||||
case token.CONST, token.VAR:
|
case token.CONST, token.VAR:
|
||||||
// constants and variables are always handled as a group
|
// constants and variables are always handled as a group
|
||||||
doc.values.Push(d);
|
doc.addValue(d);
|
||||||
case token.TYPE:
|
case token.TYPE:
|
||||||
// types are handled individually
|
// types are handled individually
|
||||||
var noPos token.Position;
|
var noPos token.Position;
|
||||||
@ -378,11 +437,14 @@ func makeFuncDocs(m map[string] *ast.FuncDecl) []*FuncDoc {
|
|||||||
|
|
||||||
|
|
||||||
// TypeDoc is the documentation for a declared type.
|
// TypeDoc is the documentation for a declared type.
|
||||||
|
// Consts and Vars are sorted lists of constants and variables of (mostly) that type.
|
||||||
// Factories is a sorted list of factory functions that return that type.
|
// Factories is a sorted list of factory functions that return that type.
|
||||||
// Methods is a sorted list of method functions on that type.
|
// Methods is a sorted list of method functions on that type.
|
||||||
type TypeDoc struct {
|
type TypeDoc struct {
|
||||||
Doc string;
|
Doc string;
|
||||||
Type *ast.TypeSpec;
|
Type *ast.TypeSpec;
|
||||||
|
Consts []*ValueDoc;
|
||||||
|
Vars []*ValueDoc;
|
||||||
Factories []*FuncDoc;
|
Factories []*FuncDoc;
|
||||||
Methods []*FuncDoc;
|
Methods []*FuncDoc;
|
||||||
Decl *ast.GenDecl;
|
Decl *ast.GenDecl;
|
||||||
@ -425,6 +487,8 @@ func (doc *docReader) makeTypeDocs(m map[string] *typeDoc) []*TypeDoc {
|
|||||||
decl.Doc = nil; // doc consumed - remove from ast.Decl node
|
decl.Doc = nil; // doc consumed - remove from ast.Decl node
|
||||||
t.Doc = astComment(doc);
|
t.Doc = astComment(doc);
|
||||||
t.Type = typespec;
|
t.Type = typespec;
|
||||||
|
t.Consts = makeValueDocs(old.values, token.CONST);
|
||||||
|
t.Vars = makeValueDocs(old.values, token.VAR);
|
||||||
t.Factories = makeFuncDocs(old.factories);
|
t.Factories = makeFuncDocs(old.factories);
|
||||||
t.Methods = makeFuncDocs(old.methods);
|
t.Methods = makeFuncDocs(old.methods);
|
||||||
t.Decl = old.decl;
|
t.Decl = old.decl;
|
||||||
@ -432,21 +496,20 @@ func (doc *docReader) makeTypeDocs(m map[string] *typeDoc) []*TypeDoc {
|
|||||||
d[i] = t;
|
d[i] = t;
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
// no corresponding type declaration found - add any associated
|
// no corresponding type declaration found - move any associated
|
||||||
// factory functions to the top-level functions lists so they
|
// values, factory functions, and methods back to the top-level
|
||||||
// are not lost (this should only happen for factory methods
|
// so that they are not lost (this should only happen if a package
|
||||||
// returning a type that is imported via a "." import such
|
// file containing the explicit type declaration is missing or if
|
||||||
// that the type name is not a qualified identifier, or if
|
// an unqualified type name was used after a "." import)
|
||||||
// the package file containing the type declaration is missing)
|
// 1) move values
|
||||||
|
doc.values.AppendVector(old.values);
|
||||||
|
// 2) move factory functions
|
||||||
for name, f := range old.factories {
|
for name, f := range old.factories {
|
||||||
doc.funcs[name] = f;
|
doc.funcs[name] = f;
|
||||||
}
|
}
|
||||||
// add any associated methods to the top-level functions
|
// 3) move methods
|
||||||
// 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 {
|
for name, f := range old.methods {
|
||||||
|
// don't overwrite functions with the same name
|
||||||
if _, found := doc.funcs[name]; !found {
|
if _, found := doc.funcs[name]; !found {
|
||||||
doc.funcs[name] = f;
|
doc.funcs[name] = f;
|
||||||
}
|
}
|
||||||
@ -494,11 +557,12 @@ func (doc *docReader) newDoc(pkgname, importpath, filepath string, filenames []s
|
|||||||
sort.SortStrings(filenames);
|
sort.SortStrings(filenames);
|
||||||
p.Filenames = filenames;
|
p.Filenames = filenames;
|
||||||
p.Doc = astComment(doc.doc);
|
p.Doc = astComment(doc.doc);
|
||||||
|
// makeTypeDocs may extend the list of doc.values and
|
||||||
|
// doc.funcs and thus must be called before any other
|
||||||
|
// function consuming those lists
|
||||||
|
p.Types = doc.makeTypeDocs(doc.types);
|
||||||
p.Consts = makeValueDocs(doc.values, token.CONST);
|
p.Consts = makeValueDocs(doc.values, token.CONST);
|
||||||
p.Vars = makeValueDocs(doc.values, token.VAR);
|
p.Vars = makeValueDocs(doc.values, token.VAR);
|
||||||
// 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.Funcs = makeFuncDocs(doc.funcs);
|
||||||
p.Bugs = makeBugDocs(doc.bugs);
|
p.Bugs = makeBugDocs(doc.bugs);
|
||||||
return p;
|
return p;
|
||||||
|
Loading…
Reference in New Issue
Block a user