diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-04-03 15:13:15 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-04-03 15:13:15 +0100 |
commit | 6a2dd7bafc24ac405aebf29f04120ca071019e92 (patch) | |
tree | ac21306c7bf9dc816f4b0e9b50322f57256eddfa /crates/ra_parser/src/grammar | |
parent | 795b8cf9c5a6f3be4117823c896f41d1a4455079 (diff) | |
parent | da8eb29a2f70a58122903bf087bd6c1d0fbd6d3f (diff) |
Merge #3836
3836: Macro patterns are not confused with expressions. r=matklad a=matklad
We treat macro calls as expressions (there's appropriate Into impl),
which causes problem if there's expresison and non-expression macro in
the same node (like in the match arm).
We fix this problem by nesting macor patterns into another node (the
same way we nest path into PathExpr or PathPat). Ideally, we probably
should add a similar nesting for macro expressions, but that needs
some careful thinking about macros in blocks: `{ am_i_expression!() }`.
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 4 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 25 |
2 files changed, 14 insertions, 15 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 0c170ac5e..c486c0211 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -79,8 +79,6 @@ fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool { | |||
79 | } | 79 | } |
80 | 80 | ||
81 | pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | 81 | pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { |
82 | // test block_items | ||
83 | // fn a() { fn b() {} } | ||
84 | let m = p.start(); | 82 | let m = p.start(); |
85 | // test attr_on_expr_stmt | 83 | // test attr_on_expr_stmt |
86 | // fn foo() { | 84 | // fn foo() { |
@@ -97,6 +95,8 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
97 | return; | 95 | return; |
98 | } | 96 | } |
99 | 97 | ||
98 | // test block_items | ||
99 | // fn a() { fn b() {} } | ||
100 | let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) { | 100 | let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) { |
101 | Ok(()) => return, | 101 | Ok(()) => return, |
102 | Err(m) => m, | 102 | Err(m) => m, |
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 3afbaa82b..936d27575 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -70,15 +70,6 @@ fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) { | |||
70 | return; | 70 | return; |
71 | } | 71 | } |
72 | } | 72 | } |
73 | // test marco_pat | ||
74 | // fn main() { | ||
75 | // let m!(x) = 0; | ||
76 | // } | ||
77 | if lhs.kind() == PATH_PAT && p.at(T![!]) { | ||
78 | let m = lhs.undo_completion(p); | ||
79 | items::macro_call_after_excl(p); | ||
80 | m.complete(p, MACRO_CALL); | ||
81 | } | ||
82 | } | 73 | } |
83 | } | 74 | } |
84 | 75 | ||
@@ -92,12 +83,12 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { | |||
92 | IDENT => match p.nth(1) { | 83 | IDENT => match p.nth(1) { |
93 | // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro | 84 | // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro |
94 | // (T![x]). | 85 | // (T![x]). |
95 | T!['('] | T!['{'] | T![!] => path_pat(p), | 86 | T!['('] | T!['{'] | T![!] => path_or_macro_pat(p), |
96 | T![:] if p.nth_at(1, T![::]) => path_pat(p), | 87 | T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p), |
97 | _ => bind_pat(p, true), | 88 | _ => bind_pat(p, true), |
98 | }, | 89 | }, |
99 | 90 | ||
100 | _ if paths::is_use_path_start(p) => path_pat(p), | 91 | _ if paths::is_use_path_start(p) => path_or_macro_pat(p), |
101 | _ if is_literal_pat_start(p) => literal_pat(p), | 92 | _ if is_literal_pat_start(p) => literal_pat(p), |
102 | 93 | ||
103 | T![.] if p.at(T![..]) => dot_dot_pat(p), | 94 | T![.] if p.at(T![..]) => dot_dot_pat(p), |
@@ -146,7 +137,7 @@ fn literal_pat(p: &mut Parser) -> CompletedMarker { | |||
146 | // let Bar { .. } = (); | 137 | // let Bar { .. } = (); |
147 | // let Bar(..) = (); | 138 | // let Bar(..) = (); |
148 | // } | 139 | // } |
149 | fn path_pat(p: &mut Parser) -> CompletedMarker { | 140 | fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker { |
150 | assert!(paths::is_use_path_start(p)); | 141 | assert!(paths::is_use_path_start(p)); |
151 | let m = p.start(); | 142 | let m = p.start(); |
152 | paths::expr_path(p); | 143 | paths::expr_path(p); |
@@ -159,6 +150,14 @@ fn path_pat(p: &mut Parser) -> CompletedMarker { | |||
159 | record_field_pat_list(p); | 150 | record_field_pat_list(p); |
160 | RECORD_PAT | 151 | RECORD_PAT |
161 | } | 152 | } |
153 | // test marco_pat | ||
154 | // fn main() { | ||
155 | // let m!(x) = 0; | ||
156 | // } | ||
157 | T![!] => { | ||
158 | items::macro_call_after_excl(p); | ||
159 | return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT); | ||
160 | } | ||
162 | _ => PATH_PAT, | 161 | _ => PATH_PAT, |
163 | }; | 162 | }; |
164 | m.complete(p, kind) | 163 | m.complete(p, kind) |