aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/inlay_hints.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/inlay_hints.rs')
-rw-r--r--crates/ra_ide/src/inlay_hints.rs101
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::{
11use crate::{FileId, FunctionSignature}; 11use crate::{FileId, FunctionSignature};
12 12
13#[derive(Clone, Debug, PartialEq, Eq)] 13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct InlayHintsOptions { 14pub 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
21impl Default for InlayHintsOptions { 21impl 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 {
41pub(crate) fn inlay_hints( 41pub(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(
68fn get_chaining_hints( 68fn 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(
108fn get_param_name_hints( 118fn 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(
148fn get_bind_pat_hints( 158fn 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)]
272mod tests { 282mod 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),