From 9f2574c97e55e2af1d1b93f60307aa9d41f55f42 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 20:32:34 +0300 Subject: add ability to get strcut field source --- crates/ra_ide_api/src/goto_definition.rs | 34 ++++++++++++++++++++++++++---- crates/ra_ide_api/src/marks.rs | 6 +++++- crates/ra_ide_api/src/navigation_target.rs | 13 +++++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 46bdde00d..45b4c56ef 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -3,6 +3,7 @@ use ra_syntax::{ AstNode, ast, algo::find_node_at_offset, }; +use test_utils::tested_by; use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; @@ -60,6 +61,7 @@ pub(crate) fn reference_definition( .parent() .and_then(ast::MethodCallExpr::cast) { + tested_by!(goto_definition_works_for_methods); let infer_result = function.infer(db); let syntax_mapping = function.body_syntax_mapping(db); let expr = ast::Expr::cast(method_call.syntax()).unwrap(); @@ -70,6 +72,19 @@ pub(crate) fn reference_definition( return Exact(NavigationTarget::from_function(db, func)); }; } + // It could also be a field access + if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::FieldExpr::cast) { + tested_by!(goto_definition_works_for_fields); + let infer_result = function.infer(db); + let syntax_mapping = function.body_syntax_mapping(db); + let expr = ast::Expr::cast(field_expr.syntax()).unwrap(); + if let Some(field) = syntax_mapping + .node_expr(expr) + .and_then(|it| infer_result.field_resolution(it)) + { + return Exact(NavigationTarget::from_field(db, field)); + }; + } } // Then try module name resolution if let Some(module) = hir::source_binder::module_from_child_node(db, file_id, name_ref.syntax()) @@ -117,6 +132,8 @@ fn name_definition( #[cfg(test)] mod tests { + use test_utils::covers; + use crate::mock_analysis::analysis_and_position; fn check_goto(fixuture: &str, expected: &str) { @@ -183,6 +200,7 @@ mod tests { #[test] fn goto_definition_works_for_methods() { + covers!(goto_definition_works_for_methods); check_goto( " //- /lib.rs @@ -197,15 +215,23 @@ mod tests { ", "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)", ); + } + #[test] + fn goto_definition_works_for_fields() { + covers!(goto_definition_works_for_fields); check_goto( " //- /lib.rs - mod <|>foo; - //- /foo/mod.rs - // empty + struct Foo { + spam: u32, + } + + fn bar(foo: &Foo) { + foo.spam<|>; + } ", - "foo SOURCE_FILE FileId(2) [0; 10)", + "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)", ); } } diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs index dc5b2702a..e33bf6c91 100644 --- a/crates/ra_ide_api/src/marks.rs +++ b/crates/ra_ide_api/src/marks.rs @@ -1 +1,5 @@ -test_utils::marks!(inserts_parens_for_function_calls); +test_utils::marks!( + inserts_parens_for_function_calls + goto_definition_works_for_methods + goto_definition_works_for_fields +); diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index c5be8e01b..ae2175dbc 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -3,7 +3,7 @@ use ra_syntax::{ SyntaxNode, AstNode, SmolStr, TextRange, ast, SyntaxKind::{self, NAME}, }; -use hir::{ModuleSource}; +use hir::{ModuleSource, FieldSource}; use crate::{FileSymbol, db::RootDatabase}; @@ -101,6 +101,17 @@ impl NavigationTarget { NavigationTarget::from_named(file_id.original_file(db), &*fn_def) } + pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget { + let (file_id, field) = field.source(db); + let file_id = file_id.original_file(db); + match field { + FieldSource::Named(it) => NavigationTarget::from_named(file_id, &*it), + FieldSource::Pos(it) => { + NavigationTarget::from_syntax(file_id, "".into(), None, it.syntax()) + } + } + } + // TODO once Def::Item is gone, this should be able to always return a NavigationTarget pub(crate) fn from_def( db: &RootDatabase, -- cgit v1.2.3