-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Pretty-print macro matchers instead of using source code #86282
Conversation
r? @ollie27 (rust-highfive has picked a reviewer for you, use r? to override) |
r? @jyn514 (feel free to reassign) |
Beta-nominating because this fixes a |
I left some comments in the commit messages too, so they may be helpful to read. |
656da0c
to
87e0452
Compare
// @has 'foo/macro.todo.html' | ||
// @has - '//span[@class="macro"]' 'macro_rules!' | ||
// @has - '//span[@class="ident"]' 'todo' | ||
// Note: count = 2 * ('=' + '>') + '+' = 2 * (1 + 1) + 1 = 5 | ||
// @count - '//pre[@class="rust macro"]//span[@class="op"]' 5 | ||
|
||
// @has - '{ ()' | ||
// @has - '//span[@class="op"]' '=' | ||
// @has - '//span[@class="op"]' '>' | ||
// @has - '{ ... };' | ||
|
||
// @has - '($ ($' | ||
// @has - '//span[@class="ident"]' 'arg' | ||
// @has - ':' | ||
// @has - '//span[@class="ident"]' 'tt' | ||
// @has - '//span[@class="op"]' '+' | ||
// @has - ')' |
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.
Do you know of a way to do a @has
check that matches on the innerText
of an element (in this case, <pre class="rust macro">
) to avoid having so many individual checks?
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 don't, @GuillaumeGomez may.
Actually my understanding is that is always used innerText, are you sure doing it the obvious way doesn't work?
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.
Just like @jyn514 said. The problem might be that the text doesn't "look like" what you might expect but that's it. :)
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 had tried something like @has - 'macro_rules! todo {'
and it failed; maybe I need to explicitly specify //pre
? I also had this issue in #83501 where @has - 'Size: 1 byte'
didn't work because Size:
was wrapped with <b>
.
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.
Ah! Maybe try with //text()
at the end.
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.
Hmm, it doesn't seem to be working. //text()
by itself gave this error:
27: Non-absolute XPath is not supported due to implementation issues
// @has - '//text()' 'macro_rules! macro1 {'
28: Non-absolute XPath is not supported due to implementation issues
// @has - '//text()' '() => { ... };'
29: Non-absolute XPath is not supported due to implementation issues
// @has - '//text()' '$ ($ arg : expr), +) => { ... };'
30: Non-absolute XPath is not supported due to implementation issues
// @has - '//text()' '}'
Encountered 4 errors
and //pre//text()
gave this:
27: @has check failed
`XPATH PATTERN` did not match
// @has - '//pre//text()' 'macro_rules! macro1 {'
28: @has check failed
`XPATH PATTERN` did not match
// @has - '//pre//text()' '() => { ... };'
29: @has check failed
`XPATH PATTERN` did not match
// @has - '//pre//text()' '$ ($ arg : expr), +) => { ... };'
30: @has check failed
`XPATH PATTERN` did not match
// @has - '//pre//text()' '}'
Encountered 4 errors
I also tried //pre///text()
(extra slash), but that didn't work either.
This comment has been minimized.
This comment has been minimized.
87e0452
to
391233e
Compare
I figured out a way to print the matchers in a prettier way, but it may have edge cases that I'm not aware of. Here's the new output: And here's what the code looks like: pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String {
match matcher {
TokenTree::Token(tok) => rustc_ast_pretty::pprust::token_to_string(tok),
TokenTree::Delimited(_span, delim_tok, stream) => {
let open_tok = Token::new(token::OpenDelim(*delim_tok), DUMMY_SP);
let close_tok = Token::new(token::CloseDelim(*delim_tok), DUMMY_SP);
format!(
"{}{}{}",
rustc_ast_pretty::pprust::token_to_string(&open_tok),
stream.trees().map(|tt| render_macro_matcher(&tt)).collect::<String>(),
rustc_ast_pretty::pprust::token_to_string(&close_tok)
)
}
}
} |
This comment has been minimized.
This comment has been minimized.
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 figured out a way to print the matchers in a prettier way, but it may have edge cases that I'm not aware of.
I don't think rustdoc's pretty print should behave differently from rustc's. Can you change this in rustc_ast_pretty instead? It should be easier there because these already have to be handled.
src/librustdoc/clean/utils.rs
Outdated
matchers | ||
.iter() | ||
.map(|matcher| format!(" {} => {{ ... }};\n", render_macro_matcher(matcher))) | ||
.collect::<String>() |
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.
Rather than allocating a new string for each arm, can you use a for loop and push_str?
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 changed it to use writeln!
, which I think should generate code fairly similar to push_str
, but is more readable.
/// as part of an item declaration. | ||
pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String { | ||
rustc_ast_pretty::pprust::tt_to_string(matcher) | ||
} |
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.
Why have this as a separate function? Just use tt_to_string.
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.
We may not use tt_to_string
in the future, or we may have additional logic, so I'd rather err on the side of having an extra function. But I can remove it if you prefer.
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.
Please remove it until and unless we add more logic.
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.
Actually, render_macro_matcher
is used in another place, for rendering macros 2.0. I'd really rather keep it so there aren't multiple places to update later on.
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 don't understand why you think this would ever change. Rustdoc uses rustc in lots of places, it doesn't make sense to wrap every single one in our own function.
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.
Oh I see, this is the function you mentioned above for removing the whitespace in the matcher. I think we should keep the function if we keep your special-casing, and remove it if not. And I do like that the special-casing makes it prettier. So I guess I'm in favor of keeping it.
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.
See also the discussion in rust-lang/compiler-team#403
// @has 'foo/macro.todo.html' | ||
// @has - '//span[@class="macro"]' 'macro_rules!' | ||
// @has - '//span[@class="ident"]' 'todo' | ||
// Note: count = 2 * ('=' + '>') + '+' = 2 * (1 + 1) + 1 = 5 | ||
// @count - '//pre[@class="rust macro"]//span[@class="op"]' 5 | ||
|
||
// @has - '{ ()' | ||
// @has - '//span[@class="op"]' '=' | ||
// @has - '//span[@class="op"]' '>' | ||
// @has - '{ ... };' | ||
|
||
// @has - '($ ($' | ||
// @has - '//span[@class="ident"]' 'arg' | ||
// @has - ':' | ||
// @has - '//span[@class="ident"]' 'tt' | ||
// @has - '//span[@class="op"]' '+' | ||
// @has - ')' |
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 don't, @GuillaumeGomez may.
Actually my understanding is that is always used innerText, are you sure doing it the obvious way doesn't work?
The problem is that they aren't already handled. For example, this is what
From what I can tell, it just puts a space after every token, which is why the output is not so great: match tt {
TokenTree::Token(token) => {
let token_str = self.token_to_string_ext(&token, convert_dollar_crate);
self.word(token_str);
if let token::DocComment(..) = token.kind {
self.hardbreak()
}
}
// ... So I don't think it would be easier to change in |
Yeah, I realized that a backport into 1.53 wouldn't make sense, but I left the label on since this will likely land in 1.55 and need to be backported to 1.54. Should I just wait until 1.53 is released before adding the label back? |
I do not think it should be backported to 1.54 either; it is merely fixing a (seemingly to me) minor bug, and not patching a beta regression. |
@Mark-Simulacrum it is a beta regression (stable now; it broke in 1.53), but for something that has been broken and fixed several times in the past. |
This comment has been minimized.
This comment has been minimized.
I think the problem is that For example, this code: fn main() {
println!("{}", stringify!($foo));
} produces the following on nightly:
but produces this instead after this PR:
|
It seems fine to omit the space after
It's not a problem, similar changes were done to the pretty-printer quite often in the past, r? @jyn514 |
@bors r+ |
📌 Commit 7ffec70 has been approved by |
☀️ Test successful - checks-actions |
…uillaumeGomez rustdoc: Preserve rendering of macro_rules matchers when possible Fixes rust-lang#92331. This approach restores the behavior prior to rust-lang#86282 **if** the matcher token held by the compiler **and** the matcher token found in the source code are identical TokenTrees. Thus rust-lang#86208 remains fixed, but without regressing formatting for the vast majority of macros which are not macro-generated.
…uillaumeGomez rustdoc: Preserve rendering of macro_rules matchers when possible Fixes rust-lang#92331. This approach restores the behavior prior to rust-lang#86282 **if** the matcher token held by the compiler **and** the matcher token found in the source code are identical TokenTrees. Thus rust-lang#86208 remains fixed, but without regressing formatting for the vast majority of macros which are not macro-generated.
…uillaumeGomez rustdoc: Preserve rendering of macro_rules matchers when possible Fixes rust-lang#92331. This approach restores the behavior prior to rust-lang#86282 **if** the matcher token held by the compiler **and** the matcher token found in the source code are identical TokenTrees. Thus rust-lang#86208 remains fixed, but without regressing formatting for the vast majority of macros which are not macro-generated.
…uillaumeGomez rustdoc: Preserve rendering of macro_rules matchers when possible Fixes rust-lang#92331. This approach restores the behavior prior to rust-lang#86282 **if** the matcher token held by the compiler **and** the matcher token found in the source code are identical TokenTrees. Thus rust-lang#86208 remains fixed, but without regressing formatting for the vast majority of macros which are not macro-generated.
…uillaumeGomez rustdoc: Preserve rendering of macro_rules matchers when possible Fixes rust-lang#92331. This approach restores the behavior prior to rust-lang#86282 **if** the matcher token held by the compiler **and** the matcher token found in the source code are identical TokenTrees. Thus rust-lang#86208 remains fixed, but without regressing formatting for the vast majority of macros which are not macro-generated.
…uillaumeGomez rustdoc: Preserve rendering of macro_rules matchers when possible Fixes rust-lang#92331. This approach restores the behavior prior to rust-lang#86282 **if** the matcher token held by the compiler **and** the matcher token found in the source code are identical TokenTrees. Thus rust-lang#86208 remains fixed, but without regressing formatting for the vast majority of macros which are not macro-generated.
Fixes #86208.