gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/golang.org/x/tools/go/packages/packages.go (about) 1 // Copyright 2018 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 packages 6 7 // See doc.go for package documentation and implementation notes. 8 9 import ( 10 "context" 11 "encoding/json" 12 "fmt" 13 "go/ast" 14 "go/parser" 15 "go/scanner" 16 "go/token" 17 "go/types" 18 "io/ioutil" 19 "log" 20 "os" 21 "path/filepath" 22 "sync" 23 24 "golang.org/x/tools/go/gcexportdata" 25 ) 26 27 // A LoadMode specifies the amount of detail to return when loading. 28 // Higher-numbered modes cause Load to return more information, 29 // but may be slower. Load may return more information than requested. 30 type LoadMode int 31 32 const ( 33 // LoadFiles finds the packages and computes their source file lists. 34 // Package fields: ID, Name, Errors, GoFiles, and OtherFiles. 35 LoadFiles LoadMode = iota 36 37 // LoadImports adds import information for each package 38 // and its dependencies. 39 // Package fields added: Imports. 40 LoadImports 41 42 // LoadTypes adds type information for package-level 43 // declarations in the packages matching the patterns. 44 // Package fields added: Types, Fset, and IllTyped. 45 // This mode uses type information provided by the build system when 46 // possible, and may fill in the ExportFile field. 47 LoadTypes 48 49 // LoadSyntax adds typed syntax trees for the packages matching the patterns. 50 // Package fields added: Syntax, and TypesInfo, for direct pattern matches only. 51 LoadSyntax 52 53 // LoadAllSyntax adds typed syntax trees for the packages matching the patterns 54 // and all dependencies. 55 // Package fields added: Types, Fset, IllTyped, Syntax, and TypesInfo, 56 // for all packages in the import graph. 57 LoadAllSyntax 58 ) 59 60 // A Config specifies details about how packages should be loaded. 61 // The zero value is a valid configuration. 62 // Calls to Load do not modify this struct. 63 type Config struct { 64 // Mode controls the level of information returned for each package. 65 Mode LoadMode 66 67 // Context specifies the context for the load operation. 68 // If the context is cancelled, the loader may stop early 69 // and return an ErrCancelled error. 70 // If Context is nil, the load cannot be cancelled. 71 Context context.Context 72 73 // Dir is the directory in which to run the build system's query tool 74 // that provides information about the packages. 75 // If Dir is empty, the tool is run in the current directory. 76 Dir string 77 78 // Env is the environment to use when invoking the build system's query tool. 79 // If Env is nil, the current environment is used. 80 // As in os/exec's Cmd, only the last value in the slice for 81 // each environment key is used. To specify the setting of only 82 // a few variables, append to the current environment, as in: 83 // 84 // opt.Env = append(os.Environ(), "GOOS=plan9", "GOARCH=386") 85 // 86 Env []string 87 88 // BuildFlags is a list of command-line flags to be passed through to 89 // the build system's query tool. 90 BuildFlags []string 91 92 // Fset provides source position information for syntax trees and types. 93 // If Fset is nil, the loader will create a new FileSet. 94 Fset *token.FileSet 95 96 // ParseFile is called to read and parse each file 97 // when preparing a package's type-checked syntax tree. 98 // It must be safe to call ParseFile simultaneously from multiple goroutines. 99 // If ParseFile is nil, the loader will uses parser.ParseFile. 100 // 101 // ParseFile should parse the source from src and use filename only for 102 // recording position information. 103 // 104 // An application may supply a custom implementation of ParseFile 105 // to change the effective file contents or the behavior of the parser, 106 // or to modify the syntax tree. For example, selectively eliminating 107 // unwanted function bodies can significantly accelerate type checking. 108 ParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) 109 110 // If Tests is set, the loader includes not just the packages 111 // matching a particular pattern but also any related test packages, 112 // including test-only variants of the package and the test executable. 113 // 114 // For example, when using the go command, loading "fmt" with Tests=true 115 // returns four packages, with IDs "fmt" (the standard package), 116 // "fmt [fmt.test]" (the package as compiled for the test), 117 // "fmt_test" (the test functions from source files in package fmt_test), 118 // and "fmt.test" (the test binary). 119 // 120 // In build systems with explicit names for tests, 121 // setting Tests may have no effect. 122 Tests bool 123 124 // Overlay provides a mapping of absolute file paths to file contents. 125 // If the file with the given path already exists, the parser will use the 126 // alternative file contents provided by the map. 127 // 128 // Overlays provide incomplete support for when a given file doesn't 129 // already exist on disk. See the package doc above for more details. 130 Overlay map[string][]byte 131 } 132 133 // driver is the type for functions that query the build system for the 134 // packages named by the patterns. 135 type driver func(cfg *Config, patterns ...string) (*driverResponse, error) 136 137 // driverResponse contains the results for a driver query. 138 type driverResponse struct { 139 // Sizes, if not nil, is the types.Sizes to use when type checking. 140 Sizes *types.StdSizes 141 142 // Roots is the set of package IDs that make up the root packages. 143 // We have to encode this separately because when we encode a single package 144 // we cannot know if it is one of the roots as that requires knowledge of the 145 // graph it is part of. 146 Roots []string `json:",omitempty"` 147 148 // Packages is the full set of packages in the graph. 149 // The packages are not connected into a graph. 150 // The Imports if populated will be stubs that only have their ID set. 151 // Imports will be connected and then type and syntax information added in a 152 // later pass (see refine). 153 Packages []*Package 154 } 155 156 // Load loads and returns the Go packages named by the given patterns. 157 // 158 // Config specifies loading options; 159 // nil behaves the same as an empty Config. 160 // 161 // Load returns an error if any of the patterns was invalid 162 // as defined by the underlying build system. 163 // It may return an empty list of packages without an error, 164 // for instance for an empty expansion of a valid wildcard. 165 // Errors associated with a particular package are recorded in the 166 // corresponding Package's Errors list, and do not cause Load to 167 // return an error. Clients may need to handle such errors before 168 // proceeding with further analysis. The PrintErrors function is 169 // provided for convenient display of all errors. 170 func Load(cfg *Config, patterns ...string) ([]*Package, error) { 171 l := newLoader(cfg) 172 response, err := defaultDriver(&l.Config, patterns...) 173 if err != nil { 174 return nil, err 175 } 176 l.sizes = response.Sizes 177 return l.refine(response.Roots, response.Packages...) 178 } 179 180 // defaultDriver is a driver that looks for an external driver binary, and if 181 // it does not find it falls back to the built in go list driver. 182 func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, error) { 183 driver := findExternalDriver(cfg) 184 if driver == nil { 185 driver = goListDriver 186 } 187 return driver(cfg, patterns...) 188 } 189 190 // A Package describes a loaded Go package. 191 type Package struct { 192 // ID is a unique identifier for a package, 193 // in a syntax provided by the underlying build system. 194 // 195 // Because the syntax varies based on the build system, 196 // clients should treat IDs as opaque and not attempt to 197 // interpret them. 198 ID string 199 200 // Name is the package name as it appears in the package source code. 201 Name string 202 203 // PkgPath is the package path as used by the go/types package. 204 PkgPath string 205 206 // Errors contains any errors encountered querying the metadata 207 // of the package, or while parsing or type-checking its files. 208 Errors []Error 209 210 // GoFiles lists the absolute file paths of the package's Go source files. 211 GoFiles []string 212 213 // CompiledGoFiles lists the absolute file paths of the package's source 214 // files that were presented to the compiler. 215 // This may differ from GoFiles if files are processed before compilation. 216 CompiledGoFiles []string 217 218 // OtherFiles lists the absolute file paths of the package's non-Go source files, 219 // including assembly, C, C++, Fortran, Objective-C, SWIG, and so on. 220 OtherFiles []string 221 222 // ExportFile is the absolute path to a file containing type 223 // information for the package as provided by the build system. 224 ExportFile string 225 226 // Imports maps import paths appearing in the package's Go source files 227 // to corresponding loaded Packages. 228 Imports map[string]*Package 229 230 // Types provides type information for the package. 231 // Modes LoadTypes and above set this field for packages matching the 232 // patterns; type information for dependencies may be missing or incomplete. 233 // Mode LoadAllSyntax sets this field for all packages, including dependencies. 234 Types *types.Package 235 236 // Fset provides position information for Types, TypesInfo, and Syntax. 237 // It is set only when Types is set. 238 Fset *token.FileSet 239 240 // IllTyped indicates whether the package or any dependency contains errors. 241 // It is set only when Types is set. 242 IllTyped bool 243 244 // Syntax is the package's syntax trees, for the files listed in CompiledGoFiles. 245 // 246 // Mode LoadSyntax sets this field for packages matching the patterns. 247 // Mode LoadAllSyntax sets this field for all packages, including dependencies. 248 Syntax []*ast.File 249 250 // TypesInfo provides type information about the package's syntax trees. 251 // It is set only when Syntax is set. 252 TypesInfo *types.Info 253 254 // TypesSizes provides the effective size function for types in TypesInfo. 255 TypesSizes types.Sizes 256 } 257 258 // An Error describes a problem with a package's metadata, syntax, or types. 259 type Error struct { 260 Pos string // "file:line:col" or "file:line" or "" or "-" 261 Msg string 262 Kind ErrorKind 263 } 264 265 // ErrorKind describes the source of the error, allowing the user to 266 // differentiate between errors generated by the driver, the parser, or the 267 // type-checker. 268 type ErrorKind int 269 270 const ( 271 UnknownError ErrorKind = iota 272 ListError 273 ParseError 274 TypeError 275 ) 276 277 func (err Error) Error() string { 278 pos := err.Pos 279 if pos == "" { 280 pos = "-" // like token.Position{}.String() 281 } 282 return pos + ": " + err.Msg 283 } 284 285 // flatPackage is the JSON form of Package 286 // It drops all the type and syntax fields, and transforms the Imports 287 // 288 // TODO(adonovan): identify this struct with Package, effectively 289 // publishing the JSON protocol. 290 type flatPackage struct { 291 ID string 292 Name string `json:",omitempty"` 293 PkgPath string `json:",omitempty"` 294 Errors []Error `json:",omitempty"` 295 GoFiles []string `json:",omitempty"` 296 CompiledGoFiles []string `json:",omitempty"` 297 OtherFiles []string `json:",omitempty"` 298 ExportFile string `json:",omitempty"` 299 Imports map[string]string `json:",omitempty"` 300 } 301 302 // MarshalJSON returns the Package in its JSON form. 303 // For the most part, the structure fields are written out unmodified, and 304 // the type and syntax fields are skipped. 305 // The imports are written out as just a map of path to package id. 306 // The errors are written using a custom type that tries to preserve the 307 // structure of error types we know about. 308 // 309 // This method exists to enable support for additional build systems. It is 310 // not intended for use by clients of the API and we may change the format. 311 func (p *Package) MarshalJSON() ([]byte, error) { 312 flat := &flatPackage{ 313 ID: p.ID, 314 Name: p.Name, 315 PkgPath: p.PkgPath, 316 Errors: p.Errors, 317 GoFiles: p.GoFiles, 318 CompiledGoFiles: p.CompiledGoFiles, 319 OtherFiles: p.OtherFiles, 320 ExportFile: p.ExportFile, 321 } 322 if len(p.Imports) > 0 { 323 flat.Imports = make(map[string]string, len(p.Imports)) 324 for path, ipkg := range p.Imports { 325 flat.Imports[path] = ipkg.ID 326 } 327 } 328 return json.Marshal(flat) 329 } 330 331 // UnmarshalJSON reads in a Package from its JSON format. 332 // See MarshalJSON for details about the format accepted. 333 func (p *Package) UnmarshalJSON(b []byte) error { 334 flat := &flatPackage{} 335 if err := json.Unmarshal(b, &flat); err != nil { 336 return err 337 } 338 *p = Package{ 339 ID: flat.ID, 340 Name: flat.Name, 341 PkgPath: flat.PkgPath, 342 Errors: flat.Errors, 343 GoFiles: flat.GoFiles, 344 CompiledGoFiles: flat.CompiledGoFiles, 345 OtherFiles: flat.OtherFiles, 346 ExportFile: flat.ExportFile, 347 } 348 if len(flat.Imports) > 0 { 349 p.Imports = make(map[string]*Package, len(flat.Imports)) 350 for path, id := range flat.Imports { 351 p.Imports[path] = &Package{ID: id} 352 } 353 } 354 return nil 355 } 356 357 func (p *Package) String() string { return p.ID } 358 359 // loaderPackage augments Package with state used during the loading phase 360 type loaderPackage struct { 361 *Package 362 importErrors map[string]error // maps each bad import to its error 363 loadOnce sync.Once 364 color uint8 // for cycle detection 365 needsrc bool // load from source (Mode >= LoadTypes) 366 needtypes bool // type information is either requested or depended on 367 initial bool // package was matched by a pattern 368 } 369 370 // loader holds the working state of a single call to load. 371 type loader struct { 372 pkgs map[string]*loaderPackage 373 Config 374 sizes types.Sizes 375 exportMu sync.Mutex // enforces mutual exclusion of exportdata operations 376 } 377 378 func newLoader(cfg *Config) *loader { 379 ld := &loader{} 380 if cfg != nil { 381 ld.Config = *cfg 382 } 383 if ld.Config.Env == nil { 384 ld.Config.Env = os.Environ() 385 } 386 if ld.Context == nil { 387 ld.Context = context.Background() 388 } 389 if ld.Dir == "" { 390 if dir, err := os.Getwd(); err == nil { 391 ld.Dir = dir 392 } 393 } 394 395 if ld.Mode >= LoadTypes { 396 if ld.Fset == nil { 397 ld.Fset = token.NewFileSet() 398 } 399 400 // ParseFile is required even in LoadTypes mode 401 // because we load source if export data is missing. 402 if ld.ParseFile == nil { 403 ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) { 404 var isrc interface{} 405 if src != nil { 406 isrc = src 407 } 408 const mode = parser.AllErrors | parser.ParseComments 409 return parser.ParseFile(fset, filename, isrc, mode) 410 } 411 } 412 } 413 return ld 414 } 415 416 // refine connects the supplied packages into a graph and then adds type and 417 // and syntax information as requested by the LoadMode. 418 func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) { 419 rootMap := make(map[string]int, len(roots)) 420 for i, root := range roots { 421 rootMap[root] = i 422 } 423 ld.pkgs = make(map[string]*loaderPackage) 424 // first pass, fixup and build the map and roots 425 var initial = make([]*loaderPackage, len(roots)) 426 for _, pkg := range list { 427 rootIndex := -1 428 if i, found := rootMap[pkg.ID]; found { 429 rootIndex = i 430 } 431 lpkg := &loaderPackage{ 432 Package: pkg, 433 needtypes: ld.Mode >= LoadAllSyntax || 434 ld.Mode >= LoadTypes && rootIndex >= 0, 435 needsrc: ld.Mode >= LoadAllSyntax || 436 ld.Mode >= LoadSyntax && rootIndex >= 0 || 437 len(ld.Overlay) > 0 || // Overlays can invalidate export data. TODO(matloob): make this check fine-grained based on dependencies on overlaid files 438 pkg.ExportFile == "" && pkg.PkgPath != "unsafe", 439 } 440 ld.pkgs[lpkg.ID] = lpkg 441 if rootIndex >= 0 { 442 initial[rootIndex] = lpkg 443 lpkg.initial = true 444 } 445 } 446 for i, root := range roots { 447 if initial[i] == nil { 448 return nil, fmt.Errorf("root package %v is missing", root) 449 } 450 } 451 452 // Materialize the import graph. 453 454 const ( 455 white = 0 // new 456 grey = 1 // in progress 457 black = 2 // complete 458 ) 459 460 // visit traverses the import graph, depth-first, 461 // and materializes the graph as Packages.Imports. 462 // 463 // Valid imports are saved in the Packages.Import map. 464 // Invalid imports (cycles and missing nodes) are saved in the importErrors map. 465 // Thus, even in the presence of both kinds of errors, the Import graph remains a DAG. 466 // 467 // visit returns whether the package needs src or has a transitive 468 // dependency on a package that does. These are the only packages 469 // for which we load source code. 470 var stack []*loaderPackage 471 var visit func(lpkg *loaderPackage) bool 472 var srcPkgs []*loaderPackage 473 visit = func(lpkg *loaderPackage) bool { 474 switch lpkg.color { 475 case black: 476 return lpkg.needsrc 477 case grey: 478 panic("internal error: grey node") 479 } 480 lpkg.color = grey 481 stack = append(stack, lpkg) // push 482 stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports 483 lpkg.Imports = make(map[string]*Package, len(stubs)) 484 for importPath, ipkg := range stubs { 485 var importErr error 486 imp := ld.pkgs[ipkg.ID] 487 if imp == nil { 488 // (includes package "C" when DisableCgo) 489 importErr = fmt.Errorf("missing package: %q", ipkg.ID) 490 } else if imp.color == grey { 491 importErr = fmt.Errorf("import cycle: %s", stack) 492 } 493 if importErr != nil { 494 if lpkg.importErrors == nil { 495 lpkg.importErrors = make(map[string]error) 496 } 497 lpkg.importErrors[importPath] = importErr 498 continue 499 } 500 501 if visit(imp) { 502 lpkg.needsrc = true 503 } 504 lpkg.Imports[importPath] = imp.Package 505 } 506 if lpkg.needsrc { 507 srcPkgs = append(srcPkgs, lpkg) 508 } 509 stack = stack[:len(stack)-1] // pop 510 lpkg.color = black 511 512 return lpkg.needsrc 513 } 514 515 if ld.Mode < LoadImports { 516 //we do this to drop the stub import packages that we are not even going to try to resolve 517 for _, lpkg := range initial { 518 lpkg.Imports = nil 519 } 520 } else { 521 // For each initial package, create its import DAG. 522 for _, lpkg := range initial { 523 visit(lpkg) 524 } 525 } 526 for _, lpkg := range srcPkgs { 527 // Complete type information is required for the 528 // immediate dependencies of each source package. 529 for _, ipkg := range lpkg.Imports { 530 imp := ld.pkgs[ipkg.ID] 531 imp.needtypes = true 532 } 533 } 534 // Load type data if needed, starting at 535 // the initial packages (roots of the import DAG). 536 if ld.Mode >= LoadTypes { 537 var wg sync.WaitGroup 538 for _, lpkg := range initial { 539 wg.Add(1) 540 go func(lpkg *loaderPackage) { 541 ld.loadRecursive(lpkg) 542 wg.Done() 543 }(lpkg) 544 } 545 wg.Wait() 546 } 547 548 result := make([]*Package, len(initial)) 549 for i, lpkg := range initial { 550 result[i] = lpkg.Package 551 } 552 return result, nil 553 } 554 555 // loadRecursive loads the specified package and its dependencies, 556 // recursively, in parallel, in topological order. 557 // It is atomic and idempotent. 558 // Precondition: ld.Mode >= LoadTypes. 559 func (ld *loader) loadRecursive(lpkg *loaderPackage) { 560 lpkg.loadOnce.Do(func() { 561 // Load the direct dependencies, in parallel. 562 var wg sync.WaitGroup 563 for _, ipkg := range lpkg.Imports { 564 imp := ld.pkgs[ipkg.ID] 565 wg.Add(1) 566 go func(imp *loaderPackage) { 567 ld.loadRecursive(imp) 568 wg.Done() 569 }(imp) 570 } 571 wg.Wait() 572 573 ld.loadPackage(lpkg) 574 }) 575 } 576 577 // loadPackage loads the specified package. 578 // It must be called only once per Package, 579 // after immediate dependencies are loaded. 580 // Precondition: ld.Mode >= LoadTypes. 581 func (ld *loader) loadPackage(lpkg *loaderPackage) { 582 if lpkg.PkgPath == "unsafe" { 583 // Fill in the blanks to avoid surprises. 584 lpkg.Types = types.Unsafe 585 lpkg.Fset = ld.Fset 586 lpkg.Syntax = []*ast.File{} 587 lpkg.TypesInfo = new(types.Info) 588 lpkg.TypesSizes = ld.sizes 589 return 590 } 591 592 // Call NewPackage directly with explicit name. 593 // This avoids skew between golist and go/types when the files' 594 // package declarations are inconsistent. 595 lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name) 596 lpkg.Fset = ld.Fset 597 598 // Subtle: we populate all Types fields with an empty Package 599 // before loading export data so that export data processing 600 // never has to create a types.Package for an indirect dependency, 601 // which would then require that such created packages be explicitly 602 // inserted back into the Import graph as a final step after export data loading. 603 // The Diamond test exercises this case. 604 if !lpkg.needtypes { 605 return 606 } 607 if !lpkg.needsrc { 608 ld.loadFromExportData(lpkg) 609 return // not a source package, don't get syntax trees 610 } 611 612 appendError := func(err error) { 613 // Convert various error types into the one true Error. 614 var errs []Error 615 switch err := err.(type) { 616 case Error: 617 // from driver 618 errs = append(errs, err) 619 620 case *os.PathError: 621 // from parser 622 errs = append(errs, Error{ 623 Pos: err.Path + ":1", 624 Msg: err.Err.Error(), 625 Kind: ParseError, 626 }) 627 628 case scanner.ErrorList: 629 // from parser 630 for _, err := range err { 631 errs = append(errs, Error{ 632 Pos: err.Pos.String(), 633 Msg: err.Msg, 634 Kind: ParseError, 635 }) 636 } 637 638 case types.Error: 639 // from type checker 640 errs = append(errs, Error{ 641 Pos: err.Fset.Position(err.Pos).String(), 642 Msg: err.Msg, 643 Kind: TypeError, 644 }) 645 646 default: 647 // unexpected impoverished error from parser? 648 errs = append(errs, Error{ 649 Pos: "-", 650 Msg: err.Error(), 651 Kind: UnknownError, 652 }) 653 654 // If you see this error message, please file a bug. 655 log.Printf("internal error: error %q (%T) without position", err, err) 656 } 657 658 lpkg.Errors = append(lpkg.Errors, errs...) 659 } 660 661 files, errs := ld.parseFiles(lpkg.CompiledGoFiles) 662 for _, err := range errs { 663 appendError(err) 664 } 665 666 lpkg.Syntax = files 667 668 lpkg.TypesInfo = &types.Info{ 669 Types: make(map[ast.Expr]types.TypeAndValue), 670 Defs: make(map[*ast.Ident]types.Object), 671 Uses: make(map[*ast.Ident]types.Object), 672 Implicits: make(map[ast.Node]types.Object), 673 Scopes: make(map[ast.Node]*types.Scope), 674 Selections: make(map[*ast.SelectorExpr]*types.Selection), 675 } 676 lpkg.TypesSizes = ld.sizes 677 678 importer := importerFunc(func(path string) (*types.Package, error) { 679 if path == "unsafe" { 680 return types.Unsafe, nil 681 } 682 683 // The imports map is keyed by import path. 684 ipkg := lpkg.Imports[path] 685 if ipkg == nil { 686 if err := lpkg.importErrors[path]; err != nil { 687 return nil, err 688 } 689 // There was skew between the metadata and the 690 // import declarations, likely due to an edit 691 // race, or because the ParseFile feature was 692 // used to supply alternative file contents. 693 return nil, fmt.Errorf("no metadata for %s", path) 694 } 695 696 if ipkg.Types != nil && ipkg.Types.Complete() { 697 return ipkg.Types, nil 698 } 699 log.Fatalf("internal error: nil Pkg importing %q from %q", path, lpkg) 700 panic("unreachable") 701 }) 702 703 // type-check 704 tc := &types.Config{ 705 Importer: importer, 706 707 // Type-check bodies of functions only in non-initial packages. 708 // Example: for import graph A->B->C and initial packages {A,C}, 709 // we can ignore function bodies in B. 710 IgnoreFuncBodies: ld.Mode < LoadAllSyntax && !lpkg.initial, 711 712 Error: appendError, 713 Sizes: ld.sizes, 714 } 715 types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) 716 717 lpkg.importErrors = nil // no longer needed 718 719 // If !Cgo, the type-checker uses FakeImportC mode, so 720 // it doesn't invoke the importer for import "C", 721 // nor report an error for the import, 722 // or for any undefined C.f reference. 723 // We must detect this explicitly and correctly 724 // mark the package as IllTyped (by reporting an error). 725 // TODO(adonovan): if these errors are annoying, 726 // we could just set IllTyped quietly. 727 if tc.FakeImportC { 728 outer: 729 for _, f := range lpkg.Syntax { 730 for _, imp := range f.Imports { 731 if imp.Path.Value == `"C"` { 732 err := types.Error{Fset: ld.Fset, Pos: imp.Pos(), Msg: `import "C" ignored`} 733 appendError(err) 734 break outer 735 } 736 } 737 } 738 } 739 740 // Record accumulated errors. 741 illTyped := len(lpkg.Errors) > 0 742 if !illTyped { 743 for _, imp := range lpkg.Imports { 744 if imp.IllTyped { 745 illTyped = true 746 break 747 } 748 } 749 } 750 lpkg.IllTyped = illTyped 751 } 752 753 // An importFunc is an implementation of the single-method 754 // types.Importer interface based on a function value. 755 type importerFunc func(path string) (*types.Package, error) 756 757 func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) } 758 759 // We use a counting semaphore to limit 760 // the number of parallel I/O calls per process. 761 var ioLimit = make(chan bool, 20) 762 763 // parseFiles reads and parses the Go source files and returns the ASTs 764 // of the ones that could be at least partially parsed, along with a 765 // list of I/O and parse errors encountered. 766 // 767 // Because files are scanned in parallel, the token.Pos 768 // positions of the resulting ast.Files are not ordered. 769 // 770 func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) { 771 var wg sync.WaitGroup 772 n := len(filenames) 773 parsed := make([]*ast.File, n) 774 errors := make([]error, n) 775 for i, file := range filenames { 776 wg.Add(1) 777 go func(i int, filename string) { 778 ioLimit <- true // wait 779 // ParseFile may return both an AST and an error. 780 var src []byte 781 for f, contents := range ld.Config.Overlay { 782 if sameFile(f, filename) { 783 src = contents 784 } 785 } 786 var err error 787 if src == nil { 788 src, err = ioutil.ReadFile(filename) 789 } 790 if err != nil { 791 parsed[i], errors[i] = nil, err 792 } else { 793 parsed[i], errors[i] = ld.ParseFile(ld.Fset, filename, src) 794 } 795 <-ioLimit // signal 796 wg.Done() 797 }(i, file) 798 } 799 wg.Wait() 800 801 // Eliminate nils, preserving order. 802 var o int 803 for _, f := range parsed { 804 if f != nil { 805 parsed[o] = f 806 o++ 807 } 808 } 809 parsed = parsed[:o] 810 811 o = 0 812 for _, err := range errors { 813 if err != nil { 814 errors[o] = err 815 o++ 816 } 817 } 818 errors = errors[:o] 819 820 return parsed, errors 821 } 822 823 // sameFile returns true if x and y have the same basename and denote 824 // the same file. 825 // 826 func sameFile(x, y string) bool { 827 if x == y { 828 // It could be the case that y doesn't exist. 829 // For instance, it may be an overlay file that 830 // hasn't been written to disk. To handle that case 831 // let x == y through. (We added the exact absolute path 832 // string to the CompiledGoFiles list, so the unwritten 833 // overlay case implies x==y.) 834 return true 835 } 836 if filepath.Base(x) == filepath.Base(y) { // (optimisation) 837 if xi, err := os.Stat(x); err == nil { 838 if yi, err := os.Stat(y); err == nil { 839 return os.SameFile(xi, yi) 840 } 841 } 842 } 843 return false 844 } 845 846 // loadFromExportData returns type information for the specified 847 // package, loading it from an export data file on the first request. 848 func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error) { 849 if lpkg.PkgPath == "" { 850 log.Fatalf("internal error: Package %s has no PkgPath", lpkg) 851 } 852 853 // Because gcexportdata.Read has the potential to create or 854 // modify the types.Package for each node in the transitive 855 // closure of dependencies of lpkg, all exportdata operations 856 // must be sequential. (Finer-grained locking would require 857 // changes to the gcexportdata API.) 858 // 859 // The exportMu lock guards the Package.Pkg field and the 860 // types.Package it points to, for each Package in the graph. 861 // 862 // Not all accesses to Package.Pkg need to be protected by exportMu: 863 // graph ordering ensures that direct dependencies of source 864 // packages are fully loaded before the importer reads their Pkg field. 865 ld.exportMu.Lock() 866 defer ld.exportMu.Unlock() 867 868 if tpkg := lpkg.Types; tpkg != nil && tpkg.Complete() { 869 return tpkg, nil // cache hit 870 } 871 872 lpkg.IllTyped = true // fail safe 873 874 if lpkg.ExportFile == "" { 875 // Errors while building export data will have been printed to stderr. 876 return nil, fmt.Errorf("no export data file") 877 } 878 f, err := os.Open(lpkg.ExportFile) 879 if err != nil { 880 return nil, err 881 } 882 defer f.Close() 883 884 // Read gc export data. 885 // 886 // We don't currently support gccgo export data because all 887 // underlying workspaces use the gc toolchain. (Even build 888 // systems that support gccgo don't use it for workspace 889 // queries.) 890 r, err := gcexportdata.NewReader(f) 891 if err != nil { 892 return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) 893 } 894 895 // Build the view. 896 // 897 // The gcexportdata machinery has no concept of package ID. 898 // It identifies packages by their PkgPath, which although not 899 // globally unique is unique within the scope of one invocation 900 // of the linker, type-checker, or gcexportdata. 901 // 902 // So, we must build a PkgPath-keyed view of the global 903 // (conceptually ID-keyed) cache of packages and pass it to 904 // gcexportdata. The view must contain every existing 905 // package that might possibly be mentioned by the 906 // current package---its transitive closure. 907 // 908 // In loadPackage, we unconditionally create a types.Package for 909 // each dependency so that export data loading does not 910 // create new ones. 911 // 912 // TODO(adonovan): it would be simpler and more efficient 913 // if the export data machinery invoked a callback to 914 // get-or-create a package instead of a map. 915 // 916 view := make(map[string]*types.Package) // view seen by gcexportdata 917 seen := make(map[*loaderPackage]bool) // all visited packages 918 var visit func(pkgs map[string]*Package) 919 visit = func(pkgs map[string]*Package) { 920 for _, p := range pkgs { 921 lpkg := ld.pkgs[p.ID] 922 if !seen[lpkg] { 923 seen[lpkg] = true 924 view[lpkg.PkgPath] = lpkg.Types 925 visit(lpkg.Imports) 926 } 927 } 928 } 929 visit(lpkg.Imports) 930 931 viewLen := len(view) + 1 // adding the self package 932 // Parse the export data. 933 // (May modify incomplete packages in view but not create new ones.) 934 tpkg, err := gcexportdata.Read(r, ld.Fset, view, lpkg.PkgPath) 935 if err != nil { 936 return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) 937 } 938 if viewLen != len(view) { 939 log.Fatalf("Unexpected package creation during export data loading") 940 } 941 942 lpkg.Types = tpkg 943 lpkg.IllTyped = false 944 945 return tpkg, nil 946 } 947 948 func usesExportData(cfg *Config) bool { 949 return LoadTypes <= cfg.Mode && cfg.Mode < LoadAllSyntax 950 }