diff options
Diffstat (limited to 'crates/assists/src')
-rw-r--r-- | crates/assists/src/utils.rs | 110 |
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 | ||
4 | use std::{iter, ops}; | 4 | use std::{iter, ops}; |
5 | 5 | ||
6 | use hir::{Adt, Crate, Enum, ScopeDef, Semantics, Trait, Type}; | 6 | use hir::{Adt, Crate, Enum, Module, ScopeDef, Semantics, Trait, Type}; |
7 | use ide_db::RootDatabase; | 7 | use ide_db::RootDatabase; |
8 | use itertools::Itertools; | 8 | use itertools::Itertools; |
9 | use rustc_hash::FxHashSet; | 9 | use 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. |
277 | pub(crate) struct FamousDefs<'a, 'b>(pub(crate) &'a Semantics<'b, RootDatabase>, pub(crate) Crate); | 277 | pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Crate); |
278 | 278 | ||
279 | #[allow(non_snake_case)] | 279 | #[allow(non_snake_case)] |
280 | impl FamousDefs<'_, '_> { | 280 | impl 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 | ||
283 | pub mod convert { | 282 | pub 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 | |||
288 | pub 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 | ||
293 | pub mod prelude { | 357 | pub 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] |
297 | pub use prelude::*; | 361 | pub 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 | } |