Commit 016d0d09 authored by Robert Griesemer's avatar Robert Griesemer

godoc: correctly categorize interface methods, performance tuning

- interface methods appeared under VarDecl in search results
  (long-standing TODO)

- don't walk parts of AST which contain no indexable material
  (minor performance tuning)

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6228047
parent 07612b8d
...@@ -148,7 +148,7 @@ func init() { ...@@ -148,7 +148,7 @@ func init() {
// sanity check: if nKinds is too large, the SpotInfo // sanity check: if nKinds is too large, the SpotInfo
// accessor functions may need to be updated // accessor functions may need to be updated
if nKinds > 8 { if nKinds > 8 {
panic("nKinds > 8") panic("internal error: nKinds > 8")
} }
} }
...@@ -457,12 +457,6 @@ func (x *Indexer) addSnippet(s *Snippet) int { ...@@ -457,12 +457,6 @@ func (x *Indexer) addSnippet(s *Snippet) int {
return index return index
} }
func (x *Indexer) visitComment(c *ast.CommentGroup) {
if c != nil {
ast.Walk(x, c)
}
}
func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) { func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) {
if id != nil { if id != nil {
lists, found := x.words[id.Name] lists, found := x.words[id.Name]
...@@ -486,20 +480,24 @@ func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) { ...@@ -486,20 +480,24 @@ func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) {
} }
} }
func (x *Indexer) visitSpec(spec ast.Spec, isVarDecl bool) { func (x *Indexer) visitFieldList(kind SpotKind, list *ast.FieldList) {
for _, f := range list.List {
x.decl = nil // no snippets for fields
for _, name := range f.Names {
x.visitIdent(kind, name)
}
ast.Walk(x, f.Type)
// ignore tag - not indexed at the moment
}
}
func (x *Indexer) visitSpec(kind SpotKind, spec ast.Spec) {
switch n := spec.(type) { switch n := spec.(type) {
case *ast.ImportSpec: case *ast.ImportSpec:
x.visitComment(n.Doc)
x.visitIdent(ImportDecl, n.Name) x.visitIdent(ImportDecl, n.Name)
ast.Walk(x, n.Path) // ignore path - not indexed at the moment
x.visitComment(n.Comment)
case *ast.ValueSpec: case *ast.ValueSpec:
x.visitComment(n.Doc)
kind := ConstDecl
if isVarDecl {
kind = VarDecl
}
for _, n := range n.Names { for _, n := range n.Names {
x.visitIdent(kind, n) x.visitIdent(kind, n)
} }
...@@ -507,57 +505,51 @@ func (x *Indexer) visitSpec(spec ast.Spec, isVarDecl bool) { ...@@ -507,57 +505,51 @@ func (x *Indexer) visitSpec(spec ast.Spec, isVarDecl bool) {
for _, v := range n.Values { for _, v := range n.Values {
ast.Walk(x, v) ast.Walk(x, v)
} }
x.visitComment(n.Comment)
case *ast.TypeSpec: case *ast.TypeSpec:
x.visitComment(n.Doc)
x.visitIdent(TypeDecl, n.Name) x.visitIdent(TypeDecl, n.Name)
ast.Walk(x, n.Type) ast.Walk(x, n.Type)
x.visitComment(n.Comment) }
}
func (x *Indexer) visitGenDecl(decl *ast.GenDecl) {
kind := VarDecl
if decl.Tok == token.CONST {
kind = ConstDecl
}
x.decl = decl
for _, s := range decl.Specs {
x.visitSpec(kind, s)
} }
} }
func (x *Indexer) Visit(node ast.Node) ast.Visitor { func (x *Indexer) Visit(node ast.Node) ast.Visitor {
// TODO(gri): methods in interface types are categorized as VarDecl
switch n := node.(type) { switch n := node.(type) {
case nil: case nil:
return nil // nothing to do
case *ast.Ident: case *ast.Ident:
x.visitIdent(Use, n) x.visitIdent(Use, n)
case *ast.Field: case *ast.FieldList:
x.decl = nil // no snippets for fields x.visitFieldList(VarDecl, n)
x.visitComment(n.Doc)
for _, m := range n.Names { case *ast.InterfaceType:
x.visitIdent(VarDecl, m) x.visitFieldList(MethodDecl, n.Methods)
}
ast.Walk(x, n.Type)
ast.Walk(x, n.Tag)
x.visitComment(n.Comment)
case *ast.DeclStmt: case *ast.DeclStmt:
// local declarations should only be *ast.GenDecls;
// ignore incorrect ASTs
if decl, ok := n.Decl.(*ast.GenDecl); ok { if decl, ok := n.Decl.(*ast.GenDecl); ok {
// local declarations can only be *ast.GenDecls
x.decl = nil // no snippets for local declarations x.decl = nil // no snippets for local declarations
x.visitComment(decl.Doc) x.visitGenDecl(decl)
for _, s := range decl.Specs {
x.visitSpec(s, decl.Tok == token.VAR)
}
} else {
// handle error case gracefully
ast.Walk(x, n.Decl)
} }
case *ast.GenDecl: case *ast.GenDecl:
x.decl = n x.decl = n
x.visitComment(n.Doc) x.visitGenDecl(n)
for _, s := range n.Specs {
x.visitSpec(s, n.Tok == token.VAR)
}
case *ast.FuncDecl: case *ast.FuncDecl:
x.visitComment(n.Doc)
kind := FuncDecl kind := FuncDecl
if n.Recv != nil { if n.Recv != nil {
kind = MethodDecl kind = MethodDecl
...@@ -571,15 +563,11 @@ func (x *Indexer) Visit(node ast.Node) ast.Visitor { ...@@ -571,15 +563,11 @@ func (x *Indexer) Visit(node ast.Node) ast.Visitor {
} }
case *ast.File: case *ast.File:
x.visitComment(n.Doc)
x.decl = nil x.decl = nil
x.visitIdent(PackageClause, n.Name) x.visitIdent(PackageClause, n.Name)
for _, d := range n.Decls { for _, d := range n.Decls {
ast.Walk(x, d) ast.Walk(x, d)
} }
// don't visit package level comments for now
// to avoid duplicate visiting from individual
// nodes
default: default:
return x return x
...@@ -622,7 +610,7 @@ func (x *Indexer) addFile(filename string, goFile bool) (file *token.File, ast * ...@@ -622,7 +610,7 @@ func (x *Indexer) addFile(filename string, goFile bool) (file *token.File, ast *
// the file set implementation changed or we have another error. // the file set implementation changed or we have another error.
base := x.fset.Base() base := x.fset.Base()
if x.sources.Len() != base { if x.sources.Len() != base {
panic("internal error - file base incorrect") panic("internal error: file base incorrect")
} }
// append file contents (src) to x.sources // append file contents (src) to x.sources
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment