@@ -316,7 +316,8 @@ trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display {
316
316
fn item_module ( w : & mut Buffer , cx : & mut Context < ' _ > , item : & clean:: Item , items : & [ clean:: Item ] ) {
317
317
write ! ( w, "{}" , document( cx, item, None , HeadingOffset :: H2 ) ) ;
318
318
319
- let mut indices = ( 0 ..items. len ( ) ) . filter ( |i| !items[ * i] . is_stripped ( ) ) . collect :: < Vec < usize > > ( ) ;
319
+ let mut not_stripped_items =
320
+ items. iter ( ) . filter ( |i| !i. is_stripped ( ) ) . enumerate ( ) . collect :: < Vec < _ > > ( ) ;
320
321
321
322
// the order of item types in the listing
322
323
fn reorder ( ty : ItemType ) -> u8 {
@@ -338,37 +339,29 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
338
339
}
339
340
}
340
341
341
- fn cmp (
342
- i1 : & clean:: Item ,
343
- i2 : & clean:: Item ,
344
- idx1 : usize ,
345
- idx2 : usize ,
346
- tcx : TyCtxt < ' _ > ,
347
- ) -> Ordering {
348
- let ty1 = i1. type_ ( ) ;
349
- let ty2 = i2. type_ ( ) ;
350
- if item_ty_to_section ( ty1) != item_ty_to_section ( ty2)
351
- || ( ty1 != ty2 && ( ty1 == ItemType :: ExternCrate || ty2 == ItemType :: ExternCrate ) )
352
- {
353
- return ( reorder ( ty1) , idx1) . cmp ( & ( reorder ( ty2) , idx2) ) ;
354
- }
355
- let s1 = i1. stability ( tcx) . as_ref ( ) . map ( |s| s. level ) ;
356
- let s2 = i2. stability ( tcx) . as_ref ( ) . map ( |s| s. level ) ;
357
- if let ( Some ( a) , Some ( b) ) = ( s1, s2) {
358
- match ( a. is_stable ( ) , b. is_stable ( ) ) {
359
- ( true , true ) | ( false , false ) => { }
360
- ( false , true ) => return Ordering :: Greater ,
361
- ( true , false ) => return Ordering :: Less ,
362
- }
342
+ fn cmp ( i1 : & clean:: Item , i2 : & clean:: Item , tcx : TyCtxt < ' _ > ) -> Ordering {
343
+ let rty1 = reorder ( i1. type_ ( ) ) ;
344
+ let rty2 = reorder ( i2. type_ ( ) ) ;
345
+ if rty1 != rty2 {
346
+ return rty1. cmp ( & rty2) ;
347
+ }
348
+ let is_stable1 = i1. stability ( tcx) . as_ref ( ) . map ( |s| s. level . is_stable ( ) ) . unwrap_or ( true ) ;
349
+ let is_stable2 = i2. stability ( tcx) . as_ref ( ) . map ( |s| s. level . is_stable ( ) ) . unwrap_or ( true ) ;
350
+ if is_stable1 != is_stable2 {
351
+ // true is bigger than false in the standard bool ordering,
352
+ // but we actually want stable items to come first
353
+ return is_stable2. cmp ( & is_stable1) ;
363
354
}
364
355
let lhs = i1. name . unwrap_or ( kw:: Empty ) ;
365
356
let rhs = i2. name . unwrap_or ( kw:: Empty ) ;
366
357
compare_names ( lhs. as_str ( ) , rhs. as_str ( ) )
367
358
}
368
359
360
+ let tcx = cx. tcx ( ) ;
361
+
369
362
match cx. shared . module_sorting {
370
363
ModuleSorting :: Alphabetical => {
371
- indices . sort_by ( |& i1 , & i2 | cmp ( & items [ i1 ] , & items [ i2 ] , i1 , i2 , cx . tcx ( ) ) ) ;
364
+ not_stripped_items . sort_by ( |( _ , i1 ) , ( _ , i2 ) | cmp ( i1 , i2 , tcx) ) ;
372
365
}
373
366
ModuleSorting :: DeclarationOrder => { }
374
367
}
@@ -391,24 +384,19 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
391
384
// can be identical even if the elements are different (mostly in imports).
392
385
// So in case this is an import, we keep everything by adding a "unique id"
393
386
// (which is the position in the vector).
394
- indices . dedup_by_key ( |i | {
387
+ not_stripped_items . dedup_by_key ( |( idx , i ) | {
395
388
(
396
- items [ * i ] . item_id ,
397
- if items [ * i ] . name . is_some ( ) { Some ( full_path ( cx, & items [ * i ] ) ) } else { None } ,
398
- items [ * i ] . type_ ( ) ,
399
- if items [ * i ] . is_import ( ) { * i } else { 0 } ,
389
+ i . item_id ,
390
+ if i . name . is_some ( ) { Some ( full_path ( cx, i ) ) } else { None } ,
391
+ i . type_ ( ) ,
392
+ if i . is_import ( ) { * idx } else { 0 } ,
400
393
)
401
394
} ) ;
402
395
403
- debug ! ( "{indices :?}" ) ;
396
+ debug ! ( "{not_stripped_items :?}" ) ;
404
397
let mut last_section = None ;
405
398
406
- for & idx in & indices {
407
- let myitem = & items[ idx] ;
408
- if myitem. is_stripped ( ) {
409
- continue ;
410
- }
411
-
399
+ for ( _, myitem) in & not_stripped_items {
412
400
let my_section = item_ty_to_section ( myitem. type_ ( ) ) ;
413
401
if Some ( my_section) != last_section {
414
402
if last_section. is_some ( ) {
@@ -424,7 +412,6 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
424
412
) ;
425
413
}
426
414
427
- let tcx = cx. tcx ( ) ;
428
415
match * myitem. kind {
429
416
clean:: ExternCrateItem { ref src } => {
430
417
use crate :: html:: format:: anchor;
@@ -453,7 +440,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
453
440
let stab_tags = if let Some ( import_def_id) = import. source . did {
454
441
// Just need an item with the correct def_id and attrs
455
442
let import_item =
456
- clean:: Item { item_id : import_def_id. into ( ) , ..myitem. clone ( ) } ;
443
+ clean:: Item { item_id : import_def_id. into ( ) , ..( * myitem) . clone ( ) } ;
457
444
458
445
let stab_tags = Some ( extra_info_tags ( & import_item, item, tcx) . to_string ( ) ) ;
459
446
stab_tags
@@ -2010,40 +1997,102 @@ fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
2010
1997
}
2011
1998
2012
1999
/// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order).
2013
- pub ( crate ) fn compare_names ( mut lhs : & str , mut rhs : & str ) -> Ordering {
2014
- /// Takes a non-numeric and a numeric part from the given &str.
2015
- fn take_parts < ' a > ( s : & mut & ' a str ) -> ( & ' a str , & ' a str ) {
2016
- let i = s. find ( |c : char | c. is_ascii_digit ( ) ) ;
2017
- let ( a, b) = s. split_at ( i. unwrap_or ( s. len ( ) ) ) ;
2018
- let i = b. find ( |c : char | !c. is_ascii_digit ( ) ) ;
2019
- let ( b, c) = b. split_at ( i. unwrap_or ( b. len ( ) ) ) ;
2020
- * s = c;
2021
- ( a, b)
2022
- }
2023
-
2024
- while !lhs. is_empty ( ) || !rhs. is_empty ( ) {
2025
- let ( la, lb) = take_parts ( & mut lhs) ;
2026
- let ( ra, rb) = take_parts ( & mut rhs) ;
2027
- // First process the non-numeric part.
2028
- match la. cmp ( ra) {
2029
- Ordering :: Equal => ( ) ,
2030
- x => return x,
2031
- }
2032
- // Then process the numeric part, if both sides have one (and they fit in a u64).
2033
- if let ( Ok ( ln) , Ok ( rn) ) = ( lb. parse :: < u64 > ( ) , rb. parse :: < u64 > ( ) ) {
2034
- match ln. cmp ( & rn) {
2035
- Ordering :: Equal => ( ) ,
2036
- x => return x,
2000
+ ///
2001
+ /// This code is copied from [`rustfmt`], and should probably be released as a crate at some point.
2002
+ ///
2003
+ /// [`rustfmt`]:https://github.com/rust-lang/rustfmt/blob/rustfmt-2.0.0-rc.2/src/formatting/reorder.rs#L32
2004
+ pub ( crate ) fn compare_names ( left : & str , right : & str ) -> Ordering {
2005
+ let mut left = left. chars ( ) . peekable ( ) ;
2006
+ let mut right = right. chars ( ) . peekable ( ) ;
2007
+
2008
+ loop {
2009
+ // The strings are equal so far and not inside a number in both sides
2010
+ let ( l, r) = match ( left. next ( ) , right. next ( ) ) {
2011
+ // Is this the end of both strings?
2012
+ ( None , None ) => return Ordering :: Equal ,
2013
+ // If for one, the shorter one is considered smaller
2014
+ ( None , Some ( _) ) => return Ordering :: Less ,
2015
+ ( Some ( _) , None ) => return Ordering :: Greater ,
2016
+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2017
+ } ;
2018
+ let next_ordering = match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2019
+ // If neither is a digit, just compare them
2020
+ ( None , None ) => Ord :: cmp ( & l, & r) ,
2021
+ // The one with shorter non-digit run is smaller
2022
+ // For `strverscmp` it's smaller iff next char in longer is greater than digits
2023
+ ( None , Some ( _) ) => Ordering :: Greater ,
2024
+ ( Some ( _) , None ) => Ordering :: Less ,
2025
+ // If both start numbers, we have to compare the numbers
2026
+ ( Some ( l) , Some ( r) ) => {
2027
+ if l == 0 || r == 0 {
2028
+ // Fraction mode: compare as if there was leading `0.`
2029
+ let ordering = Ord :: cmp ( & l, & r) ;
2030
+ if ordering != Ordering :: Equal {
2031
+ return ordering;
2032
+ }
2033
+ loop {
2034
+ // Get next pair
2035
+ let ( l, r) = match ( left. peek ( ) , right. peek ( ) ) {
2036
+ // Is this the end of both strings?
2037
+ ( None , None ) => return Ordering :: Equal ,
2038
+ // If for one, the shorter one is considered smaller
2039
+ ( None , Some ( _) ) => return Ordering :: Less ,
2040
+ ( Some ( _) , None ) => return Ordering :: Greater ,
2041
+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2042
+ } ;
2043
+ // Are they digits?
2044
+ match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2045
+ // If out of digits, use the stored ordering due to equal length
2046
+ ( None , None ) => break Ordering :: Equal ,
2047
+ // If one is shorter, it's smaller
2048
+ ( None , Some ( _) ) => return Ordering :: Less ,
2049
+ ( Some ( _) , None ) => return Ordering :: Greater ,
2050
+ // If both are digits, consume them and take into account
2051
+ ( Some ( l) , Some ( r) ) => {
2052
+ left. next ( ) ;
2053
+ right. next ( ) ;
2054
+ let ordering = Ord :: cmp ( & l, & r) ;
2055
+ if ordering != Ordering :: Equal {
2056
+ return ordering;
2057
+ }
2058
+ }
2059
+ }
2060
+ }
2061
+ } else {
2062
+ // Integer mode
2063
+ let mut same_length_ordering = Ord :: cmp ( & l, & r) ;
2064
+ loop {
2065
+ // Get next pair
2066
+ let ( l, r) = match ( left. peek ( ) , right. peek ( ) ) {
2067
+ // Is this the end of both strings?
2068
+ ( None , None ) => return same_length_ordering,
2069
+ // If for one, the shorter one is considered smaller
2070
+ ( None , Some ( _) ) => return Ordering :: Less ,
2071
+ ( Some ( _) , None ) => return Ordering :: Greater ,
2072
+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2073
+ } ;
2074
+ // Are they digits?
2075
+ match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2076
+ // If out of digits, use the stored ordering due to equal length
2077
+ ( None , None ) => break same_length_ordering,
2078
+ // If one is shorter, it's smaller
2079
+ ( None , Some ( _) ) => return Ordering :: Less ,
2080
+ ( Some ( _) , None ) => return Ordering :: Greater ,
2081
+ // If both are digits, consume them and take into account
2082
+ ( Some ( l) , Some ( r) ) => {
2083
+ left. next ( ) ;
2084
+ right. next ( ) ;
2085
+ same_length_ordering = same_length_ordering. then ( Ord :: cmp ( & l, & r) ) ;
2086
+ }
2087
+ }
2088
+ }
2089
+ }
2037
2090
}
2038
- }
2039
- // Then process the numeric part again, but this time as strings.
2040
- match lb. cmp ( rb) {
2041
- Ordering :: Equal => ( ) ,
2042
- x => return x,
2091
+ } ;
2092
+ if next_ordering != Ordering :: Equal {
2093
+ return next_ordering;
2043
2094
}
2044
2095
}
2045
-
2046
- Ordering :: Equal
2047
2096
}
2048
2097
2049
2098
pub ( super ) fn full_path ( cx : & Context < ' _ > , item : & clean:: Item ) -> String {
0 commit comments