3 ast::{self, AstNode, LetStmt, NameOwner},
7 use crate::{AssistContext, AssistId, AssistKind, Assists};
9 // Assist: add_explicit_type
11 // Specify type for a let binding.
24 pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
25 let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;
26 let module = ctx.sema.scope(let_stmt.syntax()).module()?;
27 let expr = let_stmt.initializer()?;
29 let pat = match let_stmt.pat()? {
30 ast::Pat::IdentPat(bind_pat) => bind_pat,
33 let pat_range = pat.syntax().text_range();
34 // The binding must have a name
35 let name = pat.name()?;
36 let name_range = name.syntax().text_range();
38 // Assist should only be applicable if cursor is between 'let' and '='
39 let cursor_in_range = {
40 let stmt_range = let_stmt.syntax().text_range();
41 let eq_range = let_stmt.eq_token()?.text_range();
42 let let_range = TextRange::new(stmt_range.start(), eq_range.start());
43 let_range.contains_range(ctx.frange.range)
46 cov_mark::hit!(add_explicit_type_not_applicable_if_cursor_after_equals);
50 // Assist not applicable if the type has already been specified
51 // and it has no placeholders
52 let ascribed_ty = let_stmt.ty();
53 if let Some(ty) = &ascribed_ty {
54 if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() {
55 cov_mark::hit!(add_explicit_type_not_applicable_if_ty_already_specified);
61 let ty = ctx.sema.type_of_expr(&expr)?;
62 if ty.contains_unknown() || ty.is_closure() {
63 cov_mark::hit!(add_explicit_type_not_applicable_if_ty_not_inferred);
67 let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?;
69 AssistId("add_explicit_type", AssistKind::RefactorRewrite),
70 format!("Insert explicit type `{}`", inferred_type),
72 |builder| match ascribed_ty {
73 Some(ascribed_ty) => {
74 builder.replace(ascribed_ty.syntax().text_range(), inferred_type);
77 builder.insert(name_range.end(), format!(": {}", inferred_type));
87 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
90 fn add_explicit_type_target() {
91 check_assist_target(add_explicit_type, r#"fn f() { let a$0 = 1; }"#, "a");
95 fn add_explicit_type_works_for_simple_expr() {
98 r#"fn f() { let a$0 = 1; }"#,
99 r#"fn f() { let a: i32 = 1; }"#,
104 fn add_explicit_type_works_for_underscore() {
107 r#"fn f() { let a$0: _ = 1; }"#,
108 r#"fn f() { let a: i32 = 1; }"#,
113 fn add_explicit_type_works_for_nested_underscore() {
117 enum Option<T> { Some(T), None }
120 let a$0: Option<_> = Option::Some(1);
124 enum Option<T> { Some(T), None }
127 let a: Option<i32> = Option::Some(1);
134 fn add_explicit_type_works_for_macro_call() {
137 r"macro_rules! v { () => {0u64} } fn f() { let a$0 = v!(); }",
138 r"macro_rules! v { () => {0u64} } fn f() { let a: u64 = v!(); }",
143 fn add_explicit_type_works_for_macro_call_recursive() {
146 r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a$0 = v!(); }"#,
147 r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a: u64 = v!(); }"#,
152 fn add_explicit_type_not_applicable_if_ty_not_inferred() {
153 cov_mark::check!(add_explicit_type_not_applicable_if_ty_not_inferred);
154 check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0 = None; }"#);
158 fn add_explicit_type_not_applicable_if_ty_already_specified() {
159 cov_mark::check!(add_explicit_type_not_applicable_if_ty_already_specified);
160 check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0: i32 = 1; }"#);
164 fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() {
165 check_assist_not_applicable(
167 r#"fn f() { let a$0: (i32, i32) = (3, 4); }"#,
172 fn add_explicit_type_not_applicable_if_cursor_after_equals() {
173 cov_mark::check!(add_explicit_type_not_applicable_if_cursor_after_equals);
174 check_assist_not_applicable(
176 r#"fn f() {let a =$0 match 1 {2 => 3, 3 => 5};}"#,
181 fn add_explicit_type_not_applicable_if_cursor_before_let() {
182 check_assist_not_applicable(
184 r#"fn f() $0{let a = match 1 {2 => 3, 3 => 5};}"#,
189 fn closure_parameters_are_not_added() {
190 check_assist_not_applicable(
194 let multiply_by_two$0 = |i| i * 3;
195 let six = multiply_by_two(2);
201 /// https://github.com/rust-analyzer/rust-analyzer/issues/2922
203 fn regression_issue_2922() {
213 let v: [f64; 2] = [0.0; 2];
217 // note: this may break later if we add more consteval. it just needs to be something that our
218 // consteval engine doesn't understand
219 check_assist_not_applicable(
223 let $0l = [0.0; 2+2];
230 fn default_generics_should_not_be_added() {
234 struct Test<K, T = u8> { k: K, t: T }
237 let test$0 = Test { t: 23u8, k: 33 };
241 struct Test<K, T = u8> { k: K, t: T }
244 let test: Test<i32> = Test { t: 23u8, k: 33 };