podman

Форк
0
1426 строк · 44.6 Кб
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
	// If the context is cancelled, the loader may stop early
133
	// and return an ErrCancelled error.
134
	// If Context is nil, the load cannot be cancelled.
135
	Context context.Context
136

137
	// Logf is the logger for the config.
138
	// If the user provides a logger, debug logging is enabled.
139
	// If the GOPACKAGESDEBUG environment variable is set to true,
140
	// but the logger is nil, default to log.Printf.
141
	Logf func(format string, args ...interface{})
142

143
	// Dir is the directory in which to run the build system's query tool
144
	// that provides information about the packages.
145
	// If Dir is empty, the tool is run in the current directory.
146
	Dir string
147

148
	// Env is the environment to use when invoking the build system's query tool.
149
	// If Env is nil, the current environment is used.
150
	// As in os/exec's Cmd, only the last value in the slice for
151
	// each environment key is used. To specify the setting of only
152
	// a few variables, append to the current environment, as in:
153
	//
154
	//	opt.Env = append(os.Environ(), "GOOS=plan9", "GOARCH=386")
155
	//
156
	Env []string
157

158
	// gocmdRunner guards go command calls from concurrency errors.
159
	gocmdRunner *gocommand.Runner
160

161
	// BuildFlags is a list of command-line flags to be passed through to
162
	// the build system's query tool.
163
	BuildFlags []string
164

165
	// modFile will be used for -modfile in go command invocations.
166
	modFile string
167

168
	// modFlag will be used for -modfile in go command invocations.
169
	modFlag string
170

171
	// Fset provides source position information for syntax trees and types.
172
	// If Fset is nil, Load will use a new fileset, but preserve Fset's value.
173
	Fset *token.FileSet
174

175
	// ParseFile is called to read and parse each file
176
	// when preparing a package's type-checked syntax tree.
177
	// It must be safe to call ParseFile simultaneously from multiple goroutines.
178
	// If ParseFile is nil, the loader will uses parser.ParseFile.
179
	//
180
	// ParseFile should parse the source from src and use filename only for
181
	// recording position information.
182
	//
183
	// An application may supply a custom implementation of ParseFile
184
	// to change the effective file contents or the behavior of the parser,
185
	// or to modify the syntax tree. For example, selectively eliminating
186
	// unwanted function bodies can significantly accelerate type checking.
187
	ParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error)
188

189
	// If Tests is set, the loader includes not just the packages
190
	// matching a particular pattern but also any related test packages,
191
	// including test-only variants of the package and the test executable.
192
	//
193
	// For example, when using the go command, loading "fmt" with Tests=true
194
	// returns four packages, with IDs "fmt" (the standard package),
195
	// "fmt [fmt.test]" (the package as compiled for the test),
196
	// "fmt_test" (the test functions from source files in package fmt_test),
197
	// and "fmt.test" (the test binary).
198
	//
199
	// In build systems with explicit names for tests,
200
	// setting Tests may have no effect.
201
	Tests bool
202

203
	// Overlay provides a mapping of absolute file paths to file contents.
204
	// If the file with the given path already exists, the parser will use the
205
	// alternative file contents provided by the map.
206
	//
207
	// Overlays provide incomplete support for when a given file doesn't
208
	// already exist on disk. See the package doc above for more details.
209
	Overlay map[string][]byte
210
}
211

212
// Load loads and returns the Go packages named by the given patterns.
213
//
214
// Config specifies loading options;
215
// nil behaves the same as an empty Config.
216
//
217
// Load returns an error if any of the patterns was invalid
218
// as defined by the underlying build system.
219
// It may return an empty list of packages without an error,
220
// for instance for an empty expansion of a valid wildcard.
221
// Errors associated with a particular package are recorded in the
222
// corresponding Package's Errors list, and do not cause Load to
223
// return an error. Clients may need to handle such errors before
224
// proceeding with further analysis. The PrintErrors function is
225
// provided for convenient display of all errors.
226
func Load(cfg *Config, patterns ...string) ([]*Package, error) {
227
	ld := newLoader(cfg)
228
	response, external, err := defaultDriver(&ld.Config, patterns...)
229
	if err != nil {
230
		return nil, err
231
	}
232

233
	ld.sizes = types.SizesFor(response.Compiler, response.Arch)
234
	if ld.sizes == nil && ld.Config.Mode&(NeedTypes|NeedTypesSizes|NeedTypesInfo) != 0 {
235
		// Type size information is needed but unavailable.
236
		if external {
237
			// An external driver may fail to populate the Compiler/GOARCH fields,
238
			// especially since they are relatively new (see #63700).
239
			// Provide a sensible fallback in this case.
240
			ld.sizes = types.SizesFor("gc", runtime.GOARCH)
241
			if ld.sizes == nil { // gccgo-only arch
242
				ld.sizes = types.SizesFor("gc", "amd64")
243
			}
244
		} else {
245
			// Go list should never fail to deliver accurate size information.
246
			// Reject the whole Load since the error is the same for every package.
247
			return nil, fmt.Errorf("can't determine type sizes for compiler %q on GOARCH %q",
248
				response.Compiler, response.Arch)
249
		}
250
	}
251

252
	return ld.refine(response)
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
// The boolean result indicates that an external driver handled the request.
260
func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) {
261
	const (
262
		// windowsArgMax specifies the maximum command line length for
263
		// the Windows' CreateProcess function.
264
		windowsArgMax = 32767
265
		// maxEnvSize is a very rough estimation of the maximum environment
266
		// size of a user.
267
		maxEnvSize = 16384
268
		// safeArgMax specifies the maximum safe command line length to use
269
		// by the underlying driver excl. the environment. We choose the Windows'
270
		// ARG_MAX as the starting point because it's one of the lowest ARG_MAX
271
		// constants out of the different supported platforms,
272
		// e.g., https://www.in-ulm.de/~mascheck/various/argmax/#results.
273
		safeArgMax = windowsArgMax - maxEnvSize
274
	)
275
	chunks, err := splitIntoChunks(patterns, safeArgMax)
276
	if err != nil {
277
		return nil, false, err
278
	}
279

280
	if driver := findExternalDriver(cfg); driver != nil {
281
		response, err := callDriverOnChunks(driver, cfg, chunks)
282
		if err != nil {
283
			return nil, false, err
284
		} else if !response.NotHandled {
285
			return response, true, nil
286
		}
287
		// (fall through)
288
	}
289

290
	response, err := callDriverOnChunks(goListDriver, cfg, chunks)
291
	if err != nil {
292
		return nil, false, err
293
	}
294
	return response, false, err
295
}
296

