diff options
Diffstat (limited to 'crates/ide_assists/src/handlers')
16 files changed, 396 insertions, 382 deletions
diff --git a/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs index b5b5ada5e..70949ca35 100644 --- a/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs +++ b/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs | |||
@@ -107,7 +107,7 @@ fn edit_struct_references( | |||
107 | names: &[ast::Name], | 107 | names: &[ast::Name], |
108 | ) { | 108 | ) { |
109 | let strukt_def = Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(strukt))); | 109 | let strukt_def = Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(strukt))); |
110 | let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all(); | 110 | let usages = strukt_def.usages(&ctx.sema).include_self_refs().all(); |
111 | 111 | ||
112 | let edit_node = |edit: &mut AssistBuilder, node: SyntaxNode| -> Option<()> { | 112 | let edit_node = |edit: &mut AssistBuilder, node: SyntaxNode| -> Option<()> { |
113 | match_ast! { | 113 | match_ast! { |
diff --git a/crates/ide_assists/src/handlers/early_return.rs b/crates/ide_assists/src/handlers/early_return.rs index c66f8c05d..5eb6a57f0 100644 --- a/crates/ide_assists/src/handlers/early_return.rs +++ b/crates/ide_assists/src/handlers/early_return.rs | |||
@@ -130,9 +130,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) | |||
130 | once(make::ident_pat(make::name("it")).into()), | 130 | once(make::ident_pat(make::name("it")).into()), |
131 | ); | 131 | ); |
132 | let expr = { | 132 | let expr = { |
133 | let name_ref = make::name_ref("it"); | 133 | let path = make::ext::ident_path("it"); |
134 | let segment = make::path_segment(name_ref); | ||
135 | let path = make::path_unqualified(segment); | ||
136 | make::expr_path(path) | 134 | make::expr_path(path) |
137 | }; | 135 | }; |
138 | make::match_arm(once(pat.into()), expr) | 136 | make::match_arm(once(pat.into()), expr) |
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs index 98389e4f7..da8d245e5 100644 --- a/crates/ide_assists/src/handlers/expand_glob_import.rs +++ b/crates/ide_assists/src/handlers/expand_glob_import.rs | |||
@@ -4,10 +4,10 @@ use ide_db::{ | |||
4 | defs::{Definition, NameRefClass}, | 4 | defs::{Definition, NameRefClass}, |
5 | search::SearchScope, | 5 | search::SearchScope, |
6 | }; | 6 | }; |
7 | use stdx::never; | ||
7 | use syntax::{ | 8 | use syntax::{ |
8 | algo::SyntaxRewriter, | ||
9 | ast::{self, make}, | 9 | ast::{self, make}, |
10 | AstNode, Direction, SyntaxNode, SyntaxToken, T, | 10 | ted, AstNode, Direction, SyntaxNode, SyntaxToken, T, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
@@ -42,6 +42,7 @@ use crate::{ | |||
42 | // ``` | 42 | // ``` |
43 | pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 43 | pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
44 | let star = ctx.find_token_syntax_at_offset(T![*])?; | 44 | let star = ctx.find_token_syntax_at_offset(T![*])?; |
45 | let use_tree = star.parent().and_then(ast::UseTree::cast)?; | ||
45 | let (parent, mod_path) = find_parent_and_path(&star)?; | 46 | let (parent, mod_path) = find_parent_and_path(&star)?; |
46 | let target_module = match ctx.sema.resolve_path(&mod_path)? { | 47 | let target_module = match ctx.sema.resolve_path(&mod_path)? { |
47 | PathResolution::Def(ModuleDef::Module(it)) => it, | 48 | PathResolution::Def(ModuleDef::Module(it)) => it, |
@@ -53,7 +54,6 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti | |||
53 | 54 | ||
54 | let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?; | 55 | let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?; |
55 | let imported_defs = find_imported_defs(ctx, star)?; | 56 | let imported_defs = find_imported_defs(ctx, star)?; |
56 | let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs); | ||
57 | 57 | ||
58 | let target = parent.clone().either(|n| n.syntax().clone(), |n| n.syntax().clone()); | 58 | let target = parent.clone().either(|n| n.syntax().clone(), |n| n.syntax().clone()); |
59 | acc.add( | 59 | acc.add( |
@@ -61,9 +61,31 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti | |||
61 | "Expand glob import", | 61 | "Expand glob import", |
62 | target.text_range(), | 62 | target.text_range(), |
63 | |builder| { | 63 | |builder| { |
64 | let mut rewriter = SyntaxRewriter::default(); | 64 | let use_tree = builder.make_ast_mut(use_tree); |
65 | replace_ast(&mut rewriter, parent, mod_path, names_to_import); | 65 | |
66 | builder.rewrite(rewriter); | 66 | let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs); |
67 | let expanded = make::use_tree_list(names_to_import.iter().map(|n| { | ||
68 | let path = make::ext::ident_path(&n.to_string()); | ||
69 | make::use_tree(path, None, None, false) | ||
70 | })) | ||
71 | .clone_for_update(); | ||
72 | |||
73 | match use_tree.star_token() { | ||
74 | Some(star) => { | ||
75 | let needs_braces = use_tree.path().is_some() && names_to_import.len() > 1; | ||
76 | if needs_braces { | ||
77 | ted::replace(star, expanded.syntax()) | ||
78 | } else { | ||
79 | let without_braces = expanded | ||
80 | .syntax() | ||
81 | .children_with_tokens() | ||
82 | .filter(|child| !matches!(child.kind(), T!['{'] | T!['}'])) | ||
83 | .collect(); | ||
84 | ted::replace_with_many(star, without_braces) | ||
85 | } | ||
86 | } | ||
87 | None => never!(), | ||
88 | } | ||
67 | }, | 89 | }, |
68 | ) | 90 | ) |
69 | } | 91 | } |
@@ -232,53 +254,6 @@ fn find_names_to_import( | |||
232 | used_refs.0.iter().map(|r| r.visible_name.clone()).collect() | 254 | used_refs.0.iter().map(|r| r.visible_name.clone()).collect() |
233 | } | 255 | } |
234 | 256 | ||
235 | fn replace_ast( | ||
236 | rewriter: &mut SyntaxRewriter, | ||
237 | parent: Either<ast::UseTree, ast::UseTreeList>, | ||
238 | path: ast::Path, | ||
239 | names_to_import: Vec<Name>, | ||
240 | ) { | ||
241 | let existing_use_trees = match parent.clone() { | ||
242 | Either::Left(_) => vec![], | ||
243 | Either::Right(u) => u | ||
244 | .use_trees() | ||
245 | .filter(|n| | ||
246 | // filter out star | ||
247 | n.star_token().is_none()) | ||
248 | .collect(), | ||
249 | }; | ||
250 | |||
251 | let new_use_trees: Vec<ast::UseTree> = names_to_import | ||
252 | .iter() | ||
253 | .map(|n| { | ||
254 | let path = make::path_unqualified(make::path_segment(make::name_ref(&n.to_string()))); | ||
255 | make::use_tree(path, None, None, false) | ||
256 | }) | ||
257 | .collect(); | ||
258 | |||
259 | let use_trees = [&existing_use_trees[..], &new_use_trees[..]].concat(); | ||
260 | |||
261 | match use_trees.as_slice() { | ||
262 | [name] => { | ||
263 | if let Some(end_path) = name.path() { | ||
264 | rewriter.replace_ast( | ||
265 | &parent.left_or_else(|tl| tl.parent_use_tree()), | ||
266 | &make::use_tree(make::path_concat(path, end_path), None, None, false), | ||
267 | ); | ||
268 | } | ||
269 | } | ||
270 | names => match &parent { | ||
271 | Either::Left(parent) => rewriter.replace_ast( | ||
272 | parent, | ||
273 | &make::use_tree(path, Some(make::use_tree_list(names.to_owned())), None, false), | ||
274 | ), | ||
275 | Either::Right(parent) => { | ||
276 | rewriter.replace_ast(parent, &make::use_tree_list(names.to_owned())) | ||
277 | } | ||
278 | }, | ||
279 | }; | ||
280 | } | ||
281 | |||
282 | #[cfg(test)] | 257 | #[cfg(test)] |
283 | mod tests { | 258 | mod tests { |
284 | use crate::tests::{check_assist, check_assist_not_applicable}; | 259 | use crate::tests::{check_assist, check_assist_not_applicable}; |
@@ -350,7 +325,7 @@ mod foo { | |||
350 | pub fn f() {} | 325 | pub fn f() {} |
351 | } | 326 | } |
352 | 327 | ||
353 | use foo::{f, Baz, Bar}; | 328 | use foo::{Baz, Bar, f}; |
354 | 329 | ||
355 | fn qux(bar: Bar, baz: Baz) { | 330 | fn qux(bar: Bar, baz: Baz) { |
356 | f(); | 331 | f(); |
@@ -389,7 +364,7 @@ mod foo { | |||
389 | } | 364 | } |
390 | 365 | ||
391 | use foo::Bar; | 366 | use foo::Bar; |
392 | use foo::{f, Baz}; | 367 | use foo::{Baz, f}; |
393 | 368 | ||
394 | fn qux(bar: Bar, baz: Baz) { | 369 | fn qux(bar: Bar, baz: Baz) { |
395 | f(); | 370 | f(); |
@@ -439,7 +414,7 @@ mod foo { | |||
439 | } | 414 | } |
440 | } | 415 | } |
441 | 416 | ||
442 | use foo::{bar::{f, Baz, Bar}, baz::*}; | 417 | use foo::{bar::{Baz, Bar, f}, baz::*}; |
443 | 418 | ||
444 | fn qux(bar: Bar, baz: Baz) { | 419 | fn qux(bar: Bar, baz: Baz) { |
445 | f(); | 420 | f(); |
@@ -891,7 +866,7 @@ mod foo { | |||
891 | pub struct Bar; | 866 | pub struct Bar; |
892 | } | 867 | } |
893 | 868 | ||
894 | use foo::Bar; | 869 | use foo::{Bar}; |
895 | 870 | ||
896 | struct Baz { | 871 | struct Baz { |
897 | bar: Bar | 872 | bar: Bar |
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index b30652a9d..6311afc1f 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs | |||
@@ -10,18 +10,18 @@ use ide_db::{ | |||
10 | use itertools::Itertools; | 10 | use itertools::Itertools; |
11 | use stdx::format_to; | 11 | use stdx::format_to; |
12 | use syntax::{ | 12 | use syntax::{ |
13 | algo::SyntaxRewriter, | ||
14 | ast::{ | 13 | ast::{ |
15 | self, | 14 | self, |
16 | edit::{AstNodeEdit, IndentLevel}, | 15 | edit::{AstNodeEdit, IndentLevel}, |
17 | AstNode, | 16 | AstNode, |
18 | }, | 17 | }, |
18 | ted, | ||
19 | SyntaxKind::{self, BLOCK_EXPR, BREAK_EXPR, COMMENT, PATH_EXPR, RETURN_EXPR}, | 19 | SyntaxKind::{self, BLOCK_EXPR, BREAK_EXPR, COMMENT, PATH_EXPR, RETURN_EXPR}, |
20 | SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T, | 20 | SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | use crate::{ | 23 | use crate::{ |
24 | assist_context::{AssistContext, Assists}, | 24 | assist_context::{AssistContext, Assists, TreeMutator}, |
25 | AssistId, | 25 | AssistId, |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -956,10 +956,10 @@ fn format_replacement(ctx: &AssistContext, fun: &Function, indent: IndentLevel) | |||
956 | let args = fun.params.iter().map(|param| param.to_arg(ctx)); | 956 | let args = fun.params.iter().map(|param| param.to_arg(ctx)); |
957 | let args = make::arg_list(args); | 957 | let args = make::arg_list(args); |
958 | let call_expr = if fun.self_param.is_some() { | 958 | let call_expr = if fun.self_param.is_some() { |
959 | let self_arg = make::expr_path(make_path_from_text("self")); | 959 | let self_arg = make::expr_path(make::ext::ident_path("self")); |
960 | make::expr_method_call(self_arg, &fun.name, args) | 960 | make::expr_method_call(self_arg, &fun.name, args) |
961 | } else { | 961 | } else { |
962 | let func = make::expr_path(make_path_from_text(&fun.name)); | 962 | let func = make::expr_path(make::ext::ident_path(&fun.name)); |
963 | make::expr_call(func, args) | 963 | make::expr_call(func, args) |
964 | }; | 964 | }; |
965 | 965 | ||
@@ -1054,11 +1054,11 @@ impl FlowHandler { | |||
1054 | make::expr_if(condition, block, None) | 1054 | make::expr_if(condition, block, None) |
1055 | } | 1055 | } |
1056 | FlowHandler::IfOption { action } => { | 1056 | FlowHandler::IfOption { action } => { |
1057 | let path = make_path_from_text("Some"); | 1057 | let path = make::ext::ident_path("Some"); |
1058 | let value_pat = make::ident_pat(make::name("value")); | 1058 | let value_pat = make::ident_pat(make::name("value")); |
1059 | let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into())); | 1059 | let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into())); |
1060 | let cond = make::condition(call_expr, Some(pattern.into())); | 1060 | let cond = make::condition(call_expr, Some(pattern.into())); |
1061 | let value = make::expr_path(make_path_from_text("value")); | 1061 | let value = make::expr_path(make::ext::ident_path("value")); |
1062 | let action_expr = action.make_result_handler(Some(value)); | 1062 | let action_expr = action.make_result_handler(Some(value)); |
1063 | let action_stmt = make::expr_stmt(action_expr); | 1063 | let action_stmt = make::expr_stmt(action_expr); |
1064 | let then = make::block_expr(iter::once(action_stmt.into()), None); | 1064 | let then = make::block_expr(iter::once(action_stmt.into()), None); |
@@ -1068,14 +1068,14 @@ impl FlowHandler { | |||
1068 | let some_name = "value"; | 1068 | let some_name = "value"; |
1069 | 1069 | ||
1070 | let some_arm = { | 1070 | let some_arm = { |
1071 | let path = make_path_from_text("Some"); | 1071 | let path = make::ext::ident_path("Some"); |
1072 | let value_pat = make::ident_pat(make::name(some_name)); | 1072 | let value_pat = make::ident_pat(make::name(some_name)); |
1073 | let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); | 1073 | let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); |
1074 | let value = make::expr_path(make_path_from_text(some_name)); | 1074 | let value = make::expr_path(make::ext::ident_path(some_name)); |
1075 | make::match_arm(iter::once(pat.into()), value) | 1075 | make::match_arm(iter::once(pat.into()), value) |
1076 | }; | 1076 | }; |
1077 | let none_arm = { | 1077 | let none_arm = { |
1078 | let path = make_path_from_text("None"); | 1078 | let path = make::ext::ident_path("None"); |
1079 | let pat = make::path_pat(path); | 1079 | let pat = make::path_pat(path); |
1080 | make::match_arm(iter::once(pat), none.make_result_handler(None)) | 1080 | make::match_arm(iter::once(pat), none.make_result_handler(None)) |
1081 | }; | 1081 | }; |
@@ -1087,17 +1087,17 @@ impl FlowHandler { | |||
1087 | let err_name = "value"; | 1087 | let err_name = "value"; |
1088 | 1088 | ||
1089 | let ok_arm = { | 1089 | let ok_arm = { |
1090 | let path = make_path_from_text("Ok"); | 1090 | let path = make::ext::ident_path("Ok"); |
1091 | let value_pat = make::ident_pat(make::name(ok_name)); | 1091 | let value_pat = make::ident_pat(make::name(ok_name)); |
1092 | let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); | 1092 | let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); |
1093 | let value = make::expr_path(make_path_from_text(ok_name)); | 1093 | let value = make::expr_path(make::ext::ident_path(ok_name)); |
1094 | make::match_arm(iter::once(pat.into()), value) | 1094 | make::match_arm(iter::once(pat.into()), value) |
1095 | }; | 1095 | }; |
1096 | let err_arm = { | 1096 | let err_arm = { |
1097 | let path = make_path_from_text("Err"); | 1097 | let path = make::ext::ident_path("Err"); |
1098 | let value_pat = make::ident_pat(make::name(err_name)); | 1098 | let value_pat = make::ident_pat(make::name(err_name)); |
1099 | let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); | 1099 | let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); |
1100 | let value = make::expr_path(make_path_from_text(err_name)); | 1100 | let value = make::expr_path(make::ext::ident_path(err_name)); |
1101 | make::match_arm(iter::once(pat.into()), err.make_result_handler(Some(value))) | 1101 | make::match_arm(iter::once(pat.into()), err.make_result_handler(Some(value))) |
1102 | }; | 1102 | }; |
1103 | let arms = make::match_arm_list(vec![ok_arm, err_arm]); | 1103 | let arms = make::match_arm_list(vec![ok_arm, err_arm]); |
@@ -1107,13 +1107,9 @@ impl FlowHandler { | |||
1107 | } | 1107 | } |
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | fn make_path_from_text(text: &str) -> ast::Path { | ||
1111 | make::path_unqualified(make::path_segment(make::name_ref(text))) | ||
1112 | } | ||
1113 | |||
1114 | fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr { | 1110 | fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr { |
1115 | let name = var.name(ctx.db()).unwrap().to_string(); | 1111 | let name = var.name(ctx.db()).unwrap().to_string(); |
1116 | make::expr_path(make_path_from_text(&name)) | 1112 | make::expr_path(make::ext::ident_path(&name)) |
1117 | } | 1113 | } |
1118 | 1114 | ||
1119 | fn format_function( | 1115 | fn format_function( |
@@ -1179,7 +1175,7 @@ fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Opti | |||
1179 | fun_ty.make_ty(ctx, module) | 1175 | fun_ty.make_ty(ctx, module) |
1180 | } | 1176 | } |
1181 | FlowHandler::Try { kind: TryKind::Option } => { | 1177 | FlowHandler::Try { kind: TryKind::Option } => { |
1182 | make::ty_generic(make::name_ref("Option"), iter::once(fun_ty.make_ty(ctx, module))) | 1178 | make::ext::ty_option(fun_ty.make_ty(ctx, module)) |
1183 | } | 1179 | } |
1184 | FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => { | 1180 | FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => { |
1185 | let handler_ty = parent_ret_ty | 1181 | let handler_ty = parent_ret_ty |
@@ -1187,29 +1183,21 @@ fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Opti | |||
1187 | .nth(1) | 1183 | .nth(1) |
1188 | .map(|ty| make_ty(&ty, ctx, module)) | 1184 | .map(|ty| make_ty(&ty, ctx, module)) |
1189 | .unwrap_or_else(make::ty_unit); | 1185 | .unwrap_or_else(make::ty_unit); |
1190 | make::ty_generic( | 1186 | make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty) |
1191 | make::name_ref("Result"), | ||
1192 | vec![fun_ty.make_ty(ctx, module), handler_ty], | ||
1193 | ) | ||
1194 | } | 1187 | } |
1195 | FlowHandler::If { .. } => make::ty("bool"), | 1188 | FlowHandler::If { .. } => make::ext::ty_bool(), |
1196 | FlowHandler::IfOption { action } => { | 1189 | FlowHandler::IfOption { action } => { |
1197 | let handler_ty = action | 1190 | let handler_ty = action |
1198 | .expr_ty(ctx) | 1191 | .expr_ty(ctx) |
1199 | .map(|ty| make_ty(&ty, ctx, module)) | 1192 | .map(|ty| make_ty(&ty, ctx, module)) |
1200 | .unwrap_or_else(make::ty_unit); | 1193 | .unwrap_or_else(make::ty_unit); |
1201 | make::ty_generic(make::name_ref("Option"), iter::once(handler_ty)) | 1194 | make::ext::ty_option(handler_ty) |
1202 | } | ||
1203 | FlowHandler::MatchOption { .. } => { | ||
1204 | make::ty_generic(make::name_ref("Option"), iter::once(fun_ty.make_ty(ctx, module))) | ||
1205 | } | 1195 | } |
1196 | FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)), | ||
1206 | FlowHandler::MatchResult { err } => { | 1197 | FlowHandler::MatchResult { err } => { |
1207 | let handler_ty = | 1198 | let handler_ty = |
1208 | err.expr_ty(ctx).map(|ty| make_ty(&ty, ctx, module)).unwrap_or_else(make::ty_unit); | 1199 | err.expr_ty(ctx).map(|ty| make_ty(&ty, ctx, module)).unwrap_or_else(make::ty_unit); |
1209 | make::ty_generic( | 1200 | make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty) |
1210 | make::name_ref("Result"), | ||
1211 | vec![fun_ty.make_ty(ctx, module), handler_ty], | ||
1212 | ) | ||
1213 | } | 1201 | } |
1214 | }; | 1202 | }; |
1215 | Some(make::ret_type(ret_ty)) | 1203 | Some(make::ret_type(ret_ty)) |
@@ -1296,7 +1284,7 @@ fn make_body( | |||
1296 | TryKind::Option => "Some", | 1284 | TryKind::Option => "Some", |
1297 | TryKind::Result { .. } => "Ok", | 1285 | TryKind::Result { .. } => "Ok", |
1298 | }; | 1286 | }; |
1299 | let func = make::expr_path(make_path_from_text(constructor)); | 1287 | let func = make::expr_path(make::ext::ident_path(constructor)); |
1300 | let args = make::arg_list(iter::once(tail_expr)); | 1288 | let args = make::arg_list(iter::once(tail_expr)); |
1301 | make::expr_call(func, args) | 1289 | make::expr_call(func, args) |
1302 | }) | 1290 | }) |
@@ -1306,16 +1294,16 @@ fn make_body( | |||
1306 | with_tail_expr(block, lit_false.into()) | 1294 | with_tail_expr(block, lit_false.into()) |
1307 | } | 1295 | } |
1308 | FlowHandler::IfOption { .. } => { | 1296 | FlowHandler::IfOption { .. } => { |
1309 | let none = make::expr_path(make_path_from_text("None")); | 1297 | let none = make::expr_path(make::ext::ident_path("None")); |
1310 | with_tail_expr(block, none) | 1298 | with_tail_expr(block, none) |
1311 | } | 1299 | } |
1312 | FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| { | 1300 | FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| { |
1313 | let some = make::expr_path(make_path_from_text("Some")); | 1301 | let some = make::expr_path(make::ext::ident_path("Some")); |
1314 | let args = make::arg_list(iter::once(tail_expr)); | 1302 | let args = make::arg_list(iter::once(tail_expr)); |
1315 | make::expr_call(some, args) | 1303 | make::expr_call(some, args) |
1316 | }), | 1304 | }), |
1317 | FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| { | 1305 | FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| { |
1318 | let ok = make::expr_path(make_path_from_text("Ok")); | 1306 | let ok = make::expr_path(make::ext::ident_path("Ok")); |
1319 | let args = make::arg_list(iter::once(tail_expr)); | 1307 | let args = make::arg_list(iter::once(tail_expr)); |
1320 | make::expr_call(ok, args) | 1308 | make::expr_call(ok, args) |
1321 | }), | 1309 | }), |
@@ -1361,12 +1349,16 @@ fn rewrite_body_segment( | |||
1361 | syntax: &SyntaxNode, | 1349 | syntax: &SyntaxNode, |
1362 | ) -> SyntaxNode { | 1350 | ) -> SyntaxNode { |
1363 | let syntax = fix_param_usages(ctx, params, syntax); | 1351 | let syntax = fix_param_usages(ctx, params, syntax); |
1364 | update_external_control_flow(handler, &syntax) | 1352 | update_external_control_flow(handler, &syntax); |
1353 | syntax | ||
1365 | } | 1354 | } |
1366 | 1355 | ||
1367 | /// change all usages to account for added `&`/`&mut` for some params | 1356 | /// change all usages to account for added `&`/`&mut` for some params |
1368 | fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode { | 1357 | fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode { |
1369 | let mut rewriter = SyntaxRewriter::default(); | 1358 | let mut usages_for_param: Vec<(&Param, Vec<ast::Expr>)> = Vec::new(); |
1359 | |||
1360 | let tm = TreeMutator::new(syntax); | ||
1361 | |||
1370 | for param in params { | 1362 | for param in params { |
1371 | if !param.kind().is_ref() { | 1363 | if !param.kind().is_ref() { |
1372 | continue; | 1364 | continue; |
@@ -1376,101 +1368,100 @@ fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) | |||
1376 | let usages = usages | 1368 | let usages = usages |
1377 | .iter() | 1369 | .iter() |
1378 | .filter(|reference| syntax.text_range().contains_range(reference.range)) | 1370 | .filter(|reference| syntax.text_range().contains_range(reference.range)) |
1379 | .filter_map(|reference| path_element_of_reference(syntax, reference)); | 1371 | .filter_map(|reference| path_element_of_reference(syntax, reference)) |
1380 | for path in usages { | 1372 | .map(|expr| tm.make_mut(&expr)); |
1381 | match path.syntax().ancestors().skip(1).find_map(ast::Expr::cast) { | 1373 | |
1374 | usages_for_param.push((param, usages.collect())); | ||
1375 | } | ||
1376 | |||
1377 | let res = tm.make_syntax_mut(syntax); | ||
1378 | |||
1379 | for (param, usages) in usages_for_param { | ||
1380 | for usage in usages { | ||
1381 | match usage.syntax().ancestors().skip(1).find_map(ast::Expr::cast) { | ||
1382 | Some(ast::Expr::MethodCallExpr(_)) | Some(ast::Expr::FieldExpr(_)) => { | 1382 | Some(ast::Expr::MethodCallExpr(_)) | Some(ast::Expr::FieldExpr(_)) => { |
1383 | // do nothing | 1383 | // do nothing |
1384 | } | 1384 | } |
1385 | Some(ast::Expr::RefExpr(node)) | 1385 | Some(ast::Expr::RefExpr(node)) |
1386 | if param.kind() == ParamKind::MutRef && node.mut_token().is_some() => | 1386 | if param.kind() == ParamKind::MutRef && node.mut_token().is_some() => |
1387 | { | 1387 | { |
1388 | rewriter.replace_ast(&node.clone().into(), &node.expr().unwrap()); | 1388 | ted::replace(node.syntax(), node.expr().unwrap().syntax()); |
1389 | } | 1389 | } |
1390 | Some(ast::Expr::RefExpr(node)) | 1390 | Some(ast::Expr::RefExpr(node)) |
1391 | if param.kind() == ParamKind::SharedRef && node.mut_token().is_none() => | 1391 | if param.kind() == ParamKind::SharedRef && node.mut_token().is_none() => |
1392 | { | 1392 | { |
1393 | rewriter.replace_ast(&node.clone().into(), &node.expr().unwrap()); | 1393 | ted::replace(node.syntax(), node.expr().unwrap().syntax()); |
1394 | } | 1394 | } |
1395 | Some(_) | None => { | 1395 | Some(_) | None => { |
1396 | rewriter.replace_ast(&path, &make::expr_prefix(T![*], path.clone())); | 1396 | let p = &make::expr_prefix(T![*], usage.clone()).clone_for_update(); |
1397 | ted::replace(usage.syntax(), p.syntax()) | ||
1397 | } | 1398 | } |
1398 | }; | 1399 | } |
1399 | } | 1400 | } |
1400 | } | 1401 | } |
1401 | 1402 | ||
1402 | rewriter.rewrite(syntax) | 1403 | res |
1403 | } | 1404 | } |
1404 | 1405 | ||
1405 | fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) -> SyntaxNode { | 1406 | fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) { |
1406 | let mut rewriter = SyntaxRewriter::default(); | ||
1407 | |||
1408 | let mut nested_loop = None; | 1407 | let mut nested_loop = None; |
1409 | let mut nested_scope = None; | 1408 | let mut nested_scope = None; |
1410 | for event in syntax.preorder() { | 1409 | for event in syntax.preorder() { |
1411 | let node = match event { | 1410 | match event { |
1412 | WalkEvent::Enter(e) => { | 1411 | WalkEvent::Enter(e) => match e.kind() { |
1413 | match e.kind() { | 1412 | SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => { |
1414 | SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => { | 1413 | if nested_loop.is_none() { |
1415 | if nested_loop.is_none() { | 1414 | nested_loop = Some(e.clone()); |
1416 | nested_loop = Some(e.clone()); | ||
1417 | } | ||
1418 | } | 1415 | } |
1419 | SyntaxKind::FN | 1416 | } |
1420 | | SyntaxKind::CONST | 1417 | SyntaxKind::FN |
1421 | | SyntaxKind::STATIC | 1418 | | SyntaxKind::CONST |
1422 | | SyntaxKind::IMPL | 1419 | | SyntaxKind::STATIC |
1423 | | SyntaxKind::MODULE => { | 1420 | | SyntaxKind::IMPL |
1424 | if nested_scope.is_none() { | 1421 | | SyntaxKind::MODULE => { |
1425 | nested_scope = Some(e.clone()); | 1422 | if nested_scope.is_none() { |
1426 | } | 1423 | nested_scope = Some(e.clone()); |
1427 | } | 1424 | } |
1428 | _ => {} | ||
1429 | } | 1425 | } |
1430 | e | 1426 | _ => {} |
1431 | } | 1427 | }, |
1432 | WalkEvent::Leave(e) => { | 1428 | WalkEvent::Leave(e) => { |
1429 | if nested_scope.is_none() { | ||
1430 | if let Some(expr) = ast::Expr::cast(e.clone()) { | ||
1431 | match expr { | ||
1432 | ast::Expr::ReturnExpr(return_expr) if nested_scope.is_none() => { | ||
1433 | let expr = return_expr.expr(); | ||
1434 | if let Some(replacement) = make_rewritten_flow(handler, expr) { | ||
1435 | ted::replace(return_expr.syntax(), replacement.syntax()) | ||
1436 | } | ||
1437 | } | ||
1438 | ast::Expr::BreakExpr(break_expr) if nested_loop.is_none() => { | ||
1439 | let expr = break_expr.expr(); | ||
1440 | if let Some(replacement) = make_rewritten_flow(handler, expr) { | ||
1441 | ted::replace(break_expr.syntax(), replacement.syntax()) | ||
1442 | } | ||
1443 | } | ||
1444 | ast::Expr::ContinueExpr(continue_expr) if nested_loop.is_none() => { | ||
1445 | if let Some(replacement) = make_rewritten_flow(handler, None) { | ||
1446 | ted::replace(continue_expr.syntax(), replacement.syntax()) | ||
1447 | } | ||
1448 | } | ||
1449 | _ => { | ||
1450 | // do nothing | ||
1451 | } | ||
1452 | } | ||
1453 | } | ||
1454 | } | ||
1455 | |||
1433 | if nested_loop.as_ref() == Some(&e) { | 1456 | if nested_loop.as_ref() == Some(&e) { |
1434 | nested_loop = None; | 1457 | nested_loop = None; |
1435 | } | 1458 | } |
1436 | if nested_scope.as_ref() == Some(&e) { | 1459 | if nested_scope.as_ref() == Some(&e) { |
1437 | nested_scope = None; | 1460 | nested_scope = None; |
1438 | } | 1461 | } |
1439 | continue; | ||
1440 | } | 1462 | } |
1441 | }; | 1463 | }; |
1442 | if nested_scope.is_some() { | ||
1443 | continue; | ||
1444 | } | ||
1445 | let expr = match ast::Expr::cast(node) { | ||
1446 | Some(e) => e, | ||
1447 | None => continue, | ||
1448 | }; | ||
1449 | match expr { | ||
1450 | ast::Expr::ReturnExpr(return_expr) if nested_scope.is_none() => { | ||
1451 | let expr = return_expr.expr(); | ||
1452 | if let Some(replacement) = make_rewritten_flow(handler, expr) { | ||
1453 | rewriter.replace_ast(&return_expr.into(), &replacement); | ||
1454 | } | ||
1455 | } | ||
1456 | ast::Expr::BreakExpr(break_expr) if nested_loop.is_none() => { | ||
1457 | let expr = break_expr.expr(); | ||
1458 | if let Some(replacement) = make_rewritten_flow(handler, expr) { | ||
1459 | rewriter.replace_ast(&break_expr.into(), &replacement); | ||
1460 | } | ||
1461 | } | ||
1462 | ast::Expr::ContinueExpr(continue_expr) if nested_loop.is_none() => { | ||
1463 | if let Some(replacement) = make_rewritten_flow(handler, None) { | ||
1464 | rewriter.replace_ast(&continue_expr.into(), &replacement); | ||
1465 | } | ||
1466 | } | ||
1467 | _ => { | ||
1468 | // do nothing | ||
1469 | } | ||
1470 | } | ||
1471 | } | 1464 | } |
1472 | |||
1473 | rewriter.rewrite(syntax) | ||
1474 | } | 1465 | } |
1475 | 1466 | ||
1476 | fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> { | 1467 | fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> { |
@@ -1480,16 +1471,16 @@ fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Op | |||
1480 | FlowHandler::IfOption { .. } => { | 1471 | FlowHandler::IfOption { .. } => { |
1481 | let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); | 1472 | let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); |
1482 | let args = make::arg_list(iter::once(expr)); | 1473 | let args = make::arg_list(iter::once(expr)); |
1483 | make::expr_call(make::expr_path(make_path_from_text("Some")), args) | 1474 | make::expr_call(make::expr_path(make::ext::ident_path("Some")), args) |
1484 | } | 1475 | } |
1485 | FlowHandler::MatchOption { .. } => make::expr_path(make_path_from_text("None")), | 1476 | FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")), |
1486 | FlowHandler::MatchResult { .. } => { | 1477 | FlowHandler::MatchResult { .. } => { |
1487 | let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); | 1478 | let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); |
1488 | let args = make::arg_list(iter::once(expr)); | 1479 | let args = make::arg_list(iter::once(expr)); |
1489 | make::expr_call(make::expr_path(make_path_from_text("Err")), args) | 1480 | make::expr_call(make::expr_path(make::ext::ident_path("Err")), args) |
1490 | } | 1481 | } |
1491 | }; | 1482 | }; |
1492 | Some(make::expr_return(Some(value))) | 1483 | Some(make::expr_return(Some(value)).clone_for_update()) |
1493 | } | 1484 | } |
1494 | 1485 | ||
1495 | #[cfg(test)] | 1486 | #[cfg(test)] |
diff --git a/crates/ide_assists/src/handlers/extract_variable.rs b/crates/ide_assists/src/handlers/extract_variable.rs index 136b9a55b..ae084c86c 100644 --- a/crates/ide_assists/src/handlers/extract_variable.rs +++ b/crates/ide_assists/src/handlers/extract_variable.rs | |||
@@ -54,7 +54,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
54 | 54 | ||
55 | let var_name = match &field_shorthand { | 55 | let var_name = match &field_shorthand { |
56 | Some(it) => it.to_string(), | 56 | Some(it) => it.to_string(), |
57 | None => suggest_name::variable(&to_extract, &ctx.sema), | 57 | None => suggest_name::for_variable(&to_extract, &ctx.sema), |
58 | }; | 58 | }; |
59 | let expr_range = match &field_shorthand { | 59 | let expr_range = match &field_shorthand { |
60 | Some(it) => it.syntax().text_range().cover(to_extract.syntax().text_range()), | 60 | Some(it) => it.syntax().text_range().cover(to_extract.syntax().text_range()), |
diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs index 6f95b1a07..bc9fc524b 100644 --- a/crates/ide_assists/src/handlers/generate_function.rs +++ b/crates/ide_assists/src/handlers/generate_function.rs | |||
@@ -175,7 +175,7 @@ impl FunctionBuilder { | |||
175 | } | 175 | } |
176 | 176 | ||
177 | fn render(self) -> FunctionTemplate { | 177 | fn render(self) -> FunctionTemplate { |
178 | let placeholder_expr = make::expr_todo(); | 178 | let placeholder_expr = make::ext::expr_todo(); |
179 | let fn_body = make::block_expr(vec![], Some(placeholder_expr)); | 179 | let fn_body = make::block_expr(vec![], Some(placeholder_expr)); |
180 | let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None }; | 180 | let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None }; |
181 | let mut fn_def = make::fn_( | 181 | let mut fn_def = make::fn_( |
diff --git a/crates/ide_assists/src/handlers/introduce_named_lifetime.rs b/crates/ide_assists/src/handlers/introduce_named_lifetime.rs index 9f4f71d6c..68bc15120 100644 --- a/crates/ide_assists/src/handlers/introduce_named_lifetime.rs +++ b/crates/ide_assists/src/handlers/introduce_named_lifetime.rs | |||
@@ -89,14 +89,12 @@ fn generate_fn_def_assist( | |||
89 | let loc_needing_lifetime = | 89 | let loc_needing_lifetime = |
90 | loc_needing_lifetime.and_then(|it| it.make_mut(builder).to_position()); | 90 | loc_needing_lifetime.and_then(|it| it.make_mut(builder).to_position()); |
91 | 91 | ||
92 | add_lifetime_param(fn_def.get_or_create_generic_param_list(), new_lifetime_param); | 92 | fn_def.get_or_create_generic_param_list().add_generic_param( |
93 | ted::replace( | 93 | make::lifetime_param(new_lifetime_param.clone()).clone_for_update().into(), |
94 | lifetime.syntax(), | ||
95 | make_ast_lifetime(new_lifetime_param).clone_for_update().syntax(), | ||
96 | ); | 94 | ); |
97 | loc_needing_lifetime.map(|position| { | 95 | ted::replace(lifetime.syntax(), new_lifetime_param.clone_for_update().syntax()); |
98 | ted::insert(position, make_ast_lifetime(new_lifetime_param).clone_for_update().syntax()) | 96 | loc_needing_lifetime |
99 | }); | 97 | .map(|position| ted::insert(position, new_lifetime_param.clone_for_update().syntax())); |
100 | }) | 98 | }) |
101 | } | 99 | } |
102 | 100 | ||
@@ -112,11 +110,10 @@ fn generate_impl_def_assist( | |||
112 | let impl_def = builder.make_ast_mut(impl_def); | 110 | let impl_def = builder.make_ast_mut(impl_def); |
113 | let lifetime = builder.make_ast_mut(lifetime); | 111 | let lifetime = builder.make_ast_mut(lifetime); |
114 | 112 | ||
115 | add_lifetime_param(impl_def.get_or_create_generic_param_list(), new_lifetime_param); | 113 | impl_def.get_or_create_generic_param_list().add_generic_param( |
116 | ted::replace( | 114 | make::lifetime_param(new_lifetime_param.clone()).clone_for_update().into(), |
117 | lifetime.syntax(), | ||
118 | make_ast_lifetime(new_lifetime_param).clone_for_update().syntax(), | ||
119 | ); | 115 | ); |
116 | ted::replace(lifetime.syntax(), new_lifetime_param.clone_for_update().syntax()); | ||
120 | }) | 117 | }) |
121 | } | 118 | } |
122 | 119 | ||
@@ -124,31 +121,16 @@ fn generate_impl_def_assist( | |||
124 | /// which is not in the list | 121 | /// which is not in the list |
125 | fn generate_unique_lifetime_param_name( | 122 | fn generate_unique_lifetime_param_name( |
126 | existing_type_param_list: Option<ast::GenericParamList>, | 123 | existing_type_param_list: Option<ast::GenericParamList>, |
127 | ) -> Option<char> { | 124 | ) -> Option<ast::Lifetime> { |
128 | match existing_type_param_list { | 125 | match existing_type_param_list { |
129 | Some(type_params) => { | 126 | Some(type_params) => { |
130 | let used_lifetime_params: FxHashSet<_> = type_params | 127 | let used_lifetime_params: FxHashSet<_> = |
131 | .lifetime_params() | 128 | type_params.lifetime_params().map(|p| p.syntax().text().to_string()).collect(); |
132 | .map(|p| p.syntax().text().to_string()[1..].to_owned()) | 129 | ('a'..='z').map(|it| format!("'{}", it)).find(|it| !used_lifetime_params.contains(it)) |
133 | .collect(); | ||
134 | (b'a'..=b'z').map(char::from).find(|c| !used_lifetime_params.contains(&c.to_string())) | ||
135 | } | 130 | } |
136 | None => Some('a'), | 131 | None => Some("'a".to_string()), |
137 | } | 132 | } |
138 | } | 133 | .map(|it| make::lifetime(&it)) |
139 | |||
140 | fn add_lifetime_param(type_params: ast::GenericParamList, new_lifetime_param: char) { | ||
141 | let generic_param = | ||
142 | make::generic_param(format!("'{}", new_lifetime_param), None).clone_for_update(); | ||
143 | type_params.add_generic_param(generic_param); | ||
144 | } | ||
145 | |||
146 | fn make_ast_lifetime(new_lifetime_param: char) -> ast::Lifetime { | ||
147 | make::generic_param(format!("'{}", new_lifetime_param), None) | ||
148 | .syntax() | ||
149 | .descendants() | ||
150 | .find_map(ast::Lifetime::cast) | ||
151 | .unwrap() | ||
152 | } | 134 | } |
153 | 135 | ||
154 | enum NeedsLifetime { | 136 | enum NeedsLifetime { |
diff --git a/crates/ide_assists/src/handlers/merge_imports.rs b/crates/ide_assists/src/handlers/merge_imports.rs index add7b8e37..3cd090737 100644 --- a/crates/ide_assists/src/handlers/merge_imports.rs +++ b/crates/ide_assists/src/handlers/merge_imports.rs | |||
@@ -27,14 +27,14 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
27 | if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) { | 27 | if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) { |
28 | let (merged, to_remove) = | 28 | let (merged, to_remove) = |
29 | next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| { | 29 | next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| { |
30 | try_merge_imports(&use_item, &use_item2, MergeBehavior::Full).zip(Some(use_item2)) | 30 | try_merge_imports(&use_item, &use_item2, MergeBehavior::Crate).zip(Some(use_item2)) |
31 | })?; | 31 | })?; |
32 | 32 | ||
33 | imports = Some((use_item, merged, to_remove)); | 33 | imports = Some((use_item, merged, to_remove)); |
34 | } else { | 34 | } else { |
35 | let (merged, to_remove) = | 35 | let (merged, to_remove) = |
36 | next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| { | 36 | next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| { |
37 | try_merge_trees(&tree, &use_tree, MergeBehavior::Full).zip(Some(use_tree)) | 37 | try_merge_trees(&tree, &use_tree, MergeBehavior::Crate).zip(Some(use_tree)) |
38 | })?; | 38 | })?; |
39 | 39 | ||
40 | uses = Some((tree.clone(), merged, to_remove)) | 40 | uses = Some((tree.clone(), merged, to_remove)) |
diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs index 011a28d44..fa3f76609 100644 --- a/crates/ide_assists/src/handlers/move_bounds.rs +++ b/crates/ide_assists/src/handlers/move_bounds.rs | |||
@@ -63,11 +63,7 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext | |||
63 | } | 63 | } |
64 | 64 | ||
65 | fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> { | 65 | fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> { |
66 | let path = { | 66 | let path = make::ext::ident_path(¶m.name()?.syntax().to_string()); |
67 | let name_ref = make::name_ref(¶m.name()?.syntax().to_string()); | ||
68 | let segment = make::path_segment(name_ref); | ||
69 | make::path_unqualified(segment) | ||
70 | }; | ||
71 | let predicate = make::where_pred(path, param.type_bound_list()?.bounds()); | 67 | let predicate = make::where_pred(path, param.type_bound_list()?.bounds()); |
72 | Some(predicate.clone_for_update()) | 68 | Some(predicate.clone_for_update()) |
73 | } | 69 | } |
diff --git a/crates/ide_assists/src/handlers/pull_assignment_up.rs b/crates/ide_assists/src/handlers/pull_assignment_up.rs index 04bae4e58..3128faa68 100644 --- a/crates/ide_assists/src/handlers/pull_assignment_up.rs +++ b/crates/ide_assists/src/handlers/pull_assignment_up.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use syntax::{ | 1 | use syntax::{ |
2 | ast::{self, edit::AstNodeEdit, make}, | 2 | ast::{self, make}, |
3 | AstNode, | 3 | ted, AstNode, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
@@ -37,103 +37,120 @@ use crate::{ | |||
37 | // ``` | 37 | // ``` |
38 | pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 38 | pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
39 | let assign_expr = ctx.find_node_at_offset::<ast::BinExpr>()?; | 39 | let assign_expr = ctx.find_node_at_offset::<ast::BinExpr>()?; |
40 | let name_expr = if assign_expr.op_kind()? == ast::BinOp::Assignment { | 40 | |
41 | assign_expr.lhs()? | 41 | let op_kind = assign_expr.op_kind()?; |
42 | } else { | 42 | if op_kind != ast::BinOp::Assignment { |
43 | cov_mark::hit!(test_cant_pull_non_assignments); | ||
43 | return None; | 44 | return None; |
45 | } | ||
46 | |||
47 | let mut collector = AssignmentsCollector { | ||
48 | sema: &ctx.sema, | ||
49 | common_lhs: assign_expr.lhs()?, | ||
50 | assignments: Vec::new(), | ||
44 | }; | 51 | }; |
45 | 52 | ||
46 | let (old_stmt, new_stmt) = if let Some(if_expr) = ctx.find_node_at_offset::<ast::IfExpr>() { | 53 | let tgt: ast::Expr = if let Some(if_expr) = ctx.find_node_at_offset::<ast::IfExpr>() { |
47 | ( | 54 | collector.collect_if(&if_expr)?; |
48 | ast::Expr::cast(if_expr.syntax().to_owned())?, | 55 | if_expr.into() |
49 | exprify_if(&if_expr, &ctx.sema, &name_expr)?.indent(if_expr.indent_level()), | ||
50 | ) | ||
51 | } else if let Some(match_expr) = ctx.find_node_at_offset::<ast::MatchExpr>() { | 56 | } else if let Some(match_expr) = ctx.find_node_at_offset::<ast::MatchExpr>() { |
52 | ( | 57 | collector.collect_match(&match_expr)?; |
53 | ast::Expr::cast(match_expr.syntax().to_owned())?, | 58 | match_expr.into() |
54 | exprify_match(&match_expr, &ctx.sema, &name_expr)?, | ||
55 | ) | ||
56 | } else { | 59 | } else { |
57 | return None; | 60 | return None; |
58 | }; | 61 | }; |
59 | 62 | ||
60 | let expr_stmt = make::expr_stmt(new_stmt); | 63 | if let Some(parent) = tgt.syntax().parent() { |
64 | if matches!(parent.kind(), syntax::SyntaxKind::BIN_EXPR | syntax::SyntaxKind::LET_STMT) { | ||
65 | return None; | ||
66 | } | ||
67 | } | ||
61 | 68 | ||
62 | acc.add( | 69 | acc.add( |
63 | AssistId("pull_assignment_up", AssistKind::RefactorExtract), | 70 | AssistId("pull_assignment_up", AssistKind::RefactorExtract), |
64 | "Pull assignment up", | 71 | "Pull assignment up", |
65 | old_stmt.syntax().text_range(), | 72 | tgt.syntax().text_range(), |
66 | move |edit| { | 73 | move |edit| { |
67 | edit.replace(old_stmt.syntax().text_range(), format!("{} = {};", name_expr, expr_stmt)); | 74 | let assignments: Vec<_> = collector |
75 | .assignments | ||
76 | .into_iter() | ||
77 | .map(|(stmt, rhs)| (edit.make_ast_mut(stmt), rhs.clone_for_update())) | ||
78 | .collect(); | ||
79 | |||
80 | let tgt = edit.make_ast_mut(tgt); | ||
81 | |||
82 | for (stmt, rhs) in assignments { | ||
83 | let mut stmt = stmt.syntax().clone(); | ||
84 | if let Some(parent) = stmt.parent() { | ||
85 | if ast::ExprStmt::cast(parent.clone()).is_some() { | ||
86 | stmt = parent.clone(); | ||
87 | } | ||
88 | } | ||
89 | ted::replace(stmt, rhs.syntax()); | ||
90 | } | ||
91 | let assign_expr = make::expr_assignment(collector.common_lhs, tgt.clone()); | ||
92 | let assign_stmt = make::expr_stmt(assign_expr); | ||
93 | |||
94 | ted::replace(tgt.syntax(), assign_stmt.syntax().clone_for_update()); | ||
68 | }, | 95 | }, |
69 | ) | 96 | ) |
70 | } | 97 | } |
71 | 98 | ||
72 | fn exprify_match( | 99 | struct AssignmentsCollector<'a> { |
73 | match_expr: &ast::MatchExpr, | 100 | sema: &'a hir::Semantics<'a, ide_db::RootDatabase>, |
74 | sema: &hir::Semantics<ide_db::RootDatabase>, | 101 | common_lhs: ast::Expr, |
75 | name: &ast::Expr, | 102 | assignments: Vec<(ast::BinExpr, ast::Expr)>, |
76 | ) -> Option<ast::Expr> { | 103 | } |
77 | let new_arm_list = match_expr | 104 | |
78 | .match_arm_list()? | 105 | impl<'a> AssignmentsCollector<'a> { |
79 | .arms() | 106 | fn collect_match(&mut self, match_expr: &ast::MatchExpr) -> Option<()> { |
80 | .map(|arm| { | 107 | for arm in match_expr.match_arm_list()?.arms() { |
81 | if let ast::Expr::BlockExpr(block) = arm.expr()? { | 108 | match arm.expr()? { |
82 | let new_block = exprify_block(&block, sema, name)?.indent(block.indent_level()); | 109 | ast::Expr::BlockExpr(block) => self.collect_block(&block)?, |
83 | Some(arm.replace_descendant(block, new_block)) | 110 | ast::Expr::BinExpr(expr) => self.collect_expr(&expr)?, |
111 | _ => return None, | ||
112 | } | ||
113 | } | ||
114 | |||
115 | Some(()) | ||
116 | } | ||
117 | fn collect_if(&mut self, if_expr: &ast::IfExpr) -> Option<()> { | ||
118 | let then_branch = if_expr.then_branch()?; | ||
119 | self.collect_block(&then_branch)?; | ||
120 | |||
121 | match if_expr.else_branch()? { | ||
122 | ast::ElseBranch::Block(block) => self.collect_block(&block), | ||
123 | ast::ElseBranch::IfExpr(expr) => { | ||
124 | cov_mark::hit!(test_pull_assignment_up_chained_if); | ||
125 | self.collect_if(&expr) | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | fn collect_block(&mut self, block: &ast::BlockExpr) -> Option<()> { | ||
130 | let last_expr = block.tail_expr().or_else(|| { | ||
131 | if let ast::Stmt::ExprStmt(stmt) = block.statements().last()? { | ||
132 | stmt.expr() | ||
84 | } else { | 133 | } else { |
85 | None | 134 | None |
86 | } | 135 | } |
87 | }) | 136 | })?; |
88 | .collect::<Option<Vec<_>>>()?; | ||
89 | let new_arm_list = match_expr | ||
90 | .match_arm_list()? | ||
91 | .replace_descendants(match_expr.match_arm_list()?.arms().zip(new_arm_list)); | ||
92 | Some(make::expr_match(match_expr.expr()?, new_arm_list)) | ||
93 | } | ||
94 | 137 | ||
95 | fn exprify_if( | 138 | if let ast::Expr::BinExpr(expr) = last_expr { |
96 | statement: &ast::IfExpr, | 139 | return self.collect_expr(&expr); |
97 | sema: &hir::Semantics<ide_db::RootDatabase>, | ||
98 | name: &ast::Expr, | ||
99 | ) -> Option<ast::Expr> { | ||
100 | let then_branch = exprify_block(&statement.then_branch()?, sema, name)?; | ||
101 | let else_branch = match statement.else_branch()? { | ||
102 | ast::ElseBranch::Block(ref block) => { | ||
103 | ast::ElseBranch::Block(exprify_block(block, sema, name)?) | ||
104 | } | ||
105 | ast::ElseBranch::IfExpr(expr) => { | ||
106 | cov_mark::hit!(test_pull_assignment_up_chained_if); | ||
107 | ast::ElseBranch::IfExpr(ast::IfExpr::cast( | ||
108 | exprify_if(&expr, sema, name)?.syntax().to_owned(), | ||
109 | )?) | ||
110 | } | 140 | } |
111 | }; | ||
112 | Some(make::expr_if(statement.condition()?, then_branch, Some(else_branch))) | ||
113 | } | ||
114 | 141 | ||
115 | fn exprify_block( | 142 | None |
116 | block: &ast::BlockExpr, | ||
117 | sema: &hir::Semantics<ide_db::RootDatabase>, | ||
118 | name: &ast::Expr, | ||
119 | ) -> Option<ast::BlockExpr> { | ||
120 | if block.tail_expr().is_some() { | ||
121 | return None; | ||
122 | } | 143 | } |
123 | 144 | ||
124 | let mut stmts: Vec<_> = block.statements().collect(); | 145 | fn collect_expr(&mut self, expr: &ast::BinExpr) -> Option<()> { |
125 | let stmt = stmts.pop()?; | 146 | if expr.op_kind()? == ast::BinOp::Assignment |
126 | 147 | && is_equivalent(self.sema, &expr.lhs()?, &self.common_lhs) | |
127 | if let ast::Stmt::ExprStmt(stmt) = stmt { | 148 | { |
128 | if let ast::Expr::BinExpr(expr) = stmt.expr()? { | 149 | self.assignments.push((expr.clone(), expr.rhs()?)); |
129 | if expr.op_kind()? == ast::BinOp::Assignment && is_equivalent(sema, &expr.lhs()?, name) | 150 | return Some(()); |
130 | { | ||
131 | // The last statement in the block is an assignment to the name we want | ||
132 | return Some(make::block_expr(stmts, Some(expr.rhs()?))); | ||
133 | } | ||
134 | } | 151 | } |
152 | None | ||
135 | } | 153 | } |
136 | None | ||
137 | } | 154 | } |
138 | 155 | ||
139 | fn is_equivalent( | 156 | fn is_equivalent( |
@@ -243,6 +260,37 @@ fn foo() { | |||
243 | } | 260 | } |
244 | 261 | ||
245 | #[test] | 262 | #[test] |
263 | fn test_pull_assignment_up_assignment_expressions() { | ||
264 | check_assist( | ||
265 | pull_assignment_up, | ||
266 | r#" | ||
267 | fn foo() { | ||
268 | let mut a = 1; | ||
269 | |||
270 | match 1 { | ||
271 | 1 => { $0a = 2; }, | ||
272 | 2 => a = 3, | ||
273 | 3 => { | ||
274 | a = 4 | ||
275 | } | ||
276 | } | ||
277 | }"#, | ||
278 | r#" | ||
279 | fn foo() { | ||
280 | let mut a = 1; | ||
281 | |||
282 | a = match 1 { | ||
283 | 1 => { 2 }, | ||
284 | 2 => 3, | ||
285 | 3 => { | ||
286 | 4 | ||
287 | } | ||
288 | }; | ||
289 | }"#, | ||
290 | ); | ||
291 | } | ||
292 | |||
293 | #[test] | ||
246 | fn test_pull_assignment_up_not_last_not_applicable() { | 294 | fn test_pull_assignment_up_not_last_not_applicable() { |
247 | check_assist_not_applicable( | 295 | check_assist_not_applicable( |
248 | pull_assignment_up, | 296 | pull_assignment_up, |
@@ -439,4 +487,24 @@ fn foo() { | |||
439 | "#, | 487 | "#, |
440 | ) | 488 | ) |
441 | } | 489 | } |
490 | |||
491 | #[test] | ||
492 | fn test_cant_pull_non_assignments() { | ||
493 | cov_mark::check!(test_cant_pull_non_assignments); | ||
494 | check_assist_not_applicable( | ||
495 | pull_assignment_up, | ||
496 | r#" | ||
497 | fn foo() { | ||
498 | let mut a = 1; | ||
499 | let b = &mut a; | ||
500 | |||
501 | if true { | ||
502 | $0*b + 2; | ||
503 | } else { | ||
504 | *b + 3; | ||
505 | } | ||
506 | } | ||
507 | "#, | ||
508 | ) | ||
509 | } | ||
442 | } | 510 | } |
diff --git a/crates/ide_assists/src/handlers/reorder_impl.rs b/crates/ide_assists/src/handlers/reorder_impl.rs index 72d889248..54a9a468e 100644 --- a/crates/ide_assists/src/handlers/reorder_impl.rs +++ b/crates/ide_assists/src/handlers/reorder_impl.rs | |||
@@ -79,9 +79,12 @@ pub(crate) fn reorder_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
79 | "Sort methods", | 79 | "Sort methods", |
80 | target, | 80 | target, |
81 | |builder| { | 81 | |builder| { |
82 | methods.into_iter().zip(sorted).for_each(|(old, new)| { | 82 | let methods = |
83 | ted::replace(builder.make_ast_mut(old).syntax(), new.clone_for_update().syntax()) | 83 | methods.into_iter().map(|fn_| builder.make_ast_mut(fn_)).collect::<Vec<_>>(); |
84 | }); | 84 | methods |
85 | .into_iter() | ||
86 | .zip(sorted) | ||
87 | .for_each(|(old, new)| ted::replace(old.syntax(), new.clone_for_update().syntax())); | ||
85 | }, | 88 | }, |
86 | ) | 89 | ) |
87 | } | 90 | } |
@@ -160,7 +163,7 @@ $0impl Bar for Foo {} | |||
160 | } | 163 | } |
161 | 164 | ||
162 | #[test] | 165 | #[test] |
163 | fn reorder_impl_trait_methods() { | 166 | fn reorder_impl_trait_functions() { |
164 | check_assist( | 167 | check_assist( |
165 | reorder_impl, | 168 | reorder_impl, |
166 | r#" | 169 | r#" |
@@ -197,4 +200,33 @@ impl Bar for Foo { | |||
197 | "#, | 200 | "#, |
198 | ) | 201 | ) |
199 | } | 202 | } |
203 | |||
204 | #[test] | ||
205 | fn reorder_impl_trait_methods_uneven_ident_lengths() { | ||
206 | check_assist( | ||
207 | reorder_impl, | ||
208 | r#" | ||
209 | trait Bar { | ||
210 | fn foo(&mut self) {} | ||
211 | fn fooo(&mut self) {} | ||
212 | } | ||
213 | |||
214 | struct Foo; | ||
215 | impl Bar for Foo { | ||
216 | fn fooo(&mut self) {} | ||
217 | fn foo(&mut self) {$0} | ||
218 | }"#, | ||
219 | r#" | ||
220 | trait Bar { | ||
221 | fn foo(&mut self) {} | ||
222 | fn fooo(&mut self) {} | ||
223 | } | ||
224 | |||
225 | struct Foo; | ||
226 | impl Bar for Foo { | ||
227 | fn foo(&mut self) {} | ||
228 | fn fooo(&mut self) {} | ||
229 | }"#, | ||
230 | ) | ||
231 | } | ||
200 | } | 232 | } |
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs index 694d897d1..10d9cec31 100644 --- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs | |||
@@ -84,7 +84,7 @@ pub(crate) fn replace_derive_with_manual_impl( | |||
84 | add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?; | 84 | add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?; |
85 | } | 85 | } |
86 | if no_traits_found { | 86 | if no_traits_found { |
87 | let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_name))); | 87 | let trait_path = make::ext::ident_path(trait_name); |
88 | add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?; | 88 | add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?; |
89 | } | 89 | } |
90 | Some(()) | 90 | Some(()) |
@@ -159,10 +159,8 @@ fn impl_def_from_trait( | |||
159 | if trait_items.is_empty() { | 159 | if trait_items.is_empty() { |
160 | return None; | 160 | return None; |
161 | } | 161 | } |
162 | let impl_def = make::impl_trait( | 162 | let impl_def = |
163 | trait_path.clone(), | 163 | make::impl_trait(trait_path.clone(), make::ext::ident_path(&annotated_name.text())); |
164 | make::path_unqualified(make::path_segment(make::name_ref(&annotated_name.text()))), | ||
165 | ); | ||
166 | let (impl_def, first_assoc_item) = | 164 | let (impl_def, first_assoc_item) = |
167 | add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope); | 165 | add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope); |
168 | Some((impl_def, first_assoc_item)) | 166 | Some((impl_def, first_assoc_item)) |
diff --git a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs index ff25b61ea..15420aedf 100644 --- a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs +++ b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs | |||
@@ -1,6 +1,9 @@ | |||
1 | use syntax::ast::{self, edit::AstNodeEdit, make, AstNode, GenericParamsOwner}; | 1 | use syntax::{ |
2 | ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode}, | ||
3 | ted, | ||
4 | }; | ||
2 | 5 | ||
3 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 6 | use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; |
4 | 7 | ||
5 | // Assist: replace_impl_trait_with_generic | 8 | // Assist: replace_impl_trait_with_generic |
6 | // | 9 | // |
@@ -17,30 +20,29 @@ pub(crate) fn replace_impl_trait_with_generic( | |||
17 | acc: &mut Assists, | 20 | acc: &mut Assists, |
18 | ctx: &AssistContext, | 21 | ctx: &AssistContext, |
19 | ) -> Option<()> { | 22 | ) -> Option<()> { |
20 | let type_impl_trait = ctx.find_node_at_offset::<ast::ImplTraitType>()?; | 23 | let impl_trait_type = ctx.find_node_at_offset::<ast::ImplTraitType>()?; |
21 | let type_param = type_impl_trait.syntax().parent().and_then(ast::Param::cast)?; | 24 | let param = impl_trait_type.syntax().parent().and_then(ast::Param::cast)?; |
22 | let type_fn = type_param.syntax().ancestors().find_map(ast::Fn::cast)?; | 25 | let fn_ = param.syntax().ancestors().find_map(ast::Fn::cast)?; |
23 | 26 | ||
24 | let impl_trait_ty = type_impl_trait.type_bound_list()?; | 27 | let type_bound_list = impl_trait_type.type_bound_list()?; |
25 | 28 | ||
26 | let target = type_fn.syntax().text_range(); | 29 | let target = fn_.syntax().text_range(); |
27 | acc.add( | 30 | acc.add( |
28 | AssistId("replace_impl_trait_with_generic", AssistKind::RefactorRewrite), | 31 | AssistId("replace_impl_trait_with_generic", AssistKind::RefactorRewrite), |
29 | "Replace impl trait with generic", | 32 | "Replace impl trait with generic", |
30 | target, | 33 | target, |
31 | |edit| { | 34 | |edit| { |
32 | let generic_letter = impl_trait_ty.to_string().chars().next().unwrap().to_string(); | 35 | let impl_trait_type = edit.make_ast_mut(impl_trait_type); |
36 | let fn_ = edit.make_ast_mut(fn_); | ||
33 | 37 | ||
34 | let generic_param_list = type_fn | 38 | let type_param_name = suggest_name::for_generic_parameter(&impl_trait_type); |
35 | .generic_param_list() | ||
36 | .unwrap_or_else(|| make::generic_param_list(None)) | ||
37 | .append_param(make::generic_param(generic_letter.clone(), Some(impl_trait_ty))); | ||
38 | 39 | ||
39 | let new_type_fn = type_fn | 40 | let type_param = make::type_param(make::name(&type_param_name), Some(type_bound_list)) |
40 | .replace_descendant::<ast::Type>(type_impl_trait.into(), make::ty(&generic_letter)) | 41 | .clone_for_update(); |
41 | .with_generic_param_list(generic_param_list); | 42 | let new_ty = make::ty(&type_param_name).clone_for_update(); |
42 | 43 | ||
43 | edit.replace_ast(type_fn.clone(), new_type_fn); | 44 | ted::replace(impl_trait_type.syntax(), new_ty.syntax()); |
45 | fn_.get_or_create_generic_param_list().add_generic_param(type_param.into()) | ||
44 | }, | 46 | }, |
45 | ) | 47 | ) |
46 | } | 48 | } |
@@ -55,12 +57,8 @@ mod tests { | |||
55 | fn replace_impl_trait_with_generic_params() { | 57 | fn replace_impl_trait_with_generic_params() { |
56 | check_assist( | 58 | check_assist( |
57 | replace_impl_trait_with_generic, | 59 | replace_impl_trait_with_generic, |
58 | r#" | 60 | r#"fn foo<G>(bar: $0impl Bar) {}"#, |
59 | fn foo<G>(bar: $0impl Bar) {} | 61 | r#"fn foo<G, B: Bar>(bar: B) {}"#, |
60 | "#, | ||
61 | r#" | ||
62 | fn foo<G, B: Bar>(bar: B) {} | ||
63 | "#, | ||
64 | ); | 62 | ); |
65 | } | 63 | } |
66 | 64 | ||
@@ -68,12 +66,8 @@ mod tests { | |||
68 | fn replace_impl_trait_without_generic_params() { | 66 | fn replace_impl_trait_without_generic_params() { |
69 | check_assist( | 67 | check_assist( |
70 | replace_impl_trait_with_generic, | 68 | replace_impl_trait_with_generic, |
71 | r#" | 69 | r#"fn foo(bar: $0impl Bar) {}"#, |
72 | fn foo(bar: $0impl Bar) {} | 70 | r#"fn foo<B: Bar>(bar: B) {}"#, |
73 | "#, | ||
74 | r#" | ||
75 | fn foo<B: Bar>(bar: B) {} | ||
76 | "#, | ||
77 | ); | 71 | ); |
78 | } | 72 | } |
79 | 73 | ||
@@ -81,12 +75,8 @@ mod tests { | |||
81 | fn replace_two_impl_trait_with_generic_params() { | 75 | fn replace_two_impl_trait_with_generic_params() { |
82 | check_assist( | 76 | check_assist( |
83 | replace_impl_trait_with_generic, | 77 | replace_impl_trait_with_generic, |
84 | r#" | 78 | r#"fn foo<G>(foo: impl Foo, bar: $0impl Bar) {}"#, |
85 | fn foo<G>(foo: impl Foo, bar: $0impl Bar) {} | 79 | r#"fn foo<G, B: Bar>(foo: impl Foo, bar: B) {}"#, |
86 | "#, | ||
87 | r#" | ||
88 | fn foo<G, B: Bar>(foo: impl Foo, bar: B) {} | ||
89 | "#, | ||
90 | ); | 80 | ); |
91 | } | 81 | } |
92 | 82 | ||
@@ -94,12 +84,8 @@ mod tests { | |||
94 | fn replace_impl_trait_with_empty_generic_params() { | 84 | fn replace_impl_trait_with_empty_generic_params() { |
95 | check_assist( | 85 | check_assist( |
96 | replace_impl_trait_with_generic, | 86 | replace_impl_trait_with_generic, |
97 | r#" | 87 | r#"fn foo<>(bar: $0impl Bar) {}"#, |
98 | fn foo<>(bar: $0impl Bar) {} | 88 | r#"fn foo<B: Bar>(bar: B) {}"#, |
99 | "#, | ||
100 | r#" | ||
101 | fn foo<B: Bar>(bar: B) {} | ||
102 | "#, | ||
103 | ); | 89 | ); |
104 | } | 90 | } |
105 | 91 | ||
@@ -108,13 +94,13 @@ mod tests { | |||
108 | check_assist( | 94 | check_assist( |
109 | replace_impl_trait_with_generic, | 95 | replace_impl_trait_with_generic, |
110 | r#" | 96 | r#" |
111 | fn foo< | 97 | fn foo< |
112 | >(bar: $0impl Bar) {} | 98 | >(bar: $0impl Bar) {} |
113 | "#, | 99 | "#, |
114 | r#" | 100 | r#" |
115 | fn foo<B: Bar | 101 | fn foo<B: Bar |
116 | >(bar: B) {} | 102 | >(bar: B) {} |
117 | "#, | 103 | "#, |
118 | ); | 104 | ); |
119 | } | 105 | } |
120 | 106 | ||
@@ -123,12 +109,8 @@ mod tests { | |||
123 | fn replace_impl_trait_with_exist_generic_letter() { | 109 | fn replace_impl_trait_with_exist_generic_letter() { |
124 | check_assist( | 110 | check_assist( |
125 | replace_impl_trait_with_generic, | 111 | replace_impl_trait_with_generic, |
126 | r#" | 112 | r#"fn foo<B>(bar: $0impl Bar) {}"#, |
127 | fn foo<B>(bar: $0impl Bar) {} | 113 | r#"fn foo<B, C: Bar>(bar: C) {}"#, |
128 | "#, | ||
129 | r#" | ||
130 | fn foo<B, C: Bar>(bar: C) {} | ||
131 | "#, | ||
132 | ); | 114 | ); |
133 | } | 115 | } |
134 | 116 | ||
@@ -137,19 +119,19 @@ mod tests { | |||
137 | check_assist( | 119 | check_assist( |
138 | replace_impl_trait_with_generic, | 120 | replace_impl_trait_with_generic, |
139 | r#" | 121 | r#" |
140 | fn foo< | 122 | fn foo< |
141 | G: Foo, | 123 | G: Foo, |
142 | F, | 124 | F, |
143 | H, | 125 | H, |
144 | >(bar: $0impl Bar) {} | 126 | >(bar: $0impl Bar) {} |
145 | "#, | 127 | "#, |
146 | r#" | 128 | r#" |
147 | fn foo< | 129 | fn foo< |
148 | G: Foo, | 130 | G: Foo, |
149 | F, | 131 | F, |
150 | H, B: Bar | 132 | H, B: Bar, |
151 | >(bar: B) {} | 133 | >(bar: B) {} |
152 | "#, | 134 | "#, |
153 | ); | 135 | ); |
154 | } | 136 | } |
155 | 137 | ||
@@ -157,12 +139,8 @@ mod tests { | |||
157 | fn replace_impl_trait_multiple() { | 139 | fn replace_impl_trait_multiple() { |
158 | check_assist( | 140 | check_assist( |
159 | replace_impl_trait_with_generic, | 141 | replace_impl_trait_with_generic, |
160 | r#" | 142 | r#"fn foo(bar: $0impl Foo + Bar) {}"#, |
161 | fn foo(bar: $0impl Foo + Bar) {} | 143 | r#"fn foo<F: Foo + Bar>(bar: F) {}"#, |
162 | "#, | ||
163 | r#" | ||
164 | fn foo<F: Foo + Bar>(bar: F) {} | ||
165 | "#, | ||
166 | ); | 144 | ); |
167 | } | 145 | } |
168 | } | 146 | } |
diff --git a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs index be7e724b5..1ad0fa816 100644 --- a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs +++ b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs | |||
@@ -50,22 +50,19 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> | |||
50 | "Replace with if-let", | 50 | "Replace with if-let", |
51 | target, | 51 | target, |
52 | |edit| { | 52 | |edit| { |
53 | let with_placeholder: ast::Pat = match happy_variant { | 53 | let pat = match happy_variant { |
54 | None => make::wildcard_pat().into(), | 54 | None => original_pat, |
55 | Some(var_name) => make::tuple_struct_pat( | 55 | Some(var_name) => { |
56 | make::path_unqualified(make::path_segment(make::name_ref(var_name))), | 56 | make::tuple_struct_pat(make::ext::ident_path(var_name), once(original_pat)) |
57 | once(make::wildcard_pat().into()), | 57 | .into() |
58 | ) | 58 | } |
59 | .into(), | ||
60 | }; | 59 | }; |
60 | |||
61 | let block = | 61 | let block = |
62 | make::block_expr(None, None).indent(IndentLevel::from_node(let_stmt.syntax())); | 62 | make::ext::empty_block_expr().indent(IndentLevel::from_node(let_stmt.syntax())); |
63 | let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block, None); | 63 | let if_ = make::expr_if(make::condition(init, Some(pat)), block, None); |
64 | let stmt = make::expr_stmt(if_); | 64 | let stmt = make::expr_stmt(if_); |
65 | 65 | ||
66 | let placeholder = stmt.syntax().descendants().find_map(ast::WildcardPat::cast).unwrap(); | ||
67 | let stmt = stmt.replace_descendant(placeholder.into(), original_pat); | ||
68 | |||
69 | edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); | 66 | edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); |
70 | }, | 67 | }, |
71 | ) | 68 | ) |
diff --git a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs index a986a6ae8..0fec961b4 100644 --- a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs +++ b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs | |||
@@ -32,7 +32,7 @@ use ide_db::ty_filter::TryEnum; | |||
32 | // fn main() { | 32 | // fn main() { |
33 | // let x: Result<i32, i32> = Result::Ok(92); | 33 | // let x: Result<i32, i32> = Result::Ok(92); |
34 | // let y = match x { | 34 | // let y = match x { |
35 | // Ok(a) => a, | 35 | // Ok(it) => it, |
36 | // $0_ => unreachable!(), | 36 | // $0_ => unreachable!(), |
37 | // }; | 37 | // }; |
38 | // } | 38 | // } |
@@ -52,16 +52,17 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext) | |||
52 | "Replace unwrap with match", | 52 | "Replace unwrap with match", |
53 | target, | 53 | target, |
54 | |builder| { | 54 | |builder| { |
55 | let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); | 55 | let ok_path = make::ext::ident_path(happy_variant); |
56 | let it = make::ident_pat(make::name("a")).into(); | 56 | let it = make::ident_pat(make::name("it")).into(); |
57 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); | 57 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); |
58 | 58 | ||
59 | let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); | 59 | let bind_path = make::ext::ident_path("it"); |
60 | let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); | 60 | let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); |
61 | 61 | ||
62 | let unreachable_call = make::expr_unreachable(); | 62 | let err_arm = make::match_arm( |
63 | let err_arm = | 63 | iter::once(make::wildcard_pat().into()), |
64 | make::match_arm(iter::once(make::wildcard_pat().into()), unreachable_call); | 64 | make::ext::expr_unreachable(), |
65 | ); | ||
65 | 66 | ||
66 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); | 67 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); |
67 | let match_expr = make::expr_match(caller.clone(), match_arm_list) | 68 | let match_expr = make::expr_match(caller.clone(), match_arm_list) |
@@ -110,7 +111,7 @@ fn i<T>(a: T) -> T { a } | |||
110 | fn main() { | 111 | fn main() { |
111 | let x: Result<i32, i32> = Result::Ok(92); | 112 | let x: Result<i32, i32> = Result::Ok(92); |
112 | let y = match i(x) { | 113 | let y = match i(x) { |
113 | Ok(a) => a, | 114 | Ok(it) => it, |
114 | $0_ => unreachable!(), | 115 | $0_ => unreachable!(), |
115 | }; | 116 | }; |
116 | } | 117 | } |
@@ -136,7 +137,7 @@ fn i<T>(a: T) -> T { a } | |||
136 | fn main() { | 137 | fn main() { |
137 | let x = Option::Some(92); | 138 | let x = Option::Some(92); |
138 | let y = match i(x) { | 139 | let y = match i(x) { |
139 | Some(a) => a, | 140 | Some(it) => it, |
140 | $0_ => unreachable!(), | 141 | $0_ => unreachable!(), |
141 | }; | 142 | }; |
142 | } | 143 | } |
@@ -162,7 +163,7 @@ fn i<T>(a: T) -> T { a } | |||
162 | fn main() { | 163 | fn main() { |
163 | let x: Result<i32, i32> = Result::Ok(92); | 164 | let x: Result<i32, i32> = Result::Ok(92); |
164 | let y = match i(x) { | 165 | let y = match i(x) { |
165 | Ok(a) => a, | 166 | Ok(it) => it, |
166 | $0_ => unreachable!(), | 167 | $0_ => unreachable!(), |
167 | }.count_zeroes(); | 168 | }.count_zeroes(); |
168 | } | 169 | } |
diff --git a/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs b/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs index e838630ea..2f1da82c7 100644 --- a/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs +++ b/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs | |||
@@ -54,9 +54,7 @@ pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext) | |||
54 | 54 | ||
55 | for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap { | 55 | for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap { |
56 | let ok_wrapped = make::expr_call( | 56 | let ok_wrapped = make::expr_call( |
57 | make::expr_path(make::path_unqualified(make::path_segment(make::name_ref( | 57 | make::expr_path(make::ext::ident_path("Ok")), |
58 | "Ok", | ||
59 | )))), | ||
60 | make::arg_list(iter::once(ret_expr_arg.clone())), | 58 | make::arg_list(iter::once(ret_expr_arg.clone())), |
61 | ); | 59 | ); |
62 | builder.replace_ast(ret_expr_arg, ok_wrapped); | 60 | builder.replace_ast(ret_expr_arg, ok_wrapped); |