diff options
Diffstat (limited to 'crates/ra_ide/src/inlay_hints.rs')
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 101 |
1 files changed, 57 insertions, 44 deletions
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index f4f0751c0..4b133b19b 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -11,14 +11,14 @@ use ra_syntax::{ | |||
11 | use crate::{FileId, FunctionSignature}; | 11 | use crate::{FileId, FunctionSignature}; |
12 | 12 | ||
13 | #[derive(Clone, Debug, PartialEq, Eq)] | 13 | #[derive(Clone, Debug, PartialEq, Eq)] |
14 | pub struct InlayHintsOptions { | 14 | pub struct InlayHintsConfig { |
15 | pub type_hints: bool, | 15 | pub type_hints: bool, |
16 | pub parameter_hints: bool, | 16 | pub parameter_hints: bool, |
17 | pub chaining_hints: bool, | 17 | pub chaining_hints: bool, |
18 | pub max_length: Option<usize>, | 18 | pub max_length: Option<usize>, |
19 | } | 19 | } |
20 | 20 | ||
21 | impl Default for InlayHintsOptions { | 21 | impl Default for InlayHintsConfig { |
22 | fn default() -> Self { | 22 | fn default() -> Self { |
23 | Self { type_hints: true, parameter_hints: true, chaining_hints: true, max_length: None } | 23 | Self { type_hints: true, parameter_hints: true, chaining_hints: true, max_length: None } |
24 | } | 24 | } |
@@ -41,7 +41,7 @@ pub struct InlayHint { | |||
41 | pub(crate) fn inlay_hints( | 41 | pub(crate) fn inlay_hints( |
42 | db: &RootDatabase, | 42 | db: &RootDatabase, |
43 | file_id: FileId, | 43 | file_id: FileId, |
44 | options: &InlayHintsOptions, | 44 | config: &InlayHintsConfig, |
45 | ) -> Vec<InlayHint> { | 45 | ) -> Vec<InlayHint> { |
46 | let _p = profile("inlay_hints"); | 46 | let _p = profile("inlay_hints"); |
47 | let sema = Semantics::new(db); | 47 | let sema = Semantics::new(db); |
@@ -50,14 +50,14 @@ pub(crate) fn inlay_hints( | |||
50 | let mut res = Vec::new(); | 50 | let mut res = Vec::new(); |
51 | for node in file.syntax().descendants() { | 51 | for node in file.syntax().descendants() { |
52 | if let Some(expr) = ast::Expr::cast(node.clone()) { | 52 | if let Some(expr) = ast::Expr::cast(node.clone()) { |
53 | get_chaining_hints(&mut res, &sema, options, expr); | 53 | get_chaining_hints(&mut res, &sema, config, expr); |
54 | } | 54 | } |
55 | 55 | ||
56 | match_ast! { | 56 | match_ast! { |
57 | match node { | 57 | match node { |
58 | ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, options, ast::Expr::from(it)); }, | 58 | ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, config, ast::Expr::from(it)); }, |
59 | ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, options, ast::Expr::from(it)); }, | 59 | ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, config, ast::Expr::from(it)); }, |
60 | ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, options, it); }, | 60 | ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, config, it); }, |
61 | _ => (), | 61 | _ => (), |
62 | } | 62 | } |
63 | } | 63 | } |
@@ -68,15 +68,14 @@ pub(crate) fn inlay_hints( | |||
68 | fn get_chaining_hints( | 68 | fn get_chaining_hints( |
69 | acc: &mut Vec<InlayHint>, | 69 | acc: &mut Vec<InlayHint>, |
70 | sema: &Semantics<RootDatabase>, | 70 | sema: &Semantics<RootDatabase>, |
71 | options: &InlayHintsOptions, | 71 | config: &InlayHintsConfig, |
72 | expr: ast::Expr, | 72 | expr: ast::Expr, |
73 | ) -> Option<()> { | 73 | ) -> Option<()> { |
74 | if !options.chaining_hints { | 74 | if !config.chaining_hints { |
75 | return None; | 75 | return None; |
76 | } | 76 | } |
77 | 77 | ||
78 | let ty = sema.type_of_expr(&expr)?; | 78 | if matches!(expr, ast::Expr::RecordLit(_)) { |
79 | if ty.is_unknown() { | ||
80 | return None; | 79 | return None; |
81 | } | 80 | } |
82 | 81 | ||
@@ -95,7 +94,18 @@ fn get_chaining_hints( | |||
95 | let next = tokens.next()?.kind(); | 94 | let next = tokens.next()?.kind(); |
96 | let next_next = tokens.next()?.kind(); | 95 | let next_next = tokens.next()?.kind(); |
97 | if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT { | 96 | if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT { |
98 | let label = ty.display_truncated(sema.db, options.max_length).to_string(); | 97 | let ty = sema.type_of_expr(&expr)?; |
98 | if ty.is_unknown() { | ||
99 | return None; | ||
100 | } | ||
101 | if matches!(expr, ast::Expr::PathExpr(_)) { | ||
102 | if let Some(Adt::Struct(st)) = ty.as_adt() { | ||
103 | if st.fields(sema.db).is_empty() { | ||
104 | return None; | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | let label = ty.display_truncated(sema.db, config.max_length).to_string(); | ||
99 | acc.push(InlayHint { | 109 | acc.push(InlayHint { |
100 | range: expr.syntax().text_range(), | 110 | range: expr.syntax().text_range(), |
101 | kind: InlayKind::ChainingHint, | 111 | kind: InlayKind::ChainingHint, |
@@ -108,10 +118,10 @@ fn get_chaining_hints( | |||
108 | fn get_param_name_hints( | 118 | fn get_param_name_hints( |
109 | acc: &mut Vec<InlayHint>, | 119 | acc: &mut Vec<InlayHint>, |
110 | sema: &Semantics<RootDatabase>, | 120 | sema: &Semantics<RootDatabase>, |
111 | options: &InlayHintsOptions, | 121 | config: &InlayHintsConfig, |
112 | expr: ast::Expr, | 122 | expr: ast::Expr, |
113 | ) -> Option<()> { | 123 | ) -> Option<()> { |
114 | if !options.parameter_hints { | 124 | if !config.parameter_hints { |
115 | return None; | 125 | return None; |
116 | } | 126 | } |
117 | 127 | ||
@@ -148,10 +158,10 @@ fn get_param_name_hints( | |||
148 | fn get_bind_pat_hints( | 158 | fn get_bind_pat_hints( |
149 | acc: &mut Vec<InlayHint>, | 159 | acc: &mut Vec<InlayHint>, |
150 | sema: &Semantics<RootDatabase>, | 160 | sema: &Semantics<RootDatabase>, |
151 | options: &InlayHintsOptions, | 161 | config: &InlayHintsConfig, |
152 | pat: ast::BindPat, | 162 | pat: ast::BindPat, |
153 | ) -> Option<()> { | 163 | ) -> Option<()> { |
154 | if !options.type_hints { | 164 | if !config.type_hints { |
155 | return None; | 165 | return None; |
156 | } | 166 | } |
157 | 167 | ||
@@ -164,7 +174,7 @@ fn get_bind_pat_hints( | |||
164 | acc.push(InlayHint { | 174 | acc.push(InlayHint { |
165 | range: pat.syntax().text_range(), | 175 | range: pat.syntax().text_range(), |
166 | kind: InlayKind::TypeHint, | 176 | kind: InlayKind::TypeHint, |
167 | label: ty.display_truncated(sema.db, options.max_length).to_string().into(), | 177 | label: ty.display_truncated(sema.db, config.max_length).to_string().into(), |
168 | }); | 178 | }); |
169 | Some(()) | 179 | Some(()) |
170 | } | 180 | } |
@@ -270,7 +280,7 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option< | |||
270 | 280 | ||
271 | #[cfg(test)] | 281 | #[cfg(test)] |
272 | mod tests { | 282 | mod tests { |
273 | use crate::inlay_hints::InlayHintsOptions; | 283 | use crate::inlay_hints::InlayHintsConfig; |
274 | use insta::assert_debug_snapshot; | 284 | use insta::assert_debug_snapshot; |
275 | 285 | ||
276 | use crate::mock_analysis::single_file; | 286 | use crate::mock_analysis::single_file; |
@@ -284,7 +294,7 @@ mod tests { | |||
284 | let _x = foo(4, 4); | 294 | let _x = foo(4, 4); |
285 | }"#, | 295 | }"#, |
286 | ); | 296 | ); |
287 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: true, type_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###" | 297 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: true, type_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###" |
288 | [ | 298 | [ |
289 | InlayHint { | 299 | InlayHint { |
290 | range: [106; 107), | 300 | range: [106; 107), |
@@ -308,7 +318,7 @@ mod tests { | |||
308 | let _x = foo(4, 4); | 318 | let _x = foo(4, 4); |
309 | }"#, | 319 | }"#, |
310 | ); | 320 | ); |
311 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ type_hints: false, parameter_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###"[]"###); | 321 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ type_hints: false, parameter_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###"[]"###); |
312 | } | 322 | } |
313 | 323 | ||
314 | #[test] | 324 | #[test] |
@@ -320,7 +330,7 @@ mod tests { | |||
320 | let _x = foo(4, 4); | 330 | let _x = foo(4, 4); |
321 | }"#, | 331 | }"#, |
322 | ); | 332 | ); |
323 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ type_hints: true, parameter_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###" | 333 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ type_hints: true, parameter_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###" |
324 | [ | 334 | [ |
325 | InlayHint { | 335 | InlayHint { |
326 | range: [97; 99), | 336 | range: [97; 99), |
@@ -344,7 +354,7 @@ fn main() { | |||
344 | }"#, | 354 | }"#, |
345 | ); | 355 | ); |
346 | 356 | ||
347 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###" | 357 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###" |
348 | [ | 358 | [ |
349 | InlayHint { | 359 | InlayHint { |
350 | range: [69; 71), | 360 | range: [69; 71), |
@@ -401,7 +411,7 @@ fn main() { | |||
401 | }"#, | 411 | }"#, |
402 | ); | 412 | ); |
403 | 413 | ||
404 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###" | 414 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###" |
405 | [ | 415 | [ |
406 | InlayHint { | 416 | InlayHint { |
407 | range: [193; 197), | 417 | range: [193; 197), |
@@ -481,7 +491,7 @@ fn main() { | |||
481 | }"#, | 491 | }"#, |
482 | ); | 492 | ); |
483 | 493 | ||
484 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###" | 494 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###" |
485 | [ | 495 | [ |
486 | InlayHint { | 496 | InlayHint { |
487 | range: [21; 30), | 497 | range: [21; 30), |
@@ -545,7 +555,7 @@ fn main() { | |||
545 | }"#, | 555 | }"#, |
546 | ); | 556 | ); |
547 | 557 | ||
548 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###" | 558 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###" |
549 | [ | 559 | [ |
550 | InlayHint { | 560 | InlayHint { |
551 | range: [21; 30), | 561 | range: [21; 30), |
@@ -595,7 +605,7 @@ fn main() { | |||
595 | }"#, | 605 | }"#, |
596 | ); | 606 | ); |
597 | 607 | ||
598 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###" | 608 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###" |
599 | [ | 609 | [ |
600 | InlayHint { | 610 | InlayHint { |
601 | range: [188; 192), | 611 | range: [188; 192), |
@@ -690,7 +700,7 @@ fn main() { | |||
690 | }"#, | 700 | }"#, |
691 | ); | 701 | ); |
692 | 702 | ||
693 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###" | 703 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###" |
694 | [ | 704 | [ |
695 | InlayHint { | 705 | InlayHint { |
696 | range: [188; 192), | 706 | range: [188; 192), |
@@ -785,7 +795,7 @@ fn main() { | |||
785 | }"#, | 795 | }"#, |
786 | ); | 796 | ); |
787 | 797 | ||
788 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###" | 798 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###" |
789 | [ | 799 | [ |
790 | InlayHint { | 800 | InlayHint { |
791 | range: [252; 256), | 801 | range: [252; 256), |
@@ -857,7 +867,7 @@ fn main() { | |||
857 | }"#, | 867 | }"#, |
858 | ); | 868 | ); |
859 | 869 | ||
860 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions { max_length: Some(8), ..Default::default() }).unwrap(), @r###" | 870 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###" |
861 | [ | 871 | [ |
862 | InlayHint { | 872 | InlayHint { |
863 | range: [74; 75), | 873 | range: [74; 75), |
@@ -945,7 +955,7 @@ fn main() { | |||
945 | }"#, | 955 | }"#, |
946 | ); | 956 | ); |
947 | 957 | ||
948 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###" | 958 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###" |
949 | [ | 959 | [ |
950 | InlayHint { | 960 | InlayHint { |
951 | range: [798; 809), | 961 | range: [798; 809), |
@@ -1067,7 +1077,7 @@ fn main() { | |||
1067 | }"#, | 1077 | }"#, |
1068 | ); | 1078 | ); |
1069 | 1079 | ||
1070 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions { max_length: Some(8), ..Default::default() }).unwrap(), @r###" | 1080 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###" |
1071 | [] | 1081 | [] |
1072 | "### | 1082 | "### |
1073 | ); | 1083 | ); |
@@ -1093,7 +1103,7 @@ fn main() { | |||
1093 | }"#, | 1103 | }"#, |
1094 | ); | 1104 | ); |
1095 | 1105 | ||
1096 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions { max_length: Some(8), ..Default::default() }).unwrap(), @r###" | 1106 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###" |
1097 | [] | 1107 | [] |
1098 | "### | 1108 | "### |
1099 | ); | 1109 | ); |
@@ -1115,7 +1125,7 @@ fn main() { | |||
1115 | .into_c(); | 1125 | .into_c(); |
1116 | }"#, | 1126 | }"#, |
1117 | ); | 1127 | ); |
1118 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" | 1128 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" |
1119 | [ | 1129 | [ |
1120 | InlayHint { | 1130 | InlayHint { |
1121 | range: [232; 269), | 1131 | range: [232; 269), |
@@ -1144,7 +1154,7 @@ fn main() { | |||
1144 | let c = A(B(C)).into_b().into_c(); | 1154 | let c = A(B(C)).into_b().into_c(); |
1145 | }"#, | 1155 | }"#, |
1146 | ); | 1156 | ); |
1147 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###"[]"###); | 1157 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###"[]"###); |
1148 | } | 1158 | } |
1149 | 1159 | ||
1150 | #[test] | 1160 | #[test] |
@@ -1154,32 +1164,35 @@ fn main() { | |||
1154 | struct A { pub b: B } | 1164 | struct A { pub b: B } |
1155 | struct B { pub c: C } | 1165 | struct B { pub c: C } |
1156 | struct C(pub bool); | 1166 | struct C(pub bool); |
1167 | struct D; | ||
1168 | |||
1169 | impl D { | ||
1170 | fn foo(&self) -> i32 { 42 } | ||
1171 | } | ||
1157 | 1172 | ||
1158 | fn main() { | 1173 | fn main() { |
1159 | let x = A { b: B { c: C(true) } } | 1174 | let x = A { b: B { c: C(true) } } |
1160 | .b | 1175 | .b |
1161 | .c | 1176 | .c |
1162 | .0; | 1177 | .0; |
1178 | let x = D | ||
1179 | .foo(); | ||
1163 | }"#, | 1180 | }"#, |
1164 | ); | 1181 | ); |
1165 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" | 1182 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" |
1166 | [ | 1183 | [ |
1167 | InlayHint { | 1184 | InlayHint { |
1168 | range: [150; 221), | 1185 | range: [252; 323), |
1169 | kind: ChainingHint, | 1186 | kind: ChainingHint, |
1170 | label: "C", | 1187 | label: "C", |
1171 | }, | 1188 | }, |
1172 | InlayHint { | 1189 | InlayHint { |
1173 | range: [150; 198), | 1190 | range: [252; 300), |
1174 | kind: ChainingHint, | 1191 | kind: ChainingHint, |
1175 | label: "B", | 1192 | label: "B", |
1176 | }, | 1193 | }, |
1177 | InlayHint { | 1194 | ] |
1178 | range: [150; 175), | 1195 | "###); |
1179 | kind: ChainingHint, | ||
1180 | label: "A", | ||
1181 | }, | ||
1182 | ]"###); | ||
1183 | } | 1196 | } |
1184 | 1197 | ||
1185 | #[test] | 1198 | #[test] |
@@ -1204,7 +1217,7 @@ fn main() { | |||
1204 | .into_c(); | 1217 | .into_c(); |
1205 | }"#, | 1218 | }"#, |
1206 | ); | 1219 | ); |
1207 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" | 1220 | assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" |
1208 | [ | 1221 | [ |
1209 | InlayHint { | 1222 | InlayHint { |
1210 | range: [403; 452), | 1223 | range: [403; 452), |