297
// splitIntoChunks chunks the slice so that the total number of characters
298
// in a chunk is no longer than argMax.
299
func splitIntoChunks(patterns []string, argMax int) ([][]string, error) {
300
	if argMax <= 0 {
301
		return nil, errors.New("failed to split patterns into chunks, negative safe argMax value")
302
	}
303
	var chunks [][]string
304
	charsInChunk := 0
305
	nextChunkStart := 0
306
	for i, v := range patterns {
307
		vChars := len(v)
308
		if vChars > argMax {
309
			// a single pattern is longer than the maximum safe ARG_MAX, hardly should happen
310
			return nil, errors.New("failed to split patterns into chunks, a pattern is too long")
311
		}
312
		charsInChunk += vChars + 1 // +1 is for a whitespace between patterns that has to be counted too
313
		if charsInChunk > argMax {
314
			chunks = append(chunks, patterns[nextChunkStart:i])
315
			nextChunkStart = i
316
			charsInChunk = vChars
317
		}
318
	}
319
	// add the last chunk
320
	if nextChunkStart < len(patterns) {
321
		chunks = append(chunks, patterns[nextChunkStart:])
322
	}
323
	return chunks, nil
324
}
325

326
func callDriverOnChunks(driver driver, cfg *Config, chunks [][]string) (*DriverResponse, error) {
327
	if len(chunks) == 0 {
328
		return driver(cfg)
329
	}
330
	responses := make([]*DriverResponse, len(chunks))
331
	errNotHandled := errors.New("driver returned NotHandled")
332
	var g errgroup.Group
333
	for i, chunk := range chunks {
334
		i := i
335
		chunk := chunk
336
		g.Go(func() (err error) {
337
			responses[i], err = driver(cfg, chunk...)
338
			if responses[i] != nil && responses[i].NotHandled {
339
				err = errNotHandled
340
			}
341
			return err
342
		})
343
	}
344
	if err := g.Wait(); err != nil {
345
		if errors.Is(err, errNotHandled) {
346
			return &DriverResponse{NotHandled: true}, nil
347
		}
348
		return nil, err
349
	}
350
	return mergeResponses(responses...), nil
351
}
352

353
func mergeResponses(responses ...*DriverResponse) *DriverResponse {
354
	if len(responses) == 0 {
355
		return nil
356
	}
357
	response := newDeduper()
358
	response.dr.NotHandled = false
359
	response.dr.Compiler = responses[0].Compiler
360
	response.dr.Arch = responses[0].Arch
361
	response.dr.GoVersion = responses[0].GoVersion
362
	for _, v := range responses {
363
		response.addAll(v)
364
	}
365
	return response.dr
366
}
367

368
// A Package describes a loaded Go package.
369
type Package struct {
370
	// ID is a unique identifier for a package,
371
	// in a syntax provided by the underlying build system.
372
	//
373
	// Because the syntax varies based on the build system,
374
	// clients should treat IDs as opaque and not attempt to
375
	// interpret them.
376
	ID string
377

378
	// Name is the package name as it appears in the package source code.
379
	Name string
380

381
	// PkgPath is the package path as used by the go/types package.
382
	PkgPath string
383

384
	// Errors contains any errors encountered querying the metadata
385
	// of the package, or while parsing or type-checking its files.
386
	Errors []Error
387

388
	// TypeErrors contains the subset of errors produced during type checking.
389
	TypeErrors []types.Error
390

391
	// GoFiles lists the absolute file paths of the package's Go source files.
392
	// It may include files that should not be compiled, for example because
393
	// they contain non-matching build tags, are documentary pseudo-files such as
394
	// unsafe/unsafe.go or builtin/builtin.go, or are subject to cgo preprocessing.
395
	GoFiles []string
396

397
	// CompiledGoFiles lists the absolute file paths of the package's source
398
	// files that are suitable for type checking.
399
	// This may differ from GoFiles if files are processed before compilation.
400
	CompiledGoFiles []string
401

402
	// OtherFiles lists the absolute file paths of the package's non-Go source files,
403
	// including assembly, C, C++, Fortran, Objective-C, SWIG, and so on.
404
	OtherFiles []string
405

406
	// EmbedFiles lists the absolute file paths of the package's files
407
	// embedded with go:embed.
408
	EmbedFiles []string
409

410
	// EmbedPatterns lists the absolute file patterns of the package's
411
	// files embedded with go:embed.
412
	EmbedPatterns []string
413

414
	// IgnoredFiles lists source files that are not part of the package
415
	// using the current build configuration but that might be part of
416
	// the package using other build configurations.
417
	IgnoredFiles []string
418

419
	// ExportFile is the absolute path to a file containing type
420
	// information for the package as provided by the build system.
421
	ExportFile string
422

423
	// Imports maps import paths appearing in the package's Go source files
424
	// to corresponding loaded Packages.
425
	Imports map[string]*Package
426

427
	// Types provides type information for the package.
428
	// The NeedTypes LoadMode bit sets this field for packages matching the
429
	// patterns; type information for dependencies may be missing or incomplete,
430
	// unless NeedDeps and NeedImports are also set.
431
	Types *types.Package
432

433
	// Fset provides position information for Types, TypesInfo, and Syntax.
434
	// It is set only when Types is set.
435
	Fset *token.FileSet
436

437
	// IllTyped indicates whether the package or any dependency contains errors.
438
	// It is set only when Types is set.
439
	IllTyped bool
440

441
	// Syntax is the package's syntax trees, for the files listed in CompiledGoFiles.
442
	//
443
	// The NeedSyntax LoadMode bit populates this field for packages matching the patterns.
444
	// If NeedDeps and NeedImports are also set, this field will also be populated
445
	// for dependencies.
446
	//
447
	// Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are
448
	// removed.  If parsing returned nil, Syntax may be shorter than CompiledGoFiles.
449
	Syntax []*ast.File
450

451
	// TypesInfo provides type information about the package's syntax trees.
452
	// It is set only when Syntax is set.
453
	TypesInfo *types.Info
454

455
	// TypesSizes provides the effective size function for types in TypesInfo.
456
	TypesSizes types.Sizes
457

458
	// forTest is the package under test, if any.
459
	forTest string
460

461
	// depsErrors is the DepsErrors field from the go list response, if any.
462
	depsErrors []*packagesinternal.PackageError
463

464
	// module is the module information for the package if it exists.
465
	Module *Module
466
}
467

