aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/references
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-03-02 18:00:38 +0000
committerAleksey Kladov <[email protected]>2020-03-02 18:00:38 +0000
commit2716a1fa3f8a7410248724a6ce5d4c28837db682 (patch)
treead1faf323e4cb1478e1e34e2ed9fe858c5be80e5 /crates/ra_ide/src/references
parent96eca8a1abd79840b9040250db9d1e65ec663b0e (diff)
More principled approach for gotodef for field shorhand
Callers can now decide for themselves if they should prefer field or local definition. By default, it's the local.
Diffstat (limited to 'crates/ra_ide/src/references')
-rw-r--r--crates/ra_ide/src/references/classify.rs35
1 files changed, 27 insertions, 8 deletions
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index fdd07d8d1..e837ca8a3 100644
--- a/crates/ra_ide/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -1,6 +1,6 @@
1//! Functions that are used to classify an element from its definition or reference. 1//! Functions that are used to classify an element from its definition or reference.
2 2
3use hir::{PathResolution, Semantics}; 3use hir::{Local, PathResolution, Semantics};
4use ra_ide_db::defs::NameDefinition; 4use ra_ide_db::defs::NameDefinition;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_prof::profile; 6use ra_prof::profile;
@@ -9,10 +9,24 @@ use test_utils::tested_by;
9 9
10pub use ra_ide_db::defs::{from_module_def, from_struct_field}; 10pub use ra_ide_db::defs::{from_module_def, from_struct_field};
11 11
12pub enum NameRefClass {
13 NameDefinition(NameDefinition),
14 FieldShorthand { local: Local, field: NameDefinition },
15}
16
17impl NameRefClass {
18 pub fn definition(self) -> NameDefinition {
19 match self {
20 NameRefClass::NameDefinition(def) => def,
21 NameRefClass::FieldShorthand { local, field: _ } => NameDefinition::Local(local),
22 }
23 }
24}
25
12pub(crate) fn classify_name_ref( 26pub(crate) fn classify_name_ref(
13 sema: &Semantics<RootDatabase>, 27 sema: &Semantics<RootDatabase>,
14 name_ref: &ast::NameRef, 28 name_ref: &ast::NameRef,
15) -> Option<NameDefinition> { 29) -> Option<NameRefClass> {
16 let _p = profile("classify_name_ref"); 30 let _p = profile("classify_name_ref");
17 31
18 let parent = name_ref.syntax().parent()?; 32 let parent = name_ref.syntax().parent()?;
@@ -20,29 +34,34 @@ pub(crate) fn classify_name_ref(
20 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { 34 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
21 tested_by!(goto_def_for_methods); 35 tested_by!(goto_def_for_methods);
22 if let Some(func) = sema.resolve_method_call(&method_call) { 36 if let Some(func) = sema.resolve_method_call(&method_call) {
23 return Some(from_module_def(func.into())); 37 return Some(NameRefClass::NameDefinition(NameDefinition::ModuleDef(func.into())));
24 } 38 }
25 } 39 }
26 40
27 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { 41 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
28 tested_by!(goto_def_for_fields); 42 tested_by!(goto_def_for_fields);
29 if let Some(field) = sema.resolve_field(&field_expr) { 43 if let Some(field) = sema.resolve_field(&field_expr) {
30 return Some(from_struct_field(field)); 44 return Some(NameRefClass::NameDefinition(NameDefinition::StructField(field)));
31 } 45 }
32 } 46 }
33 47
34 if let Some(record_field) = ast::RecordField::cast(parent.clone()) { 48 if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
35 tested_by!(goto_def_for_record_fields); 49 tested_by!(goto_def_for_record_fields);
36 tested_by!(goto_def_for_field_init_shorthand); 50 tested_by!(goto_def_for_field_init_shorthand);
37 if let Some(field_def) = sema.resolve_record_field(&record_field) { 51 if let Some((field, local)) = sema.resolve_record_field(&record_field) {
38 return Some(from_struct_field(field_def)); 52 let field = NameDefinition::StructField(field);
53 let res = match local {
54 None => NameRefClass::NameDefinition(field),
55 Some(local) => NameRefClass::FieldShorthand { field, local },
56 };
57 return Some(res);
39 } 58 }
40 } 59 }
41 60
42 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 61 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
43 tested_by!(goto_def_for_macros); 62 tested_by!(goto_def_for_macros);
44 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) { 63 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
45 return Some(NameDefinition::Macro(macro_def)); 64 return Some(NameRefClass::NameDefinition(NameDefinition::Macro(macro_def)));
46 } 65 }
47 } 66 }
48 67
@@ -63,5 +82,5 @@ pub(crate) fn classify_name_ref(
63 PathResolution::Macro(def) => NameDefinition::Macro(def), 82 PathResolution::Macro(def) => NameDefinition::Macro(def),
64 PathResolution::SelfType(impl_def) => NameDefinition::SelfType(impl_def), 83 PathResolution::SelfType(impl_def) => NameDefinition::SelfType(impl_def),
65 }; 84 };
66 Some(res) 85 Some(NameRefClass::NameDefinition(res))
67} 86}