aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/references/classify.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/references/classify.rs')
-rw-r--r--crates/ra_ide/src/references/classify.rs39
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
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;
7use ra_syntax::{ast, AstNode}; 7use ra_syntax::{ast, AstNode};
8use test_utils::tested_by; 8use test_utils::tested_by;
9 9
10pub use ra_ide_db::defs::{from_module_def, from_struct_field}; 10pub enum NameRefClass {
11 NameDefinition(NameDefinition),
12 FieldShorthand { local: Local, field: NameDefinition },
13}
14
15impl 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
12pub(crate) fn classify_name_ref( 24pub(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(&macro_call) { 61 if let Some(macro_def) = sema.resolve_macro_call(&macro_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}