aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-03-25 12:53:15 +0000
committerAleksey Kladov <[email protected]>2020-03-25 12:53:15 +0000
commit2ccfb49baba6a9a0381e8a5be77df5a3c8f46205 (patch)
treeeedee71ea4d2535dddeb2aa56966140652d6d2c1
parente2dd17f75b1bb5e1185acff66211e74430177592 (diff)
Always expand macros during analysis
-rw-r--r--crates/ra_hir/src/semantics.rs6
-rw-r--r--crates/ra_hir/src/source_analyzer.rs44
-rw-r--r--crates/ra_ide/src/goto_definition.rs24
3 files changed, 51 insertions, 23 deletions
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index d982f6ffa..16a5fe968 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> {
173 } 173 }
174 174
175 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 175 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
176 self.analyze(call.syntax()).resolve_method_call(call) 176 self.analyze(call.syntax()).resolve_method_call(self.db, call)
177 } 177 }
178 178
179 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<StructField> { 179 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<StructField> {
180 self.analyze(field.syntax()).resolve_field(field) 180 self.analyze(field.syntax()).resolve_field(self.db, field)
181 } 181 }
182 182
183 pub fn resolve_record_field( 183 pub fn resolve_record_field(
@@ -188,7 +188,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
188 } 188 }
189 189
190 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<VariantDef> { 190 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<VariantDef> {
191 self.analyze(record_lit.syntax()).resolve_record_literal(record_lit) 191 self.analyze(record_lit.syntax()).resolve_record_literal(self.db, record_lit)
192 } 192 }
193 193
194 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<VariantDef> { 194 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<VariantDef> {
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 10c12c910..815ca158c 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -78,9 +78,15 @@ impl SourceAnalyzer {
78 } 78 }
79 } 79 }
80 80
81 fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> { 81 fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
82 let src = InFile { file_id: self.file_id, value: expr }; 82 let src = match expr {
83 self.body_source_map.as_ref()?.node_expr(src) 83 ast::Expr::MacroCall(call) => {
84 self.expand_expr(db, InFile::new(self.file_id, call.clone()))?
85 }
86 _ => InFile::new(self.file_id, expr.clone()),
87 };
88 let sm = self.body_source_map.as_ref()?;
89 sm.node_expr(src.as_ref())
84 } 90 }
85 91
86 fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { 92 fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
@@ -104,14 +110,7 @@ impl SourceAnalyzer {
104 } 110 }
105 111
106 pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { 112 pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> {
107 let expr_id = match expr { 113 let expr_id = self.expr_id(db, expr)?;
108 ast::Expr::MacroCall(call) => {
109 let expr = self.expand_expr(db, InFile::new(self.file_id, call.clone()))?;
110 self.body_source_map.as_ref()?.node_expr(expr.as_ref())
111 }
112 _ => self.expr_id(expr),
113 }?;
114
115 let ty = self.infer.as_ref()?[expr_id].clone(); 114 let ty = self.infer.as_ref()?[expr_id].clone();
116 Type::new_with_resolver(db, &self.resolver, ty) 115 Type::new_with_resolver(db, &self.resolver, ty)
117 } 116 }
@@ -122,13 +121,21 @@ impl SourceAnalyzer {
122 Type::new_with_resolver(db, &self.resolver, ty) 121 Type::new_with_resolver(db, &self.resolver, ty)
123 } 122 }
124 123
125 pub(crate) fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 124 pub(crate) fn resolve_method_call(
126 let expr_id = self.expr_id(&call.clone().into())?; 125 &self,
126 db: &dyn HirDatabase,
127 call: &ast::MethodCallExpr,
128 ) -> Option<Function> {
129 let expr_id = self.expr_id(db, &call.clone().into())?;
127 self.infer.as_ref()?.method_resolution(expr_id).map(Function::from) 130 self.infer.as_ref()?.method_resolution(expr_id).map(Function::from)
128 } 131 }
129 132
130 pub(crate) fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { 133 pub(crate) fn resolve_field(
131 let expr_id = self.expr_id(&field.clone().into())?; 134 &self,
135 db: &dyn HirDatabase,
136 field: &ast::FieldExpr,
137 ) -> Option<crate::StructField> {
138 let expr_id = self.expr_id(db, &field.clone().into())?;
132 self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into()) 139 self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into())
133 } 140 }
134 141
@@ -138,7 +145,7 @@ impl SourceAnalyzer {
138 field: &ast::RecordField, 145 field: &ast::RecordField,
139 ) -> Option<(crate::StructField, Option<Local>)> { 146 ) -> Option<(crate::StructField, Option<Local>)> {
140 let (expr_id, local) = match field.expr() { 147 let (expr_id, local) = match field.expr() {
141 Some(it) => (self.expr_id(&it)?, None), 148 Some(it) => (self.expr_id(db, &it)?, None),
142 None => { 149 None => {
143 let src = InFile { file_id: self.file_id, value: field }; 150 let src = InFile { file_id: self.file_id, value: field };
144 let expr_id = self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?; 151 let expr_id = self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?;
@@ -159,9 +166,10 @@ impl SourceAnalyzer {
159 166
160 pub(crate) fn resolve_record_literal( 167 pub(crate) fn resolve_record_literal(
161 &self, 168 &self,
169 db: &dyn HirDatabase,
162 record_lit: &ast::RecordLit, 170 record_lit: &ast::RecordLit,
163 ) -> Option<crate::VariantDef> { 171 ) -> Option<crate::VariantDef> {
164 let expr_id = self.expr_id(&record_lit.clone().into())?; 172 let expr_id = self.expr_id(db, &record_lit.clone().into())?;
165 self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into()) 173 self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into())
166 } 174 }
167 175
@@ -207,7 +215,7 @@ impl SourceAnalyzer {
207 path: &ast::Path, 215 path: &ast::Path,
208 ) -> Option<PathResolution> { 216 ) -> Option<PathResolution> {
209 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { 217 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
210 let expr_id = self.expr_id(&path_expr.into())?; 218 let expr_id = self.expr_id(db, &path_expr.into())?;
211 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { 219 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
212 return Some(PathResolution::AssocItem(assoc.into())); 220 return Some(PathResolution::AssocItem(assoc.into()));
213 } 221 }
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index 502fcb0cf..8aed94d16 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -104,6 +104,9 @@ mod tests {
104 let (analysis, pos) = analysis_and_position(ra_fixture); 104 let (analysis, pos) = analysis_and_position(ra_fixture);
105 105
106 let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; 106 let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info;
107 if navs.len() == 0 {
108 panic!("unresolved reference")
109 }
107 assert_eq!(navs.len(), 1); 110 assert_eq!(navs.len(), 1);
108 111
109 let nav = navs.pop().unwrap(); 112 let nav = navs.pop().unwrap();
@@ -359,7 +362,7 @@ mod tests {
359 fn goto_def_for_fields() { 362 fn goto_def_for_fields() {
360 covers!(ra_ide_db::goto_def_for_fields); 363 covers!(ra_ide_db::goto_def_for_fields);
361 check_goto( 364 check_goto(
362 " 365 r"
363 //- /lib.rs 366 //- /lib.rs
364 struct Foo { 367 struct Foo {
365 spam: u32, 368 spam: u32,
@@ -378,7 +381,7 @@ mod tests {
378 fn goto_def_for_record_fields() { 381 fn goto_def_for_record_fields() {
379 covers!(ra_ide_db::goto_def_for_record_fields); 382 covers!(ra_ide_db::goto_def_for_record_fields);
380 check_goto( 383 check_goto(
381 " 384 r"
382 //- /lib.rs 385 //- /lib.rs
383 struct Foo { 386 struct Foo {
384 spam: u32, 387 spam: u32,
@@ -396,6 +399,23 @@ mod tests {
396 } 399 }
397 400
398 #[test] 401 #[test]
402 fn goto_def_for_record_fields_macros() {
403 check_goto(
404 r"
405 //- /lib.rs
406 macro_rules! m { () => { 92 };}
407 struct Foo { spam: u32 }
408
409 fn bar() -> Foo {
410 Foo { spam<|>: m!() }
411 }
412 ",
413 "spam RECORD_FIELD_DEF FileId(1) [45; 54) [45; 49)",
414 "spam: u32|spam",
415 );
416 }
417
418 #[test]
399 fn goto_for_tuple_fields() { 419 fn goto_for_tuple_fields() {
400 check_goto( 420 check_goto(
401 " 421 "