diff options
Diffstat (limited to 'crates/ra_ide/src/references')
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index fdd07d8d1..571236fdc 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -1,18 +1,30 @@ | |||
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; |
7 | use ra_syntax::{ast, AstNode}; | 7 | use ra_syntax::{ast, AstNode}; |
8 | use test_utils::tested_by; | 8 | use test_utils::tested_by; |
9 | 9 | ||
10 | pub use ra_ide_db::defs::{from_module_def, from_struct_field}; | 10 | pub enum NameRefClass { |
11 | NameDefinition(NameDefinition), | ||
12 | FieldShorthand { local: Local, field: NameDefinition }, | ||
13 | } | ||
14 | |||
15 | impl NameRefClass { | ||
16 | pub fn definition(self) -> NameDefinition { | ||
17 | match self { | ||
18 | NameRefClass::NameDefinition(def) => def, | ||
19 | NameRefClass::FieldShorthand { local, field: _ } => NameDefinition::Local(local), | ||
20 | } | ||
21 | } | ||
22 | } | ||
11 | 23 | ||
12 | pub(crate) fn classify_name_ref( | 24 | pub(crate) fn classify_name_ref( |
13 | sema: &Semantics<RootDatabase>, | 25 | sema: &Semantics<RootDatabase>, |
14 | name_ref: &ast::NameRef, | 26 | name_ref: &ast::NameRef, |
15 | ) -> Option<NameDefinition> { | 27 | ) -> Option<NameRefClass> { |
16 | let _p = profile("classify_name_ref"); | 28 | let _p = profile("classify_name_ref"); |
17 | 29 | ||
18 | let parent = name_ref.syntax().parent()?; | 30 | let parent = name_ref.syntax().parent()?; |
@@ -20,48 +32,53 @@ pub(crate) fn classify_name_ref( | |||
20 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 32 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
21 | tested_by!(goto_def_for_methods); | 33 | tested_by!(goto_def_for_methods); |
22 | if let Some(func) = sema.resolve_method_call(&method_call) { | 34 | if let Some(func) = sema.resolve_method_call(&method_call) { |
23 | return Some(from_module_def(func.into())); | 35 | return Some(NameRefClass::NameDefinition(NameDefinition::ModuleDef(func.into()))); |
24 | } | 36 | } |
25 | } | 37 | } |
26 | 38 | ||
27 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 39 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
28 | tested_by!(goto_def_for_fields); | 40 | tested_by!(goto_def_for_fields); |
29 | if let Some(field) = sema.resolve_field(&field_expr) { | 41 | if let Some(field) = sema.resolve_field(&field_expr) { |
30 | return Some(from_struct_field(field)); | 42 | return Some(NameRefClass::NameDefinition(NameDefinition::StructField(field))); |
31 | } | 43 | } |
32 | } | 44 | } |
33 | 45 | ||
34 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | 46 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
35 | tested_by!(goto_def_for_record_fields); | 47 | tested_by!(goto_def_for_record_fields); |
36 | tested_by!(goto_def_for_field_init_shorthand); | 48 | tested_by!(goto_def_for_field_init_shorthand); |
37 | if let Some(field_def) = sema.resolve_record_field(&record_field) { | 49 | if let Some((field, local)) = sema.resolve_record_field(&record_field) { |
38 | return Some(from_struct_field(field_def)); | 50 | let field = NameDefinition::StructField(field); |
51 | let res = match local { | ||
52 | None => NameRefClass::NameDefinition(field), | ||
53 | Some(local) => NameRefClass::FieldShorthand { field, local }, | ||
54 | }; | ||
55 | return Some(res); | ||
39 | } | 56 | } |
40 | } | 57 | } |
41 | 58 | ||
42 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 59 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
43 | tested_by!(goto_def_for_macros); | 60 | tested_by!(goto_def_for_macros); |
44 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | 61 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { |
45 | return Some(NameDefinition::Macro(macro_def)); | 62 | return Some(NameRefClass::NameDefinition(NameDefinition::Macro(macro_def))); |
46 | } | 63 | } |
47 | } | 64 | } |
48 | 65 | ||
49 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 66 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; |
50 | let resolved = sema.resolve_path(&path)?; | 67 | let resolved = sema.resolve_path(&path)?; |
51 | let res = match resolved { | 68 | let res = match resolved { |
52 | PathResolution::Def(def) => from_module_def(def), | 69 | PathResolution::Def(def) => NameDefinition::ModuleDef(def), |
53 | PathResolution::AssocItem(item) => { | 70 | PathResolution::AssocItem(item) => { |
54 | let def = match item { | 71 | let def = match item { |
55 | hir::AssocItem::Function(it) => it.into(), | 72 | hir::AssocItem::Function(it) => it.into(), |
56 | hir::AssocItem::Const(it) => it.into(), | 73 | hir::AssocItem::Const(it) => it.into(), |
57 | hir::AssocItem::TypeAlias(it) => it.into(), | 74 | hir::AssocItem::TypeAlias(it) => it.into(), |
58 | }; | 75 | }; |
59 | from_module_def(def) | 76 | NameDefinition::ModuleDef(def) |
60 | } | 77 | } |
61 | PathResolution::Local(local) => NameDefinition::Local(local), | 78 | PathResolution::Local(local) => NameDefinition::Local(local), |
62 | PathResolution::TypeParam(par) => NameDefinition::TypeParam(par), | 79 | PathResolution::TypeParam(par) => NameDefinition::TypeParam(par), |
63 | PathResolution::Macro(def) => NameDefinition::Macro(def), | 80 | PathResolution::Macro(def) => NameDefinition::Macro(def), |
64 | PathResolution::SelfType(impl_def) => NameDefinition::SelfType(impl_def), | 81 | PathResolution::SelfType(impl_def) => NameDefinition::SelfType(impl_def), |
65 | }; | 82 | }; |
66 | Some(res) | 83 | Some(NameRefClass::NameDefinition(res)) |
67 | } | 84 | } |