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 } ;
2
3
use ide_db:: RootDatabase ;
3
4
use stdx:: to_lower_snake_case;
4
5
use syntax:: {
@@ -194,7 +195,7 @@ fn get_bind_pat_hints(
194
195
}
195
196
196
197
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 ( ) ) {
198
199
acc. push ( hint) ;
199
200
} else {
200
201
acc. push ( InlayHint {
@@ -209,45 +210,44 @@ fn get_bind_pat_hints(
209
210
210
211
/// Checks if the type is an Iterator from std::iter and replaces its hint with an `impl Iterator<Item = Ty>`.
211
212
fn hint_iterator (
212
- db : & RootDatabase ,
213
+ sema : & Semantics < RootDatabase > ,
213
214
config : & InlayHintsConfig ,
214
215
ty : & Type ,
215
216
pat : ast:: IdentPat ,
216
217
) -> Option < InlayHint > {
218
+ let db = sema. db ;
217
219
let strukt = ty. as_adt ( ) ?;
218
220
let krate = strukt. krate ( db) ?;
219
- let module = strukt. module ( db) ;
220
221
if krate. declaration_name ( db) . as_deref ( ) != Some ( "core" ) {
221
222
return None ;
222
223
}
223
- let module = module
224
+ // assert this type comes from `core::iter`
225
+ strukt
226
+ . module ( db)
224
227
. path_to_root ( db)
225
228
. into_iter ( )
226
229
. rev ( )
227
230
. 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 ( ) ?;
234
232
if ty. impls_trait ( db, iter_trait, & [ ] ) {
235
233
let assoc_type_item = iter_trait. items ( db) . into_iter ( ) . find_map ( |item| match item {
236
234
AssocItem :: TypeAlias ( alias) if alias. name ( db) == known:: Item => Some ( alias) ,
237
235
_ => None ,
238
236
} ) ?;
239
237
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
+ ) ;
240
247
return Some ( InlayHint {
241
248
range : pat. syntax ( ) . text_range ( ) ,
242
249
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 ( ) ,
251
251
} ) ;
252
252
}
253
253
}
@@ -401,6 +401,7 @@ fn get_callable(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<Call
401
401
402
402
#[ cfg( test) ]
403
403
mod tests {
404
+ use assists:: utils:: FamousDefs ;
404
405
use expect_test:: { expect, Expect } ;
405
406
use test_utils:: extract_annotations;
406
407
@@ -1124,15 +1125,26 @@ fn main() {
1124
1125
chaining_hints : true ,
1125
1126
max_length : None ,
1126
1127
} ,
1127
- r#"
1128
+ & format ! (
1129
+ "{}\n {}\n " ,
1130
+ r#"
1128
1131
//- /main.rs crate:main deps:std
1129
1132
use std::{Option::{self, Some, None}, iter};
1130
1133
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
+
1131
1143
fn main() {
1144
+ let _x = MyIter;
1145
+ //^^ MyIter
1132
1146
let _x = iter::repeat(0);
1133
1147
//^^ impl Iterator<Item = i32>
1134
- let _y = iter::Chain(iter::repeat(0), iter::repeat(0));
1135
- //^^ impl Iterator<Item = i32>
1136
1148
fn generic<T: Clone>(t: T) {
1137
1149
let _x = iter::repeat(t);
1138
1150
//^^ impl Iterator<Item = T>
@@ -1141,42 +1153,9 @@ fn main() {
1141
1153
1142
1154
//- /std.rs crate:std deps:core
1143
1155
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
- }
1179
1156
"# ,
1157
+ FamousDefs :: FIXTURE
1158
+ ) ,
1180
1159
) ;
1181
1160
}
1182
1161
}
0 commit comments