Skip to content

Commit c6f1de6

Browse files
committed
Use FamousDefs for shorten_iterator hint
1 parent aaa3905 commit c6f1de6

File tree

2 files changed

+85
-69
lines changed

2 files changed

+85
-69
lines changed

crates/assists/src/utils.rs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -274,24 +274,54 @@ impl TryEnum {
274274
/// somewhat similar to the known paths infra inside hir, but it different; We
275275
/// want to make sure that IDE specific paths don't become interesting inside
276276
/// 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);
278278

279279
#[allow(non_snake_case)]
280280
impl FamousDefs<'_, '_> {
281-
#[cfg(test)]
282-
pub(crate) const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
281+
pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
283282
pub mod convert {
284283
pub trait From<T> {
285284
fn from(T) -> Self;
286285
}
287286
}
288287
288+
pub mod iter {
289+
pub use self::traits::iterator::Iterator;
290+
mod traits { mod iterator {
291+
use crate::option::Option;
292+
pub trait Iterator {
293+
type Item;
294+
fn next(&mut self) -> Option<Self::Item>;
295+
}
296+
} }
297+
298+
pub use self::sources::*;
299+
mod sources {
300+
use super::Iterator;
301+
pub struct Repeat<A> {
302+
element: A,
303+
}
304+
305+
pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
306+
Repeat { element: elt }
307+
}
308+
309+
impl<A: Clone> Iterator for Repeat<A> {
310+
type Item = A;
311+
312+
fn next(&mut self) -> Option<A> {
313+
Some(self.element.clone())
314+
}
315+
}
316+
}
317+
}
318+
289319
pub mod option {
290320
pub enum Option<T> { None, Some(T)}
291321
}
292322
293323
pub mod prelude {
294-
pub use crate::{convert::From, option::Option::{self, *}};
324+
pub use crate::{convert::From, iter::Iterator, option::Option::{self, *}};
295325
}
296326
#[prelude_import]
297327
pub use prelude::*;
@@ -305,6 +335,10 @@ pub use prelude::*;
305335
self.find_enum("core:option:Option")
306336
}
307337

