aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2020-12-16 20:35:15 +0000
committerLukas Wirth <[email protected]>2020-12-16 21:21:01 +0000
commit55faa2daa3fc8bd213038a012b1c5e9ad5fd3736 (patch)
tree2d84a7fa9fe93aa7a6bdd4d0f9cda87e6bb4a5da /crates/ide_db
parent067067a6c11bb5afda98f5af14bfdec4744e7812 (diff)
Lifetime reference search
Diffstat (limited to 'crates/ide_db')
-rw-r--r--crates/ide_db/src/defs.rs59
-rw-r--r--crates/ide_db/src/search.rs63
-rw-r--r--crates/ide_db/src/symbol_index.rs3
3 files changed, 107 insertions, 18 deletions
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index d4a774261..f2d1e4c39 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -6,12 +6,12 @@
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 db::HirDatabase, Crate, Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, 9 db::HirDatabase, Crate, Field, HasVisibility, ImplDef, LifetimeParam, Local, MacroDef, Module,
10 Name, PathResolution, Semantics, TypeParam, Visibility, 10 ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility,
11}; 11};
12use syntax::{ 12use syntax::{
13 ast::{self, AstNode}, 13 ast::{self, AstNode},
14 match_ast, SyntaxNode, 14 match_ast, SyntaxKind, SyntaxNode,
15}; 15};
16 16
17use crate::RootDatabase; 17use crate::RootDatabase;
@@ -25,6 +25,8 @@ pub enum Definition {
25 SelfType(ImplDef), 25 SelfType(ImplDef),
26 Local(Local), 26 Local(Local),
27 TypeParam(TypeParam), 27 TypeParam(TypeParam),
28 LifetimeParam(LifetimeParam),
29 // FIXME: Label
28} 30}
29 31
30impl Definition { 32impl Definition {
@@ -36,6 +38,7 @@ impl Definition {
36 Definition::SelfType(it) => Some(it.module(db)), 38 Definition::SelfType(it) => Some(it.module(db)),
37 Definition::Local(it) => Some(it.module(db)), 39 Definition::Local(it) => Some(it.module(db)),
38 Definition::TypeParam(it) => Some(it.module(db)), 40 Definition::TypeParam(it) => Some(it.module(db)),
41 Definition::LifetimeParam(it) => Some(it.module(db)),
39 } 42 }
40 } 43 }
41 44
@@ -47,6 +50,7 @@ impl Definition {
47 Definition::SelfType(_) => None, 50 Definition::SelfType(_) => None,
48 Definition::Local(_) => None, 51 Definition::Local(_) => None,
49 Definition::TypeParam(_) => None, 52 Definition::TypeParam(_) => None,
53 Definition::LifetimeParam(_) => None,
50 } 54 }
51 } 55 }
52 56
@@ -72,6 +76,7 @@ impl Definition {
72 Definition::SelfType(_) => return None, 76 Definition::SelfType(_) => return None,
73 Definition::Local(it) => it.name(db)?, 77 Definition::Local(it) => it.name(db)?,
74 Definition::TypeParam(it) => it.name(db), 78 Definition::TypeParam(it) => it.name(db),
79 Definition::LifetimeParam(it) => it.name(db),
75 }; 80 };
76 Some(name) 81 Some(name)
77 } 82 }
@@ -229,6 +234,25 @@ impl NameClass {
229 } 234 }
230 } 235 }
231 } 236 }
237
238 pub fn classify_lifetime(
239 sema: &Semantics<RootDatabase>,
240 lifetime: &ast::Lifetime,
241 ) -> Option<NameClass> {
242 let _p = profile::span("classify_lifetime").detail(|| lifetime.to_string());
243 let parent = lifetime.syntax().parent()?;
244
245 match_ast! {
246 match parent {
247 ast::LifetimeParam(it) => {
248 let def = sema.to_def(&it)?;
249 Some(NameClass::Definition(Definition::LifetimeParam(def)))
250 },
251 ast::Label(_it) => None,
252 _ => None,
253 }
254 }
255 }
232} 256}
233 257
234#[derive(Debug)] 258#[derive(Debug)]
@@ -338,6 +362,35 @@ impl NameRefClass {
338 let resolved = sema.resolve_extern_crate(&extern_crate)?; 362 let resolved = sema.resolve_extern_crate(&extern_crate)?;
339 Some(NameRefClass::ExternCrate(resolved)) 363 Some(NameRefClass::ExternCrate(resolved))
340 } 364 }
365
366 pub fn classify_lifetime(
367 sema: &Semantics<RootDatabase>,
368 lifetime: &ast::Lifetime,
369 ) -> Option<NameRefClass> {
370 let _p = profile::span("classify_lifetime_ref").detail(|| lifetime.to_string());
371 let parent = lifetime.syntax().parent()?;
372 match parent.kind() {
373 SyntaxKind::LIFETIME_ARG
374 | SyntaxKind::SELF_PARAM
375 | SyntaxKind::TYPE_BOUND
376 | SyntaxKind::WHERE_PRED
377 | SyntaxKind::REF_TYPE => sema
378 .resolve_lifetime_param(lifetime)
379 .map(Definition::LifetimeParam)
380 .map(NameRefClass::Definition),
381 // lifetime bounds, as in the 'b in 'a: 'b aren't wrapped in TypeBound nodes so we gotta check
382 // if our lifetime is in a LifetimeParam without being the constrained lifetime
383 _ if ast::LifetimeParam::cast(parent).and_then(|param| param.lifetime()).as_ref()
384 != Some(lifetime) =>
385 {
386 sema.resolve_lifetime_param(lifetime)
387 .map(Definition::LifetimeParam)
388 .map(NameRefClass::Definition)
389 }
390 SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => None,
391 _ => None,
392 }
393 }
341} 394}
342 395
343impl From<PathResolution> for Definition { 396impl From<PathResolution> for Definition {
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index 3936c7390..5b3997bcf 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -33,6 +33,7 @@ pub enum ReferenceKind {
33 RecordFieldExprOrPat, 33 RecordFieldExprOrPat,
34 SelfKw, 34 SelfKw,
35 EnumLiteral, 35 EnumLiteral,
36 Lifetime,
36 Other, 37 Other,
37} 38}
38 39
@@ -129,6 +130,25 @@ impl Definition {
129 return SearchScope::new(res); 130 return SearchScope::new(res);
130 } 131 }
131 132
133 if let Definition::LifetimeParam(param) = self {
134 let range = match param.parent(db) {
135 hir::GenericDef::Function(it) => it.source(db).value.syntax().text_range(),
136 hir::GenericDef::Adt(it) => match it {
137 hir::Adt::Struct(it) => it.source(db).value.syntax().text_range(),
138 hir::Adt::Union(it) => it.source(db).value.syntax().text_range(),
139 hir::Adt::Enum(it) => it.source(db).value.syntax().text_range(),
140 },
141 hir::GenericDef::Trait(it) => it.source(db).value.syntax().text_range(),
142 hir::GenericDef::TypeAlias(it) => it.source(db).value.syntax().text_range(),
143 hir::GenericDef::ImplDef(it) => it.source(db).value.syntax().text_range(),
144 hir::GenericDef::EnumVariant(it) => it.source(db).value.syntax().text_range(),
145 hir::GenericDef::Const(it) => it.source(db).value.syntax().text_range(),
146 };
147 let mut res = FxHashMap::default();
148 res.insert(file_id, Some(range));
149 return SearchScope::new(res);
150 }
151
132 let vis = self.visibility(db); 152 let vis = self.visibility(db);
133 153
134 if let Some(Visibility::Module(module)) = vis.and_then(|it| it.into()) { 154 if let Some(Visibility::Module(module)) = vis.and_then(|it| it.into()) {
@@ -255,25 +275,42 @@ impl<'a> FindUsages<'a> {
255 continue; 275 continue;
256 } 276 }
257 277
258 match sema.find_node_at_offset_with_descend(&tree, offset) { 278 if let Some(name_ref) = sema.find_node_at_offset_with_descend(&tree, offset) {
259 Some(name_ref) => { 279 if self.found_name_ref(&name_ref, sink) {
260 if self.found_name_ref(&name_ref, sink) { 280 return;
261 return; 281 }
262 } 282 } else if let Some(name) = sema.find_node_at_offset_with_descend(&tree, offset) {
283 if self.found_name(&name, sink) {
284 return;
285 }
286 } else if let Some(lifetime) = sema.find_node_at_offset_with_descend(&tree, offset)
287 {
288 if self.found_lifetime(&lifetime, sink) {
289 return;
263 } 290 }
264 None => match sema.find_node_at_offset_with_descend(&tree, offset) {
265 Some(name) => {
266 if self.found_name(&name, sink) {
267 return;
268 }
269 }
270 None => {}
271 },
272 } 291 }
273 } 292 }
274 } 293 }
275 } 294 }
276 295
296 fn found_lifetime(
297 &self,
298 lifetime: &ast::Lifetime,
299 sink: &mut dyn FnMut(Reference) -> bool,
300 ) -> bool {
301 match NameRefClass::classify_lifetime(self.sema, lifetime) {
302 Some(NameRefClass::Definition(def)) if &def == self.def => {
303 let reference = Reference {
304 file_range: self.sema.original_range(lifetime.syntax()),
305 kind: ReferenceKind::Lifetime,
306 access: None,
307 };
308 sink(reference)
309 }
310 _ => false, // not a usage
311 }
312 }
313
277 fn found_name_ref( 314 fn found_name_ref(
278 &self, 315 &self,
279 name_ref: &ast::NameRef, 316 name_ref: &ast::NameRef,
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index 121063aea..ca455fa03 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -209,8 +209,7 @@ pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<Fil
209 query.search(&buf) 209 query.search(&buf)
210} 210}
211 211
212pub fn index_resolve(db: &RootDatabase, name_ref: &ast::NameRef) -> Vec<FileSymbol> { 212pub fn index_resolve(db: &RootDatabase, name: &SmolStr) -> Vec<FileSymbol> {
213 let name = name_ref.text();
214 let mut query = Query::new(name.to_string()); 213 let mut query = Query::new(name.to_string());
215 query.exact(); 214 query.exact();
216 query.limit(4); 215 query.limit(4);