diff options
author | Aleksey Kladov <[email protected]> | 2020-03-02 18:00:38 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-03-02 18:00:38 +0000 |
commit | 2716a1fa3f8a7410248724a6ce5d4c28837db682 (patch) | |
tree | ad1faf323e4cb1478e1e34e2ed9fe858c5be80e5 /crates/ra_ide/src/references | |
parent | 96eca8a1abd79840b9040250db9d1e65ec663b0e (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.rs | 35 |
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 | ||
3 | use hir::{PathResolution, Semantics}; | 3 | use hir::{Local, PathResolution, Semantics}; |
4 | use ra_ide_db::defs::NameDefinition; | 4 | use ra_ide_db::defs::NameDefinition; |
5 | use ra_ide_db::RootDatabase; | 5 | use ra_ide_db::RootDatabase; |
6 | use ra_prof::profile; | 6 | use ra_prof::profile; |
@@ -9,10 +9,24 @@ use test_utils::tested_by; | |||
9 | 9 | ||
10 | pub use ra_ide_db::defs::{from_module_def, from_struct_field}; | 10 | pub use ra_ide_db::defs::{from_module_def, from_struct_field}; |
11 | 11 | ||
12 | pub enum NameRefClass { | ||
13 | NameDefinition(NameDefinition), | ||
14 | FieldShorthand { local: Local, field: NameDefinition }, | ||
15 | } | ||
16 | |||
17 | impl 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 | |||
12 | pub(crate) fn classify_name_ref( | 26 | pub(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(¯o_call) { | 63 | if let Some(macro_def) = sema.resolve_macro_call(¯o_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 | } |