@@ -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,55 @@ 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 {
682
741
return ;
683
742
}
684
743
}
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) ;
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) ;
748
+ return ;
749
+ }
750
+ }
751
+ } else if let Some ( sim_tree) = similar_trees. max_by_key ( |tree| ( tree. path_len , tree. similarity ) )
752
+ {
753
+ if sim_tree. path_len > 1 {
754
+ sim_tree. tree . merge ( & use_tree, merge_by) ;
688
755
return ;
689
756
}
690
757
}
@@ -897,6 +964,7 @@ impl Rewrite for UseTree {
897
964
pub ( crate ) enum SharedPrefix {
898
965
Crate ,
899
966
Module ,
967
+ One ,
900
968
}
901
969
902
970
#[ cfg( test) ]
@@ -921,7 +989,7 @@ mod test {
921
989
}
922
990
923
991
fn eat ( & mut self , c : char ) {
924
- assert ! ( self . input. next( ) . unwrap( ) == c) ;
992
+ assert_eq ! ( self . input. next( ) . unwrap( ) , c) ;
925
993
}
926
994
927
995
fn push_segment (
@@ -1111,6 +1179,49 @@ mod test {
1111
1179
) ;
1112
1180
}
1113
1181
1182
+ #[ test]
1183
+ fn test_use_tree_merge_one ( ) {
1184
+ test_merge ! ( One , [ "a" , "b" ] , [ "{a, b}" ] ) ;
1185
+
1186
+ test_merge ! ( One , [ "a::{aa, ab}" , "b" , "a" ] , [ "{a::{self, aa, ab}, b}" ] ) ;
1187
+
1188
+ test_merge ! ( One , [ "a as x" , "b as y" ] , [ "{a as x, b as y}" ] ) ;
1189
+
1190
+ test_merge ! (
1191
+ One ,
1192
+ [ "a::{aa as xa, ab}" , "b" , "a" ] ,
1193
+ [ "{a::{self, aa as xa, ab}, b}" ]
1194
+ ) ;
1195
+
1196
+ test_merge ! (
1197
+ One ,
1198
+ [ "a" , "a::{aa, ab::{aba, abb}}" ] ,
1199
+ [ "a::{self, aa, ab::{aba, abb}}" ]
1200
+ ) ;
1201
+
1202
+ test_merge ! ( One , [ "a" , "b::{ba, *}" ] , [ "{a, b::{ba, *}}" ] ) ;
1203
+
1204
+ test_merge ! ( One , [ "a" , "b" , "a::aa" ] , [ "{a::{self, aa}, b}" ] ) ;
1205
+
1206
+ test_merge ! (
1207
+ One ,
1208
+ [ "a::aa::aaa" , "a::ac::aca" , "a::aa::*" ] ,
1209
+ [ "a::{aa::{aaa, *}, ac::aca}" ]
1210
+ ) ;
1211
+
1212
+ test_merge ! (
1213
+ One ,
1214
+ [ "a" , "b::{ba, bb}" , "a::{aa::*, ab::aba}" ] ,
1215
+ [ "{a::{self, aa::*, ab::aba}, b::{ba, bb}}" ]
1216
+ ) ;
1217
+
1218
+ test_merge ! (
1219
+ One ,
1220
+ [ "b" , "a::ac::{aca, acb}" , "a::{aa::*, ab}" ] ,
1221
+ [ "{a::{aa::*, ab, ac::{aca, acb}}, b}" ]
1222
+ ) ;
1223
+ }
1224
+
1114
1225
#[ test]
1115
1226
fn test_flatten_use_trees ( ) {
1116
1227
assert_eq ! (
0 commit comments