aboutsummaryrefslogtreecommitdiff
path: root/crates/assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists')
-rw-r--r--crates/assists/src/utils.rs110
1 files changed, 96 insertions, 14 deletions
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index eb69c49a4..c1847f601 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -3,7 +3,7 @@ pub(crate) mod insert_use;
3 3
4use std::{iter, ops}; 4use std::{iter, ops};
5 5
6use hir::{Adt, Crate, Enum, ScopeDef, Semantics, Trait, Type}; 6use hir::{Adt, Crate, Enum, Module, ScopeDef, Semantics, Trait, Type};
7use ide_db::RootDatabase; 7use ide_db::RootDatabase;
8use itertools::Itertools; 8use itertools::Itertools;
9use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
@@ -274,15 +274,79 @@ impl TryEnum {
274/// somewhat similar to the known paths infra inside hir, but it different; We 274/// somewhat similar to the known paths infra inside hir, but it different; We
275/// want to make sure that IDE specific paths don't become interesting inside 275/// want to make sure that IDE specific paths don't become interesting inside
276/// the compiler itself as well. 276/// the compiler itself as well.
277pub(crate) struct FamousDefs<'a, 'b>(pub(crate) &'a Semantics<'b, RootDatabase>, pub(crate) Crate); 277pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Crate);
278 278
279#[allow(non_snake_case)] 279#[allow(non_snake_case)]
280impl FamousDefs<'_, '_> { 280impl FamousDefs<'_, '_> {
281 #[cfg(test)] 281 pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
282 pub(crate) const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
283pub mod convert { 282pub mod convert {
284 pub trait From<T> { 283 pub trait From<T> {
285 fn from(T) -> Self; 284 fn from(t: T) -> Self;
285 }
286}
287
288pub mod iter {
289 pub use self::traits::{collect::IntoIterator, iterator::Iterator};
290 mod traits {
291 pub(crate) mod iterator {
292 use crate::option::Option;
293 pub trait Iterator {
294 type Item;
295 fn next(&mut self) -> Option<Self::Item>;
296 fn by_ref(&mut self) -> &mut Self {
297 self
298 }
299 fn take(self, n: usize) -> crate::iter::Take<Self> {
300 crate::iter::Take { inner: self }
301 }
302 }
303
304 impl<I: Iterator> Iterator for &mut I {
305 type Item = I::Item;
306 fn next(&mut self) -> Option<I::Item> {
307 (**self).next()
308 }
309 }
310 }
311 pub(crate) mod collect {
312 pub trait IntoIterator {
313 type Item;
314 }
315 }
316 }
317
318 pub use self::sources::*;
319 pub(crate) mod sources {
320 use super::Iterator;
321 use crate::option::Option::{self, *};
322 pub struct Repeat<A> {
323 element: A,
324 }
325
326 pub fn repeat<T>(elt: T) -> Repeat<T> {
327 Repeat { element: elt }
328 }
329
330 impl<A> Iterator for Repeat<A> {
331 type Item = A;
332
333 fn next(&mut self) -> Option<A> {
334 None
335 }
336 }
337 }
338
339 pub use self::adapters::*;
340 pub(crate) mod adapters {
341 use super::Iterator;
342 use crate::option::Option::{self, *};
343 pub struct Take<I> { pub(crate) inner: I }
344 impl<I> Iterator for Take<I> where I: Iterator {
345 type Item = <I as Iterator>::Item;
346 fn next(&mut self) -> Option<<I as Iterator>::Item> {
347 None
348 }
349 }
286 } 350 }
287} 351}
288 352
@@ -291,7 +355,7 @@ pub mod option {
291} 355}
292 356
293pub mod prelude { 357pub mod prelude {
294 pub use crate::{convert::From, option::Option::{self, *}}; 358 pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}};
295} 359}
296#[prelude_import] 360#[prelude_import]
297pub use prelude::*; 361pub use prelude::*;
@@ -305,6 +369,14 @@ pub use prelude::*;
305 self.find_enum("core:option:Option") 369 self.find_enum("core:option:Option")
306 } 370 }
307 371
372 pub fn core_iter_Iterator(&self) -> Option<Trait> {
373 self.find_trait("core:iter:traits:iterator:Iterator")
374 }
375
376 pub fn core_iter(&self) -> Option<Module> {
377 self.find_module("core:iter")
378 }
379
308 fn find_trait(&self, path: &str) -> Option<Trait> { 380 fn find_trait(&self, path: &str) -> Option<Trait> {
309 match self.find_def(path)? { 381 match self.find_def(path)? {
310 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it), 382 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
@@ -319,23 +391,33 @@ pub use prelude::*;
319 } 391 }
320 } 392 }
321 393
394 fn find_module(&self, path: &str) -> Option<Module> {
395 match self.find_def(path)? {
396 hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(it)) => Some(it),
397 _ => None,
398 }
399 }
400
322 fn find_def(&self, path: &str) -> Option<ScopeDef> { 401 fn find_def(&self, path: &str) -> Option<ScopeDef> {
323 let db = self.0.db; 402 let db = self.0.db;
324 let mut path = path.split(':'); 403 let mut path = path.split(':');
325 let trait_ = path.next_back()?; 404 let trait_ = path.next_back()?;
326 let std_crate = path.next()?; 405 let std_crate = path.next()?;
327 let std_crate = self 406 let std_crate = if self
328 .1 407 .1
329 .dependencies(db) 408 .declaration_name(db)
330 .into_iter() 409 .map(|name| name.to_string() == std_crate)
331 .find(|dep| &dep.name.to_string() == std_crate)? 410 .unwrap_or(false)
332 .krate; 411 {
333 412 self.1
413 } else {
414 self.1.dependencies(db).into_iter().find(|dep| dep.name.to_string() == std_crate)?.krate
415 };
334 let mut module = std_crate.root_module(db); 416 let mut module = std_crate.root_module(db);
335 for segment in path { 417 for segment in path {
336 module = module.children(db).find_map(|child| { 418 module = module.children(db).find_map(|child| {
337 let name = child.name(db)?; 419 let name = child.name(db)?;
338 if &name.to_string() == segment { 420 if name.to_string() == segment {
339 Some(child) 421 Some(child)
340 } else { 422 } else {
341 None 423 None
@@ -343,7 +425,7 @@ pub use prelude::*;
343 })?; 425 })?;
344 } 426 }
345 let def = 427 let def =
346 module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1; 428 module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1;
347 Some(def) 429 Some(def)
348 } 430 }
349} 431}