diff options
Diffstat (limited to 'crates/ra_assists/src/add_explicit_type.rs')
-rw-r--r-- | crates/ra_assists/src/add_explicit_type.rs | 86 |
1 files changed, 0 insertions, 86 deletions
diff --git a/crates/ra_assists/src/add_explicit_type.rs b/crates/ra_assists/src/add_explicit_type.rs deleted file mode 100644 index 78f0f7f28..000000000 --- a/crates/ra_assists/src/add_explicit_type.rs +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | use hir::{db::HirDatabase, HirDisplay, Ty}; | ||
2 | use ra_syntax::{ | ||
3 | ast::{self, AstNode, LetStmt, NameOwner}, | ||
4 | T, | ||
5 | }; | ||
6 | |||
7 | use crate::{Assist, AssistCtx, AssistId}; | ||
8 | |||
9 | /// Add explicit type assist. | ||
10 | pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
11 | let stmt = ctx.node_at_offset::<LetStmt>()?; | ||
12 | let expr = stmt.initializer()?; | ||
13 | let pat = stmt.pat()?; | ||
14 | // Must be a binding | ||
15 | let pat = match pat { | ||
16 | ast::Pat::BindPat(bind_pat) => bind_pat, | ||
17 | _ => return None, | ||
18 | }; | ||
19 | let pat_range = pat.syntax().text_range(); | ||
20 | // The binding must have a name | ||
21 | let name = pat.name()?; | ||
22 | let name_range = name.syntax().text_range(); | ||
23 | // Assist not applicable if the type has already been specified | ||
24 | if stmt.syntax().children_with_tokens().any(|child| child.kind() == T![:]) { | ||
25 | return None; | ||
26 | } | ||
27 | // Infer type | ||
28 | let db = ctx.db; | ||
29 | let analyzer = hir::SourceAnalyzer::new(db, ctx.frange.file_id, stmt.syntax(), None); | ||
30 | let ty = analyzer.type_of(db, &expr)?; | ||
31 | // Assist not applicable if the type is unknown | ||
32 | if is_unknown(&ty) { | ||
33 | return None; | ||
34 | } | ||
35 | |||
36 | ctx.add_action(AssistId("add_explicit_type"), "add explicit type", |edit| { | ||
37 | edit.target(pat_range); | ||
38 | edit.insert(name_range.end(), format!(": {}", ty.display(db))); | ||
39 | }); | ||
40 | ctx.build() | ||
41 | } | ||
42 | |||
43 | /// Returns true if any type parameter is unknown | ||
44 | fn is_unknown(ty: &Ty) -> bool { | ||
45 | match ty { | ||
46 | Ty::Unknown => true, | ||
47 | Ty::Apply(a_ty) => a_ty.parameters.iter().any(is_unknown), | ||
48 | _ => false, | ||
49 | } | ||
50 | } | ||
51 | |||
52 | #[cfg(test)] | ||
53 | mod tests { | ||
54 | use super::*; | ||
55 | |||
56 | use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; | ||
57 | |||
58 | #[test] | ||
59 | fn add_explicit_type_target() { | ||
60 | check_assist_target(add_explicit_type, "fn f() { let a<|> = 1; }", "a"); | ||
61 | } | ||
62 | |||
63 | #[test] | ||
64 | fn add_explicit_type_works_for_simple_expr() { | ||
65 | check_assist( | ||
66 | add_explicit_type, | ||
67 | "fn f() { let a<|> = 1; }", | ||
68 | "fn f() { let a<|>: i32 = 1; }", | ||
69 | ); | ||
70 | } | ||
71 | |||
72 | #[test] | ||
73 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { | ||
74 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|> = None; }"); | ||
75 | } | ||
76 | |||
77 | #[test] | ||
78 | fn add_explicit_type_not_applicable_if_ty_already_specified() { | ||
79 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|>: i32 = 1; }"); | ||
80 | } | ||
81 | |||
82 | #[test] | ||
83 | fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() { | ||
84 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|>: (i32, i32) = (3, 4); }"); | ||
85 | } | ||
86 | } | ||