@@ -323,7 +323,7 @@ func (l *loader) parseFile(filename string, src []byte) (*ast.File, error) {
323323// populated. Additional information, like ASTs and type-checking information,
324324// can be accessed via methods on individual packages.
325325func LoadRoots (roots ... string ) ([]* Package , error ) {
326- return LoadRootsWithConfig (nil , roots ... )
326+ return LoadRootsWithConfig (& packages. Config {} , roots ... )
327327}
328328
329329// LoadRootsWithConfig functions like LoadRoots, except that it allows passing
@@ -366,41 +366,30 @@ func LoadRoots(roots ...string) ([]*Package, error) {
366366//
367367// 5. Load the filesystem path roots and return the load packages for the
368368// package/module roots AND the filesystem path roots.
369- //
370- //nolint:gocyclo
371- func LoadRootsWithConfig (cfg * packages.Config , roots ... string ) (result []* Package , retErr error ) {
369+ func LoadRootsWithConfig (cfg * packages.Config , roots ... string ) ([]* Package , error ) {
370+ l := & loader {
371+ cfg : cfg ,
372+ packages : make (map [* packages.Package ]* Package ),
373+ }
374+ l .cfg .Mode |= packages .LoadImports | packages .NeedTypesSizes
375+ if l .cfg .Fset == nil {
376+ l .cfg .Fset = token .NewFileSet ()
377+ }
378+ // put our build flags first so that callers can override them
379+ l .cfg .BuildFlags = append ([]string {"-tags" , "ignore_autogenerated" }, l .cfg .BuildFlags ... )
380+
381+ // Visit the import graphs of the loaded, root packages. If an imported
382+ // package refers to another loaded, root package, then replace the
383+ // instance of the imported package with a reference to the loaded, root
384+ // package. This is required to make kubebuilder markers work correctly
385+ // when multiple root paths are loaded and types from one path reference
386+ // types from another root path.
372387 defer func () {
373- if retErr != nil {
374- return
375- }
376- for i := range result {
377- visitImports (result , result [i ], nil )
388+ for i := range l .Roots {
389+ visitImports (l .Roots , l .Roots [i ], nil )
378390 }
379391 }()
380392
381- newLoader := func (cfg * packages.Config , cfgDir string ) * loader {
382- if cfg == nil {
383- cfg = & packages.Config {
384- Dir : cfgDir ,
385- }
386- }
387- l := & loader {
388- cfg : cfg ,
389- packages : map [* packages.Package ]* Package {},
390- }
391- l .cfg .Mode |= packages .LoadImports | packages .NeedTypesSizes
392- if l .cfg .Fset == nil {
393- l .cfg .Fset = token .NewFileSet ()
394- }
395- // put our build flags first so that callers can override them
396- l .cfg .BuildFlags = append ([]string {"-tags" , "ignore_autogenerated" }, l .cfg .BuildFlags ... )
397-
398- return l
399- }
400-
401- // initialize the default loader
402- l := newLoader (cfg , "" )
403-
404393 // uniquePkgIDs is used to keep track of the discovered packages to be nice
405394 // and try and prevent packages from showing up twice when nested module
406395 // support is enabled. there is not harm that comes from this per se, but
@@ -412,7 +401,7 @@ func LoadRootsWithConfig(cfg *packages.Config, roots ...string) (result []*Packa
412401 // if validatePkgFn is nil, a package will be returned in the slice,
413402 // otherwise the package is only returned if the result of
414403 // validatePkgFn(pkg.ID) is truthy
415- loadPackages := func (l * loader , roots ... string ) ([]* Package , error ) {
404+ loadPackages := func (roots ... string ) ([]* Package , error ) {
416405 rawPkgs , err := packages .Load (l .cfg , roots ... )
417406 if err != nil {
418407 return nil , err
@@ -430,11 +419,12 @@ func LoadRootsWithConfig(cfg *packages.Config, roots ...string) (result []*Packa
430419
431420 // if no roots were provided then load the current package and return early
432421 if len (roots ) == 0 {
433- pkgs , err := loadPackages (l )
422+ pkgs , err := loadPackages ()
434423 if err != nil {
435424 return nil , err
436425 }
437- return pkgs , nil
426+ l .Roots = append (l .Roots , pkgs ... )
427+ return l .Roots , nil
438428 }
439429
440430 // pkgRoots is a slice of roots that are package/modules and fspRoots
@@ -460,39 +450,34 @@ func LoadRootsWithConfig(cfg *packages.Config, roots ...string) (result []*Packa
460450 // system path roots due to them needing a custom, calculated value for the
461451 // cfg.Dir field
462452 if len (pkgRoots ) > 0 {
463- pkgs , err := loadPackages (l , pkgRoots ... )
453+ pkgs , err := loadPackages (pkgRoots ... )
464454 if err != nil {
465455 return nil , err
466456 }
467- result = append (result , pkgs ... )
457+ l . Roots = append (l . Roots , pkgs ... )
468458 }
469459
470460 // if there are no filesystem path roots then go ahead and return early
471461 if len (fspRoots ) == 0 {
472- return result , nil
462+ return l . Roots , nil
473463 }
474464
475465 //
476466 // at this point we are handling filesystem path roots
477467 //
478468
479- // store the value of cfg.Dir so we can use it later if it is non-empty.
480- // we need to store it now as the value of cfg.Dir will be updated by
481- // a loop below
482- var cfgDir string
483- if cfg != nil {
484- cfgDir = cfg .Dir
485- }
486-
487469 // ensure the cfg.Dir field is reset to its original value upon
488470 // returning from this function. it should honestly be fine if it is
489471 // not given most callers will not send in the cfg parameter directly,
490472 // as it's largely for testing, but still, let's be good stewards.
491473 defer func (d string ) {
492- if cfg != nil {
493- cfg .Dir = d
494- }
495- }(cfgDir )
474+ cfg .Dir = d
475+ }(cfg .Dir )
476+
477+ // store the value of cfg.Dir so we can use it later if it is non-empty.
478+ // we need to store it now as the value of cfg.Dir will be updated by
479+ // a loop below
480+ cfgDir := cfg .Dir
496481
497482 // addNestedGoModulesToRoots is given to filepath.WalkDir and adds the
498483 // directory part of p to the list of filesystem path roots IFF p is the
@@ -591,16 +576,9 @@ func LoadRootsWithConfig(cfg *packages.Config, roots ...string) (result []*Packa
591576 b = "."
592577 }
593578
594- // create the loader for this filesystem path. this is required in order
595- // to properly load the files as AST later in various workflows,
596- // including CRD generation
597- var fspLoader * loader
598- if cfg == nil {
599- fspLoader = newLoader (nil , d )
600- } else {
601- fspLoader = l
602- fspLoader .cfg .Dir = d
603- }
579+ // update the loader configuration's Dir field to the directory part of
580+ // the root
581+ l .cfg .Dir = d
604582
605583 // update the root to be "./..." or "./."
606584 // (with OS-specific filepath separator). please note filepath.Join
@@ -609,14 +587,14 @@ func LoadRootsWithConfig(cfg *packages.Config, roots ...string) (result []*Packa
609587 r = fmt .Sprintf (".%s%s" , string (filepath .Separator ), b )
610588
611589 // load the packages from the roots
612- pkgs , err := loadPackages (fspLoader , r )
590+ pkgs , err := loadPackages (r )
613591 if err != nil {
614592 return nil , err
615593 }
616- result = append (result , pkgs ... )
594+ l . Roots = append (l . Roots , pkgs ... )
617595 }
618596
619- return result , nil
597+ return l . Roots , nil
620598}
621599
622600// visitImports walks a dependency graph, replacing imported package
@@ -634,8 +612,8 @@ func visitImports(rootPkgs []*Package, pkg *Package, seen sets.String) {
634612 }
635613 }
636614 if ! seen .Has (importedPkgID ) {
637- visitImports (rootPkgs , importedPkg , seen )
638615 seen .Insert (importedPkgID )
616+ visitImports (rootPkgs , importedPkg , seen )
639617 }
640618 }
641619}
0 commit comments