From 3d4b48e481da35f19366514c0e22ed42fef037a0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 14:47:01 +0100 Subject: Fix resolve for field init shorthand --- crates/ra_hir/src/from_source.rs | 16 +++++---- crates/ra_hir/src/source_binder.rs | 8 ++++- crates/ra_hir_def/src/body.rs | 5 +++ crates/ra_ide/src/goto_definition.rs | 57 +++++++++++++++++++++----------- crates/ra_ide/src/marks.rs | 9 ++--- 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 @@ -//! FIXME: write short doc here +//! Finds a corresponding hir data structure for a syntax node in a specific +//! file. + use hir_def::{ child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, @@ -11,14 +13,14 @@ use ra_syntax::{ }; use crate::{ - db::{AstDatabase, DefDatabase, HirDatabase}, + db::{DefDatabase, HirDatabase}, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, }; pub trait FromSource: Sized { type Ast; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option; + fn from_source(db: &impl DefDatabase, src: InFile) -> Option; } pub trait FromSourceByContainer: Sized { @@ -32,7 +34,7 @@ where T: From<::Id>, { type Ast = ::Ast; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + fn from_source(db: &impl DefDatabase, src: InFile) -> Option { analyze_container(db, src.as_ref().map(|it| it.syntax()))[T::KEY] .get(&src) .copied() @@ -64,7 +66,7 @@ from_source_by_container_impls![ impl FromSource for MacroDef { type Ast = ast::MacroCall; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + fn from_source(db: &impl DefDatabase, src: InFile) -> Option { let kind = MacroDefKind::Declarative; let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); @@ -80,7 +82,7 @@ impl FromSource for MacroDef { impl FromSource for EnumVariant { type Ast = ast::EnumVariant; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + fn from_source(db: &impl DefDatabase, src: InFile) -> Option { let parent_enum = src.value.parent_enum(); let src_enum = InFile { file_id: src.file_id, value: parent_enum }; let parent_enum = Enum::from_source(db, src_enum)?; @@ -93,7 +95,7 @@ impl FromSource for EnumVariant { impl FromSource for StructField { type Ast = FieldSource; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + fn from_source(db: &impl DefDatabase, src: InFile) -> Option { let src = src.as_ref(); // 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 { } pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option { - let expr_id = self.expr_id(&field.expr()?)?; + let expr_id = match field.expr() { + Some(it) => self.expr_id(&it)?, + None => { + let src = InFile { file_id: self.file_id, value: field }; + self.body_source_map.as_ref()?.field_init_shorthand_expr(src)? + } + }; self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into()) } 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 { self.expr_map.get(&src).cloned() } + pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option { + let src = node.map(|it| Either::Right(AstPtr::new(it))); + self.expr_map.get(&src).cloned() + } + pub fn pat_syntax(&self, pat: PatId) -> Option { self.pat_map_back.get(pat).copied() } 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 { } #[test] - fn goto_definition_works_in_items() { + fn goto_def_in_items() { check_goto( " //- /lib.rs @@ -271,7 +271,7 @@ mod tests { } #[test] - fn goto_definition_works_at_start_of_item() { + fn goto_def_at_start_of_item() { check_goto( " //- /lib.rs @@ -305,7 +305,7 @@ mod tests { } #[test] - fn goto_definition_works_for_module_declaration() { + fn goto_def_for_module_declaration() { check_goto( " //- /lib.rs @@ -332,8 +332,8 @@ mod tests { } #[test] - fn goto_definition_works_for_macros() { - covers!(goto_definition_works_for_macros); + fn goto_def_for_macros() { + covers!(goto_def_for_macros); check_goto( " //- /lib.rs @@ -349,8 +349,8 @@ mod tests { } #[test] - fn goto_definition_works_for_macros_from_other_crates() { - covers!(goto_definition_works_for_macros); + fn goto_def_for_macros_from_other_crates() { + covers!(goto_def_for_macros); check_goto( " //- /lib.rs @@ -369,7 +369,7 @@ mod tests { } #[test] - fn goto_definition_works_for_macros_in_use_tree() { + fn goto_def_for_macros_in_use_tree() { check_goto( " //- /lib.rs @@ -385,7 +385,7 @@ mod tests { } #[test] - fn goto_definition_works_for_macro_defined_fn_with_arg() { + fn goto_def_for_macro_defined_fn_with_arg() { check_goto( " //- /lib.rs @@ -405,7 +405,7 @@ mod tests { } #[test] - fn goto_definition_works_for_macro_defined_fn_no_arg() { + fn goto_def_for_macro_defined_fn_no_arg() { check_goto( " //- /lib.rs @@ -425,8 +425,8 @@ mod tests { } #[test] - fn goto_definition_works_for_methods() { - covers!(goto_definition_works_for_methods); + fn goto_def_for_methods() { + covers!(goto_def_for_methods); check_goto( " //- /lib.rs @@ -445,8 +445,8 @@ mod tests { } #[test] - fn goto_definition_works_for_fields() { - covers!(goto_definition_works_for_fields); + fn goto_def_for_fields() { + covers!(goto_def_for_fields); check_goto( " //- /lib.rs @@ -464,8 +464,8 @@ mod tests { } #[test] - fn goto_definition_works_for_record_fields() { - covers!(goto_definition_works_for_record_fields); + fn goto_def_for_record_fields() { + covers!(goto_def_for_record_fields); check_goto( " //- /lib.rs @@ -502,7 +502,7 @@ mod tests { } #[test] - fn goto_definition_works_for_ufcs_inherent_methods() { + fn goto_def_for_ufcs_inherent_methods() { check_goto( " //- /lib.rs @@ -521,7 +521,7 @@ mod tests { } #[test] - fn goto_definition_works_for_ufcs_trait_methods_through_traits() { + fn goto_def_for_ufcs_trait_methods_through_traits() { check_goto( " //- /lib.rs @@ -539,7 +539,7 @@ mod tests { } #[test] - fn goto_definition_works_for_ufcs_trait_methods_through_self() { + fn goto_def_for_ufcs_trait_methods_through_self() { check_goto( " //- /lib.rs @@ -654,7 +654,7 @@ mod tests { } #[test] - fn goto_definition_works_when_used_on_definition_name_itself() { + fn goto_def_when_used_on_definition_name_itself() { check_goto( " //- /lib.rs @@ -875,4 +875,21 @@ mod tests { "x", ); } + + #[test] + fn goto_def_for_field_init_shorthand() { + covers!(goto_def_for_field_init_shorthand); + check_goto( + " + //- /lib.rs + struct Foo { x: i32 } + fn main() { + let x = 92; + Foo { x<|> }; + } + ", + "x RECORD_FIELD_DEF FileId(1) [13; 19) [13; 14)", + "x: i32|x", + ) + } } 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 @@ test_utils::marks!( inserts_angle_brackets_for_generics inserts_parens_for_function_calls - goto_definition_works_for_macros - goto_definition_works_for_methods - goto_definition_works_for_fields - goto_definition_works_for_record_fields + goto_def_for_macros + goto_def_for_methods + goto_def_for_fields + goto_def_for_record_fields + goto_def_for_field_init_shorthand call_info_bad_offset dont_complete_current_use 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( let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { - tested_by!(goto_definition_works_for_methods); + tested_by!(goto_def_for_methods); if let Some(func) = analyzer.resolve_method_call(&method_call) { return Some(from_assoc_item(db, func.into())); } } if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { - tested_by!(goto_definition_works_for_fields); + tested_by!(goto_def_for_fields); if let Some(field) = analyzer.resolve_field(&field_expr) { return Some(from_struct_field(db, field)); } } if let Some(record_field) = ast::RecordField::cast(parent.clone()) { - tested_by!(goto_definition_works_for_record_fields); + tested_by!(goto_def_for_record_fields); + tested_by!(goto_def_for_field_init_shorthand); if let Some(field_def) = analyzer.resolve_record_field(&record_field) { return Some(from_struct_field(db, field_def)); } @@ -160,7 +161,7 @@ pub(crate) fn classify_name_ref( let visibility = None; if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { - tested_by!(goto_definition_works_for_macros); + tested_by!(goto_def_for_macros); if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { let kind = NameKind::Macro(macro_def); return Some(NameDefinition { kind, container, visibility }); -- cgit v1.2.3