diff options
author | Paul Daniel Faria <[email protected]> | 2020-08-08 19:14:18 +0100 |
---|---|---|
committer | Paul Daniel Faria <[email protected]> | 2020-08-08 19:14:18 +0100 |
commit | 6cde0b1aa0f6b8623c6b81b2396f4a0345891233 (patch) | |
tree | 9d558ee8eeace0aadf241c190248d008e362d17f /crates/ra_ide_db | |
parent | a69f19a6a5899bdfb6fc498371650bf54263deff (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.rs | 100 | ||||
-rw-r--r-- | crates/ra_ide_db/src/imports_locator.rs | 2 |
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 | ||
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,19 +91,21 @@ 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) -> 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)] |
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) -> 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 | ||
315 | impl From<PathResolution> for Definition { | 333 | impl 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 | } |