@@ -13,6 +13,7 @@ use std::cmp::Ordering;
1313use syntax:: ast;
1414use syntax:: codemap:: { BytePos , Span } ;
1515
16+
1617use spanned:: Spanned ;
1718use codemap:: SpanUtils ;
1819use comment:: combine_strs_with_missing_comments;
@@ -25,14 +26,6 @@ use types::{rewrite_path, PathContext};
2526use utils:: { format_visibility, mk_sp} ;
2627use visitor:: { rewrite_extern_crate, FmtVisitor } ;
2728
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-
3629fn compare_path_segments ( a : & ast:: PathSegment , b : & ast:: PathSegment ) -> Ordering {
3730 a. identifier . name . as_str ( ) . cmp ( & b. identifier . name . as_str ( ) )
3831}
@@ -47,75 +40,76 @@ fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering {
4740 a. segments . len ( ) . cmp ( & b. segments . len ( ) )
4841}
4942
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 :: * ;
7645
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;
8952 }
9053 }
91- a. len ( ) . cmp ( & b. len ( ) )
92- }
9354
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+ }
9983 }
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 ( ) )
103104 }
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 ,
112106 }
113107}
114108
115109fn compare_use_items ( context : & RewriteContext , a : & ast:: Item , b : & ast:: Item ) -> Option < Ordering > {
116110 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 ) )
119113 }
120114 ( & ast:: ItemKind :: ExternCrate ( ..) , & ast:: ItemKind :: ExternCrate ( ..) ) => {
121115 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) ->
127121// TODO (some day) remove unused imports, expand globs, compress many single
128122// imports into a list import.
129123
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 > {
135125 let path_str = if path. segments . last ( ) . unwrap ( ) . identifier . to_string ( ) == "self"
136126 && path. segments . len ( ) > 1
137127 {
@@ -146,29 +136,34 @@ fn rewrite_view_path_prefix(
146136 Some ( path_str)
147137}
148138
149- impl Rewrite for ast:: ViewPath {
139+ impl Rewrite for ast:: UseTree {
150140 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)
154144 }
155- ast:: ViewPath_ :: ViewPathGlob ( ref path) => {
156- // 4 = "::*".len()
145+ ast:: UseTreeKind :: Glob => {
157146 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+ }
160154 }
161- ast:: ViewPath_ :: ViewPathSimple ( ident, ref path ) => {
155+ ast:: UseTreeKind :: Simple ( ident) => {
162156 let ident_str = ident. to_string ( ) ;
157+
163158 // 4 = " as ".len()
164159 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) ?;
166161
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)
169164 } else {
170- format ! ( "{} as {}" , path_str, ident_str)
171- } )
165+ Some ( format ! ( "{} as {}" , path_str, ident_str) )
166+ }
172167 }
173168 }
174169 }
@@ -178,7 +173,7 @@ impl Rewrite for ast::ViewPath {
178173fn rewrite_import (
179174 context : & RewriteContext ,
180175 vis : & ast:: Visibility ,
181- vp : & ast:: ViewPath ,
176+ tree : & ast:: UseTree ,
182177 attrs : & [ ast:: Attribute ] ,
183178 shape : Shape ,
184179) -> Option < String > {
@@ -187,14 +182,12 @@ fn rewrite_import(
187182 let rw = shape
188183 . offset_left ( vis. len ( ) + 4 )
189184 . 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 ( ) => {
195188 Some ( "" . into ( ) )
196189 }
197- _ => vp . rewrite ( context, shape) ,
190+ _ => tree . rewrite ( context, shape) ,
198191 } ) ;
199192 match rw {
200193 Some ( ref s) if !s. is_empty ( ) => Some ( format ! ( "{}use {};" , vis, s) ) ,
@@ -225,8 +218,8 @@ fn rewrite_imports(
225218 } ;
226219
227220 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) ?
230223 }
231224 ast:: ItemKind :: ExternCrate ( ..) => rewrite_extern_crate ( context, item) ?,
232225 _ => return None ,
@@ -276,10 +269,10 @@ impl<'a> FmtVisitor<'a> {
276269 self . push_rewrite ( span, rw) ;
277270 }
278271
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 ) {
280273 let span = item. span ;
281274 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) ;
283276 match rw {
284277 Some ( ref s) if s. is_empty ( ) => {
285278 // Format up to last newline
@@ -304,34 +297,48 @@ impl<'a> FmtVisitor<'a> {
304297 }
305298}
306299
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
315316 } 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)
317324 }
318- } else if item_str. is_empty ( ) {
319- path_str
320325 } 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+ }
324328}
325329
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 ;
329333
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+ } )
335342}
336343
337344#[ derive( Eq , PartialEq ) ]
@@ -408,22 +415,23 @@ impl<'a> Ord for ImportItem<'a> {
408415
409416// Pretty prints a multi-item import.
410417// If the path list is empty, it leaves the braces empty.
411- fn rewrite_use_list (
418+ fn rewrite_nested_use_tree (
412419 shape : Shape ,
413420 path : & ast:: Path ,
414- path_list : & [ ast:: PathListItem ] ,
421+ trees : & [ ( ast:: UseTree , ast :: NodeId ) ] ,
415422 span : Span ,
416423 context : & RewriteContext ,
417424) -> Option < String > {
418425 // Returns a different option to distinguish `::foo` and `foo`
419426 let path_str = rewrite_path ( context, PathContext :: Import , None , path, shape) ?;
420427
421- match path_list . len ( ) {
428+ match trees . len ( ) {
422429 0 => {
423430 return rewrite_path ( context, PathContext :: Import , None , path, shape)
424431 . map ( |path_str| format ! ( "{}::{{}}" , path_str) ) ;
425432 }
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 ) ) ,
427435 _ => ( ) ,
428436 }
429437
@@ -441,12 +449,12 @@ fn rewrite_use_list(
441449 let mut items = vec ! [ ListItem :: from_str( "" ) ] ;
442450 let iter = itemize_list (
443451 context. codemap ,
444- path_list . iter ( ) ,
452+ trees . iter ( ) . map ( | ref tree| & tree . 0 ) ,
445453 "}" ,
446454 "," ,
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 ,
450458 context. codemap . span_after ( span, "{" ) ,
451459 span. hi ( ) ,
452460 false ,
0 commit comments