aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/call_info.rs14
-rw-r--r--crates/ra_ide/src/completion.rs4
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs70
-rw-r--r--crates/ra_ide/src/completion/complete_scope.rs36
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs3
-rw-r--r--crates/ra_ide/src/completion/presentation.rs13
-rw-r--r--crates/ra_ide/src/display/function_signature.rs4
-rw-r--r--crates/ra_ide/src/hover.rs27
-rw-r--r--crates/ra_ide/src/inlay_hints.rs113
-rw-r--r--crates/ra_ide/src/lib.rs6
-rw-r--r--crates/ra_ide/src/syntax_tree.rs16
11 files changed, 267 insertions, 39 deletions
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs
index 2b35a3803..39d09a07f 100644
--- a/crates/ra_ide/src/call_info.rs
+++ b/crates/ra_ide/src/call_info.rs
@@ -544,6 +544,20 @@ fn main() {
544 } 544 }
545 545
546 #[test] 546 #[test]
547 fn generic_struct() {
548 let info = call_info(
549 r#"
550struct TS<T>(T);
551fn main() {
552 let s = TS(<|>);
553}"#,
554 );
555
556 assert_eq!(info.label(), "struct TS<T>(T) -> TS");
557 assert_eq!(info.active_parameter, Some(0));
558 }
559
560 #[test]
547 #[should_panic] 561 #[should_panic]
548 fn cant_call_named_structs() { 562 fn cant_call_named_structs() {
549 let _ = call_info( 563 let _ = call_info(
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs
index 93e53c921..cd0757be5 100644
--- a/crates/ra_ide/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
@@ -75,9 +75,9 @@ impl Default for CompletionOptions {
75pub(crate) fn completions( 75pub(crate) fn completions(
76 db: &RootDatabase, 76 db: &RootDatabase,
77 position: FilePosition, 77 position: FilePosition,
78 opts: &CompletionOptions, 78 options: &CompletionOptions,
79) -> Option<Completions> { 79) -> Option<Completions> {
80 let ctx = CompletionContext::new(db, position, opts)?; 80 let ctx = CompletionContext::new(db, position, options)?;
81 81
82 let mut acc = Completions::default(); 82 let mut acc = Completions::default();
83 83
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index d588ee364..3db17f15f 100644
--- a/crates/ra_ide/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -967,4 +967,74 @@ mod tests {
967 ] 967 ]
968 "###); 968 "###);
969 } 969 }
970
971 #[test]
972 fn function_mod_share_name() {
973 assert_debug_snapshot!(
974 do_reference_completion(
975 r"
976 fn foo() {
977 self::m::<|>
978 }
979
980 mod m {
981 pub mod z {}
982 pub fn z() {}
983 }
984 ",
985 ),
986 @r###"
987 [
988 CompletionItem {
989 label: "z",
990 source_range: [57; 57),
991 delete: [57; 57),
992 insert: "z",
993 kind: Module,
994 },
995 CompletionItem {
996 label: "z()",
997 source_range: [57; 57),
998 delete: [57; 57),
999 insert: "z()$0",
1000 kind: Function,
1001 lookup: "z",
1002 detail: "pub fn z()",
1003 },
1004 ]
1005 "###
1006 );
1007 }
1008
1009 #[test]
1010 fn completes_hashmap_new() {
1011 assert_debug_snapshot!(
1012 do_reference_completion(
1013 r"
1014 struct RandomState;
1015 struct HashMap<K, V, S = RandomState> {}
1016
1017 impl<K, V> HashMap<K, V, RandomState> {
1018 pub fn new() -> HashMap<K, V, RandomState> { }
1019 }
1020 fn foo() {
1021 HashMap::<|>
1022 }
1023 "
1024 ),
1025 @r###"
1026 [
1027 CompletionItem {
1028 label: "new()",
1029 source_range: [292; 292),
1030 delete: [292; 292),
1031 insert: "new()$0",
1032 kind: Function,
1033 lookup: "new",
1034 detail: "pub fn new() -> HashMap<K, V, RandomState>",
1035 },
1036 ]
1037 "###
1038 );
1039 }
970} 1040}
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs
index bd4adf23a..5ffff5a1c 100644
--- a/crates/ra_ide/src/completion/complete_scope.rs
+++ b/crates/ra_ide/src/completion/complete_scope.rs
@@ -42,6 +42,7 @@ mod tests {
42 kind: Function, 42 kind: Function,
43 lookup: "quux", 43 lookup: "quux",
44 detail: "fn quux(x: i32)", 44 detail: "fn quux(x: i32)",
45 trigger_call_info: true,
45 }, 46 },
46 CompletionItem { 47 CompletionItem {
47 label: "x", 48 label: "x",
@@ -844,6 +845,7 @@ mod tests {
844 kind: Function, 845 kind: Function,
845 lookup: "quux", 846 lookup: "quux",
846 detail: "fn quux(x: i32)", 847 detail: "fn quux(x: i32)",
848 trigger_call_info: true,
847 }, 849 },
848 CompletionItem { 850 CompletionItem {
849 label: "x", 851 label: "x",
@@ -865,4 +867,38 @@ mod tests {
865 "### 867 "###
866 ); 868 );
867 } 869 }
870
871 #[test]
872 fn completes_unresolved_uses() {
873 assert_debug_snapshot!(
874 do_reference_completion(
875 r"
876 use spam::Quux;
877
878 fn main() {
879 <|>
880 }
881 "
882 ),
883 @r###"
884 [
885 CompletionItem {
886 label: "Quux",
887 source_range: [82; 82),
888 delete: [82; 82),
889 insert: "Quux",
890 },
891 CompletionItem {
892 label: "main()",
893 source_range: [82; 82),
894 delete: [82; 82),
895 insert: "main()$0",
896 kind: Function,
897 lookup: "main",
898 detail: "fn main()",
899 },
900 ]
901 "###
902 );
903 }
868} 904}
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index ef0eb43b2..bc0f1aff5 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -80,6 +80,9 @@ impl fmt::Debug for CompletionItem {
80 if self.deprecated { 80 if self.deprecated {
81 s.field("deprecated", &true); 81 s.field("deprecated", &true);
82 } 82 }
83 if self.trigger_call_info {
84 s.field("trigger_call_info", &true);
85 }
83 s.finish() 86 s.finish()
84 } 87 }
85} 88}
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 5213def20..910844244 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -273,8 +273,10 @@ impl Completions {
273 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { 273 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) {
274 let is_deprecated = is_deprecated(variant, ctx.db); 274 let is_deprecated = is_deprecated(variant, ctx.db);
275 let name = variant.name(ctx.db); 275 let name = variant.name(ctx.db);
276 let detail_types = 276 let detail_types = variant
277 variant.fields(ctx.db).into_iter().map(|field| (field.name(ctx.db), field.ty(ctx.db))); 277 .fields(ctx.db)
278 .into_iter()
279 .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db)));
278 let detail = match variant.kind(ctx.db) { 280 let detail = match variant.kind(ctx.db) {
279 StructKind::Tuple | StructKind::Unit => { 281 StructKind::Tuple | StructKind::Unit => {
280 join(detail_types.map(|(_, t)| t.display(ctx.db).to_string())) 282 join(detail_types.map(|(_, t)| t.display(ctx.db).to_string()))
@@ -510,6 +512,7 @@ mod tests {
510 kind: Function, 512 kind: Function,
511 lookup: "with_args", 513 lookup: "with_args",
512 detail: "fn with_args(x: i32, y: String)", 514 detail: "fn with_args(x: i32, y: String)",
515 trigger_call_info: true,
513 }, 516 },
514 ] 517 ]
515 "### 518 "###
@@ -566,6 +569,7 @@ mod tests {
566 kind: Method, 569 kind: Method,
567 lookup: "foo", 570 lookup: "foo",
568 detail: "fn foo(&self, x: i32)", 571 detail: "fn foo(&self, x: i32)",
572 trigger_call_info: true,
569 }, 573 },
570 ] 574 ]
571 "### 575 "###
@@ -600,6 +604,7 @@ mod tests {
600 kind: Method, 604 kind: Method,
601 lookup: "foo", 605 lookup: "foo",
602 detail: "fn foo(&self, x: i32)", 606 detail: "fn foo(&self, x: i32)",
607 trigger_call_info: true,
603 }, 608 },
604 ] 609 ]
605 "### 610 "###
@@ -718,6 +723,7 @@ mod tests {
718 kind: Function, 723 kind: Function,
719 lookup: "foo", 724 lookup: "foo",
720 detail: "fn foo(xs: Ve)", 725 detail: "fn foo(xs: Ve)",
726 trigger_call_info: true,
721 }, 727 },
722 ] 728 ]
723 "### 729 "###
@@ -747,6 +753,7 @@ mod tests {
747 kind: Function, 753 kind: Function,
748 lookup: "foo", 754 lookup: "foo",
749 detail: "fn foo(xs: Ve)", 755 detail: "fn foo(xs: Ve)",
756 trigger_call_info: true,
750 }, 757 },
751 ] 758 ]
752 "### 759 "###
@@ -775,6 +782,7 @@ mod tests {
775 kind: Function, 782 kind: Function,
776 lookup: "foo", 783 lookup: "foo",
777 detail: "fn foo(xs: Ve)", 784 detail: "fn foo(xs: Ve)",
785 trigger_call_info: true,
778 }, 786 },
779 ] 787 ]
780 "### 788 "###
@@ -803,6 +811,7 @@ mod tests {
803 kind: Function, 811 kind: Function,
804 lookup: "foo", 812 lookup: "foo",
805 detail: "fn foo(xs: Ve<i128>)", 813 detail: "fn foo(xs: Ve<i128>)",
814 trigger_call_info: true,
806 }, 815 },
807 ] 816 ]
808 "### 817 "###
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs
index 2c4c932de..ec1bbd5a0 100644
--- a/crates/ra_ide/src/display/function_signature.rs
+++ b/crates/ra_ide/src/display/function_signature.rs
@@ -64,7 +64,7 @@ impl FunctionSignature {
64 .fields(db) 64 .fields(db)
65 .into_iter() 65 .into_iter()
66 .map(|field: hir::StructField| { 66 .map(|field: hir::StructField| {
67 let ty = field.ty(db); 67 let ty = field.signature_ty(db);
68 format!("{}", ty.display(db)) 68 format!("{}", ty.display(db))
69 }) 69 })
70 .collect(); 70 .collect();
@@ -102,7 +102,7 @@ impl FunctionSignature {
102 .into_iter() 102 .into_iter()
103 .map(|field: hir::StructField| { 103 .map(|field: hir::StructField| {
104 let name = field.name(db); 104 let name = field.name(db);
105 let ty = field.ty(db); 105 let ty = field.signature_ty(db);
106 format!("{}: {}", name, ty.display(db)) 106 format!("{}: {}", name, ty.display(db))
107 }) 107 })
108 .collect(); 108 .collect();
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 25e038a55..0bbba4855 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -833,19 +833,34 @@ fn func(foo: i32) { if true { <|>foo; }; }
833 } 833 }
834 834
835 #[test] 835 #[test]
836 fn test_hover_through_assert_macro() {
837 let hover_on = check_hover_result(
838 r#"
839 //- /lib.rs
840 #[rustc_builtin_macro]
841 macro_rules! assert {}
842
843 fn bar() -> bool { true }
844 fn foo() {
845 assert!(ba<|>r());
846 }
847 "#,
848 &["fn bar() -> bool"],
849 );
850
851 assert_eq!(hover_on, "bar");
852 }
853
854 #[test]
836 fn test_hover_through_literal_string_in_builtin_macro() { 855 fn test_hover_through_literal_string_in_builtin_macro() {
837 check_hover_no_result( 856 check_hover_no_result(
838 r#" 857 r#"
839 //- /lib.rs 858 //- /lib.rs
840 #[rustc_builtin_macro] 859 #[rustc_builtin_macro]
841 macro_rules! assert { 860 macro_rules! format {}
842 ($cond:expr) => {{ /* compiler built-in */ }};
843 ($cond:expr,) => {{ /* compiler built-in */ }};
844 ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
845 }
846 861
847 fn foo() { 862 fn foo() {
848 assert!("hel<|>lo"); 863 format!("hel<|>lo {}", 0);
849 } 864 }
850 "#, 865 "#,
851 ); 866 );
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index cf0cbdbd0..ecd615cf4 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -10,7 +10,20 @@ use ra_syntax::{
10 10
11use crate::{FileId, FunctionSignature}; 11use crate::{FileId, FunctionSignature};
12 12
13#[derive(Debug, PartialEq, Eq)] 13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct InlayHintsOptions {
15 pub type_hints: bool,
16 pub parameter_hints: bool,
17 pub max_length: Option<usize>,
18}
19
20impl Default for InlayHintsOptions {
21 fn default() -> Self {
22 Self { type_hints: true, parameter_hints: true, max_length: None }
23 }
24}
25
26#[derive(Clone, Debug, PartialEq, Eq)]
14pub enum InlayKind { 27pub enum InlayKind {
15 TypeHint, 28 TypeHint,
16 ParameterHint, 29 ParameterHint,
@@ -26,7 +39,7 @@ pub struct InlayHint {
26pub(crate) fn inlay_hints( 39pub(crate) fn inlay_hints(
27 db: &RootDatabase, 40 db: &RootDatabase,
28 file_id: FileId, 41 file_id: FileId,
29 max_inlay_hint_length: Option<usize>, 42 options: &InlayHintsOptions,
30) -> Vec<InlayHint> { 43) -> Vec<InlayHint> {
31 let _p = profile("inlay_hints"); 44 let _p = profile("inlay_hints");
32 let sema = Semantics::new(db); 45 let sema = Semantics::new(db);
@@ -36,9 +49,9 @@ pub(crate) fn inlay_hints(
36 for node in file.syntax().descendants() { 49 for node in file.syntax().descendants() {
37 match_ast! { 50 match_ast! {
38 match node { 51 match node {
39 ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, ast::Expr::from(it)); }, 52 ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, options, ast::Expr::from(it)); },
40 ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, ast::Expr::from(it)); }, 53 ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, options, ast::Expr::from(it)); },
41 ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, max_inlay_hint_length, it); }, 54 ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, options, it); },
42 _ => (), 55 _ => (),
43 } 56 }
44 } 57 }
@@ -49,8 +62,13 @@ pub(crate) fn inlay_hints(
49fn get_param_name_hints( 62fn get_param_name_hints(
50 acc: &mut Vec<InlayHint>, 63 acc: &mut Vec<InlayHint>,
51 sema: &Semantics<RootDatabase>, 64 sema: &Semantics<RootDatabase>,
65 options: &InlayHintsOptions,
52 expr: ast::Expr, 66 expr: ast::Expr,
53) -> Option<()> { 67) -> Option<()> {
68 if !options.parameter_hints {
69 return None;
70 }
71
54 let args = match &expr { 72 let args = match &expr {
55 ast::Expr::CallExpr(expr) => expr.arg_list()?.args(), 73 ast::Expr::CallExpr(expr) => expr.arg_list()?.args(),
56 ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(), 74 ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(),
@@ -84,9 +102,13 @@ fn get_param_name_hints(
84fn get_bind_pat_hints( 102fn get_bind_pat_hints(
85 acc: &mut Vec<InlayHint>, 103 acc: &mut Vec<InlayHint>,
86 sema: &Semantics<RootDatabase>, 104 sema: &Semantics<RootDatabase>,
87 max_inlay_hint_length: Option<usize>, 105 options: &InlayHintsOptions,
88 pat: ast::BindPat, 106 pat: ast::BindPat,
89) -> Option<()> { 107) -> Option<()> {
108 if !options.type_hints {
109 return None;
110 }
111
90 let ty = sema.type_of_pat(&pat.clone().into())?; 112 let ty = sema.type_of_pat(&pat.clone().into())?;
91 113
92 if should_not_display_type_hint(sema.db, &pat, &ty) { 114 if should_not_display_type_hint(sema.db, &pat, &ty) {
@@ -96,7 +118,7 @@ fn get_bind_pat_hints(
96 acc.push(InlayHint { 118 acc.push(InlayHint {
97 range: pat.syntax().text_range(), 119 range: pat.syntax().text_range(),
98 kind: InlayKind::TypeHint, 120 kind: InlayKind::TypeHint,
99 label: ty.display_truncated(sema.db, max_inlay_hint_length).to_string().into(), 121 label: ty.display_truncated(sema.db, options.max_length).to_string().into(),
100 }); 122 });
101 Some(()) 123 Some(())
102} 124}
@@ -202,11 +224,66 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<
202 224
203#[cfg(test)] 225#[cfg(test)]
204mod tests { 226mod tests {
227 use crate::inlay_hints::InlayHintsOptions;
205 use insta::assert_debug_snapshot; 228 use insta::assert_debug_snapshot;
206 229
207 use crate::mock_analysis::single_file; 230 use crate::mock_analysis::single_file;
208 231
209 #[test] 232 #[test]
233 fn param_hints_only() {
234 let (analysis, file_id) = single_file(
235 r#"
236 fn foo(a: i32, b: i32) -> i32 { a + b }
237 fn main() {
238 let _x = foo(4, 4);
239 }"#,
240 );
241 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: true, type_hints: false, max_length: None}).unwrap(), @r###"
242 [
243 InlayHint {
244 range: [106; 107),
245 kind: ParameterHint,
246 label: "a",
247 },
248 InlayHint {
249 range: [109; 110),
250 kind: ParameterHint,
251 label: "b",
252 },
253 ]"###);
254 }
255
256 #[test]
257 fn hints_disabled() {
258 let (analysis, file_id) = single_file(
259 r#"
260 fn foo(a: i32, b: i32) -> i32 { a + b }
261 fn main() {
262 let _x = foo(4, 4);
263 }"#,
264 );
265 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ type_hints: false, parameter_hints: false, max_length: None}).unwrap(), @r###"[]"###);
266 }
267
268 #[test]
269 fn type_hints_only() {
270 let (analysis, file_id) = single_file(
271 r#"
272 fn foo(a: i32, b: i32) -> i32 { a + b }
273 fn main() {
274 let _x = foo(4, 4);
275 }"#,
276 );
277 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ type_hints: true, parameter_hints: false, max_length: None}).unwrap(), @r###"
278 [
279 InlayHint {
280 range: [97; 99),
281 kind: TypeHint,
282 label: "i32",
283 },
284 ]"###);
285 }
286 #[test]
210 fn default_generic_types_should_not_be_displayed() { 287 fn default_generic_types_should_not_be_displayed() {
211 let (analysis, file_id) = single_file( 288 let (analysis, file_id) = single_file(
212 r#" 289 r#"
@@ -221,7 +298,7 @@ fn main() {
221}"#, 298}"#,
222 ); 299 );
223 300
224 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" 301 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###"
225 [ 302 [
226 InlayHint { 303 InlayHint {
227 range: [69; 71), 304 range: [69; 71),
@@ -278,7 +355,7 @@ fn main() {
278}"#, 355}"#,
279 ); 356 );
280 357
281 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" 358 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###"
282 [ 359 [
283 InlayHint { 360 InlayHint {
284 range: [193; 197), 361 range: [193; 197),
@@ -358,7 +435,7 @@ fn main() {
358}"#, 435}"#,
359 ); 436 );
360 437
361 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" 438 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###"
362 [ 439 [
363 InlayHint { 440 InlayHint {
364 range: [21; 30), 441 range: [21; 30),
@@ -422,7 +499,7 @@ fn main() {
422}"#, 499}"#,
423 ); 500 );
424 501
425 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" 502 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###"
426 [ 503 [
427 InlayHint { 504 InlayHint {
428 range: [21; 30), 505 range: [21; 30),
@@ -472,7 +549,7 @@ fn main() {
472}"#, 549}"#,
473 ); 550 );
474 551
475 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" 552 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###"
476 [ 553 [
477 InlayHint { 554 InlayHint {
478 range: [188; 192), 555 range: [188; 192),
@@ -567,7 +644,7 @@ fn main() {
567}"#, 644}"#,
568 ); 645 );
569 646
570 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" 647 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###"
571 [ 648 [
572 InlayHint { 649 InlayHint {
573 range: [188; 192), 650 range: [188; 192),
@@ -662,7 +739,7 @@ fn main() {
662}"#, 739}"#,
663 ); 740 );
664 741
665 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" 742 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###"
666 [ 743 [
667 InlayHint { 744 InlayHint {
668 range: [252; 256), 745 range: [252; 256),
@@ -734,7 +811,7 @@ fn main() {
734}"#, 811}"#,
735 ); 812 );
736 813
737 assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###" 814 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
738 [ 815 [
739 InlayHint { 816 InlayHint {
740 range: [74; 75), 817 range: [74; 75),
@@ -822,7 +899,7 @@ fn main() {
822}"#, 899}"#,
823 ); 900 );
824 901
825 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" 902 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions::default()).unwrap(), @r###"
826 [ 903 [
827 InlayHint { 904 InlayHint {
828 range: [798; 809), 905 range: [798; 809),
@@ -944,7 +1021,7 @@ fn main() {
944}"#, 1021}"#,
945 ); 1022 );
946 1023
947 assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###" 1024 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
948 [] 1025 []
949 "### 1026 "###
950 ); 1027 );
@@ -970,7 +1047,7 @@ fn main() {
970}"#, 1047}"#,
971 ); 1048 );
972 1049
973 assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###" 1050 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
974 [] 1051 []
975 "### 1052 "###
976 ); 1053 );
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 015fae195..e9af80b6c 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -68,7 +68,7 @@ pub use crate::{
68 expand_macro::ExpandedMacro, 68 expand_macro::ExpandedMacro,
69 folding_ranges::{Fold, FoldKind}, 69 folding_ranges::{Fold, FoldKind},
70 hover::HoverResult, 70 hover::HoverResult,
71 inlay_hints::{InlayHint, InlayKind}, 71 inlay_hints::{InlayHint, InlayHintsOptions, InlayKind},
72 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, 72 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
73 runnables::{Runnable, RunnableKind, TestId}, 73 runnables::{Runnable, RunnableKind, TestId},
74 source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, 74 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
@@ -319,9 +319,9 @@ impl Analysis {
319 pub fn inlay_hints( 319 pub fn inlay_hints(
320 &self, 320 &self,
321 file_id: FileId, 321 file_id: FileId,
322 max_inlay_hint_length: Option<usize>, 322 inlay_hint_opts: &InlayHintsOptions,
323 ) -> Cancelable<Vec<InlayHint>> { 323 ) -> Cancelable<Vec<InlayHint>> {
324 self.with_db(|db| inlay_hints::inlay_hints(db, file_id, max_inlay_hint_length)) 324 self.with_db(|db| inlay_hints::inlay_hints(db, file_id, inlay_hint_opts))
325 } 325 }
326 326
327 /// Returns the set of folding ranges. 327 /// Returns the set of folding ranges.
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs
index 55966daf3..f58e436d1 100644
--- a/crates/ra_ide/src/syntax_tree.rs
+++ b/crates/ra_ide/src/syntax_tree.rs
@@ -5,7 +5,7 @@ use ra_ide_db::RootDatabase;
5use ra_syntax::{ 5use ra_syntax::{
6 algo, AstNode, NodeOrToken, SourceFile, 6 algo, AstNode, NodeOrToken, SourceFile,
7 SyntaxKind::{RAW_STRING, STRING}, 7 SyntaxKind::{RAW_STRING, STRING},
8 SyntaxToken, TextRange, 8 SyntaxToken, TextRange, TextUnit,
9}; 9};
10 10
11pub use ra_db::FileId; 11pub use ra_db::FileId;
@@ -56,19 +56,23 @@ fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<St
56 let start = text_range.start() - node_range.start(); 56 let start = text_range.start() - node_range.start();
57 57
58 // how many characters we have selected 58 // how many characters we have selected
59 let len = text_range.len().to_usize(); 59 let len = text_range.len();
60 60
61 let node_len = node_range.len().to_usize(); 61 let node_len = node_range.len();
62 62
63 let start = start.to_usize(); 63 let start = start;
64 64
65 // We want to cap our length 65 // We want to cap our length
66 let len = len.min(node_len); 66 let len = len.min(node_len);
67 67
68 // Ensure our slice is inside the actual string 68 // Ensure our slice is inside the actual string
69 let end = if start + len < text.len() { start + len } else { text.len() - start }; 69 let end = if start + len < TextUnit::of_str(&text) {
70 start + len
71 } else {
72 TextUnit::of_str(&text) - start
73 };
70 74
71 let text = &text[start..end]; 75 let text = &text[TextRange::from_to(start, end)];
72 76
73 // Remove possible extra string quotes from the start 77 // Remove possible extra string quotes from the start
74 // and the end of the string 78 // and the end of the string