@@ -30,32 +30,78 @@ import (
30
30
// but may be slower. Load may return more information than requested.
31
31
type LoadMode int
32
32
33
+ const (
34
+ // The following constants are used to specify which fields of the Package
35
+ // should be filled when loading is done. As a special case to provide
36
+ // backwards compatibility, a LoadMode of 0 is equivalent to LoadFiles.
37
+ // For all other LoadModes, the bits below specify which fields will be filled
38
+ // in the result packages.
39
+ // WARNING: This part of the go/packages API is EXPERIMENTAL. It might
40
+ // be changed or removed up until April 15 2019. After that date it will
41
+ // be frozen.
42
+ // TODO(matloob): Remove this comment on April 15.
43
+
44
+ // ID and Errors (if present) will always be filled.
45
+
46
+ // NeedName adds Name and PkgPath.
47
+ NeedName LoadMode = 1 << iota
48
+
49
+ // NeedFiles adds GoFiles and OtherFiles.
50
+ NeedFiles
51
+
52
+ // NeedCompiledGoFiles adds CompiledGoFiles.
53
+ NeedCompiledGoFiles
54
+
55
+ // NeedImports adds Imports. If NeedDeps is not set, the Imports field will contain
56
+ // "placeholder" Packages with only the ID set.
57
+ NeedImports
58
+
59
+ // NeedDeps adds the fields requested by the LoadMode in the packages in Imports. If NeedImports
60
+ // is not set NeedDeps has no effect.
61
+ NeedDeps
62
+
63
+ // NeedExportsFile adds ExportsFile.
64
+ NeedExportsFile
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
+
33
79
const (
34
80
// LoadFiles finds the packages and computes their source file lists.
35
- // Package fields: ID, Name, Errors, GoFiles, and OtherFiles.
36
- LoadFiles LoadMode = iota
81
+ // Package fields: ID, Name, Errors, GoFiles, CompiledGoFiles, and OtherFiles.
82
+ LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles
37
83
38
84
// LoadImports adds import information for each package
39
85
// and its dependencies.
40
86
// Package fields added: Imports.
41
- LoadImports
87
+ LoadImports = LoadFiles | NeedImports | NeedDeps
42
88
43
89
// LoadTypes adds type information for package-level
44
90
// declarations in the packages matching the patterns.
45
91
// Package fields added: Types, Fset, and IllTyped.
46
92
// This mode uses type information provided by the build system when
47
93
// possible, and may fill in the ExportFile field.
48
- LoadTypes
94
+ LoadTypes = LoadImports | NeedTypes
49
95
50
96
// LoadSyntax adds typed syntax trees for the packages matching the patterns.
51
97
// Package fields added: Syntax, and TypesInfo, for direct pattern matches only.
52
- LoadSyntax
98
+ LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo | NeedTypesSizes
53
99
54
100
// LoadAllSyntax adds typed syntax trees for the packages matching the patterns
55
101
// and all dependencies.
56
102
// Package fields added: Types, Fset, IllTyped, Syntax, and TypesInfo,
57
103
// for all packages in the import graph.
58
- LoadAllSyntax
104
+ LoadAllSyntax = LoadSyntax
59
105
)
60
106
61
107
// A Config specifies details about how packages should be loaded.
@@ -381,6 +427,9 @@ func newLoader(cfg *Config) *loader {
381
427
if cfg != nil {
382
428
ld .Config = * cfg
383
429
}
430
+ if ld .Config .Mode == 0 {
431
+ ld .Config .Mode = LoadFiles // Preserve zero behavior of Mode for backwards compatibility.
432
+ }
384
433
if ld .Config .Env == nil {
385
434
ld .Config .Env = os .Environ ()
386
435
}
@@ -393,7 +442,7 @@ func newLoader(cfg *Config) *loader {
393
442
}
394
443
}
395
444
396
- if ld .Mode >= LoadTypes {
445
+ if ld .Mode & NeedTypes != 0 {
397
446
if ld .Fset == nil {
398
447
ld .Fset = token .NewFileSet ()
399
448
}
@@ -430,11 +479,9 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
430
479
rootIndex = i
431
480
}
432
481
lpkg := & loaderPackage {
433
- Package : pkg ,
434
- needtypes : ld .Mode >= LoadAllSyntax ||
435
- ld .Mode >= LoadTypes && rootIndex >= 0 ,
436
- needsrc : ld .Mode >= LoadAllSyntax ||
437
- ld .Mode >= LoadSyntax && rootIndex >= 0 ||
482
+ Package : pkg ,
483
+ needtypes : (ld .Mode & (NeedTypes | NeedTypesInfo ) != 0 && rootIndex < 0 ) || rootIndex >= 0 ,
484
+ needsrc : (ld .Mode & (NeedSyntax | NeedTypesInfo ) != 0 && rootIndex < 0 ) || rootIndex >= 0 ||
438
485
len (ld .Overlay ) > 0 || // Overlays can invalidate export data. TODO(matloob): make this check fine-grained based on dependencies on overlaid files
439
486
pkg .ExportFile == "" && pkg .PkgPath != "unsafe" ,
440
487
}
@@ -513,8 +560,8 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
513
560
return lpkg .needsrc
514
561
}
515
562
516
- if ld .Mode < LoadImports {
517
- //we do this to drop the stub import packages that we are not even going to try to resolve
563
+ if ld .Mode & NeedImports == 0 {
564
+ // We do this to drop the stub import packages that we are not even going to try to resolve.
518
565
for _ , lpkg := range initial {
519
566
lpkg .Imports = nil
520
567
}
@@ -524,17 +571,19 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
524
571
visit (lpkg )
525
572
}
526
573
}
527
- for _ , lpkg := range srcPkgs {
528
- // Complete type information is required for the
529
- // immediate dependencies of each source package.
530
- for _ , ipkg := range lpkg .Imports {
531
- imp := ld .pkgs [ipkg .ID ]
532
- imp .needtypes = true
574
+ if ld .Mode & NeedDeps != 0 {
575
+ for _ , lpkg := range srcPkgs {
576
+ // Complete type information is required for the
577
+ // immediate dependencies of each source package.
578
+ for _ , ipkg := range lpkg .Imports {
579
+ imp := ld .pkgs [ipkg .ID ]
580
+ imp .needtypes = true
581
+ }
533
582
}
534
583
}
535
584
// Load type data if needed, starting at
536
585
// the initial packages (roots of the import DAG).
537
- if ld .Mode >= LoadTypes {
586
+ if ld .Mode & NeedTypes != 0 {
538
587
var wg sync.WaitGroup
539
588
for _ , lpkg := range initial {
540
589
wg .Add (1 )
@@ -547,16 +596,59 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
547
596
}
548
597
549
598
result := make ([]* Package , len (initial ))
599
+ importPlaceholders := make (map [string ]* Package )
550
600
for i , lpkg := range initial {
551
601
result [i ] = lpkg .Package
602
+ // Clear all unrequested fields, for extra de-Hyrum-ization.
603
+ if ld .Mode & NeedName == 0 {
604
+ result [i ].Name = ""
605
+ result [i ].PkgPath = ""
606
+ }
607
+ if ld .Mode & NeedFiles == 0 {
608
+ result [i ].GoFiles = nil
609
+ result [i ].OtherFiles = nil
610
+ }
611
+ if ld .Mode & NeedCompiledGoFiles == 0 {
612
+ result [i ].CompiledGoFiles = nil
613
+ }
614
+ if ld .Mode & NeedImports == 0 {
615
+ result [i ].Imports = nil
616
+ }
617
+ if ld .Mode & NeedExportsFile == 0 {
618
+ result [i ].ExportFile = ""
619
+ }
620
+ if ld .Mode & NeedTypes == 0 {
621
+ result [i ].Types = nil
622
+ result [i ].Fset = nil
623
+ result [i ].IllTyped = false
624
+ }
625
+ if ld .Mode & NeedSyntax == 0 {
626
+ result [i ].Syntax = nil
627
+ }
628
+ if ld .Mode & NeedTypesInfo == 0 {
629
+ result [i ].TypesInfo = nil
630
+ }
631
+ if ld .Mode & NeedTypesSizes == 0 {
632
+ result [i ].TypesSizes = nil
633
+ }
634
+ if ld .Mode & NeedDeps == 0 {
635
+ for j , pkg := range result [i ].Imports {
636
+ ph , ok := importPlaceholders [pkg .ID ]
637
+ if ! ok {
638
+ ph = & Package {ID : pkg .ID }
639
+ importPlaceholders [pkg .ID ] = ph
640
+ }
641
+ result [i ].Imports [j ] = ph
642
+ }
643
+ }
552
644
}
553
645
return result , nil
554
646
}
555
647
556
648
// loadRecursive loads the specified package and its dependencies,
557
649
// recursively, in parallel, in topological order.
558
650
// It is atomic and idempotent.
559
- // Precondition: ld.Mode >= LoadTypes .
651
+ // Precondition: ld.Mode&NeedTypes .
560
652
func (ld * loader ) loadRecursive (lpkg * loaderPackage ) {
561
653
lpkg .loadOnce .Do (func () {
562
654
// Load the direct dependencies, in parallel.
@@ -708,7 +800,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
708
800
// Type-check bodies of functions only in non-initial packages.
709
801
// Example: for import graph A->B->C and initial packages {A,C},
710
802
// we can ignore function bodies in B.
711
- IgnoreFuncBodies : ld .Mode < LoadAllSyntax && ! lpkg .initial ,
803
+ IgnoreFuncBodies : ( ld .Mode & ( NeedDeps | NeedTypesInfo ) == 0 ) && ! lpkg .initial ,
712
804
713
805
Error : appendError ,
714
806
Sizes : ld .sizes ,
@@ -952,5 +1044,5 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error
952
1044
}
953
1045
954
1046
func usesExportData (cfg * Config ) bool {
955
- return LoadTypes <= cfg .Mode && cfg .Mode < LoadAllSyntax
1047
+ return cfg . Mode & NeedExportsFile != 0 || cfg .Mode & NeedTypes != 0 && cfg .Mode & NeedTypesInfo == 0
956
1048
}
0 commit comments