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.rs75
1 files changed, 55 insertions, 20 deletions
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index 66c048714..9bb95277d 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -6,13 +6,13 @@
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::{
14 ast::{self, AstNode}, 14 ast::{self, AstNode},
15 match_ast, 15 match_ast, SyntaxNode,
16}; 16};
17 17
18use crate::RootDatabase; 18use crate::RootDatabase;
@@ -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,13 +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 = path_segment.name_ref()?; 129 let name_ref_class = path_segment
127 let name_ref_class = classify_name_ref(sema, &name_ref)?; 130 .name_ref()
131 // The rename might be from a `self` token, so fallback to the name higher
132 // in the use tree.
133 .or_else(||{
134 if path_segment.self_token().is_none() {
135 return None;
136 }
128 137
129 Some(NameClass::Definition(name_ref_class.definition())) 138 let use_tree = use_tree
139 .syntax()
140 .parent()
141 .as_ref()
142 // Skip over UseTreeList
143 .and_then(SyntaxNode::parent)
144 .and_then(ast::UseTree::cast)?;
145 let path = use_tree.path()?;
146 let path_segment = path.segment()?;
147 path_segment.name_ref()
148 })
149 .and_then(|name_ref| classify_name_ref(sema, &name_ref))?;
150
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 }
130 }, 157 },
131 ast::IdentPat(it) => { 158 ast::IdentPat(it) => {
132 let local = sema.to_def(&it)?; 159 let local = sema.to_def(&it)?;
@@ -201,13 +228,15 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option
201 228
202#[derive(Debug)] 229#[derive(Debug)]
203pub enum NameRefClass { 230pub enum NameRefClass {
231 ExternCrate(Crate),
204 Definition(Definition), 232 Definition(Definition),
205 FieldShorthand { local: Local, field: Definition }, 233 FieldShorthand { local: Local, field: Definition },
206} 234}
207 235
208impl NameRefClass { 236impl NameRefClass {
209 pub fn definition(self) -> Definition { 237 pub fn definition(self, db: &dyn HirDatabase) -> Definition {
210 match self { 238 match self {
239 NameRefClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()),
211 NameRefClass::Definition(def) => def, 240 NameRefClass::Definition(def) => def,
212 NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), 241 NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local),
213 } 242 }
@@ -288,9 +317,15 @@ pub fn classify_name_ref(
288 } 317 }
289 } 318 }
290 319
291 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) {
292 let resolved = sema.resolve_path(&path)?; 321 if let Some(resolved) = sema.resolve_path(&path) {
293 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))
294} 329}
295 330
296impl From<PathResolution> for Definition { 331impl From<PathResolution> for Definition {