mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Implement ${count()}
metavariable expression
This commit is contained in:
parent
9ebaa85d37
commit
0d4d1d7e3b
7 changed files with 389 additions and 29 deletions
|
@ -52,7 +52,8 @@ impl MetaTemplate {
|
|||
pub(crate) enum Op {
|
||||
Var { name: SmolStr, kind: Option<MetaVarKind>, id: tt::TokenId },
|
||||
Ignore { name: SmolStr, id: tt::TokenId },
|
||||
Index { depth: u32 },
|
||||
Index { depth: usize },
|
||||
Count { name: SmolStr, depth: Option<usize> },
|
||||
Repeat { tokens: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
|
||||
Subtree { tokens: MetaTemplate, delimiter: tt::Delimiter },
|
||||
Literal(tt::Literal),
|
||||
|
@ -295,9 +296,13 @@ fn parse_metavar_expr(src: &mut TtIter<'_>) -> Result<Op, ()> {
|
|||
let ident = args.expect_ident()?;
|
||||
Op::Ignore { name: ident.text.clone(), id: ident.span }
|
||||
}
|
||||
"index" => {
|
||||
let depth = if args.len() == 0 { 0 } else { args.expect_u32_literal()? };
|
||||
Op::Index { depth }
|
||||
"index" => Op::Index { depth: parse_depth(&mut args)? },
|
||||
"count" => {
|
||||
let ident = args.expect_ident()?;
|
||||
// `${count(t)}` and `${count(t,)}` have different meanings. Not sure if this is a bug
|
||||
// but that's how it's implemented in rustc as of this writing. See rust-lang/rust#111904.
|
||||
let depth = if try_eat_comma(&mut args) { Some(parse_depth(&mut args)?) } else { None };
|
||||
Op::Count { name: ident.text.clone(), depth }
|
||||
}
|
||||
_ => return Err(()),
|
||||
};
|
||||
|
@ -308,3 +313,22 @@ fn parse_metavar_expr(src: &mut TtIter<'_>) -> Result<Op, ()> {
|
|||
|
||||
Ok(op)
|
||||
}
|
||||
|
||||
fn parse_depth(src: &mut TtIter<'_>) -> Result<usize, ()> {
|
||||
if src.len() == 0 {
|
||||
Ok(0)
|
||||
} else if let tt::Leaf::Literal(lit) = src.expect_literal()? {
|
||||
// Suffixes are not allowed.
|
||||
lit.text.parse().map_err(|_| ())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
fn try_eat_comma(src: &mut TtIter<'_>) -> bool {
|
||||
if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', .. }))) = src.peek_n(0) {
|
||||
let _ = src.next();
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue