Skip to content

Commit 809200e

Browse files
committed
Auto merge of #137229 - GuillaumeGomez:expand-macro, r=lolbinarycat
Add support for macro expansion in rustdoc source code pages This is what it looks like: ![Screenshot From 2025-02-18 18-08-51](https://github.com/user-attachments/assets/ce2b3806-6218-47df-94bf-e9e9ed40cd41) ![image](https://github.com/user-attachments/assets/891042db-8632-4dba-9343-e28570c058fe) You can test it [here](https://rustdoc.crud.net/imperio/macro-expansion/src/lib/lib.rs.html). In this case, I also enabled the `--generate-link-to-definition` to show that both options work well together. Note: <del>There is a bug currently in firefox where the line numbers are not displayed correctly if they're inside the "macro expansion" span: https://bugzilla.mozilla.org/show_bug.cgi?id=1949948<del> Found a workaround around this bug. r? `@notriddle`
2 parents 3776358 + d0913c5 commit 809200e

File tree

21 files changed

+795
-93
lines changed

21 files changed

+795
-93
lines changed

src/doc/rustdoc/src/unstable-features.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,3 +796,7 @@ will be split as follows:
796796
"you today?",
797797
]
798798
```
799+
800+
## `--generate-macro-expansion`: Generate macros expansion toggles in source code
801+
802+
This flag enables the generation of toggles to expand macros in the HTML source code pages.

src/librustdoc/config.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ pub(crate) struct RenderOptions {
305305
pub(crate) parts_out_dir: Option<PathToParts>,
306306
/// disable minification of CSS/JS
307307
pub(crate) disable_minification: bool,
308+
/// If `true`, HTML source pages will generate the possibility to expand macros.
309+
pub(crate) generate_macro_expansion: bool,
308310
}
309311

310312
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -786,6 +788,7 @@ impl Options {
786788
let show_type_layout = matches.opt_present("show-type-layout");
787789
let nocapture = matches.opt_present("nocapture");
788790
let generate_link_to_definition = matches.opt_present("generate-link-to-definition");
791+
let generate_macro_expansion = matches.opt_present("generate-macro-expansion");
789792
let extern_html_root_takes_precedence =
790793
matches.opt_present("extern-html-root-takes-precedence");
791794
let html_no_source = matches.opt_present("html-no-source");
@@ -801,6 +804,13 @@ impl Options {
801804
.with_note("`--generate-link-to-definition` option will be ignored")
802805
.emit();
803806
}
807+
if generate_macro_expansion && (show_coverage || output_format != OutputFormat::Html) {
808+
dcx.struct_warn(
809+
"`--generate-macro-expansion` option can only be used with HTML output format",
810+
)
811+
.with_note("`--generate-macro-expansion` option will be ignored")
812+
.emit();
813+
}
804814

805815
let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
806816
let with_examples = matches.opt_strs("with-examples");
@@ -881,6 +891,7 @@ impl Options {
881891
unstable_features,
882892
emit,
883893
generate_link_to_definition,
894+
generate_macro_expansion,
884895
call_locations,
885896
no_emit_shared: false,
886897
html_no_source,

src/librustdoc/core.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::clean::inline::build_trait;
3131
use crate::clean::{self, ItemId};
3232
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
3333
use crate::formats::cache::Cache;
34+
use crate::html::macro_expansion::{ExpandedCode, source_macro_expansion};
3435
use crate::passes;
3536
use crate::passes::Condition::*;
3637
use crate::passes::collect_intra_doc_links::LinkCollector;
@@ -334,11 +335,19 @@ pub(crate) fn run_global_ctxt(
334335
show_coverage: bool,
335336
render_options: RenderOptions,
336337
output_format: OutputFormat,
337-
) -> (clean::Crate, RenderOptions, Cache) {
338+
) -> (clean::Crate, RenderOptions, Cache, FxHashMap<rustc_span::BytePos, Vec<ExpandedCode>>) {
338339
// Certain queries assume that some checks were run elsewhere
339340
// (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
340341
// so type-check everything other than function bodies in this crate before running lints.
341342

343+
let expanded_macros = {
344+
// We need for these variables to be removed to ensure that the `Crate` won't be "stolen"
345+
// anymore.
346+
let (_resolver, krate) = &*tcx.resolver_for_lowering().borrow();
347+
348+
source_macro_expansion(&krate, &render_options, output_format, tcx.sess.source_map())
349+
};
350+
342351
// NOTE: this does not call `tcx.analysis()` so that we won't
343352
// typeck function bodies or run the default rustc lints.
344353
// (see `override_queries` in the `config`)
@@ -448,7 +457,7 @@ pub(crate) fn run_global_ctxt(
448457

449458
tcx.dcx().abort_if_errors();
450459

451-
(krate, ctxt.render_options, ctxt.cache)
460+
(krate, ctxt.render_options, ctxt.cache, expanded_macros)
452461
}
453462

454463
/// Due to <https://github.com/rust-lang/rust/pull/73566>,

src/librustdoc/formats/renderer.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,6 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
3131
/// reset the information between each call to `item` by using `restore_module_data`.
3232
type ModuleData;
3333

34-
/// Sets up any state required for the renderer. When this is called the cache has already been
35-
/// populated.
36-
fn init(
37-
krate: clean::Crate,
38-
options: RenderOptions,
39-
cache: Cache,
40-
tcx: TyCtxt<'tcx>,
41-
) -> Result<(Self, clean::Crate), Error>;
42-
4334
/// This method is called right before call [`Self::item`]. This method returns a type
4435
/// containing information that needs to be reset after the [`Self::item`] method has been
4536
/// called with the [`Self::restore_module_data`] method.
@@ -105,18 +96,23 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
10596
}
10697

10798
/// Main method for rendering a crate.
108-
pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
99+
pub(crate) fn run_format<
100+
'tcx,
101+
T: FormatRenderer<'tcx>,
102+
F: FnOnce(clean::Crate, RenderOptions, Cache, TyCtxt<'tcx>) -> Result<(T, clean::Crate), Error>,
103+
>(
109104
krate: clean::Crate,
110105
options: RenderOptions,
111106
cache: Cache,
112107
tcx: TyCtxt<'tcx>,
108+
init: F,
113109
) -> Result<(), Error> {
114110
let prof = &tcx.sess.prof;
115111

116112
let emit_crate = options.should_emit_crate();
117113
let (mut format_renderer, krate) = prof
118114
.verbose_generic_activity_with_arg("create_renderer", T::descr())
119-
.run(|| T::init(krate, options, cache, tcx))?;
115+
.run(|| init(krate, options, cache, tcx))?;
120116

121117
if !emit_crate {
122118
return Ok(());

0 commit comments

Comments
 (0)