diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2025-08-23 01:38:57 +0200 |
|---|---|---|
| committer | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2025-08-23 10:57:14 +0200 |
| commit | f5fddc776ca450c08fe8fc3ecbe5e2c969055d01 (patch) | |
| tree | 7b214b983f660f37b740a3c8941dce395816eddd | |
| parent | 0e9b126695847418a681b96b87b5976fb069394a (diff) | |
| download | rust-f5fddc776ca450c08fe8fc3ecbe5e2c969055d01.tar.gz rust-f5fddc776ca450c08fe8fc3ecbe5e2c969055d01.zip | |
Improve code and add test with macro coming from another file from the same crate
| -rw-r--r-- | src/librustdoc/html/highlight.rs | 22 | ||||
| -rw-r--r-- | src/librustdoc/html/macro_expansion.rs | 8 | ||||
| -rw-r--r-- | src/librustdoc/html/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustdoc/lib.rs | 26 | ||||
| -rw-r--r-- | tests/rustdoc-gui/macro-expansion.goml | 103 | ||||
| -rw-r--r-- | tests/rustdoc-gui/src/macro_expansion/lib.rs | 5 | ||||
| -rw-r--r-- | tests/rustdoc-gui/src/macro_expansion/other.rs | 6 |
7 files changed, 92 insertions, 80 deletions
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 583c178fa11..feafb41dc99 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -298,21 +298,17 @@ fn empty_line_number(out: &mut impl Write, _: u32, extra: &'static str) { out.write_str(extra).unwrap(); } -fn get_next_expansion<'a>( - expanded_codes: Option<&'a Vec<ExpandedCode>>, +fn get_next_expansion( + expanded_codes: &[ExpandedCode], line: u32, span: Span, -) -> Option<&'a ExpandedCode> { - if let Some(expanded_codes) = expanded_codes { - expanded_codes.iter().find(|code| code.start_line == line && code.span.lo() > span.lo()) - } else { - None - } +) -> Option<&ExpandedCode> { + expanded_codes.iter().find(|code| code.start_line == line && code.span.lo() > span.lo()) } fn get_expansion<'a, W: Write>( token_handler: &mut TokenHandler<'_, '_, W>, - expanded_codes: Option<&'a Vec<ExpandedCode>>, + expanded_codes: &'a [ExpandedCode], line: u32, span: Span, ) -> Option<&'a ExpandedCode> { @@ -356,7 +352,7 @@ fn start_expansion(out: &mut Vec<(Cow<'_, str>, Option<Class>)>, expanded_code: fn end_expansion<'a, W: Write>( token_handler: &mut TokenHandler<'_, '_, W>, - expanded_codes: Option<&'a Vec<ExpandedCode>>, + expanded_codes: &'a [ExpandedCode], expansion_start_tags: &[(&'static str, Class)], line: u32, span: Span, @@ -467,8 +463,8 @@ pub(super) fn write_code( let expanded_codes = c.context.shared.expanded_codes.get(&c.file_span.lo())?; Some((expanded_codes, c.file_span)) }) { - Some((expanded_codes, file_span)) => (Some(expanded_codes), file_span), - None => (None, DUMMY_SP), + Some((expanded_codes, file_span)) => (expanded_codes.as_slice(), file_span), + None => (&[] as &[ExpandedCode], DUMMY_SP), }; let mut current_expansion = get_expansion(&mut token_handler, expanded_codes, line, file_span); token_handler.write_pending_elems(None); @@ -1257,7 +1253,7 @@ fn string<W: Write>( if let Some(Class::Backline(line)) = klass { write_line_number_callback(out, line, "\n"); } else if let Some(Class::Expansion) = klass { - // Nothing to escape here so we get the text to write it directly. + // This has already been escaped so we get the text to write it directly. out.write_str(text.0).unwrap(); } else if let Some(closing_tag) = string_without_closing_tag(out, text, klass, href_context, open_tag) diff --git a/src/librustdoc/html/macro_expansion.rs b/src/librustdoc/html/macro_expansion.rs index d76663a3d1a..9098e92a5cd 100644 --- a/src/librustdoc/html/macro_expansion.rs +++ b/src/librustdoc/html/macro_expansion.rs @@ -45,16 +45,16 @@ pub(crate) struct ExpandedCode { struct ExpandedCodeInfo { /// Callsite of the macro. span: Span, - /// Expanded macro source code. + /// Expanded macro source code (HTML escaped). code: String, - /// Expanded span + /// Span of macro-generated code. expanded_span: Span, } /// HIR visitor which retrieves expanded macro. /// /// Once done, the `expanded_codes` will be transformed into a vec of [`ExpandedCode`] -/// which contains more information needed when running the source code highlighter. +/// which contains the information needed when running the source code highlighter. pub(crate) struct ExpandedCodeVisitor<'ast> { expanded_codes: Vec<ExpandedCodeInfo>, source_map: &'ast SourceMap, @@ -71,7 +71,7 @@ impl<'ast> ExpandedCodeVisitor<'ast> { { let info = &mut self.expanded_codes[index]; if new_span.contains(info.expanded_span) { - // We replace the item. + // New macro expansion recursively contains the old one, so replace it. info.span = callsite_span; info.expanded_span = new_span; info.code = f(); diff --git a/src/librustdoc/html/mod.rs b/src/librustdoc/html/mod.rs index 170449fc033..d42f4782845 100644 --- a/src/librustdoc/html/mod.rs +++ b/src/librustdoc/html/mod.rs @@ -3,8 +3,8 @@ pub(crate) mod format; pub(crate) mod highlight; pub(crate) mod layout; mod length_limit; -// used by the error-index generator, so it needs to be public pub(crate) mod macro_expansion; +// used by the error-index generator, so it needs to be public pub mod markdown; pub(crate) mod render; pub(crate) mod sources; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index fe56fdb2271..d891d1fba25 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -665,6 +665,14 @@ fn opts() -> Vec<RustcOptGroup> { "disable the minification of CSS/JS files (perma-unstable, do not use with cached files)", "", ), + opt( + Unstable, + Flag, + "", + "generate-macro-expansion", + "Add possibility to expand macros in the HTML source code pages", + "", + ), // deprecated / removed options opt( Stable, @@ -706,14 +714,6 @@ fn opts() -> Vec<RustcOptGroup> { "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information", "[rust]", ), - opt( - Unstable, - Flag, - "", - "generate-macro-expansion", - "Add possibility to expand macros in the HTML source code pages", - "", - ), ] } @@ -958,15 +958,7 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { ) }), config::OutputFormat::Json => sess.time("render_json", || { - run_renderer( - krate, - render_opts, - cache, - tcx, - |krate, render_opts, cache, tcx| { - json::JsonRenderer::init(krate, render_opts, cache, tcx) - }, - ) + run_renderer(krate, render_opts, cache, tcx, json::JsonRenderer::init) }), // Already handled above with doctest runners. config::OutputFormat::Doctest => unreachable!(), diff --git a/tests/rustdoc-gui/macro-expansion.goml b/tests/rustdoc-gui/macro-expansion.goml index 5e9a3049405..b87d0e4870a 100644 --- a/tests/rustdoc-gui/macro-expansion.goml +++ b/tests/rustdoc-gui/macro-expansion.goml @@ -28,86 +28,99 @@ define-function: ( ) // First we check the derive macro expansion at line 33. -call-function: ("check-expansion", {"line": 33, "original_content": "Debug"}) +call-function: ("check-expansion", {"line": 35, "original_content": "Debug"}) // Then we check the `bar` macro expansion at line 41. -call-function: ("check-expansion", {"line": 41, "original_content": "bar!(y)"}) +call-function: ("check-expansion", {"line": 43, "original_content": "bar!(y)"}) // Then we check the `println` macro expansion at line 42-44. -call-function: ("check-expansion", {"line": 42, "original_content": 'println!(" -43 {y} -44 ")'}) +call-function: ("check-expansion", {"line": 44, "original_content": 'println!(" +45 {y} +46 ")'}) // Then finally we check when there are two macro calls on a same line. -assert-count: ("#expand-50 ~ .original", 2) -assert-count: ("#expand-50 ~ .expanded", 2) +assert-count: ("#expand-52 ~ .original", 2) +assert-count: ("#expand-52 ~ .expanded", 2) store-value: (repeat_o, '/following-sibling::*[@class="original"]') store-value: (repeat_e, '/following-sibling::*[@class="expanded"]') -assert-text: ('//*[@id="expand-50"]' + |repeat_o|, "stringify!(foo)") -assert-text: ('//*[@id="expand-50"]' + |repeat_o| + |repeat_o|, "stringify!(bar)") -assert-text: ('//*[@id="expand-50"]' + |repeat_e|, '"foo"') -assert-text: ('//*[@id="expand-50"]' + |repeat_e| + |repeat_e|, '"bar"') +store-value: (expand_id, "expand-52") +assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, "stringify!(foo)") +assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, "stringify!(bar)") +assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, '"foo"') +assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, '"bar"') // The "original" content should be expanded. -assert-css: ('//*[@id="expand-50"]' + |repeat_o|, {"display": "inline"}) -assert-css: ('//*[@id="expand-50"]' + |repeat_o| + |repeat_o|, {"display": "inline"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "inline"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "inline"}) // The expanded macro should be hidden. -assert-css: ('//*[@id="expand-50"]' + |repeat_e|, {"display": "none"}) -assert-css: ('//*[@id="expand-50"]' + |repeat_e| + |repeat_e|, {"display": "none"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "none"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "none"}) // We "expand" the macro (because the line starts with a string, the label is not at the "top // level" of the `<code>`, so we need to use a different selector). -click: "#expand-50" +click: "#" + |expand_id| // The "original" content is hidden. -assert-css: ('//*[@id="expand-50"]' + |repeat_o|, {"display": "none"}) -assert-css: ('//*[@id="expand-50"]' + |repeat_o| + |repeat_o|, {"display": "none"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "none"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "none"}) // The expanded macro is visible. -assert-css: ('//*[@id="expand-50"]' + |repeat_e|, {"display": "inline"}) -assert-css: ('//*[@id="expand-50"]' + |repeat_e| + |repeat_e|, {"display": "inline"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "inline"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "inline"}) // We collapse the macro. -click: "#expand-50" +click: "#" + |expand_id| // The "original" content is expanded. -assert-css: ('//*[@id="expand-50"]' + |repeat_o|, {"display": "inline"}) -assert-css: ('//*[@id="expand-50"]' + |repeat_o| + |repeat_o|, {"display": "inline"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "inline"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "inline"}) // The expanded macro is hidden. -assert-css: ('//*[@id="expand-50"]' + |repeat_e|, {"display": "none"}) -assert-css: ('//*[@id="expand-50"]' + |repeat_e| + |repeat_e|, {"display": "none"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "none"}) +assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "none"}) -// Checking the line 46 `println` which needs to be handled differently because the line number is +// Checking the line 48 `println` which needs to be handled differently because the line number is // inside a "comment" span. -assert-text: ("#expand-46 ~ .original", 'println!(" -47 {y} -48 ")') +store-value: (expand_id, "expand-48") +assert-text: ("#" + |expand_id| + " ~ .original", 'println!(" +49 {y} +50 ")') // The "original" content should be expanded. -assert-css: ("#expand-46 ~ .original", {"display": "inline"}) +assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"}) // The expanded macro should be hidden. -assert-css: ("#expand-46 ~ .expanded", {"display": "none"}) +assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"}) // We "expand" the macro. -click: "#expand-46" +click: "#" + |expand_id| // The "original" content is hidden. -assert-css: ("#expand-46 ~ .original", {"display": "none"}) +assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"}) // The expanded macro is visible. -assert-css: ("#expand-46 ~ .expanded", {"display": "inline"}) +assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"}) // We collapse the macro. -click: "#expand-46" +click: "#" + |expand_id| // The "original" content is expanded. -assert-css: ("#expand-46 ~ .original", {"display": "inline"}) +assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"}) // The expanded macro is hidden. -assert-css: ("#expand-46 ~ .expanded", {"display": "none"}) +assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"}) // Ensure that the toggles are focusable and can be interacted with keyboard. -focus: "//a[@id='27']" +focus: "//a[@id='29']" press-key: "Tab" -assert: "#expand-27:focus" -assert-css: ("#expand-27 ~ .expanded", {"display": "none"}) -assert-css: ("#expand-27 ~ .original", {"display": "inline"}) +store-value: (expand_id, "expand-29") +assert: "#" + |expand_id| + ":focus" +assert-css: ("#" + |expand_id| +" ~ .expanded", {"display": "none"}) +assert-css: ("#" + |expand_id| +" ~ .original", {"display": "inline"}) // We now expand the macro. press-key: "Space" -assert-css: ("#expand-27 ~ .expanded", {"display": "inline"}) -assert-css: ("#expand-27 ~ .original", {"display": "none"}) +assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"}) +assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"}) // We collapse the macro. press-key: "Space" -assert-css: ("#expand-27 ~ .expanded", {"display": "none"}) -assert-css: ("#expand-27 ~ .original", {"display": "inline"}) +assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"}) +assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"}) + +// Now we check a macro coming from another file. +store-value: (expand_id, "expand-55") +// We "expand" the macro. +click: "#" + |expand_id| +// The "original" content is hidden. +assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"}) +// The expanded macro is visible. +assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"}) +assert-text: ("#" + |expand_id| + " ~ .expanded", "{ y += 2; };") diff --git a/tests/rustdoc-gui/src/macro_expansion/lib.rs b/tests/rustdoc-gui/src/macro_expansion/lib.rs index 7926e0143d8..62a92d5d15e 100644 --- a/tests/rustdoc-gui/src/macro_expansion/lib.rs +++ b/tests/rustdoc-gui/src/macro_expansion/lib.rs @@ -1,6 +1,8 @@ // Test crate used to check the `--generate-macro-expansion` option. //@ compile-flags: -Zunstable-options --generate-macro-expansion --generate-link-to-definition +mod other; + #[macro_export] macro_rules! bar { ($x:ident) => {{ @@ -48,4 +50,7 @@ fn foo() { "); let s = y_f("\ bla", stringify!(foo), stringify!(bar)); + + // Macro from another file. + other_macro!(y); } diff --git a/tests/rustdoc-gui/src/macro_expansion/other.rs b/tests/rustdoc-gui/src/macro_expansion/other.rs new file mode 100644 index 00000000000..8661b01be38 --- /dev/null +++ b/tests/rustdoc-gui/src/macro_expansion/other.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! other_macro { + ($x:ident) => {{ + $x += 2; + }} +} |
