diff options
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 44 | ||||
-rw-r--r-- | 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 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 | " |