diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 28c570c769b..8d4b8b0f0fb 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<'_> { } // FIXME: implement - ast::Pat::BoxPat(_) => Pat::Missing, - ast::Pat::RangePat(_) => Pat::Missing, + ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, }; let ptr = AstPtr::new(&pat); 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 eb97288f189..ff4599b7128 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -1,8 +1,10 @@ -use super::{infer, type_at, type_at_pos}; -use crate::test_db::TestDB; use insta::assert_snapshot; use ra_db::fixture::WithFixture; +use super::{infer, type_at, type_at_pos}; + +use crate::test_db::TestDB; + #[test] fn cfg_impl_def() { let (db, pos) = TestDB::with_position( @@ -658,3 +660,28 @@ fn test() { ); assert_eq!("S", type_at_pos(&db, pos)); } + +#[test] +fn macro_in_arm() { + assert_snapshot!( + infer(r#" +macro_rules! unit { + () => { () }; +} + +fn main() { + let x = match () { + unit!() => 92u32, + }; +} +"#), + @r###" + [52; 111) '{ ... }; }': () + [62; 63) 'x': u32 + [66; 108) 'match ... }': u32 + [72; 74) '()': () + [85; 92) 'unit!()': () + [96; 101) '92u32': u32 + "### + ); +} diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 9bfdcfd41ad..936d27575c9 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 { // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro // (T![x]). T!['('] | T!['{'] | T![!] => path_or_macro_pat(p), - T![:] if p.nth_at(1, T![::]) => path_pat(p), + T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p), _ => bind_pat(p, true), }, @@ -156,7 +156,7 @@ fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker { // } T![!] => { items::macro_call_after_excl(p); - MACRO_CALL + return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT); } _ => PATH_PAT, }; diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index dfc30d72783..4c16cf1cd9a 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 { SLICE_PAT, RANGE_PAT, LITERAL_PAT, + MACRO_PAT, TUPLE_EXPR, ARRAY_EXPR, PAREN_EXPR, diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 7204ca5b172..0c339b9879d 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -2563,6 +2563,38 @@ impl LiteralPat { } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MacroPat { + pub(crate) syntax: SyntaxNode, +} +impl std::fmt::Display for MacroPat { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl AstNode for MacroPat { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + MACRO_PAT => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} +impl MacroPat { + pub fn macro_call(&self) -> Option { + AstChildren::new(&self.syntax).next() + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordPat { pub(crate) syntax: SyntaxNode, } @@ -4600,6 +4632,7 @@ pub enum Pat { SlicePat(SlicePat), RangePat(RangePat), LiteralPat(LiteralPat), + MacroPat(MacroPat), } impl From for Pat { fn from(node: OrPat) -> Pat { @@ -4671,6 +4704,11 @@ impl From for Pat { Pat::LiteralPat(node) } } +impl From for Pat { + fn from(node: MacroPat) -> Pat { + Pat::MacroPat(node) + } +} impl std::fmt::Display for Pat { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -4681,7 +4719,7 @@ impl AstNode for Pat { match kind { OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT - | LITERAL_PAT => true, + | LITERAL_PAT | MACRO_PAT => true, _ => false, } } @@ -4701,6 +4739,7 @@ impl AstNode for Pat { SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), RANGE_PAT => Pat::RangePat(RangePat { syntax }), LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }), + MACRO_PAT => Pat::MacroPat(MacroPat { syntax }), _ => return None, }; Some(res) @@ -4721,6 +4760,7 @@ impl AstNode for Pat { Pat::SlicePat(it) => &it.syntax, Pat::RangePat(it) => &it.syntax, Pat::LiteralPat(it) => &it.syntax, + Pat::MacroPat(it) => &it.syntax, } } } 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 b05ccc0ed57..36d8f4a5f5c 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) LET_STMT@[16; 30) LET_KW@[16; 19) "let" WHITESPACE@[19; 20) " " - MACRO_CALL@[20; 25) - PATH@[20; 21) - PATH_SEGMENT@[20; 21) - NAME_REF@[20; 21) - IDENT@[20; 21) "m" - EXCL@[21; 22) "!" - TOKEN_TREE@[22; 25) - L_PAREN@[22; 23) "(" - IDENT@[23; 24) "x" - R_PAREN@[24; 25) ")" + MACRO_PAT@[20; 25) + MACRO_CALL@[20; 25) + PATH@[20; 21) + PATH_SEGMENT@[20; 21) + NAME_REF@[20; 21) + IDENT@[20; 21) "m" + EXCL@[21; 22) "!" + TOKEN_TREE@[22; 25) + L_PAREN@[22; 23) "(" + IDENT@[23; 24) "x" + R_PAREN@[24; 25) ")" WHITESPACE@[25; 26) " " EQ@[26; 27) "=" WHITESPACE@[27; 28) " " diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 99bd601989f..d9f51ec3994 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -138,6 +138,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { "SLICE_PAT", "RANGE_PAT", "LITERAL_PAT", + "MACRO_PAT", // atoms "TUPLE_EXPR", "ARRAY_EXPR", @@ -440,6 +441,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { struct SlicePat { args: [Pat] } struct RangePat {} struct LiteralPat { Literal } + struct MacroPat { MacroCall } struct RecordPat { RecordFieldPatList, Path } struct RecordFieldPatList { @@ -622,6 +624,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { SlicePat, RangePat, LiteralPat, + MacroPat, } enum AttrInput { Literal, TokenTree }