@@ -598,8 +598,6 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
598
598
base .Fatalf ("go list -export cannot be used with -find" )
599
599
}
600
600
601
- suppressDeps := ! listJsonFields .needAny ("Deps" , "DepsErrors" )
602
-
603
601
pkgOpts := load.PackageOpts {
604
602
IgnoreImports : * listFind ,
605
603
ModResolveTests : * listTest ,
@@ -767,15 +765,28 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
767
765
}
768
766
}
769
767
770
- if ! suppressDeps {
768
+ if listJsonFields . needAny ( "Deps" , "DepsErrors" ) {
771
769
all := pkgs
770
+ // Make sure we iterate through packages in a postorder traversal,
771
+ // which load.PackageList guarantees. If *listDeps, then all is
772
+ // already in PackageList order. Otherwise, calling load.PackageList
773
+ // provides the guarantee. In the case of an import cycle, the last package
774
+ // visited in the cycle, importing the first encountered package in the cycle,
775
+ // is visited first. The cycle import error will be bubbled up in the traversal
776
+ // order up to the first package in the cycle, covering all the packages
777
+ // in the cycle.
772
778
if ! * listDeps {
773
- // if *listDeps, then all is already in PackageList order.
774
779
all = load .PackageList (pkgs )
775
780
}
776
- // Recompute deps lists using new strings, from the leaves up.
777
- for _ , p := range all {
778
- collectDeps (p )
781
+ if listJsonFields .needAny ("Deps" ) {
782
+ for _ , p := range all {
783
+ collectDeps (p )
784
+ }
785
+ }
786
+ if listJsonFields .needAny ("DepsErrors" ) {
787
+ for _ , p := range all {
788
+ collectDepsErrors (p )
789
+ }
779
790
}
780
791
}
781
792
@@ -878,29 +889,15 @@ func loadPackageList(roots []*load.Package) []*load.Package {
878
889
return pkgs
879
890
}
880
891
881
- // collectDeps populates p.Deps and p.DepsErrors by iterating over
882
- // p.Internal.Imports.
883
- //
884
- // TODO(jayconrod): collectDeps iterates over transitive imports for every
885
- // package. We should only need to visit direct imports.
892
+ // collectDeps populates p.Deps by iterating over p.Internal.Imports.
893
+ // collectDeps must be called on all of p's Imports before being called on p.
886
894
func collectDeps (p * load.Package ) {
887
- deps := make (map [string ]* load.Package )
888
- var q []* load.Package
889
- q = append (q , p .Internal .Imports ... )
890
- for i := 0 ; i < len (q ); i ++ {
891
- p1 := q [i ]
892
- path := p1 .ImportPath
893
- // The same import path could produce an error or not,
894
- // depending on what tries to import it.
895
- // Prefer to record entries with errors, so we can report them.
896
- p0 := deps [path ]
897
- if p0 == nil || p1 .Error != nil && (p0 .Error == nil || len (p0 .Error .ImportStack ) > len (p1 .Error .ImportStack )) {
898
- deps [path ] = p1
899
- for _ , p2 := range p1 .Internal .Imports {
900
- if deps [p2 .ImportPath ] != p2 {
901
- q = append (q , p2 )
902
- }
903
- }
895
+ deps := make (map [string ]bool )
896
+
897
+ for _ , p := range p .Internal .Imports {
898
+ deps [p .ImportPath ] = true
899
+ for _ , q := range p .Deps {
900
+ deps [q ] = true
904
901
}
905
902
}
906
903
@@ -909,15 +906,34 @@ func collectDeps(p *load.Package) {
909
906
p .Deps = append (p .Deps , dep )
910
907
}
911
908
sort .Strings (p .Deps )
912
- for _ , dep := range p .Deps {
913
- p1 := deps [dep ]
914
- if p1 == nil {
915
- panic ("impossible: missing entry in package cache for " + dep + " imported by " + p .ImportPath )
909
+ }
910
+
911
+ // collectDeps populates p.DepsErrors by iterating over p.Internal.Imports.
912
+ // collectDepsErrors must be called on all of p's Imports before being called on p.
913
+ func collectDepsErrors (p * load.Package ) {
914
+ depsErrors := make (map [* load.PackageError ]bool )
915
+
916
+ for _ , p := range p .Internal .Imports {
917
+ if p .Error != nil {
918
+ depsErrors [p .Error ] = true
916
919
}
917
- if p1 . Error != nil {
918
- p . DepsErrors = append ( p . DepsErrors , p1 . Error )
920
+ for _ , q := range p . DepsErrors {
921
+ depsErrors [ q ] = true
919
922
}
920
923
}
924
+
925
+ p .DepsErrors = make ([]* load.PackageError , 0 , len (depsErrors ))
926
+ for deperr := range depsErrors {
927
+ p .DepsErrors = append (p .DepsErrors , deperr )
928
+ }
929
+ // Sort packages by the package on the top of the stack, which should be
930
+ // the package the error was produced for. Each package can have at most
931
+ // one error set on it.
932
+ sort .Slice (p .DepsErrors , func (i , j int ) bool {
933
+ stki , stkj := p .DepsErrors [i ].ImportStack , p .DepsErrors [j ].ImportStack
934
+ pathi , pathj := stki [len (stki )- 1 ], stkj [len (stkj )- 1 ]
935
+ return pathi < pathj
936
+ })
921
937
}
922
938
923
939
// TrackingWriter tracks the last byte written on every write so
0 commit comments