diff options
Diffstat (limited to 'crates/ra_ide_db/src/defs.rs')
-rw-r--r-- | crates/ra_ide_db/src/defs.rs | 90 |
1 files changed, 53 insertions, 37 deletions
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index b51000b03..9bb95277d 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 | Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution, | 9 | db::HirDatabase, Crate, Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, |
10 | Semantics, TypeParam, Visibility, | 10 | Name, PathResolution, Semantics, TypeParam, Visibility, |
11 | }; | 11 | }; |
12 | use ra_prof::profile; | 12 | use ra_prof::profile; |
13 | use ra_syntax::{ | 13 | use ra_syntax::{ |
@@ -80,6 +80,7 @@ impl Definition { | |||
80 | 80 | ||
81 | #[derive(Debug)] | 81 | #[derive(Debug)] |
82 | pub enum NameClass { | 82 | pub enum NameClass { |
83 | ExternCrate(Crate), | ||
83 | Definition(Definition), | 84 | Definition(Definition), |
84 | /// `None` in `if let None = Some(82) {}` | 85 | /// `None` in `if let None = Some(82) {}` |
85 | ConstReference(Definition), | 86 | ConstReference(Definition), |
@@ -90,16 +91,18 @@ pub enum NameClass { | |||
90 | } | 91 | } |
91 | 92 | ||
92 | impl NameClass { | 93 | impl NameClass { |
93 | pub fn into_definition(self) -> Option<Definition> { | 94 | pub fn into_definition(self, db: &dyn HirDatabase) -> Option<Definition> { |
94 | match self { | 95 | Some(match self { |
95 | NameClass::Definition(it) => Some(it), | 96 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), |
96 | NameClass::ConstReference(_) => None, | 97 | NameClass::Definition(it) => it, |
97 | NameClass::FieldShorthand { local, field: _ } => Some(Definition::Local(local)), | 98 | NameClass::ConstReference(_) => return None, |
98 | } | 99 | NameClass::FieldShorthand { local, field: _ } => Definition::Local(local), |
100 | }) | ||
99 | } | 101 | } |
100 | 102 | ||
101 | pub fn definition(self) -> Definition { | 103 | pub fn definition(self, db: &dyn HirDatabase) -> Definition { |
102 | match self { | 104 | match self { |
105 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), | ||
103 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, | 106 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, |
104 | NameClass::FieldShorthand { local: _, field } => field, | 107 | NameClass::FieldShorthand { local: _, field } => field, |
105 | } | 108 | } |
@@ -120,32 +123,37 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option | |||
120 | match_ast! { | 123 | match_ast! { |
121 | match parent { | 124 | match parent { |
122 | ast::Rename(it) => { | 125 | ast::Rename(it) => { |
123 | let use_tree = it.syntax().parent().and_then(ast::UseTree::cast)?; | 126 | if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) { |
124 | let path = use_tree.path()?; | 127 | let path = use_tree.path()?; |
125 | let path_segment = path.segment()?; | 128 | let path_segment = path.segment()?; |
126 | let name_ref_class = path_segment | 129 | let name_ref_class = path_segment |
127 | .name_ref() | 130 | .name_ref() |
128 | // The rename might be from a `self` token, so fallback to the name higher | 131 | // The rename might be from a `self` token, so fallback to the name higher |
129 | // in the use tree. | 132 | // in the use tree. |
130 | .or_else(||{ | 133 | .or_else(||{ |
131 | if path_segment.self_token().is_none() { | 134 | if path_segment.self_token().is_none() { |
132 | return None; | 135 | return None; |
133 | } | 136 | } |
134 | 137 | ||
135 | let use_tree = use_tree | 138 | let use_tree = use_tree |
136 | .syntax() | 139 | .syntax() |
137 | .parent() | 140 | .parent() |
138 | .as_ref() | 141 | .as_ref() |
139 | // Skip over UseTreeList | 142 | // Skip over UseTreeList |
140 | .and_then(SyntaxNode::parent) | 143 | .and_then(SyntaxNode::parent) |
141 | .and_then(ast::UseTree::cast)?; | 144 | .and_then(ast::UseTree::cast)?; |
142 | let path = use_tree.path()?; | 145 | let path = use_tree.path()?; |
143 | let path_segment = path.segment()?; | 146 | let path_segment = path.segment()?; |
144 | path_segment.name_ref() | 147 | path_segment.name_ref() |
145 | }) | 148 | }) |
146 | .and_then(|name_ref| classify_name_ref(sema, &name_ref))?; | 149 | .and_then(|name_ref| classify_name_ref(sema, &name_ref))?; |
147 | 150 | ||
148 | Some(NameClass::Definition(name_ref_class.definition())) | 151 | Some(NameClass::Definition(name_ref_class.definition(sema.db))) |
152 | } else { | ||
153 | let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?; | ||
154 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | ||
155 | Some(NameClass::ExternCrate(resolved)) | ||
156 | } | ||
149 | }, | 157 | }, |
150 | ast::IdentPat(it) => { | 158 | ast::IdentPat(it) => { |
151 | let local = sema.to_def(&it)?; | 159 | let local = sema.to_def(&it)?; |
@@ -220,13 +228,15 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option | |||
220 | 228 | ||
221 | #[derive(Debug)] | 229 | #[derive(Debug)] |
222 | pub enum NameRefClass { | 230 | pub enum NameRefClass { |
231 | ExternCrate(Crate), | ||
223 | Definition(Definition), | 232 | Definition(Definition), |
224 | FieldShorthand { local: Local, field: Definition }, | 233 | FieldShorthand { local: Local, field: Definition }, |
225 | } | 234 | } |
226 | 235 | ||
227 | impl NameRefClass { | 236 | impl NameRefClass { |
228 | pub fn definition(self) -> Definition { | 237 | pub fn definition(self, db: &dyn HirDatabase) -> Definition { |
229 | match self { | 238 | match self { |
239 | NameRefClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), | ||
230 | NameRefClass::Definition(def) => def, | 240 | NameRefClass::Definition(def) => def, |
231 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), | 241 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), |
232 | } | 242 | } |
@@ -307,9 +317,15 @@ pub fn classify_name_ref( | |||
307 | } | 317 | } |
308 | } | 318 | } |
309 | 319 | ||
310 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 320 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { |
311 | let resolved = sema.resolve_path(&path)?; | 321 | if let Some(resolved) = sema.resolve_path(&path) { |
312 | Some(NameRefClass::Definition(resolved.into())) | 322 | return Some(NameRefClass::Definition(resolved.into())); |
323 | } | ||
324 | } | ||
325 | |||
326 | let extern_crate = ast::ExternCrate::cast(parent)?; | ||
327 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | ||
328 | Some(NameRefClass::ExternCrate(resolved)) | ||
313 | } | 329 | } |
314 | 330 | ||
315 | impl From<PathResolution> for Definition { | 331 | impl From<PathResolution> for Definition { |