aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/completion/complete_postfix/format_like.rs2
-rw-r--r--crates/ide/src/inlay_hints.rs132
2 files changed, 118 insertions, 16 deletions
diff --git a/crates/ide/src/completion/complete_postfix/format_like.rs b/crates/ide/src/completion/complete_postfix/format_like.rs
index 0287fc803..81c33bf3a 100644
--- a/crates/ide/src/completion/complete_postfix/format_like.rs
+++ b/crates/ide/src/completion/complete_postfix/format_like.rs
@@ -1,4 +1,4 @@
1// Feature: Postfix completion for `format`-like strings. 1// Feature: Format String Completion.
2// 2//
3// `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`. 3// `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`.
4// 4//
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 0afe5f8fd..1d7e8de56 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,15 @@ 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 return it.in_token().is_none() ||
258 it.iterable()
259 .and_then(|iterable_expr|sema.type_of_expr(&iterable_expr))
260 .map(|iterable_ty| iterable_ty.is_unknown() || iterable_ty.is_unit())
261 .unwrap_or(true)
262 },
252 _ => (), 263 _ => (),
253 } 264 }
254 } 265 }
@@ -496,19 +507,6 @@ fn main() {
496 } 507 }
497 508
498 #[test] 509 #[test]
499 fn for_expression() {
500 check(
501 r#"
502fn main() {
503 let mut start = 0;
504 //^^^^^^^^^ i32
505 for increment in 0..2 { start += increment; }
506 //^^^^^^^^^ i32
507}"#,
508 );
509 }
510
511 #[test]
512 fn if_expr() { 510 fn if_expr() {
513 check( 511 check(
514 r#" 512 r#"
@@ -924,4 +922,108 @@ fn main() {
924 "#]], 922 "#]],
925 ); 923 );
926 } 924 }
925
926 #[test]
927 fn incomplete_for_no_hint() {
928 check(
929 r#"
930fn main() {
931 let data = &[1i32, 2, 3];
932 //^^^^ &[i32; _]
933 for i
934}"#,
935 );
936 check(
937 r#"
938//- /main.rs crate:main deps:core
939pub struct Vec<T> {}
940
941impl<T> Vec<T> {
942 pub fn new() -> Self { Vec {} }
943 pub fn push(&mut self, t: T) {}
944}
945
946impl<T> IntoIterator for Vec<T> {
947 type Item=T;
948}
949
950fn main() {
951 let mut data = Vec::new();
952 //^^^^^^^^ Vec<&str>
953 data.push("foo");
954 for i in
955
956 println!("Unit expr");
957}
958
959//- /core.rs crate:core
960#[prelude_import] use iter::*;
961mod iter {
962 trait IntoIterator {
963 type Item;
964 }
965}
966//- /alloc.rs crate:alloc deps:core
967mod collections {
968 struct Vec<T> {}
969 impl<T> Vec<T> {
970 fn new() -> Self { Vec {} }
971 fn push(&mut self, t: T) { }
972 }
973 impl<T> IntoIterator for Vec<T> {
974 type Item=T;
975 }
976}
977"#,
978 );
979 }
980
981 #[test]
982 fn complete_for_hint() {
983 check(
984 r#"
985//- /main.rs crate:main deps:core
986pub struct Vec<T> {}
987
988impl<T> Vec<T> {
989 pub fn new() -> Self { Vec {} }
990 pub fn push(&mut self, t: T) {}
991}
992
993impl<T> IntoIterator for Vec<T> {
994 type Item=T;
995}
996
997fn main() {
998 let mut data = Vec::new();
999 //^^^^^^^^ Vec<&str>
1000 data.push("foo");
1001 for i in data {
1002 //^ &str
1003 let z = i;
1004 //^ &str
1005 }
1006}
1007
1008//- /core.rs crate:core
1009#[prelude_import] use iter::*;
1010mod iter {
1011 trait IntoIterator {
1012 type Item;
1013 }
1014}
1015//- /alloc.rs crate:alloc deps:core
1016mod collections {
1017 struct Vec<T> {}
1018 impl<T> Vec<T> {
1019 fn new() -> Self { Vec {} }
1020 fn push(&mut self, t: T) { }
1021 }
1022 impl<T> IntoIterator for Vec<T> {
1023 type Item=T;
1024 }
1025}
1026"#,
1027 );
1028 }
927} 1029}