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