468
// Module provides module information for a package.
469
type Module struct {
470
	Path      string       // module path
471
	Version   string       // module version
472
	Replace   *Module      // replaced by this module
473
	Time      *time.Time   // time version was created
474
	Main      bool         // is this the main module?
475
	Indirect  bool         // is this module only an indirect dependency of main module?
476
	Dir       string       // directory holding files for this module, if any
477
	GoMod     string       // path to go.mod file used when loading this module, if any
478
	GoVersion string       // go version used in module
479
	Error     *ModuleError // error loading module
480
}
481

482
// ModuleError holds errors loading a module.
483
type ModuleError struct {
484
	Err string // the error itself
485
}
486

487
func init() {
488
	packagesinternal.GetForTest = func(p interface{}) string {
489
		return p.(*Package).forTest
490
	}
491
	packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError {
492
		return p.(*Package).depsErrors
493
	}
494
	packagesinternal.SetModFile = func(config interface{}, value string) {
495
		config.(*Config).modFile = value
496
	}
497
	packagesinternal.SetModFlag = func(config interface{}, value string) {
498
		config.(*Config).modFlag = value
499
	}
500
	packagesinternal.TypecheckCgo = int(typecheckCgo)
501
	packagesinternal.DepsErrors = int(needInternalDepsErrors)
502
	packagesinternal.ForTest = int(needInternalForTest)
503
}
504

505
// An Error describes a problem with a package's metadata, syntax, or types.
506
type Error struct {
507
	Pos  string // "file:line:col" or "file:line" or "" or "-"
508
	Msg  string
509
	Kind ErrorKind
510
}
511

512
// ErrorKind describes the source of the error, allowing the user to
513
// differentiate between errors generated by the driver, the parser, or the
514
// type-checker.
515
type ErrorKind int
516

517
const (
518
	UnknownError ErrorKind = iota
519
	ListError
520
	ParseError
521
	TypeError
522
)
523

524
func (err Error) Error() string {
525
	pos := err.Pos
526
	if pos == "" {
527
		pos = "-" // like token.Position{}.String()
528
	}
529
	return pos + ": " + err.Msg
530
}
531

532
// flatPackage is the JSON form of Package
533
// It drops all the type and syntax fields, and transforms the Imports
534
//
535
// TODO(adonovan): identify this struct with Package, effectively
536
// publishing the JSON protocol.
537
type flatPackage struct {
538
	ID              string
539
	Name            string            `json:",omitempty"`
540
	PkgPath         string            `json:",omitempty"`
541
	Errors          []Error           `json:",omitempty"`
542
	GoFiles         []string          `json:",omitempty"`
543
	CompiledGoFiles []string          `json:",omitempty"`
544
	OtherFiles      []string          `json:",omitempty"`
545
	EmbedFiles      []string          `json:",omitempty"`
546
	EmbedPatterns   []string          `json:",omitempty"`
547
	IgnoredFiles    []string          `json:",omitempty"`
548
	ExportFile      string            `json:",omitempty"`
549
	Imports         map[string]string `json:",omitempty"`
550
}
551

552
// MarshalJSON returns the Package in its JSON form.
553
// For the most part, the structure fields are written out unmodified, and
554
// the type and syntax fields are skipped.
555
// The imports are written out as just a map of path to package id.
556
// The errors are written using a custom type that tries to preserve the
557
// structure of error types we know about.
558
//
559
// This method exists to enable support for additional build systems.  It is
560
// not intended for use by clients of the API and we may change the format.
561
func (p *Package) MarshalJSON() ([]byte, error) {
562
	flat := &flatPackage{
563
		ID:              p.ID,
564
		Name:            p.Name,
565
		PkgPath:         p.PkgPath,
566
		Errors:          p.Errors,
567
		GoFiles:         p.GoFiles,
568
		CompiledGoFiles: p.CompiledGoFiles,
569
		OtherFiles:      p.OtherFiles,
570
		EmbedFiles:      p.EmbedFiles,
571
		EmbedPatterns:   p.EmbedPatterns,
572
		IgnoredFiles:    p.IgnoredFiles,
573
		ExportFile:      p.ExportFile,
574
	}
575
	if len(p.Imports) > 0 {
576
		flat.Imports = make(map[string]string, len(p.Imports))
577
		for path, ipkg := range p.Imports {
578
			flat.Imports[path] = ipkg.ID
579
		}
580
	}
581
	return json.Marshal(flat)
582
}
583

584
// UnmarshalJSON reads in a Package from its JSON format.
585
// See MarshalJSON for details about the format accepted.
586
func (p *Package) UnmarshalJSON(b []byte) error {
587
	flat := &flatPackage{}
588
	if err := json.Unmarshal(b, &flat); err != nil {
589
		return err
590
	}
591
	*p = Package{
592
		ID:              flat.ID,
593
		Name:            flat.Name,
594
		PkgPath:         flat.PkgPath,
595
		Errors:          flat.Errors,
596
		GoFiles:         flat.GoFiles,
597
		CompiledGoFiles: flat.CompiledGoFiles,
598
		OtherFiles:      flat.OtherFiles,
599
		EmbedFiles:      flat.EmbedFiles,
600
		EmbedPatterns:   flat.EmbedPatterns,
601
		ExportFile:      flat.ExportFile,
602
	}
603
	if len(flat.Imports) > 0 {
604
		p.Imports = make(map[string]*Package, len(flat.Imports))
605
		for path, id := range flat.Imports {
606
			p.Imports[path] = &Package{ID: id}
607
		}
608
	}
609
	return nil
610
}
611

612
func (p *Package) String() string { return p.ID }
613

