aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_db/src/defs.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_db/src/defs.rs')
-rw-r--r--crates/ra_ide_db/src/defs.rs90
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
8use hir::{ 8use 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};
12use ra_prof::profile; 12use ra_prof::profile;
13use ra_syntax::{ 13use ra_syntax::{
@@ -80,6 +80,7 @@ impl Definition {
80 80
81#[derive(Debug)] 81#[derive(Debug)]
82pub enum NameClass { 82pub 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
92impl NameClass { 93impl 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)]
222pub enum NameRefClass { 230pub 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
227impl NameRefClass { 236impl 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
315impl From<PathResolution> for Definition { 331impl From<PathResolution> for Definition {