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