github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/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 "strings" 23 "sync" 24 "time" 25 26 "github.com/powerman/golang-tools/go/gcexportdata" 27 "github.com/powerman/golang-tools/internal/gocommand" 28 "github.com/powerman/golang-tools/internal/packagesinternal" 29 "github.com/powerman/golang-tools/internal/typeparams" 30 "github.com/powerman/golang-tools/internal/typesinternal" 31 ) 32 33 // A LoadMode controls the amount of detail to return when loading. 34 // The bits below can be combined to specify which fields should be 35 // filled in the result packages. 36 // The zero value is a special case, equivalent to combining 37 // the NeedName, NeedFiles, and NeedCompiledGoFiles bits. 38 // ID and Errors (if present) will always be filled. 39 // Load may return more information than requested. 40 type LoadMode int 41 42 const ( 43 // NeedName adds Name and PkgPath. 44 NeedName LoadMode = 1 << iota 45 46 // NeedFiles adds GoFiles and OtherFiles. 47 NeedFiles 48 49 // NeedCompiledGoFiles adds CompiledGoFiles. 50 NeedCompiledGoFiles 51 52 // NeedImports adds Imports. If NeedDeps is not set, the Imports field will contain 53 // "placeholder" Packages with only the ID set. 54 NeedImports 55 56 // NeedDeps adds the fields requested by the LoadMode in the packages in Imports. 57 NeedDeps 58 59 // NeedExportFile adds ExportFile. 60 NeedExportFile 61 62 // NeedTypes adds Types, Fset, and IllTyped. 63 NeedTypes 64 65 // NeedSyntax adds Syntax. 66 NeedSyntax 67 68 // NeedTypesInfo adds TypesInfo. 69 NeedTypesInfo 70 71 // NeedTypesSizes adds TypesSizes. 72 NeedTypesSizes 73 74 // typecheckCgo enables full support for type checking cgo. Requires Go 1.15+. 75 // Modifies CompiledGoFiles and Types, and has no effect on its own. 76 typecheckCgo 77 78 // NeedModule adds Module. 79 NeedModule 80 81 // NeedEmbedFiles adds EmbedFiles. 82 NeedEmbedFiles 83 84 // NeedEmbedPatterns adds EmbedPatterns. 85 NeedEmbedPatterns 86 ) 87 88 const ( 89 // Deprecated: LoadFiles exists for historical compatibility 90 // and should not be used. Please directly specify the needed fields using the Need values. 91 LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles 92 93 // Deprecated: LoadImports exists for historical compatibility 94 // and should not be used. Please directly specify the needed fields using the Need values. 95 LoadImports = LoadFiles | NeedImports 96 97 // Deprecated: LoadTypes exists for historical compatibility 98 // and should not be used. Please directly specify the needed fields using the Need values. 99 LoadTypes = LoadImports | NeedTypes | NeedTypesSizes 100 101 // Deprecated: LoadSyntax exists for historical compatibility 102 // and should not be used. Please directly specify the needed fields using the Need values. 103 LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo 104 105 // Deprecated: LoadAllSyntax exists for historical compatibility 106 // and should not be used. Please directly specify the needed fields using the Need values. 107 LoadAllSyntax = LoadSyntax | NeedDeps 108 109 // Deprecated: NeedExportsFile is a historical misspelling of NeedExportFile. 110 NeedExportsFile = NeedExportFile 111 ) 112 113 // A Config specifies details about how packages should be loaded. 114 // The zero value is a valid configuration. 115 // Calls to Load do not modify this struct. 116 type Config struct { 117 // Mode controls the level of information returned for each package. 118 Mode LoadMode 119 120 // Context specifies the context for the load operation. 121 // If the context is cancelled, the loader may stop early 122 // and return an ErrCancelled error. 123 // If Context is nil, the load cannot be cancelled. 124 Context context.Context 125 126 // Logf is the logger for the config. 127 // If the user provides a logger, debug logging is enabled. 128 // If the GOPACKAGESDEBUG environment variable is set to true, 129 // but the logger is nil, default to log.Printf. 130 Logf func(format string, args ...interface{}) 131 132 // Dir is the directory in which to run the build system's query tool 133 // that provides information about the packages. 134 // If Dir is empty, the tool is run in the current directory. 135 Dir string 136 137 // Env is the environment to use when invoking the build system's query tool. 138 // If Env is nil, the current environment is used. 139 // As in os/exec's Cmd, only the last value in the slice for 140 // each environment key is used. To specify the setting of only 141 // a few variables, append to the current environment, as in: 142 // 143 // opt.Env = append(os.Environ(), "GOOS=plan9", "GOARCH=386") 144 // 145 Env []string 146 147 // gocmdRunner guards go command calls from concurrency errors. 148 gocmdRunner *gocommand.Runner 149 150 // BuildFlags is a list of command-line flags to be passed through to 151 // the build system's query tool. 152 BuildFlags []string 153 154 // modFile will be used for -modfile in go command invocations. 155 modFile string 156 157 // modFlag will be used for -modfile in go command invocations. 158 modFlag string 159 160 // Fset provides source position information for syntax trees and types. 161 // If Fset is nil, Load will use a new fileset, but preserve Fset's value. 162 Fset *token.FileSet 163 164 // ParseFile is called to read and parse each file 165 // when preparing a package's type-checked syntax tree. 166 // It must be safe to call ParseFile simultaneously from multiple goroutines. 167 // If ParseFile is nil, the loader will uses parser.ParseFile. 168 // 169 // ParseFile should parse the source from src and use filename only for 170 // recording position information. 171 // 172 // An application may supply a custom implementation of ParseFile 173 // to change the effective file contents or the behavior of the parser, 174 // or to modify the syntax tree. For example, selectively eliminating 175 // unwanted function bodies can significantly accelerate type checking. 176 ParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) 177 178 // If Tests is set, the loader includes not just the packages 179 // matching a particular pattern but also any related test packages, 180 // including test-only variants of the package and the test executable. 181 // 182 // For example, when using the go command, loading "fmt" with Tests=true 183 // returns four packages, with IDs "fmt" (the standard package), 184 // "fmt [fmt.test]" (the package as compiled for the test), 185 // "fmt_test" (the test functions from source files in package fmt_test), 186 // and "fmt.test" (the test binary). 187 // 188 // In build systems with explicit names for tests, 189 // setting Tests may have no effect. 190 Tests bool 191 192 // Overlay provides a mapping of absolute file paths to file contents. 193 // If the file with the given path already exists, the parser will use the 194 // alternative file contents provided by the map. 195 // 196 // Overlays provide incomplete support for when a given file doesn't 197 // already exist on disk. See the package doc above for more details. 198 Overlay map[string][]byte 199 } 200 201 // driver is the type for functions that query the build system for the 202 // packages named by the patterns. 203 type driver func(cfg *Config, patterns ...string) (*driverResponse, error) 204 205 // driverResponse contains the results for a driver query. 206 type driverResponse struct { 207 // NotHandled is returned if the request can't be handled by the current 208 // driver. If an external driver returns a response with NotHandled, the 209 // rest of the driverResponse is ignored, and go/packages will fallback 210 // to the next driver. If go/packages is extended in the future to support 211 // lists of multiple drivers, go/packages will fall back to the next driver. 212 NotHandled bool 213 214 // Sizes, if not nil, is the types.Sizes to use when type checking. 215 Sizes *types.StdSizes 216 217 // Roots is the set of package IDs that make up the root packages. 218 // We have to encode this separately because when we encode a single package 219 // we cannot know if it is one of the roots as that requires knowledge of the 220 // graph it is part of. 221 Roots []string `json:",omitempty"` 222 223 // Packages is the full set of packages in the graph. 224 // The packages are not connected into a graph. 225 // The Imports if populated will be stubs that only have their ID set. 226 // Imports will be connected and then type and syntax information added in a 227 // later pass (see refine). 228 Packages []*Package 229 } 230 231 // Load loads and returns the Go packages named by the given patterns. 232 // 233 // Config specifies loading options; 234 // nil behaves the same as an empty Config. 235 // 236 // Load returns an error if any of the patterns was invalid 237 // as defined by the underlying build system. 238 // It may return an empty list of packages without an error, 239 // for instance for an empty expansion of a valid wildcard. 240 // Errors associated with a particular package are recorded in the 241 // corresponding Package's Errors list, and do not cause Load to 242 // return an error. Clients may need to handle such errors before 243 // proceeding with further analysis. The PrintErrors function is 244 // provided for convenient display of all errors. 245 func Load(cfg *Config, patterns ...string) ([]*Package, error) { 246 l := newLoader(cfg) 247 response, err := defaultDriver(&l.Config, patterns...) 248 if err != nil { 249 return nil, err 250 } 251 l.sizes = response.Sizes 252 return l.refine(response.Roots, response.Packages...) 253 } 254 255 // defaultDriver is a driver that implements go/packages' fallback behavior. 256 // It will try to request to an external driver, if one exists. If there's 257 // no external driver, or the driver returns a response with NotHandled set, 258 // defaultDriver will fall back to the go list driver. 259 func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, error) { 260 driver := findExternalDriver(cfg) 261 if driver == nil { 262 driver = goListDriver 263 } 264 response, err := driver(cfg, patterns...) 265 if err != nil { 266 return response, err 267 } else if response.NotHandled { 268 return goListDriver(cfg, patterns...) 269 } 270 return response, nil 271 } 272 273 // A Package describes a loaded Go package. 274 type Package struct { 275 // ID is a unique identifier for a package, 276 // in a syntax provided by the underlying build system. 277 // 278 // Because the syntax varies based on the build system, 279 // clients should treat IDs as opaque and not attempt to 280 // interpret them. 281 ID string 282 283 // Name is the package name as it appears in the package source code. 284 Name string 285 286 // PkgPath is the package path as used by the go/types package. 287 PkgPath string 288 289 // Errors contains any errors encountered querying the metadata 290 // of the package, or while parsing or type-checking its files. 291 Errors []Error 292 293 // GoFiles lists the absolute file paths of the package's Go source files. 294 GoFiles []string 295 296 // CompiledGoFiles lists the absolute file paths of the package's source 297 // files that are suitable for type checking. 298 // This may differ from GoFiles if files are processed before compilation. 299 CompiledGoFiles []string 300 301 // OtherFiles lists the absolute file paths of the package's non-Go source files, 302 // including assembly, C, C++, Fortran, Objective-C, SWIG, and so on. 303 OtherFiles []string 304 305 // EmbedFiles lists the absolute file paths of the package's files 306 // embedded with go:embed. 307 EmbedFiles []string 308 309 // EmbedPatterns lists the absolute file patterns of the package's 310 // files embedded with go:embed. 311 EmbedPatterns []string 312 313 // IgnoredFiles lists source files that are not part of the package 314 // using the current build configuration but that might be part of 315 // the package using other build configurations. 316 IgnoredFiles []string 317 318 // ExportFile is the absolute path to a file containing type 319 // information for the package as provided by the build system. 320 ExportFile string 321 322 // Imports maps import paths appearing in the package's Go source files 323 // to corresponding loaded Packages. 324 Imports map[string]*Package 325 326 // Types provides type information for the package. 327 // The NeedTypes LoadMode bit sets this field for packages matching the 328 // patterns; type information for dependencies may be missing or incomplete, 329 // unless NeedDeps and NeedImports are also set. 330 Types *types.Package 331 332 // Fset provides position information for Types, TypesInfo, and Syntax. 333 // It is set only when Types is set. 334 Fset *token.FileSet 335 336 // IllTyped indicates whether the package or any dependency contains errors. 337 // It is set only when Types is set. 338 IllTyped bool 339 340 // Syntax is the package's syntax trees, for the files listed in CompiledGoFiles. 341 // 342 // The NeedSyntax LoadMode bit populates this field for packages matching the patterns. 343 // If NeedDeps and NeedImports are also set, this field will also be populated 344 // for dependencies. 345 // 346 // Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are 347 // removed. If parsing returned nil, Syntax may be shorter than CompiledGoFiles. 348 Syntax []*ast.File 349 350 // TypesInfo provides type information about the package's syntax trees. 351 // It is set only when Syntax is set. 352 TypesInfo *types.Info 353 354 // TypesSizes provides the effective size function for types in TypesInfo. 355 TypesSizes types.Sizes 356 357 // forTest is the package under test, if any. 358 forTest string 359 360 // depsErrors is the DepsErrors field from the go list response, if any. 361 depsErrors []*packagesinternal.PackageError 362 363 // module is the module information for the package if it exists. 364 Module *Module 365 } 366 367 // Module provides module information for a package. 368 type Module struct { 369 Path string // module path 370 Version string // module version 371 Replace *Module // replaced by this module 372 Time *time.Time // time version was created 373 Main bool // is this the main module? 374 Indirect bool // is this module only an indirect dependency of main module? 375 Dir string // directory holding files for this module, if any 376 GoMod string // path to go.mod file used when loading this module, if any 377 GoVersion string // go version used in module 378 Error *ModuleError // error loading module 379 } 380 381 // ModuleError holds errors loading a module. 382 type ModuleError struct { 383 Err string // the error itself 384 } 385 386 func init() { 387 packagesinternal.GetForTest = func(p interface{}) string { 388 return p.(*Package).forTest 389 } 390 packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError { 391 return p.(*Package).depsErrors 392 } 393 packagesinternal.GetGoCmdRunner = func(config interface{}) *gocommand.Runner { 394 return config.(*Config).gocmdRunner 395 } 396 packagesinternal.SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) { 397 config.(*Config).gocmdRunner = runner 398 } 399 packagesinternal.SetModFile = func(config interface{}, value string) { 400 config.(*Config).modFile = value 401 } 402 packagesinternal.SetModFlag = func(config interface{}, value string) { 403 config.(*Config).modFlag = value 404 } 405 packagesinternal.TypecheckCgo = int(typecheckCgo) 406 } 407 408 // An Error describes a problem with a package's metadata, syntax, or types. 409 type Error struct { 410 Pos string // "file:line:col" or "file:line" or "" or "-" 411 Msg string 412 Kind ErrorKind 413 } 414 415 // ErrorKind describes the source of the error, allowing the user to 416 // differentiate between errors generated by the driver, the parser, or the 417 // type-checker. 418 type ErrorKind int 419 420 const ( 421 UnknownError ErrorKind = iota 422 ListError 423 ParseError 424 TypeError 425 ) 426 427 func (err Error) Error() string { 428 pos := err.Pos 429 if pos == "" { 430 pos = "-" // like token.Position{}.String() 431 } 432 return pos + ": " + err.Msg 433 } 434 435 // flatPackage is the JSON form of Package 436 // It drops all the type and syntax fields, and transforms the Imports 437 // 438 // TODO(adonovan): identify this struct with Package, effectively 439 // publishing the JSON protocol. 440 type flatPackage struct { 441 ID string 442 Name string `json:",omitempty"` 443 PkgPath string `json:",omitempty"` 444 Errors []Error `json:",omitempty"` 445 GoFiles []string `json:",omitempty"` 446 CompiledGoFiles []string `json:",omitempty"` 447 OtherFiles []string `json:",omitempty"` 448 EmbedFiles []string `json:",omitempty"` 449 EmbedPatterns []string `json:",omitempty"` 450 IgnoredFiles []string `json:",omitempty"` 451 ExportFile string `json:",omitempty"` 452 Imports map[string]string `json:",omitempty"` 453 } 454 455 // MarshalJSON returns the Package in its JSON form. 456 // For the most part, the structure fields are written out unmodified, and 457 // the type and syntax fields are skipped. 458 // The imports are written out as just a map of path to package id. 459 // The errors are written using a custom type that tries to preserve the 460 // structure of error types we know about. 461 // 462 // This method exists to enable support for additional build systems. It is 463 // not intended for use by clients of the API and we may change the format. 464 func (p *Package) MarshalJSON() ([]byte, error) { 465 flat := &flatPackage{ 466 ID: p.ID, 467 Name: p.Name, 468 PkgPath: p.PkgPath, 469 Errors: p.Errors, 470 GoFiles: p.GoFiles, 471 CompiledGoFiles: p.CompiledGoFiles, 472 OtherFiles: p.OtherFiles, 473 EmbedFiles: p.EmbedFiles, 474 EmbedPatterns: p.EmbedPatterns, 475 IgnoredFiles: p.IgnoredFiles, 476 ExportFile: p.ExportFile, 477 } 478 if len(p.Imports) > 0 { 479 flat.Imports = make(map[string]string, len(p.Imports)) 480 for path, ipkg := range p.Imports { 481 flat.Imports[path] = ipkg.ID 482 } 483 } 484 return json.Marshal(flat) 485 } 486 487 // UnmarshalJSON reads in a Package from its JSON format. 488 // See MarshalJSON for details about the format accepted. 489 func (p *Package) UnmarshalJSON(b []byte) error { 490 flat := &flatPackage{} 491 if err := json.Unmarshal(b, &flat); err != nil { 492 return err 493 } 494 *p = Package{ 495 ID: flat.ID, 496 Name: flat.Name, 497 PkgPath: flat.PkgPath, 498 Errors: flat.Errors, 499 GoFiles: flat.GoFiles, 500 CompiledGoFiles: flat.CompiledGoFiles, 501 OtherFiles: flat.OtherFiles, 502 EmbedFiles: flat.EmbedFiles, 503 EmbedPatterns: flat.EmbedPatterns, 504 ExportFile: flat.ExportFile, 505 } 506 if len(flat.Imports) > 0 { 507 p.Imports = make(map[string]*Package, len(flat.Imports)) 508 for path, id := range flat.Imports { 509 p.Imports[path] = &Package{ID: id} 510 } 511 } 512 return nil 513 } 514 515 func (p *Package) String() string { return p.ID } 516 517 // loaderPackage augments Package with state used during the loading phase 518 type loaderPackage struct { 519 *Package 520 importErrors map[string]error // maps each bad import to its error 521 loadOnce sync.Once 522 color uint8 // for cycle detection 523 needsrc bool // load from source (Mode >= LoadTypes) 524 needtypes bool // type information is either requested or depended on 525 initial bool // package was matched by a pattern 526 } 527 528 // loader holds the working state of a single call to load. 529 type loader struct { 530 pkgs map[string]*loaderPackage 531 Config 532 sizes types.Sizes 533 parseCache map[string]*parseValue 534 parseCacheMu sync.Mutex 535 exportMu sync.Mutex // enforces mutual exclusion of exportdata operations 536 537 // Config.Mode contains the implied mode (see impliedLoadMode). 538 // Implied mode contains all the fields we need the data for. 539 // In requestedMode there are the actually requested fields. 540 // We'll zero them out before returning packages to the user. 541 // This makes it easier for us to get the conditions where 542 // we need certain modes right. 543 requestedMode LoadMode 544 } 545 546 type parseValue struct { 547 f *ast.File 548 err error 549 ready chan struct{} 550 } 551 552 func newLoader(cfg *Config) *loader { 553 ld := &loader{ 554 parseCache: map[string]*parseValue{}, 555 } 556 if cfg != nil { 557 ld.Config = *cfg 558 // If the user has provided a logger, use it. 559 ld.Config.Logf = cfg.Logf 560 } 561 if ld.Config.Logf == nil { 562 // If the GOPACKAGESDEBUG environment variable is set to true, 563 // but the user has not provided a logger, default to log.Printf. 564 if debug { 565 ld.Config.Logf = log.Printf 566 } else { 567 ld.Config.Logf = func(format string, args ...interface{}) {} 568 } 569 } 570 if ld.Config.Mode == 0 { 571 ld.Config.Mode = NeedName | NeedFiles | NeedCompiledGoFiles // Preserve zero behavior of Mode for backwards compatibility. 572 } 573 if ld.Config.Env == nil { 574 ld.Config.Env = os.Environ() 575 } 576 if ld.Config.gocmdRunner == nil { 577 ld.Config.gocmdRunner = &gocommand.Runner{} 578 } 579 if ld.Context == nil { 580 ld.Context = context.Background() 581 } 582 if ld.Dir == "" { 583 if dir, err := os.Getwd(); err == nil { 584 ld.Dir = dir 585 } 586 } 587 588 // Save the actually requested fields. We'll zero them out before returning packages to the user. 589 ld.requestedMode = ld.Mode 590 ld.Mode = impliedLoadMode(ld.Mode) 591 592 if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { 593 if ld.Fset == nil { 594 ld.Fset = token.NewFileSet() 595 } 596 597 // ParseFile is required even in LoadTypes mode 598 // because we load source if export data is missing. 599 if ld.ParseFile == nil { 600 ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) { 601 const mode = parser.AllErrors | parser.ParseComments 602 return parser.ParseFile(fset, filename, src, mode) 603 } 604 } 605 } 606 607 return ld 608 } 609 610 // refine connects the supplied packages into a graph and then adds type and 611 // and syntax information as requested by the LoadMode. 612 func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) { 613 rootMap := make(map[string]int, len(roots)) 614 for i, root := range roots { 615 rootMap[root] = i 616 } 617 ld.pkgs = make(map[string]*loaderPackage) 618 // first pass, fixup and build the map and roots 619 var initial = make([]*loaderPackage, len(roots)) 620 for _, pkg := range list { 621 rootIndex := -1 622 if i, found := rootMap[pkg.ID]; found { 623 rootIndex = i 624 } 625 626 // Overlays can invalidate export data. 627 // TODO(matloob): make this check fine-grained based on dependencies on overlaid files 628 exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe" 629 // This package needs type information if the caller requested types and the package is 630 // either a root, or it's a non-root and the user requested dependencies ... 631 needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) 632 // This package needs source if the call requested source (or types info, which implies source) 633 // and the package is either a root, or itas a non- root and the user requested dependencies... 634 needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) || 635 // ... or if we need types and the exportData is invalid. We fall back to (incompletely) 636 // typechecking packages from source if they fail to compile. 637 (ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe" 638 lpkg := &loaderPackage{ 639 Package: pkg, 640 needtypes: needtypes, 641 needsrc: needsrc, 642 } 643 ld.pkgs[lpkg.ID] = lpkg 644 if rootIndex >= 0 { 645 initial[rootIndex] = lpkg 646 lpkg.initial = true 647 } 648 } 649 for i, root := range roots { 650 if initial[i] == nil { 651 return nil, fmt.Errorf("root package %v is missing", root) 652 } 653 } 654 655 // Materialize the import graph. 656 657 const ( 658 white = 0 // new 659 grey = 1 // in progress 660 black = 2 // complete 661 ) 662 663 // visit traverses the import graph, depth-first, 664 // and materializes the graph as Packages.Imports. 665 // 666 // Valid imports are saved in the Packages.Import map. 667 // Invalid imports (cycles and missing nodes) are saved in the importErrors map. 668 // Thus, even in the presence of both kinds of errors, the Import graph remains a DAG. 669 // 670 // visit returns whether the package needs src or has a transitive 671 // dependency on a package that does. These are the only packages 672 // for which we load source code. 673 var stack []*loaderPackage 674 var visit func(lpkg *loaderPackage) bool 675 var srcPkgs []*loaderPackage 676 visit = func(lpkg *loaderPackage) bool { 677 switch lpkg.color { 678 case black: 679 return lpkg.needsrc 680 case grey: 681 panic("internal error: grey node") 682 } 683 lpkg.color = grey 684 stack = append(stack, lpkg) // push 685 stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports 686 // If NeedImports isn't set, the imports fields will all be zeroed out. 687 if ld.Mode&NeedImports != 0 { 688 lpkg.Imports = make(map[string]*Package, len(stubs)) 689 for importPath, ipkg := range stubs { 690 var importErr error 691 imp := ld.pkgs[ipkg.ID] 692 if imp == nil { 693 // (includes package "C" when DisableCgo) 694 importErr = fmt.Errorf("missing package: %q", ipkg.ID) 695 } else if imp.color == grey { 696 importErr = fmt.Errorf("import cycle: %s", stack) 697 } 698 if importErr != nil { 699 if lpkg.importErrors == nil { 700 lpkg.importErrors = make(map[string]error) 701 } 702 lpkg.importErrors[importPath] = importErr 703 continue 704 } 705 706 if visit(imp) { 707 lpkg.needsrc = true 708 } 709 lpkg.Imports[importPath] = imp.Package 710 } 711 } 712 if lpkg.needsrc { 713 srcPkgs = append(srcPkgs, lpkg) 714 } 715 if ld.Mode&NeedTypesSizes != 0 { 716 lpkg.TypesSizes = ld.sizes 717 } 718 stack = stack[:len(stack)-1] // pop 719 lpkg.color = black 720 721 return lpkg.needsrc 722 } 723 724 if ld.Mode&NeedImports == 0 { 725 // We do this to drop the stub import packages that we are not even going to try to resolve. 726 for _, lpkg := range initial { 727 lpkg.Imports = nil 728 } 729 } else { 730 // For each initial package, create its import DAG. 731 for _, lpkg := range initial { 732 visit(lpkg) 733 } 734 } 735 if ld.Mode&NeedImports != 0 && ld.Mode&NeedTypes != 0 { 736 for _, lpkg := range srcPkgs { 737 // Complete type information is required for the 738 // immediate dependencies of each source package. 739 for _, ipkg := range lpkg.Imports { 740 imp := ld.pkgs[ipkg.ID] 741 imp.needtypes = true 742 } 743 } 744 } 745 // Load type data and syntax if needed, starting at 746 // the initial packages (roots of the import DAG). 747 if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { 748 var wg sync.WaitGroup 749 for _, lpkg := range initial { 750 wg.Add(1) 751 go func(lpkg *loaderPackage) { 752 ld.loadRecursive(lpkg) 753 wg.Done() 754 }(lpkg) 755 } 756 wg.Wait() 757 } 758 759 result := make([]*Package, len(initial)) 760 for i, lpkg := range initial { 761 result[i] = lpkg.Package 762 } 763 for i := range ld.pkgs { 764 // Clear all unrequested fields, 765 // to catch programs that use more than they request. 766 if ld.requestedMode&NeedName == 0 { 767 ld.pkgs[i].Name = "" 768 ld.pkgs[i].PkgPath = "" 769 } 770 if ld.requestedMode&NeedFiles == 0 { 771 ld.pkgs[i].GoFiles = nil 772 ld.pkgs[i].OtherFiles = nil 773 ld.pkgs[i].IgnoredFiles = nil 774 } 775 if ld.requestedMode&NeedEmbedFiles == 0 { 776 ld.pkgs[i].EmbedFiles = nil 777 } 778 if ld.requestedMode&NeedEmbedPatterns == 0 { 779 ld.pkgs[i].EmbedPatterns = nil 780 } 781 if ld.requestedMode&NeedCompiledGoFiles == 0 { 782 ld.pkgs[i].CompiledGoFiles = nil 783 } 784 if ld.requestedMode&NeedImports == 0 { 785 ld.pkgs[i].Imports = nil 786 } 787 if ld.requestedMode&NeedExportFile == 0 { 788 ld.pkgs[i].ExportFile = "" 789 } 790 if ld.requestedMode&NeedTypes == 0 { 791 ld.pkgs[i].Types = nil 792 ld.pkgs[i].Fset = nil 793 ld.pkgs[i].IllTyped = false 794 } 795 if ld.requestedMode&NeedSyntax == 0 { 796 ld.pkgs[i].Syntax = nil 797 } 798 if ld.requestedMode&NeedTypesInfo == 0 { 799 ld.pkgs[i].TypesInfo = nil 800 } 801 if ld.requestedMode&NeedTypesSizes == 0 { 802 ld.pkgs[i].TypesSizes = nil 803 } 804 if ld.requestedMode&NeedModule == 0 { 805 ld.pkgs[i].Module = nil 806 } 807 } 808 809 return result, nil 810 } 811 812 // loadRecursive loads the specified package and its dependencies, 813 // recursively, in parallel, in topological order. 814 // It is atomic and idempotent. 815 // Precondition: ld.Mode&NeedTypes. 816 func (ld *loader) loadRecursive(lpkg *loaderPackage) { 817 lpkg.loadOnce.Do(func() { 818 // Load the direct dependencies, in parallel. 819 var wg sync.WaitGroup 820 for _, ipkg := range lpkg.Imports { 821 imp := ld.pkgs[ipkg.ID] 822 wg.Add(1) 823 go func(imp *loaderPackage) { 824 ld.loadRecursive(imp) 825 wg.Done() 826 }(imp) 827 } 828 wg.Wait() 829 ld.loadPackage(lpkg) 830 }) 831 } 832 833 // loadPackage loads the specified package. 834 // It must be called only once per Package, 835 // after immediate dependencies are loaded. 836 // Precondition: ld.Mode & NeedTypes. 837 func (ld *loader) loadPackage(lpkg *loaderPackage) { 838 if lpkg.PkgPath == "unsafe" { 839 // Fill in the blanks to avoid surprises. 840 lpkg.Types = types.Unsafe 841 lpkg.Fset = ld.Fset 842 lpkg.Syntax = []*ast.File{} 843 lpkg.TypesInfo = new(types.Info) 844 lpkg.TypesSizes = ld.sizes 845 return 846 } 847 848 // Call NewPackage directly with explicit name. 849 // This avoids skew between golist and go/types when the files' 850 // package declarations are inconsistent. 851 lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name) 852 lpkg.Fset = ld.Fset 853 854 // Subtle: we populate all Types fields with an empty Package 855 // before loading export data so that export data processing 856 // never has to create a types.Package for an indirect dependency, 857 // which would then require that such created packages be explicitly 858 // inserted back into the Import graph as a final step after export data loading. 859 // The Diamond test exercises this case. 860 if !lpkg.needtypes && !lpkg.needsrc { 861 return 862 } 863 if !lpkg.needsrc { 864 ld.loadFromExportData(lpkg) 865 return // not a source package, don't get syntax trees 866 } 867 868 appendError := func(err error) { 869 // Convert various error types into the one true Error. 870 var errs []Error 871 switch err := err.(type) { 872 case Error: 873 // from driver 874 errs = append(errs, err) 875 876 case *os.PathError: 877 // from parser 878 errs = append(errs, Error{ 879 Pos: err.Path + ":1", 880 Msg: err.Err.Error(), 881 Kind: ParseError, 882 }) 883 884 case scanner.ErrorList: 885 // from parser 886 for _, err := range err { 887 errs = append(errs, Error{ 888 Pos: err.Pos.String(), 889 Msg: err.Msg, 890 Kind: ParseError, 891 }) 892 } 893 894 case types.Error: 895 // from type checker 896 errs = append(errs, Error{ 897 Pos: err.Fset.Position(err.Pos).String(), 898 Msg: err.Msg, 899 Kind: TypeError, 900 }) 901 902 default: 903 // unexpected impoverished error from parser? 904 errs = append(errs, Error{ 905 Pos: "-", 906 Msg: err.Error(), 907 Kind: UnknownError, 908 }) 909 910 // If you see this error message, please file a bug. 911 log.Printf("internal error: error %q (%T) without position", err, err) 912 } 913 914 lpkg.Errors = append(lpkg.Errors, errs...) 915 } 916 917 if ld.Config.Mode&NeedTypes != 0 && len(lpkg.CompiledGoFiles) == 0 && lpkg.ExportFile != "" { 918 // The config requested loading sources and types, but sources are missing. 919 // Add an error to the package and fall back to loading from export data. 920 appendError(Error{"-", fmt.Sprintf("sources missing for package %s", lpkg.ID), ParseError}) 921 ld.loadFromExportData(lpkg) 922 return // can't get syntax trees for this package 923 } 924 925 files, errs := ld.parseFiles(lpkg.CompiledGoFiles) 926 for _, err := range errs { 927 appendError(err) 928 } 929 930 lpkg.Syntax = files 931 if ld.Config.Mode&NeedTypes == 0 { 932 return 933 } 934 935 lpkg.TypesInfo = &types.Info{ 936 Types: make(map[ast.Expr]types.TypeAndValue), 937 Defs: make(map[*ast.Ident]types.Object), 938 Uses: make(map[*ast.Ident]types.Object), 939 Implicits: make(map[ast.Node]types.Object), 940 Scopes: make(map[ast.Node]*types.Scope), 941 Selections: make(map[*ast.SelectorExpr]*types.Selection), 942 } 943 typeparams.InitInstanceInfo(lpkg.TypesInfo) 944 lpkg.TypesSizes = ld.sizes 945 946 importer := importerFunc(func(path string) (*types.Package, error) { 947 if path == "unsafe" { 948 return types.Unsafe, nil 949 } 950 951 // The imports map is keyed by import path. 952 ipkg := lpkg.Imports[path] 953 if ipkg == nil { 954 if err := lpkg.importErrors[path]; err != nil { 955 return nil, err 956 } 957 // There was skew between the metadata and the 958 // import declarations, likely due to an edit 959 // race, or because the ParseFile feature was 960 // used to supply alternative file contents. 961 return nil, fmt.Errorf("no metadata for %s", path) 962 } 963 964 if ipkg.Types != nil && ipkg.Types.Complete() { 965 return ipkg.Types, nil 966 } 967 log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg) 968 panic("unreachable") 969 }) 970 971 // type-check 972 tc := &types.Config{ 973 Importer: importer, 974 975 // Type-check bodies of functions only in non-initial packages. 976 // Example: for import graph A->B->C and initial packages {A,C}, 977 // we can ignore function bodies in B. 978 IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial, 979 980 Error: appendError, 981 Sizes: ld.sizes, 982 } 983 if (ld.Mode & typecheckCgo) != 0 { 984 if !typesinternal.SetUsesCgo(tc) { 985 appendError(Error{ 986 Msg: "typecheckCgo requires Go 1.15+", 987 Kind: ListError, 988 }) 989 return 990 } 991 } 992 types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) 993 994 lpkg.importErrors = nil // no longer needed 995 996 // If !Cgo, the type-checker uses FakeImportC mode, so 997 // it doesn't invoke the importer for import "C", 998 // nor report an error for the import, 999 // or for any undefined C.f reference. 1000 // We must detect this explicitly and correctly 1001 // mark the package as IllTyped (by reporting an error). 1002 // TODO(adonovan): if these errors are annoying, 1003 // we could just set IllTyped quietly. 1004 if tc.FakeImportC { 1005 outer: 1006 for _, f := range lpkg.Syntax { 1007 for _, imp := range f.Imports { 1008 if imp.Path.Value == `"C"` { 1009 err := types.Error{Fset: ld.Fset, Pos: imp.Pos(), Msg: `import "C" ignored`} 1010 appendError(err) 1011 break outer 1012 } 1013 } 1014 } 1015 } 1016 1017 // Record accumulated errors. 1018 illTyped := len(lpkg.Errors) > 0 1019 if !illTyped { 1020 for _, imp := range lpkg.Imports { 1021 if imp.IllTyped { 1022 illTyped = true 1023 break 1024 } 1025 } 1026 } 1027 lpkg.IllTyped = illTyped 1028 } 1029 1030 // An importFunc is an implementation of the single-method 1031 // types.Importer interface based on a function value. 1032 type importerFunc func(path string) (*types.Package, error) 1033 1034 func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) } 1035 1036 // We use a counting semaphore to limit 1037 // the number of parallel I/O calls per process. 1038 var ioLimit = make(chan bool, 20) 1039 1040 func (ld *loader) parseFile(filename string) (*ast.File, error) { 1041 ld.parseCacheMu.Lock() 1042 v, ok := ld.parseCache[filename] 1043 if ok { 1044 // cache hit 1045 ld.parseCacheMu.Unlock() 1046 <-v.ready 1047 } else { 1048 // cache miss 1049 v = &parseValue{ready: make(chan struct{})} 1050 ld.parseCache[filename] = v 1051 ld.parseCacheMu.Unlock() 1052 1053 var src []byte 1054 for f, contents := range ld.Config.Overlay { 1055 if sameFile(f, filename) { 1056 src = contents 1057 } 1058 } 1059 var err error 1060 if src == nil { 1061 ioLimit <- true // wait 1062 src, err = ioutil.ReadFile(filename) 1063 <-ioLimit // signal 1064 } 1065 if err != nil { 1066 v.err = err 1067 } else { 1068 v.f, v.err = ld.ParseFile(ld.Fset, filename, src) 1069 } 1070 1071 close(v.ready) 1072 } 1073 return v.f, v.err 1074 } 1075 1076 // parseFiles reads and parses the Go source files and returns the ASTs 1077 // of the ones that could be at least partially parsed, along with a 1078 // list of I/O and parse errors encountered. 1079 // 1080 // Because files are scanned in parallel, the token.Pos 1081 // positions of the resulting ast.Files are not ordered. 1082 // 1083 func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) { 1084 var wg sync.WaitGroup 1085 n := len(filenames) 1086 parsed := make([]*ast.File, n) 1087 errors := make([]error, n) 1088 for i, file := range filenames { 1089 if ld.Config.Context.Err() != nil { 1090 parsed[i] = nil 1091 errors[i] = ld.Config.Context.Err() 1092 continue 1093 } 1094 wg.Add(1) 1095 go func(i int, filename string) { 1096 parsed[i], errors[i] = ld.parseFile(filename) 1097 wg.Done() 1098 }(i, file) 1099 } 1100 wg.Wait() 1101 1102 // Eliminate nils, preserving order. 1103 var o int 1104 for _, f := range parsed { 1105 if f != nil { 1106 parsed[o] = f 1107 o++ 1108 } 1109 } 1110 parsed = parsed[:o] 1111 1112 o = 0 1113 for _, err := range errors { 1114 if err != nil { 1115 errors[o] = err 1116 o++ 1117 } 1118 } 1119 errors = errors[:o] 1120 1121 return parsed, errors 1122 } 1123 1124 // sameFile returns true if x and y have the same basename and denote 1125 // the same file. 1126 // 1127 func sameFile(x, y string) bool { 1128 if x == y { 1129 // It could be the case that y doesn't exist. 1130 // For instance, it may be an overlay file that 1131 // hasn't been written to disk. To handle that case 1132 // let x == y through. (We added the exact absolute path 1133 // string to the CompiledGoFiles list, so the unwritten 1134 // overlay case implies x==y.) 1135 return true 1136 } 1137 if strings.EqualFold(filepath.Base(x), filepath.Base(y)) { // (optimisation) 1138 if xi, err := os.Stat(x); err == nil { 1139 if yi, err := os.Stat(y); err == nil { 1140 return os.SameFile(xi, yi) 1141 } 1142 } 1143 } 1144 return false 1145 } 1146 1147 // loadFromExportData returns type information for the specified 1148 // package, loading it from an export data file on the first request. 1149 func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error) { 1150 if lpkg.PkgPath == "" { 1151 log.Fatalf("internal error: Package %s has no PkgPath", lpkg) 1152 } 1153 1154 // Because gcexportdata.Read has the potential to create or 1155 // modify the types.Package for each node in the transitive 1156 // closure of dependencies of lpkg, all exportdata operations 1157 // must be sequential. (Finer-grained locking would require 1158 // changes to the gcexportdata API.) 1159 // 1160 // The exportMu lock guards the Package.Pkg field and the 1161 // types.Package it points to, for each Package in the graph. 1162 // 1163 // Not all accesses to Package.Pkg need to be protected by exportMu: 1164 // graph ordering ensures that direct dependencies of source 1165 // packages are fully loaded before the importer reads their Pkg field. 1166 ld.exportMu.Lock() 1167 defer ld.exportMu.Unlock() 1168 1169 if tpkg := lpkg.Types; tpkg != nil && tpkg.Complete() { 1170 return tpkg, nil // cache hit 1171 } 1172 1173 lpkg.IllTyped = true // fail safe 1174 1175 if lpkg.ExportFile == "" { 1176 // Errors while building export data will have been printed to stderr. 1177 return nil, fmt.Errorf("no export data file") 1178 } 1179 f, err := os.Open(lpkg.ExportFile) 1180 if err != nil { 1181 return nil, err 1182 } 1183 defer f.Close() 1184 1185 // Read gc export data. 1186 // 1187 // We don't currently support gccgo export data because all 1188 // underlying workspaces use the gc toolchain. (Even build 1189 // systems that support gccgo don't use it for workspace 1190 // queries.) 1191 r, err := gcexportdata.NewReader(f) 1192 if err != nil { 1193 return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) 1194 } 1195 1196 // Build the view. 1197 // 1198 // The gcexportdata machinery has no concept of package ID. 1199 // It identifies packages by their PkgPath, which although not 1200 // globally unique is unique within the scope of one invocation 1201 // of the linker, type-checker, or gcexportdata. 1202 // 1203 // So, we must build a PkgPath-keyed view of the global 1204 // (conceptually ID-keyed) cache of packages and pass it to 1205 // gcexportdata. The view must contain every existing 1206 // package that might possibly be mentioned by the 1207 // current package---its transitive closure. 1208 // 1209 // In loadPackage, we unconditionally create a types.Package for 1210 // each dependency so that export data loading does not 1211 // create new ones. 1212 // 1213 // TODO(adonovan): it would be simpler and more efficient 1214 // if the export data machinery invoked a callback to 1215 // get-or-create a package instead of a map. 1216 // 1217 view := make(map[string]*types.Package) // view seen by gcexportdata 1218 seen := make(map[*loaderPackage]bool) // all visited packages 1219 var visit func(pkgs map[string]*Package) 1220 visit = func(pkgs map[string]*Package) { 1221 for _, p := range pkgs { 1222 lpkg := ld.pkgs[p.ID] 1223 if !seen[lpkg] { 1224 seen[lpkg] = true 1225 view[lpkg.PkgPath] = lpkg.Types 1226 visit(lpkg.Imports) 1227 } 1228 } 1229 } 1230 visit(lpkg.Imports) 1231 1232 viewLen := len(view) + 1 // adding the self package 1233 // Parse the export data. 1234 // (May modify incomplete packages in view but not create new ones.) 1235 tpkg, err := gcexportdata.Read(r, ld.Fset, view, lpkg.PkgPath) 1236 if err != nil { 1237 return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) 1238 } 1239 if _, ok := view["go.shape"]; ok { 1240 viewLen++ // account for the pseudopackage "go.shape" that gets created by generic code 1241 } 1242 if viewLen != len(view) { 1243 log.Panicf("github.com/powerman/golang-tools/go/packages: unexpected new packages during load of %s", lpkg.PkgPath) 1244 } 1245 1246 lpkg.Types = tpkg 1247 lpkg.IllTyped = false 1248 1249 return tpkg, nil 1250 } 1251 1252 // impliedLoadMode returns loadMode with its dependencies. 1253 func impliedLoadMode(loadMode LoadMode) LoadMode { 1254 if loadMode&(NeedDeps|NeedTypes|NeedTypesInfo) != 0 { 1255 // All these things require knowing the import graph. 1256 loadMode |= NeedImports 1257 } 1258 1259 return loadMode 1260 } 1261 1262 func usesExportData(cfg *Config) bool { 1263 return cfg.Mode&NeedExportFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0 1264 }