@@ -138,6 +138,29 @@ impl UseSegment {
138
138
}
139
139
}
140
140
141
+ // Check if self == other with their aliases removed.
142
+ fn equal_except_alias ( & self , other : & Self ) -> bool {
143
+ match ( self , other) {
144
+ ( UseSegment :: Ident ( ref s1, _) , UseSegment :: Ident ( ref s2, _) ) => s1 == s2,
145
+ ( UseSegment :: Slf ( _) , UseSegment :: Slf ( _) )
146
+ | ( UseSegment :: Super ( _) , UseSegment :: Super ( _) )
147
+ | ( UseSegment :: Crate ( _) , UseSegment :: Crate ( _) )
148
+ | ( UseSegment :: Glob , UseSegment :: Glob ) => true ,
149
+ ( UseSegment :: List ( ref list1) , UseSegment :: List ( ref list2) ) => list1 == list2,
150
+ _ => false ,
151
+ }
152
+ }
153
+
154
+ fn get_alias ( & self ) -> Option < & str > {
155
+ match self {
156
+ UseSegment :: Ident ( _, a)
157
+ | UseSegment :: Slf ( a)
158
+ | UseSegment :: Super ( a)
159
+ | UseSegment :: Crate ( a) => a. as_deref ( ) ,
160
+ _ => None ,
161
+ }
162
+ }
163
+
141
164
fn from_path_segment (
142
165
context : & RewriteContext < ' _ > ,
143
166
path_seg : & ast:: PathSegment ,
@@ -558,6 +581,7 @@ impl UseTree {
558
581
SharedPrefix :: Module => {
559
582
self . path [ ..self . path . len ( ) - 1 ] == other. path [ ..other. path . len ( ) - 1 ]
560
583
}
584
+ SharedPrefix :: One => true ,
561
585
}
562
586
}
563
587
}
@@ -598,7 +622,7 @@ impl UseTree {
598
622
fn merge ( & mut self , other : & UseTree , merge_by : SharedPrefix ) {
599
623
let mut prefix = 0 ;
600
624
for ( a, b) in self . path . iter ( ) . zip ( other. path . iter ( ) ) {
601
- if * a == * b {
625
+ if a . equal_except_alias ( b ) {
602
626
prefix += 1 ;
603
627
} else {
604
628
break ;
@@ -633,14 +657,20 @@ fn merge_rest(
633
657
return Some ( new_path) ;
634
658
}
635
659
} else if len == 1 {
636
- let rest = if a. len ( ) == len { & b[ 1 ..] } else { & a[ 1 ..] } ;
637
- return Some ( vec ! [
638
- b[ 0 ] . clone( ) ,
639
- UseSegment :: List ( vec![
640
- UseTree :: from_path( vec![ UseSegment :: Slf ( None ) ] , DUMMY_SP ) ,
641
- UseTree :: from_path( rest. to_vec( ) , DUMMY_SP ) ,
642
- ] ) ,
643
- ] ) ;
660
+ let ( common, rest) = if a. len ( ) == len {
661
+ ( & a[ 0 ] , & b[ 1 ..] )
662
+ } else {
663
+ ( & b[ 0 ] , & a[ 1 ..] )
664
+ } ;
665
+ let mut list = vec ! [ UseTree :: from_path(
666
+ vec![ UseSegment :: Slf ( common. get_alias( ) . map( ToString :: to_string) ) ] ,
667
+ DUMMY_SP ,
668
+ ) ] ;
669
+ match rest {
670
+ [ UseSegment :: List ( rest_list) ] => list. extend ( rest_list. clone ( ) ) ,
671
+ _ => list. push ( UseTree :: from_path ( rest. to_vec ( ) , DUMMY_SP ) ) ,
672
+ }
673
+ return Some ( vec ! [ b[ 0 ] . clone( ) , UseSegment :: List ( list) ] ) ;
644
674
} else {
645
675
len -= 1 ;
646
676
}
@@ -655,18 +685,54 @@ fn merge_rest(
655
685
}
656
686
657
687
fn merge_use_trees_inner ( trees : & mut Vec < UseTree > , use_tree : UseTree , merge_by : SharedPrefix ) {
658
- let similar_trees = trees
659
- . iter_mut ( )
660
- . filter ( |tree| tree. share_prefix ( & use_tree, merge_by) ) ;
688
+ struct SimilarTree < ' a > {
689
+ similarity : usize ,
690
+ path_len : usize ,
691
+ tree : & ' a mut UseTree ,
692
+ }
693
+
694
+ let similar_trees = trees. iter_mut ( ) . filter_map ( |tree| {
695
+ if tree. share_prefix ( & use_tree, merge_by) {
696
+ // In the case of `SharedPrefix::One`, `similarity` is used for deciding with which
697
+ // tree `use_tree` should be merge.
698
+ // In other cases `similarity` won't be used, so set it to `0` as a dummy value.
699
+ let similarity = if merge_by == SharedPrefix :: One {
700
+ tree. path
701
+ . iter ( )
702
+ . zip ( & use_tree. path )
703
+ . take_while ( |( a, b) | a. equal_except_alias ( b) )
704
+ . count ( )
705
+ } else {
706
+ 0
707
+ } ;
708
+
709
+ let path_len = tree. path . len ( ) ;
710
+ Some ( SimilarTree {
711
+ similarity,
712
+ tree,
713
+ path_len,
714
+ } )
715
+ } else {
716
+ None
717
+ }
718
+ } ) ;
719
+
661
720
if use_tree. path . len ( ) == 1 && merge_by == SharedPrefix :: Crate {
662
- if let Some ( tree) = similar_trees. min_by_key ( |tree| tree. path . len ( ) ) {
663
- if tree. path . len ( ) == 1 {
721
+ if let Some ( tree) = similar_trees. min_by_key ( |tree| tree. path_len ) {
722
+ if tree. path_len == 1 {
723
+ return ;
724
+ }
725
+ }
726
+ } else if merge_by == SharedPrefix :: One {
727
+ if let Some ( sim_tree) = similar_trees. max_by_key ( |tree| tree. similarity ) {
728
+ if sim_tree. similarity > 0 {
729
+ sim_tree. tree . merge ( & use_tree, merge_by) ;
664
730
return ;
665
731
}
666
732
}
667
- } else if let Some ( tree ) = similar_trees. max_by_key ( |tree| tree. path . len ( ) ) {
668
- if tree . path . len ( ) > 1 {
669
- tree. merge ( & use_tree, merge_by) ;
733
+ } else if let Some ( sim_tree ) = similar_trees. max_by_key ( |tree| tree. path_len ) {
734
+ if sim_tree . path_len > 1 {
735
+ sim_tree . tree . merge ( & use_tree, merge_by) ;
670
736
return ;
671
737
}
672
738
}
@@ -880,6 +946,7 @@ impl Rewrite for UseTree {
880
946
pub ( crate ) enum SharedPrefix {
881
947
Crate ,
882
948
Module ,
949
+ One ,
883
950
}
884
951
885
952
#[ cfg( test) ]
@@ -904,7 +971,7 @@ mod test {
904
971
}
905
972
906
973
fn eat ( & mut self , c : char ) {
907
- assert ! ( self . input. next( ) . unwrap( ) == c) ;
974
+ assert_eq ! ( self . input. next( ) . unwrap( ) , c) ;
908
975
}
909
976
910
977
fn push_segment (
@@ -1094,6 +1161,49 @@ mod test {
1094
1161
) ;
1095
1162
}
1096
1163
1164
+ #[ test]
1165
+ fn test_use_tree_merge_one ( ) {
1166
+ test_merge ! ( One , [ "a" , "b" ] , [ "{a, b}" ] ) ;
1167
+
1168
+ test_merge ! ( One , [ "a::{aa, ab}" , "b" , "a" ] , [ "{a::{self, aa, ab}, b}" ] ) ;
1169
+
1170
+ test_merge ! ( One , [ "a as x" , "b as y" ] , [ "{a as x, b as y}" ] ) ;
1171
+
1172
+ test_merge ! (
1173
+ One ,
1174
+ [ "a::{aa as xa, ab}" , "b" , "a" ] ,
1175
+ [ "{a::{self, aa as xa, ab}, b}" ]
1176
+ ) ;
1177
+
1178
+ test_merge ! (
1179
+ One ,
1180
+ [ "a" , "a::{aa, ab::{aba, abb}}" ] ,
1181
+ [ "a::{self, aa, ab::{aba, abb}}" ]
1182
+ ) ;
1183
+
1184
+ test_merge ! ( One , [ "a" , "b::{ba, *}" ] , [ "{a, b::{ba, *}}" ] ) ;
1185
+
1186
+ test_merge ! ( One , [ "a" , "b" , "a::aa" ] , [ "{a::{self, aa}, b}" ] ) ;
1187
+
1188
+ test_merge ! (
1189
+ One ,
1190
+ [ "a::aa::aaa" , "a::ac::aca" , "a::aa::*" ] ,
1191
+ [ "a::{aa::{aaa, *}, ac::aca}" ]
1192
+ ) ;
1193
+
1194
+ test_merge ! (
1195
+ One ,
1196
+ [ "a" , "b::{ba, bb}" , "a::{aa::*, ab::aba}" ] ,
1197
+ [ "{a::{self, aa::*, ab::aba}, b::{ba, bb}}" ]
1198
+ ) ;
1199
+
1200
+ test_merge ! (
1201
+ One ,
1202
+ [ "b" , "a::ac::{aca, acb}" , "a::{aa::*, ab}" ] ,
1203
+ [ "{a::{aa::*, ab, ac::{aca, acb}}, b}" ]
1204
+ ) ;
1205
+ }
1206
+
1097
1207
#[ test]
1098
1208
fn test_flatten_use_trees ( ) {
1099
1209
assert_eq ! (
0 commit comments