@@ -30,32 +30,78 @@ import (
3030// but may be slower. Load may return more information than requested.
3131type LoadMode int
3232
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+
3379const (
3480 // 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
3783
3884 // LoadImports adds import information for each package
3985 // and its dependencies.
4086 // Package fields added: Imports.
41- LoadImports
87+ LoadImports = LoadFiles | NeedImports | NeedDeps
4288
4389 // LoadTypes adds type information for package-level
4490 // declarations in the packages matching the patterns.
4591 // Package fields added: Types, Fset, and IllTyped.
4692 // This mode uses type information provided by the build system when
4793 // possible, and may fill in the ExportFile field.
48- LoadTypes
94+ LoadTypes = LoadImports | NeedTypes
4995
5096 // LoadSyntax adds typed syntax trees for the packages matching the patterns.
5197 // Package fields added: Syntax, and TypesInfo, for direct pattern matches only.
52- LoadSyntax
98+ LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo | NeedTypesSizes
5399
54100 // LoadAllSyntax adds typed syntax trees for the packages matching the patterns
55101 // and all dependencies.
56102 // Package fields added: Types, Fset, IllTyped, Syntax, and TypesInfo,
57103 // for all packages in the import graph.
58- LoadAllSyntax
104+ LoadAllSyntax = LoadSyntax
59105)
60106
61107// A Config specifies details about how packages should be loaded.
@@ -381,6 +427,9 @@ func newLoader(cfg *Config) *loader {
381427 if cfg != nil {
382428 ld .Config = * cfg
383429 }
430+ if ld .Config .Mode == 0 {
431+ ld .Config .Mode = LoadFiles // Preserve zero behavior of Mode for backwards compatibility.
432+ }
384433 if ld .Config .Env == nil {
385434 ld .Config .Env = os .Environ ()
386435 }
@@ -393,7 +442,7 @@ func newLoader(cfg *Config) *loader {
393442 }
394443 }
395444
396- if ld .Mode >= LoadTypes {
445+ if ld .Mode & NeedTypes != 0 {
397446 if ld .Fset == nil {
398447 ld .Fset = token .NewFileSet ()
399448 }
@@ -430,11 +479,9 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
430479 rootIndex = i
431480 }
432481 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 ||
438485 len (ld .Overlay ) > 0 || // Overlays can invalidate export data. TODO(matloob): make this check fine-grained based on dependencies on overlaid files
439486 pkg .ExportFile == "" && pkg .PkgPath != "unsafe" ,
440487 }
@@ -513,8 +560,8 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
513560 return lpkg .needsrc
514561 }
515562
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.
518565 for _ , lpkg := range initial {
519566 lpkg .Imports = nil
520567 }
@@ -524,17 +571,19 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
524571 visit (lpkg )
525572 }
526573 }
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+ }
533582 }
534583 }
535584 // Load type data if needed, starting at
536585 // the initial packages (roots of the import DAG).
537- if ld .Mode >= LoadTypes {
586+ if ld .Mode & NeedTypes != 0 {
538587 var wg sync.WaitGroup
539588 for _ , lpkg := range initial {
540589 wg .Add (1 )
@@ -547,16 +596,59 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
547596 }
548597
549598 result := make ([]* Package , len (initial ))
599+ importPlaceholders := make (map [string ]* Package )
550600 for i , lpkg := range initial {
551601 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+ }
552644 }
553645 return result , nil
554646}
555647
556648// loadRecursive loads the specified package and its dependencies,
557649// recursively, in parallel, in topological order.
558650// It is atomic and idempotent.
559- // Precondition: ld.Mode >= LoadTypes .
651+ // Precondition: ld.Mode&NeedTypes .
560652func (ld * loader ) loadRecursive (lpkg * loaderPackage ) {
561653 lpkg .loadOnce .Do (func () {
562654 // Load the direct dependencies, in parallel.
@@ -708,7 +800,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
708800 // Type-check bodies of functions only in non-initial packages.
709801 // Example: for import graph A->B->C and initial packages {A,C},
710802 // we can ignore function bodies in B.
711- IgnoreFuncBodies : ld .Mode < LoadAllSyntax && ! lpkg .initial ,
803+ IgnoreFuncBodies : ( ld .Mode & ( NeedDeps | NeedTypesInfo ) == 0 ) && ! lpkg .initial ,
712804
713805 Error : appendError ,
714806 Sizes : ld .sizes ,
@@ -952,5 +1044,5 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error
9521044}
9531045
9541046func 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
9561048}
0 commit comments