diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-03-02 18:01:50 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-02 18:01:50 +0000 |
commit | 7928ac4bbd8c75ac779d6da7e9cbe6aa314fb5bd (patch) | |
tree | 4a0f3b337f334d5355a79c60279bebefa0c68616 /crates/ra_ide/src/references/classify.rs | |
parent | 71b53b2cae74d6f84c79d21b24754792a8435149 (diff) | |
parent | 2716a1fa3f8a7410248724a6ce5d4c28837db682 (diff) |
Merge #3405
3405: More principled approach for gotodef for field shorhand r=matklad a=matklad
Callers can now decide for themselves if they should prefer field or
local definition. By default, it's the local.
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_ide/src/references/classify.rs')
-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 | } |