diff options
Diffstat (limited to 'crates/ide_db/src')
-rw-r--r-- | crates/ide_db/src/defs.rs | 338 | ||||
-rw-r--r-- | crates/ide_db/src/imports_locator.rs | 4 | ||||
-rw-r--r-- | crates/ide_db/src/search.rs | 6 |
3 files changed, 174 insertions, 174 deletions
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index 717581593..3cef0baf7 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs | |||
@@ -110,121 +110,121 @@ impl NameClass { | |||
110 | NameClass::PatFieldShorthand { local_def: _, field_ref } => field_ref, | 110 | NameClass::PatFieldShorthand { local_def: _, field_ref } => field_ref, |
111 | } | 111 | } |
112 | } | 112 | } |
113 | } | ||
114 | 113 | ||
115 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { | 114 | pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { |
116 | let _p = profile::span("classify_name"); | 115 | let _p = profile::span("classify_name"); |
117 | 116 | ||
118 | let parent = name.syntax().parent()?; | 117 | let parent = name.syntax().parent()?; |
119 | 118 | ||
120 | if let Some(bind_pat) = ast::IdentPat::cast(parent.clone()) { | 119 | if let Some(bind_pat) = ast::IdentPat::cast(parent.clone()) { |
121 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { | 120 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { |
122 | return Some(NameClass::ConstReference(Definition::ModuleDef(def))); | 121 | return Some(NameClass::ConstReference(Definition::ModuleDef(def))); |
122 | } | ||
123 | } | 123 | } |
124 | } | ||
125 | 124 | ||
126 | match_ast! { | 125 | match_ast! { |
127 | match parent { | 126 | match parent { |
128 | ast::Rename(it) => { | 127 | ast::Rename(it) => { |
129 | if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) { | 128 | if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) { |
130 | let path = use_tree.path()?; | 129 | let path = use_tree.path()?; |
131 | let path_segment = path.segment()?; | 130 | let path_segment = path.segment()?; |
132 | let name_ref_class = path_segment | 131 | let name_ref_class = path_segment |
133 | .name_ref() | 132 | .name_ref() |
134 | // The rename might be from a `self` token, so fallback to the name higher | 133 | // The rename might be from a `self` token, so fallback to the name higher |
135 | // in the use tree. | 134 | // in the use tree. |
136 | .or_else(||{ | 135 | .or_else(||{ |
137 | if path_segment.self_token().is_none() { | 136 | if path_segment.self_token().is_none() { |
138 | return None; | 137 | return None; |
139 | } | 138 | } |
140 | 139 | ||
141 | let use_tree = use_tree | 140 | let use_tree = use_tree |
142 | .syntax() | 141 | .syntax() |
143 | .parent() | 142 | .parent() |
144 | .as_ref() | 143 | .as_ref() |
145 | // Skip over UseTreeList | 144 | // Skip over UseTreeList |
146 | .and_then(SyntaxNode::parent) | 145 | .and_then(SyntaxNode::parent) |
147 | .and_then(ast::UseTree::cast)?; | 146 | .and_then(ast::UseTree::cast)?; |
148 | let path = use_tree.path()?; | 147 | let path = use_tree.path()?; |
149 | let path_segment = path.segment()?; | 148 | let path_segment = path.segment()?; |
150 | path_segment.name_ref() | 149 | path_segment.name_ref() |
151 | }) | 150 | }) |
152 | .and_then(|name_ref| classify_name_ref(sema, &name_ref))?; | 151 | .and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?; |
153 | 152 | ||
154 | Some(NameClass::Definition(name_ref_class.definition(sema.db))) | 153 | Some(NameClass::Definition(name_ref_class.definition(sema.db))) |
155 | } else { | 154 | } else { |
156 | let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?; | 155 | let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?; |
157 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | 156 | let resolved = sema.resolve_extern_crate(&extern_crate)?; |
158 | Some(NameClass::ExternCrate(resolved)) | 157 | Some(NameClass::ExternCrate(resolved)) |
159 | } | 158 | } |
160 | }, | 159 | }, |
161 | ast::IdentPat(it) => { | 160 | ast::IdentPat(it) => { |
162 | let local = sema.to_def(&it)?; | 161 | let local = sema.to_def(&it)?; |
163 | 162 | ||
164 | if let Some(record_pat_field) = it.syntax().parent().and_then(ast::RecordPatField::cast) { | 163 | if let Some(record_pat_field) = it.syntax().parent().and_then(ast::RecordPatField::cast) { |
165 | if record_pat_field.name_ref().is_none() { | 164 | if record_pat_field.name_ref().is_none() { |
166 | if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) { | 165 | if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) { |
167 | let field = Definition::Field(field); | 166 | let field = Definition::Field(field); |
168 | return Some(NameClass::PatFieldShorthand { local_def: local, field_ref: field }); | 167 | return Some(NameClass::PatFieldShorthand { local_def: local, field_ref: field }); |
168 | } | ||
169 | } | 169 | } |
170 | } | 170 | } |
171 | } | ||
172 | 171 | ||
173 | Some(NameClass::Definition(Definition::Local(local))) | 172 | Some(NameClass::Definition(Definition::Local(local))) |
174 | }, | 173 | }, |
175 | ast::RecordField(it) => { | 174 | ast::RecordField(it) => { |
176 | let field: hir::Field = sema.to_def(&it)?; | 175 | let field: hir::Field = sema.to_def(&it)?; |
177 | Some(NameClass::Definition(Definition::Field(field))) | 176 | Some(NameClass::Definition(Definition::Field(field))) |
178 | }, | 177 | }, |
179 | ast::Module(it) => { | 178 | ast::Module(it) => { |
180 | let def = sema.to_def(&it)?; | 179 | let def = sema.to_def(&it)?; |
181 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 180 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
182 | }, | 181 | }, |
183 | ast::Struct(it) => { | 182 | ast::Struct(it) => { |
184 | let def: hir::Struct = sema.to_def(&it)?; | 183 | let def: hir::Struct = sema.to_def(&it)?; |
185 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 184 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
186 | }, | 185 | }, |
187 | ast::Union(it) => { | 186 | ast::Union(it) => { |
188 | let def: hir::Union = sema.to_def(&it)?; | 187 | let def: hir::Union = sema.to_def(&it)?; |
189 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 188 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
190 | }, | 189 | }, |
191 | ast::Enum(it) => { | 190 | ast::Enum(it) => { |
192 | let def: hir::Enum = sema.to_def(&it)?; | 191 | let def: hir::Enum = sema.to_def(&it)?; |
193 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 192 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
194 | }, | 193 | }, |
195 | ast::Trait(it) => { | 194 | ast::Trait(it) => { |
196 | let def: hir::Trait = sema.to_def(&it)?; | 195 | let def: hir::Trait = sema.to_def(&it)?; |
197 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 196 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
198 | }, | 197 | }, |
199 | ast::Static(it) => { | 198 | ast::Static(it) => { |
200 | let def: hir::Static = sema.to_def(&it)?; | 199 | let def: hir::Static = sema.to_def(&it)?; |
201 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 200 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
202 | }, | 201 | }, |
203 | ast::Variant(it) => { | 202 | ast::Variant(it) => { |
204 | let def: hir::EnumVariant = sema.to_def(&it)?; | 203 | let def: hir::EnumVariant = sema.to_def(&it)?; |
205 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 204 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
206 | }, | 205 | }, |
207 | ast::Fn(it) => { | 206 | ast::Fn(it) => { |
208 | let def: hir::Function = sema.to_def(&it)?; | 207 | let def: hir::Function = sema.to_def(&it)?; |
209 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 208 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
210 | }, | 209 | }, |
211 | ast::Const(it) => { | 210 | ast::Const(it) => { |
212 | let def: hir::Const = sema.to_def(&it)?; | 211 | let def: hir::Const = sema.to_def(&it)?; |
213 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 212 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
214 | }, | 213 | }, |
215 | ast::TypeAlias(it) => { | 214 | ast::TypeAlias(it) => { |
216 | let def: hir::TypeAlias = sema.to_def(&it)?; | 215 | let def: hir::TypeAlias = sema.to_def(&it)?; |
217 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 216 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
218 | }, | 217 | }, |
219 | ast::MacroCall(it) => { | 218 | ast::MacroCall(it) => { |
220 | let def = sema.to_def(&it)?; | 219 | let def = sema.to_def(&it)?; |
221 | Some(NameClass::Definition(Definition::Macro(def))) | 220 | Some(NameClass::Definition(Definition::Macro(def))) |
222 | }, | 221 | }, |
223 | ast::TypeParam(it) => { | 222 | ast::TypeParam(it) => { |
224 | let def = sema.to_def(&it)?; | 223 | let def = sema.to_def(&it)?; |
225 | Some(NameClass::Definition(Definition::TypeParam(def))) | 224 | Some(NameClass::Definition(Definition::TypeParam(def))) |
226 | }, | 225 | }, |
227 | _ => None, | 226 | _ => None, |
227 | } | ||
228 | } | 228 | } |
229 | } | 229 | } |
230 | } | 230 | } |
@@ -244,91 +244,91 @@ impl NameRefClass { | |||
244 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), | 244 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), |
245 | } | 245 | } |
246 | } | 246 | } |
247 | } | ||
248 | 247 | ||
249 | // Note: we don't have unit-tests for this rather important function. | 248 | // Note: we don't have unit-tests for this rather important function. |
250 | // It is primarily exercised via goto definition tests in `ide`. | 249 | // It is primarily exercised via goto definition tests in `ide`. |
251 | pub fn classify_name_ref( | 250 | pub fn classify( |
252 | sema: &Semantics<RootDatabase>, | 251 | sema: &Semantics<RootDatabase>, |
253 | name_ref: &ast::NameRef, | 252 | name_ref: &ast::NameRef, |
254 | ) -> Option<NameRefClass> { | 253 | ) -> Option<NameRefClass> { |
255 | let _p = profile::span("classify_name_ref"); | 254 | let _p = profile::span("classify_name_ref"); |
256 | 255 | ||
257 | let parent = name_ref.syntax().parent()?; | 256 | let parent = name_ref.syntax().parent()?; |
258 | 257 | ||
259 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 258 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
260 | if let Some(func) = sema.resolve_method_call(&method_call) { | 259 | if let Some(func) = sema.resolve_method_call(&method_call) { |
261 | return Some(NameRefClass::Definition(Definition::ModuleDef(func.into()))); | 260 | return Some(NameRefClass::Definition(Definition::ModuleDef(func.into()))); |
261 | } | ||
262 | } | 262 | } |
263 | } | ||
264 | 263 | ||
265 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 264 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
266 | if let Some(field) = sema.resolve_field(&field_expr) { | 265 | if let Some(field) = sema.resolve_field(&field_expr) { |
267 | return Some(NameRefClass::Definition(Definition::Field(field))); | 266 | return Some(NameRefClass::Definition(Definition::Field(field))); |
267 | } | ||
268 | } | 268 | } |
269 | } | ||
270 | 269 | ||
271 | if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) { | 270 | if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) { |
272 | if let Some((field, local)) = sema.resolve_record_field(&record_field) { | 271 | if let Some((field, local)) = sema.resolve_record_field(&record_field) { |
273 | let field = Definition::Field(field); | 272 | let field = Definition::Field(field); |
274 | let res = match local { | 273 | let res = match local { |
275 | None => NameRefClass::Definition(field), | 274 | None => NameRefClass::Definition(field), |
276 | Some(local) => NameRefClass::FieldShorthand { field, local }, | 275 | Some(local) => NameRefClass::FieldShorthand { field, local }, |
277 | }; | 276 | }; |
278 | return Some(res); | 277 | return Some(res); |
278 | } | ||
279 | } | 279 | } |
280 | } | ||
281 | 280 | ||
282 | if let Some(record_pat_field) = ast::RecordPatField::cast(parent.clone()) { | 281 | if let Some(record_pat_field) = ast::RecordPatField::cast(parent.clone()) { |
283 | if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) { | 282 | if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) { |
284 | let field = Definition::Field(field); | 283 | let field = Definition::Field(field); |
285 | return Some(NameRefClass::Definition(field)); | 284 | return Some(NameRefClass::Definition(field)); |
285 | } | ||
286 | } | 286 | } |
287 | } | ||
288 | 287 | ||
289 | if ast::AssocTypeArg::cast(parent.clone()).is_some() { | 288 | if ast::AssocTypeArg::cast(parent.clone()).is_some() { |
290 | // `Trait<Assoc = Ty>` | 289 | // `Trait<Assoc = Ty>` |
291 | // ^^^^^ | 290 | // ^^^^^ |
292 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 291 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; |
293 | let resolved = sema.resolve_path(&path)?; | 292 | let resolved = sema.resolve_path(&path)?; |
294 | if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved { | 293 | if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved { |
295 | if let Some(ty) = tr | 294 | if let Some(ty) = tr |
296 | .items(sema.db) | 295 | .items(sema.db) |
297 | .iter() | 296 | .iter() |
298 | .filter_map(|assoc| match assoc { | 297 | .filter_map(|assoc| match assoc { |
299 | hir::AssocItem::TypeAlias(it) => Some(*it), | 298 | hir::AssocItem::TypeAlias(it) => Some(*it), |
300 | _ => None, | 299 | _ => None, |
301 | }) | 300 | }) |
302 | .find(|alias| alias.name(sema.db).to_string() == **name_ref.text()) | 301 | .find(|alias| alias.name(sema.db).to_string() == **name_ref.text()) |
303 | { | 302 | { |
304 | return Some(NameRefClass::Definition(Definition::ModuleDef( | 303 | return Some(NameRefClass::Definition(Definition::ModuleDef( |
305 | ModuleDef::TypeAlias(ty), | 304 | ModuleDef::TypeAlias(ty), |
306 | ))); | 305 | ))); |
306 | } | ||
307 | } | 307 | } |
308 | } | 308 | } |
309 | } | ||
310 | 309 | ||
311 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 310 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
312 | if let Some(path) = macro_call.path() { | 311 | if let Some(path) = macro_call.path() { |
313 | if path.qualifier().is_none() { | 312 | if path.qualifier().is_none() { |
314 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment | 313 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment |
315 | // paths are handled below (allowing `log<|>::info!` to resolve to the log crate). | 314 | // paths are handled below (allowing `log<|>::info!` to resolve to the log crate). |
316 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | 315 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { |
317 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); | 316 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); |
317 | } | ||
318 | } | 318 | } |
319 | } | 319 | } |
320 | } | 320 | } |
321 | } | ||
322 | 321 | ||
323 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { | 322 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { |
324 | if let Some(resolved) = sema.resolve_path(&path) { | 323 | if let Some(resolved) = sema.resolve_path(&path) { |
325 | return Some(NameRefClass::Definition(resolved.into())); | 324 | return Some(NameRefClass::Definition(resolved.into())); |
325 | } | ||
326 | } | 326 | } |
327 | } | ||
328 | 327 | ||
329 | let extern_crate = ast::ExternCrate::cast(parent)?; | 328 | let extern_crate = ast::ExternCrate::cast(parent)?; |
330 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | 329 | let resolved = sema.resolve_extern_crate(&extern_crate)?; |
331 | Some(NameRefClass::ExternCrate(resolved)) | 330 | Some(NameRefClass::ExternCrate(resolved)) |
331 | } | ||
332 | } | 332 | } |
333 | 333 | ||
334 | impl From<PathResolution> for Definition { | 334 | impl From<PathResolution> for Definition { |
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/imports_locator.rs index e0d3e7293..8c925fbdc 100644 --- a/crates/ide_db/src/imports_locator.rs +++ b/crates/ide_db/src/imports_locator.rs | |||
@@ -5,7 +5,7 @@ use hir::{Crate, MacroDef, ModuleDef, Semantics}; | |||
5 | use syntax::{ast, AstNode, SyntaxKind::NAME}; | 5 | use syntax::{ast, AstNode, SyntaxKind::NAME}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | defs::{classify_name, Definition}, | 8 | defs::{Definition, NameClass}, |
9 | symbol_index::{self, FileSymbol, Query}, | 9 | symbol_index::{self, FileSymbol, Query}, |
10 | RootDatabase, | 10 | RootDatabase, |
11 | }; | 11 | }; |
@@ -60,5 +60,5 @@ fn get_name_definition<'a>( | |||
60 | candidate_node | 60 | candidate_node |
61 | }; | 61 | }; |
62 | let name = ast::Name::cast(candidate_name_node)?; | 62 | let name = ast::Name::cast(candidate_name_node)?; |
63 | classify_name(sema, &name)?.definition(sema.db) | 63 | NameClass::classify(sema, &name)?.definition(sema.db) |
64 | } | 64 | } |
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 8048aa621..3af52ec5e 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -14,7 +14,7 @@ use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; | |||
14 | 14 | ||
15 | use crate::defs::NameClass; | 15 | use crate::defs::NameClass; |
16 | use crate::{ | 16 | use crate::{ |
17 | defs::{classify_name, classify_name_ref, Definition, NameRefClass}, | 17 | defs::{Definition, NameRefClass}, |
18 | RootDatabase, | 18 | RootDatabase, |
19 | }; | 19 | }; |
20 | 20 | ||
@@ -276,7 +276,7 @@ impl<'a> FindUsages<'a> { | |||
276 | name_ref: &ast::NameRef, | 276 | name_ref: &ast::NameRef, |
277 | sink: &mut dyn FnMut(Reference) -> bool, | 277 | sink: &mut dyn FnMut(Reference) -> bool, |
278 | ) -> bool { | 278 | ) -> bool { |
279 | match classify_name_ref(self.sema, &name_ref) { | 279 | match NameRefClass::classify(self.sema, &name_ref) { |
280 | Some(NameRefClass::Definition(def)) if &def == self.def => { | 280 | Some(NameRefClass::Definition(def)) if &def == self.def => { |
281 | let kind = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) | 281 | let kind = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) |
282 | { | 282 | { |
@@ -313,7 +313,7 @@ impl<'a> FindUsages<'a> { | |||
313 | } | 313 | } |
314 | 314 | ||
315 | fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool { | 315 | fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool { |
316 | match classify_name(self.sema, name) { | 316 | match NameClass::classify(self.sema, name) { |
317 | Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) => { | 317 | Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) => { |
318 | let reference = match self.def { | 318 | let reference = match self.def { |
319 | Definition::Field(_) if &field_ref == self.def => Reference { | 319 | Definition::Field(_) if &field_ref == self.def => Reference { |