diff options
author | Aleksey Kladov <[email protected]> | 2020-08-19 17:58:48 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-08-19 17:58:48 +0100 |
commit | 81b0976187d73eba4f9b14d8a0b8539ab8f06dcd (patch) | |
tree | 15017f0b41ea44614d603f0b9e029e7bc86a5c44 | |
parent | 686a6a26fd2263e4bb958fbcf94b04244ed73e08 (diff) |
Future proof find-usages API
We might want to provide more efficient impls for check if usages
exist, limiting the search, filtering and cancellation, so let's
violate YAGNI a bit here.
-rw-r--r-- | crates/assists/src/handlers/extract_struct_from_enum_variant.rs | 2 | ||||
-rw-r--r-- | crates/assists/src/handlers/inline_local_variable.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/references.rs | 4 | ||||
-rw-r--r-- | crates/ide_db/src/search.rs | 48 | ||||
-rw-r--r-- | crates/ssr/src/search.rs | 2 |
5 files changed, 41 insertions, 17 deletions
diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index d62e06b4a..c1124b9e2 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -53,7 +53,7 @@ pub(crate) fn extract_struct_from_enum_variant( | |||
53 | target, | 53 | target, |
54 | |builder| { | 54 | |builder| { |
55 | let definition = Definition::ModuleDef(ModuleDef::EnumVariant(variant_hir)); | 55 | let definition = Definition::ModuleDef(ModuleDef::EnumVariant(variant_hir)); |
56 | let res = definition.find_usages(&ctx.sema, None); | 56 | let res = definition.usages(&ctx.sema).all(); |
57 | let start_offset = variant.parent_enum().syntax().text_range().start(); | 57 | let start_offset = variant.parent_enum().syntax().text_range().start(); |
58 | let mut visited_modules_set = FxHashSet::default(); | 58 | let mut visited_modules_set = FxHashSet::default(); |
59 | visited_modules_set.insert(current_module); | 59 | visited_modules_set.insert(current_module); |
diff --git a/crates/assists/src/handlers/inline_local_variable.rs b/crates/assists/src/handlers/inline_local_variable.rs index 2b52b333b..164bbce86 100644 --- a/crates/assists/src/handlers/inline_local_variable.rs +++ b/crates/assists/src/handlers/inline_local_variable.rs | |||
@@ -44,7 +44,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O | |||
44 | 44 | ||
45 | let def = ctx.sema.to_def(&bind_pat)?; | 45 | let def = ctx.sema.to_def(&bind_pat)?; |
46 | let def = Definition::Local(def); | 46 | let def = Definition::Local(def); |
47 | let refs = def.find_usages(&ctx.sema, None); | 47 | let refs = def.usages(&ctx.sema).all(); |
48 | if refs.is_empty() { | 48 | if refs.is_empty() { |
49 | mark::hit!(test_not_applicable_if_variable_unused); | 49 | mark::hit!(test_not_applicable_if_variable_unused); |
50 | return None; | 50 | return None; |
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 0a76ec6b4..722c8f406 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -106,7 +106,9 @@ pub(crate) fn find_all_refs( | |||
106 | let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; | 106 | let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; |
107 | 107 | ||
108 | let references = def | 108 | let references = def |
109 | .find_usages(sema, search_scope) | 109 | .usages(sema) |
110 | .set_scope(search_scope) | ||
111 | .all() | ||
110 | .into_iter() | 112 | .into_iter() |
111 | .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) | 113 | .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) |
112 | .collect(); | 114 | .collect(); |
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index b9360bf12..ce7631c69 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -181,22 +181,44 @@ impl Definition { | |||
181 | SearchScope::new(res) | 181 | SearchScope::new(res) |
182 | } | 182 | } |
183 | 183 | ||
184 | pub fn find_usages( | 184 | pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> { |
185 | &self, | 185 | FindUsages { def: self, sema, scope: None } |
186 | sema: &Semantics<RootDatabase>, | 186 | } |
187 | search_scope: Option<SearchScope>, | 187 | } |
188 | ) -> Vec<Reference> { | 188 | |
189 | pub struct FindUsages<'a> { | ||
190 | def: &'a Definition, | ||
191 | sema: &'a Semantics<'a, RootDatabase>, | ||
192 | scope: Option<SearchScope>, | ||
193 | } | ||
194 | |||
195 | impl<'a> FindUsages<'a> { | ||
196 | pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> { | ||
197 | self.set_scope(Some(scope)) | ||
198 | } | ||
199 | pub fn set_scope(mut self, scope: Option<SearchScope>) -> FindUsages<'a> { | ||
200 | assert!(self.scope.is_none()); | ||
201 | self.scope = scope; | ||
202 | self | ||
203 | } | ||
204 | |||
205 | pub fn at_least_one(self) -> bool { | ||
206 | self.all().is_empty() | ||
207 | } | ||
208 | |||
209 | pub fn all(self) -> Vec<Reference> { | ||
189 | let _p = profile::span("Definition::find_usages"); | 210 | let _p = profile::span("Definition::find_usages"); |
211 | let sema = self.sema; | ||
190 | 212 | ||
191 | let search_scope = { | 213 | let search_scope = { |
192 | let base = self.search_scope(sema.db); | 214 | let base = self.def.search_scope(sema.db); |
193 | match search_scope { | 215 | match self.scope { |
194 | None => base, | 216 | None => base, |
195 | Some(scope) => base.intersection(&scope), | 217 | Some(scope) => base.intersection(&scope), |
196 | } | 218 | } |
197 | }; | 219 | }; |
198 | 220 | ||
199 | let name = match self.name(sema.db) { | 221 | let name = match self.def.name(sema.db) { |
200 | None => return Vec::new(), | 222 | None => return Vec::new(), |
201 | Some(it) => it.to_string(), | 223 | Some(it) => it.to_string(), |
202 | }; | 224 | }; |
@@ -225,7 +247,7 @@ impl Definition { | |||
225 | }; | 247 | }; |
226 | 248 | ||
227 | match classify_name_ref(&sema, &name_ref) { | 249 | match classify_name_ref(&sema, &name_ref) { |
228 | Some(NameRefClass::Definition(def)) if &def == self => { | 250 | Some(NameRefClass::Definition(def)) if &def == self.def => { |
229 | let kind = if is_record_lit_name_ref(&name_ref) | 251 | let kind = if is_record_lit_name_ref(&name_ref) |
230 | || is_call_expr_name_ref(&name_ref) | 252 | || is_call_expr_name_ref(&name_ref) |
231 | { | 253 | { |
@@ -242,14 +264,14 @@ impl Definition { | |||
242 | }); | 264 | }); |
243 | } | 265 | } |
244 | Some(NameRefClass::FieldShorthand { local, field }) => { | 266 | Some(NameRefClass::FieldShorthand { local, field }) => { |
245 | match self { | 267 | match self.def { |
246 | Definition::Field(_) if &field == self => refs.push(Reference { | 268 | Definition::Field(_) if &field == self.def => refs.push(Reference { |
247 | file_range: sema.original_range(name_ref.syntax()), | 269 | file_range: self.sema.original_range(name_ref.syntax()), |
248 | kind: ReferenceKind::FieldShorthandForField, | 270 | kind: ReferenceKind::FieldShorthandForField, |
249 | access: reference_access(&field, &name_ref), | 271 | access: reference_access(&field, &name_ref), |
250 | }), | 272 | }), |
251 | Definition::Local(l) if &local == l => refs.push(Reference { | 273 | Definition::Local(l) if &local == l => refs.push(Reference { |
252 | file_range: sema.original_range(name_ref.syntax()), | 274 | file_range: self.sema.original_range(name_ref.syntax()), |
253 | kind: ReferenceKind::FieldShorthandForLocal, | 275 | kind: ReferenceKind::FieldShorthandForLocal, |
254 | access: reference_access(&Definition::Local(local), &name_ref), | 276 | access: reference_access(&Definition::Local(local), &name_ref), |
255 | }), | 277 | }), |
diff --git a/crates/ssr/src/search.rs b/crates/ssr/src/search.rs index 8509cfa4d..a595fd269 100644 --- a/crates/ssr/src/search.rs +++ b/crates/ssr/src/search.rs | |||
@@ -114,7 +114,7 @@ impl<'db> MatchFinder<'db> { | |||
114 | // cache miss. This is a limitation of NLL and is fixed with Polonius. For now we do two | 114 | // cache miss. This is a limitation of NLL and is fixed with Polonius. For now we do two |
115 | // lookups in the case of a cache hit. | 115 | // lookups in the case of a cache hit. |
116 | if usage_cache.find(&definition).is_none() { | 116 | if usage_cache.find(&definition).is_none() { |
117 | let usages = definition.find_usages(&self.sema, Some(self.search_scope())); | 117 | let usages = definition.usages(&self.sema).in_scope(self.search_scope()).all(); |
118 | usage_cache.usages.push((definition, usages)); | 118 | usage_cache.usages.push((definition, usages)); |
119 | return &usage_cache.usages.last().unwrap().1; | 119 | return &usage_cache.usages.last().unwrap().1; |
120 | } | 120 | } |