From c6f1de6ac5d3496fc3c30b5e15263db68d057695 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 6 Oct 2020 21:05:57 +0200 Subject: Use FamousDefs for shorten_iterator hint --- crates/assists/src/utils.rs | 61 ++++++++++++++++++++++------ crates/ide/src/inlay_hints.rs | 93 +++++++++++++++++-------------------------- 2 files changed, 85 insertions(+), 69 deletions(-) (limited to 'crates') diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index eb69c49a4..0335969fd 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs @@ -274,24 +274,54 @@ impl TryEnum { /// somewhat similar to the known paths infra inside hir, but it different; We /// want to make sure that IDE specific paths don't become interesting inside /// the compiler itself as well. -pub(crate) struct FamousDefs<'a, 'b>(pub(crate) &'a Semantics<'b, RootDatabase>, pub(crate) Crate); +pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Crate); #[allow(non_snake_case)] impl FamousDefs<'_, '_> { - #[cfg(test)] - pub(crate) const FIXTURE: &'static str = r#"//- /libcore.rs crate:core + pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core pub mod convert { pub trait From { fn from(T) -> Self; } } +pub mod iter { + pub use self::traits::iterator::Iterator; + mod traits { mod iterator { + use crate::option::Option; + pub trait Iterator { + type Item; + fn next(&mut self) -> Option; + } + } } + + pub use self::sources::*; + mod sources { + use super::Iterator; + pub struct Repeat { + element: A, + } + + pub fn repeat(elt: T) -> Repeat { + Repeat { element: elt } + } + + impl Iterator for Repeat { + type Item = A; + + fn next(&mut self) -> Option { + Some(self.element.clone()) + } + } + } +} + pub mod option { pub enum Option { None, Some(T)} } pub mod prelude { - pub use crate::{convert::From, option::Option::{self, *}}; + pub use crate::{convert::From, iter::Iterator, option::Option::{self, *}}; } #[prelude_import] pub use prelude::*; @@ -305,6 +335,10 @@ pub use prelude::*; self.find_enum("core:option:Option") } + pub fn core_iter_Iterator(&self) -> Option { + self.find_trait("core:iter:traits:iterator:Iterator") + } + fn find_trait(&self, path: &str) -> Option { match self.find_def(path)? { hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it), @@ -324,18 +358,21 @@ pub use prelude::*; let mut path = path.split(':'); let trait_ = path.next_back()?; let std_crate = path.next()?; - let std_crate = self + let std_crate = if self .1 - .dependencies(db) - .into_iter() - .find(|dep| &dep.name.to_string() == std_crate)? - .krate; - + .declaration_name(db) + .map(|name| name.to_string() == std_crate) + .unwrap_or(false) + { + self.1 + } else { + self.1.dependencies(db).into_iter().find(|dep| dep.name.to_string() == std_crate)?.krate + }; let mut module = std_crate.root_module(db); for segment in path { module = module.children(db).find_map(|child| { let name = child.name(db)?; - if &name.to_string() == segment { + if name.to_string() == segment { Some(child) } else { None @@ -343,7 +380,7 @@ pub use prelude::*; })?; } let def = - module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1; + module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1; Some(def) } } diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index d8e67bbd9..27bd1e37f 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -1,4 +1,5 @@ -use hir::{known, Adt, AssocItem, Callable, HirDisplay, ModuleDef, Semantics, Type}; +use assists::utils::FamousDefs; +use hir::{known, Adt, AssocItem, Callable, HirDisplay, Semantics, Type}; use ide_db::RootDatabase; use stdx::to_lower_snake_case; use syntax::{ @@ -194,7 +195,7 @@ fn get_bind_pat_hints( } let db = sema.db; - if let Some(hint) = hint_iterator(db, config, &ty, pat.clone()) { + if let Some(hint) = hint_iterator(sema, config, &ty, pat.clone()) { acc.push(hint); } else { acc.push(InlayHint { @@ -209,45 +210,44 @@ fn get_bind_pat_hints( /// Checks if the type is an Iterator from std::iter and replaces its hint with an `impl Iterator`. fn hint_iterator( - db: &RootDatabase, + sema: &Semantics, config: &InlayHintsConfig, ty: &Type, pat: ast::IdentPat, ) -> Option { + let db = sema.db; let strukt = ty.as_adt()?; let krate = strukt.krate(db)?; - let module = strukt.module(db); if krate.declaration_name(db).as_deref() != Some("core") { return None; } - let module = module + // assert this type comes from `core::iter` + strukt + .module(db) .path_to_root(db) .into_iter() .rev() .find(|module| module.name(db) == Some(known::iter))?; - let iter_trait = module.scope(db, None).into_iter().find_map(|(name, def)| match def { - hir::ScopeDef::ModuleDef(ModuleDef::Trait(r#trait)) if name == known::Iterator => { - Some(r#trait) - } - _ => None, - })?; + let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?; if ty.impls_trait(db, iter_trait, &[]) { let assoc_type_item = iter_trait.items(db).into_iter().find_map(|item| match item { AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias), _ => None, })?; if let Some(ty) = ty.normalize_trait_assoc_type(db, iter_trait, &[], assoc_type_item) { + const LABEL_START: &str = "impl Iterator", - ty.display_truncated( - db, - config.max_length.map(|len| len - 22 /*len of the template string above*/) - ) - ) - .into(), + label: format!("{}{}{}", LABEL_START, ty_display, LABEL_END).into(), }); } } @@ -401,6 +401,7 @@ fn get_callable(sema: &Semantics, expr: &ast::Expr) -> Option Option { + None + } +} + fn main() { + let _x = MyIter; + //^^ MyIter let _x = iter::repeat(0); //^^ impl Iterator - let _y = iter::Chain(iter::repeat(0), iter::repeat(0)); - //^^ impl Iterator fn generic(t: T) { let _x = iter::repeat(t); //^^ impl Iterator @@ -1141,42 +1153,9 @@ fn main() { //- /std.rs crate:std deps:core use core::*; - -//- /core.rs crate:core -pub enum Option { - Some(T), - None -} - -pub mod iter { - pub use self::traits::iterator::Iterator; - pub mod traits { pub mod iterator { - pub trait Iterator { - type Item; - } - } } - - pub use self::sources::*; - pub mod sources { - use super::Iterator; - pub struct Repeat(pub T); - - pub fn repeat(t: T) -> Repeat { - Repeat(f) - } - - impl Iterator for Repeat { - type Item = T; - } - - pub struct Chain(pub A, pub B); - - impl Iterator for Chain where A: Iterator, B: Iterator { - type Item = T; - } - } -} "#, + FamousDefs::FIXTURE + ), ); } } -- cgit v1.2.3