diff options
author | Aleksey Kladov <[email protected]> | 2020-05-19 23:07:00 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-05-19 23:27:10 +0100 |
commit | 80545e5d3a72ef05a77ff9584234f030c69bfe9f (patch) | |
tree | 72b770193eb81853cab75a97e19d46eba12c44d8 /crates/ra_assists/src | |
parent | 1bc1f28bc58b2dbcf8f8f548c277e2c90e3075cd (diff) |
New assist: add turbo fish
Diffstat (limited to 'crates/ra_assists/src')
-rw-r--r-- | crates/ra_assists/src/handlers/add_turbo_fish.rs | 134 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_assists/src/marks.rs | 2 | ||||
-rw-r--r-- | crates/ra_assists/src/tests/generated.rs | 19 |
4 files changed, 157 insertions, 0 deletions
diff --git a/crates/ra_assists/src/handlers/add_turbo_fish.rs b/crates/ra_assists/src/handlers/add_turbo_fish.rs new file mode 100644 index 000000000..a0363bc78 --- /dev/null +++ b/crates/ra_assists/src/handlers/add_turbo_fish.rs | |||
@@ -0,0 +1,134 @@ | |||
1 | use ra_ide_db::defs::{classify_name_ref, Definition, NameRefClass}; | ||
2 | use ra_syntax::{ast, AstNode, SyntaxKind, T}; | ||
3 | |||
4 | use crate::{ | ||
5 | assist_context::{AssistContext, Assists}, | ||
6 | AssistId, | ||
7 | }; | ||
8 | use test_utils::tested_by; | ||
9 | |||
10 | // Assist: add_turbo_fish | ||
11 | // | ||
12 | // Adds `::<_>` to a call of a generic method or function. | ||
13 | // | ||
14 | // ``` | ||
15 | // fn make<T>() -> T { todo!() } | ||
16 | // fn main() { | ||
17 | // let x = make<|>(); | ||
18 | // } | ||
19 | // ``` | ||
20 | // -> | ||
21 | // ``` | ||
22 | // fn make<T>() -> T { todo!() } | ||
23 | // fn main() { | ||
24 | // let x = make::<${0:_}>(); | ||
25 | // } | ||
26 | // ``` | ||
27 | pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
28 | let ident = ctx.find_token_at_offset(SyntaxKind::IDENT)?; | ||
29 | let next_token = ident.next_token()?; | ||
30 | if next_token.kind() == T![::] { | ||
31 | tested_by!(add_turbo_fish_one_fish_is_enough); | ||
32 | return None; | ||
33 | } | ||
34 | let name_ref = ast::NameRef::cast(ident.parent())?; | ||
35 | let def = match classify_name_ref(&ctx.sema, &name_ref)? { | ||
36 | NameRefClass::Definition(def) => def, | ||
37 | NameRefClass::FieldShorthand { .. } => return None, | ||
38 | }; | ||
39 | let fun = match def { | ||
40 | Definition::ModuleDef(hir::ModuleDef::Function(it)) => it, | ||
41 | _ => return None, | ||
42 | }; | ||
43 | let generics = hir::GenericDef::Function(fun).params(ctx.sema.db); | ||
44 | if generics.is_empty() { | ||
45 | tested_by!(add_turbo_fish_non_generic); | ||
46 | return None; | ||
47 | } | ||
48 | acc.add(AssistId("add_turbo_fish"), "Add `::<>`", ident.text_range(), |builder| { | ||
49 | match ctx.config.snippet_cap { | ||
50 | Some(cap) => builder.insert_snippet(cap, ident.text_range().end(), "::<${0:_}>"), | ||
51 | None => builder.insert(ident.text_range().end(), "::<_>"), | ||
52 | } | ||
53 | }) | ||
54 | } | ||
55 | |||
56 | #[cfg(test)] | ||
57 | mod tests { | ||
58 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
59 | |||
60 | use super::*; | ||
61 | use test_utils::covers; | ||
62 | |||
63 | #[test] | ||
64 | fn add_turbo_fish_function() { | ||
65 | check_assist( | ||
66 | add_turbo_fish, | ||
67 | r#" | ||
68 | fn make<T>() -> T {} | ||
69 | fn main() { | ||
70 | make<|>(); | ||
71 | } | ||
72 | "#, | ||
73 | r#" | ||
74 | fn make<T>() -> T {} | ||
75 | fn main() { | ||
76 | make::<${0:_}>(); | ||
77 | } | ||
78 | "#, | ||
79 | ); | ||
80 | } | ||
81 | |||
82 | #[test] | ||
83 | fn add_turbo_fish_method() { | ||
84 | check_assist( | ||
85 | add_turbo_fish, | ||
86 | r#" | ||
87 | struct S; | ||
88 | impl S { | ||
89 | fn make<T>(&self) -> T {} | ||
90 | } | ||
91 | fn main() { | ||
92 | S.make<|>(); | ||
93 | } | ||
94 | "#, | ||
95 | r#" | ||
96 | struct S; | ||
97 | impl S { | ||
98 | fn make<T>(&self) -> T {} | ||
99 | } | ||
100 | fn main() { | ||
101 | S.make::<${0:_}>(); | ||
102 | } | ||
103 | "#, | ||
104 | ); | ||
105 | } | ||
106 | |||
107 | #[test] | ||
108 | fn add_turbo_fish_one_fish_is_enough() { | ||
109 | covers!(add_turbo_fish_one_fish_is_enough); | ||
110 | check_assist_not_applicable( | ||
111 | add_turbo_fish, | ||
112 | r#" | ||
113 | fn make<T>() -> T {} | ||
114 | fn main() { | ||
115 | make<|>::<()>(); | ||
116 | } | ||
117 | "#, | ||
118 | ); | ||
119 | } | ||
120 | |||
121 | #[test] | ||
122 | fn add_turbo_fish_non_generic() { | ||
123 | covers!(add_turbo_fish_non_generic); | ||
124 | check_assist_not_applicable( | ||
125 | add_turbo_fish, | ||
126 | r#" | ||
127 | fn make() -> () {} | ||
128 | fn main() { | ||
129 | make<|>(); | ||
130 | } | ||
131 | "#, | ||
132 | ); | ||
133 | } | ||
134 | } | ||
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 7f0a723c9..339f24100 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -110,6 +110,7 @@ mod handlers { | |||
110 | mod add_impl; | 110 | mod add_impl; |
111 | mod add_missing_impl_members; | 111 | mod add_missing_impl_members; |
112 | mod add_new; | 112 | mod add_new; |
113 | mod add_turbo_fish; | ||
113 | mod apply_demorgan; | 114 | mod apply_demorgan; |
114 | mod auto_import; | 115 | mod auto_import; |
115 | mod change_return_type_to_result; | 116 | mod change_return_type_to_result; |
@@ -147,6 +148,7 @@ mod handlers { | |||
147 | add_function::add_function, | 148 | add_function::add_function, |
148 | add_impl::add_impl, | 149 | add_impl::add_impl, |
149 | add_new::add_new, | 150 | add_new::add_new, |
151 | add_turbo_fish::add_turbo_fish, | ||
150 | apply_demorgan::apply_demorgan, | 152 | apply_demorgan::apply_demorgan, |
151 | auto_import::auto_import, | 153 | auto_import::auto_import, |
152 | change_return_type_to_result::change_return_type_to_result, | 154 | change_return_type_to_result::change_return_type_to_result, |
diff --git a/crates/ra_assists/src/marks.rs b/crates/ra_assists/src/marks.rs index 8d910205f..d579e627f 100644 --- a/crates/ra_assists/src/marks.rs +++ b/crates/ra_assists/src/marks.rs | |||
@@ -9,4 +9,6 @@ test_utils::marks![ | |||
9 | test_not_applicable_if_variable_unused | 9 | test_not_applicable_if_variable_unused |
10 | change_visibility_field_false_positive | 10 | change_visibility_field_false_positive |
11 | test_add_from_impl_already_exists | 11 | test_add_from_impl_already_exists |
12 | add_turbo_fish_one_fish_is_enough | ||
13 | add_turbo_fish_non_generic | ||
12 | ]; | 14 | ]; |
diff --git a/crates/ra_assists/src/tests/generated.rs b/crates/ra_assists/src/tests/generated.rs index 9487c9239..32fbcdef4 100644 --- a/crates/ra_assists/src/tests/generated.rs +++ b/crates/ra_assists/src/tests/generated.rs | |||
@@ -212,6 +212,25 @@ impl<T: Clone> Ctx<T> { | |||
212 | } | 212 | } |
213 | 213 | ||
214 | #[test] | 214 | #[test] |
215 | fn doctest_add_turbo_fish() { | ||
216 | check_doc_test( | ||
217 | "add_turbo_fish", | ||
218 | r#####" | ||
219 | fn make<T>() -> T { todo!() } | ||
220 | fn main() { | ||
221 | let x = make<|>(); | ||
222 | } | ||
223 | "#####, | ||
224 | r#####" | ||
225 | fn make<T>() -> T { todo!() } | ||
226 | fn main() { | ||
227 | let x = make::<${0:_}>(); | ||
228 | } | ||
229 | "#####, | ||
230 | ) | ||
231 | } | ||
232 | |||
233 | #[test] | ||
215 | fn doctest_apply_demorgan() { | 234 | fn doctest_apply_demorgan() { |
216 | check_doc_test( | 235 | check_doc_test( |
217 | "apply_demorgan", | 236 | "apply_demorgan", |