From ef24747703b6a30abb242d43f09c584edfed1b24 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 15 Sep 2022 13:03:04 -0700 Subject: [PATCH] rustdoc: use more precise URLs for jump-to-definition links As an example, this cuts down by about 11%. $ du -h new_mod.rs.html old_mod.rs.html 296K new_mod.rs.html 332K old_mod.rs.html --- src/librustdoc/html/highlight.rs | 8 ++++--- src/librustdoc/html/render/context.rs | 30 +++++++++++++++++++++++++++ src/librustdoc/html/sources.rs | 5 ++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 1e6cab8fcd3..8922bf37785 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -29,6 +29,8 @@ pub(crate) struct HrefContext<'a, 'b, 'c> { /// This field is used to know "how far" from the top of the directory we are to link to either /// documentation pages or other source pages. pub(crate) root_path: &'c str, + /// This field is used to calculate precise local URLs. + pub(crate) current_href: &'c str, } /// Decorations are represented as a map from CSS class to vector of character ranges. @@ -977,9 +979,9 @@ fn string_without_closing_tag( // a link to their definition can be generated using this: // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338 match href { - LinkFromSrc::Local(span) => context - .href_from_span(*span, true) - .map(|s| format!("{}{}", href_context.root_path, s)), + LinkFromSrc::Local(span) => { + context.href_from_span_relative(*span, href_context.current_href) + } LinkFromSrc::External(def_id) => { format::href_with_root_path(*def_id, context, Some(href_context.root_path)) .ok() diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 01b96dc7215..62def4a94e8 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -31,6 +31,7 @@ use crate::formats::FormatRenderer; use crate::html::escape::Escape; use crate::html::format::{join_with_double_colon, Buffer}; use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap}; +use crate::html::url_parts_builder::UrlPartsBuilder; use crate::html::{layout, sources}; use crate::scrape_examples::AllCallLocations; use crate::try_err; @@ -370,6 +371,35 @@ impl<'tcx> Context<'tcx> { anchor = anchor )) } + + pub(crate) fn href_from_span_relative( + &self, + span: clean::Span, + relative_to: &str, + ) -> Option { + self.href_from_span(span, false).map(|s| { + let mut url = UrlPartsBuilder::new(); + let mut dest_href_parts = s.split('/'); + let mut cur_href_parts = relative_to.split('/'); + for (cur_href_part, dest_href_part) in (&mut cur_href_parts).zip(&mut dest_href_parts) { + if cur_href_part != dest_href_part { + url.push(dest_href_part); + break; + } + } + for dest_href_part in dest_href_parts { + url.push(dest_href_part); + } + let loline = span.lo(self.sess()).line; + let hiline = span.hi(self.sess()).line; + format!( + "{}{}#{}", + "../".repeat(cur_href_parts.count()), + url.finish(), + if loline == hiline { loline.to_string() } else { format!("{loline}-{hiline}") } + ) + }) + } } /// Generates the documentation for `crate` into the directory `dst` diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index f37c54e4298..2e2bee78b95 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -288,11 +288,14 @@ pub(crate) fn print_src( } } line_numbers.write_str(""); + let current_href = &context + .href_from_span(clean::Span::new(file_span), false) + .expect("only local crates should have sources emitted"); highlight::render_source_with_highlighting( s, buf, line_numbers, - highlight::HrefContext { context, file_span, root_path }, + highlight::HrefContext { context, file_span, root_path, current_href }, decoration_info, ); }