@@ -13,6 +13,7 @@ use std::cmp::Ordering;
13
13
use syntax:: ast;
14
14
use syntax:: codemap:: { BytePos , Span } ;
15
15
16
+
16
17
use spanned:: Spanned ;
17
18
use codemap:: SpanUtils ;
18
19
use comment:: combine_strs_with_missing_comments;
@@ -25,14 +26,6 @@ use types::{rewrite_path, PathContext};
25
26
use utils:: { format_visibility, mk_sp} ;
26
27
use visitor:: { rewrite_extern_crate, FmtVisitor } ;
27
28
28
- fn path_of ( a : & ast:: ViewPath_ ) -> & ast:: Path {
29
- match * a {
30
- ast:: ViewPath_ :: ViewPathSimple ( _, ref p)
31
- | ast:: ViewPath_ :: ViewPathGlob ( ref p)
32
- | ast:: ViewPath_ :: ViewPathList ( ref p, _) => p,
33
- }
34
- }
35
-
36
29
fn compare_path_segments ( a : & ast:: PathSegment , b : & ast:: PathSegment ) -> Ordering {
37
30
a. identifier . name . as_str ( ) . cmp ( & b. identifier . name . as_str ( ) )
38
31
}
@@ -47,75 +40,76 @@ fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering {
47
40
a. segments . len ( ) . cmp ( & b. segments . len ( ) )
48
41
}
49
42
50
- fn compare_path_list_items ( a : & ast:: PathListItem , b : & ast:: PathListItem ) -> Ordering {
51
- let a_name_str = & * a. node . name . name . as_str ( ) ;
52
- let b_name_str = & * b. node . name . name . as_str ( ) ;
53
- let name_ordering = if a_name_str == "self" {
54
- if b_name_str == "self" {
55
- Ordering :: Equal
56
- } else {
57
- Ordering :: Less
58
- }
59
- } else if b_name_str == "self" {
60
- Ordering :: Greater
61
- } else {
62
- a_name_str. cmp ( b_name_str)
63
- } ;
64
- if name_ordering == Ordering :: Equal {
65
- match a. node . rename {
66
- Some ( a_rename) => match b. node . rename {
67
- Some ( b_rename) => a_rename. name . as_str ( ) . cmp ( & b_rename. name . as_str ( ) ) ,
68
- None => Ordering :: Greater ,
69
- } ,
70
- None => Ordering :: Less ,
71
- }
72
- } else {
73
- name_ordering
74
- }
75
- }
43
+ fn compare_use_trees ( a : & ast:: UseTree , b : & ast:: UseTree , nested : bool ) -> Ordering {
44
+ use ast:: UseTreeKind :: * ;
76
45
77
- fn compare_path_list_item_lists (
78
- a_items : & [ ast:: PathListItem ] ,
79
- b_items : & [ ast:: PathListItem ] ,
80
- ) -> Ordering {
81
- let mut a = a_items. to_owned ( ) ;
82
- let mut b = b_items. to_owned ( ) ;
83
- a. sort_by ( |a, b| compare_path_list_items ( a, b) ) ;
84
- b. sort_by ( |a, b| compare_path_list_items ( a, b) ) ;
85
- for comparison_pair in a. iter ( ) . zip ( b. iter ( ) ) {
86
- let ord = compare_path_list_items ( comparison_pair. 0 , comparison_pair. 1 ) ;
87
- if ord != Ordering :: Equal {
88
- return ord;
46
+ // `use_nested_groups` is not yet supported, remove the `if !nested` when support will be
47
+ // fully added
48
+ if !nested {
49
+ let paths_cmp = compare_paths ( & a. prefix , & b. prefix ) ;
50
+ if paths_cmp != Ordering :: Equal {
51
+ return paths_cmp;
89
52
}
90
53
}
91
- a. len ( ) . cmp ( & b. len ( ) )
92
- }
93
54
94
- fn compare_view_path_types ( a : & ast:: ViewPath_ , b : & ast:: ViewPath_ ) -> Ordering {
95
- use syntax:: ast:: ViewPath_ :: * ;
96
- match ( a, b) {
97
- ( & ViewPathSimple ( ..) , & ViewPathSimple ( ..) ) | ( & ViewPathGlob ( _) , & ViewPathGlob ( _) ) => {
98
- Ordering :: Equal
55
+ match ( & a. kind , & b. kind ) {
56
+ ( & Simple ( ident_a) , & Simple ( ident_b) ) => {
57
+ let name_a = & * a. prefix . segments . last ( ) . unwrap ( ) . identifier . name . as_str ( ) ;
58
+ let name_b = & * b. prefix . segments . last ( ) . unwrap ( ) . identifier . name . as_str ( ) ;
59
+ let name_ordering = if name_a == "self" {
60
+ if name_b == "self" {
61
+ Ordering :: Equal
62
+ } else {
63
+ Ordering :: Less
64
+ }
65
+ } else if name_b == "self" {
66
+ Ordering :: Greater
67
+ } else {
68
+ name_a. cmp ( name_b)
69
+ } ;
70
+ if name_ordering == Ordering :: Equal {
71
+ if ident_a. name . as_str ( ) != name_a {
72
+ if ident_b. name . as_str ( ) != name_b {
73
+ ident_a. name . as_str ( ) . cmp ( & ident_b. name . as_str ( ) )
74
+ } else {
75
+ Ordering :: Greater
76
+ }
77
+ } else {
78
+ Ordering :: Less
79
+ }
80
+ } else {
81
+ name_ordering
82
+ }
99
83
}
100
- ( & ViewPathSimple ( ..) , _) | ( & ViewPathGlob ( _) , & ViewPathList ( ..) ) => Ordering :: Less ,
101
- ( & ViewPathList ( _, ref a_items) , & ViewPathList ( _, ref b_items) ) => {
102
- compare_path_list_item_lists ( a_items, b_items)
84
+ ( & Glob , & Glob ) => Ordering :: Equal ,
85
+ ( & Simple ( _) , _) | ( & Glob , & Nested ( _) ) => Ordering :: Less ,
86
+ ( & Nested ( ref a_items) , & Nested ( ref b_items) ) => {
87
+ let mut a = a_items
88
+ . iter ( )
89
+ . map ( |& ( ref tree, _) | tree. clone ( ) )
90
+ . collect :: < Vec < _ > > ( ) ;
91
+ let mut b = b_items
92
+ . iter ( )
93
+ . map ( |& ( ref tree, _) | tree. clone ( ) )
94
+ . collect :: < Vec < _ > > ( ) ;
95
+ a. sort_by ( |a, b| compare_use_trees ( a, b, true ) ) ;
96
+ b. sort_by ( |a, b| compare_use_trees ( a, b, true ) ) ;
97
+ for comparison_pair in a. iter ( ) . zip ( b. iter ( ) ) {
98
+ let ord = compare_use_trees ( comparison_pair. 0 , comparison_pair. 1 , true ) ;
99
+ if ord != Ordering :: Equal {
100
+ return ord;
101
+ }
102
+ }
103
+ a. len ( ) . cmp ( & b. len ( ) )
103
104
}
104
- ( & ViewPathGlob ( _) , & ViewPathSimple ( ..) ) | ( & ViewPathList ( ..) , _) => Ordering :: Greater ,
105
- }
106
- }
107
-
108
- fn compare_view_paths ( a : & ast:: ViewPath_ , b : & ast:: ViewPath_ ) -> Ordering {
109
- match compare_paths ( path_of ( a) , path_of ( b) ) {
110
- Ordering :: Equal => compare_view_path_types ( a, b) ,
111
- cmp => cmp,
105
+ ( & Glob , & Simple ( _) ) | ( & Nested ( _) , _) => Ordering :: Greater ,
112
106
}
113
107
}
114
108
115
109
fn compare_use_items ( context : & RewriteContext , a : & ast:: Item , b : & ast:: Item ) -> Option < Ordering > {
116
110
match ( & a. node , & b. node ) {
117
- ( & ast:: ItemKind :: Use ( ref a_vp ) , & ast:: ItemKind :: Use ( ref b_vp ) ) => {
118
- Some ( compare_view_paths ( & a_vp . node , & b_vp . node ) )
111
+ ( & ast:: ItemKind :: Use ( ref a_tree ) , & ast:: ItemKind :: Use ( ref b_tree ) ) => {
112
+ Some ( compare_use_trees ( & a_tree , & b_tree , false ) )
119
113
}
120
114
( & ast:: ItemKind :: ExternCrate ( ..) , & ast:: ItemKind :: ExternCrate ( ..) ) => {
121
115
Some ( context. snippet ( a. span ) . cmp ( & context. snippet ( b. span ) ) )
@@ -127,11 +121,7 @@ fn compare_use_items(context: &RewriteContext, a: &ast::Item, b: &ast::Item) ->
127
121
// TODO (some day) remove unused imports, expand globs, compress many single
128
122
// imports into a list import.
129
123
130
- fn rewrite_view_path_prefix (
131
- path : & ast:: Path ,
132
- context : & RewriteContext ,
133
- shape : Shape ,
134
- ) -> Option < String > {
124
+ fn rewrite_prefix ( path : & ast:: Path , context : & RewriteContext , shape : Shape ) -> Option < String > {
135
125
let path_str = if path. segments . last ( ) . unwrap ( ) . identifier . to_string ( ) == "self"
136
126
&& path. segments . len ( ) > 1
137
127
{
@@ -146,29 +136,34 @@ fn rewrite_view_path_prefix(
146
136
Some ( path_str)
147
137
}
148
138
149
- impl Rewrite for ast:: ViewPath {
139
+ impl Rewrite for ast:: UseTree {
150
140
fn rewrite ( & self , context : & RewriteContext , shape : Shape ) -> Option < String > {
151
- match self . node {
152
- ast:: ViewPath_ :: ViewPathList ( ref path , ref path_list ) => {
153
- rewrite_use_list ( shape, path , path_list , self . span , context)
141
+ match self . kind {
142
+ ast:: UseTreeKind :: Nested ( ref items ) => {
143
+ rewrite_nested_use_tree ( shape, & self . prefix , items , self . span , context)
154
144
}
155
- ast:: ViewPath_ :: ViewPathGlob ( ref path) => {
156
- // 4 = "::*".len()
145
+ ast:: UseTreeKind :: Glob => {
157
146
let prefix_shape = shape. sub_width ( 3 ) ?;
158
- let path_str = rewrite_view_path_prefix ( path, context, prefix_shape) ?;
159
- Some ( format ! ( "{}::*" , path_str) )
147
+
148
+ if self . prefix . segments . len ( ) > 0 {
149
+ let path_str = rewrite_prefix ( & self . prefix , context, prefix_shape) ?;
150
+ Some ( format ! ( "{}::*" , path_str) )
151
+ } else {
152
+ Some ( "*" . into ( ) )
153
+ }
160
154
}
161
- ast:: ViewPath_ :: ViewPathSimple ( ident, ref path ) => {
155
+ ast:: UseTreeKind :: Simple ( ident) => {
162
156
let ident_str = ident. to_string ( ) ;
157
+
163
158
// 4 = " as ".len()
164
159
let prefix_shape = shape. sub_width ( ident_str. len ( ) + 4 ) ?;
165
- let path_str = rewrite_view_path_prefix ( path , context, prefix_shape) ?;
160
+ let path_str = rewrite_prefix ( & self . prefix , context, prefix_shape) ?;
166
161
167
- Some ( if path . segments . last ( ) . unwrap ( ) . identifier == ident {
168
- path_str
162
+ if self . prefix . segments . last ( ) . unwrap ( ) . identifier == ident {
163
+ Some ( path_str)
169
164
} else {
170
- format ! ( "{} as {}" , path_str, ident_str)
171
- } )
165
+ Some ( format ! ( "{} as {}" , path_str, ident_str) )
166
+ }
172
167
}
173
168
}
174
169
}
@@ -178,7 +173,7 @@ impl Rewrite for ast::ViewPath {
178
173
fn rewrite_import (
179
174
context : & RewriteContext ,
180
175
vis : & ast:: Visibility ,
181
- vp : & ast:: ViewPath ,
176
+ tree : & ast:: UseTree ,
182
177
attrs : & [ ast:: Attribute ] ,
183
178
shape : Shape ,
184
179
) -> Option < String > {
@@ -187,14 +182,12 @@ fn rewrite_import(
187
182
let rw = shape
188
183
. offset_left ( vis. len ( ) + 4 )
189
184
. and_then ( |shape| shape. sub_width ( 1 ) )
190
- . and_then ( |shape| match vp. node {
191
- // If we have an empty path list with no attributes, we erase it
192
- ast:: ViewPath_ :: ViewPathList ( _, ref path_list)
193
- if path_list. is_empty ( ) && attrs. is_empty ( ) =>
194
- {
185
+ . and_then ( |shape| match tree. kind {
186
+ // If we have an empty nested group with no attributes, we erase it
187
+ ast:: UseTreeKind :: Nested ( ref items) if items. is_empty ( ) && attrs. is_empty ( ) => {
195
188
Some ( "" . into ( ) )
196
189
}
197
- _ => vp . rewrite ( context, shape) ,
190
+ _ => tree . rewrite ( context, shape) ,
198
191
} ) ;
199
192
match rw {
200
193
Some ( ref s) if !s. is_empty ( ) => Some ( format ! ( "{}use {};" , vis, s) ) ,
@@ -225,8 +218,8 @@ fn rewrite_imports(
225
218
} ;
226
219
227
220
let item_str = match item. node {
228
- ast:: ItemKind :: Use ( ref vp ) => {
229
- rewrite_import ( context, & item. vis , vp , & item. attrs , shape) ?
221
+ ast:: ItemKind :: Use ( ref tree ) => {
222
+ rewrite_import ( context, & item. vis , tree , & item. attrs , shape) ?
230
223
}
231
224
ast:: ItemKind :: ExternCrate ( ..) => rewrite_extern_crate ( context, item) ?,
232
225
_ => return None ,
@@ -276,10 +269,10 @@ impl<'a> FmtVisitor<'a> {
276
269
self . push_rewrite ( span, rw) ;
277
270
}
278
271
279
- pub fn format_import ( & mut self , item : & ast:: Item , vp : & ast:: ViewPath ) {
272
+ pub fn format_import ( & mut self , item : & ast:: Item , tree : & ast:: UseTree ) {
280
273
let span = item. span ;
281
274
let shape = self . shape ( ) ;
282
- let rw = rewrite_import ( & self . get_context ( ) , & item. vis , vp , & item. attrs , shape) ;
275
+ let rw = rewrite_import ( & self . get_context ( ) , & item. vis , tree , & item. attrs , shape) ;
283
276
match rw {
284
277
Some ( ref s) if s. is_empty ( ) => {
285
278
// Format up to last newline
@@ -304,34 +297,48 @@ impl<'a> FmtVisitor<'a> {
304
297
}
305
298
}
306
299
307
- fn rewrite_single_use_list ( path_str : String , vpi : & ast:: PathListItem ) -> String {
308
- let mut item_str = vpi. node . name . to_string ( ) ;
309
- if item_str == "self" {
310
- item_str = "" . to_owned ( ) ;
311
- }
312
- let path_item_str = if path_str. is_empty ( ) {
313
- if item_str. is_empty ( ) {
314
- "self" . to_owned ( )
300
+ fn rewrite_nested_use_tree_single ( path_str : String , tree : & ast:: UseTree ) -> String {
301
+ if let ast:: UseTreeKind :: Simple ( rename) = tree. kind {
302
+ let ident = tree. prefix . segments . last ( ) . unwrap ( ) . identifier ;
303
+ let mut item_str = ident. name . to_string ( ) ;
304
+ if item_str == "self" {
305
+ item_str = "" . to_owned ( ) ;
306
+ }
307
+
308
+ let path_item_str = if path_str. is_empty ( ) {
309
+ if item_str. is_empty ( ) {
310
+ "self" . to_owned ( )
311
+ } else {
312
+ item_str
313
+ }
314
+ } else if item_str. is_empty ( ) {
315
+ path_str
315
316
} else {
316
- item_str
317
+ format ! ( "{}::{}" , path_str, item_str)
318
+ } ;
319
+
320
+ if ident == rename {
321
+ path_item_str
322
+ } else {
323
+ format ! ( "{} as {}" , path_item_str, rename)
317
324
}
318
- } else if item_str. is_empty ( ) {
319
- path_str
320
325
} else {
321
- format ! ( "{}::{}" , path_str, item_str)
322
- } ;
323
- append_alias ( path_item_str, vpi)
326
+ unimplemented ! ( "`use_nested_groups` is not yet fully supported" ) ;
327
+ }
324
328
}
325
329
326
- fn rewrite_path_item ( vpi : & & ast:: PathListItem ) -> Option < String > {
327
- Some ( append_alias ( vpi . node . name . to_string ( ) , vpi ) )
328
- }
330
+ fn rewrite_nested_use_tree_item ( tree : & & ast:: UseTree ) -> Option < String > {
331
+ Some ( if let ast :: UseTreeKind :: Simple ( rename ) = tree . kind {
332
+ let ident = tree . prefix . segments . last ( ) . unwrap ( ) . identifier ;
329
333
330
- fn append_alias ( path_item_str : String , vpi : & ast:: PathListItem ) -> String {
331
- match vpi. node . rename {
332
- Some ( rename) => format ! ( "{} as {}" , path_item_str, rename) ,
333
- None => path_item_str,
334
- }
334
+ if ident == rename {
335
+ ident. name . to_string ( )
336
+ } else {
337
+ format ! ( "{} as {}" , ident. name. to_string( ) , rename)
338
+ }
339
+ } else {
340
+ unimplemented ! ( "`use_nested_groups` is not yet fully supported" ) ;
341
+ } )
335
342
}
336
343
337
344
#[ derive( Eq , PartialEq ) ]
@@ -408,22 +415,23 @@ impl<'a> Ord for ImportItem<'a> {
408
415
409
416
// Pretty prints a multi-item import.
410
417
// If the path list is empty, it leaves the braces empty.
411
- fn rewrite_use_list (
418
+ fn rewrite_nested_use_tree (
412
419
shape : Shape ,
413
420
path : & ast:: Path ,
414
- path_list : & [ ast:: PathListItem ] ,
421
+ trees : & [ ( ast:: UseTree , ast :: NodeId ) ] ,
415
422
span : Span ,
416
423
context : & RewriteContext ,
417
424
) -> Option < String > {
418
425
// Returns a different option to distinguish `::foo` and `foo`
419
426
let path_str = rewrite_path ( context, PathContext :: Import , None , path, shape) ?;
420
427
421
- match path_list . len ( ) {
428
+ match trees . len ( ) {
422
429
0 => {
423
430
return rewrite_path ( context, PathContext :: Import , None , path, shape)
424
431
. map ( |path_str| format ! ( "{}::{{}}" , path_str) ) ;
425
432
}
426
- 1 => return Some ( rewrite_single_use_list ( path_str, & path_list[ 0 ] ) ) ,
433
+ // TODO: fix this
434
+ 1 => return Some ( rewrite_nested_use_tree_single ( path_str, & trees[ 0 ] . 0 ) ) ,
427
435
_ => ( ) ,
428
436
}
429
437
@@ -441,12 +449,12 @@ fn rewrite_use_list(
441
449
let mut items = vec ! [ ListItem :: from_str( "" ) ] ;
442
450
let iter = itemize_list (
443
451
context. codemap ,
444
- path_list . iter ( ) ,
452
+ trees . iter ( ) . map ( | ref tree| & tree . 0 ) ,
445
453
"}" ,
446
454
"," ,
447
- |vpi| vpi . span . lo ( ) ,
448
- |vpi| vpi . span . hi ( ) ,
449
- rewrite_path_item ,
455
+ |tree| tree . span . lo ( ) ,
456
+ |tree| tree . span . hi ( ) ,
457
+ rewrite_nested_use_tree_item ,
450
458
context. codemap . span_after ( span, "{" ) ,
451
459
span. hi ( ) ,
452
460
false ,
0 commit comments