aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src/handlers/add_turbo_fish.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src/handlers/add_turbo_fish.rs')
-rw-r--r--crates/ide_assists/src/handlers/add_turbo_fish.rs138
1 files changed, 137 insertions, 1 deletions
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs
index 8e9ea4fad..f18e3edf9 100644
--- a/crates/ide_assists/src/handlers/add_turbo_fish.rs
+++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs
@@ -31,11 +31,13 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
31 return None; 31 return None;
32 } 32 }
33 mark::hit!(add_turbo_fish_after_call); 33 mark::hit!(add_turbo_fish_after_call);
34 mark::hit!(add_type_ascription_after_call);
34 arg_list.l_paren_token()?.prev_token().filter(|it| it.kind() == SyntaxKind::IDENT) 35 arg_list.l_paren_token()?.prev_token().filter(|it| it.kind() == SyntaxKind::IDENT)
35 })?; 36 })?;
36 let next_token = ident.next_token()?; 37 let next_token = ident.next_token()?;
37 if next_token.kind() == T![::] { 38 if next_token.kind() == T![::] {
38 mark::hit!(add_turbo_fish_one_fish_is_enough); 39 mark::hit!(add_turbo_fish_one_fish_is_enough);
40 mark::hit!(add_type_ascription_turbofished);
39 return None; 41 return None;
40 } 42 }
41 let name_ref = ast::NameRef::cast(ident.parent())?; 43 let name_ref = ast::NameRef::cast(ident.parent())?;
@@ -50,8 +52,27 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
50 let generics = hir::GenericDef::Function(fun).params(ctx.sema.db); 52 let generics = hir::GenericDef::Function(fun).params(ctx.sema.db);
51 if generics.is_empty() { 53 if generics.is_empty() {
52 mark::hit!(add_turbo_fish_non_generic); 54 mark::hit!(add_turbo_fish_non_generic);
55 mark::hit!(add_type_ascription_non_generic);
53 return None; 56 return None;
54 } 57 }
58
59 if let Some(let_stmt) = ctx.find_node_at_offset::<ast::LetStmt>() {
60 if let_stmt.colon_token().is_none() {
61 let type_pos = let_stmt.pat()?.syntax().last_token()?.text_range().end();
62 acc.add(
63 AssistId("add_type_ascription", AssistKind::RefactorRewrite),
64 "Add `: _` before assignment operator",
65 ident.text_range(),
66 |builder| match ctx.config.snippet_cap {
67 Some(cap) => builder.insert_snippet(cap, type_pos, ": ${0:_}"),
68 None => builder.insert(type_pos, ": _"),
69 },
70 )?
71 } else {
72 mark::hit!(add_type_ascription_already_typed);
73 }
74 }
75
55 acc.add( 76 acc.add(
56 AssistId("add_turbo_fish", AssistKind::RefactorRewrite), 77 AssistId("add_turbo_fish", AssistKind::RefactorRewrite),
57 "Add `::<>`", 78 "Add `::<>`",
@@ -65,7 +86,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
65 86
66#[cfg(test)] 87#[cfg(test)]
67mod tests { 88mod tests {
68 use crate::tests::{check_assist, check_assist_not_applicable}; 89 use crate::tests::{check_assist, check_assist_by_label, check_assist_not_applicable};
69 90
70 use super::*; 91 use super::*;
71 use test_utils::mark; 92 use test_utils::mark;
@@ -161,4 +182,119 @@ fn main() {
161"#, 182"#,
162 ); 183 );
163 } 184 }
185
186 #[test]
187 fn add_type_ascription_function() {
188 check_assist_by_label(
189 add_turbo_fish,
190 r#"
191fn make<T>() -> T {}
192fn main() {
193 let x = make$0();
194}
195"#,
196 r#"
197fn make<T>() -> T {}
198fn main() {
199 let x: ${0:_} = make();
200}
201"#,
202 "Add `: _` before assignment operator",
203 );
204 }
205
206 #[test]
207 fn add_type_ascription_after_call() {
208 mark::check!(add_type_ascription_after_call);
209 check_assist_by_label(
210 add_turbo_fish,
211 r#"
212fn make<T>() -> T {}
213fn main() {
214 let x = make()$0;
215}
216"#,
217 r#"
218fn make<T>() -> T {}
219fn main() {
220 let x: ${0:_} = make();
221}
222"#,
223 "Add `: _` before assignment operator",
224 );
225 }
226
227 #[test]
228 fn add_type_ascription_method() {
229 check_assist_by_label(
230 add_turbo_fish,
231 r#"
232struct S;
233impl S {
234 fn make<T>(&self) -> T {}
235}
236fn main() {
237 let x = S.make$0();
238}
239"#,
240 r#"
241struct S;
242impl S {
243 fn make<T>(&self) -> T {}
244}
245fn main() {
246 let x: ${0:_} = S.make();
247}
248"#,
249 "Add `: _` before assignment operator",
250 );
251 }
252
253 #[test]
254 fn add_type_ascription_turbofished() {
255 mark::check!(add_type_ascription_turbofished);
256 check_assist_not_applicable(
257 add_turbo_fish,
258 r#"
259fn make<T>() -> T {}
260fn main() {
261 let x = make$0::<()>();
262}
263"#,
264 );
265 }
266
267 #[test]
268 fn add_type_ascription_already_typed() {
269 mark::check!(add_type_ascription_already_typed);
270 check_assist(
271 add_turbo_fish,
272 r#"
273fn make<T>() -> T {}
274fn main() {
275 let x: () = make$0();
276}
277"#,
278 r#"
279fn make<T>() -> T {}
280fn main() {
281 let x: () = make::<${0:_}>();
282}
283"#,
284 );
285 }
286
287 #[test]
288 fn add_type_ascription_non_generic() {
289 mark::check!(add_type_ascription_non_generic);
290 check_assist_not_applicable(
291 add_turbo_fish,
292 r#"
293fn make() -> () {}
294fn main() {
295 let x = make$0();
296}
297"#,
298 );
299 }
164} 300}