614
// loaderPackage augments Package with state used during the loading phase
615
type loaderPackage struct {
616
	*Package
617
	importErrors map[string]error // maps each bad import to its error
618
	loadOnce     sync.Once
619
	color        uint8 // for cycle detection
620
	needsrc      bool  // load from source (Mode >= LoadTypes)
621
	needtypes    bool  // type information is either requested or depended on
622
	initial      bool  // package was matched by a pattern
623
	goVersion    int   // minor version number of go command on PATH
624
}
625

626
// loader holds the working state of a single call to load.
627
type loader struct {
628
	pkgs map[string]*loaderPackage
629
	Config
630
	sizes        types.Sizes // non-nil if needed by mode
631
	parseCache   map[string]*parseValue
632
	parseCacheMu sync.Mutex
633
	exportMu     sync.Mutex // enforces mutual exclusion of exportdata operations
634

635
	// Config.Mode contains the implied mode (see impliedLoadMode).
636
	// Implied mode contains all the fields we need the data for.
637
	// In requestedMode there are the actually requested fields.
638
	// We'll zero them out before returning packages to the user.
639
	// This makes it easier for us to get the conditions where
640
	// we need certain modes right.
641
	requestedMode LoadMode
642
}
643

644
type parseValue struct {
645
	f     *ast.File
646
	err   error
647
	ready chan struct{}
648
}
649

650
func newLoader(cfg *Config) *loader {
651
	ld := &loader{
652
		parseCache: map[string]*parseValue{},
653
	}
654
	if cfg != nil {
655
		ld.Config = *cfg
656
		// If the user has provided a logger, use it.
657
		ld.Config.Logf = cfg.Logf
658
	}
659
	if ld.Config.Logf == nil {
660
		// If the GOPACKAGESDEBUG environment variable is set to true,
661
		// but the user has not provided a logger, default to log.Printf.
662
		if debug {
663
			ld.Config.Logf = log.Printf
664
		} else {
665
			ld.Config.Logf = func(format string, args ...interface{}) {}
666
		}
667
	}
668
	if ld.Config.Mode == 0 {
669
		ld.Config.Mode = NeedName | NeedFiles | NeedCompiledGoFiles // Preserve zero behavior of Mode for backwards compatibility.
670
	}
671
	if ld.Config.Env == nil {
672
		ld.Config.Env = os.Environ()
673
	}
674
	if ld.Config.gocmdRunner == nil {
675
		ld.Config.gocmdRunner = &gocommand.Runner{}
676
	}
677
	if ld.Context == nil {
678
		ld.Context = context.Background()
679
	}
680
	if ld.Dir == "" {
681
		if dir, err := os.Getwd(); err == nil {
682
			ld.Dir = dir
683
		}
684
	}
685

686
	// Save the actually requested fields. We'll zero them out before returning packages to the user.
687
	ld.requestedMode = ld.Mode
688
	ld.Mode = impliedLoadMode(ld.Mode)
689

690
	if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
691
		if ld.Fset == nil {
692
			ld.Fset = token.NewFileSet()
693
		}
694

695
		// ParseFile is required even in LoadTypes mode
696
		// because we load source if export data is missing.
697
		if ld.ParseFile == nil {
698
			ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
699
				const mode = parser.AllErrors | parser.ParseComments
700
				return parser.ParseFile(fset, filename, src, mode)
701
			}
702
		}
703
	}
704

705
	return ld
706
}
707

708
// refine connects the supplied packages into a graph and then adds type
709
// and syntax information as requested by the LoadMode.
710
func (ld *loader) refine(response *DriverResponse) ([]*Package, error) {
711
	roots := response.Roots
712
	rootMap := make(map[string]int, len(roots))
713
	for i, root := range roots {
714
		rootMap[root] = i
715
	}
716
	ld.pkgs = make(map[string]*loaderPackage)
717
	// first pass, fixup and build the map and roots
718
	var initial = make([]*loaderPackage, len(roots))
719
	for _, pkg := range response.Packages {
720
		rootIndex := -1
721
		if i, found := rootMap[pkg.ID]; found {
722
			rootIndex = i
723
		}
724

725
		// Overlays can invalidate export data.
726
		// TODO(matloob): make this check fine-grained based on dependencies on overlaid files
727
		exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe"
728
		// This package needs type information if the caller requested types and the package is
729
		// either a root, or it's a non-root and the user requested dependencies ...
730
		needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0))
731
		// This package needs source if the call requested source (or types info, which implies source)
732
		// and the package is either a root, or itas a non- root and the user requested dependencies...
733
		needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) ||
734
			// ... or if we need types and the exportData is invalid. We fall back to (incompletely)
735
			// typechecking packages from source if they fail to compile.
736
			(ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe"
737
		lpkg := &loaderPackage{
738
			Package:   pkg,
739
			needtypes: needtypes,
740
			needsrc:   needsrc,
741
			goVersion: response.GoVersion,
742
		}
743
		ld.pkgs[lpkg.ID] = lpkg
744
		if rootIndex >= 0 {
745
			initial[rootIndex] = lpkg
746
			lpkg.initial = true
747
		}
748
	}
749
	for i, root := range roots {
750
		if initial[i] == nil {
751
			return nil, fmt.Errorf("root package %v is missing", root)
752
		}
753
	}
754

