aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
authorIgor Aleksanov <[email protected]>2020-09-13 18:24:04 +0100
committerIgor Aleksanov <[email protected]>2020-10-03 06:30:25 +0100
commit8ca214fbfbd2058140764bf12005a9281a121601 (patch)
tree4da7bda151a3c88013140b1942a22f892cc7bb21 /crates/ide
parent03dcf5111ad23700335d25ef02749666bbd08cca (diff)
Better inlay hints in 'for' loops
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/inlay_hints.rs51
1 files changed, 49 insertions, 2 deletions
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 0afe5f8fd..60dc74d41 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -189,7 +189,7 @@ fn get_bind_pat_hints(
189 189
190 let ty = sema.type_of_pat(&pat.clone().into())?; 190 let ty = sema.type_of_pat(&pat.clone().into())?;
191 191
192 if should_not_display_type_hint(sema.db, &pat, &ty) { 192 if should_not_display_type_hint(sema, &pat, &ty) {
193 return None; 193 return None;
194 } 194 }
195 195
@@ -215,10 +215,12 @@ fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &Typ
215} 215}
216 216
217fn should_not_display_type_hint( 217fn should_not_display_type_hint(
218 db: &RootDatabase, 218 sema: &Semantics<RootDatabase>,
219 bind_pat: &ast::IdentPat, 219 bind_pat: &ast::IdentPat,
220 pat_ty: &Type, 220 pat_ty: &Type,
221) -> bool { 221) -> bool {
222 let db = sema.db;
223
222 if pat_ty.is_unknown() { 224 if pat_ty.is_unknown() {
223 return true; 225 return true;
224 } 226 }
@@ -249,6 +251,14 @@ fn should_not_display_type_hint(
249 return it.condition().and_then(|condition| condition.pat()).is_some() 251 return it.condition().and_then(|condition| condition.pat()).is_some()
250 && pat_is_enum_variant(db, bind_pat, pat_ty); 252 && pat_is_enum_variant(db, bind_pat, pat_ty);
251 }, 253 },
254 ast::ForExpr(it) => {
255 // We *should* display hint only if user provided "in {expr}" and we know the type of expr (and it's not unit).
256 // Type of expr should be iterable.
257 let type_is_known = |ty: Option<hir::Type>| ty.map(|ty| !ty.is_unit() && !ty.is_unknown()).unwrap_or(false);
258 let should_display = it.in_token().is_some()
259 && it.iterable().map(|expr| type_is_known(sema.type_of_expr(&expr))).unwrap_or(false);
260 return !should_display;
261 },
252 _ => (), 262 _ => (),
253 } 263 }
254 } 264 }
@@ -924,4 +934,41 @@ fn main() {
924 "#]], 934 "#]],
925 ); 935 );
926 } 936 }
937
938 #[test]
939 fn incomplete_for_no_hint() {
940 check(
941 r#"
942fn main() {
943 let data = &[1i32, 2, 3];
944 //^^^^ &[i32; _]
945 for i
946}"#,
947 );
948 check(
949 r#"
950fn main() {
951 let data = &[1i32, 2, 3];
952 //^^^^ &[i32; _]
953 for i in
954
955 println!("Unit expr");
956}"#,
957 );
958 }
959
960 #[test]
961 fn complete_for_hint() {
962 check(
963 r#"
964fn main() {
965 let data = &[ 1, 2, 3 ];
966 //^^^^ &[i32; _]
967 for i in data.into_iter() {
968 //^ &i32
969 println!("{}", i);
970 }
971}"#,
972 );
973 }
927} 974}