diff options
author | Aleksey Kladov <[email protected]> | 2020-04-03 14:38:42 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-04-03 15:12:38 +0100 |
commit | da8eb29a2f70a58122903bf087bd6c1d0fbd6d3f (patch) | |
tree | ac21306c7bf9dc816f4b0e9b50322f57256eddfa /crates | |
parent | 0e46ed8420469741d718ac223fad1088c151b497 (diff) |
Macro patterns are not confused with expressions.
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!() }`.
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/macros.rs | 31 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 4 | ||||
-rw-r--r-- | crates/ra_parser/src/syntax_kind/generated.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 42 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt | 21 |
6 files changed, 85 insertions, 17 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 28c570c76..8d4b8b0f0 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -672,8 +672,7 @@ impl ExprCollector<'_> { | |||
672 | } | 672 | } |
673 | 673 | ||
674 | // FIXME: implement | 674 | // FIXME: implement |
675 | ast::Pat::BoxPat(_) => Pat::Missing, | 675 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, |
676 | ast::Pat::RangePat(_) => Pat::Missing, | ||
677 | }; | 676 | }; |
678 | let ptr = AstPtr::new(&pat); | 677 | let ptr = AstPtr::new(&pat); |
679 | self.alloc_pat(pattern, Either::Left(ptr)) | 678 | self.alloc_pat(pattern, Either::Left(ptr)) |
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index eb97288f1..ff4599b71 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -1,8 +1,10 @@ | |||
1 | use super::{infer, type_at, type_at_pos}; | ||
2 | use crate::test_db::TestDB; | ||
3 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
4 | use ra_db::fixture::WithFixture; | 2 | use ra_db::fixture::WithFixture; |
5 | 3 | ||
4 | use super::{infer, type_at, type_at_pos}; | ||
5 | |||
6 | use crate::test_db::TestDB; | ||
7 | |||
6 | #[test] | 8 | #[test] |
7 | fn cfg_impl_def() { | 9 | fn cfg_impl_def() { |
8 | let (db, pos) = TestDB::with_position( | 10 | let (db, pos) = TestDB::with_position( |
@@ -658,3 +660,28 @@ fn test() { | |||
658 | ); | 660 | ); |
659 | assert_eq!("S", type_at_pos(&db, pos)); | 661 | assert_eq!("S", type_at_pos(&db, pos)); |
660 | } | 662 | } |
663 | |||
664 | #[test] | ||
665 | fn macro_in_arm() { | ||
666 | assert_snapshot!( | ||
667 | infer(r#" | ||
668 | macro_rules! unit { | ||
669 | () => { () }; | ||
670 | } | ||
671 | |||
672 | fn main() { | ||
673 | let x = match () { | ||
674 | unit!() => 92u32, | ||
675 | }; | ||
676 | } | ||
677 | "#), | ||
678 | @r###" | ||
679 | [52; 111) '{ ... }; }': () | ||
680 | [62; 63) 'x': u32 | ||
681 | [66; 108) 'match ... }': u32 | ||
682 | [72; 74) '()': () | ||
683 | [85; 92) 'unit!()': () | ||
684 | [96; 101) '92u32': u32 | ||
685 | "### | ||
686 | ); | ||
687 | } | ||
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 9bfdcfd41..936d27575 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -84,7 +84,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { | |||
84 | // 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 |
85 | // (T![x]). | 85 | // (T![x]). |
86 | T!['('] | T!['{'] | T![!] => path_or_macro_pat(p), | 86 | T!['('] | T!['{'] | T![!] => path_or_macro_pat(p), |
87 | T![:] if p.nth_at(1, T![::]) => path_pat(p), | 87 | T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p), |
88 | _ => bind_pat(p, true), | 88 | _ => bind_pat(p, true), |
89 | }, | 89 | }, |
90 | 90 | ||
@@ -156,7 +156,7 @@ fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker { | |||
156 | // } | 156 | // } |
157 | T![!] => { | 157 | T![!] => { |
158 | items::macro_call_after_excl(p); | 158 | items::macro_call_after_excl(p); |
159 | MACRO_CALL | 159 | return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT); |
160 | } | 160 | } |
161 | _ => PATH_PAT, | 161 | _ => PATH_PAT, |
162 | }; | 162 | }; |
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index dfc30d727..4c16cf1cd 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs | |||
@@ -167,6 +167,7 @@ pub enum SyntaxKind { | |||
167 | SLICE_PAT, | 167 | SLICE_PAT, |
168 | RANGE_PAT, | 168 | RANGE_PAT, |
169 | LITERAL_PAT, | 169 | LITERAL_PAT, |
170 | MACRO_PAT, | ||
170 | TUPLE_EXPR, | 171 | TUPLE_EXPR, |
171 | ARRAY_EXPR, | 172 | ARRAY_EXPR, |
172 | PAREN_EXPR, | 173 | PAREN_EXPR, |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 7204ca5b1..0c339b987 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -2563,6 +2563,38 @@ impl LiteralPat { | |||
2563 | } | 2563 | } |
2564 | } | 2564 | } |
2565 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 2565 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
2566 | pub struct MacroPat { | ||
2567 | pub(crate) syntax: SyntaxNode, | ||
2568 | } | ||
2569 | impl std::fmt::Display for MacroPat { | ||
2570 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
2571 | std::fmt::Display::fmt(self.syntax(), f) | ||
2572 | } | ||
2573 | } | ||
2574 | impl AstNode for MacroPat { | ||
2575 | fn can_cast(kind: SyntaxKind) -> bool { | ||
2576 | match kind { | ||
2577 | MACRO_PAT => true, | ||
2578 | _ => false, | ||
2579 | } | ||
2580 | } | ||
2581 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
2582 | if Self::can_cast(syntax.kind()) { | ||
2583 | Some(Self { syntax }) | ||
2584 | } else { | ||
2585 | None | ||
2586 | } | ||
2587 | } | ||
2588 | fn syntax(&self) -> &SyntaxNode { | ||
2589 | &self.syntax | ||
2590 | } | ||
2591 | } | ||
2592 | impl MacroPat { | ||
2593 | pub fn macro_call(&self) -> Option<MacroCall> { | ||
2594 | AstChildren::new(&self.syntax).next() | ||
2595 | } | ||
2596 | } | ||
2597 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2566 | pub struct RecordPat { | 2598 | pub struct RecordPat { |
2567 | pub(crate) syntax: SyntaxNode, | 2599 | pub(crate) syntax: SyntaxNode, |
2568 | } | 2600 | } |
@@ -4600,6 +4632,7 @@ pub enum Pat { | |||
4600 | SlicePat(SlicePat), | 4632 | SlicePat(SlicePat), |
4601 | RangePat(RangePat), | 4633 | RangePat(RangePat), |
4602 | LiteralPat(LiteralPat), | 4634 | LiteralPat(LiteralPat), |
4635 | MacroPat(MacroPat), | ||
4603 | } | 4636 | } |
4604 | impl From<OrPat> for Pat { | 4637 | impl From<OrPat> for Pat { |
4605 | fn from(node: OrPat) -> Pat { | 4638 | fn from(node: OrPat) -> Pat { |
@@ -4671,6 +4704,11 @@ impl From<LiteralPat> for Pat { | |||
4671 | Pat::LiteralPat(node) | 4704 | Pat::LiteralPat(node) |
4672 | } | 4705 | } |
4673 | } | 4706 | } |
4707 | impl From<MacroPat> for Pat { | ||
4708 | fn from(node: MacroPat) -> Pat { | ||
4709 | Pat::MacroPat(node) | ||
4710 | } | ||
4711 | } | ||
4674 | impl std::fmt::Display for Pat { | 4712 | impl std::fmt::Display for Pat { |
4675 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 4713 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
4676 | std::fmt::Display::fmt(self.syntax(), f) | 4714 | std::fmt::Display::fmt(self.syntax(), f) |
@@ -4681,7 +4719,7 @@ impl AstNode for Pat { | |||
4681 | match kind { | 4719 | match kind { |
4682 | OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT | 4720 | OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT |
4683 | | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | 4721 | | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT |
4684 | | LITERAL_PAT => true, | 4722 | | LITERAL_PAT | MACRO_PAT => true, |
4685 | _ => false, | 4723 | _ => false, |
4686 | } | 4724 | } |
4687 | } | 4725 | } |
@@ -4701,6 +4739,7 @@ impl AstNode for Pat { | |||
4701 | SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), | 4739 | SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), |
4702 | RANGE_PAT => Pat::RangePat(RangePat { syntax }), | 4740 | RANGE_PAT => Pat::RangePat(RangePat { syntax }), |
4703 | LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }), | 4741 | LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }), |
4742 | MACRO_PAT => Pat::MacroPat(MacroPat { syntax }), | ||
4704 | _ => return None, | 4743 | _ => return None, |
4705 | }; | 4744 | }; |
4706 | Some(res) | 4745 | Some(res) |
@@ -4721,6 +4760,7 @@ impl AstNode for Pat { | |||
4721 | Pat::SlicePat(it) => &it.syntax, | 4760 | Pat::SlicePat(it) => &it.syntax, |
4722 | Pat::RangePat(it) => &it.syntax, | 4761 | Pat::RangePat(it) => &it.syntax, |
4723 | Pat::LiteralPat(it) => &it.syntax, | 4762 | Pat::LiteralPat(it) => &it.syntax, |
4763 | Pat::MacroPat(it) => &it.syntax, | ||
4724 | } | 4764 | } |
4725 | } | 4765 | } |
4726 | } | 4766 | } |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt index b05ccc0ed..36d8f4a5f 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt | |||
@@ -15,16 +15,17 @@ SOURCE_FILE@[0; 33) | |||
15 | LET_STMT@[16; 30) | 15 | LET_STMT@[16; 30) |
16 | LET_KW@[16; 19) "let" | 16 | LET_KW@[16; 19) "let" |
17 | WHITESPACE@[19; 20) " " | 17 | WHITESPACE@[19; 20) " " |
18 | MACRO_CALL@[20; 25) | 18 | MACRO_PAT@[20; 25) |
19 | PATH@[20; 21) | 19 | MACRO_CALL@[20; 25) |
20 | PATH_SEGMENT@[20; 21) | 20 | PATH@[20; 21) |
21 | NAME_REF@[20; 21) | 21 | PATH_SEGMENT@[20; 21) |
22 | IDENT@[20; 21) "m" | 22 | NAME_REF@[20; 21) |
23 | EXCL@[21; 22) "!" | 23 | IDENT@[20; 21) "m" |
24 | TOKEN_TREE@[22; 25) | 24 | EXCL@[21; 22) "!" |
25 | L_PAREN@[22; 23) "(" | 25 | TOKEN_TREE@[22; 25) |
26 | IDENT@[23; 24) "x" | 26 | L_PAREN@[22; 23) "(" |
27 | R_PAREN@[24; 25) ")" | 27 | IDENT@[23; 24) "x" |
28 | R_PAREN@[24; 25) ")" | ||
28 | WHITESPACE@[25; 26) " " | 29 | WHITESPACE@[25; 26) " " |
29 | EQ@[26; 27) "=" | 30 | EQ@[26; 27) "=" |
30 | WHITESPACE@[27; 28) " " | 31 | WHITESPACE@[27; 28) " " |