github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/go/doc/reader.go (about) 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 5 package doc 6 7 import ( 8 "go/ast" 9 "go/token" 10 "sort" 11 "strconv" 12 ) 13 14 // ---------------------------------------------------------------------------- 15 // function/method sets 16 // 17 // Internally, we treat functions like methods and collect them in method sets. 18 19 // A methodSet describes a set of methods. Entries where Decl == nil are conflict 20 // entries (more than one method with the same name at the same embedding level). 21 // 22 type methodSet map[string]*Func 23 24 // recvString returns a string representation of recv of the 25 // form "T", "*T", or "BADRECV" (if not a proper receiver type). 26 // 27 func recvString(recv ast.Expr) string { 28 switch t := recv.(type) { 29 case *ast.Ident: 30 return t.Name 31 case *ast.StarExpr: 32 return "*" + recvString(t.X) 33 } 34 return "BADRECV" 35 } 36 37 // set creates the corresponding Func for f and adds it to mset. 38 // If there are multiple f's with the same name, set keeps the first 39 // one with documentation; conflicts are ignored. The boolean 40 // specifies whether to leave the AST untouched. 41 // 42 func (mset methodSet) set(f *ast.FuncDecl, preserveAST bool) { 43 name := f.Name.Name 44 if g := mset[name]; g != nil && g.Doc != "" { 45 // A function with the same name has already been registered; 46 // since it has documentation, assume f is simply another 47 // implementation and ignore it. This does not happen if the 48 // caller is using go/build.ScanDir to determine the list of 49 // files implementing a package. 50 return 51 } 52 // function doesn't exist or has no documentation; use f 53 recv := "" 54 if f.Recv != nil { 55 var typ ast.Expr 56 // be careful in case of incorrect ASTs 57 if list := f.Recv.List; len(list) == 1 { 58 typ = list[0].Type 59 } 60 recv = recvString(typ) 61 } 62 mset[name] = &Func{ 63 Doc: f.Doc.Text(), 64 Name: name, 65 Decl: f, 66 Recv: recv, 67 Orig: recv, 68 } 69 if !preserveAST { 70 f.Doc = nil // doc consumed - remove from AST 71 } 72 } 73 74 // add adds method m to the method set; m is ignored if the method set 75 // already contains a method with the same name at the same or a higher 76 // level than m. 77 // 78 func (mset methodSet) add(m *Func) { 79 old := mset[m.Name] 80 if old == nil || m.Level < old.Level { 81 mset[m.Name] = m 82 return 83 } 84 if m.Level == old.Level { 85 // conflict - mark it using a method with nil Decl 86 mset[m.Name] = &Func{ 87 Name: m.Name, 88 Level: m.Level, 89 } 90 } 91 } 92 93 // ---------------------------------------------------------------------------- 94 // Named types 95 96 // baseTypeName returns the name of the base type of x (or "") 97 // and whether the type is imported or not. 98 // 99 func baseTypeName(x ast.Expr) (name string, imported bool) { 100 switch t := x.(type) { 101 case *ast.Ident: 102 return t.Name, false 103 case *ast.SelectorExpr: 104 if _, ok := t.X.(*ast.Ident); ok { 105 // only possible for qualified type names; 106 // assume type is imported 107 return t.Sel.Name, true 108 } 109 case *ast.ParenExpr: 110 return baseTypeName(t.X) 111 case *ast.StarExpr: 112 return baseTypeName(t.X) 113 } 114 return 115 } 116 117 // An embeddedSet describes a set of embedded types. 118 type embeddedSet map[*namedType]bool 119 120 // A namedType represents a named unqualified (package local, or possibly 121 // predeclared) type. The namedType for a type name is always found via 122 // reader.lookupType. 123 // 124 type namedType struct { 125 doc string // doc comment for type 126 name string // type name 127 decl *ast.GenDecl // nil if declaration hasn't been seen yet 128 129 isEmbedded bool // true if this type is embedded 130 isStruct bool // true if this type is a struct 131 embedded embeddedSet // true if the embedded type is a pointer 132 133 // associated declarations 134 values []*Value // consts and vars 135 funcs methodSet 136 methods methodSet 137 } 138 139 // ---------------------------------------------------------------------------- 140 // AST reader 141 142 // reader accumulates documentation for a single package. 143 // It modifies the AST: Comments (declaration documentation) 144 // that have been collected by the reader are set to nil 145 // in the respective AST nodes so that they are not printed 146 // twice (once when printing the documentation and once when 147 // printing the corresponding AST node). 148 // 149 type reader struct { 150 mode Mode 151 152 // package properties 153 doc string // package documentation, if any 154 filenames []string 155 notes map[string][]*Note 156 157 // declarations 158 imports map[string]int 159 hasDotImp bool // if set, package contains a dot import 160 values []*Value // consts and vars 161 order int // sort order of const and var declarations (when we can't use a name) 162 types map[string]*namedType 163 funcs methodSet 164 165 // support for package-local error type declarations 166 errorDecl bool // if set, type "error" was declared locally 167 fixlist []*ast.InterfaceType // list of interfaces containing anonymous field "error" 168 } 169 170 func (r *reader) isVisible(name string) bool { 171 return r.mode&AllDecls != 0 || ast.IsExported(name) 172 } 173 174 // lookupType returns the base type with the given name. 175 // If the base type has not been encountered yet, a new 176 // type with the given name but no associated declaration 177 // is added to the type map. 178 // 179 func (r *reader) lookupType(name string) *namedType { 180 if name == "" || name == "_" { 181 return nil // no type docs for anonymous types 182 } 183 if typ, found := r.types[name]; found { 184 return typ 185 } 186 // type not found - add one without declaration 187 typ := &namedType{ 188 name: name, 189 embedded: make(embeddedSet), 190 funcs: make(methodSet), 191 methods: make(methodSet), 192 } 193 r.types[name] = typ 194 return typ 195 } 196 197 // recordAnonymousField registers fieldType as the type of an 198 // anonymous field in the parent type. If the field is imported 199 // (qualified name) or the parent is nil, the field is ignored. 200 // The function returns the field name. 201 // 202 func (r *reader) recordAnonymousField(parent *namedType, fieldType ast.Expr) (fname string) { 203 fname, imp := baseTypeName(fieldType) 204 if parent == nil || imp { 205 return 206 } 207 if ftype := r.lookupType(fname); ftype != nil { 208 ftype.isEmbedded = true 209 _, ptr := fieldType.(*ast.StarExpr) 210 parent.embedded[ftype] = ptr 211 } 212 return 213 } 214 215 func (r *reader) readDoc(comment *ast.CommentGroup) { 216 // By convention there should be only one package comment 217 // but collect all of them if there are more than one. 218 text := comment.Text() 219 if r.doc == "" { 220 r.doc = text 221 return 222 } 223 r.doc += "\n" + text 224 } 225 226 func (r *reader) remember(typ *ast.InterfaceType) { 227 r.fixlist = append(r.fixlist, typ) 228 } 229 230 func specNames(specs []ast.Spec) []string { 231 names := make([]string, 0, len(specs)) // reasonable estimate 232 for _, s := range specs { 233 // s guaranteed to be an *ast.ValueSpec by readValue 234 for _, ident := range s.(*ast.ValueSpec).Names { 235 names = append(names, ident.Name) 236 } 237 } 238 return names 239 } 240 241 // readValue processes a const or var declaration. 242 // 243 func (r *reader) readValue(decl *ast.GenDecl) { 244 // determine if decl should be associated with a type 245 // Heuristic: For each typed entry, determine the type name, if any. 246 // If there is exactly one type name that is sufficiently 247 // frequent, associate the decl with the respective type. 248 domName := "" 249 domFreq := 0 250 prev := "" 251 n := 0 252 for _, spec := range decl.Specs { 253 s, ok := spec.(*ast.ValueSpec) 254 if !ok { 255 continue // should not happen, but be conservative 256 } 257 name := "" 258 switch { 259 case s.Type != nil: 260 // a type is present; determine its name 261 if n, imp := baseTypeName(s.Type); !imp { 262 name = n 263 } 264 case decl.Tok == token.CONST && len(s.Values) == 0: 265 // no type or value is present but we have a constant declaration; 266 // use the previous type name (possibly the empty string) 267 name = prev 268 } 269 if name != "" { 270 // entry has a named type 271 if domName != "" && domName != name { 272 // more than one type name - do not associate 273 // with any type 274 domName = "" 275 break 276 } 277 domName = name 278 domFreq++ 279 } 280 prev = name 281 n++ 282 } 283 284 // nothing to do w/o a legal declaration 285 if n == 0 { 286 return 287 } 288 289 // determine values list with which to associate the Value for this decl 290 values := &r.values 291 const threshold = 0.75 292 if domName != "" && r.isVisible(domName) && domFreq >= int(float64(len(decl.Specs))*threshold) { 293 // typed entries are sufficiently frequent 294 if typ := r.lookupType(domName); typ != nil { 295 values = &typ.values // associate with that type 296 } 297 } 298 299 *values = append(*values, &Value{ 300 Doc: decl.Doc.Text(), 301 Names: specNames(decl.Specs), 302 Decl: decl, 303 order: r.order, 304 }) 305 if r.mode&PreserveAST == 0 { 306 decl.Doc = nil // doc consumed - remove from AST 307 } 308 // Note: It's important that the order used here is global because the cleanupTypes 309 // methods may move values associated with types back into the global list. If the 310 // order is list-specific, sorting is not deterministic because the same order value 311 // may appear multiple times (was bug, found when fixing #16153). 312 r.order++ 313 } 314 315 // fields returns a struct's fields or an interface's methods. 316 // 317 func fields(typ ast.Expr) (list []*ast.Field, isStruct bool) { 318 var fields *ast.FieldList 319 switch t := typ.(type) { 320 case *ast.StructType: 321 fields = t.Fields 322 isStruct = true 323 case *ast.InterfaceType: 324 fields = t.Methods 325 } 326 if fields != nil { 327 list = fields.List 328 } 329 return 330 } 331 332 // readType processes a type declaration. 333 // 334 func (r *reader) readType(decl *ast.GenDecl, spec *ast.TypeSpec) { 335 typ := r.lookupType(spec.Name.Name) 336 if typ == nil { 337 return // no name or blank name - ignore the type 338 } 339 340 // A type should be added at most once, so typ.decl 341 // should be nil - if it is not, simply overwrite it. 342 typ.decl = decl 343 344 // compute documentation 345 doc := spec.Doc 346 if doc == nil { 347 // no doc associated with the spec, use the declaration doc, if any 348 doc = decl.Doc 349 } 350 if r.mode&PreserveAST == 0 { 351 spec.Doc = nil // doc consumed - remove from AST 352 decl.Doc = nil // doc consumed - remove from AST 353 } 354 typ.doc = doc.Text() 355 356 // record anonymous fields (they may contribute methods) 357 // (some fields may have been recorded already when filtering 358 // exports, but that's ok) 359 var list []*ast.Field 360 list, typ.isStruct = fields(spec.Type) 361 for _, field := range list { 362 if len(field.Names) == 0 { 363 r.recordAnonymousField(typ, field.Type) 364 } 365 } 366 } 367 368 // isPredeclared reports whether n denotes a predeclared type. 369 // 370 func (r *reader) isPredeclared(n string) bool { 371 return predeclaredTypes[n] && r.types[n] == nil 372 } 373 374 // readFunc processes a func or method declaration. 375 // 376 func (r *reader) readFunc(fun *ast.FuncDecl) { 377 // strip function body if requested. 378 if r.mode&PreserveAST == 0 { 379 fun.Body = nil 380 } 381 382 // associate methods with the receiver type, if any 383 if fun.Recv != nil { 384 // method 385 if len(fun.Recv.List) == 0 { 386 // should not happen (incorrect AST); (See issue 17788) 387 // don't show this method 388 return 389 } 390 recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type) 391 if imp { 392 // should not happen (incorrect AST); 393 // don't show this method 394 return 395 } 396 if typ := r.lookupType(recvTypeName); typ != nil { 397 typ.methods.set(fun, r.mode&PreserveAST != 0) 398 } 399 // otherwise ignore the method 400 // TODO(gri): There may be exported methods of non-exported types 401 // that can be called because of exported values (consts, vars, or 402 // function results) of that type. Could determine if that is the 403 // case and then show those methods in an appropriate section. 404 return 405 } 406 407 // Associate factory functions with the first visible result type, as long as 408 // others are predeclared types. 409 if fun.Type.Results.NumFields() >= 1 { 410 var typ *namedType // type to associate the function with 411 numResultTypes := 0 412 for _, res := range fun.Type.Results.List { 413 factoryType := res.Type 414 if t, ok := factoryType.(*ast.ArrayType); ok { 415 // We consider functions that return slices or arrays of type 416 // T (or pointers to T) as factory functions of T. 417 factoryType = t.Elt 418 } 419 if n, imp := baseTypeName(factoryType); !imp && r.isVisible(n) && !r.isPredeclared(n) { 420 if t := r.lookupType(n); t != nil { 421 typ = t 422 numResultTypes++ 423 if numResultTypes > 1 { 424 break 425 } 426 } 427 } 428 } 429 // If there is exactly one result type, 430 // associate the function with that type. 431 if numResultTypes == 1 { 432 typ.funcs.set(fun, r.mode&PreserveAST != 0) 433 return 434 } 435 } 436 437 // just an ordinary function 438 r.funcs.set(fun, r.mode&PreserveAST != 0) 439 } 440 441 var ( 442 noteMarker = `([A-Z][A-Z]+)\(([^)]+)\):?` // MARKER(uid), MARKER at least 2 chars, uid at least 1 char 443 noteMarkerRx = newLazyRE(`^[ \t]*` + noteMarker) // MARKER(uid) at text start 444 noteCommentRx = newLazyRE(`^/[/*][ \t]*` + noteMarker) // MARKER(uid) at comment start 445 ) 446 447 // readNote collects a single note from a sequence of comments. 448 // 449 func (r *reader) readNote(list []*ast.Comment) { 450 text := (&ast.CommentGroup{List: list}).Text() 451 if m := noteMarkerRx.FindStringSubmatchIndex(text); m != nil { 452 // The note body starts after the marker. 453 // We remove any formatting so that we don't 454 // get spurious line breaks/indentation when 455 // showing the TODO body. 456 body := clean(text[m[1]:], keepNL) 457 if body != "" { 458 marker := text[m[2]:m[3]] 459 r.notes[marker] = append(r.notes[marker], &Note{ 460 Pos: list[0].Pos(), 461 End: list[len(list)-1].End(), 462 UID: text[m[4]:m[5]], 463 Body: body, 464 }) 465 } 466 } 467 } 468 469 // readNotes extracts notes from comments. 470 // A note must start at the beginning of a comment with "MARKER(uid):" 471 // and is followed by the note body (e.g., "// BUG(gri): fix this"). 472 // The note ends at the end of the comment group or at the start of 473 // another note in the same comment group, whichever comes first. 474 // 475 func (r *reader) readNotes(comments []*ast.CommentGroup) { 476 for _, group := range comments { 477 i := -1 // comment index of most recent note start, valid if >= 0 478 list := group.List 479 for j, c := range list { 480 if noteCommentRx.MatchString(c.Text) { 481 if i >= 0 { 482 r.readNote(list[i:j]) 483 } 484 i = j 485 } 486 } 487 if i >= 0 { 488 r.readNote(list[i:]) 489 } 490 } 491 } 492 493 // readFile adds the AST for a source file to the reader. 494 // 495 func (r *reader) readFile(src *ast.File) { 496 // add package documentation 497 if src.Doc != nil { 498 r.readDoc(src.Doc) 499 if r.mode&PreserveAST == 0 { 500 src.Doc = nil // doc consumed - remove from AST 501 } 502 } 503 504 // add all declarations but for functions which are processed in a separate pass 505 for _, decl := range src.Decls { 506 switch d := decl.(type) { 507 case *ast.GenDecl: 508 switch d.Tok { 509 case token.IMPORT: 510 // imports are handled individually 511 for _, spec := range d.Specs { 512 if s, ok := spec.(*ast.ImportSpec); ok { 513 if import_, err := strconv.Unquote(s.Path.Value); err == nil { 514 r.imports[import_] = 1 515 if s.Name != nil && s.Name.Name == "." { 516 r.hasDotImp = true 517 } 518 } 519 } 520 } 521 case token.CONST, token.VAR: 522 // constants and variables are always handled as a group 523 r.readValue(d) 524 case token.TYPE: 525 // types are handled individually 526 if len(d.Specs) == 1 && !d.Lparen.IsValid() { 527 // common case: single declaration w/o parentheses 528 // (if a single declaration is parenthesized, 529 // create a new fake declaration below, so that 530 // go/doc type declarations always appear w/o 531 // parentheses) 532 if s, ok := d.Specs[0].(*ast.TypeSpec); ok { 533 r.readType(d, s) 534 } 535 break 536 } 537 for _, spec := range d.Specs { 538 if s, ok := spec.(*ast.TypeSpec); ok { 539 // use an individual (possibly fake) declaration 540 // for each type; this also ensures that each type 541 // gets to (re-)use the declaration documentation 542 // if there's none associated with the spec itself 543 fake := &ast.GenDecl{ 544 Doc: d.Doc, 545 // don't use the existing TokPos because it 546 // will lead to the wrong selection range for 547 // the fake declaration if there are more 548 // than one type in the group (this affects 549 // src/cmd/godoc/godoc.go's posLink_urlFunc) 550 TokPos: s.Pos(), 551 Tok: token.TYPE, 552 Specs: []ast.Spec{s}, 553 } 554 r.readType(fake, s) 555 } 556 } 557 } 558 } 559 } 560 561 // collect MARKER(...): annotations 562 r.readNotes(src.Comments) 563 if r.mode&PreserveAST == 0 { 564 src.Comments = nil // consumed unassociated comments - remove from AST 565 } 566 } 567 568 func (r *reader) readPackage(pkg *ast.Package, mode Mode) { 569 // initialize reader 570 r.filenames = make([]string, len(pkg.Files)) 571 r.imports = make(map[string]int) 572 r.mode = mode 573 r.types = make(map[string]*namedType) 574 r.funcs = make(methodSet) 575 r.notes = make(map[string][]*Note) 576 577 // sort package files before reading them so that the 578 // result does not depend on map iteration order 579 i := 0 580 for filename := range pkg.Files { 581 r.filenames[i] = filename 582 i++ 583 } 584 sort.Strings(r.filenames) 585 586 // process files in sorted order 587 for _, filename := range r.filenames { 588 f := pkg.Files[filename] 589 if mode&AllDecls == 0 { 590 r.fileExports(f) 591 } 592 r.readFile(f) 593 } 594 595 // process functions now that we have better type information 596 for _, f := range pkg.Files { 597 for _, decl := range f.Decls { 598 if d, ok := decl.(*ast.FuncDecl); ok { 599 r.readFunc(d) 600 } 601 } 602 } 603 } 604 605 // ---------------------------------------------------------------------------- 606 // Types 607 608 func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func { 609 if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 { 610 return f // shouldn't happen, but be safe 611 } 612 613 // copy existing receiver field and set new type 614 newField := *f.Decl.Recv.List[0] 615 origPos := newField.Type.Pos() 616 _, origRecvIsPtr := newField.Type.(*ast.StarExpr) 617 newIdent := &ast.Ident{NamePos: origPos, Name: recvTypeName} 618 var typ ast.Expr = newIdent 619 if !embeddedIsPtr && origRecvIsPtr { 620 newIdent.NamePos++ // '*' is one character 621 typ = &ast.StarExpr{Star: origPos, X: newIdent} 622 } 623 newField.Type = typ 624 625 // copy existing receiver field list and set new receiver field 626 newFieldList := *f.Decl.Recv 627 newFieldList.List = []*ast.Field{&newField} 628 629 // copy existing function declaration and set new receiver field list 630 newFuncDecl := *f.Decl 631 newFuncDecl.Recv = &newFieldList 632 633 // copy existing function documentation and set new declaration 634 newF := *f 635 newF.Decl = &newFuncDecl 636 newF.Recv = recvString(typ) 637 // the Orig field never changes 638 newF.Level = level 639 640 return &newF 641 } 642 643 // collectEmbeddedMethods collects the embedded methods of typ in mset. 644 // 645 func (r *reader) collectEmbeddedMethods(mset methodSet, typ *namedType, recvTypeName string, embeddedIsPtr bool, level int, visited embeddedSet) { 646 visited[typ] = true 647 for embedded, isPtr := range typ.embedded { 648 // Once an embedded type is embedded as a pointer type 649 // all embedded types in those types are treated like 650 // pointer types for the purpose of the receiver type 651 // computation; i.e., embeddedIsPtr is sticky for this 652 // embedding hierarchy. 653 thisEmbeddedIsPtr := embeddedIsPtr || isPtr 654 for _, m := range embedded.methods { 655 // only top-level methods are embedded 656 if m.Level == 0 { 657 mset.add(customizeRecv(m, recvTypeName, thisEmbeddedIsPtr, level)) 658 } 659 } 660 if !visited[embedded] { 661 r.collectEmbeddedMethods(mset, embedded, recvTypeName, thisEmbeddedIsPtr, level+1, visited) 662 } 663 } 664 delete(visited, typ) 665 } 666 667 // computeMethodSets determines the actual method sets for each type encountered. 668 // 669 func (r *reader) computeMethodSets() { 670 for _, t := range r.types { 671 // collect embedded methods for t 672 if t.isStruct { 673 // struct 674 r.collectEmbeddedMethods(t.methods, t, t.name, false, 1, make(embeddedSet)) 675 } else { 676 // interface 677 // TODO(gri) fix this 678 } 679 } 680 681 // if error was declared locally, don't treat it as exported field anymore 682 if r.errorDecl { 683 for _, ityp := range r.fixlist { 684 removeErrorField(ityp) 685 } 686 } 687 } 688 689 // cleanupTypes removes the association of functions and methods with 690 // types that have no declaration. Instead, these functions and methods 691 // are shown at the package level. It also removes types with missing 692 // declarations or which are not visible. 693 // 694 func (r *reader) cleanupTypes() { 695 for _, t := range r.types { 696 visible := r.isVisible(t.name) 697 predeclared := predeclaredTypes[t.name] 698 699 if t.decl == nil && (predeclared || visible && (t.isEmbedded || r.hasDotImp)) { 700 // t.name is a predeclared type (and was not redeclared in this package), 701 // or it was embedded somewhere but its declaration is missing (because 702 // the AST is incomplete), or we have a dot-import (and all bets are off): 703 // move any associated values, funcs, and methods back to the top-level so 704 // that they are not lost. 705 // 1) move values 706 r.values = append(r.values, t.values...) 707 // 2) move factory functions 708 for name, f := range t.funcs { 709 // in a correct AST, package-level function names 710 // are all different - no need to check for conflicts 711 r.funcs[name] = f 712 } 713 // 3) move methods 714 if !predeclared { 715 for name, m := range t.methods { 716 // don't overwrite functions with the same name - drop them 717 if _, found := r.funcs[name]; !found { 718 r.funcs[name] = m 719 } 720 } 721 } 722 } 723 // remove types w/o declaration or which are not visible 724 if t.decl == nil || !visible { 725 delete(r.types, t.name) 726 } 727 } 728 } 729 730 // ---------------------------------------------------------------------------- 731 // Sorting 732 733 type data struct { 734 n int 735 swap func(i, j int) 736 less func(i, j int) bool 737 } 738 739 func (d *data) Len() int { return d.n } 740 func (d *data) Swap(i, j int) { d.swap(i, j) } 741 func (d *data) Less(i, j int) bool { return d.less(i, j) } 742 743 // sortBy is a helper function for sorting 744 func sortBy(less func(i, j int) bool, swap func(i, j int), n int) { 745 sort.Sort(&data{n, swap, less}) 746 } 747 748 func sortedKeys(m map[string]int) []string { 749 list := make([]string, len(m)) 750 i := 0 751 for key := range m { 752 list[i] = key 753 i++ 754 } 755 sort.Strings(list) 756 return list 757 } 758 759 // sortingName returns the name to use when sorting d into place. 760 // 761 func sortingName(d *ast.GenDecl) string { 762 if len(d.Specs) == 1 { 763 if s, ok := d.Specs[0].(*ast.ValueSpec); ok { 764 return s.Names[0].Name 765 } 766 } 767 return "" 768 } 769 770 func sortedValues(m []*Value, tok token.Token) []*Value { 771 list := make([]*Value, len(m)) // big enough in any case 772 i := 0 773 for _, val := range m { 774 if val.Decl.Tok == tok { 775 list[i] = val 776 i++ 777 } 778 } 779 list = list[0:i] 780 781 sortBy( 782 func(i, j int) bool { 783 if ni, nj := sortingName(list[i].Decl), sortingName(list[j].Decl); ni != nj { 784 return ni < nj 785 } 786 return list[i].order < list[j].order 787 }, 788 func(i, j int) { list[i], list[j] = list[j], list[i] }, 789 len(list), 790 ) 791 792 return list 793 } 794 795 func sortedTypes(m map[string]*namedType, allMethods bool) []*Type { 796 list := make([]*Type, len(m)) 797 i := 0 798 for _, t := range m { 799 list[i] = &Type{ 800 Doc: t.doc, 801 Name: t.name, 802 Decl: t.decl, 803 Consts: sortedValues(t.values, token.CONST), 804 Vars: sortedValues(t.values, token.VAR), 805 Funcs: sortedFuncs(t.funcs, true), 806 Methods: sortedFuncs(t.methods, allMethods), 807 } 808 i++ 809 } 810 811 sortBy( 812 func(i, j int) bool { return list[i].Name < list[j].Name }, 813 func(i, j int) { list[i], list[j] = list[j], list[i] }, 814 len(list), 815 ) 816 817 return list 818 } 819 820 func removeStar(s string) string { 821 if len(s) > 0 && s[0] == '*' { 822 return s[1:] 823 } 824 return s 825 } 826 827 func sortedFuncs(m methodSet, allMethods bool) []*Func { 828 list := make([]*Func, len(m)) 829 i := 0 830 for _, m := range m { 831 // determine which methods to include 832 switch { 833 case m.Decl == nil: 834 // exclude conflict entry 835 case allMethods, m.Level == 0, !ast.IsExported(removeStar(m.Orig)): 836 // forced inclusion, method not embedded, or method 837 // embedded but original receiver type not exported 838 list[i] = m 839 i++ 840 } 841 } 842 list = list[0:i] 843 sortBy( 844 func(i, j int) bool { return list[i].Name < list[j].Name }, 845 func(i, j int) { list[i], list[j] = list[j], list[i] }, 846 len(list), 847 ) 848 return list 849 } 850 851 // noteBodies returns a list of note body strings given a list of notes. 852 // This is only used to populate the deprecated Package.Bugs field. 853 // 854 func noteBodies(notes []*Note) []string { 855 var list []string 856 for _, n := range notes { 857 list = append(list, n.Body) 858 } 859 return list 860 } 861 862 // ---------------------------------------------------------------------------- 863 // Predeclared identifiers 864 865 // IsPredeclared reports whether s is a predeclared identifier. 866 func IsPredeclared(s string) bool { 867 return predeclaredTypes[s] || predeclaredFuncs[s] || predeclaredConstants[s] 868 } 869 870 var predeclaredTypes = map[string]bool{ 871 "bool": true, 872 "byte": true, 873 "complex64": true, 874 "complex128": true, 875 "error": true, 876 "float32": true, 877 "float64": true, 878 "int": true, 879 "int8": true, 880 "int16": true, 881 "int32": true, 882 "int64": true, 883 "rune": true, 884 "string": true, 885 "uint": true, 886 "uint8": true, 887 "uint16": true, 888 "uint32": true, 889 "uint64": true, 890 "uintptr": true, 891 } 892 893 var predeclaredFuncs = map[string]bool{ 894 "append": true, 895 "cap": true, 896 "close": true, 897 "complex": true, 898 "copy": true, 899 "delete": true, 900 "imag": true, 901 "len": true, 902 "make": true, 903 "new": true, 904 "panic": true, 905 "print": true, 906 "println": true, 907 "real": true, 908 "recover": true, 909 } 910 911 var predeclaredConstants = map[string]bool{ 912 "false": true, 913 "iota": true, 914 "nil": true, 915 "true": true, 916 }