about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/html/highlight.rs2
-rw-r--r--src/librustdoc/html/render/context.rs26
-rw-r--r--src/librustdoc/html/render/mod.rs45
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css1
-rw-r--r--src/librustdoc/html/static/js/scrape-examples.js46
-rw-r--r--src/librustdoc/scrape_examples.rs3
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs4
7 files changed, 64 insertions, 63 deletions
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 8ef5fabb901..bef99087a19 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -691,7 +691,7 @@ fn string<T: Display>(
                 // 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)
+                        .href_from_span(*span, true)
                         .map(|s| format!("{}{}", context_info.root_path, s)),
                     LinkFromSrc::External(def_id) => {
                         format::href_with_root_path(*def_id, context, Some(context_info.root_path))
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 364be8ae756..323bae3c9c4 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -295,10 +295,10 @@ impl<'tcx> Context<'tcx> {
     /// may happen, for example, with externally inlined items where the source
     /// of their crate documentation isn't known.
     pub(super) fn src_href(&self, item: &clean::Item) -> Option<String> {
-        self.href_from_span(item.span(self.tcx()))
+        self.href_from_span(item.span(self.tcx()), true)
     }
 
-    crate fn href_from_span(&self, span: clean::Span) -> Option<String> {
+    crate fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option<String> {
         if span.is_dummy() {
             return None;
         }
@@ -345,16 +345,26 @@ impl<'tcx> Context<'tcx> {
             (&*symbol, &path)
         };
 
-        let loline = span.lo(self.sess()).line;
-        let hiline = span.hi(self.sess()).line;
-        let lines =
-            if loline == hiline { loline.to_string() } else { format!("{}-{}", loline, hiline) };
+        let anchor = if with_lines {
+            let loline = span.lo(self.sess()).line;
+            let hiline = span.hi(self.sess()).line;
+            format!(
+                "#{}",
+                if loline == hiline {
+                    loline.to_string()
+                } else {
+                    format!("{}-{}", loline, hiline)
+                }
+            )
+        } else {
+            "".to_string()
+        };
         Some(format!(
-            "{root}src/{krate}/{path}#{lines}",
+            "{root}src/{krate}/{path}{anchor}",
             root = Escape(&root),
             krate = krate,
             path = path,
-            lines = lines
+            anchor = anchor
         ))
     }
 }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 5e4b068cf15..3a4c6891708 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2475,12 +2475,11 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, def_id: DefId, item:
     };
 
     // Generate a unique ID so users can link to this section for a given method
-    // FIXME: this should use init_id_map instead of derive
     let id = cx.id_map.borrow_mut().derive("scraped-examples");
     write!(
         w,
         "<div class=\"docblock scraped-example-list\">\
-          <span></span>
+          <span></span>\
           <h5 id=\"{id}\" class=\"section-header\">\
              <a href=\"#{id}\">Examples found in repository</a>\
           </h5>",
@@ -2516,42 +2515,51 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, def_id: DefId, item:
 
         // The call locations need to be updated to reflect that the size of the program has changed.
         // Specifically, the ranges are all subtracted by `byte_min` since that's the new zero point.
-        let (byte_ranges, line_ranges): (Vec<_>, Vec<_>) = call_data
+        let (mut byte_ranges, line_ranges): (Vec<_>, Vec<_>) = call_data
             .locations
             .iter()
             .map(|loc| {
                 let (byte_lo, byte_hi) = loc.call_expr.byte_span;
                 let (line_lo, line_hi) = loc.call_expr.line_span;
-                ((byte_lo - byte_min, byte_hi - byte_min), (line_lo - line_min, line_hi - line_min))
+                let byte_range = (byte_lo - byte_min, byte_hi - byte_min);
+                let line_range = (line_lo - line_min, line_hi - line_min);
+                let (anchor, line_title) = if line_lo == line_hi {
+                    (format!("{}", line_lo + 1), format!("line {}", line_lo + 1))
+                } else {
+                    (
+                        format!("{}-{}", line_lo + 1, line_hi + 1),
+                        format!("lines {}-{}", line_lo + 1, line_hi + 1),
+                    )
+                };
+                let line_url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor);
+
+                (byte_range, (line_range, line_url, line_title))
             })
             .unzip();
 
-        let (init_min, init_max) = line_ranges[0];
-        let line_range = if init_min == init_max {
-            format!("line {}", init_min + line_min + 1)
-        } else {
-            format!("lines {}-{}", init_min + line_min + 1, init_max + line_min + 1)
-        };
-
+        let (_, init_url, init_title) = &line_ranges[0];
         let needs_expansion = line_max - line_min > NUM_VISIBLE_LINES;
+        let locations_encoded = serde_json::to_string(&line_ranges).unwrap();
 
         write!(
             w,
             "<div class=\"scraped-example {expanded_cls}\" data-locs=\"{locations}\">\
                 <div class=\"scraped-example-title\">\
-                   {name} (<a href=\"{root}{url}\">{line_range}</a>)\
+                   {name} (<a href=\"{url}\">{title}</a>)\
                 </div>\
                 <div class=\"code-wrapper\">",
-            root = cx.root_path(),
-            url = call_data.url,
-            name = call_data.display_name,
-            line_range = line_range,
             expanded_cls = if needs_expansion { "" } else { "expanded" },
+            name = call_data.display_name,
+            url = init_url,
+            title = init_title,
             // The locations are encoded as a data attribute, so they can be read
             // later by the JS for interactions.
-            locations = serde_json::to_string(&line_ranges).unwrap(),
+            locations = Escape(&locations_encoded)
         );
-        write!(w, r#"<span class="prev">&pr;</span> <span class="next">&sc;</span>"#);
+
+        if line_ranges.len() > 1 {
+            write!(w, r#"<span class="prev">&pr;</span> <span class="next">&sc;</span>"#);
+        }
 
         if needs_expansion {
             write!(w, r#"<span class="expand">&varr;</span>"#);
@@ -2580,6 +2588,7 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, def_id: DefId, item:
         let root_path = vec!["../"; cx.current.len() - 1].join("");
 
         let mut decoration_info = FxHashMap::default();
+        decoration_info.insert("highlight focus", vec![byte_ranges.remove(0)]);
         decoration_info.insert("highlight", byte_ranges);
 
         sources::print_src(
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 820f6a00f20..49bdb2455ac 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1986,6 +1986,7 @@ details.undocumented[open] > summary::before {
 .scraped-example:not(.expanded) .code-wrapper .example-wrap pre.rust {
 	overflow-y: hidden;
 	max-height: 240px;
+	padding-bottom: 0;
 }
 
 .scraped-example .code-wrapper .prev {
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index 307843f2426..664b187e33e 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -15,41 +15,23 @@
 
     function updateScrapedExample(example) {
         var locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
-        var first_line_no = example.querySelector('.line-numbers > span:first-child');
-        var offset = parseInt(first_line_no.innerHTML) - 1;
-
         var locIndex = 0;
         var highlights = example.querySelectorAll('.highlight');
         var link = example.querySelector('.scraped-example-title a');
-        addClass(highlights[0], 'focus');
+
         if (locs.length > 1) {
             // Toggle through list of examples in a given file
-            var onChangeLoc = function(f) {
+            var onChangeLoc = function(changeIndex) {
                 removeClass(highlights[locIndex], 'focus');
-                f();
-                scrollToLoc(example, locs[locIndex]);
+                changeIndex();
+                scrollToLoc(example, locs[locIndex][0]);
                 addClass(highlights[locIndex], 'focus');
 
-                var curLoc = locs[locIndex];
-                var minLine = curLoc[0] + offset + 1;
-                var maxLine = curLoc[1] + offset + 1;
-
-                var text;
-                var anchor;
-                if (minLine == maxLine) {
-                    text = 'line ' + minLine.toString();
-                    anchor = minLine.toString();
-                } else {
-                    var range = minLine.toString() + '-' + maxLine.toString();
-                    text = 'lines ' + range;
-                    anchor = range;
-                }
-
-                var url = new URL(link.href);
-                url.hash = anchor;
+                var url = locs[locIndex][1];
+                var title = locs[locIndex][2];
 
-                link.href = url.toString();
-                link.innerHTML = text;
+                link.href = url;
+                link.innerHTML = title;
             };
 
             example.querySelector('.prev')
@@ -61,12 +43,10 @@
 
             example.querySelector('.next')
                 .addEventListener('click', function() {
-                    onChangeLoc(function() { locIndex = (locIndex + 1) % locs.length; });
+                    onChangeLoc(function() {
+                        locIndex = (locIndex + 1) % locs.length;
+                    });
                 });
-        } else {
-            // Remove buttons if there's only one example in the file
-            example.querySelector('.prev').remove();
-            example.querySelector('.next').remove();
         }
 
         var expandButton = example.querySelector('.expand');
@@ -74,7 +54,7 @@
             expandButton.addEventListener('click', function () {
                 if (hasClass(example, "expanded")) {
                     removeClass(example, "expanded");
-                    scrollToLoc(example, locs[0]);
+                    scrollToLoc(example, locs[0][0]);
                 } else {
                     addClass(example, "expanded");
                 }
@@ -82,7 +62,7 @@
         }
 
         // Start with the first example in view
-        scrollToLoc(example, locs[0]);
+        scrollToLoc(example, locs[0][0]);
     }
 
     var firstExamples = document.querySelectorAll('.scraped-example-list > .scraped-example');
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 3a8e5337f5b..c75a4244620 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -171,7 +171,7 @@ where
                 let cx = &self.cx;
                 let mk_call_data = || {
                     let clean_span = crate::clean::types::Span::new(span);
-                    let url = cx.href_from_span(clean_span).unwrap();
+                    let url = cx.href_from_span(clean_span, false).unwrap();
                     let display_name = file_path.display().to_string();
                     let edition = span.edition();
                     CallData { locations: Vec::new(), url, display_name, edition }
@@ -233,6 +233,7 @@ crate fn run(
     Ok(())
 }
 
+// Note: the Handler must be passed in explicitly because sess isn't available while parsing options
 crate fn load_call_locations(
     with_examples: Vec<String>,
     diag: &rustc_errors::Handler,
diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs
index b021f27da56..f525a4270dd 100644
--- a/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs
+++ b/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs
@@ -1,5 +1,5 @@
-// @has foobar/b/fn.foo.html '//*[@class="scraped-example"]' 'ex.rs'
-// @has foobar/c/fn.foo.html '//*[@class="scraped-example"]' 'ex.rs'
+// @has foobar/b/fn.foo.html '//*[@class="scraped-example expanded"]' 'ex.rs'
+// @has foobar/c/fn.foo.html '//*[@class="scraped-example expanded"]' 'ex.rs'
 
 #[path = "a.rs"]
 pub mod b;