diff options
Diffstat (limited to 'crates/ra_ide_api/src/references/classify.rs')
-rw-r--r-- | crates/ra_ide_api/src/references/classify.rs | 186 |
1 files changed, 0 insertions, 186 deletions
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs deleted file mode 100644 index 5cea805ec..000000000 --- a/crates/ra_ide_api/src/references/classify.rs +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | //! Functions that are used to classify an element from its definition or reference. | ||
2 | |||
3 | use hir::{FromSource, Module, ModuleSource, PathResolution, Source, SourceAnalyzer}; | ||
4 | use ra_prof::profile; | ||
5 | use ra_syntax::{ast, match_ast, AstNode}; | ||
6 | use test_utils::tested_by; | ||
7 | |||
8 | use super::{ | ||
9 | name_definition::{from_assoc_item, from_module_def, from_struct_field}, | ||
10 | NameDefinition, NameKind, | ||
11 | }; | ||
12 | use crate::db::RootDatabase; | ||
13 | |||
14 | pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Option<NameDefinition> { | ||
15 | let _p = profile("classify_name"); | ||
16 | let parent = name.value.syntax().parent()?; | ||
17 | |||
18 | match_ast! { | ||
19 | match parent { | ||
20 | ast::BindPat(it) => { | ||
21 | let src = name.with_value(it); | ||
22 | let local = hir::Local::from_source(db, src)?; | ||
23 | Some(NameDefinition { | ||
24 | visibility: None, | ||
25 | container: local.module(db), | ||
26 | kind: NameKind::Local(local), | ||
27 | }) | ||
28 | }, | ||
29 | ast::RecordFieldDef(it) => { | ||
30 | let ast = hir::FieldSource::Named(it); | ||
31 | let src = name.with_value(ast); | ||
32 | let field = hir::StructField::from_source(db, src)?; | ||
33 | Some(from_struct_field(db, field)) | ||
34 | }, | ||
35 | ast::Module(it) => { | ||
36 | let def = { | ||
37 | if !it.has_semi() { | ||
38 | let ast = hir::ModuleSource::Module(it); | ||
39 | let src = name.with_value(ast); | ||
40 | hir::Module::from_definition(db, src) | ||
41 | } else { | ||
42 | let src = name.with_value(it); | ||
43 | hir::Module::from_declaration(db, src) | ||
44 | } | ||
45 | }?; | ||
46 | Some(from_module_def(db, def.into(), None)) | ||
47 | }, | ||
48 | ast::StructDef(it) => { | ||
49 | let src = name.with_value(it); | ||
50 | let def = hir::Struct::from_source(db, src)?; | ||
51 | Some(from_module_def(db, def.into(), None)) | ||
52 | }, | ||
53 | ast::EnumDef(it) => { | ||
54 | let src = name.with_value(it); | ||
55 | let def = hir::Enum::from_source(db, src)?; | ||
56 | Some(from_module_def(db, def.into(), None)) | ||
57 | }, | ||
58 | ast::TraitDef(it) => { | ||
59 | let src = name.with_value(it); | ||
60 | let def = hir::Trait::from_source(db, src)?; | ||
61 | Some(from_module_def(db, def.into(), None)) | ||
62 | }, | ||
63 | ast::StaticDef(it) => { | ||
64 | let src = name.with_value(it); | ||
65 | let def = hir::Static::from_source(db, src)?; | ||
66 | Some(from_module_def(db, def.into(), None)) | ||
67 | }, | ||
68 | ast::EnumVariant(it) => { | ||
69 | let src = name.with_value(it); | ||
70 | let def = hir::EnumVariant::from_source(db, src)?; | ||
71 | Some(from_module_def(db, def.into(), None)) | ||
72 | }, | ||
73 | ast::FnDef(it) => { | ||
74 | let src = name.with_value(it); | ||
75 | let def = hir::Function::from_source(db, src)?; | ||
76 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | ||
77 | Some(from_assoc_item(db, def.into())) | ||
78 | } else { | ||
79 | Some(from_module_def(db, def.into(), None)) | ||
80 | } | ||
81 | }, | ||
82 | ast::ConstDef(it) => { | ||
83 | let src = name.with_value(it); | ||
84 | let def = hir::Const::from_source(db, src)?; | ||
85 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | ||
86 | Some(from_assoc_item(db, def.into())) | ||
87 | } else { | ||
88 | Some(from_module_def(db, def.into(), None)) | ||
89 | } | ||
90 | }, | ||
91 | ast::TypeAliasDef(it) => { | ||
92 | let src = name.with_value(it); | ||
93 | let def = hir::TypeAlias::from_source(db, src)?; | ||
94 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | ||
95 | Some(from_assoc_item(db, def.into())) | ||
96 | } else { | ||
97 | Some(from_module_def(db, def.into(), None)) | ||
98 | } | ||
99 | }, | ||
100 | ast::MacroCall(it) => { | ||
101 | let src = name.with_value(it); | ||
102 | let def = hir::MacroDef::from_source(db, src.clone())?; | ||
103 | |||
104 | let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); | ||
105 | let module = Module::from_definition(db, src.with_value(module_src))?; | ||
106 | |||
107 | Some(NameDefinition { | ||
108 | visibility: None, | ||
109 | container: module, | ||
110 | kind: NameKind::Macro(def), | ||
111 | }) | ||
112 | }, | ||
113 | _ => None, | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | pub(crate) fn classify_name_ref( | ||
119 | db: &RootDatabase, | ||
120 | name_ref: Source<&ast::NameRef>, | ||
121 | ) -> Option<NameDefinition> { | ||
122 | let _p = profile("classify_name_ref"); | ||
123 | |||
124 | let parent = name_ref.value.syntax().parent()?; | ||
125 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); | ||
126 | |||
127 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | ||
128 | tested_by!(goto_definition_works_for_methods); | ||
129 | if let Some(func) = analyzer.resolve_method_call(&method_call) { | ||
130 | return Some(from_assoc_item(db, func.into())); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | ||
135 | tested_by!(goto_definition_works_for_fields); | ||
136 | if let Some(field) = analyzer.resolve_field(&field_expr) { | ||
137 | return Some(from_struct_field(db, field)); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | ||
142 | tested_by!(goto_definition_works_for_record_fields); | ||
143 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { | ||
144 | return Some(from_struct_field(db, field_def)); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | let ast = ModuleSource::from_child_node(db, name_ref.with_value(&parent)); | ||
149 | // FIXME: find correct container and visibility for each case | ||
150 | let container = Module::from_definition(db, name_ref.with_value(ast))?; | ||
151 | let visibility = None; | ||
152 | |||
153 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | ||
154 | tested_by!(goto_definition_works_for_macros); | ||
155 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { | ||
156 | let kind = NameKind::Macro(macro_def); | ||
157 | return Some(NameDefinition { kind, container, visibility }); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | let path = name_ref.value.syntax().ancestors().find_map(ast::Path::cast)?; | ||
162 | let resolved = analyzer.resolve_path(db, &path)?; | ||
163 | match resolved { | ||
164 | PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))), | ||
165 | PathResolution::AssocItem(item) => Some(from_assoc_item(db, item)), | ||
166 | PathResolution::Local(local) => { | ||
167 | let container = local.module(db); | ||
168 | let kind = NameKind::Local(local); | ||
169 | Some(NameDefinition { kind, container, visibility: None }) | ||
170 | } | ||
171 | PathResolution::GenericParam(par) => { | ||
172 | // FIXME: get generic param def | ||
173 | let kind = NameKind::GenericParam(par); | ||
174 | Some(NameDefinition { kind, container, visibility }) | ||
175 | } | ||
176 | PathResolution::Macro(def) => { | ||
177 | let kind = NameKind::Macro(def); | ||
178 | Some(NameDefinition { kind, container, visibility }) | ||
179 | } | ||
180 | PathResolution::SelfType(impl_block) => { | ||
181 | let kind = NameKind::SelfType(impl_block); | ||
182 | let container = impl_block.module(db); | ||
183 | Some(NameDefinition { kind, container, visibility }) | ||
184 | } | ||
185 | } | ||
186 | } | ||