diff options
| -rw-r--r-- | compiler/rustc_span/src/lib.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_span/src/span_encoding.rs | 14 | ||||
| -rw-r--r-- | src/librustdoc/html/markdown/footnotes.rs | 60 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/search.js | 11 | ||||
| -rw-r--r-- | tests/rustdoc-js-std/write.js | 24 | ||||
| -rw-r--r-- | tests/rustdoc-js/case.js | 17 | ||||
| -rw-r--r-- | tests/rustdoc-js/case.rs | 7 | ||||
| -rw-r--r-- | tests/rustdoc/footnote-reference-in-footnote-def.rs | 20 |
8 files changed, 120 insertions, 39 deletions
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index baa1c2c91c7..8966cfc9171 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -559,12 +559,6 @@ impl Span { !self.is_dummy() && sm.is_span_accessible(self) } - /// Returns `true` if this span comes from any kind of macro, desugaring or inlining. - #[inline] - pub fn from_expansion(self) -> bool { - !self.ctxt().is_root() - } - /// Returns `true` if `span` originates in a derive-macro's expansion. pub fn in_derive_expansion(self) -> bool { matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index db8170fa6ae..9d6c7d2a42a 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -303,6 +303,13 @@ impl Span { } } + /// Returns `true` if this span comes from any kind of macro, desugaring or inlining. + #[inline] + pub fn from_expansion(self) -> bool { + // If the span is fully inferred then ctxt > MAX_CTXT + self.inline_ctxt().map_or(true, |ctxt| !ctxt.is_root()) + } + /// Returns `true` if this is a dummy span with any hygienic context. #[inline] pub fn is_dummy(self) -> bool { @@ -370,9 +377,10 @@ impl Span { pub fn eq_ctxt(self, other: Span) -> bool { match (self.inline_ctxt(), other.inline_ctxt()) { (Ok(ctxt1), Ok(ctxt2)) => ctxt1 == ctxt2, - (Ok(ctxt), Err(index)) | (Err(index), Ok(ctxt)) => { - with_span_interner(|interner| ctxt == interner.spans[index].ctxt) - } + // If `inline_ctxt` returns `Ok` the context is <= MAX_CTXT. + // If it returns `Err` the span is fully interned and the context is > MAX_CTXT. + // As these do not overlap an `Ok` and `Err` result cannot have an equal context. + (Ok(_), Err(_)) | (Err(_), Ok(_)) => false, (Err(index1), Err(index2)) => with_span_interner(|interner| { interner.spans[index1].ctxt == interner.spans[index2].ctxt }), diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs index 0958d446c2d..fcb8a174a95 100644 --- a/src/librustdoc/html/markdown/footnotes.rs +++ b/src/librustdoc/html/markdown/footnotes.rs @@ -1,7 +1,7 @@ //! Markdown footnote handling. use std::fmt::Write as _; -use pulldown_cmark::{Event, Tag, TagEnd, html}; +use pulldown_cmark::{CowStr, Event, Tag, TagEnd, html}; use rustc_data_structures::fx::FxIndexMap; use super::SpannedEvent; @@ -21,7 +21,7 @@ struct FootnoteDef<'a> { id: usize, } -impl<'a, 'b, I> Footnotes<'a, 'b, I> { +impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> { pub(super) fn new(iter: I, existing_footnotes: &'b mut usize) -> Self { Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes } } @@ -34,6 +34,34 @@ impl<'a, 'b, I> Footnotes<'a, 'b, I> { // Don't allow changing the ID of existing entrys, but allow changing the contents. (content, *id) } + + fn handle_footnote_reference(&mut self, reference: &CowStr<'a>) -> Event<'a> { + // When we see a reference (to a footnote we may not know) the definition of, + // reserve a number for it, and emit a link to that number. + let (_, id) = self.get_entry(reference); + let reference = format!( + "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{1}</a></sup>", + id, + // Although the ID count is for the whole page, the footnote reference + // are local to the item so we make this ID "local" when displayed. + id - *self.existing_footnotes + ); + Event::Html(reference.into()) + } + + fn collect_footnote_def(&mut self) -> Vec<Event<'a>> { + let mut content = Vec::new(); + while let Some((event, _)) = self.inner.next() { + match event { + Event::End(TagEnd::FootnoteDefinition) => break, + Event::FootnoteReference(ref reference) => { + content.push(self.handle_footnote_reference(reference)); + } + event => content.push(event), + } + } + content + } } impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, 'b, I> { @@ -41,24 +69,15 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, 'b fn next(&mut self) -> Option<Self::Item> { loop { - match self.inner.next() { + let next = self.inner.next(); + match next { Some((Event::FootnoteReference(ref reference), range)) => { - // When we see a reference (to a footnote we may not know) the definition of, - // reserve a number for it, and emit a link to that number. - let (_, id) = self.get_entry(reference); - let reference = format!( - "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{1}</a></sup>", - id, - // Although the ID count is for the whole page, the footnote reference - // are local to the item so we make this ID "local" when displayed. - id - *self.existing_footnotes - ); - return Some((Event::Html(reference.into()), range)); + return Some((self.handle_footnote_reference(reference), range)); } Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => { // When we see a footnote definition, collect the assocated content, and store // that for rendering later. - let content = collect_footnote_def(&mut self.inner); + let content = self.collect_footnote_def(); let (entry_content, _) = self.get_entry(&def); *entry_content = content; } @@ -80,17 +99,6 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, 'b } } -fn collect_footnote_def<'a>(events: impl Iterator<Item = SpannedEvent<'a>>) -> Vec<Event<'a>> { - let mut content = Vec::new(); - for (event, _) in events { - if let Event::End(TagEnd::FootnoteDefinition) = event { - break; - } - content.push(event); - } - content -} - fn render_footnotes_defs(mut footnotes: Vec<FootnoteDef<'_>>) -> String { let mut ret = String::from("<div class=\"footnotes\"><hr><ol>"); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 4e1bbbbf59d..a95a13aac47 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2500,6 +2500,7 @@ class DocSearch { const sortResults = async(results, typeInfo, preferredCrate) => { const userQuery = parsedQuery.userQuery; const normalizedUserQuery = parsedQuery.userQuery.toLowerCase(); + const isMixedCase = normalizedUserQuery !== userQuery; const result_list = []; for (const result of results.values()) { result.item = this.searchIndex[result.id]; @@ -2511,10 +2512,12 @@ class DocSearch { let a, b; // sort by exact case-sensitive match - a = (aaa.item.name !== userQuery); - b = (bbb.item.name !== userQuery); - if (a !== b) { - return a - b; + if (isMixedCase) { + a = (aaa.item.name !== userQuery); + b = (bbb.item.name !== userQuery); + if (a !== b) { + return a - b; + } } // sort by exact match with regard to the last word (mismatch goes later) diff --git a/tests/rustdoc-js-std/write.js b/tests/rustdoc-js-std/write.js new file mode 100644 index 00000000000..4a9475102a5 --- /dev/null +++ b/tests/rustdoc-js-std/write.js @@ -0,0 +1,24 @@ +const EXPECTED = [ + { + 'query': 'write', + 'others': [ + { 'path': 'std::fmt', 'name': 'write' }, + { 'path': 'std::fs', 'name': 'write' }, + { 'path': 'std::ptr', 'name': 'write' }, + { 'path': 'std::fmt', 'name': 'Write' }, + { 'path': 'std::io', 'name': 'Write' }, + { 'path': 'std::hash::Hasher', 'name': 'write' }, + ], + }, + { + 'query': 'Write', + 'others': [ + { 'path': 'std::fmt', 'name': 'Write' }, + { 'path': 'std::io', 'name': 'Write' }, + { 'path': 'std::fmt', 'name': 'write' }, + { 'path': 'std::fs', 'name': 'write' }, + { 'path': 'std::ptr', 'name': 'write' }, + { 'path': 'std::hash::Hasher', 'name': 'write' }, + ], + }, +]; diff --git a/tests/rustdoc-js/case.js b/tests/rustdoc-js/case.js new file mode 100644 index 00000000000..22b970eb139 --- /dev/null +++ b/tests/rustdoc-js/case.js @@ -0,0 +1,17 @@ +const EXPECTED = [ + { + 'query': 'Foo', + 'others': [ + { 'path': 'case', 'name': 'Foo', 'desc': 'Docs for Foo' }, + { 'path': 'case', 'name': 'foo', 'desc': 'Docs for foo' }, + ], + }, + { + 'query': 'foo', + 'others': [ + // https://github.com/rust-lang/rust/issues/133017 + { 'path': 'case', 'name': 'Foo', 'desc': 'Docs for Foo' }, + { 'path': 'case', 'name': 'foo', 'desc': 'Docs for foo' }, + ], + }, +]; diff --git a/tests/rustdoc-js/case.rs b/tests/rustdoc-js/case.rs new file mode 100644 index 00000000000..532edd55f1d --- /dev/null +++ b/tests/rustdoc-js/case.rs @@ -0,0 +1,7 @@ +#![allow(nonstandard_style)] + +/// Docs for Foo +pub struct Foo; + +/// Docs for foo +pub struct foo; diff --git a/tests/rustdoc/footnote-reference-in-footnote-def.rs b/tests/rustdoc/footnote-reference-in-footnote-def.rs new file mode 100644 index 00000000000..db3f9a59ef8 --- /dev/null +++ b/tests/rustdoc/footnote-reference-in-footnote-def.rs @@ -0,0 +1,20 @@ +// Checks that footnote references in footnote definitions are correctly generated. +// Regression test for <https://github.com/rust-lang/rust/issues/131946>. + +#![crate_name = "foo"] + +//@ has 'foo/index.html' +//@ has - '//*[@class="docblock"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1' +//@ has - '//li[@id="fn1"]/p' 'meow' +//@ has - '//li[@id="fn1"]/p/sup[@id="fnref2"]/a[@href="#fn2"]' '2' +//@ has - '//li[@id="fn1"]//a[@href="#fn2"]' '2' +//@ has - '//li[@id="fn2"]/p' 'uwu' +//@ has - '//li[@id="fn2"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1' +//@ has - '//li[@id="fn2"]//a[@href="#fn1"]' '1' + +//! # footnote-hell +//! +//! Hello [^a]. +//! +//! [^a]: meow [^b] +//! [^b]: uwu [^a] |
