Major rewrite
* use dep for vendoring * lets encrypt * moved web to transfer.sh-web repo * single command install * added first tests
This commit is contained in:
359
vendor/github.com/golang/gddo/doc/code.go
generated
vendored
Normal file
359
vendor/github.com/golang/gddo/doc/code.go
generated
vendored
Normal file
@@ -0,0 +1,359 @@
|
||||
// Copyright 2013 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 or at
|
||||
// https://developers.google.com/open-source/licenses/bsd.
|
||||
|
||||
package doc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/doc"
|
||||
"go/printer"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
notPredeclared = iota
|
||||
predeclaredType
|
||||
predeclaredConstant
|
||||
predeclaredFunction
|
||||
)
|
||||
|
||||
// predeclared represents the set of all predeclared identifiers.
|
||||
var predeclared = map[string]int{
|
||||
"bool": predeclaredType,
|
||||
"byte": predeclaredType,
|
||||
"complex128": predeclaredType,
|
||||
"complex64": predeclaredType,
|
||||
"error": predeclaredType,
|
||||
"float32": predeclaredType,
|
||||
"float64": predeclaredType,
|
||||
"int16": predeclaredType,
|
||||
"int32": predeclaredType,
|
||||
"int64": predeclaredType,
|
||||
"int8": predeclaredType,
|
||||
"int": predeclaredType,
|
||||
"rune": predeclaredType,
|
||||
"string": predeclaredType,
|
||||
"uint16": predeclaredType,
|
||||
"uint32": predeclaredType,
|
||||
"uint64": predeclaredType,
|
||||
"uint8": predeclaredType,
|
||||
"uint": predeclaredType,
|
||||
"uintptr": predeclaredType,
|
||||
|
||||
"true": predeclaredConstant,
|
||||
"false": predeclaredConstant,
|
||||
"iota": predeclaredConstant,
|
||||
"nil": predeclaredConstant,
|
||||
|
||||
"append": predeclaredFunction,
|
||||
"cap": predeclaredFunction,
|
||||
"close": predeclaredFunction,
|
||||
"complex": predeclaredFunction,
|
||||
"copy": predeclaredFunction,
|
||||
"delete": predeclaredFunction,
|
||||
"imag": predeclaredFunction,
|
||||
"len": predeclaredFunction,
|
||||
"make": predeclaredFunction,
|
||||
"new": predeclaredFunction,
|
||||
"panic": predeclaredFunction,
|
||||
"print": predeclaredFunction,
|
||||
"println": predeclaredFunction,
|
||||
"real": predeclaredFunction,
|
||||
"recover": predeclaredFunction,
|
||||
}
|
||||
|
||||
type AnnotationKind int16
|
||||
|
||||
const (
|
||||
// Link to export in package specified by Paths[PathIndex] with fragment
|
||||
// Text[strings.LastIndex(Text[Pos:End], ".")+1:End].
|
||||
LinkAnnotation AnnotationKind = iota
|
||||
|
||||
// Anchor with name specified by Text[Pos:End] or typeName + "." +
|
||||
// Text[Pos:End] for type declarations.
|
||||
AnchorAnnotation
|
||||
|
||||
// Comment.
|
||||
CommentAnnotation
|
||||
|
||||
// Link to package specified by Paths[PathIndex].
|
||||
PackageLinkAnnotation
|
||||
|
||||
// Link to builtin entity with name Text[Pos:End].
|
||||
BuiltinAnnotation
|
||||
)
|
||||
|
||||
type Annotation struct {
|
||||
Pos, End int32
|
||||
Kind AnnotationKind
|
||||
PathIndex int16
|
||||
}
|
||||
|
||||
type Code struct {
|
||||
Text string
|
||||
Annotations []Annotation
|
||||
Paths []string
|
||||
}
|
||||
|
||||
// declVisitor modifies a declaration AST for printing and collects annotations.
|
||||
type declVisitor struct {
|
||||
annotations []Annotation
|
||||
paths []string
|
||||
pathIndex map[string]int
|
||||
comments []*ast.CommentGroup
|
||||
}
|
||||
|
||||
func (v *declVisitor) add(kind AnnotationKind, importPath string) {
|
||||
pathIndex := -1
|
||||
if importPath != "" {
|
||||
var ok bool
|
||||
pathIndex, ok = v.pathIndex[importPath]
|
||||
if !ok {
|
||||
pathIndex = len(v.paths)
|
||||
v.paths = append(v.paths, importPath)
|
||||
v.pathIndex[importPath] = pathIndex
|
||||
}
|
||||
}
|
||||
v.annotations = append(v.annotations, Annotation{Kind: kind, PathIndex: int16(pathIndex)})
|
||||
}
|
||||
|
||||
func (v *declVisitor) ignoreName() {
|
||||
v.add(-1, "")
|
||||
}
|
||||
|
||||
func (v *declVisitor) Visit(n ast.Node) ast.Visitor {
|
||||
switch n := n.(type) {
|
||||
case *ast.TypeSpec:
|
||||
v.ignoreName()
|
||||
switch n := n.Type.(type) {
|
||||
case *ast.InterfaceType:
|
||||
for _, f := range n.Methods.List {
|
||||
for _ = range f.Names {
|
||||
v.add(AnchorAnnotation, "")
|
||||
}
|
||||
ast.Walk(v, f.Type)
|
||||
}
|
||||
case *ast.StructType:
|
||||
for _, f := range n.Fields.List {
|
||||
for _ = range f.Names {
|
||||
v.add(AnchorAnnotation, "")
|
||||
}
|
||||
ast.Walk(v, f.Type)
|
||||
}
|
||||
default:
|
||||
ast.Walk(v, n)
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
if n.Recv != nil {
|
||||
ast.Walk(v, n.Recv)
|
||||
}
|
||||
v.ignoreName()
|
||||
ast.Walk(v, n.Type)
|
||||
case *ast.Field:
|
||||
for _ = range n.Names {
|
||||
v.ignoreName()
|
||||
}
|
||||
ast.Walk(v, n.Type)
|
||||
case *ast.ValueSpec:
|
||||
for _ = range n.Names {
|
||||
v.add(AnchorAnnotation, "")
|
||||
}
|
||||
if n.Type != nil {
|
||||
ast.Walk(v, n.Type)
|
||||
}
|
||||
for _, x := range n.Values {
|
||||
ast.Walk(v, x)
|
||||
}
|
||||
case *ast.Ident:
|
||||
switch {
|
||||
case n.Obj == nil && predeclared[n.Name] != notPredeclared:
|
||||
v.add(BuiltinAnnotation, "")
|
||||
case n.Obj != nil && ast.IsExported(n.Name):
|
||||
v.add(LinkAnnotation, "")
|
||||
default:
|
||||
v.ignoreName()
|
||||
}
|
||||
case *ast.SelectorExpr:
|
||||
if x, _ := n.X.(*ast.Ident); x != nil {
|
||||
if obj := x.Obj; obj != nil && obj.Kind == ast.Pkg {
|
||||
if spec, _ := obj.Decl.(*ast.ImportSpec); spec != nil {
|
||||
if path, err := strconv.Unquote(spec.Path.Value); err == nil {
|
||||
v.add(PackageLinkAnnotation, path)
|
||||
if path == "C" {
|
||||
v.ignoreName()
|
||||
} else {
|
||||
v.add(LinkAnnotation, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.Walk(v, n.X)
|
||||
v.ignoreName()
|
||||
case *ast.BasicLit:
|
||||
if n.Kind == token.STRING && len(n.Value) > 128 {
|
||||
v.comments = append(v.comments,
|
||||
&ast.CommentGroup{List: []*ast.Comment{{
|
||||
Slash: n.Pos(),
|
||||
Text: fmt.Sprintf("/* %d byte string literal not displayed */", len(n.Value)),
|
||||
}}})
|
||||
n.Value = `""`
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
case *ast.CompositeLit:
|
||||
if len(n.Elts) > 100 {
|
||||
if n.Type != nil {
|
||||
ast.Walk(v, n.Type)
|
||||
}
|
||||
v.comments = append(v.comments,
|
||||
&ast.CommentGroup{List: []*ast.Comment{{
|
||||
Slash: n.Lbrace,
|
||||
Text: fmt.Sprintf("/* %d elements not displayed */", len(n.Elts)),
|
||||
}}})
|
||||
n.Elts = n.Elts[:0]
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
default:
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *builder) printDecl(decl ast.Decl) (d Code) {
|
||||
v := &declVisitor{pathIndex: make(map[string]int)}
|
||||
ast.Walk(v, decl)
|
||||
b.buf = b.buf[:0]
|
||||
err := (&printer.Config{Mode: printer.UseSpaces, Tabwidth: 4}).Fprint(
|
||||
sliceWriter{&b.buf},
|
||||
b.fset,
|
||||
&printer.CommentedNode{Node: decl, Comments: v.comments})
|
||||
if err != nil {
|
||||
return Code{Text: err.Error()}
|
||||
}
|
||||
|
||||
var annotations []Annotation
|
||||
var s scanner.Scanner
|
||||
fset := token.NewFileSet()
|
||||
file := fset.AddFile("", fset.Base(), len(b.buf))
|
||||
s.Init(file, b.buf, nil, scanner.ScanComments)
|
||||
prevTok := token.ILLEGAL
|
||||
loop:
|
||||
for {
|
||||
pos, tok, lit := s.Scan()
|
||||
switch tok {
|
||||
case token.EOF:
|
||||
break loop
|
||||
case token.COMMENT:
|
||||
p := file.Offset(pos)
|
||||
e := p + len(lit)
|
||||
if prevTok == token.COMMENT {
|
||||
annotations[len(annotations)-1].End = int32(e)
|
||||
} else {
|
||||
annotations = append(annotations, Annotation{Kind: CommentAnnotation, Pos: int32(p), End: int32(e)})
|
||||
}
|
||||
case token.IDENT:
|
||||
if len(v.annotations) == 0 {
|
||||
// Oops!
|
||||
break loop
|
||||
}
|
||||
annotation := v.annotations[0]
|
||||
v.annotations = v.annotations[1:]
|
||||
if annotation.Kind == -1 {
|
||||
continue
|
||||
}
|
||||
p := file.Offset(pos)
|
||||
e := p + len(lit)
|
||||
annotation.Pos = int32(p)
|
||||
annotation.End = int32(e)
|
||||
annotations = append(annotations, annotation)
|
||||
}
|
||||
prevTok = tok
|
||||
}
|
||||
return Code{Text: string(b.buf), Annotations: annotations, Paths: v.paths}
|
||||
}
|
||||
|
||||
func (b *builder) position(n ast.Node) Pos {
|
||||
var position Pos
|
||||
pos := b.fset.Position(n.Pos())
|
||||
src := b.srcs[pos.Filename]
|
||||
if src != nil {
|
||||
position.File = int16(src.index)
|
||||
position.Line = int32(pos.Line)
|
||||
end := b.fset.Position(n.End())
|
||||
if src == b.srcs[end.Filename] {
|
||||
n := end.Line - pos.Line
|
||||
if n >= 0 && n <= math.MaxUint16 {
|
||||
position.N = uint16(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
return position
|
||||
}
|
||||
|
||||
func (b *builder) printExample(e *doc.Example) (code Code, output string) {
|
||||
output = e.Output
|
||||
|
||||
b.buf = b.buf[:0]
|
||||
var n interface{}
|
||||
if _, ok := e.Code.(*ast.File); ok {
|
||||
n = e.Play
|
||||
} else {
|
||||
n = &printer.CommentedNode{Node: e.Code, Comments: e.Comments}
|
||||
}
|
||||
err := (&printer.Config{Mode: printer.UseSpaces, Tabwidth: 4}).Fprint(sliceWriter{&b.buf}, b.fset, n)
|
||||
if err != nil {
|
||||
return Code{Text: err.Error()}, output
|
||||
}
|
||||
|
||||
// additional formatting if this is a function body
|
||||
if i := len(b.buf); i >= 2 && b.buf[0] == '{' && b.buf[i-1] == '}' {
|
||||
// remove surrounding braces
|
||||
b.buf = b.buf[1 : i-1]
|
||||
// unindent
|
||||
b.buf = bytes.Replace(b.buf, []byte("\n "), []byte("\n"), -1)
|
||||
// remove output comment
|
||||
if j := exampleOutputRx.FindIndex(b.buf); j != nil {
|
||||
b.buf = bytes.TrimSpace(b.buf[:j[0]])
|
||||
}
|
||||
} else {
|
||||
// drop output, as the output comment will appear in the code
|
||||
output = ""
|
||||
}
|
||||
|
||||
var annotations []Annotation
|
||||
var s scanner.Scanner
|
||||
fset := token.NewFileSet()
|
||||
file := fset.AddFile("", fset.Base(), len(b.buf))
|
||||
s.Init(file, b.buf, nil, scanner.ScanComments)
|
||||
prevTok := token.ILLEGAL
|
||||
scanLoop:
|
||||
for {
|
||||
pos, tok, lit := s.Scan()
|
||||
switch tok {
|
||||
case token.EOF:
|
||||
break scanLoop
|
||||
case token.COMMENT:
|
||||
p := file.Offset(pos)
|
||||
e := p + len(lit)
|
||||
if prevTok == token.COMMENT {
|
||||
annotations[len(annotations)-1].End = int32(e)
|
||||
} else {
|
||||
annotations = append(annotations, Annotation{Kind: CommentAnnotation, Pos: int32(p), End: int32(e)})
|
||||
}
|
||||
}
|
||||
prevTok = tok
|
||||
}
|
||||
|
||||
return Code{Text: string(b.buf), Annotations: annotations}, output
|
||||
}
|
Reference in New Issue
Block a user