Daily bump.
[official-gcc.git] / libgo / go / go / doc / reader.go
blobd9e721d01b001deb0e25d8d584da41f0acd4016e
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.
5 package doc
7 import (
8 "fmt"
9 "go/ast"
10 "go/token"
11 "internal/lazyregexp"
12 "sort"
13 "strconv"
14 "strings"
17 // ----------------------------------------------------------------------------
18 // function/method sets
20 // Internally, we treat functions like methods and collect them in method sets.
22 // A methodSet describes a set of methods. Entries where Decl == nil are conflict
23 // entries (more than one method with the same name at the same embedding level).
25 type methodSet map[string]*Func
27 // recvString returns a string representation of recv of the form "T", "*T",
28 // "T[A, ...]", "*T[A, ...]" or "BADRECV" (if not a proper receiver type).
30 func recvString(recv ast.Expr) string {
31 switch t := recv.(type) {
32 case *ast.Ident:
33 return t.Name
34 case *ast.StarExpr:
35 return "*" + recvString(t.X)
36 case *ast.IndexExpr:
37 // Generic type with one parameter.
38 return fmt.Sprintf("%s[%s]", recvString(t.X), recvParam(t.Index))
39 case *ast.IndexListExpr:
40 // Generic type with multiple parameters.
41 if len(t.Indices) > 0 {
42 var b strings.Builder
43 b.WriteString(recvString(t.X))
44 b.WriteByte('[')
45 b.WriteString(recvParam(t.Indices[0]))
46 for _, e := range t.Indices[1:] {
47 b.WriteString(", ")
48 b.WriteString(recvParam(e))
50 b.WriteByte(']')
51 return b.String()
54 return "BADRECV"
57 func recvParam(p ast.Expr) string {
58 if id, ok := p.(*ast.Ident); ok {
59 return id.Name
61 return "BADPARAM"
64 // set creates the corresponding Func for f and adds it to mset.
65 // If there are multiple f's with the same name, set keeps the first
66 // one with documentation; conflicts are ignored. The boolean
67 // specifies whether to leave the AST untouched.
69 func (mset methodSet) set(f *ast.FuncDecl, preserveAST bool) {
70 name := f.Name.Name
71 if g := mset[name]; g != nil && g.Doc != "" {
72 // A function with the same name has already been registered;
73 // since it has documentation, assume f is simply another
74 // implementation and ignore it. This does not happen if the
75 // caller is using go/build.ScanDir to determine the list of
76 // files implementing a package.
77 return
79 // function doesn't exist or has no documentation; use f
80 recv := ""
81 if f.Recv != nil {
82 var typ ast.Expr
83 // be careful in case of incorrect ASTs
84 if list := f.Recv.List; len(list) == 1 {
85 typ = list[0].Type
87 recv = recvString(typ)
89 mset[name] = &Func{
90 Doc: f.Doc.Text(),
91 Name: name,
92 Decl: f,
93 Recv: recv,
94 Orig: recv,
96 if !preserveAST {
97 f.Doc = nil // doc consumed - remove from AST
101 // add adds method m to the method set; m is ignored if the method set
102 // already contains a method with the same name at the same or a higher
103 // level than m.
105 func (mset methodSet) add(m *Func) {
106 old := mset[m.Name]
107 if old == nil || m.Level < old.Level {
108 mset[m.Name] = m
109 return
111 if m.Level == old.Level {
112 // conflict - mark it using a method with nil Decl
113 mset[m.Name] = &Func{
114 Name: m.Name,
115 Level: m.Level,
120 // ----------------------------------------------------------------------------
121 // Named types
123 // baseTypeName returns the name of the base type of x (or "")
124 // and whether the type is imported or not.
126 func baseTypeName(x ast.Expr) (name string, imported bool) {
127 switch t := x.(type) {
128 case *ast.Ident:
129 return t.Name, false
130 case *ast.IndexExpr:
131 return baseTypeName(t.X)
132 case *ast.IndexListExpr:
133 return baseTypeName(t.X)
134 case *ast.SelectorExpr:
135 if _, ok := t.X.(*ast.Ident); ok {
136 // only possible for qualified type names;
137 // assume type is imported
138 return t.Sel.Name, true
140 case *ast.ParenExpr:
141 return baseTypeName(t.X)
142 case *ast.StarExpr:
143 return baseTypeName(t.X)
145 return "", false
148 // An embeddedSet describes a set of embedded types.
149 type embeddedSet map[*namedType]bool
151 // A namedType represents a named unqualified (package local, or possibly
152 // predeclared) type. The namedType for a type name is always found via
153 // reader.lookupType.
155 type namedType struct {
156 doc string // doc comment for type
157 name string // type name
158 decl *ast.GenDecl // nil if declaration hasn't been seen yet
160 isEmbedded bool // true if this type is embedded
161 isStruct bool // true if this type is a struct
162 embedded embeddedSet // true if the embedded type is a pointer
164 // associated declarations
165 values []*Value // consts and vars
166 funcs methodSet
167 methods methodSet
170 // ----------------------------------------------------------------------------
171 // AST reader
173 // reader accumulates documentation for a single package.
174 // It modifies the AST: Comments (declaration documentation)
175 // that have been collected by the reader are set to nil
176 // in the respective AST nodes so that they are not printed
177 // twice (once when printing the documentation and once when
178 // printing the corresponding AST node).
180 type reader struct {
181 mode Mode
183 // package properties
184 doc string // package documentation, if any
185 filenames []string
186 notes map[string][]*Note
188 // declarations
189 imports map[string]int
190 hasDotImp bool // if set, package contains a dot import
191 values []*Value // consts and vars
192 order int // sort order of const and var declarations (when we can't use a name)
193 types map[string]*namedType
194 funcs methodSet
196 // support for package-local shadowing of predeclared types
197 shadowedPredecl map[string]bool
198 fixmap map[string][]*ast.InterfaceType
201 func (r *reader) isVisible(name string) bool {
202 return r.mode&AllDecls != 0 || token.IsExported(name)
205 // lookupType returns the base type with the given name.
206 // If the base type has not been encountered yet, a new
207 // type with the given name but no associated declaration
208 // is added to the type map.
210 func (r *reader) lookupType(name string) *namedType {
211 if name == "" || name == "_" {
212 return nil // no type docs for anonymous types
214 if typ, found := r.types[name]; found {
215 return typ
217 // type not found - add one without declaration
218 typ := &namedType{
219 name: name,
220 embedded: make(embeddedSet),
221 funcs: make(methodSet),
222 methods: make(methodSet),
224 r.types[name] = typ
225 return typ
228 // recordAnonymousField registers fieldType as the type of an
229 // anonymous field in the parent type. If the field is imported
230 // (qualified name) or the parent is nil, the field is ignored.
231 // The function returns the field name.
233 func (r *reader) recordAnonymousField(parent *namedType, fieldType ast.Expr) (fname string) {
234 fname, imp := baseTypeName(fieldType)
235 if parent == nil || imp {
236 return
238 if ftype := r.lookupType(fname); ftype != nil {
239 ftype.isEmbedded = true
240 _, ptr := fieldType.(*ast.StarExpr)
241 parent.embedded[ftype] = ptr
243 return
246 func (r *reader) readDoc(comment *ast.CommentGroup) {
247 // By convention there should be only one package comment
248 // but collect all of them if there are more than one.
249 text := comment.Text()
250 if r.doc == "" {
251 r.doc = text
252 return
254 r.doc += "\n" + text
257 func (r *reader) remember(predecl string, typ *ast.InterfaceType) {
258 if r.fixmap == nil {
259 r.fixmap = make(map[string][]*ast.InterfaceType)
261 r.fixmap[predecl] = append(r.fixmap[predecl], typ)
264 func specNames(specs []ast.Spec) []string {
265 names := make([]string, 0, len(specs)) // reasonable estimate
266 for _, s := range specs {
267 // s guaranteed to be an *ast.ValueSpec by readValue
268 for _, ident := range s.(*ast.ValueSpec).Names {
269 names = append(names, ident.Name)
272 return names
275 // readValue processes a const or var declaration.
277 func (r *reader) readValue(decl *ast.GenDecl) {
278 // determine if decl should be associated with a type
279 // Heuristic: For each typed entry, determine the type name, if any.
280 // If there is exactly one type name that is sufficiently
281 // frequent, associate the decl with the respective type.
282 domName := ""
283 domFreq := 0
284 prev := ""
285 n := 0
286 for _, spec := range decl.Specs {
287 s, ok := spec.(*ast.ValueSpec)
288 if !ok {
289 continue // should not happen, but be conservative
291 name := ""
292 switch {
293 case s.Type != nil:
294 // a type is present; determine its name
295 if n, imp := baseTypeName(s.Type); !imp {
296 name = n
298 case decl.Tok == token.CONST && len(s.Values) == 0:
299 // no type or value is present but we have a constant declaration;
300 // use the previous type name (possibly the empty string)
301 name = prev
303 if name != "" {
304 // entry has a named type
305 if domName != "" && domName != name {
306 // more than one type name - do not associate
307 // with any type
308 domName = ""
309 break
311 domName = name
312 domFreq++
314 prev = name
318 // nothing to do w/o a legal declaration
319 if n == 0 {
320 return
323 // determine values list with which to associate the Value for this decl
324 values := &r.values
325 const threshold = 0.75
326 if domName != "" && r.isVisible(domName) && domFreq >= int(float64(len(decl.Specs))*threshold) {
327 // typed entries are sufficiently frequent
328 if typ := r.lookupType(domName); typ != nil {
329 values = &typ.values // associate with that type
333 *values = append(*values, &Value{
334 Doc: decl.Doc.Text(),
335 Names: specNames(decl.Specs),
336 Decl: decl,
337 order: r.order,
339 if r.mode&PreserveAST == 0 {
340 decl.Doc = nil // doc consumed - remove from AST
342 // Note: It's important that the order used here is global because the cleanupTypes
343 // methods may move values associated with types back into the global list. If the
344 // order is list-specific, sorting is not deterministic because the same order value
345 // may appear multiple times (was bug, found when fixing #16153).
346 r.order++
349 // fields returns a struct's fields or an interface's methods.
351 func fields(typ ast.Expr) (list []*ast.Field, isStruct bool) {
352 var fields *ast.FieldList
353 switch t := typ.(type) {
354 case *ast.StructType:
355 fields = t.Fields
356 isStruct = true
357 case *ast.InterfaceType:
358 fields = t.Methods
360 if fields != nil {
361 list = fields.List
363 return
366 // readType processes a type declaration.
368 func (r *reader) readType(decl *ast.GenDecl, spec *ast.TypeSpec) {
369 typ := r.lookupType(spec.Name.Name)
370 if typ == nil {
371 return // no name or blank name - ignore the type
374 // A type should be added at most once, so typ.decl
375 // should be nil - if it is not, simply overwrite it.
376 typ.decl = decl
378 // compute documentation
379 doc := spec.Doc
380 if doc == nil {
381 // no doc associated with the spec, use the declaration doc, if any
382 doc = decl.Doc
384 if r.mode&PreserveAST == 0 {
385 spec.Doc = nil // doc consumed - remove from AST
386 decl.Doc = nil // doc consumed - remove from AST
388 typ.doc = doc.Text()
390 // record anonymous fields (they may contribute methods)
391 // (some fields may have been recorded already when filtering
392 // exports, but that's ok)
393 var list []*ast.Field
394 list, typ.isStruct = fields(spec.Type)
395 for _, field := range list {
396 if len(field.Names) == 0 {
397 r.recordAnonymousField(typ, field.Type)
402 // isPredeclared reports whether n denotes a predeclared type.
404 func (r *reader) isPredeclared(n string) bool {
405 return predeclaredTypes[n] && r.types[n] == nil
408 // readFunc processes a func or method declaration.
410 func (r *reader) readFunc(fun *ast.FuncDecl) {
411 // strip function body if requested.
412 if r.mode&PreserveAST == 0 {
413 fun.Body = nil
416 // associate methods with the receiver type, if any
417 if fun.Recv != nil {
418 // method
419 if len(fun.Recv.List) == 0 {
420 // should not happen (incorrect AST); (See issue 17788)
421 // don't show this method
422 return
424 recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type)
425 if imp {
426 // should not happen (incorrect AST);
427 // don't show this method
428 return
430 if typ := r.lookupType(recvTypeName); typ != nil {
431 typ.methods.set(fun, r.mode&PreserveAST != 0)
433 // otherwise ignore the method
434 // TODO(gri): There may be exported methods of non-exported types
435 // that can be called because of exported values (consts, vars, or
436 // function results) of that type. Could determine if that is the
437 // case and then show those methods in an appropriate section.
438 return
441 // Associate factory functions with the first visible result type, as long as
442 // others are predeclared types.
443 if fun.Type.Results.NumFields() >= 1 {
444 var typ *namedType // type to associate the function with
445 numResultTypes := 0
446 for _, res := range fun.Type.Results.List {
447 factoryType := res.Type
448 if t, ok := factoryType.(*ast.ArrayType); ok {
449 // We consider functions that return slices or arrays of type
450 // T (or pointers to T) as factory functions of T.
451 factoryType = t.Elt
453 if n, imp := baseTypeName(factoryType); !imp && r.isVisible(n) && !r.isPredeclared(n) {
454 if lookupTypeParam(n, fun.Type.TypeParams) != nil {
455 // Issue #49477: don't associate fun with its type parameter result.
456 // A type parameter is not a defined type.
457 continue
459 if t := r.lookupType(n); t != nil {
460 typ = t
461 numResultTypes++
462 if numResultTypes > 1 {
463 break
468 // If there is exactly one result type,
469 // associate the function with that type.
470 if numResultTypes == 1 {
471 typ.funcs.set(fun, r.mode&PreserveAST != 0)
472 return
476 // just an ordinary function
477 r.funcs.set(fun, r.mode&PreserveAST != 0)
480 // lookupTypeParam searches for type parameters named name within the tparams
481 // field list, returning the relevant identifier if found, or nil if not.
482 func lookupTypeParam(name string, tparams *ast.FieldList) *ast.Ident {
483 if tparams == nil {
484 return nil
486 for _, field := range tparams.List {
487 for _, id := range field.Names {
488 if id.Name == name {
489 return id
493 return nil
496 var (
497 noteMarker = `([A-Z][A-Z]+)\(([^)]+)\):?` // MARKER(uid), MARKER at least 2 chars, uid at least 1 char
498 noteMarkerRx = lazyregexp.New(`^[ \t]*` + noteMarker) // MARKER(uid) at text start
499 noteCommentRx = lazyregexp.New(`^/[/*][ \t]*` + noteMarker) // MARKER(uid) at comment start
502 // readNote collects a single note from a sequence of comments.
504 func (r *reader) readNote(list []*ast.Comment) {
505 text := (&ast.CommentGroup{List: list}).Text()
506 if m := noteMarkerRx.FindStringSubmatchIndex(text); m != nil {
507 // The note body starts after the marker.
508 // We remove any formatting so that we don't
509 // get spurious line breaks/indentation when
510 // showing the TODO body.
511 body := clean(text[m[1]:], keepNL)
512 if body != "" {
513 marker := text[m[2]:m[3]]
514 r.notes[marker] = append(r.notes[marker], &Note{
515 Pos: list[0].Pos(),
516 End: list[len(list)-1].End(),
517 UID: text[m[4]:m[5]],
518 Body: body,
524 // readNotes extracts notes from comments.
525 // A note must start at the beginning of a comment with "MARKER(uid):"
526 // and is followed by the note body (e.g., "// BUG(gri): fix this").
527 // The note ends at the end of the comment group or at the start of
528 // another note in the same comment group, whichever comes first.
530 func (r *reader) readNotes(comments []*ast.CommentGroup) {
531 for _, group := range comments {
532 i := -1 // comment index of most recent note start, valid if >= 0
533 list := group.List
534 for j, c := range list {
535 if noteCommentRx.MatchString(c.Text) {
536 if i >= 0 {
537 r.readNote(list[i:j])
539 i = j
542 if i >= 0 {
543 r.readNote(list[i:])
548 // readFile adds the AST for a source file to the reader.
550 func (r *reader) readFile(src *ast.File) {
551 // add package documentation
552 if src.Doc != nil {
553 r.readDoc(src.Doc)
554 if r.mode&PreserveAST == 0 {
555 src.Doc = nil // doc consumed - remove from AST
559 // add all declarations but for functions which are processed in a separate pass
560 for _, decl := range src.Decls {
561 switch d := decl.(type) {
562 case *ast.GenDecl:
563 switch d.Tok {
564 case token.IMPORT:
565 // imports are handled individually
566 for _, spec := range d.Specs {
567 if s, ok := spec.(*ast.ImportSpec); ok {
568 if import_, err := strconv.Unquote(s.Path.Value); err == nil {
569 r.imports[import_] = 1
570 if s.Name != nil && s.Name.Name == "." {
571 r.hasDotImp = true
576 case token.CONST, token.VAR:
577 // constants and variables are always handled as a group
578 r.readValue(d)
579 case token.TYPE:
580 // types are handled individually
581 if len(d.Specs) == 1 && !d.Lparen.IsValid() {
582 // common case: single declaration w/o parentheses
583 // (if a single declaration is parenthesized,
584 // create a new fake declaration below, so that
585 // go/doc type declarations always appear w/o
586 // parentheses)
587 if s, ok := d.Specs[0].(*ast.TypeSpec); ok {
588 r.readType(d, s)
590 break
592 for _, spec := range d.Specs {
593 if s, ok := spec.(*ast.TypeSpec); ok {
594 // use an individual (possibly fake) declaration
595 // for each type; this also ensures that each type
596 // gets to (re-)use the declaration documentation
597 // if there's none associated with the spec itself
598 fake := &ast.GenDecl{
599 Doc: d.Doc,
600 // don't use the existing TokPos because it
601 // will lead to the wrong selection range for
602 // the fake declaration if there are more
603 // than one type in the group (this affects
604 // src/cmd/godoc/godoc.go's posLink_urlFunc)
605 TokPos: s.Pos(),
606 Tok: token.TYPE,
607 Specs: []ast.Spec{s},
609 r.readType(fake, s)
616 // collect MARKER(...): annotations
617 r.readNotes(src.Comments)
618 if r.mode&PreserveAST == 0 {
619 src.Comments = nil // consumed unassociated comments - remove from AST
623 func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
624 // initialize reader
625 r.filenames = make([]string, len(pkg.Files))
626 r.imports = make(map[string]int)
627 r.mode = mode
628 r.types = make(map[string]*namedType)
629 r.funcs = make(methodSet)
630 r.notes = make(map[string][]*Note)
632 // sort package files before reading them so that the
633 // result does not depend on map iteration order
634 i := 0
635 for filename := range pkg.Files {
636 r.filenames[i] = filename
639 sort.Strings(r.filenames)
641 // process files in sorted order
642 for _, filename := range r.filenames {
643 f := pkg.Files[filename]
644 if mode&AllDecls == 0 {
645 r.fileExports(f)
647 r.readFile(f)
650 // process functions now that we have better type information
651 for _, f := range pkg.Files {
652 for _, decl := range f.Decls {
653 if d, ok := decl.(*ast.FuncDecl); ok {
654 r.readFunc(d)
660 // ----------------------------------------------------------------------------
661 // Types
663 func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func {
664 if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 {
665 return f // shouldn't happen, but be safe
668 // copy existing receiver field and set new type
669 newField := *f.Decl.Recv.List[0]
670 origPos := newField.Type.Pos()
671 _, origRecvIsPtr := newField.Type.(*ast.StarExpr)
672 newIdent := &ast.Ident{NamePos: origPos, Name: recvTypeName}
673 var typ ast.Expr = newIdent
674 if !embeddedIsPtr && origRecvIsPtr {
675 newIdent.NamePos++ // '*' is one character
676 typ = &ast.StarExpr{Star: origPos, X: newIdent}
678 newField.Type = typ
680 // copy existing receiver field list and set new receiver field
681 newFieldList := *f.Decl.Recv
682 newFieldList.List = []*ast.Field{&newField}
684 // copy existing function declaration and set new receiver field list
685 newFuncDecl := *f.Decl
686 newFuncDecl.Recv = &newFieldList
688 // copy existing function documentation and set new declaration
689 newF := *f
690 newF.Decl = &newFuncDecl
691 newF.Recv = recvString(typ)
692 // the Orig field never changes
693 newF.Level = level
695 return &newF
698 // collectEmbeddedMethods collects the embedded methods of typ in mset.
700 func (r *reader) collectEmbeddedMethods(mset methodSet, typ *namedType, recvTypeName string, embeddedIsPtr bool, level int, visited embeddedSet) {
701 visited[typ] = true
702 for embedded, isPtr := range typ.embedded {
703 // Once an embedded type is embedded as a pointer type
704 // all embedded types in those types are treated like
705 // pointer types for the purpose of the receiver type
706 // computation; i.e., embeddedIsPtr is sticky for this
707 // embedding hierarchy.
708 thisEmbeddedIsPtr := embeddedIsPtr || isPtr
709 for _, m := range embedded.methods {
710 // only top-level methods are embedded
711 if m.Level == 0 {
712 mset.add(customizeRecv(m, recvTypeName, thisEmbeddedIsPtr, level))
715 if !visited[embedded] {
716 r.collectEmbeddedMethods(mset, embedded, recvTypeName, thisEmbeddedIsPtr, level+1, visited)
719 delete(visited, typ)
722 // computeMethodSets determines the actual method sets for each type encountered.
724 func (r *reader) computeMethodSets() {
725 for _, t := range r.types {
726 // collect embedded methods for t
727 if t.isStruct {
728 // struct
729 r.collectEmbeddedMethods(t.methods, t, t.name, false, 1, make(embeddedSet))
730 } else {
731 // interface
732 // TODO(gri) fix this
736 // For any predeclared names that are declared locally, don't treat them as
737 // exported fields anymore.
738 for predecl := range r.shadowedPredecl {
739 for _, ityp := range r.fixmap[predecl] {
740 removeAnonymousField(predecl, ityp)
745 // cleanupTypes removes the association of functions and methods with
746 // types that have no declaration. Instead, these functions and methods
747 // are shown at the package level. It also removes types with missing
748 // declarations or which are not visible.
750 func (r *reader) cleanupTypes() {
751 for _, t := range r.types {
752 visible := r.isVisible(t.name)
753 predeclared := predeclaredTypes[t.name]
755 if t.decl == nil && (predeclared || visible && (t.isEmbedded || r.hasDotImp)) {
756 // t.name is a predeclared type (and was not redeclared in this package),
757 // or it was embedded somewhere but its declaration is missing (because
758 // the AST is incomplete), or we have a dot-import (and all bets are off):
759 // move any associated values, funcs, and methods back to the top-level so
760 // that they are not lost.
761 // 1) move values
762 r.values = append(r.values, t.values...)
763 // 2) move factory functions
764 for name, f := range t.funcs {
765 // in a correct AST, package-level function names
766 // are all different - no need to check for conflicts
767 r.funcs[name] = f
769 // 3) move methods
770 if !predeclared {
771 for name, m := range t.methods {
772 // don't overwrite functions with the same name - drop them
773 if _, found := r.funcs[name]; !found {
774 r.funcs[name] = m
779 // remove types w/o declaration or which are not visible
780 if t.decl == nil || !visible {
781 delete(r.types, t.name)
786 // ----------------------------------------------------------------------------
787 // Sorting
789 type data struct {
790 n int
791 swap func(i, j int)
792 less func(i, j int) bool
795 func (d *data) Len() int { return d.n }
796 func (d *data) Swap(i, j int) { d.swap(i, j) }
797 func (d *data) Less(i, j int) bool { return d.less(i, j) }
799 // sortBy is a helper function for sorting
800 func sortBy(less func(i, j int) bool, swap func(i, j int), n int) {
801 sort.Sort(&data{n, swap, less})
804 func sortedKeys(m map[string]int) []string {
805 list := make([]string, len(m))
806 i := 0
807 for key := range m {
808 list[i] = key
811 sort.Strings(list)
812 return list
815 // sortingName returns the name to use when sorting d into place.
817 func sortingName(d *ast.GenDecl) string {
818 if len(d.Specs) == 1 {
819 if s, ok := d.Specs[0].(*ast.ValueSpec); ok {
820 return s.Names[0].Name
823 return ""
826 func sortedValues(m []*Value, tok token.Token) []*Value {
827 list := make([]*Value, len(m)) // big enough in any case
828 i := 0
829 for _, val := range m {
830 if val.Decl.Tok == tok {
831 list[i] = val
835 list = list[0:i]
837 sortBy(
838 func(i, j int) bool {
839 if ni, nj := sortingName(list[i].Decl), sortingName(list[j].Decl); ni != nj {
840 return ni < nj
842 return list[i].order < list[j].order
844 func(i, j int) { list[i], list[j] = list[j], list[i] },
845 len(list),
848 return list
851 func sortedTypes(m map[string]*namedType, allMethods bool) []*Type {
852 list := make([]*Type, len(m))
853 i := 0
854 for _, t := range m {
855 list[i] = &Type{
856 Doc: t.doc,
857 Name: t.name,
858 Decl: t.decl,
859 Consts: sortedValues(t.values, token.CONST),
860 Vars: sortedValues(t.values, token.VAR),
861 Funcs: sortedFuncs(t.funcs, true),
862 Methods: sortedFuncs(t.methods, allMethods),
867 sortBy(
868 func(i, j int) bool { return list[i].Name < list[j].Name },
869 func(i, j int) { list[i], list[j] = list[j], list[i] },
870 len(list),
873 return list
876 func removeStar(s string) string {
877 if len(s) > 0 && s[0] == '*' {
878 return s[1:]
880 return s
883 func sortedFuncs(m methodSet, allMethods bool) []*Func {
884 list := make([]*Func, len(m))
885 i := 0
886 for _, m := range m {
887 // determine which methods to include
888 switch {
889 case m.Decl == nil:
890 // exclude conflict entry
891 case allMethods, m.Level == 0, !token.IsExported(removeStar(m.Orig)):
892 // forced inclusion, method not embedded, or method
893 // embedded but original receiver type not exported
894 list[i] = m
898 list = list[0:i]
899 sortBy(
900 func(i, j int) bool { return list[i].Name < list[j].Name },
901 func(i, j int) { list[i], list[j] = list[j], list[i] },
902 len(list),
904 return list
907 // noteBodies returns a list of note body strings given a list of notes.
908 // This is only used to populate the deprecated Package.Bugs field.
910 func noteBodies(notes []*Note) []string {
911 var list []string
912 for _, n := range notes {
913 list = append(list, n.Body)
915 return list
918 // ----------------------------------------------------------------------------
919 // Predeclared identifiers
921 // IsPredeclared reports whether s is a predeclared identifier.
922 func IsPredeclared(s string) bool {
923 return predeclaredTypes[s] || predeclaredFuncs[s] || predeclaredConstants[s]
926 var predeclaredTypes = map[string]bool{
927 "any": true,
928 "bool": true,
929 "byte": true,
930 "comparable": true,
931 "complex64": true,
932 "complex128": true,
933 "error": true,
934 "float32": true,
935 "float64": true,
936 "int": true,
937 "int8": true,
938 "int16": true,
939 "int32": true,
940 "int64": true,
941 "rune": true,
942 "string": true,
943 "uint": true,
944 "uint8": true,
945 "uint16": true,
946 "uint32": true,
947 "uint64": true,
948 "uintptr": true,
951 var predeclaredFuncs = map[string]bool{
952 "append": true,
953 "cap": true,
954 "close": true,
955 "complex": true,
956 "copy": true,
957 "delete": true,
958 "imag": true,
959 "len": true,
960 "make": true,
961 "new": true,
962 "panic": true,
963 "print": true,
964 "println": true,
965 "real": true,
966 "recover": true,
969 var predeclaredConstants = map[string]bool{
970 "false": true,
971 "iota": true,
972 "nil": true,
973 "true": true,