diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index c37736f137df9..c8dbc8d321002 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -428,6 +428,27 @@ impl<'a, F: Write> TokenHandler<'a, '_, F> { } } } + + /// Used when we're done with the current expansion "original code" (ie code before expansion). + /// We close all tags inside `Class::Original` and only keep the ones that were not closed yet. + fn close_original_tag(&mut self) { + let mut classes_to_reopen = Vec::new(); + while let Some(mut class_info) = self.class_stack.open_classes.pop() { + if class_info.class == Class::Original { + while let Some(class_info) = classes_to_reopen.pop() { + self.class_stack.open_classes.push(class_info); + } + class_info.close_tag(self.out); + return; + } + class_info.close_tag(self.out); + if !class_info.pending_exit { + class_info.closing_tag = None; + classes_to_reopen.push(class_info); + } + } + panic!("Didn't find `Class::Original` to close"); + } } impl Drop for TokenHandler<'_, '_, F> { @@ -476,7 +497,9 @@ fn end_expansion<'a, W: Write>( expanded_codes: &'a [ExpandedCode], span: Span, ) -> Option<&'a ExpandedCode> { - token_handler.class_stack.exit_elem(); + // We close `Class::Original` and everything open inside it. + token_handler.close_original_tag(); + // Then we check if we have another macro expansion on the same line. let expansion = get_next_expansion(expanded_codes, token_handler.line, span); if expansion.is_none() { token_handler.close_expansion(); diff --git a/tests/rustdoc/macro/auxiliary/one-line-expand.rs b/tests/rustdoc/macro/auxiliary/one-line-expand.rs new file mode 100644 index 0000000000000..14df0f2d4f20e --- /dev/null +++ b/tests/rustdoc/macro/auxiliary/one-line-expand.rs @@ -0,0 +1,15 @@ +//@ force-host +//@ no-prefer-dynamic +//@ compile-flags: --crate-type proc-macro + +#![crate_type = "proc-macro"] +#![crate_name = "just_some_proc"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn repro(_args: TokenStream, _input: TokenStream) -> TokenStream { + "struct Repro;".parse().unwrap() +} diff --git a/tests/rustdoc/macro/one-line-expand.rs b/tests/rustdoc/macro/one-line-expand.rs new file mode 100644 index 0000000000000..ceb9521820d61 --- /dev/null +++ b/tests/rustdoc/macro/one-line-expand.rs @@ -0,0 +1,19 @@ +// Regression test for . +// It ensures that the macro expansion correctly handles its "class stack". + +//@ compile-flags: -Zunstable-options --generate-macro-expansion +//@ aux-build:one-line-expand.rs + +#![crate_name = "foo"] + +extern crate just_some_proc; + +//@ has 'src/foo/one-line-expand.rs.html' +//@ has - '//*[@class="comment"]' '//' +//@ has - '//*[@class="original"]' '#[just_some_proc::repro]' +//@ has - '//*[@class="original"]/*[@class="attr"]' '#[just_some_proc::repro]' +//@ has - '//code/*[@class="kw"]' 'struct ' + +// +#[just_some_proc::repro] +struct Repro;