338+
pub fn core_iter_Iterator(&self) -> Option<Trait> {
339+
self.find_trait("core:iter:traits:iterator:Iterator")
340+
}
341+
308342
fn find_trait(&self, path: &str) -> Option<Trait> {
309343
match self.find_def(path)? {
310344
hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
@@ -324,26 +358,29 @@ pub use prelude::*;
324358
let mut path = path.split(':');
325359
let trait_ = path.next_back()?;
326360
let std_crate = path.next()?;
327-
let std_crate = self
361+
let std_crate = if self
328362
.1
329-
.dependencies(db)
330-
.into_iter()
331-
.find(|dep| &dep.name.to_string() == std_crate)?
332-
.krate;
333-
363+
.declaration_name(db)
364+
.map(|name| name.to_string() == std_crate)
365+
.unwrap_or(false)
366+
{
367+
self.1
368+
} else {
369+
self.1.dependencies(db).into_iter().find(|dep| dep.name.to_string() == std_crate)?.krate
370+
};
334371
let mut module = std_crate.root_module(db);
335372
for segment in path {
336373
module = module.children(db).find_map(|child| {
337374
let name = child.name(db)?;
338-
if &name.to_string() == segment {
375+
if name.to_string() == segment {
339376
Some(child)
340377
} else {
341378
None
342379
}
343380
})?;
344381
}
345382
let def =
346-
module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1;
383+
module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1;
347384
Some(def)
348385
}
349386
}

crates/ide/src/inlay_hints.rs

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use hir::{known, Adt, AssocItem, Callable, HirDisplay, ModuleDef, Semantics, Type};
1+
use assists::utils::FamousDefs;
2+
use hir::{known, Adt, AssocItem, Callable, HirDisplay, Semantics, Type};
23
use ide_db::RootDatabase;
34
use stdx::to_lower_snake_case;
45
use syntax::{
@@ -194,7 +195,7 @@ fn get_bind_pat_hints(
194195
}
195196

196197
let db = sema.db;
197-
if let Some(hint) = hint_iterator(db, config, &ty, pat.clone()) {
198+
if let Some(hint) = hint_iterator(sema, config, &ty, pat.clone()) {
198199
acc.push(hint);
199200
} else {
200201
acc.push(InlayHint {
@@ -209,45 +210,44 @@ fn get_bind_pat_hints(
209210

210211
/// Checks if the type is an Iterator from std::iter and replaces its hint with an `impl Iterator<Item = Ty>`.
211212
fn hint_iterator(
212-
db: &RootDatabase,
213+
sema: &Semantics<RootDatabase>,
213214
config: &InlayHintsConfig,
214215
ty: &Type,
215216
pat: ast::IdentPat,
216217
) -> Option<InlayHint> {
218+
let db = sema.db;
217219
let strukt = ty.as_adt()?;
218220
let krate = strukt.krate(db)?;
219-
let module = strukt.module(db);
220221
if krate.declaration_name(db).as_deref() != Some("core") {
221222
return None;
222223
}
223-
let module = module
224+
// assert this type comes from `core::iter`
225+
strukt
226+
.module(db)
224227
.path_to_root(db)
225228
.into_iter()
226229
.rev()
227230
.find(|module| module.name(db) == Some(known::iter))?;
228-
let iter_trait = module.scope(db, None).into_iter().find_map(|(name, def)| match def {
229-
hir::ScopeDef::ModuleDef(ModuleDef::Trait(r#trait)) if name == known::Iterator => {
230-
Some(r#trait)
231-
}
232-
_ => None,
233-
})?;
231+
let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
234232
if ty.impls_trait(db, iter_trait, &[]) {
235233
let assoc_type_item = iter_trait.items(db).into_iter().find_map(|item| match item {
236234
AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias),
237235
_ => None,
238236
})?;
239237
if let Some(ty) = ty.normalize_trait_assoc_type(db, iter_trait, &[], assoc_type_item) {
238+
const LABEL_START: &str = "impl Iterator<Item = ";
239+
const LABEL_END: &str = ">";
240+
241+
let ty_display = ty.display_truncated(
242+
db,
243+
config
244+
.max_length
245+
.map(|len| len.saturating_sub(LABEL_START.len() + LABEL_END.len())),
246+
);
240247
return Some(InlayHint {
241248
range: pat.syntax().text_range(),
242249
kind: InlayKind::TypeHint,
243-
label: format!(
244-
"impl Iterator<Item = {}>",
245-
ty.display_truncated(
246-
db,
247-
config.max_length.map(|len| len - 22 /*len of the template string above*/)
248-
)
249-
)
250-
.into(),
250+
label: format!("{}{}{}", LABEL_START, ty_display, LABEL_END).into(),
251251
});
252252
}
253253
}
@@ -401,6 +401,7 @@ fn get_callable(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<Call
401401

402402
#[cfg(test)]
403403
mod tests {
404+
use assists::utils::FamousDefs;
404405
use expect_test::{expect, Expect};
405406
use test_utils::extract_annotations;
406407

@@ -1124,15 +1125,26 @@ fn main() {
11241125
chaining_hints: true,
11251126
max_length: None,
11261127
},
1127-
r#"
1128+
&format!(
1129+
"{}\n{}\n",
1130+
r#"
11281131
//- /main.rs crate:main deps:std
11291132
use std::{Option::{self, Some, None}, iter};
11301133
1134+
struct MyIter;
1135+
1136+
impl iter::Iterator for MyIter {
1137+
type Item = ();
1138+
fn next(&mut self) -> Option<Self::Item> {
1139+
None
1140+
}
1141+
}
1142+
11311143
fn main() {
1144+
let _x = MyIter;
1145+
//^^ MyIter
11321146
let _x = iter::repeat(0);
11331147
//^^ impl Iterator<Item = i32>
1134-
let _y = iter::Chain(iter::repeat(0), iter::repeat(0));
1135-
//^^ impl Iterator<Item = i32>
11361148
fn generic<T: Clone>(t: T) {
11371149
let _x = iter::repeat(t);
11381150
//^^ impl Iterator<Item = T>
@@ -1141,42 +1153,9 @@ fn main() {
11411153
11421154
//- /std.rs crate:std deps:core
11431155
use core::*;
1144-
1145-
//- /core.rs crate:core
1146-
pub enum Option<T> {
1147-
Some(T),
1148-
None
1149-
}
1150-
1151-
pub mod iter {
1152-
pub use self::traits::iterator::Iterator;
1153-
pub mod traits { pub mod iterator {
1154-
pub trait Iterator {
1155-
type Item;
1156-
}
1157-
} }
1158-
1159-
pub use self::sources::*;
1160-
pub mod sources {
1161-
use super::Iterator;
1162-
pub struct Repeat<T: Clone>(pub T);
1163-
1164-
pub fn repeat<T: Clone>(t: T) -> Repeat<T> {
1165-
Repeat(f)
1166-
}
1167-
1168-
impl<T: Clone> Iterator for Repeat<T> {
1169-
type Item = T;
1170-
}
1171-
1172-
pub struct Chain<A, B>(pub A, pub B);
1173-
1174-
impl<T, A, B> Iterator for Chain<A, B> where A: Iterator<Item = T>, B: Iterator<Item = T> {
1175-
type Item = T;
1176-
}
1177-
}
1178-
}
11791156
"#,
1157+
FamousDefs::FIXTURE
1158+
),
11801159
);
11811160
}
11821161
}

0 commit comments

Comments
 (0)