@@ -1059,6 +1059,64 @@ fn string<T: Display, W: Write>(
10591059 }
10601060}
10611061
1062+ fn generate_link_to_def (
1063+ out : & mut impl Write ,
1064+ text_s : & str ,
1065+ klass : Class ,
1066+ href_context : & Option < HrefContext < ' _ , ' _ > > ,
1067+ def_span : Span ,
1068+ open_tag : bool ,
1069+ ) -> bool {
1070+ if let Some ( href_context) = href_context
1071+ && let Some ( href) =
1072+ href_context. context . shared . span_correspondence_map . get ( & def_span) . and_then ( |href| {
1073+ let context = href_context. context ;
1074+ // FIXME: later on, it'd be nice to provide two links (if possible) for all items:
1075+ // one to the documentation page and one to the source definition.
1076+ // FIXME: currently, external items only generate a link to their documentation,
1077+ // a link to their definition can be generated using this:
1078+ // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
1079+ match href {
1080+ LinkFromSrc :: Local ( span) => {
1081+ context. href_from_span_relative ( * span, & href_context. current_href )
1082+ }
1083+ LinkFromSrc :: External ( def_id) => {
1084+ format:: href_with_root_path ( * def_id, context, Some ( href_context. root_path ) )
1085+ . ok ( )
1086+ . map ( |( url, _, _) | url)
1087+ }
1088+ LinkFromSrc :: Primitive ( prim) => format:: href_with_root_path (
1089+ PrimitiveType :: primitive_locations ( context. tcx ( ) ) [ prim] ,
1090+ context,
1091+ Some ( href_context. root_path ) ,
1092+ )
1093+ . ok ( )
1094+ . map ( |( url, _, _) | url) ,
1095+ LinkFromSrc :: Doc ( def_id) => {
1096+ format:: href_with_root_path ( * def_id, context, Some ( href_context. root_path ) )
1097+ . ok ( )
1098+ . map ( |( doc_link, _, _) | doc_link)
1099+ }
1100+ }
1101+ } )
1102+ {
1103+ if !open_tag {
1104+ // We're already inside an element which has the same klass, no need to give it
1105+ // again.
1106+ write ! ( out, "<a href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1107+ } else {
1108+ let klass_s = klass. as_html ( ) ;
1109+ if klass_s. is_empty ( ) {
1110+ write ! ( out, "<a href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1111+ } else {
1112+ write ! ( out, "<a class=\" {klass_s}\" href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1113+ }
1114+ }
1115+ return true ;
1116+ }
1117+ false
1118+ }
1119+
10621120/// This function writes `text` into `out` with some modifications depending on `klass`:
10631121///
10641122/// * If `klass` is `None`, `text` is written into `out` with no modification.
@@ -1088,10 +1146,14 @@ fn string_without_closing_tag<T: Display>(
10881146 return Some ( "</span>" ) ;
10891147 } ;
10901148
1149+ let mut added_links = false ;
10911150 let mut text_s = text. to_string ( ) ;
10921151 if text_s. contains ( "::" ) {
1152+ let mut span = def_span. with_hi ( def_span. lo ( ) ) ;
10931153 text_s = text_s. split ( "::" ) . intersperse ( "::" ) . fold ( String :: new ( ) , |mut path, t| {
1154+ span = span. with_hi ( span. hi ( ) + BytePos ( t. len ( ) as _ ) ) ;
10941155 match t {
1156+ "::" => write ! ( & mut path, "::" ) ,
10951157 "self" | "Self" => write ! (
10961158 & mut path,
10971159 "<span class=\" {klass}\" >{t}</span>" ,
@@ -1104,58 +1166,24 @@ fn string_without_closing_tag<T: Display>(
11041166 klass = Class :: KeyWord . as_html( ) ,
11051167 )
11061168 }
1107- t => write ! ( & mut path, "{t}" ) ,
1169+ t => {
1170+ if !t. is_empty ( )
1171+ && generate_link_to_def ( & mut path, t, klass, href_context, span, open_tag)
1172+ {
1173+ added_links = true ;
1174+ write ! ( & mut path, "</a>" )
1175+ } else {
1176+ write ! ( & mut path, "{t}" )
1177+ }
1178+ }
11081179 }
11091180 . expect ( "Failed to build source HTML path" ) ;
1181+ span = span. with_lo ( span. lo ( ) + BytePos ( t. len ( ) as _ ) ) ;
11101182 path
11111183 } ) ;
11121184 }
11131185
1114- if let Some ( href_context) = href_context
1115- && let Some ( href) = href_context. context . shared . span_correspondence_map . get ( & def_span)
1116- && let Some ( href) = {
1117- let context = href_context. context ;
1118- // FIXME: later on, it'd be nice to provide two links (if possible) for all items:
1119- // one to the documentation page and one to the source definition.
1120- // FIXME: currently, external items only generate a link to their documentation,
1121- // a link to their definition can be generated using this:
1122- // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
1123- match href {
1124- LinkFromSrc :: Local ( span) => {
1125- context. href_from_span_relative ( * span, & href_context. current_href )
1126- }
1127- LinkFromSrc :: External ( def_id) => {
1128- format:: href_with_root_path ( * def_id, context, Some ( href_context. root_path ) )
1129- . ok ( )
1130- . map ( |( url, _, _) | url)
1131- }
1132- LinkFromSrc :: Primitive ( prim) => format:: href_with_root_path (
1133- PrimitiveType :: primitive_locations ( context. tcx ( ) ) [ prim] ,
1134- context,
1135- Some ( href_context. root_path ) ,
1136- )
1137- . ok ( )
1138- . map ( |( url, _, _) | url) ,
1139- LinkFromSrc :: Doc ( def_id) => {
1140- format:: href_with_root_path ( * def_id, context, Some ( href_context. root_path ) )
1141- . ok ( )
1142- . map ( |( doc_link, _, _) | doc_link)
1143- }
1144- }
1145- }
1146- {
1147- if !open_tag {
1148- // We're already inside an element which has the same klass, no need to give it
1149- // again.
1150- write ! ( out, "<a href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1151- } else {
1152- let klass_s = klass. as_html ( ) ;
1153- if klass_s. is_empty ( ) {
1154- write ! ( out, "<a href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1155- } else {
1156- write ! ( out, "<a class=\" {klass_s}\" href=\" {href}\" >{text_s}" ) . unwrap ( ) ;
1157- }
1158- }
1186+ if !added_links && generate_link_to_def ( out, & text_s, klass, href_context, def_span, open_tag) {
11591187 return Some ( "</a>" ) ;
11601188 }
11611189 if !open_tag {
0 commit comments