aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-12-20 13:47:01 +0000
committerAleksey Kladov <[email protected]>2019-12-20 13:48:14 +0000
commit3d4b48e481da35f19366514c0e22ed42fef037a0 (patch)
tree9e4ff021db736a76bc82555886d868cd7429f021
parenta0571359f3ea5361f1676b0777b578c6deefdc7d (diff)
Fix resolve for field init shorthand
-rw-r--r--crates/ra_hir/src/from_source.rs16
-rw-r--r--crates/ra_hir/src/source_binder.rs8
-rw-r--r--crates/ra_hir_def/src/body.rs5
-rw-r--r--crates/ra_ide/src/goto_definition.rs57
-rw-r--r--crates/ra_ide/src/marks.rs9
-rw-r--r--crates/ra_ide/src/references/classify.rs9
6 files changed, 68 insertions, 36 deletions
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 3b6454a1d..42ca55fe7 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,4 +1,6 @@
1//! FIXME: write short doc here 1//! Finds a corresponding hir data structure for a syntax node in a specific
2//! file.
3
2use hir_def::{ 4use hir_def::{
3 child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, 5 child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource,
4 ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, 6 ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId,
@@ -11,14 +13,14 @@ use ra_syntax::{
11}; 13};
12 14
13use crate::{ 15use crate::{
14 db::{AstDatabase, DefDatabase, HirDatabase}, 16 db::{DefDatabase, HirDatabase},
15 Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, 17 Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local,
16 MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, 18 MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union,
17}; 19};
18 20
19pub trait FromSource: Sized { 21pub trait FromSource: Sized {
20 type Ast; 22 type Ast;
21 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self>; 23 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self>;
22} 24}
23 25
24pub trait FromSourceByContainer: Sized { 26pub trait FromSourceByContainer: Sized {
@@ -32,7 +34,7 @@ where
32 T: From<<T as FromSourceByContainer>::Id>, 34 T: From<<T as FromSourceByContainer>::Id>,
33{ 35{
34 type Ast = <T as FromSourceByContainer>::Ast; 36 type Ast = <T as FromSourceByContainer>::Ast;
35 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 37 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> {
36 analyze_container(db, src.as_ref().map(|it| it.syntax()))[T::KEY] 38 analyze_container(db, src.as_ref().map(|it| it.syntax()))[T::KEY]
37 .get(&src) 39 .get(&src)
38 .copied() 40 .copied()
@@ -64,7 +66,7 @@ from_source_by_container_impls![
64 66
65impl FromSource for MacroDef { 67impl FromSource for MacroDef {
66 type Ast = ast::MacroCall; 68 type Ast = ast::MacroCall;
67 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 69 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> {
68 let kind = MacroDefKind::Declarative; 70 let kind = MacroDefKind::Declarative;
69 71
70 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); 72 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
@@ -80,7 +82,7 @@ impl FromSource for MacroDef {
80 82
81impl FromSource for EnumVariant { 83impl FromSource for EnumVariant {
82 type Ast = ast::EnumVariant; 84 type Ast = ast::EnumVariant;
83 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 85 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> {
84 let parent_enum = src.value.parent_enum(); 86 let parent_enum = src.value.parent_enum();
85 let src_enum = InFile { file_id: src.file_id, value: parent_enum }; 87 let src_enum = InFile { file_id: src.file_id, value: parent_enum };
86 let parent_enum = Enum::from_source(db, src_enum)?; 88 let parent_enum = Enum::from_source(db, src_enum)?;
@@ -93,7 +95,7 @@ impl FromSource for EnumVariant {
93 95
94impl FromSource for StructField { 96impl FromSource for StructField {
95 type Ast = FieldSource; 97 type Ast = FieldSource;
96 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 98 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> {
97 let src = src.as_ref(); 99 let src = src.as_ref();
98 100
99 // FIXME this is buggy 101 // FIXME this is buggy
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index d326169b3..b60a6b87e 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -237,7 +237,13 @@ impl SourceAnalyzer {
237 } 237 }
238 238
239 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> { 239 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> {
240 let expr_id = self.expr_id(&field.expr()?)?; 240 let expr_id = match field.expr() {
241 Some(it) => self.expr_id(&it)?,
242 None => {
243 let src = InFile { file_id: self.file_id, value: field };
244 self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?
245 }
246 };
241 self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into()) 247 self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into())
242 } 248 }
243 249
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 92c32b080..401fe0b9b 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -229,6 +229,11 @@ impl BodySourceMap {
229 self.expr_map.get(&src).cloned() 229 self.expr_map.get(&src).cloned()
230 } 230 }
231 231
232 pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
233 let src = node.map(|it| Either::Right(AstPtr::new(it)));
234 self.expr_map.get(&src).cloned()
235 }
236
232 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> { 237 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> {
233 self.pat_map_back.get(pat).copied() 238 self.pat_map_back.get(pat).copied()
234 } 239 }
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index ee4ae3e03..9b5744789 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -258,7 +258,7 @@ mod tests {
258 } 258 }
259 259
260 #[test] 260 #[test]
261 fn goto_definition_works_in_items() { 261 fn goto_def_in_items() {
262 check_goto( 262 check_goto(
263 " 263 "
264 //- /lib.rs 264 //- /lib.rs
@@ -271,7 +271,7 @@ mod tests {
271 } 271 }
272 272
273 #[test] 273 #[test]
274 fn goto_definition_works_at_start_of_item() { 274 fn goto_def_at_start_of_item() {
275 check_goto( 275 check_goto(
276 " 276 "
277 //- /lib.rs 277 //- /lib.rs
@@ -305,7 +305,7 @@ mod tests {
305 } 305 }
306 306
307 #[test] 307 #[test]
308 fn goto_definition_works_for_module_declaration() { 308 fn goto_def_for_module_declaration() {
309 check_goto( 309 check_goto(
310 " 310 "
311 //- /lib.rs 311 //- /lib.rs
@@ -332,8 +332,8 @@ mod tests {
332 } 332 }
333 333
334 #[test] 334 #[test]
335 fn goto_definition_works_for_macros() { 335 fn goto_def_for_macros() {
336 covers!(goto_definition_works_for_macros); 336 covers!(goto_def_for_macros);
337 check_goto( 337 check_goto(
338 " 338 "
339 //- /lib.rs 339 //- /lib.rs
@@ -349,8 +349,8 @@ mod tests {
349 } 349 }
350 350
351 #[test] 351 #[test]
352 fn goto_definition_works_for_macros_from_other_crates() { 352 fn goto_def_for_macros_from_other_crates() {
353 covers!(goto_definition_works_for_macros); 353 covers!(goto_def_for_macros);
354 check_goto( 354 check_goto(
355 " 355 "
356 //- /lib.rs 356 //- /lib.rs
@@ -369,7 +369,7 @@ mod tests {
369 } 369 }
370 370
371 #[test] 371 #[test]
372 fn goto_definition_works_for_macros_in_use_tree() { 372 fn goto_def_for_macros_in_use_tree() {
373 check_goto( 373 check_goto(
374 " 374 "
375 //- /lib.rs 375 //- /lib.rs
@@ -385,7 +385,7 @@ mod tests {
385 } 385 }
386 386
387 #[test] 387 #[test]
388 fn goto_definition_works_for_macro_defined_fn_with_arg() { 388 fn goto_def_for_macro_defined_fn_with_arg() {
389 check_goto( 389 check_goto(
390 " 390 "
391 //- /lib.rs 391 //- /lib.rs
@@ -405,7 +405,7 @@ mod tests {
405 } 405 }
406 406
407 #[test] 407 #[test]
408 fn goto_definition_works_for_macro_defined_fn_no_arg() { 408 fn goto_def_for_macro_defined_fn_no_arg() {
409 check_goto( 409 check_goto(
410 " 410 "
411 //- /lib.rs 411 //- /lib.rs
@@ -425,8 +425,8 @@ mod tests {
425 } 425 }
426 426
427 #[test] 427 #[test]
428 fn goto_definition_works_for_methods() { 428 fn goto_def_for_methods() {
429 covers!(goto_definition_works_for_methods); 429 covers!(goto_def_for_methods);
430 check_goto( 430 check_goto(
431 " 431 "
432 //- /lib.rs 432 //- /lib.rs
@@ -445,8 +445,8 @@ mod tests {
445 } 445 }
446 446
447 #[test] 447 #[test]
448 fn goto_definition_works_for_fields() { 448 fn goto_def_for_fields() {
449 covers!(goto_definition_works_for_fields); 449 covers!(goto_def_for_fields);
450 check_goto( 450 check_goto(
451 " 451 "
452 //- /lib.rs 452 //- /lib.rs
@@ -464,8 +464,8 @@ mod tests {
464 } 464 }
465 465
466 #[test] 466 #[test]
467 fn goto_definition_works_for_record_fields() { 467 fn goto_def_for_record_fields() {
468 covers!(goto_definition_works_for_record_fields); 468 covers!(goto_def_for_record_fields);
469 check_goto( 469 check_goto(
470 " 470 "
471 //- /lib.rs 471 //- /lib.rs
@@ -502,7 +502,7 @@ mod tests {
502 } 502 }
503 503
504 #[test] 504 #[test]
505 fn goto_definition_works_for_ufcs_inherent_methods() { 505 fn goto_def_for_ufcs_inherent_methods() {
506 check_goto( 506 check_goto(
507 " 507 "
508 //- /lib.rs 508 //- /lib.rs
@@ -521,7 +521,7 @@ mod tests {
521 } 521 }
522 522
523 #[test] 523 #[test]
524 fn goto_definition_works_for_ufcs_trait_methods_through_traits() { 524 fn goto_def_for_ufcs_trait_methods_through_traits() {
525 check_goto( 525 check_goto(
526 " 526 "
527 //- /lib.rs 527 //- /lib.rs
@@ -539,7 +539,7 @@ mod tests {
539 } 539 }
540 540
541 #[test] 541 #[test]
542 fn goto_definition_works_for_ufcs_trait_methods_through_self() { 542 fn goto_def_for_ufcs_trait_methods_through_self() {
543 check_goto( 543 check_goto(
544 " 544 "
545 //- /lib.rs 545 //- /lib.rs
@@ -654,7 +654,7 @@ mod tests {
654 } 654 }
655 655
656 #[test] 656 #[test]
657 fn goto_definition_works_when_used_on_definition_name_itself() { 657 fn goto_def_when_used_on_definition_name_itself() {
658 check_goto( 658 check_goto(
659 " 659 "
660 //- /lib.rs 660 //- /lib.rs
@@ -875,4 +875,21 @@ mod tests {
875 "x", 875 "x",
876 ); 876 );
877 } 877 }
878
879 #[test]
880 fn goto_def_for_field_init_shorthand() {
881 covers!(goto_def_for_field_init_shorthand);
882 check_goto(
883 "
884 //- /lib.rs
885 struct Foo { x: i32 }
886 fn main() {
887 let x = 92;
888 Foo { x<|> };
889 }
890 ",
891 "x RECORD_FIELD_DEF FileId(1) [13; 19) [13; 14)",
892 "x: i32|x",
893 )
894 }
878} 895}
diff --git a/crates/ra_ide/src/marks.rs b/crates/ra_ide/src/marks.rs
index 848ae4dc7..077a44473 100644
--- a/crates/ra_ide/src/marks.rs
+++ b/crates/ra_ide/src/marks.rs
@@ -3,10 +3,11 @@
3test_utils::marks!( 3test_utils::marks!(
4 inserts_angle_brackets_for_generics 4 inserts_angle_brackets_for_generics
5 inserts_parens_for_function_calls 5 inserts_parens_for_function_calls
6 goto_definition_works_for_macros 6 goto_def_for_macros
7 goto_definition_works_for_methods 7 goto_def_for_methods
8 goto_definition_works_for_fields 8 goto_def_for_fields
9 goto_definition_works_for_record_fields 9 goto_def_for_record_fields
10 goto_def_for_field_init_shorthand
10 call_info_bad_offset 11 call_info_bad_offset
11 dont_complete_current_use 12 dont_complete_current_use
12 dont_complete_primitive_in_use 13 dont_complete_primitive_in_use
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index c1f091ec0..3483a7176 100644
--- a/crates/ra_ide/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -134,21 +134,22 @@ pub(crate) fn classify_name_ref(
134 let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); 134 let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None);
135 135
136 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { 136 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
137 tested_by!(goto_definition_works_for_methods); 137 tested_by!(goto_def_for_methods);
138 if let Some(func) = analyzer.resolve_method_call(&method_call) { 138 if let Some(func) = analyzer.resolve_method_call(&method_call) {
139 return Some(from_assoc_item(db, func.into())); 139 return Some(from_assoc_item(db, func.into()));
140 } 140 }
141 } 141 }
142 142
143 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { 143 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
144 tested_by!(goto_definition_works_for_fields); 144 tested_by!(goto_def_for_fields);
145 if let Some(field) = analyzer.resolve_field(&field_expr) { 145 if let Some(field) = analyzer.resolve_field(&field_expr) {
146 return Some(from_struct_field(db, field)); 146 return Some(from_struct_field(db, field));
147 } 147 }
148 } 148 }
149 149
150 if let Some(record_field) = ast::RecordField::cast(parent.clone()) { 150 if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
151 tested_by!(goto_definition_works_for_record_fields); 151 tested_by!(goto_def_for_record_fields);
152 tested_by!(goto_def_for_field_init_shorthand);
152 if let Some(field_def) = analyzer.resolve_record_field(&record_field) { 153 if let Some(field_def) = analyzer.resolve_record_field(&record_field) {
153 return Some(from_struct_field(db, field_def)); 154 return Some(from_struct_field(db, field_def));
154 } 155 }
@@ -160,7 +161,7 @@ pub(crate) fn classify_name_ref(
160 let visibility = None; 161 let visibility = None;
161 162
162 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 163 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
163 tested_by!(goto_definition_works_for_macros); 164 tested_by!(goto_def_for_macros);
164 if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(&macro_call)) { 165 if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(&macro_call)) {
165 let kind = NameKind::Macro(macro_def); 166 let kind = NameKind::Macro(macro_def);
166 return Some(NameDefinition { kind, container, visibility }); 167 return Some(NameDefinition { kind, container, visibility });