aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_db/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_db/src')
-rw-r--r--crates/ra_ide_db/src/defs.rs78
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
8use hir::{ 8use 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};
12use ra_prof::profile; 12use ra_prof::profile;
13use ra_syntax::{ 13use ra_syntax::{
@@ -117,6 +117,8 @@ impl NameClass {
117} 117}
118 118
119pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { 119pub 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
129fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Definition> { 131fn 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
197pub enum NameRefClass {
198 Definition(Definition),
199 FieldShorthand { local: Local, field: Definition },
200}
201
202impl 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
211pub 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(&macro_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}