@@ -143,6 +143,29 @@ impl UseSegment {
143
143
}
144
144
}
145
145
146
+ // Check if self == other with their aliases removed.
147
+ fn equal_except_alias ( & self , other : & Self ) -> bool {
148
+ match ( self , other) {
149
+ ( UseSegment :: Ident ( ref s1, _) , UseSegment :: Ident ( ref s2, _) ) => s1 == s2,
150
+ ( UseSegment :: Slf ( _) , UseSegment :: Slf ( _) )
151
+ | ( UseSegment :: Super ( _) , UseSegment :: Super ( _) )
152
+ | ( UseSegment :: Crate ( _) , UseSegment :: Crate ( _) )
153
+ | ( UseSegment :: Glob , UseSegment :: Glob ) => true ,
154
+ ( UseSegment :: List ( ref list1) , UseSegment :: List ( ref list2) ) => list1 == list2,
155
+ _ => false ,
156
+ }
157
+ }
158
+
159
+ fn get_alias ( & self ) -> Option < & str > {
160
+ match self {
161
+ UseSegment :: Ident ( _, a)
162
+ | UseSegment :: Slf ( a)
163
+ | UseSegment :: Super ( a)
164
+ | UseSegment :: Crate ( a) => a. as_deref ( ) ,
165
+ _ => None ,
166
+ }
167
+ }
168
+
146
169
fn from_path_segment (
147
170
context : & RewriteContext < ' _ > ,
148
171
path_seg : & ast:: PathSegment ,
@@ -579,6 +602,7 @@ impl UseTree {
579
602
SharedPrefix :: Module => {
580
603
self . path [ ..self . path . len ( ) - 1 ] == other. path [ ..other. path . len ( ) - 1 ]
581
604
}
605
+ SharedPrefix :: One => true ,
582
606
}
583
607
}
584
608
}
@@ -616,7 +640,7 @@ impl UseTree {
616
640
fn merge ( & mut self , other : & UseTree , merge_by : SharedPrefix ) {
617
641
let mut prefix = 0 ;
618
642
for ( a, b) in self . path . iter ( ) . zip ( other. path . iter ( ) ) {
619
- if * a == * b {
643
+ if a . equal_except_alias ( b ) {
620
644
prefix += 1 ;
621
645
} else {
622
646
break ;
@@ -651,14 +675,20 @@ fn merge_rest(
651
675
return Some ( new_path) ;
652
676
}
653
677
} else if len == 1 {
654
- let rest = if a. len ( ) == len { & b[ 1 ..] } else { & a[ 1 ..] } ;
655
- return Some ( vec ! [
656
- b[ 0 ] . clone( ) ,
657
- UseSegment :: List ( vec![
658
- UseTree :: from_path( vec![ UseSegment :: Slf ( None ) ] , DUMMY_SP ) ,
659
- UseTree :: from_path( rest. to_vec( ) , DUMMY_SP ) ,
660
- ] ) ,
661
- ] ) ;
678
+ let ( common, rest) = if a. len ( ) == len {
679
+ ( & a[ 0 ] , & b[ 1 ..] )
680
+ } else {
681
+ ( & b[ 0 ] , & a[ 1 ..] )
682
+ } ;
683
+ let mut list = vec ! [ UseTree :: from_path(
684
+ vec![ UseSegment :: Slf ( common. get_alias( ) . map( ToString :: to_string) ) ] ,
685
+ DUMMY_SP ,
686
+ ) ] ;
687
+ match rest {
688
+ [ UseSegment :: List ( rest_list) ] => list. extend ( rest_list. clone ( ) ) ,
689
+ _ => list. push ( UseTree :: from_path ( rest. to_vec ( ) , DUMMY_SP ) ) ,
690
+ }
691
+ return Some ( vec ! [ b[ 0 ] . clone( ) , UseSegment :: List ( list) ] ) ;
662
692
} else {
663
693
len -= 1 ;
664
694
}
@@ -673,18 +703,54 @@ fn merge_rest(
673
703
}
674
704
675
705
fn merge_use_trees_inner ( trees : & mut Vec < UseTree > , use_tree : UseTree , merge_by : SharedPrefix ) {
676
- let similar_trees = trees
677
- . iter_mut ( )
678
- . filter ( |tree| tree. share_prefix ( & use_tree, merge_by) ) ;
706
+ struct SimilarTree < ' a > {
707
+ similarity : usize ,
708
+ path_len : usize ,
709
+ tree : & ' a mut UseTree ,
710
+ }
711
+
712
+ let similar_trees = trees. iter_mut ( ) . filter_map ( |tree| {
713
+ if tree. share_prefix ( & use_tree, merge_by) {
714
+ // In the case of `SharedPrefix::One`, `similarity` is used for deciding with which
715
+ // tree `use_tree` should be merge.
716
+ // In other cases `similarity` won't be used, so set it to `0` as a dummy value.
717
+ let similarity = if merge_by == SharedPrefix :: One {
718
+ tree. path
719
+ . iter ( )
720
+ . zip ( & use_tree. path )
721
+ . take_while ( |( a, b) | a. equal_except_alias ( b) )
722
+ . count ( )
723
+ } else {
724
+ 0
725
+ } ;
726
+
727
+ let path_len = tree. path . len ( ) ;
728
+ Some ( SimilarTree {
729
+ similarity,
730
+ tree,
731
+ path_len,
732
+ } )
733
+ } else {
734
+ None
735
+ }
736
+ } ) ;
737
+
679
738
if use_tree. path . len ( ) == 1 && merge_by == SharedPrefix :: Crate {
680
- if let Some ( tree) = similar_trees. min_by_key ( |tree| tree. path . len ( ) ) {
681
- if tree. path . len ( ) == 1 {
739
+ if let Some ( tree) = similar_trees. min_by_key ( |tree| tree. path_len ) {
740
+ if tree. path_len == 1 {
741
+ return ;
742
+ }
743
+ }
744
+ } else if merge_by == SharedPrefix :: One {
745
+ if let Some ( sim_tree) = similar_trees. max_by_key ( |tree| tree. similarity ) {
746
+ if sim_tree. similarity > 0 {
747
+ sim_tree. tree . merge ( & use_tree, merge_by) ;
682
748
return ;
683
749
}
684
750
}
685
- } else if let Some ( tree ) = similar_trees. max_by_key ( |tree| tree. path . len ( ) ) {
686
- if tree . path . len ( ) > 1 {
687
- tree. merge ( & use_tree, merge_by) ;
751
+ } else if let Some ( sim_tree ) = similar_trees. max_by_key ( |tree| tree. path_len ) {
752
+ if sim_tree . path_len > 1 {
753
+ sim_tree . tree . merge ( & use_tree, merge_by) ;
688
754
return ;
689
755
}
690
756
}
@@ -897,6 +963,7 @@ impl Rewrite for UseTree {
897
963
pub ( crate ) enum SharedPrefix {
898
964
Crate ,
899
965
Module ,
966
+ One ,
900
967
}
901
968
902
969
#[ cfg( test) ]
@@ -921,7 +988,7 @@ mod test {
921
988
}
922
989
923
990
fn eat ( & mut self , c : char ) {
924
- assert ! ( self . input. next( ) . unwrap( ) == c) ;
991
+ assert_eq ! ( self . input. next( ) . unwrap( ) , c) ;
925
992
}
926
993
927
994
fn push_segment (
@@ -1111,6 +1178,49 @@ mod test {
1111
1178
) ;
1112
1179
}
1113
1180
1181
+ #[ test]
1182
+ fn test_use_tree_merge_one ( ) {
1183
+ test_merge ! ( One , [ "a" , "b" ] , [ "{a, b}" ] ) ;
1184
+
1185
+ test_merge ! ( One , [ "a::{aa, ab}" , "b" , "a" ] , [ "{a::{self, aa, ab}, b}" ] ) ;
1186
+
1187
+ test_merge ! ( One , [ "a as x" , "b as y" ] , [ "{a as x, b as y}" ] ) ;
1188
+
1189
+ test_merge ! (
1190
+ One ,
1191
+ [ "a::{aa as xa, ab}" , "b" , "a" ] ,
1192
+ [ "{a::{self, aa as xa, ab}, b}" ]
1193
+ ) ;
1194
+
1195
+ test_merge ! (
1196
+ One ,
1197
+ [ "a" , "a::{aa, ab::{aba, abb}}" ] ,
1198
+ [ "a::{self, aa, ab::{aba, abb}}" ]
1199
+ ) ;
1200
+
1201
+ test_merge ! ( One , [ "a" , "b::{ba, *}" ] , [ "{a, b::{ba, *}}" ] ) ;
1202
+
1203
+ test_merge ! ( One , [ "a" , "b" , "a::aa" ] , [ "{a::{self, aa}, b}" ] ) ;
1204
+
1205
+ test_merge ! (
1206
+ One ,
1207
+ [ "a::aa::aaa" , "a::ac::aca" , "a::aa::*" ] ,
1208
+ [ "a::{aa::{aaa, *}, ac::aca}" ]
1209
+ ) ;
1210
+
1211
+ test_merge ! (
1212
+ One ,
1213
+ [ "a" , "b::{ba, bb}" , "a::{aa::*, ab::aba}" ] ,
1214
+ [ "{a::{self, aa::*, ab::aba}, b::{ba, bb}}" ]
1215
+ ) ;
1216
+
1217
+ test_merge ! (
1218
+ One ,
1219
+ [ "b" , "a::ac::{aca, acb}" , "a::{aa::*, ab}" ] ,
1220
+ [ "{a::{aa::*, ab, ac::{aca, acb}}, b}" ]
1221
+ ) ;
1222
+ }
1223
+
1114
1224
#[ test]
1115
1225
fn test_flatten_use_trees ( ) {
1116
1226
assert_eq ! (
0 commit comments