diff options
author | Aleksey Kladov <[email protected]> | 2019-12-20 13:47:01 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-12-20 13:48:14 +0000 |
commit | 3d4b48e481da35f19366514c0e22ed42fef037a0 (patch) | |
tree | 9e4ff021db736a76bc82555886d868cd7429f021 | |
parent | a0571359f3ea5361f1676b0777b578c6deefdc7d (diff) |
Fix resolve for field init shorthand
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 57 | ||||
-rw-r--r-- | crates/ra_ide/src/marks.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 9 |
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 | |||
2 | use hir_def::{ | 4 | use 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 | ||
13 | use crate::{ | 15 | use 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 | ||
19 | pub trait FromSource: Sized { | 21 | pub 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 | ||
24 | pub trait FromSourceByContainer: Sized { | 26 | pub 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 | ||
65 | impl FromSource for MacroDef { | 67 | impl 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 | ||
81 | impl FromSource for EnumVariant { | 83 | impl 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 | ||
94 | impl FromSource for StructField { | 96 | impl 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 @@ | |||
3 | test_utils::marks!( | 3 | test_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(¯o_call)) { | 165 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_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 }); |