mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
feat: allow attributes on all expressions
Attrs are syntactically valid on any expression, even if they are not allowed semantically everywhere yet.
This commit is contained in:
parent
7dc331faef
commit
56964c9bd3
20 changed files with 303 additions and 335 deletions
|
@ -650,9 +650,11 @@ impl ExprCollector<'_> {
|
|||
self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
|
||||
}
|
||||
ast::Stmt::ExprStmt(stmt) => {
|
||||
if self.check_cfg(&stmt).is_none() {
|
||||
if let Some(expr) = stmt.expr() {
|
||||
if self.check_cfg(&expr).is_none() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let has_semi = stmt.semicolon_token().is_some();
|
||||
// Note that macro could be expended to multiple statements
|
||||
if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
|
||||
|
|
|
@ -63,7 +63,7 @@ pub(crate) mod entry_points {
|
|||
pub(crate) use types::type_;
|
||||
|
||||
pub(crate) fn expr(p: &mut Parser) {
|
||||
let _ = expressions::expr_with_attrs(p);
|
||||
let _ = expressions::expr(p);
|
||||
}
|
||||
|
||||
pub(crate) fn stmt(p: &mut Parser) {
|
||||
|
|
|
@ -41,7 +41,7 @@ pub(super) fn meta(p: &mut Parser) {
|
|||
match p.current() {
|
||||
T![=] => {
|
||||
p.bump(T![=]);
|
||||
if expressions::expr(p).0.is_none() {
|
||||
if !expressions::expr(p) {
|
||||
p.error("expected expression");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,35 +13,19 @@ pub(super) enum StmtWithSemi {
|
|||
|
||||
const EXPR_FIRST: TokenSet = LHS_FIRST;
|
||||
|
||||
pub(super) fn expr(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) {
|
||||
pub(super) fn expr(p: &mut Parser) -> bool {
|
||||
let r = Restrictions { forbid_structs: false, prefer_stmt: false };
|
||||
expr_bp(p, r, 1)
|
||||
expr_bp(p, None, r, 1).is_some()
|
||||
}
|
||||
|
||||
pub(super) fn expr_with_attrs(p: &mut Parser) -> bool {
|
||||
let m = p.start();
|
||||
let has_attrs = p.at(T![#]);
|
||||
attributes::outer_attrs(p);
|
||||
|
||||
let (cm, _block_like) = expr(p);
|
||||
let success = cm.is_some();
|
||||
|
||||
match (has_attrs, cm) {
|
||||
(true, Some(cm)) => cm.extend_to(p, m),
|
||||
_ => m.abandon(p),
|
||||
}
|
||||
|
||||
success
|
||||
}
|
||||
|
||||
pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) {
|
||||
pub(super) fn expr_stmt(p: &mut Parser, m: Option<Marker>) -> Option<(CompletedMarker, BlockLike)> {
|
||||
let r = Restrictions { forbid_structs: false, prefer_stmt: true };
|
||||
expr_bp(p, r, 1)
|
||||
expr_bp(p, m, r, 1)
|
||||
}
|
||||
|
||||
fn expr_no_struct(p: &mut Parser) {
|
||||
let r = Restrictions { forbid_structs: true, prefer_stmt: false };
|
||||
expr_bp(p, r, 1);
|
||||
expr_bp(p, None, r, 1);
|
||||
}
|
||||
|
||||
pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi, prefer_expr: bool) {
|
||||
|
@ -53,7 +37,6 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi, prefer_expr: bool) {
|
|||
// #[C] #[D] {}
|
||||
// #[D] return ();
|
||||
// }
|
||||
let has_attrs = p.at(T![#]);
|
||||
attributes::outer_attrs(p);
|
||||
|
||||
if p.at(T![let]) {
|
||||
|
@ -68,31 +51,8 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi, prefer_expr: bool) {
|
|||
Err(m) => m,
|
||||
};
|
||||
|
||||
let (cm, blocklike) = expr_stmt(p);
|
||||
let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR);
|
||||
|
||||
if has_attrs {
|
||||
if matches!(kind, BIN_EXPR | RANGE_EXPR) {
|
||||
// test_err attr_on_expr_not_allowed
|
||||
// fn foo() {
|
||||
// #[A] 1 + 2;
|
||||
// #[B] if true {};
|
||||
// }
|
||||
p.error(format!("attributes are not allowed on {:?}", kind));
|
||||
}
|
||||
}
|
||||
|
||||
if p.at(T!['}']) || (prefer_expr && p.at(EOF)) {
|
||||
// test attr_on_last_expr_in_block
|
||||
// fn foo() {
|
||||
// { #[A] bar!()? }
|
||||
// #[B] &()
|
||||
// }
|
||||
match cm {
|
||||
Some(cm) => cm.extend_to(p, m),
|
||||
None => m.abandon(p),
|
||||
}
|
||||
} else {
|
||||
if let Some((cm, blocklike)) = expr_stmt(p, Some(m)) {
|
||||
if !(p.at(T!['}']) || (prefer_expr && p.at(EOF))) {
|
||||
// test no_semi_after_block
|
||||
// fn foo() {
|
||||
// if true {}
|
||||
|
@ -107,7 +67,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi, prefer_expr: bool) {
|
|||
// }
|
||||
// test!{}
|
||||
// }
|
||||
|
||||
let m = cm.precede(p);
|
||||
match with_semi {
|
||||
StmtWithSemi::No => (),
|
||||
StmtWithSemi::Optional => {
|
||||
|
@ -124,6 +84,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi, prefer_expr: bool) {
|
|||
|
||||
m.complete(p, EXPR_STMT);
|
||||
}
|
||||
}
|
||||
|
||||
// test let_stmt
|
||||
// fn f() { let x: i32 = 92; }
|
||||
|
@ -138,7 +99,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi, prefer_expr: bool) {
|
|||
if p.eat(T![=]) {
|
||||
// test let_stmt_init
|
||||
// fn f() { let x = 92; }
|
||||
expressions::expr_with_attrs(p);
|
||||
expressions::expr(p);
|
||||
}
|
||||
|
||||
match with_semi {
|
||||
|
@ -234,20 +195,34 @@ fn current_op(p: &Parser) -> (u8, SyntaxKind) {
|
|||
}
|
||||
|
||||
// Parses expression with binding power of at least bp.
|
||||
fn expr_bp(p: &mut Parser, mut r: Restrictions, bp: u8) -> (Option<CompletedMarker>, BlockLike) {
|
||||
fn expr_bp(
|
||||
p: &mut Parser,
|
||||
m: Option<Marker>,
|
||||
mut r: Restrictions,
|
||||
bp: u8,
|
||||
) -> Option<(CompletedMarker, BlockLike)> {
|
||||
let m = m.unwrap_or_else(|| {
|
||||
let m = p.start();
|
||||
attributes::outer_attrs(p);
|
||||
m
|
||||
});
|
||||
let mut lhs = match lhs(p, r) {
|
||||
Some((lhs, blocklike)) => {
|
||||
let lhs = lhs.extend_to(p, m);
|
||||
if r.prefer_stmt && blocklike.is_block() {
|
||||
// test stmt_bin_expr_ambiguity
|
||||
// fn f() {
|
||||
// let _ = {1} & 2;
|
||||
// {1} &2;
|
||||
// }
|
||||
return (Some(lhs), BlockLike::Block);
|
||||
return Some((lhs, BlockLike::Block));
|
||||
}
|
||||
lhs
|
||||
}
|
||||
None => return (None, BlockLike::NotBlock),
|
||||
None => {
|
||||
m.abandon(p);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
loop {
|
||||
|
@ -285,10 +260,10 @@ fn expr_bp(p: &mut Parser, mut r: Restrictions, bp: u8) -> (Option<CompletedMark
|
|||
}
|
||||
}
|
||||
|
||||
expr_bp(p, Restrictions { prefer_stmt: false, ..r }, op_bp + 1);
|
||||
expr_bp(p, None, Restrictions { prefer_stmt: false, ..r }, op_bp + 1);
|
||||
lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
|
||||
}
|
||||
(Some(lhs), BlockLike::NotBlock)
|
||||
Some((lhs, BlockLike::NotBlock))
|
||||
}
|
||||
|
||||
const LHS_FIRST: TokenSet =
|
||||
|
@ -341,9 +316,10 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
|
|||
m = p.start();
|
||||
p.bump(op);
|
||||
if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
|
||||
expr_bp(p, r, 2);
|
||||
expr_bp(p, None, r, 2);
|
||||
}
|
||||
return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
|
||||
let cm = m.complete(p, RANGE_EXPR);
|
||||
return Some((cm, BlockLike::NotBlock));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,12 +329,15 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
|
|||
// {p}.x = 10;
|
||||
// }
|
||||
let (lhs, blocklike) = atom::atom_expr(p, r)?;
|
||||
return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block())));
|
||||
let (cm, block_like) =
|
||||
postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()));
|
||||
return Some((cm, block_like));
|
||||
}
|
||||
};
|
||||
// parse the interior of the unary expression
|
||||
expr_bp(p, r, 255);
|
||||
Some((m.complete(p, kind), BlockLike::NotBlock))
|
||||
expr_bp(p, None, r, 255);
|
||||
let cm = m.complete(p, kind);
|
||||
Some((cm, BlockLike::NotBlock))
|
||||
}
|
||||
|
||||
fn postfix_expr(
|
||||
|
@ -536,7 +515,7 @@ fn arg_list(p: &mut Parser) {
|
|||
// fn main() {
|
||||
// foo(#[attr] 92)
|
||||
// }
|
||||
if !expr_with_attrs(p) {
|
||||
if !expr(p) {
|
||||
break;
|
||||
}
|
||||
if !p.at(T![')']) && !p.expect(T![,]) {
|
||||
|
|
|
@ -176,7 +176,7 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker {
|
|||
|
||||
// test tuple_attrs
|
||||
// const A: (i64, i64) = (1, #[cfg(test)] 2);
|
||||
if !expr_with_attrs(p) {
|
||||
if !expr(p) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ fn array_expr(p: &mut Parser) -> CompletedMarker {
|
|||
|
||||
// test array_attrs
|
||||
// const A: &[i64] = &[1, #[cfg(test)] 2];
|
||||
if !expr_with_attrs(p) {
|
||||
if !expr(p) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -438,7 +438,10 @@ fn match_arm(p: &mut Parser) {
|
|||
match_guard(p);
|
||||
}
|
||||
p.expect(T![=>]);
|
||||
let blocklike = expr_stmt(p).1;
|
||||
let blocklike = match expr_stmt(p, None) {
|
||||
Some((_, blocklike)) => blocklike,
|
||||
None => BlockLike::NotBlock,
|
||||
};
|
||||
|
||||
// test match_arms_commas
|
||||
// fn foo() {
|
||||
|
@ -619,14 +622,14 @@ fn meta_var_expr(p: &mut Parser) -> CompletedMarker {
|
|||
assert!(p.at(L_DOLLAR));
|
||||
let m = p.start();
|
||||
p.bump(L_DOLLAR);
|
||||
let (completed, _is_block) =
|
||||
expr_bp(p, Restrictions { forbid_structs: false, prefer_stmt: false }, 1);
|
||||
let expr = expr_bp(p, None, Restrictions { forbid_structs: false, prefer_stmt: false }, 1);
|
||||
|
||||
match (completed, p.current()) {
|
||||
(Some(it), R_DOLLAR) => {
|
||||
match (expr, p.current()) {
|
||||
(Some((cm, _)), R_DOLLAR) => {
|
||||
p.bump(R_DOLLAR);
|
||||
// FIXME: this leaves the dollar hanging in the air...
|
||||
m.abandon(p);
|
||||
it
|
||||
cm
|
||||
}
|
||||
_ => {
|
||||
while !p.at(R_DOLLAR) {
|
||||
|
|
|
@ -339,7 +339,7 @@ impl CompletedMarker {
|
|||
}
|
||||
|
||||
/// Extends this completed marker *to the left* up to `m`.
|
||||
pub(crate) fn extend_to(self, p: &mut Parser, mut m: Marker) {
|
||||
pub(crate) fn extend_to(self, p: &mut Parser, mut m: Marker) -> CompletedMarker {
|
||||
m.bomb.defuse();
|
||||
let idx = m.pos as usize;
|
||||
match &mut p.events[idx] {
|
||||
|
@ -348,6 +348,7 @@ impl CompletedMarker {
|
|||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn kind(&self) -> SyntaxKind {
|
||||
|
|
|
@ -26,7 +26,6 @@ SOURCE_FILE@0..43
|
|||
PATH_SEGMENT@23..24
|
||||
NAME_REF@23..24
|
||||
IDENT@23..24 "f"
|
||||
EXPR_STMT@24..25
|
||||
ERROR@24..25
|
||||
COLON@24..25 ":"
|
||||
WHITESPACE@25..26 " "
|
||||
|
@ -55,4 +54,3 @@ error 15..15: expected an item
|
|||
error 17..17: expected an item
|
||||
error 24..24: expected SEMICOLON
|
||||
error 24..24: expected expression
|
||||
error 25..25: expected SEMICOLON
|
||||
|
|
|
@ -24,7 +24,6 @@ SOURCE_FILE@0..112
|
|||
WHITESPACE@15..16 " "
|
||||
ERROR@16..17
|
||||
AT@16..17 "@"
|
||||
EXPR_STMT@17..18
|
||||
ERROR@17..18
|
||||
COMMA@17..18 ","
|
||||
WHITESPACE@18..19 " "
|
||||
|
@ -71,13 +70,11 @@ SOURCE_FILE@0..112
|
|||
WHITESPACE@52..53 " "
|
||||
ERROR@53..54
|
||||
AT@53..54 "@"
|
||||
EXPR_STMT@54..55
|
||||
ERROR@54..55
|
||||
COMMA@54..55 ","
|
||||
WHITESPACE@55..56 " "
|
||||
IMPL@56..60
|
||||
IMPL_KW@56..60 "impl"
|
||||
EXPR_STMT@60..61
|
||||
ERROR@60..61
|
||||
COMMA@60..61 ","
|
||||
WHITESPACE@61..62 " "
|
||||
|
@ -122,14 +119,11 @@ SOURCE_FILE@0..112
|
|||
WHITESPACE@91..92 " "
|
||||
ERROR@92..93
|
||||
AT@92..93 "@"
|
||||
EXPR_STMT@93..94
|
||||
ERROR@93..94
|
||||
COMMA@93..94 ","
|
||||
WHITESPACE@94..95 " "
|
||||
EXPR_STMT@95..96
|
||||
ERROR@95..96
|
||||
R_BRACK@95..96 "]"
|
||||
EXPR_STMT@96..97
|
||||
ERROR@96..97
|
||||
COMMA@96..97 ","
|
||||
WHITESPACE@97..98 " "
|
||||
|
@ -149,7 +143,6 @@ error 16..16: expected expression
|
|||
error 17..17: expected R_BRACK
|
||||
error 17..17: expected SEMICOLON
|
||||
error 17..17: expected expression
|
||||
error 18..18: expected SEMICOLON
|
||||
error 25..25: expected a name
|
||||
error 26..26: expected `;`, `{`, or `(`
|
||||
error 30..30: expected pattern
|
||||
|
@ -157,22 +150,17 @@ error 31..31: expected SEMICOLON
|
|||
error 53..53: expected expression
|
||||
error 54..54: expected SEMICOLON
|
||||
error 54..54: expected expression
|
||||
error 55..55: expected SEMICOLON
|
||||
error 60..60: expected type
|
||||
error 60..60: expected `{`
|
||||
error 60..60: expected expression
|
||||
error 61..61: expected SEMICOLON
|
||||
error 65..65: expected pattern
|
||||
error 65..65: expected SEMICOLON
|
||||
error 65..65: expected expression
|
||||
error 92..92: expected expression
|
||||
error 93..93: expected SEMICOLON
|
||||
error 93..93: expected expression
|
||||
error 94..94: expected SEMICOLON
|
||||
error 95..95: expected expression
|
||||
error 96..96: expected SEMICOLON
|
||||
error 96..96: expected expression
|
||||
error 97..97: expected SEMICOLON
|
||||
error 103..103: expected a name
|
||||
error 104..104: expected `{`
|
||||
error 108..108: expected pattern
|
||||
|
|
|
@ -143,7 +143,6 @@ SOURCE_FILE@0..240
|
|||
LIFETIME_IDENT@117..119 "'a"
|
||||
R_ANGLE@119..120 ">"
|
||||
R_PAREN@120..121 ")"
|
||||
EXPR_STMT@121..123
|
||||
ERROR@121..122
|
||||
R_ANGLE@121..122 ">"
|
||||
SEMICOLON@122..123 ";"
|
||||
|
@ -173,11 +172,9 @@ SOURCE_FILE@0..240
|
|||
PATH_SEGMENT@141..146
|
||||
NAME_REF@141..146
|
||||
IDENT@141..146 "Sized"
|
||||
EXPR_STMT@146..147
|
||||
ERROR@146..147
|
||||
R_PAREN@146..147 ")"
|
||||
WHITESPACE@147..148 " "
|
||||
EXPR_STMT@148..149
|
||||
ERROR@148..149
|
||||
PLUS@148..149 "+"
|
||||
WHITESPACE@149..150 " "
|
||||
|
@ -288,7 +285,6 @@ SOURCE_FILE@0..240
|
|||
NAME_REF@229..234
|
||||
IDENT@229..234 "Sized"
|
||||
R_PAREN@234..235 ")"
|
||||
EXPR_STMT@235..237
|
||||
ERROR@235..236
|
||||
R_ANGLE@235..236 ">"
|
||||
SEMICOLON@236..237 ";"
|
||||
|
@ -306,9 +302,7 @@ error 141..141: expected R_ANGLE
|
|||
error 141..141: expected SEMICOLON
|
||||
error 146..146: expected SEMICOLON
|
||||
error 146..146: expected expression
|
||||
error 147..147: expected SEMICOLON
|
||||
error 148..148: expected expression
|
||||
error 149..149: expected SEMICOLON
|
||||
error 155..155: expected type
|
||||
error 158..158: expected IN_KW
|
||||
error 165..165: expected expression
|
||||
|
|
|
@ -51,7 +51,6 @@ SOURCE_FILE@0..83
|
|||
BLOCK_EXPR@66..80
|
||||
L_CURLY@66..67 "{"
|
||||
WHITESPACE@67..68 " "
|
||||
EXPR_STMT@68..75
|
||||
ERROR@68..75
|
||||
LABEL@68..75
|
||||
LIFETIME@68..74
|
||||
|
@ -69,4 +68,3 @@ error 24..24: expected existential, fn, trait or impl
|
|||
error 41..41: expected existential, fn, trait or impl
|
||||
error 56..56: expected a block
|
||||
error 75..75: expected a loop
|
||||
error 75..75: expected SEMICOLON
|
||||
|
|
|
@ -11,7 +11,6 @@ SOURCE_FILE@0..30
|
|||
BLOCK_EXPR@10..29
|
||||
L_CURLY@10..11 "{"
|
||||
WHITESPACE@11..16 "\n "
|
||||
EXPR_STMT@16..22
|
||||
ERROR@16..22
|
||||
LABEL@16..22
|
||||
LIFETIME@16..21
|
||||
|
@ -24,6 +23,5 @@ SOURCE_FILE@0..30
|
|||
R_CURLY@28..29 "}"
|
||||
WHITESPACE@29..30 "\n"
|
||||
error 22..22: expected a loop
|
||||
error 22..22: expected SEMICOLON
|
||||
error 27..27: expected type
|
||||
error 27..27: expected `{`
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
SOURCE_FILE@0..48
|
||||
FN@0..47
|
||||
FN_KW@0..2 "fn"
|
||||
WHITESPACE@2..3 " "
|
||||
NAME@3..6
|
||||
IDENT@3..6 "foo"
|
||||
PARAM_LIST@6..8
|
||||
L_PAREN@6..7 "("
|
||||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..47
|
||||
L_CURLY@9..10 "{"
|
||||
WHITESPACE@10..14 "\n "
|
||||
EXPR_STMT@14..25
|
||||
ATTR@14..18
|
||||
POUND@14..15 "#"
|
||||
L_BRACK@15..16 "["
|
||||
META@16..17
|
||||
PATH@16..17
|
||||
PATH_SEGMENT@16..17
|
||||
NAME_REF@16..17
|
||||
IDENT@16..17 "A"
|
||||
R_BRACK@17..18 "]"
|
||||
WHITESPACE@18..19 " "
|
||||
BIN_EXPR@19..24
|
||||
LITERAL@19..20
|
||||
INT_NUMBER@19..20 "1"
|
||||
WHITESPACE@20..21 " "
|
||||
PLUS@21..22 "+"
|
||||
WHITESPACE@22..23 " "
|
||||
LITERAL@23..24
|
||||
INT_NUMBER@23..24 "2"
|
||||
SEMICOLON@24..25 ";"
|
||||
WHITESPACE@25..29 "\n "
|
||||
EXPR_STMT@29..45
|
||||
ATTR@29..33
|
||||
POUND@29..30 "#"
|
||||
L_BRACK@30..31 "["
|
||||
META@31..32
|
||||
PATH@31..32
|
||||
PATH_SEGMENT@31..32
|
||||
NAME_REF@31..32
|
||||
IDENT@31..32 "B"
|
||||
R_BRACK@32..33 "]"
|
||||
WHITESPACE@33..34 " "
|
||||
IF_EXPR@34..44
|
||||
IF_KW@34..36 "if"
|
||||
WHITESPACE@36..37 " "
|
||||
CONDITION@37..41
|
||||
LITERAL@37..41
|
||||
TRUE_KW@37..41 "true"
|
||||
WHITESPACE@41..42 " "
|
||||
BLOCK_EXPR@42..44
|
||||
L_CURLY@42..43 "{"
|
||||
R_CURLY@43..44 "}"
|
||||
SEMICOLON@44..45 ";"
|
||||
WHITESPACE@45..46 "\n"
|
||||
R_CURLY@46..47 "}"
|
||||
WHITESPACE@47..48 "\n"
|
||||
error 24..24: attributes are not allowed on BIN_EXPR
|
|
@ -1,4 +0,0 @@
|
|||
fn foo() {
|
||||
#[A] 1 + 2;
|
||||
#[B] if true {};
|
||||
}
|
|
@ -12,6 +12,7 @@ SOURCE_FILE@0..82
|
|||
L_CURLY@9..10 "{"
|
||||
WHITESPACE@10..15 "\n "
|
||||
EXPR_STMT@15..26
|
||||
CALL_EXPR@15..25
|
||||
ATTR@15..19
|
||||
POUND@15..16 "#"
|
||||
L_BRACK@16..17 "["
|
||||
|
@ -22,7 +23,6 @@ SOURCE_FILE@0..82
|
|||
IDENT@17..18 "A"
|
||||
R_BRACK@18..19 "]"
|
||||
WHITESPACE@19..20 " "
|
||||
CALL_EXPR@20..25
|
||||
PATH_EXPR@20..23
|
||||
PATH@20..23
|
||||
PATH_SEGMENT@20..23
|
||||
|
@ -34,6 +34,7 @@ SOURCE_FILE@0..82
|
|||
SEMICOLON@25..26 ";"
|
||||
WHITESPACE@26..31 "\n "
|
||||
EXPR_STMT@31..42
|
||||
MACRO_CALL@31..42
|
||||
ATTR@31..35
|
||||
POUND@31..32 "#"
|
||||
L_BRACK@32..33 "["
|
||||
|
@ -44,7 +45,6 @@ SOURCE_FILE@0..82
|
|||
IDENT@33..34 "B"
|
||||
R_BRACK@34..35 "]"
|
||||
WHITESPACE@35..36 " "
|
||||
MACRO_CALL@36..42
|
||||
PATH@36..39
|
||||
PATH_SEGMENT@36..39
|
||||
NAME_REF@36..39
|
||||
|
@ -55,6 +55,7 @@ SOURCE_FILE@0..82
|
|||
R_CURLY@41..42 "}"
|
||||
WHITESPACE@42..47 "\n "
|
||||
EXPR_STMT@47..59
|
||||
BLOCK_EXPR@47..59
|
||||
ATTR@47..51
|
||||
POUND@47..48 "#"
|
||||
L_BRACK@48..49 "["
|
||||
|
@ -75,11 +76,11 @@ SOURCE_FILE@0..82
|
|||
IDENT@54..55 "D"
|
||||
R_BRACK@55..56 "]"
|
||||
WHITESPACE@56..57 " "
|
||||
BLOCK_EXPR@57..59
|
||||
L_CURLY@57..58 "{"
|
||||
R_CURLY@58..59 "}"
|
||||
WHITESPACE@59..64 "\n "
|
||||
EXPR_STMT@64..79
|
||||
RETURN_EXPR@64..78
|
||||
ATTR@64..68
|
||||
POUND@64..65 "#"
|
||||
L_BRACK@65..66 "["
|
||||
|
@ -90,7 +91,6 @@ SOURCE_FILE@0..82
|
|||
IDENT@66..67 "D"
|
||||
R_BRACK@67..68 "]"
|
||||
WHITESPACE@68..69 " "
|
||||
RETURN_EXPR@69..78
|
||||
RETURN_KW@69..75 "return"
|
||||
WHITESPACE@75..76 " "
|
||||
TUPLE_EXPR@76..78
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
SOURCE_FILE@0..47
|
||||
FN@0..46
|
||||
FN_KW@0..2 "fn"
|
||||
WHITESPACE@2..3 " "
|
||||
NAME@3..6
|
||||
IDENT@3..6 "foo"
|
||||
PARAM_LIST@6..8
|
||||
L_PAREN@6..7 "("
|
||||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..46
|
||||
L_CURLY@9..10 "{"
|
||||
WHITESPACE@10..15 "\n "
|
||||
EXPR_STMT@15..31
|
||||
BLOCK_EXPR@15..31
|
||||
L_CURLY@15..16 "{"
|
||||
WHITESPACE@16..17 " "
|
||||
TRY_EXPR@17..29
|
||||
ATTR@17..21
|
||||
POUND@17..18 "#"
|
||||
L_BRACK@18..19 "["
|
||||
META@19..20
|
||||
PATH@19..20
|
||||
PATH_SEGMENT@19..20
|
||||
NAME_REF@19..20
|
||||
IDENT@19..20 "A"
|
||||
R_BRACK@20..21 "]"
|
||||
WHITESPACE@21..22 " "
|
||||
MACRO_CALL@22..28
|
||||
PATH@22..25
|
||||
PATH_SEGMENT@22..25
|
||||
NAME_REF@22..25
|
||||
IDENT@22..25 "bar"
|
||||
BANG@25..26 "!"
|
||||
TOKEN_TREE@26..28
|
||||
L_PAREN@26..27 "("
|
||||
R_PAREN@27..28 ")"
|
||||
QUESTION@28..29 "?"
|
||||
WHITESPACE@29..30 " "
|
||||
R_CURLY@30..31 "}"
|
||||
WHITESPACE@31..36 "\n "
|
||||
REF_EXPR@36..44
|
||||
ATTR@36..40
|
||||
POUND@36..37 "#"
|
||||
L_BRACK@37..38 "["
|
||||
META@38..39
|
||||
PATH@38..39
|
||||
PATH_SEGMENT@38..39
|
||||
NAME_REF@38..39
|
||||
IDENT@38..39 "B"
|
||||
R_BRACK@39..40 "]"
|
||||
WHITESPACE@40..41 " "
|
||||
AMP@41..42 "&"
|
||||
TUPLE_EXPR@42..44
|
||||
L_PAREN@42..43 "("
|
||||
R_PAREN@43..44 ")"
|
||||
WHITESPACE@44..45 "\n"
|
||||
R_CURLY@45..46 "}"
|
||||
WHITESPACE@46..47 "\n"
|
|
@ -1,4 +0,0 @@
|
|||
fn foo() {
|
||||
{ #[A] bar!()? }
|
||||
#[B] &()
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
SOURCE_FILE@0..44
|
||||
FN@0..43
|
||||
FN_KW@0..2 "fn"
|
||||
WHITESPACE@2..3 " "
|
||||
NAME@3..4
|
||||
IDENT@3..4 "f"
|
||||
PARAM_LIST@4..6
|
||||
L_PAREN@4..5 "("
|
||||
R_PAREN@5..6 ")"
|
||||
WHITESPACE@6..7 " "
|
||||
BLOCK_EXPR@7..43
|
||||
L_CURLY@7..8 "{"
|
||||
WHITESPACE@8..13 "\n "
|
||||
PAREN_EXPR@13..41
|
||||
L_PAREN@13..14 "("
|
||||
BIN_EXPR@14..40
|
||||
TRY_EXPR@14..23
|
||||
ATTR@14..18
|
||||
POUND@14..15 "#"
|
||||
L_BRACK@15..16 "["
|
||||
META@16..17
|
||||
PATH@16..17
|
||||
PATH_SEGMENT@16..17
|
||||
NAME_REF@16..17
|
||||
IDENT@16..17 "a"
|
||||
R_BRACK@17..18 "]"
|
||||
WHITESPACE@18..19 " "
|
||||
PATH_EXPR@19..22
|
||||
PATH@19..22
|
||||
PATH_SEGMENT@19..22
|
||||
NAME_REF@19..22
|
||||
IDENT@19..22 "lhs"
|
||||
QUESTION@22..23 "?"
|
||||
WHITESPACE@23..24 " "
|
||||
PLUS@24..25 "+"
|
||||
WHITESPACE@25..26 " "
|
||||
AWAIT_EXPR@26..40
|
||||
ATTR@26..30
|
||||
POUND@26..27 "#"
|
||||
L_BRACK@27..28 "["
|
||||
META@28..29
|
||||
PATH@28..29
|
||||
PATH_SEGMENT@28..29
|
||||
NAME_REF@28..29
|
||||
IDENT@28..29 "b"
|
||||
R_BRACK@29..30 "]"
|
||||
WHITESPACE@30..31 " "
|
||||
PATH_EXPR@31..34
|
||||
PATH@31..34
|
||||
PATH_SEGMENT@31..34
|
||||
NAME_REF@31..34
|
||||
IDENT@31..34 "rhs"
|
||||
DOT@34..35 "."
|
||||
AWAIT_KW@35..40 "await"
|
||||
R_PAREN@40..41 ")"
|
||||
WHITESPACE@41..42 "\n"
|
||||
R_CURLY@42..43 "}"
|
||||
WHITESPACE@43..44 "\n"
|
|
@ -0,0 +1,3 @@
|
|||
fn f() {
|
||||
(#[a] lhs? + #[b] rhs.await)
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
SOURCE_FILE@0..52
|
||||
FN@0..51
|
||||
FN_KW@0..2 "fn"
|
||||
WHITESPACE@2..3 " "
|
||||
NAME@3..6
|
||||
IDENT@3..6 "foo"
|
||||
PARAM_LIST@6..8
|
||||
L_PAREN@6..7 "("
|
||||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..51
|
||||
L_CURLY@9..10 "{"
|
||||
WHITESPACE@10..15 "\n "
|
||||
EXPR_STMT@15..36
|
||||
BLOCK_EXPR@15..36
|
||||
ATTR@15..19
|
||||
POUND@15..16 "#"
|
||||
L_BRACK@16..17 "["
|
||||
META@17..18
|
||||
PATH@17..18
|
||||
PATH_SEGMENT@17..18
|
||||
NAME_REF@17..18
|
||||
IDENT@17..18 "A"
|
||||
R_BRACK@18..19 "]"
|
||||
WHITESPACE@19..20 " "
|
||||
L_CURLY@20..21 "{"
|
||||
WHITESPACE@21..22 " "
|
||||
TRY_EXPR@22..34
|
||||
ATTR@22..26
|
||||
POUND@22..23 "#"
|
||||
L_BRACK@23..24 "["
|
||||
META@24..25
|
||||
PATH@24..25
|
||||
PATH_SEGMENT@24..25
|
||||
NAME_REF@24..25
|
||||
IDENT@24..25 "B"
|
||||
R_BRACK@25..26 "]"
|
||||
WHITESPACE@26..27 " "
|
||||
MACRO_CALL@27..33
|
||||
PATH@27..30
|
||||
PATH_SEGMENT@27..30
|
||||
NAME_REF@27..30
|
||||
IDENT@27..30 "bar"
|
||||
BANG@30..31 "!"
|
||||
TOKEN_TREE@31..33
|
||||
L_PAREN@31..32 "("
|
||||
R_PAREN@32..33 ")"
|
||||
QUESTION@33..34 "?"
|
||||
WHITESPACE@34..35 " "
|
||||
R_CURLY@35..36 "}"
|
||||
WHITESPACE@36..41 "\n "
|
||||
REF_EXPR@41..49
|
||||
ATTR@41..45
|
||||
POUND@41..42 "#"
|
||||
L_BRACK@42..43 "["
|
||||
META@43..44
|
||||
PATH@43..44
|
||||
PATH_SEGMENT@43..44
|
||||
NAME_REF@43..44
|
||||
IDENT@43..44 "C"
|
||||
R_BRACK@44..45 "]"
|
||||
WHITESPACE@45..46 " "
|
||||
AMP@46..47 "&"
|
||||
TUPLE_EXPR@47..49
|
||||
L_PAREN@47..48 "("
|
||||
R_PAREN@48..49 ")"
|
||||
WHITESPACE@49..50 "\n"
|
||||
R_CURLY@50..51 "}"
|
||||
WHITESPACE@51..52 "\n"
|
|
@ -0,0 +1,4 @@
|
|||
fn foo() {
|
||||
#[A] { #[B] bar!()? }
|
||||
#[C] &()
|
||||
}
|
Loading…
Reference in a new issue