755
	if ld.Mode&NeedImports != 0 {
756
		// Materialize the import graph.
757

758
		const (
759
			white = 0 // new
760
			grey  = 1 // in progress
761
			black = 2 // complete
762
		)
763

764
		// visit traverses the import graph, depth-first,
765
		// and materializes the graph as Packages.Imports.
766
		//
767
		// Valid imports are saved in the Packages.Import map.
768
		// Invalid imports (cycles and missing nodes) are saved in the importErrors map.
769
		// Thus, even in the presence of both kinds of errors,
770
		// the Import graph remains a DAG.
771
		//
772
		// visit returns whether the package needs src or has a transitive
773
		// dependency on a package that does. These are the only packages
774
		// for which we load source code.
775
		var stack []*loaderPackage
776
		var visit func(lpkg *loaderPackage) bool
777
		visit = func(lpkg *loaderPackage) bool {
778
			switch lpkg.color {
779
			case black:
780
				return lpkg.needsrc
781
			case grey:
782
				panic("internal error: grey node")
783
			}
784
			lpkg.color = grey
785
			stack = append(stack, lpkg) // push
786
			stubs := lpkg.Imports       // the structure form has only stubs with the ID in the Imports
787
			lpkg.Imports = make(map[string]*Package, len(stubs))
788
			for importPath, ipkg := range stubs {
789
				var importErr error
790
				imp := ld.pkgs[ipkg.ID]
791
				if imp == nil {
792
					// (includes package "C" when DisableCgo)
793
					importErr = fmt.Errorf("missing package: %q", ipkg.ID)
794
				} else if imp.color == grey {
795
					importErr = fmt.Errorf("import cycle: %s", stack)
796
				}
797
				if importErr != nil {
798
					if lpkg.importErrors == nil {
799
						lpkg.importErrors = make(map[string]error)
800
					}
801
					lpkg.importErrors[importPath] = importErr
802
					continue
803
				}
804

805
				if visit(imp) {
806
					lpkg.needsrc = true
807
				}
808
				lpkg.Imports[importPath] = imp.Package
809
			}
810

811
			// Complete type information is required for the
812
			// immediate dependencies of each source package.
813
			if lpkg.needsrc && ld.Mode&NeedTypes != 0 {
814
				for _, ipkg := range lpkg.Imports {
815
					ld.pkgs[ipkg.ID].needtypes = true
816
				}
817
			}
818

819
			// NeedTypeSizes causes TypeSizes to be set even
820
			// on packages for which types aren't needed.
821
			if ld.Mode&NeedTypesSizes != 0 {
822
				lpkg.TypesSizes = ld.sizes
823
			}
824
			stack = stack[:len(stack)-1] // pop
825
			lpkg.color = black
826

827
			return lpkg.needsrc
828
		}
829

830
		// For each initial package, create its import DAG.
831
		for _, lpkg := range initial {
832
			visit(lpkg)
833
		}
834

835
	} else {
836
		// !NeedImports: drop the stub (ID-only) import packages
837
		// that we are not even going to try to resolve.
838
		for _, lpkg := range initial {
839
			lpkg.Imports = nil
840
		}
841
	}
842

843
	// Load type data and syntax if needed, starting at
844
	// the initial packages (roots of the import DAG).
845
	if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
846
		var wg sync.WaitGroup
847
		for _, lpkg := range initial {
848
			wg.Add(1)
849
			go func(lpkg *loaderPackage) {
850
				ld.loadRecursive(lpkg)
851
				wg.Done()
852
			}(lpkg)
853
		}
854
		wg.Wait()
855
	}
856

857
	result := make([]*Package, len(initial))
858
	for i, lpkg := range initial {
859
		result[i] = lpkg.Package
860
	}
861
	for i := range ld.pkgs {
862
		// Clear all unrequested fields,
863
		// to catch programs that use more than they request.
864
		if ld.requestedMode&NeedName == 0 {
865
			ld.pkgs[i].Name = ""
866
			ld.pkgs[i].PkgPath = ""
867
		}
868
		if ld.requestedMode&NeedFiles == 0 {
869
			ld.pkgs[i].GoFiles = nil
870
			ld.pkgs[i].OtherFiles = nil
871
			ld.pkgs[i].IgnoredFiles = nil
872
		}
873
		if ld.requestedMode&NeedEmbedFiles == 0 {
874
			ld.pkgs[i].EmbedFiles = nil
875
		}
876
		if ld.requestedMode&NeedEmbedPatterns == 0 {
877
			ld.pkgs[i].EmbedPatterns = nil
878
		}
879
		if ld.requestedMode&NeedCompiledGoFiles == 0 {
880
			ld.pkgs[i].CompiledGoFiles = nil
881
		}
882
		if ld.requestedMode&NeedImports == 0 {
883
			ld.pkgs[i].Imports = nil
884
		}
885
		if ld.requestedMode&NeedExportFile == 0 {
886
			ld.pkgs[i].ExportFile = ""
887
		}
888
		if ld.requestedMode&NeedTypes == 0 {
889
			ld.pkgs[i].Types = nil
890
			ld.pkgs[i].Fset = nil
891
			ld.pkgs[i].IllTyped = false
892
		}
893
		if ld.requestedMode&NeedSyntax == 0 {
894
			ld.pkgs[i].Syntax = nil
895
		}
896
		if ld.requestedMode&NeedTypesInfo == 0 {
897
			ld.pkgs[i].TypesInfo = nil
898
		}
899
		if ld.requestedMode&NeedTypesSizes == 0 {
900
			ld.pkgs[i].TypesSizes = nil
901
		}
902
		if ld.requestedMode&NeedModule == 0 {
903
			ld.pkgs[i].Module = nil
904
		}
905
	}
906

907
	return result, nil
908
}
909

910
// loadRecursive loads the specified package and its dependencies,
911
// recursively, in parallel, in topological order.
912
// It is atomic and idempotent.
913
// Precondition: ld.Mode&NeedTypes.
914
func (ld *loader) loadRecursive(lpkg *loaderPackage) {
915
	lpkg.loadOnce.Do(func() {
916
		// Load the direct dependencies, in parallel.
917
		var wg sync.WaitGroup
918
		for _, ipkg := range lpkg.Imports {
919
			imp := ld.pkgs[ipkg.ID]
920
			wg.Add(1)
921
			go func(imp *loaderPackage) {
922
				ld.loadRecursive(imp)
923
				wg.Done()
924
			}(imp)
925
		}
926
		wg.Wait()
927
		ld.loadPackage(lpkg)
928
	})
929
}
930

931
// loadPackage loads the specified package.
932
// It must be called only once per Package,
933
// after immediate dependencies are loaded.
934
// Precondition: ld.Mode & NeedTypes.
935
func (ld *loader) loadPackage(lpkg *loaderPackage) {
936
	if lpkg.PkgPath == "unsafe" {
937
		// Fill in the blanks to avoid surprises.
938
		lpkg.Types = types.Unsafe
939
		lpkg.Fset = ld.Fset
940
		lpkg.Syntax = []*ast.File{}
941
		lpkg.TypesInfo = new(types.Info)
942
		lpkg.TypesSizes = ld.sizes
943
		return
944
	}
945

946
	// Call NewPackage directly with explicit name.
947
	// This avoids skew between golist and go/types when the files'
948
	// package declarations are inconsistent.
949
	lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name)
