From 233f01c9ba555e5d06f336cb0ff64e7a83e4a23a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 6 May 2020 12:51:28 +0200 Subject: [PATCH] Move target to AssistLabel Target is used for assists sorting, so we need it before we compute the action. --- crates/ra_assists/src/assist_ctx.rs | 17 +- .../src/handlers/add_custom_impl.rs | 5 +- crates/ra_assists/src/handlers/add_derive.rs | 4 +- .../src/handlers/add_explicit_type.rs | 2 +- .../src/handlers/add_from_impl_for_enum.rs | 2 + .../ra_assists/src/handlers/add_function.rs | 6 +- crates/ra_assists/src/handlers/add_impl.rs | 59 ++++--- .../src/handlers/add_missing_impl_members.rs | 14 +- crates/ra_assists/src/handlers/add_new.rs | 5 +- .../ra_assists/src/handlers/apply_demorgan.rs | 3 +- crates/ra_assists/src/handlers/auto_import.rs | 3 +- .../src/handlers/change_visibility.rs | 32 ++-- .../ra_assists/src/handlers/early_return.rs | 157 +++++++++--------- .../src/handlers/fill_match_arms.rs | 5 +- .../ra_assists/src/handlers/flip_binexpr.rs | 3 +- crates/ra_assists/src/handlers/flip_comma.rs | 3 +- .../src/handlers/flip_trait_bound.rs | 4 +- .../src/handlers/inline_local_variable.rs | 2 + .../src/handlers/introduce_variable.rs | 4 +- crates/ra_assists/src/handlers/invert_if.rs | 3 +- .../ra_assists/src/handlers/merge_imports.rs | 3 +- .../src/handlers/merge_match_arms.rs | 3 +- crates/ra_assists/src/handlers/move_bounds.rs | 49 +++--- crates/ra_assists/src/handlers/move_guard.rs | 7 +- crates/ra_assists/src/handlers/raw_string.rs | 16 +- crates/ra_assists/src/handlers/remove_dbg.rs | 4 +- crates/ra_assists/src/handlers/remove_mut.rs | 3 +- .../ra_assists/src/handlers/reorder_fields.rs | 4 +- .../src/handlers/replace_if_let_with_match.rs | 47 +++--- .../src/handlers/replace_let_with_if_let.rs | 4 +- .../replace_qualified_name_with_use.rs | 2 + .../src/handlers/replace_unwrap_with_match.rs | 38 +++-- .../ra_assists/src/handlers/split_import.rs | 4 +- .../ra_assists/src/handlers/unwrap_block.rs | 4 +- crates/ra_assists/src/lib.rs | 16 +- crates/ra_assists/src/tests.rs | 3 +- 36 files changed, 288 insertions(+), 252 deletions(-) diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 83dd270c6c..600e5689cc 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -94,9 +94,10 @@ impl<'a> AssistCtx<'a> { self, id: AssistId, label: impl Into, + target: TextRange, f: impl FnOnce(&mut ActionBuilder), ) -> Option { - let label = AssistLabel::new(id, label.into(), None); + let label = AssistLabel::new(id, label.into(), None, target); let mut info = AssistInfo::new(label); if self.should_compute_edit { @@ -152,9 +153,10 @@ impl<'a> AssistGroup<'a> { &mut self, id: AssistId, label: impl Into, + target: TextRange, f: impl FnOnce(&mut ActionBuilder), ) { - let label = AssistLabel::new(id, label.into(), Some(self.group.clone())); + let label = AssistLabel::new(id, label.into(), Some(self.group.clone()), target); let mut info = AssistInfo::new(label).with_group(self.group.clone()); if self.ctx.should_compute_edit { @@ -181,7 +183,6 @@ impl<'a> AssistGroup<'a> { pub(crate) struct ActionBuilder<'a, 'b> { edit: TextEditBuilder, cursor_position: Option, - target: Option, file: AssistFile, ctx: &'a AssistCtx<'b>, } @@ -191,7 +192,6 @@ impl<'a, 'b> ActionBuilder<'a, 'b> { Self { edit: TextEditBuilder::default(), cursor_position: None, - target: None, file: AssistFile::default(), ctx, } @@ -237,14 +237,6 @@ impl<'a, 'b> ActionBuilder<'a, 'b> { self.cursor_position = Some(offset) } - /// Specify that the assist should be active withing the `target` range. - /// - /// Target ranges are used to sort assists: the smaller the target range, - /// the more specific assist is, and so it should be sorted first. - pub(crate) fn target(&mut self, target: TextRange) { - self.target = Some(target) - } - /// Get access to the raw `TextEditBuilder`. pub(crate) fn text_edit_builder(&mut self) -> &mut TextEditBuilder { &mut self.edit @@ -267,7 +259,6 @@ impl<'a, 'b> ActionBuilder<'a, 'b> { AssistAction { edit: self.edit.finish(), cursor_position: self.cursor_position, - target: self.target, file: self.file, } } diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs index b72f7aeac8..869d4dc045 100644 --- a/crates/ra_assists/src/handlers/add_custom_impl.rs +++ b/crates/ra_assists/src/handlers/add_custom_impl.rs @@ -48,9 +48,8 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option { let label = format!("Add custom impl '{}' for '{}'", trait_token.text().as_str(), annotated_name); - ctx.add_assist(AssistId("add_custom_impl"), label, |edit| { - edit.target(attr.syntax().text_range()); - + let target = attr.syntax().text_range(); + ctx.add_assist(AssistId("add_custom_impl"), label, target, |edit| { let new_attr_input = input .syntax() .descendants_with_tokens() diff --git a/crates/ra_assists/src/handlers/add_derive.rs b/crates/ra_assists/src/handlers/add_derive.rs index 3629dac6bf..2a6bb1caed 100644 --- a/crates/ra_assists/src/handlers/add_derive.rs +++ b/crates/ra_assists/src/handlers/add_derive.rs @@ -27,7 +27,8 @@ use crate::{Assist, AssistCtx, AssistId}; pub(crate) fn add_derive(ctx: AssistCtx) -> Option { let nominal = ctx.find_node_at_offset::()?; let node_start = derive_insertion_offset(&nominal)?; - ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", |edit| { + let target = nominal.syntax().text_range(); + ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", target, |edit| { let derive_attr = nominal .attrs() .filter_map(|x| x.as_simple_call()) @@ -41,7 +42,6 @@ pub(crate) fn add_derive(ctx: AssistCtx) -> Option { } Some(tt) => tt.syntax().text_range().end() - TextSize::of(')'), }; - edit.target(nominal.syntax().text_range()); edit.set_cursor(offset) }) } diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index e39e1f4f3c..a59ec16b2d 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs @@ -62,8 +62,8 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option { ctx.add_assist( AssistId("add_explicit_type"), format!("Insert explicit type '{}'", new_type_string), + pat_range, |edit| { - edit.target(pat_range); if let Some(ascribed_ty) = ascribed_ty { edit.replace(ascribed_ty.syntax().text_range(), new_type_string); } else { diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs index ee0d5ce986..81deb3dfa3 100644 --- a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs +++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs @@ -47,9 +47,11 @@ pub(crate) fn add_from_impl_for_enum(ctx: AssistCtx) -> Option { return None; } + let target = variant.syntax().text_range(); ctx.add_assist( AssistId("add_from_impl_for_enum"), "Add From impl for this enum variant", + target, |edit| { let start_offset = variant.parent_enum().syntax().text_range().end(); let mut buf = String::new(); diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs index cb2afc863d..76c0f9783b 100644 --- a/crates/ra_assists/src/handlers/add_function.rs +++ b/crates/ra_assists/src/handlers/add_function.rs @@ -57,9 +57,9 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option { let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; - ctx.add_assist(AssistId("add_function"), "Add function", |edit| { - edit.target(call.syntax().text_range()); - + let target = call.syntax().text_range(); + // TODO: assert here? + ctx.add_assist(AssistId("add_function"), "Add function", target, |edit| { if let Some(function_template) = function_builder.render() { edit.set_file(function_template.file); edit.set_cursor(function_template.cursor_offset); diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index 3d390c20bc..557344ebb8 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs @@ -28,33 +28,40 @@ use crate::{Assist, AssistCtx, AssistId}; pub(crate) fn add_impl(ctx: AssistCtx) -> Option { let nominal = ctx.find_node_at_offset::()?; let name = nominal.name()?; - ctx.add_assist(AssistId("add_impl"), format!("Implement {}", name.text().as_str()), |edit| { - edit.target(nominal.syntax().text_range()); - let type_params = nominal.type_param_list(); - let start_offset = nominal.syntax().text_range().end(); - let mut buf = String::new(); - buf.push_str("\n\nimpl"); - if let Some(type_params) = &type_params { - format_to!(buf, "{}", type_params.syntax()); - } - buf.push_str(" "); - buf.push_str(name.text().as_str()); - if let Some(type_params) = type_params { - let lifetime_params = type_params - .lifetime_params() - .filter_map(|it| it.lifetime_token()) - .map(|it| it.text().clone()); - let type_params = - type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); + let target = nominal.syntax().text_range(); + ctx.add_assist( + AssistId("add_impl"), + format!("Implement {}", name.text().as_str()), + target, + |edit| { + let type_params = nominal.type_param_list(); + let start_offset = nominal.syntax().text_range().end(); + let mut buf = String::new(); + buf.push_str("\n\nimpl"); + if let Some(type_params) = &type_params { + format_to!(buf, "{}", type_params.syntax()); + } + buf.push_str(" "); + buf.push_str(name.text().as_str()); + if let Some(type_params) = type_params { + let lifetime_params = type_params + .lifetime_params() + .filter_map(|it| it.lifetime_token()) + .map(|it| it.text().clone()); + let type_params = type_params + .type_params() + .filter_map(|it| it.name()) + .map(|it| it.text().clone()); - let generic_params = lifetime_params.chain(type_params).sep_by(", "); - format_to!(buf, "<{}>", generic_params) - } - buf.push_str(" {\n"); - edit.set_cursor(start_offset + TextSize::of(&buf)); - buf.push_str("\n}"); - edit.insert(start_offset, buf); - }) + let generic_params = lifetime_params.chain(type_params).sep_by(", "); + format_to!(buf, "<{}>", generic_params) + } + buf.push_str(" {\n"); + edit.set_cursor(start_offset + TextSize::of(&buf)); + buf.push_str("\n}"); + edit.insert(start_offset, buf); + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index f7a1015033..7df7865909 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs @@ -107,10 +107,10 @@ fn add_missing_impl_members_inner( label: &'static str, ) -> Option { let _p = ra_prof::profile("add_missing_impl_members_inner"); - let impl_node = ctx.find_node_at_offset::()?; - let impl_item_list = impl_node.item_list()?; + let impl_def = ctx.find_node_at_offset::()?; + let impl_item_list = impl_def.item_list()?; - let trait_ = resolve_target_trait(&ctx.sema, &impl_node)?; + let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?; let def_name = |item: &ast::AssocItem| -> Option { match item { @@ -121,7 +121,7 @@ fn add_missing_impl_members_inner( .map(|it| it.text().clone()) }; - let missing_items = get_missing_assoc_items(&ctx.sema, &impl_node) + let missing_items = get_missing_assoc_items(&ctx.sema, &impl_def) .iter() .map(|i| match i { hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db).value), @@ -143,13 +143,13 @@ fn add_missing_impl_members_inner( } let sema = ctx.sema; - - ctx.add_assist(AssistId(assist_id), label, |edit| { + let target = impl_def.syntax().text_range(); + ctx.add_assist(AssistId(assist_id), label, target, |edit| { let n_existing_items = impl_item_list.assoc_items().count(); let source_scope = sema.scope_for_def(trait_); let target_scope = sema.scope(impl_item_list.syntax()); let ast_transform = QualifyPaths::new(&target_scope, &source_scope) - .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_node)); + .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_def)); let items = missing_items .into_iter() .map(|it| ast_transform::apply(&*ast_transform, it)) diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index 1b5d604d18..1c3f8435ab 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs @@ -41,9 +41,8 @@ pub(crate) fn add_new(ctx: AssistCtx) -> Option { // Return early if we've found an existing new fn let impl_def = find_struct_impl(&ctx, &strukt)?; - ctx.add_assist(AssistId("add_new"), "Add default constructor", |edit| { - edit.target(strukt.syntax().text_range()); - + let target = strukt.syntax().text_range(); + ctx.add_assist(AssistId("add_new"), "Add default constructor", target, |edit| { let mut buf = String::with_capacity(512); if impl_def.is_some() { diff --git a/crates/ra_assists/src/handlers/apply_demorgan.rs b/crates/ra_assists/src/handlers/apply_demorgan.rs index a0c48d8729..a5b26e5b93 100644 --- a/crates/ra_assists/src/handlers/apply_demorgan.rs +++ b/crates/ra_assists/src/handlers/apply_demorgan.rs @@ -39,8 +39,7 @@ pub(crate) fn apply_demorgan(ctx: AssistCtx) -> Option { let rhs_range = rhs.syntax().text_range(); let not_rhs = invert_boolean_expression(rhs); - ctx.add_assist(AssistId("apply_demorgan"), "Apply De Morgan's law", |edit| { - edit.target(op_range); + ctx.add_assist(AssistId("apply_demorgan"), "Apply De Morgan's law", op_range, |edit| { edit.replace(op_range, opposite_op); edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs index 9e4171ccd8..2224b9714b 100644 --- a/crates/ra_assists/src/handlers/auto_import.rs +++ b/crates/ra_assists/src/handlers/auto_import.rs @@ -48,8 +48,7 @@ pub(crate) fn auto_import(ctx: AssistCtx) -> Option { let range = ctx.sema.original_range(&auto_import_assets.syntax_under_caret).range; let mut group = ctx.add_assist_group(auto_import_assets.get_import_group_message()); for import in proposed_imports { - group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| { - edit.target(range); + group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), range, |edit| { insert_use_statement(&auto_import_assets.syntax_under_caret, &import, edit); }); } diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index 6ac1f8e69e..489db83e6e 100644 --- a/crates/ra_assists/src/handlers/change_visibility.rs +++ b/crates/ra_assists/src/handlers/change_visibility.rs @@ -66,11 +66,15 @@ fn add_vis(ctx: AssistCtx) -> Option { return None; }; - ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub(crate)", |edit| { - edit.target(target); - edit.insert(offset, "pub(crate) "); - edit.set_cursor(offset); - }) + ctx.add_assist( + AssistId("change_visibility"), + "Change visibility to pub(crate)", + target, + |edit| { + edit.insert(offset, "pub(crate) "); + edit.set_cursor(offset); + }, + ) } fn vis_offset(node: &SyntaxNode) -> TextSize { @@ -86,22 +90,28 @@ fn vis_offset(node: &SyntaxNode) -> TextSize { fn change_vis(ctx: AssistCtx, vis: ast::Visibility) -> Option { if vis.syntax().text() == "pub" { + let target = vis.syntax().text_range(); return ctx.add_assist( AssistId("change_visibility"), "Change Visibility to pub(crate)", + target, |edit| { - edit.target(vis.syntax().text_range()); edit.replace(vis.syntax().text_range(), "pub(crate)"); edit.set_cursor(vis.syntax().text_range().start()) }, ); } if vis.syntax().text() == "pub(crate)" { - return ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub", |edit| { - edit.target(vis.syntax().text_range()); - edit.replace(vis.syntax().text_range(), "pub"); - edit.set_cursor(vis.syntax().text_range().start()); - }); + let target = vis.syntax().text_range(); + return ctx.add_assist( + AssistId("change_visibility"), + "Change visibility to pub", + target, + |edit| { + edit.replace(vis.syntax().text_range(), "pub"); + edit.set_cursor(vis.syntax().text_range().start()); + }, + ); } None } diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs index 55ccc37b00..4bd6040b2a 100644 --- a/crates/ra_assists/src/handlers/early_return.rs +++ b/crates/ra_assists/src/handlers/early_return.rs @@ -95,89 +95,94 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option { then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; let cursor_position = ctx.frange.range.start(); - ctx.add_assist(AssistId("convert_to_guarded_return"), "Convert to guarded return", |edit| { - let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); - let new_block = match if_let_pat { - None => { - // If. - let new_expr = { - let then_branch = - make::block_expr(once(make::expr_stmt(early_expression).into()), None); - let cond = invert_boolean_expression(cond_expr); - let e = make::expr_if(make::condition(cond, None), then_branch); - if_indent_level.increase_indent(e) - }; - replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) - } - Some((path, bound_ident)) => { - // If-let. - let match_expr = { - let happy_arm = { - let pat = make::tuple_struct_pat( - path, - once(make::bind_pat(make::name("it")).into()), - ); - let expr = { - let name_ref = make::name_ref("it"); - let segment = make::path_segment(name_ref); - let path = make::path_unqualified(segment); - make::expr_path(path) + let target = if_expr.syntax().text_range(); + ctx.add_assist( + AssistId("convert_to_guarded_return"), + "Convert to guarded return", + target, + |edit| { + let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); + let new_block = match if_let_pat { + None => { + // If. + let new_expr = { + let then_branch = + make::block_expr(once(make::expr_stmt(early_expression).into()), None); + let cond = invert_boolean_expression(cond_expr); + let e = make::expr_if(make::condition(cond, None), then_branch); + if_indent_level.increase_indent(e) + }; + replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) + } + Some((path, bound_ident)) => { + // If-let. + let match_expr = { + let happy_arm = { + let pat = make::tuple_struct_pat( + path, + once(make::bind_pat(make::name("it")).into()), + ); + let expr = { + let name_ref = make::name_ref("it"); + let segment = make::path_segment(name_ref); + let path = make::path_unqualified(segment); + make::expr_path(path) + }; + make::match_arm(once(pat.into()), expr) }; - make::match_arm(once(pat.into()), expr) + + let sad_arm = make::match_arm( + // FIXME: would be cool to use `None` or `Err(_)` if appropriate + once(make::placeholder_pat().into()), + early_expression, + ); + + make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) }; - let sad_arm = make::match_arm( - // FIXME: would be cool to use `None` or `Err(_)` if appropriate - once(make::placeholder_pat().into()), - early_expression, + let let_stmt = make::let_stmt( + make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), + Some(match_expr), ); + let let_stmt = if_indent_level.increase_indent(let_stmt); + replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) + } + }; + edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); + edit.set_cursor(cursor_position); - make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) - }; - - let let_stmt = make::let_stmt( - make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), - Some(match_expr), + fn replace( + new_expr: &SyntaxNode, + then_block: &ast::BlockExpr, + parent_block: &ast::BlockExpr, + if_expr: &ast::IfExpr, + ) -> SyntaxNode { + let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone()); + let end_of_then = then_block_items.syntax().last_child_or_token().unwrap(); + let end_of_then = + if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { + end_of_then.prev_sibling_or_token().unwrap() + } else { + end_of_then + }; + let mut then_statements = new_expr.children_with_tokens().chain( + then_block_items + .syntax() + .children_with_tokens() + .skip(1) + .take_while(|i| *i != end_of_then), ); - let let_stmt = if_indent_level.increase_indent(let_stmt); - replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) + replace_children( + &parent_block.syntax(), + RangeInclusive::new( + if_expr.clone().syntax().clone().into(), + if_expr.syntax().clone().into(), + ), + &mut then_statements, + ) } - }; - edit.target(if_expr.syntax().text_range()); - edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); - edit.set_cursor(cursor_position); - - fn replace( - new_expr: &SyntaxNode, - then_block: &ast::BlockExpr, - parent_block: &ast::BlockExpr, - if_expr: &ast::IfExpr, - ) -> SyntaxNode { - let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone()); - let end_of_then = then_block_items.syntax().last_child_or_token().unwrap(); - let end_of_then = - if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { - end_of_then.prev_sibling_or_token().unwrap() - } else { - end_of_then - }; - let mut then_statements = new_expr.children_with_tokens().chain( - then_block_items - .syntax() - .children_with_tokens() - .skip(1) - .take_while(|i| *i != end_of_then), - ); - replace_children( - &parent_block.syntax(), - RangeInclusive::new( - if_expr.clone().syntax().clone().into(), - if_expr.syntax().clone().into(), - ), - &mut then_statements, - ) - } - }) + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs index 1f9cd55852..7c8f8bdf24 100644 --- a/crates/ra_assists/src/handlers/fill_match_arms.rs +++ b/crates/ra_assists/src/handlers/fill_match_arms.rs @@ -92,10 +92,9 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option { return None; } - ctx.add_assist(AssistId("fill_match_arms"), "Fill match arms", |edit| { + let target = match_expr.syntax().text_range(); + ctx.add_assist(AssistId("fill_match_arms"), "Fill match arms", target, |edit| { let new_arm_list = match_arm_list.remove_placeholder().append_arms(missing_arms); - - edit.target(match_expr.syntax().text_range()); edit.set_cursor(expr.syntax().text_range().start()); edit.replace_ast(match_arm_list, new_arm_list); }) diff --git a/crates/ra_assists/src/handlers/flip_binexpr.rs b/crates/ra_assists/src/handlers/flip_binexpr.rs index 41db963dc6..cb7264d7bb 100644 --- a/crates/ra_assists/src/handlers/flip_binexpr.rs +++ b/crates/ra_assists/src/handlers/flip_binexpr.rs @@ -33,8 +33,7 @@ pub(crate) fn flip_binexpr(ctx: AssistCtx) -> Option { return None; } - ctx.add_assist(AssistId("flip_binexpr"), "Flip binary expression", |edit| { - edit.target(op_range); + ctx.add_assist(AssistId("flip_binexpr"), "Flip binary expression", op_range, |edit| { if let FlipAction::FlipAndReplaceOp(new_op) = action { edit.replace(op_range, new_op); } diff --git a/crates/ra_assists/src/handlers/flip_comma.rs b/crates/ra_assists/src/handlers/flip_comma.rs index e65c9a41db..24982ae225 100644 --- a/crates/ra_assists/src/handlers/flip_comma.rs +++ b/crates/ra_assists/src/handlers/flip_comma.rs @@ -28,8 +28,7 @@ pub(crate) fn flip_comma(ctx: AssistCtx) -> Option { return None; } - ctx.add_assist(AssistId("flip_comma"), "Flip comma", |edit| { - edit.target(comma.text_range()); + ctx.add_assist(AssistId("flip_comma"), "Flip comma", comma.text_range(), |edit| { edit.replace(prev.text_range(), next.to_string()); edit.replace(next.text_range(), prev.to_string()); }) diff --git a/crates/ra_assists/src/handlers/flip_trait_bound.rs b/crates/ra_assists/src/handlers/flip_trait_bound.rs index f186da5858..6a3b2df679 100644 --- a/crates/ra_assists/src/handlers/flip_trait_bound.rs +++ b/crates/ra_assists/src/handlers/flip_trait_bound.rs @@ -32,8 +32,8 @@ pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option { non_trivia_sibling(plus.clone().into(), Direction::Next)?, ); - ctx.add_assist(AssistId("flip_trait_bound"), "Flip trait bounds", |edit| { - edit.target(plus.text_range()); + let target = plus.text_range(); + ctx.add_assist(AssistId("flip_trait_bound"), "Flip trait bounds", target, |edit| { edit.replace(before.text_range(), after.to_string()); edit.replace(after.text_range(), before.to_string()); }) diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index 5f3b8dfd11..e5765c845e 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs @@ -106,9 +106,11 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option { let init_str = initializer_expr.syntax().text().to_string(); let init_in_paren = format!("({})", &init_str); + let target = bind_pat.syntax().text_range(); ctx.add_assist( AssistId("inline_local_variable"), "Inline variable", + target, move |edit: &mut ActionBuilder| { edit.delete(delete_range); for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index 9c2c20b22c..3c340ff3b9 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs @@ -42,7 +42,8 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option { if indent.kind() != WHITESPACE { return None; } - ctx.add_assist(AssistId("introduce_variable"), "Extract into variable", move |edit| { + let target = expr.syntax().text_range(); + ctx.add_assist(AssistId("introduce_variable"), "Extract into variable", target, move |edit| { let mut buf = String::new(); let cursor_offset = if wrap_in_block { @@ -79,7 +80,6 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option { buf.push_str(text); } - edit.target(expr.syntax().text_range()); edit.replace(expr.syntax().text_range(), "var_name".to_string()); edit.insert(anchor_stmt.text_range().start(), buf); if wrap_in_block { diff --git a/crates/ra_assists/src/handlers/invert_if.rs b/crates/ra_assists/src/handlers/invert_if.rs index 303c1806d2..b16271443e 100644 --- a/crates/ra_assists/src/handlers/invert_if.rs +++ b/crates/ra_assists/src/handlers/invert_if.rs @@ -47,8 +47,7 @@ pub(crate) fn invert_if(ctx: AssistCtx) -> Option { let else_node = else_block.syntax(); let else_range = else_node.text_range(); let then_range = then_node.text_range(); - return ctx.add_assist(AssistId("invert_if"), "Invert if", |edit| { - edit.target(if_range); + return ctx.add_assist(AssistId("invert_if"), "Invert if", if_range, |edit| { edit.replace(cond_range, flip_cond.syntax().text()); edit.replace(else_range, then_node.text()); edit.replace(then_range, else_node.text()); diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs index 9a2083609d..de74d83d85 100644 --- a/crates/ra_assists/src/handlers/merge_imports.rs +++ b/crates/ra_assists/src/handlers/merge_imports.rs @@ -52,7 +52,8 @@ pub(crate) fn merge_imports(ctx: AssistCtx) -> Option { } }; - ctx.add_assist(AssistId("merge_imports"), "Merge imports", |edit| { + let target = tree.syntax().text_range(); + ctx.add_assist(AssistId("merge_imports"), "Merge imports", target, |edit| { edit.rewrite(rewriter); // FIXME: we only need because our diff is imprecise edit.set_cursor(offset); diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs index 9ae099b413..7c4d9d55d7 100644 --- a/crates/ra_assists/src/handlers/merge_match_arms.rs +++ b/crates/ra_assists/src/handlers/merge_match_arms.rs @@ -70,7 +70,7 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option { return None; } - ctx.add_assist(AssistId("merge_match_arms"), "Merge match arms", |edit| { + ctx.add_assist(AssistId("merge_match_arms"), "Merge match arms", current_text_range, |edit| { let pats = if arms_to_merge.iter().any(contains_placeholder) { "_".into() } else { @@ -87,7 +87,6 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option { let start = arms_to_merge.first().unwrap().syntax().text_range().start(); let end = arms_to_merge.last().unwrap().syntax().text_range().end(); - edit.target(current_text_range); edit.set_cursor(match cursor_pos { CursorPos::InExpr(back_offset) => start + TextSize::of(&arm) - back_offset, CursorPos::InPat(offset) => offset, diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs index 89956aea95..44e50cb6e6 100644 --- a/crates/ra_assists/src/handlers/move_bounds.rs +++ b/crates/ra_assists/src/handlers/move_bounds.rs @@ -49,30 +49,37 @@ pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option { } }; - ctx.add_assist(AssistId("move_bounds_to_where_clause"), "Move to where clause", |edit| { - let new_params = type_param_list - .type_params() - .filter(|it| it.type_bound_list().is_some()) - .map(|type_param| { - let without_bounds = type_param.remove_bounds(); - (type_param, without_bounds) - }); + let target = type_param_list.syntax().text_range(); + ctx.add_assist( + AssistId("move_bounds_to_where_clause"), + "Move to where clause", + target, + |edit| { + let new_params = type_param_list + .type_params() + .filter(|it| it.type_bound_list().is_some()) + .map(|type_param| { + let without_bounds = type_param.remove_bounds(); + (type_param, without_bounds) + }); - let new_type_param_list = type_param_list.replace_descendants(new_params); - edit.replace_ast(type_param_list.clone(), new_type_param_list); + let new_type_param_list = type_param_list.replace_descendants(new_params); + edit.replace_ast(type_param_list.clone(), new_type_param_list); - let where_clause = { - let predicates = type_param_list.type_params().filter_map(build_predicate); - make::where_clause(predicates) - }; + let where_clause = { + let predicates = type_param_list.type_params().filter_map(build_predicate); + make::where_clause(predicates) + }; - let to_insert = match anchor.prev_sibling_or_token() { - Some(ref elem) if elem.kind() == WHITESPACE => format!("{} ", where_clause.syntax()), - _ => format!(" {}", where_clause.syntax()), - }; - edit.insert(anchor.text_range().start(), to_insert); - edit.target(type_param_list.syntax().text_range()); - }) + let to_insert = match anchor.prev_sibling_or_token() { + Some(ref elem) if elem.kind() == WHITESPACE => { + format!("{} ", where_clause.syntax()) + } + _ => format!(" {}", where_clause.syntax()), + }; + edit.insert(anchor.text_range().start(), to_insert); + }, + ) } fn build_predicate(param: ast::TypeParam) -> Option { diff --git a/crates/ra_assists/src/handlers/move_guard.rs b/crates/ra_assists/src/handlers/move_guard.rs index f2aa7e5940..29bc9a9ffb 100644 --- a/crates/ra_assists/src/handlers/move_guard.rs +++ b/crates/ra_assists/src/handlers/move_guard.rs @@ -40,8 +40,8 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option { let arm_expr = match_arm.expr()?; let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); - ctx.add_assist(AssistId("move_guard_to_arm_body"), "Move guard to arm body", |edit| { - edit.target(guard.syntax().text_range()); + let target = guard.syntax().text_range(); + ctx.add_assist(AssistId("move_guard_to_arm_body"), "Move guard to arm body", target, |edit| { let offseting_amount = match space_before_guard.and_then(|it| it.into_token()) { Some(tok) => { if ast::Whitespace::cast(tok.clone()).is_some() { @@ -108,11 +108,12 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option { let buf = format!(" if {}", cond.syntax().text()); + let target = if_expr.syntax().text_range(); ctx.add_assist( AssistId("move_arm_cond_to_match_guard"), "Move condition to match guard", + target, |edit| { - edit.target(if_expr.syntax().text_range()); let then_only_expr = then_block.statements().next().is_none(); match &then_block.expr() { diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs index 542f7a6379..155c679b4b 100644 --- a/crates/ra_assists/src/handlers/raw_string.rs +++ b/crates/ra_assists/src/handlers/raw_string.rs @@ -25,8 +25,8 @@ use crate::{Assist, AssistCtx, AssistId}; pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option { let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?; let value = token.value()?; - ctx.add_assist(AssistId("make_raw_string"), "Rewrite as raw string", |edit| { - edit.target(token.syntax().text_range()); + let target = token.syntax().text_range(); + ctx.add_assist(AssistId("make_raw_string"), "Rewrite as raw string", target, |edit| { let max_hash_streak = count_hashes(&value); let mut hashes = String::with_capacity(max_hash_streak + 1); for _ in 0..hashes.capacity() { @@ -54,8 +54,8 @@ pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option { pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option { let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?; let value = token.value()?; - ctx.add_assist(AssistId("make_usual_string"), "Rewrite as regular string", |edit| { - edit.target(token.syntax().text_range()); + let target = token.syntax().text_range(); + ctx.add_assist(AssistId("make_usual_string"), "Rewrite as regular string", target, |edit| { // parse inside string to escape `"` let escaped = value.escape_default().to_string(); edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); @@ -79,8 +79,8 @@ pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option { // ``` pub(crate) fn add_hash(ctx: AssistCtx) -> Option { let token = ctx.find_token_at_offset(RAW_STRING)?; - ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| { - edit.target(token.text_range()); + let target = token.text_range(); + ctx.add_assist(AssistId("add_hash"), "Add # to raw string", target, |edit| { edit.insert(token.text_range().start() + TextSize::of('r'), "#"); edit.insert(token.text_range().end(), "#"); }) @@ -108,8 +108,8 @@ pub(crate) fn remove_hash(ctx: AssistCtx) -> Option { // no hash to remove return None; } - ctx.add_assist(AssistId("remove_hash"), "Remove hash from raw string", |edit| { - edit.target(token.text_range()); + let target = token.text_range(); + ctx.add_assist(AssistId("remove_hash"), "Remove hash from raw string", target, |edit| { let result = &text[2..text.len() - 1]; let result = if result.starts_with('\"') { // FIXME: this logic is wrong, not only the last has has to handled specially diff --git a/crates/ra_assists/src/handlers/remove_dbg.rs b/crates/ra_assists/src/handlers/remove_dbg.rs index ddfb21a7e3..e6e02f2aec 100644 --- a/crates/ra_assists/src/handlers/remove_dbg.rs +++ b/crates/ra_assists/src/handlers/remove_dbg.rs @@ -57,8 +57,8 @@ pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option { text.slice(without_parens).to_string() }; - ctx.add_assist(AssistId("remove_dbg"), "Remove dbg!()", |edit| { - edit.target(macro_call.syntax().text_range()); + let target = macro_call.syntax().text_range(); + ctx.add_assist(AssistId("remove_dbg"), "Remove dbg!()", target, |edit| { edit.replace(macro_range, macro_content); edit.set_cursor(cursor_pos); }) diff --git a/crates/ra_assists/src/handlers/remove_mut.rs b/crates/ra_assists/src/handlers/remove_mut.rs index e598023b25..9f72f879d5 100644 --- a/crates/ra_assists/src/handlers/remove_mut.rs +++ b/crates/ra_assists/src/handlers/remove_mut.rs @@ -25,7 +25,8 @@ pub(crate) fn remove_mut(ctx: AssistCtx) -> Option { _ => mut_token.text_range().end(), }; - ctx.add_assist(AssistId("remove_mut"), "Remove `mut` keyword", |edit| { + let target = mut_token.text_range(); + ctx.add_assist(AssistId("remove_mut"), "Remove `mut` keyword", target, |edit| { edit.set_cursor(delete_from); edit.delete(TextRange::new(delete_from, delete_to)); }) diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs index a57e327b8f..0b930dea21 100644 --- a/crates/ra_assists/src/handlers/reorder_fields.rs +++ b/crates/ra_assists/src/handlers/reorder_fields.rs @@ -50,11 +50,11 @@ fn reorder(ctx: AssistCtx) -> Option { return None; } - ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", |edit| { + let target = record.syntax().text_range(); + ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", target, |edit| { for (old, new) in fields.iter().zip(&sorted_fields) { algo::diff(old, new).into_text_edit(edit.text_edit_builder()); } - edit.target(record.syntax().text_range()) }) } diff --git a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs index d0df3b84e3..2eb8348f82 100644 --- a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs +++ b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs @@ -44,30 +44,35 @@ pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option { }; let sema = ctx.sema; - ctx.add_assist(AssistId("replace_if_let_with_match"), "Replace with match", move |edit| { - let match_expr = { - let then_arm = { - let then_expr = unwrap_trivial_block(then_block); - make::match_arm(vec![pat.clone()], then_expr) + let target = if_expr.syntax().text_range(); + ctx.add_assist( + AssistId("replace_if_let_with_match"), + "Replace with match", + target, + move |edit| { + let match_expr = { + let then_arm = { + let then_expr = unwrap_trivial_block(then_block); + make::match_arm(vec![pat.clone()], then_expr) + }; + let else_arm = { + let pattern = sema + .type_of_pat(&pat) + .and_then(|ty| TryEnum::from_ty(sema, &ty)) + .map(|it| it.sad_pattern()) + .unwrap_or_else(|| make::placeholder_pat().into()); + let else_expr = unwrap_trivial_block(else_block); + make::match_arm(vec![pattern], else_expr) + }; + make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])) }; - let else_arm = { - let pattern = sema - .type_of_pat(&pat) - .and_then(|ty| TryEnum::from_ty(sema, &ty)) - .map(|it| it.sad_pattern()) - .unwrap_or_else(|| make::placeholder_pat().into()); - let else_expr = unwrap_trivial_block(else_block); - make::match_arm(vec![pattern], else_expr) - }; - make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])) - }; - let match_expr = IndentLevel::from_node(if_expr.syntax()).increase_indent(match_expr); + let match_expr = IndentLevel::from_node(if_expr.syntax()).increase_indent(match_expr); - edit.target(if_expr.syntax().text_range()); - edit.set_cursor(if_expr.syntax().text_range().start()); - edit.replace_ast::(if_expr.into(), match_expr); - }) + edit.set_cursor(if_expr.syntax().text_range().start()); + edit.replace_ast::(if_expr.into(), match_expr); + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs index dc4d16055b..a5509a5673 100644 --- a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs +++ b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs @@ -47,7 +47,8 @@ pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option { let ty = ctx.sema.type_of_expr(&init)?; let happy_variant = TryEnum::from_ty(ctx.sema, &ty).map(|it| it.happy_case()); - ctx.add_assist(AssistId("replace_let_with_if_let"), "Replace with if-let", |edit| { + let target = let_kw.text_range(); + ctx.add_assist(AssistId("replace_let_with_if_let"), "Replace with if-let", target, |edit| { let with_placeholder: ast::Pat = match happy_variant { None => make::placeholder_pat().into(), Some(var_name) => make::tuple_struct_pat( @@ -67,7 +68,6 @@ pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option { let stmt = stmt.replace_descendant(placeholder.into(), original_pat); edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); - edit.target(let_kw.text_range()); edit.set_cursor(target_offset); }) } diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs index 6241789240..fd41da64b8 100644 --- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs @@ -33,9 +33,11 @@ pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option return None; } + let target = path.syntax().text_range(); ctx.add_assist( AssistId("replace_qualified_name_with_use"), "Replace qualified path with use", + target, |edit| { let path_to_import = hir_path.mod_path().clone(); insert_use_statement(path.syntax(), &path_to_import, edit); diff --git a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs index dcb471edb0..c6b73da67b 100644 --- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs +++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs @@ -38,26 +38,32 @@ pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option { let caller = method_call.expr()?; let ty = ctx.sema.type_of_expr(&caller)?; let happy_variant = TryEnum::from_ty(ctx.sema, &ty)?.happy_case(); + let target = method_call.syntax().text_range(); + ctx.add_assist( + AssistId("replace_unwrap_with_match"), + "Replace unwrap with match", + target, + |edit| { + let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); + let it = make::bind_pat(make::name("a")).into(); + let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); - ctx.add_assist(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", |edit| { - let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); - let it = make::bind_pat(make::name("a")).into(); - let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); + let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); + let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); - let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); - let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); + let unreachable_call = make::unreachable_macro_call().into(); + let err_arm = + make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); - let unreachable_call = make::unreachable_macro_call().into(); - let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); + let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); + let match_expr = make::expr_match(caller.clone(), match_arm_list); + let match_expr = + IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr); - let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); - let match_expr = make::expr_match(caller.clone(), match_arm_list); - let match_expr = IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr); - - edit.target(method_call.syntax().text_range()); - edit.set_cursor(caller.syntax().text_range().start()); - edit.replace_ast::(method_call.into(), match_expr); - }) + edit.set_cursor(caller.syntax().text_range().start()); + edit.replace_ast::(method_call.into(), match_expr); + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/split_import.rs b/crates/ra_assists/src/handlers/split_import.rs index a59f2f76f6..d495639746 100644 --- a/crates/ra_assists/src/handlers/split_import.rs +++ b/crates/ra_assists/src/handlers/split_import.rs @@ -28,8 +28,8 @@ pub(crate) fn split_import(ctx: AssistCtx) -> Option { } let cursor = ctx.frange.range.start(); - ctx.add_assist(AssistId("split_import"), "Split import", |edit| { - edit.target(colon_colon.text_range()); + let target = colon_colon.text_range(); + ctx.add_assist(AssistId("split_import"), "Split import", target, |edit| { edit.replace_ast(use_tree, new_tree); edit.set_cursor(cursor); }) diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs index 89992117d8..6df927abbd 100644 --- a/crates/ra_assists/src/handlers/unwrap_block.rs +++ b/crates/ra_assists/src/handlers/unwrap_block.rs @@ -57,9 +57,9 @@ pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option { } }; - ctx.add_assist(AssistId("unwrap_block"), "Unwrap block", |edit| { + let target = expr_to_unwrap.syntax().text_range(); + ctx.add_assist(AssistId("unwrap_block"), "Unwrap block", target, |edit| { edit.set_cursor(expr.syntax().text_range().start()); - edit.target(expr_to_unwrap.syntax().text_range()); let pat_start: &[_] = &[' ', '{', '\n']; let expr_to_unwrap = expr_to_unwrap.to_string(); diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index b794b021d7..f4f37614ff 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -36,16 +36,24 @@ pub struct AssistLabel { /// Short description of the assist, as shown in the UI. pub label: String, pub group: Option, + /// Target ranges are used to sort assists: the smaller the target range, + /// the more specific assist is, and so it should be sorted first. + pub target: TextRange, } #[derive(Clone, Debug)] pub struct GroupLabel(pub String); impl AssistLabel { - pub(crate) fn new(id: AssistId, label: String, group: Option) -> AssistLabel { + pub(crate) fn new( + id: AssistId, + label: String, + group: Option, + target: TextRange, + ) -> AssistLabel { // FIXME: make fields private, so that this invariant can't be broken assert!(label.starts_with(|c: char| c.is_uppercase())); - AssistLabel { id, label, group } + AssistLabel { id, label, group, target } } } @@ -53,8 +61,6 @@ impl AssistLabel { pub struct AssistAction { pub edit: TextEdit, pub cursor_position: Option, - // FIXME: This belongs to `AssistLabel` - pub target: Option, pub file: AssistFile, } @@ -104,7 +110,7 @@ pub fn resolved_assists(db: &RootDatabase, range: FileRange) -> Vec>(); - a.sort_by_key(|it| it.action.target.map_or(TextSize::from(!0u32), |it| it.len())); + a.sort_by_key(|it| it.label.target.len()); a } diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs index 483e119319..dd9026df61 100644 --- a/crates/ra_assists/src/tests.rs +++ b/crates/ra_assists/src/tests.rs @@ -118,8 +118,7 @@ fn check(assist: Handler, before: &str, expected: ExpectedResult) { assert_eq_text!(after, &actual); } (Some(assist), ExpectedResult::Target(target)) => { - let action = assist.0[0].action.clone().unwrap(); - let range = action.target.expect("expected target on action"); + let range = assist.0[0].label.target; assert_eq_text!(&text_without_caret[range], target); } (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),