aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_db
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-08-08 19:14:18 +0100
committerPaul Daniel Faria <[email protected]>2020-08-08 19:14:18 +0100
commit6cde0b1aa0f6b8623c6b81b2396f4a0345891233 (patch)
tree9d558ee8eeace0aadf241c190248d008e362d17f /crates/ra_ide_db
parenta69f19a6a5899bdfb6fc498371650bf54263deff (diff)
Add support for extern crate
This adds syntax highlighting, hover and goto def functionality for extern crate
Diffstat (limited to 'crates/ra_ide_db')
-rw-r--r--crates/ra_ide_db/src/defs.rs100
-rw-r--r--crates/ra_ide_db/src/imports_locator.rs2
2 files changed, 60 insertions, 42 deletions
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index b51000b03..e2a4f2983 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,19 +91,21 @@ 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) -> Option<Definition> {
102 match self { 104 Some(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 })
106 } 109 }
107} 110}
108 111
@@ -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,16 +228,20 @@ 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) -> Option<Definition> {
229 match self { 238 Some(match self {
239 NameRefClass::ExternCrate(krate) => {
240 Definition::ModuleDef(krate.root_module(db)?.into())
241 }
230 NameRefClass::Definition(def) => def, 242 NameRefClass::Definition(def) => def,
231 NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), 243 NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local),
232 } 244 })
233 } 245 }
234} 246}
235 247
@@ -307,9 +319,15 @@ pub fn classify_name_ref(
307 } 319 }
308 } 320 }
309 321
310 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; 322 if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
311 let resolved = sema.resolve_path(&path)?; 323 if let Some(resolved) = sema.resolve_path(&path) {
312 Some(NameRefClass::Definition(resolved.into())) 324 return Some(NameRefClass::Definition(resolved.into()));
325 }
326 }
327
328 let extern_crate = ast::ExternCrate::cast(parent)?;
329 let resolved = sema.resolve_extern_crate(&extern_crate)?;
330 Some(NameRefClass::ExternCrate(resolved))
313} 331}
314 332
315impl From<PathResolution> for Definition { 333impl From<PathResolution> for Definition {
diff --git a/crates/ra_ide_db/src/imports_locator.rs b/crates/ra_ide_db/src/imports_locator.rs
index 1fba71ff8..9e040973b 100644
--- a/crates/ra_ide_db/src/imports_locator.rs
+++ b/crates/ra_ide_db/src/imports_locator.rs
@@ -61,5 +61,5 @@ fn get_name_definition<'a>(
61 candidate_node 61 candidate_node
62 }; 62 };
63 let name = ast::Name::cast(candidate_name_node)?; 63 let name = ast::Name::cast(candidate_name_node)?;
64 classify_name(sema, &name)?.into_definition() 64 classify_name(sema, &name)?.into_definition(sema.db)
65} 65}