950
	lpkg.Fset = ld.Fset
951

952
	// Subtle: we populate all Types fields with an empty Package
953
	// before loading export data so that export data processing
954
	// never has to create a types.Package for an indirect dependency,
955
	// which would then require that such created packages be explicitly
956
	// inserted back into the Import graph as a final step after export data loading.
957
	// (Hence this return is after the Types assignment.)
958
	// The Diamond test exercises this case.
959
	if !lpkg.needtypes && !lpkg.needsrc {
960
		return
961
	}
962
	if !lpkg.needsrc {
963
		if err := ld.loadFromExportData(lpkg); err != nil {
964
			lpkg.Errors = append(lpkg.Errors, Error{
965
				Pos:  "-",
966
				Msg:  err.Error(),
967
				Kind: UnknownError, // e.g. can't find/open/parse export data
968
			})
969
		}
970
		return // not a source package, don't get syntax trees
971
	}
972

973
	appendError := func(err error) {
974
		// Convert various error types into the one true Error.
975
		var errs []Error
976
		switch err := err.(type) {
977
		case Error:
978
			// from driver
979
			errs = append(errs, err)
980

981
		case *os.PathError:
982
			// from parser
983
			errs = append(errs, Error{
984
				Pos:  err.Path + ":1",
985
				Msg:  err.Err.Error(),
986
				Kind: ParseError,
987
			})
988

989
		case scanner.ErrorList:
990
			// from parser
991
			for _, err := range err {
992
				errs = append(errs, Error{
993
					Pos:  err.Pos.String(),
994
					Msg:  err.Msg,
995
					Kind: ParseError,
996
				})
997
			}
998

999
		case types.Error:
1000
			// from type checker
1001
			lpkg.TypeErrors = append(lpkg.TypeErrors, err)
1002
			errs = append(errs, Error{
1003
				Pos:  err.Fset.Position(err.Pos).String(),
1004
				Msg:  err.Msg,
1005
				Kind: TypeError,
1006
			})
1007

1008
		default:
1009
			// unexpected impoverished error from parser?
1010
			errs = append(errs, Error{
1011
				Pos:  "-",
1012
				Msg:  err.Error(),
1013
				Kind: UnknownError,
1014
			})
1015

1016
			// If you see this error message, please file a bug.
1017
			log.Printf("internal error: error %q (%T) without position", err, err)
1018
		}
1019

1020
		lpkg.Errors = append(lpkg.Errors, errs...)
1021
	}
1022

1023
	// If the go command on the PATH is newer than the runtime,
1024
	// then the go/{scanner,ast,parser,types} packages from the
1025
	// standard library may be unable to process the files
1026
	// selected by go list.
1027
	//
1028
	// There is currently no way to downgrade the effective
1029
	// version of the go command (see issue 52078), so we proceed
1030
	// with the newer go command but, in case of parse or type
1031
	// errors, we emit an additional diagnostic.
1032
	//
1033
	// See:
1034
	// - golang.org/issue/52078 (flag to set release tags)
1035
	// - golang.org/issue/50825 (gopls legacy version support)
1036
	// - golang.org/issue/55883 (go/packages confusing error)
1037
	//
1038
	// Should we assert a hard minimum of (currently) go1.16 here?
1039
	var runtimeVersion int
1040
	if _, err := fmt.Sscanf(runtime.Version(), "go1.%d", &runtimeVersion); err == nil && runtimeVersion < lpkg.goVersion {
1041
		defer func() {
1042
			if len(lpkg.Errors) > 0 {
1043
				appendError(Error{
1044
					Pos:  "-",
1045
					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),
1046
					Kind: UnknownError,
1047
				})
1048
			}
1049
		}()
1050
	}
1051

1052
	if ld.Config.Mode&NeedTypes != 0 && len(lpkg.CompiledGoFiles) == 0 && lpkg.ExportFile != "" {
1053
		// The config requested loading sources and types, but sources are missing.
1054
		// Add an error to the package and fall back to loading from export data.
1055
		appendError(Error{"-", fmt.Sprintf("sources missing for package %s", lpkg.ID), ParseError})
1056
		_ = ld.loadFromExportData(lpkg) // ignore any secondary errors
1057

1058
		return // can't get syntax trees for this package
1059
	}
1060

1061
	files, errs := ld.parseFiles(lpkg.CompiledGoFiles)
1062
	for _, err := range errs {
1063
		appendError(err)
1064
	}
1065

1066
	lpkg.Syntax = files
1067
	if ld.Config.Mode&NeedTypes == 0 {
1068
		return
1069
	}
1070

1071
	lpkg.TypesInfo = &types.Info{
1072
		Types:      make(map[ast.Expr]types.TypeAndValue),
1073
		Defs:       make(map[*ast.Ident]types.Object),
1074
		Uses:       make(map[*ast.Ident]types.Object),
1075
		Implicits:  make(map[ast.Node]types.Object),
1076
		Instances:  make(map[*ast.Ident]types.Instance),
1077
		Scopes:     make(map[ast.Node]*types.Scope),
1078
		Selections: make(map[*ast.SelectorExpr]*types.Selection),
1079
	}
1080
	versions.InitFileVersions(lpkg.TypesInfo)
1081
	lpkg.TypesSizes = ld.sizes
1082

1083
	importer := importerFunc(func(path string) (*types.Package, error) {
1084
		if path == "unsafe" {
1085
			return types.Unsafe, nil
1086
		}
1087

1088
		// The imports map is keyed by import path.
1089
		ipkg := lpkg.Imports[path]
1090
		if ipkg == nil {
1091
			if err := lpkg.importErrors[path]; err != nil {
1092
				return nil, err
1093
			}
1094
			// There was skew between the metadata and the
1095
			// import declarations, likely due to an edit
1096
			// race, or because the ParseFile feature was
1097
			// used to supply alternative file contents.
1098
			return nil, fmt.Errorf("no metadata for %s", path)
1099
		}
1100

1101
		if ipkg.Types != nil && ipkg.Types.Complete() {
1102
			return ipkg.Types, nil
1103
		}
1104
		log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg)
1105
		panic("unreachable")
1106
	})
