@@ -59,58 +59,74 @@ interface NativeDependency {
5959// native dependenciess need to be sorted so the deepst dependencies are built before it's parents
6060//
6161// for example, given this dep structure (assuming these are all native dependencies that need to be built)
62+ // (note: we list all dependencies at the root level, so the leaf nodes are essentially references to the root nodes)
63+ //
6264// |- dep1
6365// |- dep2
64- // |- dep3
65- // |- dep4
66- // |-dep5
67- // |- dep6
66+ // |- |- dep3
67+ // |- |- dep4
68+ // |- |- |- dep5
69+ // |- dep3
70+ // |- dep4
71+ // |- |- dep5
72+ // |- dep5
6873//
6974// It is sorted:
70- // |- dep1 - doesn't depend on anything, so the order stays the same as in the input list
71- // |- dep3 - doesn't depend on anything, so the order stays the same as in the input list
72- // |- dep5 - doesn't depend on anything, so the order stays the same as in the input list
73- // |- dep6 - doesn't depend on anything, so the order stays the same as in the input list
74- // |- dep4 - depends on dep6, so dep6 must be built first, ie above ^
75- // |- dep2 - depends on dep3, dep4, dep5 and dep6, so all of them must be built first
75+ //
76+ // |- dep1
77+ // |- dep3
78+ // |- dep5
79+ // |- dep4 # depends on dep5, so dep5 must be built first, ie above ^
80+ // |- |- dep5
81+ // |- dep2 # depends on dep3, dep4 (and dep5 through dep4) so all of them must be built first before dep2 is built
82+ // |- |- dep3
83+ // |- |- dep4
84+ // |- |- |- dep5
7685//
7786// for more details see: https://wikiless.org/wiki/Topological_sorting?lang=en
7887//
7988function topologicalSortNativeDependencies (
80- nativeDeps : NativeDependency [ ] ,
89+ dependencies : NativeDependency [ ] ,
8190 start : NativeDependency [ ] = [ ] ,
82- depth = 0
91+ depth = 0 ,
92+ total = 0 // do not pass in, we calculate it in the initial run!
8393) : NativeDependency [ ] {
84- const processedDeps = nativeDeps . reduce (
85- ( accumulator , nativeDep : NativeDependency ) => {
86- if (
87- nativeDep . dependencies . every (
88- Array . prototype . includes ,
89- accumulator . map ( ( n ) => n . name )
90- )
91- ) {
92- accumulator . push ( nativeDep ) ;
94+ // we set the total on the initial call - and never increment it, as it's used for esacaping the recursion
95+ if ( total === 0 ) {
96+ total = dependencies . length ;
97+ }
98+
99+ const sortedDeps = dependencies . reduce (
100+ ( sortedDeps , currentDependency : NativeDependency ) => {
101+ const allSubDependenciesProcessed = currentDependency . dependencies . every (
102+ ( subDependency ) => {
103+ return sortedDeps . some ( ( dep ) => dep . name === subDependency ) ;
104+ }
105+ ) ;
106+ if ( allSubDependenciesProcessed ) {
107+ sortedDeps . push ( currentDependency ) ;
93108 }
94- return accumulator ;
109+ return sortedDeps ;
95110 } ,
96111 start
97112 ) ;
98113
99- const remainingDeps = nativeDeps . filter (
100- ( nativeDep ) => ! processedDeps . includes ( nativeDep )
114+ const remainingDeps = dependencies . filter (
115+ ( nativeDep ) => ! sortedDeps . includes ( nativeDep )
101116 ) ;
102117
103- // recurse if we still have unprocessed deps
118+ // recurse if we still have remaining deps
104119 // the second condition here prevents infinite recursion
105- if ( remainingDeps . length && depth <= nativeDeps . length ) {
120+ if ( remainingDeps . length && sortedDeps . length < total ) {
106121 return topologicalSortNativeDependencies (
107122 remainingDeps ,
108- processedDeps ,
109- depth + 1
123+ sortedDeps ,
124+ depth + 1 ,
125+ total
110126 ) ;
111127 }
112128
113- return processedDeps ;
129+ return sortedDeps ;
114130}
115131
116132export class AndroidProjectService extends projectServiceBaseLib . PlatformProjectServiceBase {
0 commit comments