@@ -37,7 +37,7 @@ pub use self::ExternalLocation::*;
3737use std:: ascii:: AsciiExt ;
3838use std:: cell:: RefCell ;
3939use std:: cmp:: Ordering ;
40- use std:: collections:: BTreeMap ;
40+ use std:: collections:: { BTreeMap , HashSet } ;
4141use std:: default:: Default ;
4242use std:: error;
4343use std:: fmt:: { self , Display , Formatter , Write as FmtWrite } ;
@@ -3207,12 +3207,37 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
32073207 }
32083208}
32093209
3210+ fn should_render_item ( item : & clean:: Item , deref_mut_ : bool ) -> bool {
3211+ let self_type_opt = match item. inner {
3212+ clean:: MethodItem ( ref method) => method. decl . self_type ( ) ,
3213+ clean:: TyMethodItem ( ref method) => method. decl . self_type ( ) ,
3214+ _ => None
3215+ } ;
3216+
3217+ if let Some ( self_ty) = self_type_opt {
3218+ let ( by_mut_ref, by_box) = match self_ty {
3219+ SelfTy :: SelfBorrowed ( _, mutability) |
3220+ SelfTy :: SelfExplicit ( clean:: BorrowedRef { mutability, .. } ) => {
3221+ ( mutability == Mutability :: Mutable , false )
3222+ } ,
3223+ SelfTy :: SelfExplicit ( clean:: ResolvedPath { did, .. } ) => {
3224+ ( false , Some ( did) == cache ( ) . owned_box_did )
3225+ } ,
3226+ _ => ( false , false ) ,
3227+ } ;
3228+
3229+ ( deref_mut_ || !by_mut_ref) && !by_box
3230+ } else {
3231+ false
3232+ }
3233+ }
3234+
32103235fn render_impl ( w : & mut fmt:: Formatter , cx : & Context , i : & Impl , link : AssocItemLink ,
32113236 render_mode : RenderMode , outer_version : Option < & str > ,
32123237 show_def_docs : bool ) -> fmt:: Result {
32133238 if render_mode == RenderMode :: Normal {
32143239 let id = derive_id ( match i. inner_impl ( ) . trait_ {
3215- Some ( ref t) => format ! ( "impl-{}" , Escape ( & format!( "{:#}" , t) ) ) ,
3240+ Some ( ref t) => format ! ( "impl-{}" , small_url_encode ( & format!( "{:#}" , t) ) ) ,
32163241 None => "impl" . to_string ( ) ,
32173242 } ) ;
32183243 write ! ( w, "<h3 id='{}' class='impl'><span class='in-band'><code>{}</code>" ,
@@ -3244,30 +3269,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
32443269
32453270 let render_method_item: bool = match render_mode {
32463271 RenderMode :: Normal => true ,
3247- RenderMode :: ForDeref { mut_ : deref_mut_ } => {
3248- let self_type_opt = match item. inner {
3249- clean:: MethodItem ( ref method) => method. decl . self_type ( ) ,
3250- clean:: TyMethodItem ( ref method) => method. decl . self_type ( ) ,
3251- _ => None
3252- } ;
3253-
3254- if let Some ( self_ty) = self_type_opt {
3255- let ( by_mut_ref, by_box) = match self_ty {
3256- SelfTy :: SelfBorrowed ( _, mutability) |
3257- SelfTy :: SelfExplicit ( clean:: BorrowedRef { mutability, .. } ) => {
3258- ( mutability == Mutability :: Mutable , false )
3259- } ,
3260- SelfTy :: SelfExplicit ( clean:: ResolvedPath { did, .. } ) => {
3261- ( false , Some ( did) == cache ( ) . owned_box_did )
3262- } ,
3263- _ => ( false , false ) ,
3264- } ;
3265-
3266- ( deref_mut_ || !by_mut_ref) && !by_box
3267- } else {
3268- false
3269- }
3270- } ,
3272+ RenderMode :: ForDeref { mut_ : deref_mut_ } => should_render_item ( & item, deref_mut_) ,
32713273 } ;
32723274
32733275 match item. inner {
@@ -3514,12 +3516,48 @@ impl<'a> fmt::Display for Sidebar<'a> {
35143516 }
35153517}
35163518
3519+ fn get_methods ( i : & clean:: Impl , for_deref : bool ) -> Vec < String > {
3520+ i. items . iter ( ) . filter_map ( |item| {
3521+ match item. name {
3522+ // Maybe check with clean::Visibility::Public as well?
3523+ Some ( ref name) if !name. is_empty ( ) && item. visibility . is_some ( ) && item. is_method ( ) => {
3524+ if !for_deref || should_render_item ( item, false ) {
3525+ Some ( format ! ( "<a href=\" #method.{name}\" >{name}</a>" , name = name) )
3526+ } else {
3527+ None
3528+ }
3529+ }
3530+ _ => None ,
3531+ }
3532+ } ) . collect :: < Vec < _ > > ( )
3533+ }
3534+
3535+ // The point is to url encode any potential character from a type with genericity.
3536+ fn small_url_encode ( s : & str ) -> String {
3537+ s. replace ( "<" , "%3C" )
3538+ . replace ( ">" , "%3E" )
3539+ . replace ( " " , "%20" )
3540+ . replace ( "?" , "%3F" )
3541+ . replace ( "'" , "%27" )
3542+ . replace ( "&" , "%26" )
3543+ . replace ( "," , "%2C" )
3544+ . replace ( ":" , "%3A" )
3545+ . replace ( ";" , "%3B" )
3546+ . replace ( "[" , "%5B" )
3547+ . replace ( "]" , "%5D" )
3548+ }
3549+
35173550fn sidebar_assoc_items ( it : & clean:: Item ) -> String {
35183551 let mut out = String :: new ( ) ;
35193552 let c = cache ( ) ;
35203553 if let Some ( v) = c. impls . get ( & it. def_id ) {
3521- if v. iter ( ) . any ( |i| i. inner_impl ( ) . trait_ . is_none ( ) ) {
3522- out. push_str ( "<li><a href=\" #methods\" >Methods</a></li>" ) ;
3554+ let ret = v. iter ( )
3555+ . filter ( |i| i. inner_impl ( ) . trait_ . is_none ( ) )
3556+ . flat_map ( |i| get_methods ( i. inner_impl ( ) , false ) )
3557+ . collect :: < String > ( ) ;
3558+ if !ret. is_empty ( ) {
3559+ out. push_str ( & format ! ( "<a class=\" sidebar-title\" href=\" #methods\" >Methods\
3560+ </a><div class=\" sidebar-links\" >{}</div>", ret) ) ;
35233561 }
35243562
35253563 if v. iter ( ) . any ( |i| i. inner_impl ( ) . trait_ . is_some ( ) ) {
@@ -3535,16 +3573,40 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
35353573 let inner_impl = target. def_id ( ) . or ( target. primitive_type ( ) . and_then ( |prim| {
35363574 c. primitive_locations . get ( & prim) . cloned ( )
35373575 } ) ) . and_then ( |did| c. impls . get ( & did) ) ;
3538- if inner_impl . is_some ( ) {
3539- out. push_str ( "<li><a href=\" #deref-methods\" >" ) ;
3576+ if let Some ( impls ) = inner_impl {
3577+ out. push_str ( "<a class= \" sidebar-title \" href=\" #deref-methods\" >" ) ;
35403578 out. push_str ( & format ! ( "Methods from {:#}<Target={:#}>" ,
3541- impl_. inner_impl( ) . trait_. as_ref( ) . unwrap( ) ,
3542- target) ) ;
3543- out. push_str ( "</a></li>" ) ;
3579+ impl_. inner_impl( ) . trait_. as_ref( ) . unwrap( ) ,
3580+ target) ) ;
3581+ out. push_str ( "</a>" ) ;
3582+ let ret = impls. iter ( )
3583+ . filter ( |i| i. inner_impl ( ) . trait_ . is_none ( ) )
3584+ . flat_map ( |i| get_methods ( i. inner_impl ( ) , true ) )
3585+ . collect :: < String > ( ) ;
3586+ out. push_str ( & format ! ( "<div class=\" sidebar-links\" >{}</div>" , ret) ) ;
35443587 }
35453588 }
35463589 }
3547- out. push_str ( "<li><a href=\" #implementations\" >Trait Implementations</a></li>" ) ;
3590+ let mut links = HashSet :: new ( ) ;
3591+ let ret = v. iter ( )
3592+ . filter_map ( |i| if let Some ( ref i) = i. inner_impl ( ) . trait_ {
3593+ let out = format ! ( "{:#}" , i) . replace ( "<" , "<" ) . replace ( ">" , ">" ) ;
3594+ let encoded = small_url_encode ( & format ! ( "{:#}" , i) ) ;
3595+ let generated = format ! ( "<a href=\" #impl-{}\" >{}</a>" , encoded, out) ;
3596+ if !links. contains ( & generated) && links. insert ( generated. clone ( ) ) {
3597+ Some ( generated)
3598+ } else {
3599+ None
3600+ }
3601+ } else {
3602+ None
3603+ } )
3604+ . collect :: < String > ( ) ;
3605+ if !ret. is_empty ( ) {
3606+ out. push_str ( "<a class=\" sidebar-title\" href=\" #implementations\" >\
3607+ Trait Implementations</a>") ;
3608+ out. push_str ( & format ! ( "<div class=\" sidebar-links\" >{}</div>" , ret) ) ;
3609+ }
35483610 }
35493611 }
35503612
@@ -3565,7 +3627,7 @@ fn sidebar_struct(fmt: &mut fmt::Formatter, it: &clean::Item,
35653627 sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
35663628
35673629 if !sidebar. is_empty ( ) {
3568- write ! ( fmt, "<div class=\" block items\" ><ul>{}</ul> </div>" , sidebar) ?;
3630+ write ! ( fmt, "<div class=\" block items\" >{} </div>" , sidebar) ?;
35693631 }
35703632 Ok ( ( ) )
35713633}
@@ -3592,8 +3654,6 @@ fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
35923654 sidebar. push_str ( "<li><a href=\" #provided-methods\" >Provided Methods</a></li>" ) ;
35933655 }
35943656
3595- sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
3596-
35973657 let c = cache ( ) ;
35983658
35993659 if let Some ( implementors) = c. implementors . get ( & it. def_id ) {
@@ -3607,15 +3667,17 @@ fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
36073667
36083668 sidebar. push_str ( "<li><a href=\" #implementors\" >Implementors</a></li>" ) ;
36093669
3610- write ! ( fmt, "<div class=\" block items\" ><ul>{}</ul></div>" , sidebar)
3670+ sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
3671+
3672+ write ! ( fmt, "<div class=\" block items\" >{}</div>" , sidebar)
36113673}
36123674
36133675fn sidebar_primitive ( fmt : & mut fmt:: Formatter , it : & clean:: Item ,
36143676 _p : & clean:: PrimitiveType ) -> fmt:: Result {
36153677 let sidebar = sidebar_assoc_items ( it) ;
36163678
36173679 if !sidebar. is_empty ( ) {
3618- write ! ( fmt, "<div class=\" block items\" ><ul>{}</ul> </div>" , sidebar) ?;
3680+ write ! ( fmt, "<div class=\" block items\" >{} </div>" , sidebar) ?;
36193681 }
36203682 Ok ( ( ) )
36213683}
@@ -3625,7 +3687,7 @@ fn sidebar_typedef(fmt: &mut fmt::Formatter, it: &clean::Item,
36253687 let sidebar = sidebar_assoc_items ( it) ;
36263688
36273689 if !sidebar. is_empty ( ) {
3628- write ! ( fmt, "<div class=\" block items\" ><ul>{}</ul> </div>" , sidebar) ?;
3690+ write ! ( fmt, "<div class=\" block items\" >{} </div>" , sidebar) ?;
36293691 }
36303692 Ok ( ( ) )
36313693}
@@ -3642,7 +3704,7 @@ fn sidebar_union(fmt: &mut fmt::Formatter, it: &clean::Item,
36423704 sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
36433705
36443706 if !sidebar. is_empty ( ) {
3645- write ! ( fmt, "<div class=\" block items\" ><ul>{}</ul> </div>" , sidebar) ?;
3707+ write ! ( fmt, "<div class=\" block items\" >{} </div>" , sidebar) ?;
36463708 }
36473709 Ok ( ( ) )
36483710}
@@ -3658,7 +3720,7 @@ fn sidebar_enum(fmt: &mut fmt::Formatter, it: &clean::Item,
36583720 sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
36593721
36603722 if !sidebar. is_empty ( ) {
3661- write ! ( fmt, "<div class=\" block items\" ><ul>{}</ul> </div>" , sidebar) ?;
3723+ write ! ( fmt, "<div class=\" block items\" >{} </div>" , sidebar) ?;
36623724 }
36633725 Ok ( ( ) )
36643726}
0 commit comments