Add metavariables to TokenDescription
.
Pasted metavariables are wrapped in invisible delimiters, which pretty-print as empty strings, and changing that can break some proc macros. But error messages saying "expected identifer, found ``" are bad. So this commit adds support for metavariables in `TokenDescription` so they print as "metavariable" in error messages, instead of "``". It's not used meaningfully yet, but will be needed to get rid of interpolated tokens.
This commit is contained in:
parent
afe238f66f
commit
cfafa9380b
3 changed files with 58 additions and 16 deletions
|
@ -21,7 +21,9 @@ pub(crate) use item::FnParseMode;
|
|||
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
||||
use path::PathStyle;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
|
||||
use rustc_ast::token::{
|
||||
self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, Token, TokenKind,
|
||||
};
|
||||
use rustc_ast::tokenstream::{
|
||||
AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor,
|
||||
};
|
||||
|
@ -410,6 +412,12 @@ pub(super) enum TokenDescription {
|
|||
Keyword,
|
||||
ReservedKeyword,
|
||||
DocComment,
|
||||
|
||||
// Expanded metavariables are wrapped in invisible delimiters which aren't
|
||||
// pretty-printed. In error messages we must handle these specially
|
||||
// otherwise we get confusing things in messages like "expected `(`, found
|
||||
// ``". It's better to say e.g. "expected `(`, found type metavariable".
|
||||
MetaVar(MetaVarKind),
|
||||
}
|
||||
|
||||
impl TokenDescription {
|
||||
|
@ -419,26 +427,29 @@ impl TokenDescription {
|
|||
_ if token.is_used_keyword() => Some(TokenDescription::Keyword),
|
||||
_ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword),
|
||||
token::DocComment(..) => Some(TokenDescription::DocComment),
|
||||
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => {
|
||||
Some(TokenDescription::MetaVar(kind))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn token_descr(token: &Token) -> String {
|
||||
let name = pprust::token_to_string(token).to_string();
|
||||
let s = pprust::token_to_string(token).to_string();
|
||||
|
||||
let kind = match (TokenDescription::from_token(token), &token.kind) {
|
||||
(Some(TokenDescription::ReservedIdentifier), _) => Some("reserved identifier"),
|
||||
(Some(TokenDescription::Keyword), _) => Some("keyword"),
|
||||
(Some(TokenDescription::ReservedKeyword), _) => Some("reserved keyword"),
|
||||
(Some(TokenDescription::DocComment), _) => Some("doc comment"),
|
||||
(None, TokenKind::NtIdent(..)) => Some("identifier"),
|
||||
(None, TokenKind::NtLifetime(..)) => Some("lifetime"),
|
||||
(None, TokenKind::Interpolated(node)) => Some(node.descr()),
|
||||
(None, _) => None,
|
||||
};
|
||||
|
||||
if let Some(kind) = kind { format!("{kind} `{name}`") } else { format!("`{name}`") }
|
||||
match (TokenDescription::from_token(token), &token.kind) {
|
||||
(Some(TokenDescription::ReservedIdentifier), _) => format!("reserved identifier `{s}`"),
|
||||
(Some(TokenDescription::Keyword), _) => format!("keyword `{s}`"),
|
||||
(Some(TokenDescription::ReservedKeyword), _) => format!("reserved keyword `{s}`"),
|
||||
(Some(TokenDescription::DocComment), _) => format!("doc comment `{s}`"),
|
||||
// Deliberately doesn't print `s`, which is empty.
|
||||
(Some(TokenDescription::MetaVar(kind)), _) => format!("`{kind}` metavariable"),
|
||||
(None, TokenKind::NtIdent(..)) => format!("identifier `{s}`"),
|
||||
(None, TokenKind::NtLifetime(..)) => format!("lifetime `{s}`"),
|
||||
(None, TokenKind::Interpolated(node)) => format!("{} `{s}`", node.descr()),
|
||||
(None, _) => format!("`{s}`"),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue