diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
commit | 5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch) | |
tree | c0650497e988f47be9c6f2324fa692a52dea82e1 /src/cmd/godoc/snippet.go | |
parent | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff) | |
download | golang-5ff4c17907d5b19510a62e08fd8d3b11e62b431d.tar.gz |
Imported Upstream version 60upstream/60
Diffstat (limited to 'src/cmd/godoc/snippet.go')
-rwxr-xr-x | src/cmd/godoc/snippet.go | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/cmd/godoc/snippet.go b/src/cmd/godoc/snippet.go new file mode 100755 index 000000000..68e27d9a0 --- /dev/null +++ b/src/cmd/godoc/snippet.go @@ -0,0 +1,100 @@ +// 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/token" + "fmt" +) + +type Snippet struct { + Line int + Text string // HTML-escaped +} + +func newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet { + // TODO instead of pretty-printing the node, should use the original source instead + var buf1 bytes.Buffer + writeNode(&buf1, fset, decl) + // wrap text with <pre> tag + var buf2 bytes.Buffer + buf2.WriteString("<pre>") + FormatText(&buf2, buf1.Bytes(), -1, true, id.Name, nil) + buf2.WriteString("</pre>") + return &Snippet{fset.Position(id.Pos()).Line, buf2.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(fset *token.FileSet, 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.Pos(), d.Tok, d.Lparen, []ast.Spec{s}, d.Rparen} + + return newSnippet(fset, dd, id) +} + +func funcSnippet(fset *token.FileSet, 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(fset, 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(fset *token.FileSet, decl ast.Decl, id *ast.Ident) (s *Snippet) { + switch d := decl.(type) { + case *ast.GenDecl: + s = genSnippet(fset, d, id) + case *ast.FuncDecl: + s = funcSnippet(fset, d, id) + } + + // handle failure gracefully + if s == nil { + var buf bytes.Buffer + fmt.Fprintf(&buf, `<span class="alert">could not generate a snippet for <span class="highlight">%s</span></span>`, id.Name) + s = &Snippet{fset.Position(id.Pos()).Line, buf.String()} + } + return +} |