mirror of
https://github.com/golang/go
synced 2024-11-20 09:54:45 -07:00
snippet generator for godoc search results
R=rsc http://go/go-review/1013014
This commit is contained in:
parent
d493964976
commit
57035a9041
122
src/cmd/godoc/snippet.go
Executable file
122
src/cmd/godoc/snippet.go
Executable file
@ -0,0 +1,122 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains the infrastructure to create a code
|
||||
// snippet for search results.
|
||||
//
|
||||
// Note: At the moment, this only creates HTML snippets.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes";
|
||||
"go/ast";
|
||||
"go/printer";
|
||||
"fmt";
|
||||
"strings";
|
||||
)
|
||||
|
||||
|
||||
type Snippet struct {
|
||||
Line int;
|
||||
Text string;
|
||||
}
|
||||
|
||||
|
||||
type snippetStyler struct {
|
||||
Styler; // defined in godoc.go
|
||||
highlight *ast.Ident; // identifier to highlight
|
||||
}
|
||||
|
||||
|
||||
func (s *snippetStyler) LineTag(line int) (text []uint8, tag printer.HtmlTag) {
|
||||
return; // no LineTag for snippets
|
||||
}
|
||||
|
||||
|
||||
func (s *snippetStyler) Ident(id *ast.Ident) (text []byte, tag printer.HtmlTag) {
|
||||
text = strings.Bytes(id.Value);
|
||||
if s.highlight == id {
|
||||
tag = printer.HtmlTag{"<span class=highlight>", "</span>"};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
func newSnippet(decl ast.Decl, id *ast.Ident) *Snippet {
|
||||
var buf bytes.Buffer;
|
||||
writeNode(&buf, decl, true, &snippetStyler{highlight: id});
|
||||
return &Snippet{id.Pos().Line, buf.String()};
|
||||
}
|
||||
|
||||
|
||||
func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec {
|
||||
for _, spec := range list {
|
||||
switch s := spec.(type) {
|
||||
case *ast.ImportSpec:
|
||||
if s.Name == id {
|
||||
return s;
|
||||
}
|
||||
case *ast.ValueSpec:
|
||||
for _, n := range s.Names {
|
||||
if n == id {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
case *ast.TypeSpec:
|
||||
if s.Name == id {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
func genSnippet(d *ast.GenDecl, id *ast.Ident) *Snippet {
|
||||
s := findSpec(d.Specs, id);
|
||||
if s == nil {
|
||||
return nil; // declaration doesn't contain id - exit gracefully
|
||||
}
|
||||
|
||||
// only use the spec containing the id for the snippet
|
||||
dd := &ast.GenDecl{d.Doc, d.Position, d.Tok, d.Lparen, []ast.Spec{s}, d.Rparen};
|
||||
|
||||
return newSnippet(dd, id);
|
||||
}
|
||||
|
||||
|
||||
func funcSnippet(d *ast.FuncDecl, id *ast.Ident) *Snippet {
|
||||
if d.Name != id {
|
||||
return nil; // declaration doesn't contain id - exit gracefully
|
||||
}
|
||||
|
||||
// only use the function signature for the snippet
|
||||
dd := &ast.FuncDecl{d.Doc, d.Recv, d.Name, d.Type, nil};
|
||||
|
||||
return newSnippet(dd, id);
|
||||
}
|
||||
|
||||
|
||||
// NewSnippet creates a text snippet from a declaration decl containing an
|
||||
// identifier id. Parts of the declaration not containing the identifier
|
||||
// may be removed for a more compact snippet.
|
||||
//
|
||||
func NewSnippet(decl ast.Decl, id *ast.Ident) (s *Snippet) {
|
||||
switch d := decl.(type) {
|
||||
case *ast.GenDecl:
|
||||
s = genSnippet(d, id);
|
||||
case *ast.FuncDecl:
|
||||
s = funcSnippet(d, id);
|
||||
}
|
||||
|
||||
// handle failure gracefully
|
||||
if s == nil {
|
||||
s = &Snippet{
|
||||
id.Pos().Line,
|
||||
fmt.Sprintf(`could not generate a snippet for <span class="highlight">%s</span>`, id.Value),
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
Loading…
Reference in New Issue
Block a user