mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 05:38:46 +00:00
Simplify most of the inlay hints tests
This commit is contained in:
parent
0954d31bee
commit
442c13ba17
2 changed files with 199 additions and 631 deletions
|
@ -3,7 +3,7 @@ use ra_ide_db::RootDatabase;
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner},
|
ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner},
|
||||||
match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange,
|
match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{FileId, FunctionSignature};
|
use crate::{FileId, FunctionSignature};
|
||||||
|
@ -112,7 +112,7 @@ fn get_chaining_hints(
|
||||||
// Ignoring extra whitespace and comments
|
// Ignoring extra whitespace and comments
|
||||||
let next = tokens.next()?.kind();
|
let next = tokens.next()?.kind();
|
||||||
let next_next = tokens.next()?.kind();
|
let next_next = tokens.next()?.kind();
|
||||||
if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT {
|
if next == SyntaxKind::WHITESPACE && next_next == T![.] {
|
||||||
let ty = sema.type_of_expr(&expr)?;
|
let ty = sema.type_of_expr(&expr)?;
|
||||||
if ty.is_unknown() {
|
if ty.is_unknown() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -345,583 +345,245 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::inlay_hints::InlayHintsConfig;
|
|
||||||
use insta::assert_debug_snapshot;
|
use insta::assert_debug_snapshot;
|
||||||
|
use test_utils::extract_annotations;
|
||||||
|
|
||||||
use crate::mock_analysis::single_file;
|
use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file};
|
||||||
|
|
||||||
|
fn check(ra_fixture: &str) {
|
||||||
|
check_with_config(ra_fixture, InlayHintsConfig::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_with_config(ra_fixture: &str, config: InlayHintsConfig) {
|
||||||
|
let (analysis, file_id) = single_file(ra_fixture);
|
||||||
|
let expected = extract_annotations(&*analysis.file_text(file_id).unwrap());
|
||||||
|
let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap();
|
||||||
|
let actual =
|
||||||
|
inlay_hints.into_iter().map(|it| (it.range, it.label.to_string())).collect::<Vec<_>>();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn param_hints_only() {
|
fn param_hints_only() {
|
||||||
let (analysis, file_id) = single_file(
|
check_with_config(
|
||||||
r#"
|
r#"
|
||||||
fn foo(a: i32, b: i32) -> i32 { a + b }
|
fn foo(a: i32, b: i32) -> i32 { a + b }
|
||||||
fn main() {
|
fn main() {
|
||||||
let _x = foo(4, 4);
|
let _x = foo(
|
||||||
}"#,
|
4,
|
||||||
|
//^ a
|
||||||
|
4,
|
||||||
|
//^ b
|
||||||
);
|
);
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: true, type_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###"
|
}"#,
|
||||||
[
|
InlayHintsConfig {
|
||||||
InlayHint {
|
parameter_hints: true,
|
||||||
range: 69..70,
|
type_hints: false,
|
||||||
kind: ParameterHint,
|
chaining_hints: false,
|
||||||
label: "a",
|
max_length: None,
|
||||||
},
|
},
|
||||||
InlayHint {
|
);
|
||||||
range: 72..73,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "b",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hints_disabled() {
|
fn hints_disabled() {
|
||||||
let (analysis, file_id) = single_file(
|
check_with_config(
|
||||||
r#"
|
r#"
|
||||||
fn foo(a: i32, b: i32) -> i32 { a + b }
|
fn foo(a: i32, b: i32) -> i32 { a + b }
|
||||||
fn main() {
|
fn main() {
|
||||||
let _x = foo(4, 4);
|
let _x = foo(4, 4);
|
||||||
}"#,
|
}"#,
|
||||||
|
InlayHintsConfig {
|
||||||
|
type_hints: false,
|
||||||
|
parameter_hints: false,
|
||||||
|
chaining_hints: false,
|
||||||
|
max_length: None,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ type_hints: false, parameter_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###"[]"###);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn type_hints_only() {
|
fn type_hints_only() {
|
||||||
let (analysis, file_id) = single_file(
|
check_with_config(
|
||||||
r#"
|
r#"
|
||||||
fn foo(a: i32, b: i32) -> i32 { a + b }
|
fn foo(a: i32, b: i32) -> i32 { a + b }
|
||||||
fn main() {
|
fn main() {
|
||||||
let _x = foo(4, 4);
|
let _x = foo(4, 4);
|
||||||
|
//^^ i32
|
||||||
}"#,
|
}"#,
|
||||||
);
|
InlayHintsConfig {
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ type_hints: true, parameter_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###"
|
type_hints: true,
|
||||||
[
|
parameter_hints: false,
|
||||||
InlayHint {
|
chaining_hints: false,
|
||||||
range: 60..62,
|
max_length: None,
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
},
|
||||||
]
|
);
|
||||||
"###);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_generic_types_should_not_be_displayed() {
|
fn default_generic_types_should_not_be_displayed() {
|
||||||
let (analysis, file_id) = single_file(
|
check(
|
||||||
r#"
|
r#"
|
||||||
struct Test<K, T = u8> {
|
struct Test<K, T = u8> { k: K, t: T }
|
||||||
k: K,
|
|
||||||
t: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let zz = Test { t: 23u8, k: 33 };
|
let zz = Test { t: 23u8, k: 33 };
|
||||||
|
//^^ Test<i32>
|
||||||
let zz_ref = &zz;
|
let zz_ref = &zz;
|
||||||
|
//^^^^^^ &Test<i32>
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 68..70,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "Test<i32>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 106..112,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&Test<i32>",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn let_statement() {
|
fn let_statement() {
|
||||||
let (analysis, file_id) = single_file(
|
check(
|
||||||
r#"
|
r#"
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
enum CustomOption<T> {
|
enum Option<T> { None, Some(T) }
|
||||||
None,
|
|
||||||
Some(T),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
struct Test {
|
struct Test { a: Option<u32>, b: u8 }
|
||||||
a: CustomOption<u32>,
|
|
||||||
b: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct InnerStruct {}
|
struct InnerStruct {}
|
||||||
|
|
||||||
let test = 54;
|
let test = 54;
|
||||||
|
//^^^^ i32
|
||||||
let test: i32 = 33;
|
let test: i32 = 33;
|
||||||
let mut test = 33;
|
let mut test = 33;
|
||||||
|
//^^^^^^^^ i32
|
||||||
let _ = 22;
|
let _ = 22;
|
||||||
let test = "test";
|
let test = "test";
|
||||||
|
//^^^^ &str
|
||||||
let test = InnerStruct {};
|
let test = InnerStruct {};
|
||||||
|
|
||||||
let test = vec![222];
|
let test = unresolved();
|
||||||
let test: Vec<_> = (0..3).collect();
|
|
||||||
let test = (0..3).collect::<Vec<i128>>();
|
|
||||||
let test = (0..3).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let mut test = Vec::new();
|
|
||||||
test.push(333);
|
|
||||||
|
|
||||||
let test = (42, 'a');
|
let test = (42, 'a');
|
||||||
let (a, (b, c, (d, e), f)) = (2, (3, 4, (6.6, 7.7), 5));
|
//^^^^ (i32, char)
|
||||||
|
let (a, (b, (c,)) = (2, (3, (9.2,));
|
||||||
|
//^ i32 ^ i32 ^ f64
|
||||||
let &x = &92;
|
let &x = &92;
|
||||||
|
//^ i32
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 192..196,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 235..243,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 274..278,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&str",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 538..542,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "(i32, char)",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 565..566,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 569..570,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 572..573,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 576..577,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "f64",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 579..580,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "f64",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 583..584,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 626..627,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn closure_parameters() {
|
fn closure_parameters() {
|
||||||
let (analysis, file_id) = single_file(
|
check(
|
||||||
r#"
|
r#"
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
(0..2).for_each(|increment| {
|
//^^^^^^^^^ i32
|
||||||
start += increment;
|
(0..2).for_each(|increment| { start += increment; });
|
||||||
});
|
//^^^^^^^^^ i32
|
||||||
|
|
||||||
let multiply = |a, b, c, d| a * b * c * d;
|
let multiply =
|
||||||
let _: i32 = multiply(1, 2, 3, 4);
|
//^^^^^^^^ |…| -> i32
|
||||||
|
| a, b| a * b
|
||||||
|
//^ i32 ^ i32
|
||||||
|
;
|
||||||
|
|
||||||
|
let _: i32 = multiply(1, 2);
|
||||||
let multiply_ref = &multiply;
|
let multiply_ref = &multiply;
|
||||||
|
//^^^^^^^^^^^^ &|…| -> i32
|
||||||
|
|
||||||
let return_42 = || 42;
|
let return_42 = || 42;
|
||||||
|
//^^^^^^^^^ || -> i32
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 20..29,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 56..65,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 114..122,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "|…| -> i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 126..127,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 129..130,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 132..133,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 135..136,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 200..212,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&|…| -> i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 235..244,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "|| -> i32",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn for_expression() {
|
fn for_expression() {
|
||||||
let (analysis, file_id) = single_file(
|
check(
|
||||||
r#"
|
r#"
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
for increment in 0..2 {
|
//^^^^^^^^^ i32
|
||||||
start += increment;
|
for increment in 0..2 { start += increment; }
|
||||||
}
|
//^^^^^^^^^ i32
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 20..29,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 43..52,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_expr() {
|
fn if_expr() {
|
||||||
let (analysis, file_id) = single_file(
|
check(
|
||||||
r#"
|
r#"
|
||||||
#[derive(PartialEq)]
|
enum Option<T> { None, Some(T) }
|
||||||
enum CustomOption<T> {
|
use Option::*;
|
||||||
None,
|
|
||||||
Some(T),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
struct Test { a: Option<u32>, b: u8 }
|
||||||
struct Test {
|
|
||||||
a: CustomOption<u32>,
|
|
||||||
b: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
use CustomOption::*;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let test = Some(Test { a: Some(3), b: 1 });
|
let test = Some(Test { a: Some(3), b: 1 });
|
||||||
|
//^^^^ Option<Test>
|
||||||
if let None = &test {};
|
if let None = &test {};
|
||||||
if let test = &test {};
|
if let test = &test {};
|
||||||
|
//^^^^ &Option<Test>
|
||||||
if let Some(test) = &test {};
|
if let Some(test) = &test {};
|
||||||
|
//^^^^ &Test
|
||||||
if let Some(Test { a, b }) = &test {};
|
if let Some(Test { a, b }) = &test {};
|
||||||
|
//^ &Option<u32> ^ &u8
|
||||||
if let Some(Test { a: x, b: y }) = &test {};
|
if let Some(Test { a: x, b: y }) = &test {};
|
||||||
|
//^ &Option<u32> ^ &u8
|
||||||
if let Some(Test { a: Some(x), b: y }) = &test {};
|
if let Some(Test { a: Some(x), b: y }) = &test {};
|
||||||
|
//^ &u32 ^ &u8
|
||||||
if let Some(Test { a: None, b: y }) = &test {};
|
if let Some(Test { a: None, b: y }) = &test {};
|
||||||
|
//^ &u8
|
||||||
if let Some(Test { b: y, .. }) = &test {};
|
if let Some(Test { b: y, .. }) = &test {};
|
||||||
|
//^ &u8
|
||||||
if test == None {}
|
if test == None {}
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 187..191,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "CustomOption<Test>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 266..270,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&CustomOption<Test>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 299..303,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&Test",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 340..341,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&CustomOption<u32>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 343..344,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 386..387,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&CustomOption<u32>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 392..393,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 440..441,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 447..448,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 499..500,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 542..543,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn while_expr() {
|
fn while_expr() {
|
||||||
let (analysis, file_id) = single_file(
|
check(
|
||||||
r#"
|
r#"
|
||||||
#[derive(PartialEq)]
|
enum Option<T> { None, Some(T) }
|
||||||
enum CustomOption<T> {
|
use Option::*;
|
||||||
None,
|
|
||||||
Some(T),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
struct Test { a: Option<u32>, b: u8 }
|
||||||
struct Test {
|
|
||||||
a: CustomOption<u32>,
|
|
||||||
b: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
use CustomOption::*;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let test = Some(Test { a: Some(3), b: 1 });
|
let test = Some(Test { a: Some(3), b: 1 });
|
||||||
while let None = &test {};
|
//^^^^ Option<Test>
|
||||||
while let test = &test {};
|
|
||||||
while let Some(test) = &test {};
|
|
||||||
while let Some(Test { a, b }) = &test {};
|
|
||||||
while let Some(Test { a: x, b: y }) = &test {};
|
|
||||||
while let Some(Test { a: Some(x), b: y }) = &test {};
|
while let Some(Test { a: Some(x), b: y }) = &test {};
|
||||||
while let Some(Test { a: None, b: y }) = &test {};
|
//^ &u32 ^ &u8
|
||||||
while let Some(Test { b: y, .. }) = &test {};
|
|
||||||
|
|
||||||
while test == None {}
|
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 187..191,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "CustomOption<Test>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 272..276,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&CustomOption<Test>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 308..312,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&Test",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 352..353,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&CustomOption<u32>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 355..356,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 401..402,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&CustomOption<u32>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 407..408,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 458..459,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 465..466,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 520..521,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 566..567,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "&u8",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn match_arm_list() {
|
fn match_arm_list() {
|
||||||
let (analysis, file_id) = single_file(
|
check(
|
||||||
r#"
|
r#"
|
||||||
#[derive(PartialEq)]
|
enum Option<T> { None, Some(T) }
|
||||||
enum CustomOption<T> {
|
use Option::*;
|
||||||
None,
|
|
||||||
Some(T),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
struct Test { a: Option<u32>, b: u8 }
|
||||||
struct Test {
|
|
||||||
a: CustomOption<u32>,
|
|
||||||
b: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
use CustomOption::*;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match Some(Test { a: Some(3), b: 1 }) {
|
match Some(Test { a: Some(3), b: 1 }) {
|
||||||
None => (),
|
None => (),
|
||||||
test => (),
|
test => (),
|
||||||
Some(test) => (),
|
//^^^^ Option<Test>
|
||||||
Some(Test { a, b }) => (),
|
|
||||||
Some(Test { a: x, b: y }) => (),
|
|
||||||
Some(Test { a: Some(x), b: y }) => (),
|
Some(Test { a: Some(x), b: y }) => (),
|
||||||
Some(Test { a: None, b: y }) => (),
|
//^ u32 ^ u8
|
||||||
Some(Test { b: y, .. }) => (),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 251..255,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "CustomOption<Test>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 276..280,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "Test",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 309..310,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "CustomOption<u32>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 312..313,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 347..348,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "CustomOption<u32>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 353..354,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 393..394,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "u32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 400..401,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 444..445,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "u8",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 479..480,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "u8",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hint_truncation() {
|
fn hint_truncation() {
|
||||||
let (analysis, file_id) = single_file(
|
check_with_config(
|
||||||
r#"
|
r#"
|
||||||
struct Smol<T>(T);
|
struct Smol<T>(T);
|
||||||
|
|
||||||
|
@ -929,52 +591,26 @@ struct VeryLongOuterName<T>(T);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = Smol(0u32);
|
let a = Smol(0u32);
|
||||||
|
//^ Smol<u32>
|
||||||
let b = VeryLongOuterName(0usize);
|
let b = VeryLongOuterName(0usize);
|
||||||
|
//^ VeryLongOuterName<…>
|
||||||
let c = Smol(Smol(0u32))
|
let c = Smol(Smol(0u32))
|
||||||
|
//^ Smol<Smol<…>>
|
||||||
}"#,
|
}"#,
|
||||||
);
|
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 73..74,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "Smol<u32>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 97..98,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "VeryLongOuterName<…>",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 136..137,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "Smol<Smol<…>>",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_call_parameter_hint() {
|
fn function_call_parameter_hint() {
|
||||||
let (analysis, file_id) = single_file(
|
check(
|
||||||
r#"
|
r#"
|
||||||
enum CustomOption<T> {
|
enum Option<T> { None, Some(T) }
|
||||||
None,
|
use Option::*;
|
||||||
Some(T),
|
|
||||||
}
|
|
||||||
use CustomOption::*;
|
|
||||||
|
|
||||||
struct FileId {}
|
struct FileId {}
|
||||||
struct SmolStr {}
|
struct SmolStr {}
|
||||||
|
|
||||||
impl From<&str> for SmolStr {
|
|
||||||
fn from(_: &str) -> Self {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TextRange {}
|
struct TextRange {}
|
||||||
struct SyntaxKind {}
|
struct SyntaxKind {}
|
||||||
struct NavigationTarget {}
|
struct NavigationTarget {}
|
||||||
|
@ -982,18 +618,15 @@ struct NavigationTarget {}
|
||||||
struct Test {}
|
struct Test {}
|
||||||
|
|
||||||
impl Test {
|
impl Test {
|
||||||
fn method(&self, mut param: i32) -> i32 {
|
fn method(&self, mut param: i32) -> i32 { param * 2 }
|
||||||
param * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_syntax(
|
fn from_syntax(
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
name: SmolStr,
|
name: SmolStr,
|
||||||
focus_range: CustomOption<TextRange>,
|
focus_range: Option<TextRange>,
|
||||||
full_range: TextRange,
|
full_range: TextRange,
|
||||||
kind: SyntaxKind,
|
kind: SyntaxKind,
|
||||||
docs: CustomOption<String>,
|
docs: Option<String>,
|
||||||
description: CustomOption<String>,
|
|
||||||
) -> NavigationTarget {
|
) -> NavigationTarget {
|
||||||
NavigationTarget {}
|
NavigationTarget {}
|
||||||
}
|
}
|
||||||
|
@ -1005,108 +638,35 @@ fn test_func(mut foo: i32, bar: i32, msg: &str, _: i32, last: i32) -> i32 {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let not_literal = 1;
|
let not_literal = 1;
|
||||||
|
//^^^^^^^^^^^ i32
|
||||||
let _: i32 = test_func(1, 2, "hello", 3, not_literal);
|
let _: i32 = test_func(1, 2, "hello", 3, not_literal);
|
||||||
|
//^ foo ^ bar ^^^^^^^ msg ^^^^^^^^^^^ last
|
||||||
let t: Test = Test {};
|
let t: Test = Test {};
|
||||||
t.method(123);
|
t.method(123);
|
||||||
|
//^^^ param
|
||||||
Test::method(&t, 3456);
|
Test::method(&t, 3456);
|
||||||
|
//^^ &self ^^^^ param
|
||||||
Test::from_syntax(
|
Test::from_syntax(
|
||||||
FileId {},
|
FileId {},
|
||||||
|
//^^^^^^^^^ file_id
|
||||||
"impl".into(),
|
"impl".into(),
|
||||||
|
//^^^^^^^^^^^^^ name
|
||||||
None,
|
None,
|
||||||
|
//^^^^ focus_range
|
||||||
TextRange {},
|
TextRange {},
|
||||||
|
//^^^^^^^^^^^^ full_range
|
||||||
SyntaxKind {},
|
SyntaxKind {},
|
||||||
|
//^^^^^^^^^^^^^ kind
|
||||||
None,
|
None,
|
||||||
None,
|
//^^^^ docs
|
||||||
);
|
);
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig::default()).unwrap(), @r###"
|
|
||||||
[
|
|
||||||
InlayHint {
|
|
||||||
range: 797..808,
|
|
||||||
kind: TypeHint,
|
|
||||||
label: "i32",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 841..842,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "foo",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 844..845,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "bar",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 847..854,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "msg",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 859..870,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "last",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 913..916,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "param",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 936..938,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "&self",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 940..944,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "param",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 979..988,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "file_id",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 998..1011,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "name",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 1021..1025,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "focus_range",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 1035..1047,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "full_range",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 1057..1070,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "kind",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 1080..1084,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "docs",
|
|
||||||
},
|
|
||||||
InlayHint {
|
|
||||||
range: 1094..1098,
|
|
||||||
kind: ParameterHint,
|
|
||||||
label: "description",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
"###
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn omitted_parameters_hints_heuristics() {
|
fn omitted_parameters_hints_heuristics() {
|
||||||
let (analysis, file_id) = single_file(
|
check_with_config(
|
||||||
r#"
|
r#"
|
||||||
fn map(f: i32) {}
|
fn map(f: i32) {}
|
||||||
fn filter(predicate: i32) {}
|
fn filter(predicate: i32) {}
|
||||||
|
@ -1187,23 +747,16 @@ fn main() {
|
||||||
let _: f64 = a.div_euclid(b);
|
let _: f64 = a.div_euclid(b);
|
||||||
let _: f64 = a.abs_sub(b);
|
let _: f64 = a.abs_sub(b);
|
||||||
}"#,
|
}"#,
|
||||||
);
|
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
|
|
||||||
[]
|
|
||||||
"###
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unit_structs_have_no_type_hints() {
|
fn unit_structs_have_no_type_hints() {
|
||||||
let (analysis, file_id) = single_file(
|
check_with_config(
|
||||||
r#"
|
r#"
|
||||||
enum CustomResult<T, E> {
|
enum Result<T, E> { Ok(T), Err(E) }
|
||||||
Ok(T),
|
use Result::*;
|
||||||
Err(E),
|
|
||||||
}
|
|
||||||
use CustomResult::*;
|
|
||||||
|
|
||||||
struct SyntheticSyntax;
|
struct SyntheticSyntax;
|
||||||
|
|
||||||
|
@ -1213,11 +766,7 @@ fn main() {
|
||||||
Err(SyntheticSyntax) => (),
|
Err(SyntheticSyntax) => (),
|
||||||
}
|
}
|
||||||
}"#,
|
}"#,
|
||||||
);
|
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||||
|
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
|
|
||||||
[]
|
|
||||||
"###
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1255,7 +804,7 @@ fn main() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn chaining_hints_without_newlines() {
|
fn chaining_hints_without_newlines() {
|
||||||
let (analysis, file_id) = single_file(
|
check_with_config(
|
||||||
r#"
|
r#"
|
||||||
struct A(B);
|
struct A(B);
|
||||||
impl A { fn into_b(self) -> B { self.0 } }
|
impl A { fn into_b(self) -> B { self.0 } }
|
||||||
|
@ -1266,8 +815,13 @@ fn main() {
|
||||||
fn main() {
|
fn main() {
|
||||||
let c = A(B(C)).into_b().into_c();
|
let c = A(B(C)).into_b().into_c();
|
||||||
}"#,
|
}"#,
|
||||||
|
InlayHintsConfig {
|
||||||
|
parameter_hints: false,
|
||||||
|
type_hints: false,
|
||||||
|
chaining_hints: true,
|
||||||
|
max_length: None,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###"[]"###);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub mod mark;
|
||||||
mod fixture;
|
mod fixture;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryInto,
|
convert::{TryFrom, TryInto},
|
||||||
env, fs,
|
env, fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
@ -169,10 +169,9 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
|
||||||
for line in lines_with_ends(text) {
|
for line in lines_with_ends(text) {
|
||||||
if let Some(idx) = line.find("//^") {
|
if let Some(idx) = line.find("//^") {
|
||||||
let offset = prev_line_start.unwrap() + TextSize::of(&line[..idx + "//".len()]);
|
let offset = prev_line_start.unwrap() + TextSize::of(&line[..idx + "//".len()]);
|
||||||
let marker_and_data = &line[idx + "//".len()..];
|
for (line_range, text) in extract_line_annotations(&line[idx + "//".len()..]) {
|
||||||
let len = marker_and_data.chars().take_while(|&it| it == '^').count();
|
res.push((line_range + offset, text))
|
||||||
let data = marker_and_data[len..].trim().to_string();
|
}
|
||||||
res.push((TextRange::at(offset, len.try_into().unwrap()), data))
|
|
||||||
}
|
}
|
||||||
prev_line_start = Some(line_start);
|
prev_line_start = Some(line_start);
|
||||||
line_start += TextSize::of(line);
|
line_start += TextSize::of(line);
|
||||||
|
@ -180,13 +179,28 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extract_line_annotations(mut line: &str) -> Vec<(TextRange, String)> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
let mut offset: TextSize = 0.into();
|
||||||
|
while !line.is_empty() {
|
||||||
|
let len = line.chars().take_while(|&it| it == '^').count();
|
||||||
|
assert!(len > 0);
|
||||||
|
let range = TextRange::at(offset, len.try_into().unwrap());
|
||||||
|
let next = line[len..].find('^').map_or(line.len(), |it| it + len);
|
||||||
|
res.push((range, line[len..][..next - len].trim().to_string()));
|
||||||
|
line = &line[next..];
|
||||||
|
offset += TextSize::try_from(next).unwrap();
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_annotations() {
|
fn test_extract_annotations() {
|
||||||
let text = stdx::trim_indent(
|
let text = stdx::trim_indent(
|
||||||
r#"
|
r#"
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = 92;
|
let (x, y) = (9, 2);
|
||||||
//^ def
|
//^ def ^ def
|
||||||
zoo + 1
|
zoo + 1
|
||||||
} //^^^ i32
|
} //^^^ i32
|
||||||
"#,
|
"#,
|
||||||
|
@ -195,7 +209,7 @@ fn main() {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(range, ann)| (&text[range], ann))
|
.map(|(range, ann)| (&text[range], ann))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert_eq!(res, vec![("x", "def".into()), ("zoo", "i32".into()),]);
|
assert_eq!(res, vec![("x", "def".into()), ("y", "def".into()), ("zoo", "i32".into()),]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparison functionality borrowed from cargo:
|
// Comparison functionality borrowed from cargo:
|
||||||
|
|
Loading…
Reference in a new issue