diff options
Diffstat (limited to 'crates/ra_ide_db')
-rw-r--r-- | crates/ra_ide_db/src/defs.rs | 78 |
1 files changed, 75 insertions, 3 deletions
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 215daa441..f057435bf 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs | |||
@@ -6,8 +6,8 @@ | |||
6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). | 6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). |
7 | 7 | ||
8 | use hir::{ | 8 | use hir::{ |
9 | Adt, FieldSource, HasSource, ImplDef, Local, MacroDef, Module, ModuleDef, Name, Semantics, | 9 | Adt, FieldSource, HasSource, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution, |
10 | StructField, TypeParam, | 10 | Semantics, StructField, TypeParam, |
11 | }; | 11 | }; |
12 | use ra_prof::profile; | 12 | use ra_prof::profile; |
13 | use ra_syntax::{ | 13 | use ra_syntax::{ |
@@ -117,6 +117,8 @@ impl NameClass { | |||
117 | } | 117 | } |
118 | 118 | ||
119 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { | 119 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { |
120 | let _p = profile("classify_name"); | ||
121 | |||
120 | if let Some(bind_pat) = name.syntax().parent().and_then(ast::BindPat::cast) { | 122 | if let Some(bind_pat) = name.syntax().parent().and_then(ast::BindPat::cast) { |
121 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { | 123 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { |
122 | return Some(NameClass::ConstReference(Definition::ModuleDef(def))); | 124 | return Some(NameClass::ConstReference(Definition::ModuleDef(def))); |
@@ -127,7 +129,6 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option | |||
127 | } | 129 | } |
128 | 130 | ||
129 | fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Definition> { | 131 | fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Definition> { |
130 | let _p = profile("classify_name"); | ||
131 | let parent = name.syntax().parent()?; | 132 | let parent = name.syntax().parent()?; |
132 | 133 | ||
133 | match_ast! { | 134 | match_ast! { |
@@ -192,3 +193,74 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti | |||
192 | } | 193 | } |
193 | } | 194 | } |
194 | } | 195 | } |
196 | |||
197 | pub enum NameRefClass { | ||
198 | Definition(Definition), | ||
199 | FieldShorthand { local: Local, field: Definition }, | ||
200 | } | ||
201 | |||
202 | impl NameRefClass { | ||
203 | pub fn definition(self) -> Definition { | ||
204 | match self { | ||
205 | NameRefClass::Definition(def) => def, | ||
206 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | |||
211 | pub fn classify_name_ref( | ||
212 | sema: &Semantics<RootDatabase>, | ||
213 | name_ref: &ast::NameRef, | ||
214 | ) -> Option<NameRefClass> { | ||
215 | let _p = profile("classify_name_ref"); | ||
216 | |||
217 | let parent = name_ref.syntax().parent()?; | ||
218 | |||
219 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | ||
220 | if let Some(func) = sema.resolve_method_call(&method_call) { | ||
221 | return Some(NameRefClass::Definition(Definition::ModuleDef(func.into()))); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | ||
226 | if let Some(field) = sema.resolve_field(&field_expr) { | ||
227 | return Some(NameRefClass::Definition(Definition::StructField(field))); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | ||
232 | if let Some((field, local)) = sema.resolve_record_field(&record_field) { | ||
233 | let field = Definition::StructField(field); | ||
234 | let res = match local { | ||
235 | None => NameRefClass::Definition(field), | ||
236 | Some(local) => NameRefClass::FieldShorthand { field, local }, | ||
237 | }; | ||
238 | return Some(res); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | ||
243 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | ||
244 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | ||
249 | let resolved = sema.resolve_path(&path)?; | ||
250 | let res = match resolved { | ||
251 | PathResolution::Def(def) => Definition::ModuleDef(def), | ||
252 | PathResolution::AssocItem(item) => { | ||
253 | let def = match item { | ||
254 | hir::AssocItem::Function(it) => it.into(), | ||
255 | hir::AssocItem::Const(it) => it.into(), | ||
256 | hir::AssocItem::TypeAlias(it) => it.into(), | ||
257 | }; | ||
258 | Definition::ModuleDef(def) | ||
259 | } | ||
260 | PathResolution::Local(local) => Definition::Local(local), | ||
261 | PathResolution::TypeParam(par) => Definition::TypeParam(par), | ||
262 | PathResolution::Macro(def) => Definition::Macro(def), | ||
263 | PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def), | ||
264 | }; | ||
265 | Some(NameRefClass::Definition(res)) | ||
266 | } | ||