@@ -12,61 +12,59 @@ impl<'a> FileDependencyRelation<'a> {
1212 }
1313
1414 pub fn get_best_analysis_order ( & self , file_ids : Vec < FileId > ) -> Vec < FileId > {
15- if self . dependencies . is_empty ( ) {
15+ let n = file_ids. len ( ) ;
16+ if n == 0 || self . dependencies . is_empty ( ) {
1617 return file_ids;
1718 }
1819
19- let file_set: HashSet < _ > = file_ids. iter ( ) . copied ( ) . collect ( ) ;
20+ let file_to_idx: HashMap < FileId , usize > = file_ids
21+ . iter ( )
22+ . enumerate ( )
23+ . map ( |( i, & f) | ( f, i) )
24+ . collect ( ) ;
2025
21- let mut in_degree: HashMap < FileId , usize > = HashMap :: new ( ) ;
22- let mut adjacency: HashMap < FileId , Vec < FileId > > = HashMap :: new ( ) ;
26+ let mut in_degree = vec ! [ 0usize ; n ] ;
27+ let mut adjacency: Vec < Vec < usize > > = vec ! [ Vec :: new( ) ; n ] ;
2328
24- for file_id in & file_ids {
25- if let Some ( deps) = self . dependencies . get ( file_id) {
26- adjacency. entry ( * file_id) . or_default ( ) ;
29+ for ( idx, & file_id) in file_ids. iter ( ) . enumerate ( ) {
30+ if let Some ( deps) = self . dependencies . get ( & file_id) {
2731 for & dep in deps {
28- if file_set . contains ( & dep) {
29- adjacency. entry ( dep ) . or_default ( ) . push ( * file_id ) ;
30- * in_degree. entry ( * file_id ) . or_default ( ) += 1 ;
32+ if let Some ( & dep_idx ) = file_to_idx . get ( & dep) {
33+ adjacency[ dep_idx ] . push ( idx ) ;
34+ in_degree[ idx ] += 1 ;
3135 }
3236 }
33- } else {
34- adjacency. entry ( * file_id) . or_default ( ) ;
35- in_degree. entry ( * file_id) . or_default ( ) ;
3637 }
3738 }
39+ let mut result = Vec :: with_capacity ( n) ;
40+ let mut queue = VecDeque :: with_capacity ( n) ;
3841
39- let mut queue = VecDeque :: new ( ) ;
40- let mut sorted_keys: Vec < _ > = adjacency. keys ( ) . copied ( ) . collect ( ) ;
41- sorted_keys. sort ( ) ;
42- for & file in & sorted_keys {
43- if * in_degree. get ( & file) . unwrap_or ( & 0 ) == 0 {
44- queue. push_back ( file) ;
45- }
42+ let mut zero_in_degree: Vec < usize > = ( 0 ..n) . filter ( |& i| in_degree[ i] == 0 ) . collect ( ) ;
43+ zero_in_degree. sort_by_key ( |& i| file_ids[ i] ) ;
44+
45+ for idx in zero_in_degree {
46+ queue. push_back ( idx) ;
4647 }
4748
48- let mut order = Vec :: new ( ) ;
49- while let Some ( node) = queue. pop_front ( ) {
50- order. push ( node) ;
51- if let Some ( neighbors) = adjacency. get ( & node) {
52- for & n in neighbors {
53- if let Some ( x) = in_degree. get_mut ( & n) {
54- * x = x. saturating_sub ( 1 ) ;
55- if * x == 0 {
56- queue. push_back ( n) ;
57- }
58- }
49+ while let Some ( idx) = queue. pop_front ( ) {
50+ result. push ( file_ids[ idx] ) ;
51+ for & neighbor in & adjacency[ idx] {
52+ in_degree[ neighbor] -= 1 ;
53+ if in_degree[ neighbor] == 0 {
54+ queue. push_back ( neighbor) ;
5955 }
6056 }
6157 }
6258
63- let processed: HashSet < _ > = order. iter ( ) . copied ( ) . collect ( ) ;
64- for file in file_ids {
65- if !processed. contains ( & file) {
66- order. push ( file) ;
59+ if result. len ( ) < n {
60+ for ( idx, & deg) in in_degree. iter ( ) . enumerate ( ) {
61+ if deg > 0 {
62+ result. push ( file_ids[ idx] ) ;
63+ }
6764 }
6865 }
69- order
66+
67+ result
7068 }
7169
7270 /// Get all direct and indirect dependencies for the file list
@@ -102,36 +100,80 @@ mod tests {
102100 #[ test]
103101 fn test_best_analysis_order ( ) {
104102 let mut map = HashMap :: new ( ) ;
103+ // 文件1依赖文件2
105104 map. insert ( FileId :: new ( 1 ) , {
106105 let mut s = HashSet :: new ( ) ;
107106 s. insert ( FileId :: new ( 2 ) ) ;
108107 s
109108 } ) ;
109+ // 文件2没有依赖
110110 map. insert ( FileId :: new ( 2 ) , HashSet :: new ( ) ) ;
111111 let rel = FileDependencyRelation :: new ( & map) ;
112112 let result = rel. get_best_analysis_order ( vec ! [ FileId :: new( 1 ) , FileId :: new( 2 ) ] ) ;
113+ // 文件2没有依赖,应该在前;文件1依赖文件2,在后
113114 assert_eq ! ( result, vec![ FileId :: new( 2 ) , FileId :: new( 1 ) ] ) ;
114115 }
115116
116117 #[ test]
117118 fn test_best_analysis_order2 ( ) {
118119 let mut map = HashMap :: new ( ) ;
120+ // 文件1依赖文件2和文件3
119121 map. insert ( 1 . into ( ) , {
120122 let mut s = HashSet :: new ( ) ;
121123 s. insert ( 2 . into ( ) ) ;
122124 s. insert ( 3 . into ( ) ) ;
123125 s
124126 } ) ;
127+ // 文件2依赖文件3
125128 map. insert ( 2 . into ( ) , {
126129 let mut s = HashSet :: new ( ) ;
127130 s. insert ( 3 . into ( ) ) ;
128131 s
129132 } ) ;
133+ // 文件3没有依赖
134+ map. insert ( 3 . into ( ) , HashSet :: new ( ) ) ;
130135 let rel = FileDependencyRelation :: new ( & map) ;
131136 let result = rel. get_best_analysis_order ( vec ! [ 1 . into( ) , 2 . into( ) , 3 . into( ) ] ) ;
137+ // 文件3没有依赖,应该在最前面;然后是2,最后是1
132138 assert_eq ! ( result, vec![ 3 . into( ) , 2 . into( ) , 1 . into( ) ] ) ;
133139 }
134140
141+ #[ test]
142+ fn test_no_deps_files_first ( ) {
143+ let mut map = HashMap :: new ( ) ;
144+ // 文件1依赖文件2
145+ map. insert ( FileId :: new ( 1 ) , {
146+ let mut s = HashSet :: new ( ) ;
147+ s. insert ( FileId :: new ( 2 ) ) ;
148+ s
149+ } ) ;
150+ // 文件2依赖文件1(循环依赖)
151+ map. insert ( FileId :: new ( 2 ) , {
152+ let mut s = HashSet :: new ( ) ;
153+ s. insert ( FileId :: new ( 1 ) ) ;
154+ s
155+ } ) ;
156+ // 文件3没有依赖
157+ map. insert ( FileId :: new ( 3 ) , HashSet :: new ( ) ) ;
158+ // 文件4没有依赖
159+ map. insert ( FileId :: new ( 4 ) , HashSet :: new ( ) ) ;
160+
161+ let rel = FileDependencyRelation :: new ( & map) ;
162+ let result = rel. get_best_analysis_order ( vec ! [
163+ FileId :: new( 1 ) ,
164+ FileId :: new( 2 ) ,
165+ FileId :: new( 3 ) ,
166+ FileId :: new( 4 ) ,
167+ ] ) ;
168+
169+ // 文件3和4没有依赖,应该在前面
170+ assert_eq ! ( result[ 0 ] , FileId :: new( 3 ) ) ;
171+ assert_eq ! ( result[ 1 ] , FileId :: new( 4 ) ) ;
172+ // 文件1和2有循环依赖,在后面
173+ assert ! ( result. contains( & FileId :: new( 1 ) ) ) ;
174+ assert ! ( result. contains( & FileId :: new( 2 ) ) ) ;
175+ }
176+
135177 #[ test]
136178 fn test_collect_file_dependents ( ) {
137179 let mut deps = HashMap :: new ( ) ;
0 commit comments