1107

1108
	// type-check
1109
	tc := &types.Config{
1110
		Importer: importer,
1111

1112
		// Type-check bodies of functions only in initial packages.
1113
		// Example: for import graph A->B->C and initial packages {A,C},
1114
		// we can ignore function bodies in B.
1115
		IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial,
1116

1117
		Error: appendError,
1118
		Sizes: ld.sizes, // may be nil
1119
	}
1120
	if lpkg.Module != nil && lpkg.Module.GoVersion != "" {
1121
		tc.GoVersion = "go" + lpkg.Module.GoVersion
1122
	}
1123
	if (ld.Mode & typecheckCgo) != 0 {
1124
		if !typesinternal.SetUsesCgo(tc) {
1125
			appendError(Error{
1126
				Msg:  "typecheckCgo requires Go 1.15+",
1127
				Kind: ListError,
1128
			})
1129
			return
1130
		}
1131
	}
1132

1133
	typErr := types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)
1134
	lpkg.importErrors = nil // no longer needed
1135

1136
	// In go/types go1.21 and go1.22, Checker.Files failed fast with a
1137
	// a "too new" error, without calling tc.Error and without
1138
	// proceeding to type-check the package (#66525).
1139
	// We rely on the runtimeVersion error to give the suggested remedy.
1140
	if typErr != nil && len(lpkg.Errors) == 0 && len(lpkg.Syntax) > 0 {
1141
		if msg := typErr.Error(); strings.HasPrefix(msg, "package requires newer Go version") {
1142
			appendError(types.Error{
1143
				Fset: ld.Fset,
1144
				Pos:  lpkg.Syntax[0].Package,
1145
				Msg:  msg,
1146
			})
1147
		}
1148
	}
1149

1150
	// If !Cgo, the type-checker uses FakeImportC mode, so
1151
	// it doesn't invoke the importer for import "C",
1152
	// nor report an error for the import,
1153
	// or for any undefined C.f reference.
1154
	// We must detect this explicitly and correctly
1155
	// mark the package as IllTyped (by reporting an error).
1156
	// TODO(adonovan): if these errors are annoying,
1157
	// we could just set IllTyped quietly.
1158
	if tc.FakeImportC {
1159
	outer:
1160
		for _, f := range lpkg.Syntax {
1161
			for _, imp := range f.Imports {
1162
				if imp.Path.Value == `"C"` {
1163
					err := types.Error{Fset: ld.Fset, Pos: imp.Pos(), Msg: `import "C" ignored`}
1164
					appendError(err)
1165
					break outer
1166
				}
1167
			}
1168
		}
1169
	}
1170

1171
	// If types.Checker.Files had an error that was unreported,
1172
	// make sure to report the unknown error so the package is illTyped.
1173
	if typErr != nil && len(lpkg.Errors) == 0 {
1174
		appendError(typErr)
1175
	}
1176

1177
	// Record accumulated errors.
1178
	illTyped := len(lpkg.Errors) > 0
1179
	if !illTyped {
1180
		for _, imp := range lpkg.Imports {
1181
			if imp.IllTyped {
1182
				illTyped = true
1183
				break
1184
			}
1185
		}
1186
	}
1187
	lpkg.IllTyped = illTyped
1188
}
1189

1190
// An importFunc is an implementation of the single-method
1191
// types.Importer interface based on a function value.
1192
type importerFunc func(path string) (*types.Package, error)
1193

1194
func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
1195

1196
// We use a counting semaphore to limit
1197
// the number of parallel I/O calls per process.
1198
var ioLimit = make(chan bool, 20)
1199

1200
func (ld *loader) parseFile(filename string) (*ast.File, error) {
1201
	ld.parseCacheMu.Lock()
1202
	v, ok := ld.parseCache[filename]
1203
	if ok {
1204
		// cache hit
1205
		ld.parseCacheMu.Unlock()
1206
		<-v.ready
1207
	} else {
1208
		// cache miss
1209
		v = &parseValue{ready: make(chan struct{})}
1210
		ld.parseCache[filename] = v
1211
		ld.parseCacheMu.Unlock()
1212

1213
		var src []byte
1214
		for f, contents := range ld.Config.Overlay {
1215
			if sameFile(f, filename) {
1216
				src = contents
1217
			}
1218
		}
1219
		var err error
1220
		if src == nil {
1221
			ioLimit <- true // wait
1222
			src, err = os.ReadFile(filename)
1223
			<-ioLimit // signal
1224
		}
1225
		if err != nil {
1226
			v.err = err
1227
		} else {
1228
			v.f, v.err = ld.ParseFile(ld.Fset, filename, src)
1229
		}
1230

1231
		close(v.ready)
1232
	}
1233
	return v.f, v.err
1234
}
1235

1236
// parseFiles reads and parses the Go source files and returns the ASTs
1237
// of the ones that could be at least partially parsed, along with a
1238
// list of I/O and parse errors encountered.
1239
//
1240
// Because files are scanned in parallel, the token.Pos
1241
// positions of the resulting ast.Files are not ordered.
1242
func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) {
1243
	var wg sync.WaitGroup
1244
	n := len(filenames)
1245
	parsed := make([]*ast.File, n)
1246
	errors := make([]error, n)
1247
	for i, file := range filenames {
1248
		if ld.Config.Context.Err() != nil {
1249
			parsed[i] = nil
1250
			errors[i] = ld.Config.Context.Err()
1251
			continue
1252
		}
1253
		wg.Add(1)
1254
		go func(i int, filename string) {
1255
			parsed[i], errors[i] = ld.parseFile(filename)
1256
			wg.Done()
1257
		}(i, file)
1258
	}
1259
	wg.Wait()
1260

1261
	// Eliminate nils, preserving order.
1262
	var o int
1263
	for _, f := range parsed {
1264
		if f != nil {
1265
			parsed[o] = f
1266
			o++
1267
		}
1268
	}
1269
	parsed = parsed[:o]
1270

1271
	o = 0
1272
	for _, err := range errors {
1273
		if err != nil {
1274
			errors[o] = err
1275
			o++
1276
		}
1277
	}
1278
	errors = errors[:o]
1279

1280
	return parsed, errors
1281
}
1282

