From b336f2801c1d458990b7122bc4eba126beea37f9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 May 2021 17:29:51 +0200 Subject: [PATCH] Fix invalid generation of HTML in highlight --- src/librustdoc/html/highlight.rs | 83 ++++++++++--------- .../html/highlight/fixtures/highlight.html | 4 + src/librustdoc/html/highlight/tests.rs | 14 ++++ 3 files changed, 60 insertions(+), 41 deletions(-) create mode 100644 src/librustdoc/html/highlight/fixtures/highlight.html diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 13c02110514..9adb95fe90e 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -313,6 +313,7 @@ impl<'a> Classifier<'a> { .unwrap_or(false) { let tokens = self.get_full_ident_path(); + // We need this variable because `tokens` is consumed in the loop. let skip = !tokens.is_empty(); for (token, start, end) in tokens { let text = &self.src[start..end]; @@ -549,51 +550,51 @@ fn string( None => return write!(out, "{}", text), Some(klass) => klass, }; - if let Some(def_span) = klass.get_span() { - let mut text = text.to_string(); - if text.contains("::") { - text = text.split("::").intersperse("::").fold(String::new(), |mut path, t| { - match t { - "self" | "Self" => write!( - &mut path, - "{}", - Class::Self_(LightSpan::empty()).as_html(), - t - ), - "crate" | "super" => write!( - &mut path, - "{}", - Class::KeyWord.as_html(), - t - ), - t => write!(&mut path, "{}", t), - } - .expect("Failed to build source HTML path"); - path - }); + let def_span = match klass.get_span() { + Some(d) => d, + None => { + write!(out, "{}", klass.as_html(), text); + return; } - if let Some(context_info) = context_info { - if let Some(href) = - context_info.context.shared.span_correspondance_map.get(&def_span).and_then( - |href| { - let context = context_info.context; - match href { - LinkFromSrc::Local(span) => context - .href_from_span(*span) - .map(|s| format!("{}{}", context_info.root_path, s)), - LinkFromSrc::External(def_id) => { - format::href(*def_id, context).map(|(url, _, _)| url) - } - } - }, - ) - { - write!(out, "{}", klass.as_html(), href, text); - return; + }; + let mut text_s = text.to_string(); + if text_s.contains("::") { + text_s = text_s.split("::").intersperse("::").fold(String::new(), |mut path, t| { + match t { + "self" | "Self" => write!( + &mut path, + "{}", + Class::Self_(LightSpan::empty()).as_html(), + t + ), + "crate" | "super" => { + write!(&mut path, "{}", Class::KeyWord.as_html(), t) + } + t => write!(&mut path, "{}", t), } + .expect("Failed to build source HTML path"); + path + }); + } + if let Some(context_info) = context_info { + if let Some(href) = + context_info.context.shared.span_correspondance_map.get(&def_span).and_then(|href| { + let context = context_info.context; + match href { + LinkFromSrc::Local(span) => context + .href_from_span(*span) + .map(|s| format!("{}{}", context_info.root_path, s)), + LinkFromSrc::External(def_id) => { + format::href(*def_id, context).map(|(url, _, _)| url) + } + } + }) + { + write!(out, "{}", klass.as_html(), href, text_s); + return; } } - write!(out, "{}", klass.as_html(), text); + write!(out, "{}", klass.as_html(), text_s); } #[cfg(test)] diff --git a/src/librustdoc/html/highlight/fixtures/highlight.html b/src/librustdoc/html/highlight/fixtures/highlight.html new file mode 100644 index 00000000000..abc2db1790c --- /dev/null +++ b/src/librustdoc/html/highlight/fixtures/highlight.html @@ -0,0 +1,4 @@ +use crate::a::foo; +use self::whatever; +let x = super::b::foo; +let y = Self::whatever; \ No newline at end of file diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index 1259a1f3a23..68592ae96c1 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -40,3 +40,17 @@ fn test_dos_backline() { expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner()); }); } + +#[test] +fn test_keyword_highlight() { + create_default_session_globals_then(|| { + let src = "use crate::a::foo; +use self::whatever; +let x = super::b::foo; +let y = Self::whatever;"; + + let mut html = Buffer::new(); + write_code(&mut html, src, Edition::Edition2018, None); + expect_file!["fixtures/highlight.html"].assert_eq(&html.into_inner()); + }); +}