summaryrefslogtreecommitdiff
path: root/src/cmd/godoc/snippet.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/godoc/snippet.go')
-rwxr-xr-xsrc/cmd/godoc/snippet.go122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/cmd/godoc/snippet.go b/src/cmd/godoc/snippet.go
new file mode 100755
index 000000000..add85aacb
--- /dev/null
+++ b/src/cmd/godoc/snippet.go
@@ -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;
+}