-
Notifications
You must be signed in to change notification settings - Fork 14k
rustdoc: add support for macro_rules macros of multiple kinds #148005
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This adds support for advanced RFC 3697 and 3698 macros, that look
like this:
```
/// Doc Comment.
macro_rules! NAME {
attr(key = $value:literal) ($attached:item) => { ... };
derive() ($attached:item) => { ... };
($bang:tt) => { ... };
}
```
And can be used like this:
```
/*attr*/ #[NAME]
/*derive*/ #[derive(NAME)]
/*bang*/ NAME!{}
```
The basic problem is that there are three different ways to use
this macro, and, historically, these three ways were implemented
by fully-separated proc macro items with separate doc comments.
We want these new declarative macros to work the same way,
so they appear in the same section of the module table of contents
and can be filtered for in the search engine.
This commit makes the feature work by generating separate pages
for each macro kind. These separate pages appear in separate
sections of the module table of contents, produce separate
search results, and have duplicate copies of the doc comment.
The following features would also be helpful, but are left
for future commits to implement:
- To improve the produced documentation, we should probably add
support for adding `///` attributes to macro rules arms, so that
the different syntaxes can actually be documented separately.
- This commit doesn't test intra-doc links.
Parts of rust-lang#145458 are directly
used in this code.
Co-Authored-By: Guillaume Gomez <[email protected]>
|
Although I find the result of this approach less good (ie, duplicated files generated for the same macro), considering how much easier the implementation is, I'd prefer for this one to be merged. I'll close #145458. |
|
Btw, the PR looks ready to me so feel free to r=me unless you want to make more changes. |
|
rustdoc-json-types is a public (although nightly-only) API. If possible, consider changing cc @CraftSpider, @aDotInTheVoid, @Enselic, @obi1kenobi Some changes occurred in GUI tests. Some changes occurred in HTML/CSS/JS. |
|
rustbot has assigned @GuillaumeGomez. Use |
|
I know you have already looked at the code a little bit. Can you check it and make sure I'm using the bitflags correctly? |
…triddle [rustdoc] Include attribute and derive macros when filtering on "macros" As discussed [here](rust-lang#147909), some filters should have been "grouped". This PR allows attribute and derive macros to match the `macro` filter. I'll wait for rust-lang#148005 to add more tests as it would require a proc-macro library for now. r? `@notriddle`
…triddle [rustdoc] Include attribute and derive macros when filtering on "macros" As discussed [here](rust-lang#147909), some filters should have been "grouped". This PR allows attribute and derive macros to match the `macro` filter. I'll wait for rust-lang#148005 to add more tests as it would require a proc-macro library for now. r? ``@notriddle``
…triddle [rustdoc] Include attribute and derive macros when filtering on "macros" As discussed [here](rust-lang#147909), some filters should have been "grouped". This PR allows attribute and derive macros to match the `macro` filter. I'll wait for rust-lang#148005 to add more tests as it would require a proc-macro library for now. r? ```@notriddle```
Rollup merge of #148176 - GuillaumeGomez:filter-macros, r=notriddle [rustdoc] Include attribute and derive macros when filtering on "macros" As discussed [here](#147909), some filters should have been "grouped". This PR allows attribute and derive macros to match the `macro` filter. I'll wait for #148005 to add more tests as it would require a proc-macro library for now. r? ```@notriddle```
[rustdoc] Include attribute and derive macros when filtering on "macros" As discussed [here](rust-lang/rust#147909), some filters should have been "grouped". This PR allows attribute and derive macros to match the `macro` filter. I'll wait for rust-lang/rust#148005 to add more tests as it would require a proc-macro library for now. r? ```@notriddle```
| unreachable!("Iterating over macro kinds always yields one kind at a time") | ||
| } | ||
| }; | ||
| record_extern_fqn(cx, did, type_kind); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have a comment noting the fact that we create multiple (pages? search index entries? something else?) for macros that are of multiple kinds, since it's a somewhat unexpected behavior.
| match mac_kind { | ||
| MacroKinds::BANG => MacroKind::Bang, | ||
| MacroKinds::ATTR => MacroKind::Attr, | ||
| MacroKinds::DERIVE => MacroKind::Derive, | ||
| _ => unreachable!( | ||
| "Iterating over macro kinds always yields one kind at a time" | ||
| ), | ||
| }, | ||
| ); | ||
| let type_kind = match mac_kind { | ||
| MacroKinds::BANG => ItemType::Macro, | ||
| MacroKinds::ATTR => ItemType::MacroAttribute, | ||
| MacroKinds::DERIVE => ItemType::MacroDerive, | ||
| _ => { | ||
| unreachable!("Iterating over macro kinds always yields one kind at a time") | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: These two match statements could be merged into one that returns a tuple.
| DefKind::Macro(kinds) if kinds == MacroKinds::ATTR | MacroKinds::DERIVE => { | ||
| &[ItemType::MacroAttribute, ItemType::MacroDerive] | ||
| } | ||
| DefKind::Macro(kinds) if kinds == MacroKinds::ATTR | MacroKinds::BANG => { | ||
| &[ItemType::Macro, ItemType::MacroAttribute] | ||
| } | ||
| DefKind::Macro(kinds) if kinds == MacroKinds::DERIVE | MacroKinds::BANG => { | ||
| &[ItemType::Macro, ItemType::MacroDerive] | ||
| } | ||
| DefKind::Macro(kinds) | ||
| if kinds == MacroKinds::BANG | MacroKinds::ATTR | MacroKinds::DERIVE => | ||
| { | ||
| &[ItemType::Macro, ItemType::MacroAttribute, ItemType::MacroDerive] | ||
| } | ||
| DefKind::Macro(kinds) => unimplemented!("unsupported macro kinds {kinds:?}"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code like this makes me really wish we were using enumset instead.
|
|
||
| let def_kind = tcx.def_kind(def_id); | ||
| let shortty = def_kind.into(); | ||
| let shortty = ItemType::from_def_kind(def_kind, None)[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that href_with_root_path will always link to the same page, regardless of context, is this what we want?
|
@rustbot author |
|
Reminder, once the PR becomes ready for a review, use |
|
(Asking with my Am I correct in understanding that with this PR:
This is somewhat undesirable, because it worsens It's not a breaking change to move procedural derive macro to a declarative derive macro, of course. However:
If it's not a huge lift to do so, it'd be nice to include this information in rustdoc JSON. I'd be happy to review and offer feedback if that'd be helpful. |
|
@obi1kenobi maybe a naive question, but can't you just check if the source crate is a proc_macro crate? or does inlining mess with that? |
|
Honestly, I'm not sure. But I imagine most consumers of rustdoc JSON would want to show users accurate diagnostics on where the item came from, and "here's this one weird trick that works but isn't that discoverable" isn't a great story to tell all of them :) If it's truly that easy, it feels like it's even more of an argument to just include a flag or similar in the JSON. |
…triddle [rustdoc] Include attribute and derive macros when filtering on "macros" As discussed [here](rust-lang#147909), some filters should have been "grouped". This PR allows attribute and derive macros to match the `macro` filter. I'll wait for rust-lang#148005 to add more tests as it would require a proc-macro library for now. r? ```@notriddle```
…triddle [rustdoc] Include attribute and derive macros when filtering on "macros" As discussed [here](rust-lang#147909), some filters should have been "grouped". This PR allows attribute and derive macros to match the `macro` filter. I'll wait for rust-lang#148005 to add more tests as it would require a proc-macro library for now. r? ```@notriddle```
[rustdoc] Include attribute and derive macros when filtering on "macros" As discussed [here](rust-lang/rust#147909), some filters should have been "grouped". This PR allows attribute and derive macros to match the `macro` filter. I'll wait for rust-lang/rust#148005 to add more tests as it would require a proc-macro library for now. r? ```@notriddle```
As far as I can tell, the only change to the clean->JSON conversion is these lines: diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 909262d563e9f..b57f27f529738 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -892,8 +892,8 @@ impl FromClean<ItemType> for ItemKind {
Keyword => ItemKind::Keyword,
Attribute => ItemKind::Attribute,
TraitAlias => ItemKind::TraitAlias,
- ProcAttribute => ItemKind::ProcAttribute,
- ProcDerive => ItemKind::ProcDerive,
+ MacroAttribute => ItemKind::ProcAttribute,
+ MacroDerive => ItemKind::ProcDerive,
}
}
}The code that generates ItemEnum wasn't changed, so the proc macros and declarative macros should still be distinguishable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broadly LGTM, just some polishing suggestions.
| /// or `ItemEnum::ProcMacro(ProcMacro { kind: MacroKind::Bang })` | ||
| Macro, | ||
| /// A procedural macro attribute. | ||
| /// A macro attribute. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed procedural was deleted here, but was not deleted below in the doc comment for ProcDerive. I found that surprising, is that intentional?
| /// An attribute bang macro. | ||
| #[macro_export] | ||
| macro_rules! attr_macro { | ||
| attr() () => {}; | ||
| () => {}; | ||
| } | ||
|
|
||
| /// An attribute bang macro. | ||
| #[macro_export] | ||
| macro_rules! derive_macro { | ||
| derive() () => {}; | ||
| () => {}; | ||
| } | ||
|
|
||
| #[macro_export] | ||
| macro_rules! one_for_all_macro { | ||
| attr() () => {}; | ||
| derive() () => {}; | ||
| () => {}; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great! Would you mind adding a similar test to tests/rustdoc-json, just to make it super obvious how these macros are represented?
Happy to help if you get stuck on the syntax for the checks.
| /// and `ItemEnum::Macro(_)`; this should probably be renamed. | ||
| ProcAttribute, | ||
| /// A procedural macro usable in the `#[derive()]` attribute. | ||
| /// | ||
| /// Corresponds to `ItemEnum::ProcMacro(ProcMacro { kind: MacroKind::Derive })` | ||
| /// and `ItemEnum::Macro(_)`; this should probably be renamed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My 2 cents: go ahead and rename them right now. There's no time like the present, and there's no stability guarantee to worry about in rustdoc JSON. The format is versioned anyway.
Speaking of, remember to bump the version number :)
This adds support for advanced RFC 3697 and 3698 macros, that look like this:
And can be used like this:
The basic problem is that there are three different ways to use this macro, and, historically, these three ways were implemented by fully-separated proc macro items with separate doc comments. We want these new declarative macros to work the same way, so they appear in the same section of the module table of contents and can be filtered for in the search engine.
This commit makes the feature work by generating separate pages for each macro kind. These separate pages appear in separate sections of the module table of contents, produce separate search results, and have duplicate copies of the doc comment.
The following features would also be helpful, but are left for future commits to implement:
To improve the produced documentation, we should probably add support for adding
///attributes to macro rules arms, so that the different syntaxes can actually be documented separately.This commit doesn't test intra-doc links.
Parts of #145458 are directly used in this code.
cc @joshtriplett @GuillaumeGomez @lolbinarycat