1283
// sameFile returns true if x and y have the same basename and denote
1284
// the same file.
1285
func sameFile(x, y string) bool {
1286
	if x == y {
1287
		// It could be the case that y doesn't exist.
1288
		// For instance, it may be an overlay file that
1289
		// hasn't been written to disk. To handle that case
1290
		// let x == y through. (We added the exact absolute path
1291
		// string to the CompiledGoFiles list, so the unwritten
1292
		// overlay case implies x==y.)
1293
		return true
1294
	}
1295
	if strings.EqualFold(filepath.Base(x), filepath.Base(y)) { // (optimisation)
1296
		if xi, err := os.Stat(x); err == nil {
1297
			if yi, err := os.Stat(y); err == nil {
1298
				return os.SameFile(xi, yi)
1299
			}
1300
		}
1301
	}
1302
	return false
1303
}
1304

1305
// loadFromExportData ensures that type information is present for the specified
1306
// package, loading it from an export data file on the first request.
1307
// On success it sets lpkg.Types to a new Package.
1308
func (ld *loader) loadFromExportData(lpkg *loaderPackage) error {
1309
	if lpkg.PkgPath == "" {
1310
		log.Fatalf("internal error: Package %s has no PkgPath", lpkg)
1311
	}
1312

1313
	// Because gcexportdata.Read has the potential to create or
1314
	// modify the types.Package for each node in the transitive
1315
	// closure of dependencies of lpkg, all exportdata operations
1316
	// must be sequential. (Finer-grained locking would require
1317
	// changes to the gcexportdata API.)
1318
	//
1319
	// The exportMu lock guards the lpkg.Types field and the
1320
	// types.Package it points to, for each loaderPackage in the graph.
1321
	//
1322
	// Not all accesses to Package.Pkg need to be protected by exportMu:
1323
	// graph ordering ensures that direct dependencies of source
1324
	// packages are fully loaded before the importer reads their Pkg field.
1325
	ld.exportMu.Lock()
1326
	defer ld.exportMu.Unlock()
1327

1328
	if tpkg := lpkg.Types; tpkg != nil && tpkg.Complete() {
1329
		return nil // cache hit
1330
	}
1331

1332
	lpkg.IllTyped = true // fail safe
1333

1334
	if lpkg.ExportFile == "" {
1335
		// Errors while building export data will have been printed to stderr.
1336
		return fmt.Errorf("no export data file")
1337
	}
1338
	f, err := os.Open(lpkg.ExportFile)
1339
	if err != nil {
1340
		return err
1341
	}
1342
	defer f.Close()
1343

1344
	// Read gc export data.
1345
	//
1346
	// We don't currently support gccgo export data because all
1347
	// underlying workspaces use the gc toolchain. (Even build
1348
	// systems that support gccgo don't use it for workspace
1349
	// queries.)
1350
	r, err := gcexportdata.NewReader(f)
1351
	if err != nil {
1352
		return fmt.Errorf("reading %s: %v", lpkg.ExportFile, err)
1353
	}
1354

1355
	// Build the view.
1356
	//
1357
	// The gcexportdata machinery has no concept of package ID.
1358
	// It identifies packages by their PkgPath, which although not
1359
	// globally unique is unique within the scope of one invocation
1360
	// of the linker, type-checker, or gcexportdata.
1361
	//
1362
	// So, we must build a PkgPath-keyed view of the global
1363
	// (conceptually ID-keyed) cache of packages and pass it to
1364
	// gcexportdata. The view must contain every existing
1365
	// package that might possibly be mentioned by the
1366
	// current package---its transitive closure.
1367
	//
1368
	// In loadPackage, we unconditionally create a types.Package for
1369
	// each dependency so that export data loading does not
1370
	// create new ones.
1371
	//
1372
	// TODO(adonovan): it would be simpler and more efficient
1373
	// if the export data machinery invoked a callback to
1374
	// get-or-create a package instead of a map.
1375
	//
1376
	view := make(map[string]*types.Package) // view seen by gcexportdata
1377
	seen := make(map[*loaderPackage]bool)   // all visited packages
1378
	var visit func(pkgs map[string]*Package)
1379
	visit = func(pkgs map[string]*Package) {
1380
		for _, p := range pkgs {
1381
			lpkg := ld.pkgs[p.ID]
1382
			if !seen[lpkg] {
1383
				seen[lpkg] = true
1384
				view[lpkg.PkgPath] = lpkg.Types
1385
				visit(lpkg.Imports)
1386
			}
1387
		}
1388
	}
1389
	visit(lpkg.Imports)
1390

1391
	viewLen := len(view) + 1 // adding the self package
1392
	// Parse the export data.
1393
	// (May modify incomplete packages in view but not create new ones.)
1394
	tpkg, err := gcexportdata.Read(r, ld.Fset, view, lpkg.PkgPath)
1395
	if err != nil {
1396
		return fmt.Errorf("reading %s: %v", lpkg.ExportFile, err)
1397
	}
1398
	if _, ok := view["go.shape"]; ok {
1399
		// Account for the pseudopackage "go.shape" that gets
1400
		// created by generic code.
1401
		viewLen++
1402
	}
1403
	if viewLen != len(view) {
1404
		log.Panicf("golang.org/x/tools/go/packages: unexpected new packages during load of %s", lpkg.PkgPath)
1405
	}
1406

1407
	lpkg.Types = tpkg
1408
	lpkg.IllTyped = false
1409
	return nil
1410
}
1411

1412
// impliedLoadMode returns loadMode with its dependencies.
1413
func impliedLoadMode(loadMode LoadMode) LoadMode {
1414
	if loadMode&(NeedDeps|NeedTypes|NeedTypesInfo) != 0 {
1415
		// All these things require knowing the import graph.
1416
		loadMode |= NeedImports
1417
	}
1418

1419
	return loadMode
1420
}
1421

1422
func usesExportData(cfg *Config) bool {
1423
	return cfg.Mode&NeedExportFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0
1424
}
1425

1426
var _ interface{} = io.Discard // assert build toolchain is go1.16 or later
1427

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.