Skip to content

Commit 75d2e9c

Browse files
Fix parsing of format_args!("...", keyword=...)
1 parent 4eed808 commit 75d2e9c

11 files changed

Lines changed: 127 additions & 30 deletions

File tree

crates/hir-def/src/expr_store/lower/format_args.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
//! Lowering of `format_args!()`.
22
33
use base_db::FxIndexSet;
4-
use hir_expand::name::{AsName, Name};
4+
use hir_expand::name::Name;
55
use intern::{Symbol, sym};
6-
use syntax::{
7-
AstPtr, AstToken as _,
8-
ast::{self, HasName},
9-
};
6+
use syntax::{AstPtr, AstToken as _, ast};
107

118
use crate::{
129
builtin_type::BuiltinUint,
@@ -32,8 +29,8 @@ impl<'db> ExprCollector<'db> {
3229
let mut args = FormatArgumentsCollector::default();
3330
f.args().for_each(|arg| {
3431
args.add(FormatArgument {
35-
kind: match arg.name() {
36-
Some(name) => FormatArgumentKind::Named(name.as_name()),
32+
kind: match arg.arg_name() {
33+
Some(name) => FormatArgumentKind::Named(Name::new_root(name.name().text())),
3734
None => FormatArgumentKind::Normal,
3835
},
3936
expr: self.collect_expr_opt(arg.expr()),

crates/ide/src/syntax_highlighting/test_data/highlight_strings.html

Lines changed: 11 additions & 11 deletions
Large diffs are not rendered by default.

crates/parser/src/grammar/expressions/atom.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,20 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
278278
}
279279
Some(m.complete(p, OFFSET_OF_EXPR))
280280
} else if p.eat_contextual_kw(T![format_args]) {
281+
// test format_args_named_arg_keyword
282+
// fn main() {
283+
// builtin#format_args("{type}", type=1);
284+
// }
281285
p.expect(T!['(']);
282286
expr(p);
283287
if p.eat(T![,]) {
284288
while !p.at(EOF) && !p.at(T![')']) {
285289
let m = p.start();
286-
if p.at(IDENT) && p.nth_at(1, T![=]) && !p.nth_at(2, T![=]) {
287-
name(p);
290+
if p.current().is_any_identifier() && p.nth_at(1, T![=]) && !p.nth_at(2, T![=]) {
291+
let m = p.start();
292+
p.bump_any();
288293
p.bump(T![=]);
294+
m.complete(p, FORMAT_ARGS_ARG_NAME);
289295
}
290296
if expr(p).is_none() {
291297
m.abandon(p);

crates/parser/src/syntax_kind/generated.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ pub enum SyntaxKind {
201201
FN,
202202
FN_PTR_TYPE,
203203
FORMAT_ARGS_ARG,
204+
FORMAT_ARGS_ARG_NAME,
204205
FORMAT_ARGS_EXPR,
205206
FOR_BINDER,
206207
FOR_EXPR,
@@ -373,6 +374,7 @@ impl SyntaxKind {
373374
| FN
374375
| FN_PTR_TYPE
375376
| FORMAT_ARGS_ARG
377+
| FORMAT_ARGS_ARG_NAME
376378
| FORMAT_ARGS_EXPR
377379
| FOR_BINDER
378380
| FOR_EXPR

crates/parser/test_data/generated/runner.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ mod ok {
265265
#[test]
266266
fn for_type() { run_and_expect_no_errors("test_data/parser/inline/ok/for_type.rs"); }
267267
#[test]
268+
fn format_args_named_arg_keyword() {
269+
run_and_expect_no_errors("test_data/parser/inline/ok/format_args_named_arg_keyword.rs");
270+
}
271+
#[test]
268272
fn frontmatter() { run_and_expect_no_errors("test_data/parser/inline/ok/frontmatter.rs"); }
269273
#[test]
270274
fn full_range_expr() {

crates/parser/test_data/parser/inline/ok/builtin_expr.rast

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ SOURCE_FILE
4444
COMMA ","
4545
WHITESPACE " "
4646
FORMAT_ARGS_ARG
47-
NAME
47+
FORMAT_ARGS_ARG_NAME
4848
IDENT "a"
49-
WHITESPACE " "
50-
EQ "="
49+
WHITESPACE " "
50+
EQ "="
5151
WHITESPACE " "
5252
BIN_EXPR
5353
LITERAL
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "main"
7+
PARAM_LIST
8+
L_PAREN "("
9+
R_PAREN ")"
10+
WHITESPACE " "
11+
BLOCK_EXPR
12+
STMT_LIST
13+
L_CURLY "{"
14+
WHITESPACE "\n "
15+
EXPR_STMT
16+
FORMAT_ARGS_EXPR
17+
BUILTIN_KW "builtin"
18+
POUND "#"
19+
FORMAT_ARGS_KW "format_args"
20+
L_PAREN "("
21+
LITERAL
22+
STRING "\"{type}\""
23+
COMMA ","
24+
WHITESPACE " "
25+
FORMAT_ARGS_ARG
26+
FORMAT_ARGS_ARG_NAME
27+
TYPE_KW "type"
28+
EQ "="
29+
LITERAL
30+
INT_NUMBER "1"
31+
R_PAREN ")"
32+
SEMICOLON ";"
33+
WHITESPACE "\n"
34+
R_CURLY "}"
35+
WHITESPACE "\n"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
builtin#format_args("{type}", type=1);
3+
}

crates/syntax/rust.ungram

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,10 @@ FormatArgsExpr =
438438
')'
439439

440440
FormatArgsArg =
441-
(Name '=')? Expr
441+
arg_name:FormatArgsArgName? Expr
442+
443+
FormatArgsArgName =
444+
'=' // This also has a name, but it's any token and we can't put it here
442445

443446
MacroExpr =
444447
MacroCall

crates/syntax/src/ast/generated/nodes.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -639,10 +639,16 @@ impl ForType {
639639
pub struct FormatArgsArg {
640640
pub(crate) syntax: SyntaxNode,
641641
}
642-
impl ast::HasName for FormatArgsArg {}
643642
impl FormatArgsArg {
643+
#[inline]
644+
pub fn arg_name(&self) -> Option<FormatArgsArgName> { support::child(&self.syntax) }
644645
#[inline]
645646
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
647+
}
648+
pub struct FormatArgsArgName {
649+
pub(crate) syntax: SyntaxNode,
650+
}
651+
impl FormatArgsArgName {
646652
#[inline]
647653
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
648654
}
@@ -3722,6 +3728,38 @@ impl fmt::Debug for FormatArgsArg {
37223728
f.debug_struct("FormatArgsArg").field("syntax", &self.syntax).finish()
37233729
}
37243730
}
3731+
impl AstNode for FormatArgsArgName {
3732+
#[inline]
3733+
fn kind() -> SyntaxKind
3734+
where
3735+
Self: Sized,
3736+
{
3737+
FORMAT_ARGS_ARG_NAME
3738+
}
3739+
#[inline]
3740+
fn can_cast(kind: SyntaxKind) -> bool { kind == FORMAT_ARGS_ARG_NAME }
3741+
#[inline]
3742+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3743+
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
3744+
}
3745+
#[inline]
3746+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3747+
}
3748+
impl hash::Hash for FormatArgsArgName {
3749+
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
3750+
}
3751+
impl Eq for FormatArgsArgName {}
3752+
impl PartialEq for FormatArgsArgName {
3753+
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
3754+
}
3755+
impl Clone for FormatArgsArgName {
3756+
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
3757+
}
3758+
impl fmt::Debug for FormatArgsArgName {
3759+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3760+
f.debug_struct("FormatArgsArgName").field("syntax", &self.syntax).finish()
3761+
}
3762+
}
37253763
impl AstNode for FormatArgsExpr {
37263764
#[inline]
37273765
fn kind() -> SyntaxKind
@@ -8947,7 +8985,6 @@ impl AstNode for AnyHasName {
89478985
| CONST_PARAM
89488986
| ENUM
89498987
| FN
8950-
| FORMAT_ARGS_ARG
89518988
| IDENT_PAT
89528989
| MACRO_DEF
89538990
| MACRO_RULES
@@ -9006,10 +9043,6 @@ impl From<Fn> for AnyHasName {
90069043
#[inline]
90079044
fn from(node: Fn) -> AnyHasName { AnyHasName { syntax: node.syntax } }
90089045
}
9009-
impl From<FormatArgsArg> for AnyHasName {
9010-
#[inline]
9011-
fn from(node: FormatArgsArg) -> AnyHasName { AnyHasName { syntax: node.syntax } }
9012-
}
90139046
impl From<IdentPat> for AnyHasName {
90149047
#[inline]
90159048
fn from(node: IdentPat) -> AnyHasName { AnyHasName { syntax: node.syntax } }
@@ -9541,6 +9574,11 @@ impl std::fmt::Display for FormatArgsArg {
95419574
std::fmt::Display::fmt(self.syntax(), f)
95429575
}
95439576
}
9577+
impl std::fmt::Display for FormatArgsArgName {
9578+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9579+
std::fmt::Display::fmt(self.syntax(), f)
9580+
}
9581+
}
95449582
impl std::fmt::Display for FormatArgsExpr {
95459583
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95469584
std::fmt::Display::fmt(self.syntax(), f)

0 commit comments

Comments
 (0)