2009-10-26 16:47:56 -06:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-08 22:46:20 -07:00
|
|
|
func (s *snippetStyler) LineTag(line int) (text []uint8, tag printer.HTMLTag) {
|
2009-11-09 13:07:39 -07:00
|
|
|
return // no LineTag for snippets
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-08 22:46:20 -07:00
|
|
|
func (s *snippetStyler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) {
|
2009-10-26 16:47:56 -06:00
|
|
|
text = strings.Bytes(id.Value);
|
|
|
|
if s.highlight == id {
|
2009-11-09 13:07:39 -07:00
|
|
|
tag = printer.HTMLTag{"<span class=highlight>", "</span>"}
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
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 {
|
2009-11-09 13:07:39 -07:00
|
|
|
return s
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
case *ast.ValueSpec:
|
|
|
|
for _, n := range s.Names {
|
|
|
|
if n == id {
|
2009-11-09 13:07:39 -07:00
|
|
|
return s
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case *ast.TypeSpec:
|
|
|
|
if s.Name == id {
|
2009-11-09 13:07:39 -07:00
|
|
|
return s
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func genSnippet(d *ast.GenDecl, id *ast.Ident) *Snippet {
|
|
|
|
s := findSpec(d.Specs, id);
|
|
|
|
if s == nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
return nil // declaration doesn't contain id - exit gracefully
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 {
|
2009-11-09 13:07:39 -07:00
|
|
|
return nil // declaration doesn't contain id - exit gracefully
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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:
|
2009-11-09 13:07:39 -07:00
|
|
|
s = genSnippet(d, id)
|
2009-10-26 16:47:56 -06:00
|
|
|
case *ast.FuncDecl:
|
2009-11-09 13:07:39 -07:00
|
|
|
s = funcSnippet(d, id)
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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),
|
2009-11-09 13:07:39 -07:00
|
|
|
}
|
2009-10-26 16:47:56 -06:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|