diff options
-rw-r--r-- | crates/ra_hir/src/expr.rs | 53 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 24 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 11 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0129_marco_pat.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0129_marco_pat.txt | 36 |
5 files changed, 93 insertions, 34 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index db74d28e8..cdadf3ba6 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -10,7 +10,7 @@ use ra_syntax::{ | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | Path, Name, HirDatabase, Resolver,DefWithBody, Either, | 13 | Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId, |
14 | name::AsName, | 14 | name::AsName, |
15 | ids::{MacroCallId}, | 15 | ids::{MacroCallId}, |
16 | type_ref::{Mutability, TypeRef}, | 16 | type_ref::{Mutability, TypeRef}, |
@@ -488,15 +488,19 @@ pub(crate) struct ExprCollector<DB> { | |||
488 | params: Vec<PatId>, | 488 | params: Vec<PatId>, |
489 | body_expr: Option<ExprId>, | 489 | body_expr: Option<ExprId>, |
490 | resolver: Resolver, | 490 | resolver: Resolver, |
491 | // FIXEME: Its a quick hack,see issue #1196 | 491 | // Expr collector expands macros along the way. original points to the file |
492 | is_in_macro: bool, | 492 | // we started with, current points to the current macro expansion. source |
493 | // maps don't support macros yet, so we only record info into source map if | ||
494 | // current == original (see #1196) | ||
495 | original_file_id: HirFileId, | ||
496 | current_file_id: HirFileId, | ||
493 | } | 497 | } |
494 | 498 | ||
495 | impl<'a, DB> ExprCollector<&'a DB> | 499 | impl<'a, DB> ExprCollector<&'a DB> |
496 | where | 500 | where |
497 | DB: HirDatabase, | 501 | DB: HirDatabase, |
498 | { | 502 | { |
499 | fn new(owner: DefWithBody, resolver: Resolver, db: &'a DB) -> Self { | 503 | fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self { |
500 | ExprCollector { | 504 | ExprCollector { |
501 | owner, | 505 | owner, |
502 | resolver, | 506 | resolver, |
@@ -506,23 +510,23 @@ where | |||
506 | source_map: BodySourceMap::default(), | 510 | source_map: BodySourceMap::default(), |
507 | params: Vec::new(), | 511 | params: Vec::new(), |
508 | body_expr: None, | 512 | body_expr: None, |
509 | is_in_macro: false, | 513 | original_file_id: file_id, |
514 | current_file_id: file_id, | ||
510 | } | 515 | } |
511 | } | 516 | } |
512 | fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId { | 517 | fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId { |
513 | let id = self.exprs.alloc(expr); | 518 | let id = self.exprs.alloc(expr); |
514 | if !self.is_in_macro { | 519 | if self.current_file_id == self.original_file_id { |
515 | self.source_map.expr_map.insert(syntax_ptr, id); | 520 | self.source_map.expr_map.insert(syntax_ptr, id); |
516 | self.source_map.expr_map_back.insert(id, syntax_ptr); | 521 | self.source_map.expr_map_back.insert(id, syntax_ptr); |
517 | } | 522 | } |
518 | |||
519 | id | 523 | id |
520 | } | 524 | } |
521 | 525 | ||
522 | fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { | 526 | fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { |
523 | let id = self.pats.alloc(pat); | 527 | let id = self.pats.alloc(pat); |
524 | 528 | ||
525 | if !self.is_in_macro { | 529 | if self.current_file_id == self.original_file_id { |
526 | self.source_map.pat_map.insert(ptr, id); | 530 | self.source_map.pat_map.insert(ptr, id); |
527 | self.source_map.pat_map_back.insert(id, ptr); | 531 | self.source_map.pat_map_back.insert(id, ptr); |
528 | } | 532 | } |
@@ -815,12 +819,19 @@ where | |||
815 | // very hacky.FIXME change to use the macro resolution | 819 | // very hacky.FIXME change to use the macro resolution |
816 | let path = e.path().and_then(Path::from_ast); | 820 | let path = e.path().and_then(Path::from_ast); |
817 | 821 | ||
818 | if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, e) { | 822 | let ast_id = self |
823 | .db | ||
824 | .ast_id_map(self.current_file_id) | ||
825 | .ast_id(e) | ||
826 | .with_file_id(self.current_file_id); | ||
827 | |||
828 | if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, ast_id) { | ||
819 | if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) { | 829 | if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) { |
820 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); | 830 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); |
821 | let old = std::mem::replace(&mut self.is_in_macro, true); | 831 | let old_file_id = |
832 | std::mem::replace(&mut self.current_file_id, call_id.into()); | ||
822 | let id = self.collect_expr(&expr); | 833 | let id = self.collect_expr(&expr); |
823 | self.is_in_macro = old; | 834 | self.current_file_id = old_file_id; |
824 | id | 835 | id |
825 | } else { | 836 | } else { |
826 | // FIXME: Instead of just dropping the error from expansion | 837 | // FIXME: Instead of just dropping the error from expansion |
@@ -1006,12 +1017,24 @@ pub(crate) fn body_with_source_map_query( | |||
1006 | db: &impl HirDatabase, | 1017 | db: &impl HirDatabase, |
1007 | def: DefWithBody, | 1018 | def: DefWithBody, |
1008 | ) -> (Arc<Body>, Arc<BodySourceMap>) { | 1019 | ) -> (Arc<Body>, Arc<BodySourceMap>) { |
1009 | let mut collector = ExprCollector::new(def, def.resolver(db), db); | 1020 | let mut collector; |
1010 | 1021 | ||
1011 | match def { | 1022 | match def { |
1012 | DefWithBody::Const(ref c) => collector.collect_const_body(&c.source(db).1), | 1023 | DefWithBody::Const(ref c) => { |
1013 | DefWithBody::Function(ref f) => collector.collect_fn_body(&f.source(db).1), | 1024 | let (file_id, src) = c.source(db); |
1014 | DefWithBody::Static(ref s) => collector.collect_static_body(&s.source(db).1), | 1025 | collector = ExprCollector::new(def, file_id, def.resolver(db), db); |
1026 | collector.collect_const_body(&src) | ||
1027 | } | ||
1028 | DefWithBody::Function(ref f) => { | ||
1029 | let (file_id, src) = f.source(db); | ||
1030 | collector = ExprCollector::new(def, file_id, def.resolver(db), db); | ||
1031 | collector.collect_fn_body(&src) | ||
1032 | } | ||
1033 | DefWithBody::Static(ref s) => { | ||
1034 | let (file_id, src) = s.source(db); | ||
1035 | collector = ExprCollector::new(def, file_id, def.resolver(db), db); | ||
1036 | collector.collect_static_body(&src) | ||
1037 | } | ||
1015 | } | 1038 | } |
1016 | 1039 | ||
1017 | let (body, source_map) = collector.finish(); | 1040 | let (body, source_map) = collector.finish(); |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index d1f97c104..bc9170cdc 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -10,6 +10,7 @@ use crate::{ | |||
10 | code_model_api::Crate, | 10 | code_model_api::Crate, |
11 | MacroCallId, | 11 | MacroCallId, |
12 | MacroCallLoc, | 12 | MacroCallLoc, |
13 | AstId, | ||
13 | db::HirDatabase, | 14 | db::HirDatabase, |
14 | name::{Name, KnownName}, | 15 | name::{Name, KnownName}, |
15 | nameres::{PerNs, CrateDefMap, CrateModuleId}, | 16 | nameres::{PerNs, CrateDefMap, CrateModuleId}, |
@@ -17,7 +18,7 @@ use crate::{ | |||
17 | expr::{scope::{ExprScopes, ScopeId}, PatId}, | 18 | expr::{scope::{ExprScopes, ScopeId}, PatId}, |
18 | impl_block::ImplBlock, | 19 | impl_block::ImplBlock, |
19 | path::Path, | 20 | path::Path, |
20 | Trait | 21 | Trait, |
21 | }; | 22 | }; |
22 | 23 | ||
23 | #[derive(Debug, Clone, Default)] | 24 | #[derive(Debug, Clone, Default)] |
@@ -138,25 +139,12 @@ impl Resolver { | |||
138 | &self, | 139 | &self, |
139 | db: &impl HirDatabase, | 140 | db: &impl HirDatabase, |
140 | path: Option<Path>, | 141 | path: Option<Path>, |
141 | call: &ast::MacroCall, | 142 | ast_id: AstId<ast::MacroCall>, |
142 | ) -> Option<MacroCallId> { | 143 | ) -> Option<MacroCallId> { |
143 | let name = path.and_then(|path| path.expand_macro_expr()).unwrap_or_else(Name::missing); | 144 | let name = path.and_then(|path| path.expand_macro_expr()).unwrap_or_else(Name::missing); |
144 | let macro_def_id = self.module().and_then(|(module, _)| module.find_macro(&name)); | 145 | let def_id = self.module().and_then(|(module, _)| module.find_macro(&name))?; |
145 | if let Some(def_id) = macro_def_id { | 146 | let call_loc = MacroCallLoc { def: *def_id, ast_id }.id(db); |
146 | self.module().and_then(|(module, _)| { | 147 | Some(call_loc) |
147 | // we do this to get the ast_id for the macro call | ||
148 | // if we used the ast_id from the def_id variable | ||
149 | // it gives us the ast_id of the defenition site | ||
150 | let module = module.mk_module(module.root()); | ||
151 | let hir_file_id = module.definition_source(db).0; | ||
152 | let ast_id = db.ast_id_map(hir_file_id).ast_id(call).with_file_id(hir_file_id); | ||
153 | let call_loc = MacroCallLoc { def: *def_id, ast_id }.id(db); | ||
154 | |||
155 | Some(call_loc) | ||
156 | }) | ||
157 | } else { | ||
158 | None | ||
159 | } | ||
160 | } | 148 | } |
161 | 149 | ||
162 | /// Returns the resolved path segments | 150 | /// Returns the resolved path segments |
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 03fa9b71e..12dd22bde 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -40,6 +40,15 @@ pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { | |||
40 | atom_pat(p, recovery_set); | 40 | atom_pat(p, recovery_set); |
41 | m.complete(p, RANGE_PAT); | 41 | m.complete(p, RANGE_PAT); |
42 | } | 42 | } |
43 | // test marco_pat | ||
44 | // fn main() { | ||
45 | // let m!(x) = 0; | ||
46 | // } | ||
47 | else if lhs.kind() == PATH_PAT && p.at(EXCL) { | ||
48 | let m = lhs.precede(p); | ||
49 | items::macro_call_after_excl(p); | ||
50 | m.complete(p, MACRO_CALL); | ||
51 | } | ||
43 | } | 52 | } |
44 | } | 53 | } |
45 | 54 | ||
@@ -51,7 +60,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { | |||
51 | let la1 = p.nth(1); | 60 | let la1 = p.nth(1); |
52 | if la0 == REF_KW | 61 | if la0 == REF_KW |
53 | || la0 == MUT_KW | 62 | || la0 == MUT_KW |
54 | || (la0 == IDENT && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY)) | 63 | || (la0 == IDENT && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY || la1 == EXCL)) |
55 | { | 64 | { |
56 | return Some(bind_pat(p, true)); | 65 | return Some(bind_pat(p, true)); |
57 | } | 66 | } |
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0129_marco_pat.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0129_marco_pat.rs new file mode 100644 index 000000000..811181d9b --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0129_marco_pat.rs | |||
@@ -0,0 +1,3 @@ | |||
1 | fn main() { | ||
2 | let m!(x) = 0; | ||
3 | } | ||
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0129_marco_pat.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0129_marco_pat.txt new file mode 100644 index 000000000..50b4ab2e7 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0129_marco_pat.txt | |||
@@ -0,0 +1,36 @@ | |||
1 | SOURCE_FILE@[0; 33) | ||
2 | FN_DEF@[0; 32) | ||
3 | FN_KW@[0; 2) "fn" | ||
4 | WHITESPACE@[2; 3) " " | ||
5 | NAME@[3; 7) | ||
6 | IDENT@[3; 7) "main" | ||
7 | PARAM_LIST@[7; 9) | ||
8 | L_PAREN@[7; 8) "(" | ||
9 | R_PAREN@[8; 9) ")" | ||
10 | WHITESPACE@[9; 10) " " | ||
11 | BLOCK@[10; 32) | ||
12 | L_CURLY@[10; 11) "{" | ||
13 | WHITESPACE@[11; 16) "\n " | ||
14 | LET_STMT@[16; 30) | ||
15 | LET_KW@[16; 19) "let" | ||
16 | WHITESPACE@[19; 20) " " | ||
17 | MACRO_CALL@[20; 25) | ||
18 | PATH_PAT@[20; 21) | ||
19 | PATH@[20; 21) | ||
20 | PATH_SEGMENT@[20; 21) | ||
21 | NAME_REF@[20; 21) | ||
22 | IDENT@[20; 21) "m" | ||
23 | EXCL@[21; 22) "!" | ||
24 | TOKEN_TREE@[22; 25) | ||
25 | L_PAREN@[22; 23) "(" | ||
26 | IDENT@[23; 24) "x" | ||
27 | R_PAREN@[24; 25) ")" | ||
28 | WHITESPACE@[25; 26) " " | ||
29 | EQ@[26; 27) "=" | ||
30 | WHITESPACE@[27; 28) " " | ||
31 | LITERAL@[28; 29) | ||
32 | INT_NUMBER@[28; 29) "0" | ||
33 | SEMI@[29; 30) ";" | ||
34 | WHITESPACE@[30; 31) "\n" | ||
35 | R_CURLY@[31; 32) "}" | ||
36 | WHITESPACE@[32; 33) "\n" | ||