@@ -1052,6 +1052,64 @@ fn string<T: Display, W: Write>(
10521052 }
10531053}
10541054
1055+ fn generate_link_to_def (
1056+ out : & mut impl Write ,
1057+ text_s : & str ,
1058+ klass : Class ,
1059+ href_context : & Option < HrefContext < ' _ , ' _ > > ,
1060+ def_span : Span ,
1061+ open_tag : bool ,
1062+ ) -> bool {
1063+ if let Some ( href_context) = href_context
1064+ && let Some ( href) =
1065+ href_context. context . shared . span_correspondence_map . get ( & def_span) . and_then ( |href| {
1066+ let context = href_context. context ;
1067+ // FIXME: later on, it'd be nice to provide two links (if possible) for all items:
1068+ // one to the documentation page and one to the source definition.
1069+ // FIXME: currently, external items only generate a link to their documentation,
1070+ // a link to their definition can be generated using this:
1071+ // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
1072+ match href {
1073+ LinkFromSrc :: Local ( span) => {
1074+ context. href_from_span_relative ( * span, & href_context. current_href )
1075+ }
1076+ LinkFromSrc :: External ( def_id) => {
1077+ format:: href_with_root_path ( * def_id, context, Some ( href_context. root_path ) )
1078+ . ok ( )
1079+ . map ( |( url, _, _) | url)
1080+ }
1081+ LinkFromSrc :: Primitive ( prim) => format:: href_with_root_path (
1082+ PrimitiveType :: primitive_locations ( context. tcx ( ) ) [ prim] ,
1083+ context,
1084+ Some ( href_context. root_path ) ,
1085+ )
1086+ . ok ( )
1087+ . map ( |( url, _, _) | url) ,
1088+ LinkFromSrc :: Doc ( def_id) => {
1089+ format:: href_with_root_path ( * def_id, context, Some ( href_context. root_path ) )
1090+ . ok ( )
1091+ . map ( |( doc_link, _, _) | doc_link)
1092+ }
1093+ }
1094+ } )
1095+ {
1096+ if !open_tag {
1097+ // We're already inside an element which has the same klass, no need to give it
1098+ // again.
1099+ write ! ( out, "<a href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1100+ } else {
1101+ let klass_s = klass. as_html ( ) ;
1102+ if klass_s. is_empty ( ) {
1103+ write ! ( out, "<a href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1104+ } else {
1105+ write ! ( out, "<a class=\" {klass_s}\" href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1106+ }
1107+ }
1108+ return true ;
1109+ }
1110+ false
1111+ }
1112+
10551113/// This function writes `text` into `out` with some modifications depending on `klass`:
10561114///
10571115/// * If `klass` is `None`, `text` is written into `out` with no modification.
@@ -1081,10 +1139,14 @@ fn string_without_closing_tag<T: Display>(
10811139 return Some ( "</span>" ) ;
10821140 } ;
10831141
1142+ let mut added_links = false ;
10841143 let mut text_s = text. to_string ( ) ;
10851144 if text_s. contains ( "::" ) {
1145+ let mut span = def_span. with_hi ( def_span. lo ( ) ) ;
10861146 text_s = text_s. split ( "::" ) . intersperse ( "::" ) . fold ( String :: new ( ) , |mut path, t| {
1147+ span = span. with_hi ( span. hi ( ) + BytePos ( t. len ( ) as _ ) ) ;
10871148 match t {
1149+ "::" => write ! ( & mut path, "::" ) ,
10881150 "self" | "Self" => write ! (
10891151 & mut path,
10901152 "<span class=\" {klass}\" >{t}</span>" ,
@@ -1097,58 +1159,24 @@ fn string_without_closing_tag<T: Display>(
10971159 klass = Class :: KeyWord . as_html( ) ,
10981160 )
10991161 }
1100- t => write ! ( & mut path, "{t}" ) ,
1162+ t => {
1163+ if !t. is_empty ( )
1164+ && generate_link_to_def ( & mut path, t, klass, href_context, span, open_tag)
1165+ {
1166+ added_links = true ;
1167+ write ! ( & mut path, "</a>" )
1168+ } else {
1169+ write ! ( & mut path, "{t}" )
1170+ }
1171+ }
11011172 }
11021173 . expect ( "Failed to build source HTML path" ) ;
1174+ span = span. with_lo ( span. lo ( ) + BytePos ( t. len ( ) as _ ) ) ;
11031175 path
11041176 } ) ;
11051177 }
11061178
1107- if let Some ( href_context) = href_context
1108- && let Some ( href) = href_context. context . shared . span_correspondence_map . get ( & def_span)
1109- && let Some ( href) = {
1110- let context = href_context. context ;
1111- // FIXME: later on, it'd be nice to provide two links (if possible) for all items:
1112- // one to the documentation page and one to the source definition.
1113- // FIXME: currently, external items only generate a link to their documentation,
1114- // a link to their definition can be generated using this:
1115- // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
1116- match href {
1117- LinkFromSrc :: Local ( span) => {
1118- context. href_from_span_relative ( * span, & href_context. current_href )
1119- }
1120- LinkFromSrc :: External ( def_id) => {
1121- format:: href_with_root_path ( * def_id, context, Some ( href_context. root_path ) )
1122- . ok ( )
1123- . map ( |( url, _, _) | url)
1124- }
1125- LinkFromSrc :: Primitive ( prim) => format:: href_with_root_path (
1126- PrimitiveType :: primitive_locations ( context. tcx ( ) ) [ prim] ,
1127- context,
1128- Some ( href_context. root_path ) ,
1129- )
1130- . ok ( )
1131- . map ( |( url, _, _) | url) ,
1132- LinkFromSrc :: Doc ( def_id) => {
1133- format:: href_with_root_path ( * def_id, context, Some ( href_context. root_path ) )
1134- . ok ( )
1135- . map ( |( doc_link, _, _) | doc_link)
1136- }
1137- }
1138- }
1139- {
1140- if !open_tag {
1141- // We're already inside an element which has the same klass, no need to give it
1142- // again.
1143- write ! ( out, "<a href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1144- } else {
1145- let klass_s = klass. as_html ( ) ;
1146- if klass_s. is_empty ( ) {
1147- write ! ( out, "<a href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1148- } else {
1149- write ! ( out, "<a class=\" {klass_s}\" href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1150- }
1151- }
1179+ if !added_links && generate_link_to_def ( out, & text_s, klass, href_context, def_span, open_tag) {
11521180 return Some ( "</a>" ) ;
11531181 }
11541182 if !open_tag {
0 commit comments