From 2ccfb49baba6a9a0381e8a5be77df5a3c8f46205 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 25 Mar 2020 13:53:15 +0100 Subject: [PATCH] Always expand macros during analysis --- crates/ra_hir/src/semantics.rs | 6 ++-- crates/ra_hir/src/source_analyzer.rs | 44 ++++++++++++++++------------ crates/ra_ide/src/goto_definition.rs | 24 +++++++++++++-- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index d982f6ffa6..16a5fe9680 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -173,11 +173,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { } pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { - self.analyze(call.syntax()).resolve_method_call(call) + self.analyze(call.syntax()).resolve_method_call(self.db, call) } pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option { - self.analyze(field.syntax()).resolve_field(field) + self.analyze(field.syntax()).resolve_field(self.db, field) } pub fn resolve_record_field( @@ -188,7 +188,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { } pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option { - self.analyze(record_lit.syntax()).resolve_record_literal(record_lit) + self.analyze(record_lit.syntax()).resolve_record_literal(self.db, record_lit) } pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option { diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 10c12c910f..815ca158c1 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs @@ -78,9 +78,15 @@ impl SourceAnalyzer { } } - fn expr_id(&self, expr: &ast::Expr) -> Option { - let src = InFile { file_id: self.file_id, value: expr }; - self.body_source_map.as_ref()?.node_expr(src) + fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option { + let src = match expr { + ast::Expr::MacroCall(call) => { + self.expand_expr(db, InFile::new(self.file_id, call.clone()))? + } + _ => InFile::new(self.file_id, expr.clone()), + }; + let sm = self.body_source_map.as_ref()?; + sm.node_expr(src.as_ref()) } fn pat_id(&self, pat: &ast::Pat) -> Option { @@ -104,14 +110,7 @@ impl SourceAnalyzer { } pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option { - let expr_id = match expr { - ast::Expr::MacroCall(call) => { - let expr = self.expand_expr(db, InFile::new(self.file_id, call.clone()))?; - self.body_source_map.as_ref()?.node_expr(expr.as_ref()) - } - _ => self.expr_id(expr), - }?; - + let expr_id = self.expr_id(db, expr)?; let ty = self.infer.as_ref()?[expr_id].clone(); Type::new_with_resolver(db, &self.resolver, ty) } @@ -122,13 +121,21 @@ impl SourceAnalyzer { Type::new_with_resolver(db, &self.resolver, ty) } - pub(crate) fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { - let expr_id = self.expr_id(&call.clone().into())?; + pub(crate) fn resolve_method_call( + &self, + db: &dyn HirDatabase, + call: &ast::MethodCallExpr, + ) -> Option { + let expr_id = self.expr_id(db, &call.clone().into())?; self.infer.as_ref()?.method_resolution(expr_id).map(Function::from) } - pub(crate) fn resolve_field(&self, field: &ast::FieldExpr) -> Option { - let expr_id = self.expr_id(&field.clone().into())?; + pub(crate) fn resolve_field( + &self, + db: &dyn HirDatabase, + field: &ast::FieldExpr, + ) -> Option { + let expr_id = self.expr_id(db, &field.clone().into())?; self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into()) } @@ -138,7 +145,7 @@ impl SourceAnalyzer { field: &ast::RecordField, ) -> Option<(crate::StructField, Option)> { let (expr_id, local) = match field.expr() { - Some(it) => (self.expr_id(&it)?, None), + Some(it) => (self.expr_id(db, &it)?, None), None => { let src = InFile { file_id: self.file_id, value: field }; let expr_id = self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?; @@ -159,9 +166,10 @@ impl SourceAnalyzer { pub(crate) fn resolve_record_literal( &self, + db: &dyn HirDatabase, record_lit: &ast::RecordLit, ) -> Option { - let expr_id = self.expr_id(&record_lit.clone().into())?; + let expr_id = self.expr_id(db, &record_lit.clone().into())?; self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into()) } @@ -207,7 +215,7 @@ impl SourceAnalyzer { path: &ast::Path, ) -> Option { if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { - let expr_id = self.expr_id(&path_expr.into())?; + let expr_id = self.expr_id(db, &path_expr.into())?; if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { return Some(PathResolution::AssocItem(assoc.into())); } diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 502fcb0cf6..8aed94d162 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -104,6 +104,9 @@ mod tests { let (analysis, pos) = analysis_and_position(ra_fixture); let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; + if navs.len() == 0 { + panic!("unresolved reference") + } assert_eq!(navs.len(), 1); let nav = navs.pop().unwrap(); @@ -359,7 +362,7 @@ mod tests { fn goto_def_for_fields() { covers!(ra_ide_db::goto_def_for_fields); check_goto( - " + r" //- /lib.rs struct Foo { spam: u32, @@ -378,7 +381,7 @@ mod tests { fn goto_def_for_record_fields() { covers!(ra_ide_db::goto_def_for_record_fields); check_goto( - " + r" //- /lib.rs struct Foo { spam: u32, @@ -395,6 +398,23 @@ mod tests { ); } + #[test] + fn goto_def_for_record_fields_macros() { + check_goto( + r" + //- /lib.rs + macro_rules! m { () => { 92 };} + struct Foo { spam: u32 } + + fn bar() -> Foo { + Foo { spam<|>: m!() } + } + ", + "spam RECORD_FIELD_DEF FileId(1) [45; 54) [45; 49)", + "spam: u32|spam", + ); + } + #[test] fn goto_for_tuple_fields() { check_goto(