]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgo/go/go/doc/doc.go
libgo: update to Go1.14beta1
[thirdparty/gcc.git] / libgo / go / go / doc / doc.go
CommitLineData
7a938933
ILT
1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
9ff56c95 5// Package doc extracts source code documentation from a Go AST.
7a938933
ILT
6package doc
7
8import (
5a8ea165 9 "fmt"
7a938933 10 "go/ast"
9af4cb95 11 "go/token"
5a8ea165 12 "strings"
7a938933
ILT
13)
14
df1304ee
ILT
15// Package is the documentation for an entire package.
16type Package struct {
17 Doc string
18 Name string
19 ImportPath string
af92e385 20 Imports []string
df1304ee 21 Filenames []string
be47d6ec 22 Notes map[string][]*Note
af146490
ILT
23
24 // Deprecated: For backward compatibility Bugs is still populated,
be47d6ec
ILT
25 // but all new code should use Notes instead.
26 Bugs []string
9af4cb95
ILT
27
28 // declarations
29 Consts []*Value
30 Types []*Type
31 Vars []*Value
32 Funcs []*Func
5a8ea165
ILT
33
34 // Examples is a sorted list of examples associated with
35 // the package. Examples are extracted from _test.go files
36 // provided to NewFromFiles.
37 Examples []*Example
df1304ee
ILT
38}
39
40// Value is the documentation for a (possibly grouped) var or const declaration.
41type Value struct {
7a938933 42 Doc string
df1304ee 43 Names []string // var or const names in declaration order
7a938933 44 Decl *ast.GenDecl
df1304ee 45
7a938933
ILT
46 order int
47}
48
9af4cb95 49// Type is the documentation for a type declaration.
df1304ee 50type Type struct {
9af4cb95
ILT
51 Doc string
52 Name string
53 Decl *ast.GenDecl
7a938933 54
9af4cb95
ILT
55 // associated declarations
56 Consts []*Value // sorted list of constants of (mostly) this type
57 Vars []*Value // sorted list of variables of (mostly) this type
58 Funcs []*Func // sorted list of functions returning this type
59 Methods []*Func // sorted list of methods (including embedded ones) of this type
5a8ea165
ILT
60
61 // Examples is a sorted list of examples associated with
62 // this type. Examples are extracted from _test.go files
63 // provided to NewFromFiles.
64 Examples []*Example
7a938933
ILT
65}
66
df1304ee
ILT
67// Func is the documentation for a func declaration.
68type Func struct {
7a938933 69 Doc string
7a938933
ILT
70 Name string
71 Decl *ast.FuncDecl
9af4cb95
ILT
72
73 // methods
74 // (for functions, these fields have the respective zero value)
75 Recv string // actual receiver "T" or "*T"
76 Orig string // original receiver "T" or "*T"
77 Level int // embedding level; 0 means not embedded
5a8ea165
ILT
78
79 // Examples is a sorted list of examples associated with this
80 // function or method. Examples are extracted from _test.go files
81 // provided to NewFromFiles.
82 Examples []*Example
7a938933
ILT
83}
84
be47d6ec
ILT
85// A Note represents a marked comment starting with "MARKER(uid): note body".
86// Any note with a marker of 2 or more upper case [A-Z] letters and a uid of
87// at least one character is recognized. The ":" following the uid is optional.
88// Notes are collected in the Package.Notes map indexed by the notes marker.
89type Note struct {
90 Pos, End token.Pos // position range of the comment containing the marker
91 UID string // uid found with the marker
92 Body string // note body text
93}
94
5a8ea165 95// Mode values control the operation of New and NewFromFiles.
df1304ee 96type Mode int
7a938933 97
df1304ee 98const (
4f4a855d
ILT
99 // AllDecls says to extract documentation for all package-level
100 // declarations, not just exported ones.
df1304ee 101 AllDecls Mode = 1 << iota
94252f4b 102
4f4a855d
ILT
103 // AllMethods says to show all embedded methods, not just the ones of
104 // invisible (unexported) anonymous fields.
94252f4b 105 AllMethods
4f4a855d
ILT
106
107 // PreserveAST says to leave the AST unmodified. Originally, pieces of
108 // the AST such as function bodies were nil-ed out to save memory in
109 // godoc, but not all programs want that behavior.
110 PreserveAST
df1304ee 111)
df4aa89a 112
9af4cb95
ILT
113// New computes the package documentation for the given package AST.
114// New takes ownership of the AST pkg and may edit or overwrite it.
5a8ea165
ILT
115// To have the Examples fields populated, use NewFromFiles and include
116// the package's _test.go files.
9af4cb95
ILT
117//
118func New(pkg *ast.Package, importPath string, mode Mode) *Package {
119 var r reader
120 r.readPackage(pkg, mode)
121 r.computeMethodSets()
122 r.cleanupTypes()
123 return &Package{
124 Doc: r.doc,
125 Name: pkg.Name,
126 ImportPath: importPath,
127 Imports: sortedKeys(r.imports),
128 Filenames: r.filenames,
be47d6ec
ILT
129 Notes: r.notes,
130 Bugs: noteBodies(r.notes["BUG"]),
9af4cb95 131 Consts: sortedValues(r.values, token.CONST),
94252f4b 132 Types: sortedTypes(r.types, mode&AllMethods != 0),
9af4cb95 133 Vars: sortedValues(r.values, token.VAR),
94252f4b 134 Funcs: sortedFuncs(r.funcs, true),
df4aa89a 135 }
7a938933 136}
5a8ea165
ILT
137
138// NewFromFiles computes documentation for a package.
139//
140// The package is specified by a list of *ast.Files and corresponding
141// file set, which must not be nil. NewFromFiles does not skip files
142// based on build constraints, so it is the caller's responsibility to
143// provide only the files that are matched by the build context.
144// The import path of the package is specified by importPath.
145//
146// Examples found in _test.go files are associated with the corresponding
147// type, function, method, or the package, based on their name.
148// If the example has a suffix in its name, it is set in the
149// Example.Suffix field. Examples with malformed names are skipped.
150//
151// Optionally, a single extra argument of type Mode can be provided to
152// control low-level aspects of the documentation extraction behavior.
153//
154// NewFromFiles takes ownership of the AST files and may edit them,
155// unless the PreserveAST Mode bit is on.
156//
157func NewFromFiles(fset *token.FileSet, files []*ast.File, importPath string, opts ...interface{}) (*Package, error) {
158 // Check for invalid API usage.
159 if fset == nil {
160 panic(fmt.Errorf("doc.NewFromFiles: no token.FileSet provided (fset == nil)"))
161 }
162 var mode Mode
163 switch len(opts) { // There can only be 0 or 1 options, so a simple switch works for now.
164 case 0:
165 // Nothing to do.
166 case 1:
167 m, ok := opts[0].(Mode)
168 if !ok {
169 panic(fmt.Errorf("doc.NewFromFiles: option argument type must be doc.Mode"))
170 }
171 mode = m
172 default:
173 panic(fmt.Errorf("doc.NewFromFiles: there must not be more than 1 option argument"))
174 }
175
176 // Collect .go and _test.go files.
177 var (
178 goFiles = make(map[string]*ast.File)
179 testGoFiles []*ast.File
180 )
181 for i := range files {
182 f := fset.File(files[i].Pos())
183 if f == nil {
184 return nil, fmt.Errorf("file files[%d] is not found in the provided file set", i)
185 }
186 switch name := f.Name(); {
187 case strings.HasSuffix(name, ".go") && !strings.HasSuffix(name, "_test.go"):
188 goFiles[name] = files[i]
189 case strings.HasSuffix(name, "_test.go"):
190 testGoFiles = append(testGoFiles, files[i])
191 default:
192 return nil, fmt.Errorf("file files[%d] filename %q does not have a .go extension", i, name)
193 }
194 }
195
196 // TODO(dmitshur,gri): A relatively high level call to ast.NewPackage with a simpleImporter
197 // ast.Importer implementation is made below. It might be possible to short-circuit and simplify.
198
199 // Compute package documentation.
200 pkg, _ := ast.NewPackage(fset, goFiles, simpleImporter, nil) // Ignore errors that can happen due to unresolved identifiers.
201 p := New(pkg, importPath, mode)
202 classifyExamples(p, Examples(testGoFiles...))
203 return p, nil
204}
205
206// simpleImporter returns a (dummy) package object named by the last path
207// component of the provided package path (as is the convention for packages).
208// This is sufficient to resolve package identifiers without doing an actual
209// import. It never returns an error.
210func simpleImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
211 pkg := imports[path]
212 if pkg == nil {
213 // note that strings.LastIndex returns -1 if there is no "/"
214 pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:])
215 pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import
216 imports[path] = pkg
217 }
218 return pkg, nil
219}