@@ -59,58 +59,74 @@ interface NativeDependency {
59
59
// native dependenciess need to be sorted so the deepst dependencies are built before it's parents
60
60
//
61
61
// 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
+ //
62
64
// |- dep1
63
65
// |- dep2
64
- // |- dep3
65
- // |- dep4
66
- // |-dep5
67
- // |- dep6
66
+ // |- |- dep3
67
+ // |- |- dep4
68
+ // |- |- |- dep5
69
+ // |- dep3
70
+ // |- dep4
71
+ // |- |- dep5
72
+ // |- dep5
68
73
//
69
74
// 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
76
85
//
77
86
// for more details see: https://wikiless.org/wiki/Topological_sorting?lang=en
78
87
//
79
88
function topologicalSortNativeDependencies (
80
- nativeDeps : NativeDependency [ ] ,
89
+ dependencies : NativeDependency [ ] ,
81
90
start : NativeDependency [ ] = [ ] ,
82
- depth = 0
91
+ depth = 0 ,
92
+ total = 0 // do not pass in, we calculate it in the initial run!
83
93
) : 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 ) ;
93
108
}
94
- return accumulator ;
109
+ return sortedDeps ;
95
110
} ,
96
111
start
97
112
) ;
98
113
99
- const remainingDeps = nativeDeps . filter (
100
- ( nativeDep ) => ! processedDeps . includes ( nativeDep )
114
+ const remainingDeps = dependencies . filter (
115
+ ( nativeDep ) => ! sortedDeps . includes ( nativeDep )
101
116
) ;
102
117
103
- // recurse if we still have unprocessed deps
118
+ // recurse if we still have remaining deps
104
119
// the second condition here prevents infinite recursion
105
- if ( remainingDeps . length && depth <= nativeDeps . length ) {
120
+ if ( remainingDeps . length && sortedDeps . length < total ) {
106
121
return topologicalSortNativeDependencies (
107
122
remainingDeps ,
108
- processedDeps ,
109
- depth + 1
123
+ sortedDeps ,
124
+ depth + 1 ,
125
+ total
110
126
) ;
111
127
}
112
128
113
- return processedDeps ;
129
+ return sortedDeps ;
114
130
}
115
131
116
132
export class AndroidProjectService extends projectServiceBaseLib . PlatformProjectServiceBase {
0 commit comments