From 16156d766dd8a5624d9455ffded6358fe879c416 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Mon, 23 Dec 2019 13:18:28 +0800 Subject: Add macro call support for type_of --- crates/ra_hir/src/source_binder.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 85b378483..3af477818 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -17,7 +17,7 @@ use hir_def::{ nameres::ModuleSource, path::path, resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, - AssocItemId, DefWithBodyId, + AssocItemId, DefWithBodyId, Expander, }; use hir_expand::{ hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, @@ -216,7 +216,14 @@ impl SourceAnalyzer { } pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option { - let expr_id = self.expr_id(expr)?; + let expr_id = if let Some(macro_call) = ast::MacroCall::cast(expr.syntax().clone()) { + let mut expander = Expander::new(db, self.file_id, self.body_owner?.module(db).id); + let expr = expand_macro_call_to_expr(db, &mut expander, macro_call)?; + self.body_source_map.as_ref()?.node_expr(expr.as_ref())? + } else { + self.expr_id(expr)? + }; + let ty = self.infer.as_ref()?[expr_id].clone(); let environment = TraitEnvironment::lower(db, &self.resolver); Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) @@ -501,6 +508,21 @@ fn scope_for_offset( }) } +fn expand_macro_call_to_expr( + db: &impl HirDatabase, + expander: &mut Expander, + macro_call: ast::MacroCall, +) -> Option> { + let (mark, expr): (_, ast::Expr) = expander.enter_expand(db, macro_call)?; + let expr = if let Some(child) = ast::MacroCall::cast(expr.syntax().clone()) { + expand_macro_call_to_expr(db, expander, child) + } else { + Some(expander.to_source(expr)) + }; + expander.exit(db, mark); + expr +} + // XXX: during completion, cursor might be outside of any particular // expression. Try to figure out the correct scope... fn adjust( -- cgit v1.2.3 From 12cc2ed5572e4df8cfbdaef79ed3c865fda0764c Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Mon, 23 Dec 2019 21:47:11 +0800 Subject: Use pre-stored macro file --- crates/ra_hir/src/source_binder.rs | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 3af477818..2c422af8b 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -17,7 +17,7 @@ use hir_def::{ nameres::ModuleSource, path::path, resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, - AssocItemId, DefWithBodyId, Expander, + AssocItemId, DefWithBodyId, }; use hir_expand::{ hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, @@ -215,10 +215,27 @@ impl SourceAnalyzer { self.body_source_map.as_ref()?.node_pat(src) } + fn expand_expr( + &self, + db: &impl HirDatabase, + expr: InFile<&ast::Expr>, + ) -> Option> { + let macro_call = ast::MacroCall::cast(expr.value.syntax().clone())?; + let macro_file = + self.body_source_map.as_ref()?.node_macro_file(expr.with_value(¯o_call))?; + let expanded = db.parse_or_expand(macro_file)?; + let kind = expanded.kind(); + let expr = InFile::new(macro_file, ast::Expr::cast(expanded)?); + + if ast::MacroCall::can_cast(kind) { + self.expand_expr(db, expr.as_ref()) + } else { + Some(expr) + } + } + pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option { - let expr_id = if let Some(macro_call) = ast::MacroCall::cast(expr.syntax().clone()) { - let mut expander = Expander::new(db, self.file_id, self.body_owner?.module(db).id); - let expr = expand_macro_call_to_expr(db, &mut expander, macro_call)?; + let expr_id = if let Some(expr) = self.expand_expr(db, InFile::new(self.file_id, expr)) { self.body_source_map.as_ref()?.node_expr(expr.as_ref())? } else { self.expr_id(expr)? @@ -508,21 +525,6 @@ fn scope_for_offset( }) } -fn expand_macro_call_to_expr( - db: &impl HirDatabase, - expander: &mut Expander, - macro_call: ast::MacroCall, -) -> Option> { - let (mark, expr): (_, ast::Expr) = expander.enter_expand(db, macro_call)?; - let expr = if let Some(child) = ast::MacroCall::cast(expr.syntax().clone()) { - expand_macro_call_to_expr(db, expander, child) - } else { - Some(expander.to_source(expr)) - }; - expander.exit(db, mark); - expr -} - // XXX: during completion, cursor might be outside of any particular // expression. Try to figure out the correct scope... fn adjust( -- cgit v1.2.3