From b98c16a034620913f3dbc67bd3f48ad2686face7 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Sun, 28 Jun 2020 18:36:05 -0400 Subject: Categorize assists --- crates/ra_assists/src/assist_context.rs | 8 +- crates/ra_assists/src/handlers/add_custom_impl.rs | 4 +- crates/ra_assists/src/handlers/add_derive.rs | 4 +- .../ra_assists/src/handlers/add_explicit_type.rs | 3 +- .../src/handlers/add_from_impl_for_enum.rs | 3 +- crates/ra_assists/src/handlers/add_function.rs | 26 ++-- crates/ra_assists/src/handlers/add_impl.rs | 68 +++++---- .../src/handlers/add_missing_impl_members.rs | 4 +- crates/ra_assists/src/handlers/add_new.rs | 92 ++++++------ crates/ra_assists/src/handlers/add_turbo_fish.rs | 14 +- crates/ra_assists/src/handlers/apply_demorgan.rs | 18 ++- crates/ra_assists/src/handlers/auto_import.rs | 5 +- .../src/handlers/change_return_type_to_result.rs | 3 +- .../ra_assists/src/handlers/change_visibility.rs | 16 ++- crates/ra_assists/src/handlers/early_return.rs | 157 +++++++++++---------- .../handlers/extract_struct_from_enum_variant.rs | 4 +- crates/ra_assists/src/handlers/extract_variable.rs | 138 +++++++++--------- crates/ra_assists/src/handlers/fill_match_arms.rs | 44 +++--- crates/ra_assists/src/handlers/fix_visibility.rs | 6 +- crates/ra_assists/src/handlers/flip_binexpr.rs | 22 +-- crates/ra_assists/src/handlers/flip_comma.rs | 16 ++- crates/ra_assists/src/handlers/flip_trait_bound.rs | 16 ++- .../src/handlers/inline_local_variable.rs | 23 +-- .../src/handlers/introduce_named_lifetime.rs | 6 +- crates/ra_assists/src/handlers/invert_if.rs | 4 +- crates/ra_assists/src/handlers/merge_imports.rs | 14 +- crates/ra_assists/src/handlers/merge_match_arms.rs | 46 +++--- crates/ra_assists/src/handlers/move_bounds.rs | 56 ++++---- crates/ra_assists/src/handlers/move_guard.rs | 29 ++-- crates/ra_assists/src/handlers/raw_string.rs | 75 ++++++---- crates/ra_assists/src/handlers/remove_dbg.rs | 4 +- crates/ra_assists/src/handlers/remove_mut.rs | 14 +- crates/ra_assists/src/handlers/reorder_fields.rs | 18 ++- .../src/handlers/replace_if_let_with_match.rs | 51 ++++--- .../src/handlers/replace_let_with_if_let.rs | 42 +++--- .../handlers/replace_qualified_name_with_use.rs | 3 +- .../src/handlers/replace_unwrap_with_match.rs | 61 ++++---- crates/ra_assists/src/handlers/split_import.rs | 4 +- crates/ra_assists/src/handlers/unwrap_block.rs | 66 +++++---- crates/ra_assists/src/lib.rs | 16 ++- 40 files changed, 702 insertions(+), 501 deletions(-) (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index 3640bb4d2..c35d0254a 100644 --- a/crates/ra_assists/src/assist_context.rs +++ b/crates/ra_assists/src/assist_context.rs @@ -19,7 +19,7 @@ use ra_text_edit::TextEditBuilder; use crate::{ assist_config::{AssistConfig, SnippetCap}, - Assist, AssistId, GroupLabel, ResolvedAssist, + Assist, AssistId, AssistKind, GroupLabel, ResolvedAssist, }; /// `AssistContext` allows to apply an assist or check if it could be applied. @@ -135,22 +135,24 @@ impl Assists { pub(crate) fn add( &mut self, id: AssistId, + kind: AssistKind, label: impl Into, target: TextRange, f: impl FnOnce(&mut AssistBuilder), ) -> Option<()> { - let label = Assist::new(id, label.into(), None, target); + let label = Assist::new(id, kind, label.into(), None, target); self.add_impl(label, f) } pub(crate) fn add_group( &mut self, group: &GroupLabel, id: AssistId, + kind: AssistKind, label: impl Into, target: TextRange, f: impl FnOnce(&mut AssistBuilder), ) -> Option<()> { - let label = Assist::new(id, label.into(), Some(group.clone()), target); + let label = Assist::new(id, kind, label.into(), Some(group.clone()), target); self.add_impl(label, f) } fn add_impl(&mut self, label: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> { diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs index fa70c8496..e86b01dbb 100644 --- a/crates/ra_assists/src/handlers/add_custom_impl.rs +++ b/crates/ra_assists/src/handlers/add_custom_impl.rs @@ -8,7 +8,7 @@ use stdx::SepBy; use crate::{ assist_context::{AssistContext, Assists}, - AssistId, + AssistId, AssistKind, }; // Assist: add_custom_impl @@ -52,7 +52,7 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option< format!("Add custom impl `{}` for `{}`", trait_token.text().as_str(), annotated_name); let target = attr.syntax().text_range(); - acc.add(AssistId("add_custom_impl"), label, target, |builder| { + acc.add(AssistId("add_custom_impl"), AssistKind::Refactor, label, target, |builder| { 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 b123b8498..3b7a570b0 100644 --- a/crates/ra_assists/src/handlers/add_derive.rs +++ b/crates/ra_assists/src/handlers/add_derive.rs @@ -4,7 +4,7 @@ use ra_syntax::{ TextSize, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: add_derive // @@ -29,7 +29,7 @@ pub(crate) fn add_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let nominal = ctx.find_node_at_offset::()?; let node_start = derive_insertion_offset(&nominal)?; let target = nominal.syntax().text_range(); - acc.add(AssistId("add_derive"), "Add `#[derive]`", target, |builder| { + acc.add(AssistId("add_derive"), AssistKind::Refactor, "Add `#[derive]`", target, |builder| { let derive_attr = nominal .attrs() .filter_map(|x| x.as_simple_call()) diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index 11df922a2..653137d43 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs @@ -4,7 +4,7 @@ use ra_syntax::{ TextRange, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: add_explicit_type // @@ -60,6 +60,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?; acc.add( AssistId("add_explicit_type"), + AssistKind::RefactorRewrite, format!("Insert explicit type `{}`", inferred_type), pat_range, |builder| match ascribed_ty { 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 b0e56e1b5..505085c54 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 @@ -2,7 +2,7 @@ use ra_ide_db::RootDatabase; use ra_syntax::ast::{self, AstNode, NameOwner}; use test_utils::mark; -use crate::{utils::FamousDefs, AssistContext, AssistId, Assists}; +use crate::{utils::FamousDefs, AssistContext, AssistId, AssistKind, Assists}; // Assist: add_from_impl_for_enum // @@ -46,6 +46,7 @@ pub(crate) fn add_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> let target = variant.syntax().text_range(); acc.add( AssistId("add_from_impl_for_enum"), + AssistKind::Refactor, "Add From impl for this enum variant", target, |edit| { diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs index fc4e82309..a11bc2551 100644 --- a/crates/ra_assists/src/handlers/add_function.rs +++ b/crates/ra_assists/src/handlers/add_function.rs @@ -13,7 +13,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ assist_config::SnippetCap, utils::{render_snippet, Cursor}, - AssistContext, AssistId, Assists, + AssistContext, AssistId, AssistKind, Assists, }; // Assist: add_function @@ -62,15 +62,21 @@ pub(crate) fn add_function(acc: &mut Assists, ctx: &AssistContext) -> Option<()> let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; let target = call.syntax().text_range(); - acc.add(AssistId("add_function"), "Add function", target, |builder| { - let function_template = function_builder.render(); - builder.edit_file(function_template.file); - let new_fn = function_template.to_string(ctx.config.snippet_cap); - match ctx.config.snippet_cap { - Some(cap) => builder.insert_snippet(cap, function_template.insert_offset, new_fn), - None => builder.insert(function_template.insert_offset, new_fn), - } - }) + acc.add( + AssistId("add_function"), + AssistKind::RefactorExtract, + "Add function", + target, + |builder| { + let function_template = function_builder.render(); + builder.edit_file(function_template.file); + let new_fn = function_template.to_string(ctx.config.snippet_cap); + match ctx.config.snippet_cap { + Some(cap) => builder.insert_snippet(cap, function_template.insert_offset, new_fn), + None => builder.insert(function_template.insert_offset, new_fn), + } + }, + ) } struct FunctionTemplate { diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index eceba7d0a..405e3c568 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs @@ -1,7 +1,7 @@ use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; use stdx::{format_to, SepBy}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: add_impl // @@ -26,38 +26,46 @@ pub(crate) fn add_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let nominal = ctx.find_node_at_offset::()?; let name = nominal.name()?; let target = nominal.syntax().text_range(); - acc.add(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()); + acc.add( + AssistId("add_impl"), + AssistKind::Refactor, + 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) - } - match ctx.config.snippet_cap { - Some(cap) => { - buf.push_str(" {\n $0\n}"); - edit.insert_snippet(cap, start_offset, buf); + let generic_params = lifetime_params.chain(type_params).sep_by(", "); + format_to!(buf, "<{}>", generic_params) } - None => { - buf.push_str(" {\n}"); - edit.insert(start_offset, buf); + match ctx.config.snippet_cap { + Some(cap) => { + buf.push_str(" {\n $0\n}"); + edit.insert_snippet(cap, start_offset, buf); + } + None => { + 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 77e092f62..13b441a29 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs @@ -12,7 +12,7 @@ use crate::{ assist_context::{AssistContext, Assists}, ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, utils::{get_missing_assoc_items, render_snippet, resolve_target_trait, Cursor}, - AssistId, + AssistId, AssistKind, }; #[derive(PartialEq)] @@ -147,7 +147,7 @@ fn add_missing_impl_members_inner( } let target = impl_def.syntax().text_range(); - acc.add(AssistId(assist_id), label, target, |builder| { + acc.add(AssistId(assist_id), AssistKind::QuickFix, label, target, |builder| { let n_existing_items = impl_item_list.assoc_items().count(); let source_scope = ctx.sema.scope_for_def(trait_); let target_scope = ctx.sema.scope(impl_item_list.syntax()); diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index e41b2aa06..4cd3ca264 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs @@ -7,7 +7,7 @@ use ra_syntax::{ }; use stdx::{format_to, SepBy}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: add_new // @@ -42,50 +42,56 @@ pub(crate) fn add_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let impl_def = find_struct_impl(&ctx, &strukt)?; let target = strukt.syntax().text_range(); - acc.add(AssistId("add_new"), "Add default constructor", target, |builder| { - let mut buf = String::with_capacity(512); - - if impl_def.is_some() { - buf.push('\n'); - } - - let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); - - let params = field_list - .fields() - .filter_map(|f| { - Some(format!("{}: {}", f.name()?.syntax(), f.ascribed_type()?.syntax())) - }) - .sep_by(", "); - let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", "); - - format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields); - - let start_offset = impl_def - .and_then(|impl_def| { + acc.add( + AssistId("add_new"), + AssistKind::Refactor, + "Add default constructor", + target, + |builder| { + let mut buf = String::with_capacity(512); + + if impl_def.is_some() { buf.push('\n'); - let start = impl_def - .syntax() - .descendants_with_tokens() - .find(|t| t.kind() == T!['{'])? - .text_range() - .end(); - - Some(start) - }) - .unwrap_or_else(|| { - buf = generate_impl_text(&strukt, &buf); - strukt.syntax().text_range().end() - }); - - match ctx.config.snippet_cap { - None => builder.insert(start_offset, buf), - Some(cap) => { - buf = buf.replace("fn new", "fn $0new"); - builder.insert_snippet(cap, start_offset, buf); } - } - }) + + let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); + + let params = field_list + .fields() + .filter_map(|f| { + Some(format!("{}: {}", f.name()?.syntax(), f.ascribed_type()?.syntax())) + }) + .sep_by(", "); + let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", "); + + format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields); + + let start_offset = impl_def + .and_then(|impl_def| { + buf.push('\n'); + let start = impl_def + .syntax() + .descendants_with_tokens() + .find(|t| t.kind() == T!['{'])? + .text_range() + .end(); + + Some(start) + }) + .unwrap_or_else(|| { + buf = generate_impl_text(&strukt, &buf); + strukt.syntax().text_range().end() + }); + + match ctx.config.snippet_cap { + None => builder.insert(start_offset, buf), + Some(cap) => { + buf = buf.replace("fn new", "fn $0new"); + builder.insert_snippet(cap, start_offset, buf); + } + } + }, + ) } // Generates the surrounding `impl Type { }` including type and lifetime diff --git a/crates/ra_assists/src/handlers/add_turbo_fish.rs b/crates/ra_assists/src/handlers/add_turbo_fish.rs index 26acf81f2..7a807fbde 100644 --- a/crates/ra_assists/src/handlers/add_turbo_fish.rs +++ b/crates/ra_assists/src/handlers/add_turbo_fish.rs @@ -4,7 +4,7 @@ use test_utils::mark; use crate::{ assist_context::{AssistContext, Assists}, - AssistId, + AssistId, AssistKind, }; // Assist: add_turbo_fish @@ -45,12 +45,16 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( mark::hit!(add_turbo_fish_non_generic); return None; } - acc.add(AssistId("add_turbo_fish"), "Add `::<>`", ident.text_range(), |builder| { - match ctx.config.snippet_cap { + acc.add( + AssistId("add_turbo_fish"), + AssistKind::RefactorRewrite, + "Add `::<>`", + ident.text_range(), + |builder| match ctx.config.snippet_cap { Some(cap) => builder.insert_snippet(cap, ident.text_range().end(), "::<${0:_}>"), None => builder.insert(ident.text_range().end(), "::<_>"), - } - }) + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/apply_demorgan.rs b/crates/ra_assists/src/handlers/apply_demorgan.rs index 233e8fb8e..a1fd6e112 100644 --- a/crates/ra_assists/src/handlers/apply_demorgan.rs +++ b/crates/ra_assists/src/handlers/apply_demorgan.rs @@ -1,6 +1,6 @@ use ra_syntax::ast::{self, AstNode}; -use crate::{utils::invert_boolean_expression, AssistContext, AssistId, Assists}; +use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists}; // Assist: apply_demorgan // @@ -39,11 +39,17 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<( let rhs_range = rhs.syntax().text_range(); let not_rhs = invert_boolean_expression(rhs); - acc.add(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())); - }) + acc.add( + AssistId("apply_demorgan"), + AssistKind::RefactorRewrite, + "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())); + }, + ) } // Return the opposite text for a given logical operator, if it makes sense diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs index 4cd77adbf..4d97ed101 100644 --- a/crates/ra_assists/src/handlers/auto_import.rs +++ b/crates/ra_assists/src/handlers/auto_import.rs @@ -13,7 +13,9 @@ use ra_syntax::{ }; use rustc_hash::FxHashSet; -use crate::{utils::insert_use_statement, AssistContext, AssistId, Assists, GroupLabel}; +use crate::{ + utils::insert_use_statement, AssistContext, AssistId, AssistKind, Assists, GroupLabel, +}; // Assist: auto_import // @@ -47,6 +49,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> acc.add_group( &group, AssistId("auto_import"), + AssistKind::QuickFix, format!("Import `{}`", &import), range, |builder| { diff --git a/crates/ra_assists/src/handlers/change_return_type_to_result.rs b/crates/ra_assists/src/handlers/change_return_type_to_result.rs index 855baf187..2be6d5e49 100644 --- a/crates/ra_assists/src/handlers/change_return_type_to_result.rs +++ b/crates/ra_assists/src/handlers/change_return_type_to_result.rs @@ -3,7 +3,7 @@ use ra_syntax::{ AstNode, SyntaxNode, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; use test_utils::mark; // Assist: change_return_type_to_result @@ -36,6 +36,7 @@ pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContex acc.add( AssistId("change_return_type_to_result"), + AssistKind::RefactorRewrite, "Change return type to Result", type_ref.syntax().text_range(), |builder| { diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index 157c7b665..34c7e481d 100644 --- a/crates/ra_assists/src/handlers/change_visibility.rs +++ b/crates/ra_assists/src/handlers/change_visibility.rs @@ -6,7 +6,7 @@ use ra_syntax::{ }; use test_utils::mark; -use crate::{utils::vis_offset, AssistContext, AssistId, Assists}; +use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; // Assist: change_visibility // @@ -62,9 +62,15 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { return None; }; - acc.add(AssistId("change_visibility"), "Change visibility to pub(crate)", target, |edit| { - edit.insert(offset, "pub(crate) "); - }) + acc.add( + AssistId("change_visibility"), + AssistKind::RefactorRewrite, + "Change visibility to pub(crate)", + target, + |edit| { + edit.insert(offset, "pub(crate) "); + }, + ) } fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { @@ -72,6 +78,7 @@ fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { let target = vis.syntax().text_range(); return acc.add( AssistId("change_visibility"), + AssistKind::RefactorRewrite, "Change Visibility to pub(crate)", target, |edit| { @@ -83,6 +90,7 @@ fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { let target = vis.syntax().text_range(); return acc.add( AssistId("change_visibility"), + AssistKind::RefactorRewrite, "Change visibility to pub", target, |edit| { diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs index dfade7432..9ccd42cd7 100644 --- a/crates/ra_assists/src/handlers/early_return.rs +++ b/crates/ra_assists/src/handlers/early_return.rs @@ -15,7 +15,7 @@ use ra_syntax::{ use crate::{ assist_context::{AssistContext, Assists}, utils::invert_boolean_expression, - AssistId, + AssistId, AssistKind, }; // Assist: convert_to_guarded_return @@ -99,86 +99,93 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; let target = if_expr.syntax().text_range(); - acc.add(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); - make::expr_if(make::condition(cond, None), then_branch).indent(if_indent_level) - }; - 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) + acc.add( + AssistId("convert_to_guarded_return"), + AssistKind::RefactorRewrite, + "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); + make::expr_if(make::condition(cond, None), then_branch) + .indent(if_indent_level) }; + 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) + }; - 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 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])) - }; + 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), + let let_stmt = make::let_stmt( + make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), + Some(match_expr), + ); + let let_stmt = let_stmt.indent(if_indent_level); + replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) + } + }; + edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); + + fn replace( + new_expr: &SyntaxNode, + then_block: &ast::BlockExpr, + parent_block: &ast::BlockExpr, + if_expr: &ast::IfExpr, + ) -> SyntaxNode { + let then_block_items = then_block.dedent(IndentLevel(1)); + 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 = let_stmt.indent(if_indent_level); - 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.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); - - fn replace( - new_expr: &SyntaxNode, - then_block: &ast::BlockExpr, - parent_block: &ast::BlockExpr, - if_expr: &ast::IfExpr, - ) -> SyntaxNode { - let then_block_items = then_block.dedent(IndentLevel(1)); - 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/extract_struct_from_enum_variant.rs b/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs index ca19cf198..e1ae485c9 100644 --- a/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs @@ -10,7 +10,8 @@ use ra_syntax::{ use rustc_hash::FxHashSet; use crate::{ - assist_context::AssistBuilder, utils::insert_use_statement, AssistContext, AssistId, Assists, + assist_context::AssistBuilder, utils::insert_use_statement, AssistContext, AssistId, + AssistKind, Assists, }; // Assist: extract_struct_from_enum_variant @@ -49,6 +50,7 @@ pub(crate) fn extract_struct_from_enum_variant( let target = variant.syntax().text_range(); acc.add( AssistId("extract_struct_from_enum_variant"), + AssistKind::RefactorRewrite, "Extract struct from enum variant", target, |builder| { diff --git a/crates/ra_assists/src/handlers/extract_variable.rs b/crates/ra_assists/src/handlers/extract_variable.rs index c4150d2bb..8f7ffdaff 100644 --- a/crates/ra_assists/src/handlers/extract_variable.rs +++ b/crates/ra_assists/src/handlers/extract_variable.rs @@ -9,7 +9,7 @@ use ra_syntax::{ use stdx::format_to; use test_utils::mark; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: extract_variable // @@ -43,80 +43,86 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option return None; } let target = expr.syntax().text_range(); - acc.add(AssistId("extract_variable"), "Extract into variable", target, move |edit| { - let field_shorthand = match expr.syntax().parent().and_then(ast::RecordField::cast) { - Some(field) => field.name_ref(), - None => None, - }; - - let mut buf = String::new(); - - let var_name = match &field_shorthand { - Some(it) => it.to_string(), - None => "var_name".to_string(), - }; - let expr_range = match &field_shorthand { - Some(it) => it.syntax().text_range().cover(expr.syntax().text_range()), - None => expr.syntax().text_range(), - }; - - if wrap_in_block { - format_to!(buf, "{{ let {} = ", var_name); - } else { - format_to!(buf, "let {} = ", var_name); - }; - format_to!(buf, "{}", expr.syntax()); - - let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); - let is_full_stmt = if let Some(expr_stmt) = &full_stmt { - Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) - } else { - false - }; - if is_full_stmt { - mark::hit!(test_extract_var_expr_stmt); - if full_stmt.unwrap().semicolon_token().is_none() { - buf.push_str(";"); + acc.add( + AssistId("extract_variable"), + AssistKind::RefactorExtract, + "Extract into variable", + target, + move |edit| { + let field_shorthand = match expr.syntax().parent().and_then(ast::RecordField::cast) { + Some(field) => field.name_ref(), + None => None, + }; + + let mut buf = String::new(); + + let var_name = match &field_shorthand { + Some(it) => it.to_string(), + None => "var_name".to_string(), + }; + let expr_range = match &field_shorthand { + Some(it) => it.syntax().text_range().cover(expr.syntax().text_range()), + None => expr.syntax().text_range(), + }; + + if wrap_in_block { + format_to!(buf, "{{ let {} = ", var_name); + } else { + format_to!(buf, "let {} = ", var_name); + }; + format_to!(buf, "{}", expr.syntax()); + + let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); + let is_full_stmt = if let Some(expr_stmt) = &full_stmt { + Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) + } else { + false + }; + if is_full_stmt { + mark::hit!(test_extract_var_expr_stmt); + if full_stmt.unwrap().semicolon_token().is_none() { + buf.push_str(";"); + } + match ctx.config.snippet_cap { + Some(cap) => { + let snip = buf + .replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); + edit.replace_snippet(cap, expr_range, snip) + } + None => edit.replace(expr_range, buf), + } + return; + } + + buf.push_str(";"); + + // We want to maintain the indent level, + // but we do not want to duplicate possible + // extra newlines in the indent block + let text = indent.text(); + if text.starts_with('\n') { + buf.push_str("\n"); + buf.push_str(text.trim_start_matches('\n')); + } else { + buf.push_str(text); } + + edit.replace(expr_range, var_name.clone()); + let offset = anchor_stmt.text_range().start(); match ctx.config.snippet_cap { Some(cap) => { let snip = buf.replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); - edit.replace_snippet(cap, expr_range, snip) + edit.insert_snippet(cap, offset, snip) } - None => edit.replace(expr_range, buf), + None => edit.insert(offset, buf), } - return; - } - buf.push_str(";"); - - // We want to maintain the indent level, - // but we do not want to duplicate possible - // extra newlines in the indent block - let text = indent.text(); - if text.starts_with('\n') { - buf.push_str("\n"); - buf.push_str(text.trim_start_matches('\n')); - } else { - buf.push_str(text); - } - - edit.replace(expr_range, var_name.clone()); - let offset = anchor_stmt.text_range().start(); - match ctx.config.snippet_cap { - Some(cap) => { - let snip = - buf.replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); - edit.insert_snippet(cap, offset, snip) + if wrap_in_block { + edit.insert(anchor_stmt.text_range().end(), " }"); } - None => edit.insert(offset, buf), - } - - if wrap_in_block { - edit.insert(anchor_stmt.text_range().end(), " }"); - } - }) + }, + ) } /// Check whether the node is a valid expression which can be extracted to a variable. diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs index 5b1235682..96610dbf5 100644 --- a/crates/ra_assists/src/handlers/fill_match_arms.rs +++ b/crates/ra_assists/src/handlers/fill_match_arms.rs @@ -8,7 +8,7 @@ use test_utils::mark; use crate::{ utils::{render_snippet, Cursor, FamousDefs}, - AssistContext, AssistId, Assists, + AssistContext, AssistId, AssistKind, Assists, }; // Assist: fill_match_arms @@ -103,24 +103,30 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< } let target = match_expr.syntax().text_range(); - acc.add(AssistId("fill_match_arms"), "Fill match arms", target, |builder| { - let new_arm_list = match_arm_list.remove_placeholder(); - let n_old_arms = new_arm_list.arms().count(); - let new_arm_list = new_arm_list.append_arms(missing_arms); - let first_new_arm = new_arm_list.arms().nth(n_old_arms); - let old_range = match_arm_list.syntax().text_range(); - match (first_new_arm, ctx.config.snippet_cap) { - (Some(first_new_arm), Some(cap)) => { - let snippet = render_snippet( - cap, - new_arm_list.syntax(), - Cursor::Before(first_new_arm.syntax()), - ); - builder.replace_snippet(cap, old_range, snippet); - } - _ => builder.replace(old_range, new_arm_list.to_string()), - } - }) + acc.add( + AssistId("fill_match_arms"), + AssistKind::RefactorRewrite, + "Fill match arms", + target, + |builder| { + let new_arm_list = match_arm_list.remove_placeholder(); + let n_old_arms = new_arm_list.arms().count(); + let new_arm_list = new_arm_list.append_arms(missing_arms); + let first_new_arm = new_arm_list.arms().nth(n_old_arms); + let old_range = match_arm_list.syntax().text_range(); + match (first_new_arm, ctx.config.snippet_cap) { + (Some(first_new_arm), Some(cap)) => { + let snippet = render_snippet( + cap, + new_arm_list.syntax(), + Cursor::Before(first_new_arm.syntax()), + ); + builder.replace_snippet(cap, old_range, snippet); + } + _ => builder.replace(old_range, new_arm_list.to_string()), + } + }, + ) } fn is_variant_missing(existing_arms: &mut Vec, var: &Pat) -> bool { diff --git a/crates/ra_assists/src/handlers/fix_visibility.rs b/crates/ra_assists/src/handlers/fix_visibility.rs index c0f57c329..9c6f9efc2 100644 --- a/crates/ra_assists/src/handlers/fix_visibility.rs +++ b/crates/ra_assists/src/handlers/fix_visibility.rs @@ -2,7 +2,7 @@ use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution}; use ra_db::FileId; use ra_syntax::{ast, AstNode, TextRange, TextSize}; -use crate::{utils::vis_offset, AssistContext, AssistId, Assists}; +use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; // FIXME: this really should be a fix for diagnostic, rather than an assist. @@ -58,7 +58,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O Some(name) => format!("Change visibility of {} to {}", name, missing_visibility), }; - acc.add(AssistId("fix_visibility"), assist_label, target, |builder| { + acc.add(AssistId("fix_visibility"), AssistKind::QuickFix, assist_label, target, |builder| { builder.edit_file(target_file); match ctx.config.snippet_cap { Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), @@ -101,7 +101,7 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> let assist_label = format!("Change visibility of {}.{} to {}", parent_name, target_name, missing_visibility); - acc.add(AssistId("fix_visibility"), assist_label, target, |builder| { + acc.add(AssistId("fix_visibility"), AssistKind::QuickFix, assist_label, target, |builder| { builder.edit_file(target_file); match ctx.config.snippet_cap { Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), diff --git a/crates/ra_assists/src/handlers/flip_binexpr.rs b/crates/ra_assists/src/handlers/flip_binexpr.rs index 573196576..aee55762f 100644 --- a/crates/ra_assists/src/handlers/flip_binexpr.rs +++ b/crates/ra_assists/src/handlers/flip_binexpr.rs @@ -1,6 +1,6 @@ use ra_syntax::ast::{AstNode, BinExpr, BinOp}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: flip_binexpr // @@ -33,13 +33,19 @@ pub(crate) fn flip_binexpr(acc: &mut Assists, ctx: &AssistContext) -> Option<()> return None; } - acc.add(AssistId("flip_binexpr"), "Flip binary expression", op_range, |edit| { - if let FlipAction::FlipAndReplaceOp(new_op) = action { - edit.replace(op_range, new_op); - } - edit.replace(lhs.text_range(), rhs.text()); - edit.replace(rhs.text_range(), lhs.text()); - }) + acc.add( + AssistId("flip_binexpr"), + AssistKind::RefactorRewrite, + "Flip binary expression", + op_range, + |edit| { + if let FlipAction::FlipAndReplaceOp(new_op) = action { + edit.replace(op_range, new_op); + } + edit.replace(lhs.text_range(), rhs.text()); + edit.replace(rhs.text_range(), lhs.text()); + }, + ) } enum FlipAction { diff --git a/crates/ra_assists/src/handlers/flip_comma.rs b/crates/ra_assists/src/handlers/flip_comma.rs index a57a1c463..9971ffa71 100644 --- a/crates/ra_assists/src/handlers/flip_comma.rs +++ b/crates/ra_assists/src/handlers/flip_comma.rs @@ -1,6 +1,6 @@ use ra_syntax::{algo::non_trivia_sibling, Direction, T}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: flip_comma // @@ -28,10 +28,16 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { return None; } - acc.add(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()); - }) + acc.add( + AssistId("flip_comma"), + AssistKind::RefactorRewrite, + "Flip comma", + comma.text_range(), + |edit| { + edit.replace(prev.text_range(), next.to_string()); + edit.replace(next.text_range(), prev.to_string()); + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/flip_trait_bound.rs b/crates/ra_assists/src/handlers/flip_trait_bound.rs index 0115adc8b..192f70ccb 100644 --- a/crates/ra_assists/src/handlers/flip_trait_bound.rs +++ b/crates/ra_assists/src/handlers/flip_trait_bound.rs @@ -4,7 +4,7 @@ use ra_syntax::{ Direction, T, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: flip_trait_bound // @@ -33,10 +33,16 @@ pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext) -> Option ); let target = plus.text_range(); - acc.add(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()); - }) + acc.add( + AssistId("flip_trait_bound"), + AssistKind::RefactorRewrite, + "Flip trait bounds", + target, + |edit| { + edit.replace(before.text_range(), after.to_string()); + edit.replace(after.text_range(), before.to_string()); + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index 259839535..f1bd8b46d 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs @@ -7,7 +7,7 @@ use test_utils::mark; use crate::{ assist_context::{AssistContext, Assists}, - AssistId, + AssistId, AssistKind, }; // Assist: inline_local_variable @@ -110,13 +110,20 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O let init_in_paren = format!("({})", &init_str); let target = bind_pat.syntax().text_range(); - acc.add(AssistId("inline_local_variable"), "Inline variable", target, move |builder| { - builder.delete(delete_range); - for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { - let replacement = if should_wrap { init_in_paren.clone() } else { init_str.clone() }; - builder.replace(desc.file_range.range, replacement) - } - }) + acc.add( + AssistId("inline_local_variable"), + AssistKind::RefactorInline, + "Inline variable", + target, + move |builder| { + builder.delete(delete_range); + for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { + let replacement = + if should_wrap { init_in_paren.clone() } else { init_str.clone() }; + builder.replace(desc.file_range.range, replacement) + } + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/introduce_named_lifetime.rs b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs index 28fcbc9ba..374274824 100644 --- a/crates/ra_assists/src/handlers/introduce_named_lifetime.rs +++ b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs @@ -4,7 +4,7 @@ use ra_syntax::{ }; use rustc_hash::FxHashSet; -use crate::{assist_context::AssistBuilder, AssistContext, AssistId, Assists}; +use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists}; static ASSIST_NAME: &str = "introduce_named_lifetime"; static ASSIST_LABEL: &str = "Introduce named lifetime"; @@ -83,7 +83,7 @@ fn generate_fn_def_assist( _ => return None, } }; - acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| { + acc.add(AssistId(ASSIST_NAME), AssistKind::Refactor, ASSIST_LABEL, lifetime_loc, |builder| { add_lifetime_param(fn_def, builder, end_of_fn_ident, new_lifetime_param); builder.replace(lifetime_loc, format!("'{}", new_lifetime_param)); loc_needing_lifetime.map(|loc| builder.insert(loc, format!("'{} ", new_lifetime_param))); @@ -98,7 +98,7 @@ fn generate_impl_def_assist( ) -> Option<()> { let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.type_param_list())?; let end_of_impl_kw = impl_def.impl_token()?.text_range().end(); - acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| { + acc.add(AssistId(ASSIST_NAME), AssistKind::Refactor, ASSIST_LABEL, lifetime_loc, |builder| { add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param); builder.replace(lifetime_loc, format!("'{}", new_lifetime_param)); }) diff --git a/crates/ra_assists/src/handlers/invert_if.rs b/crates/ra_assists/src/handlers/invert_if.rs index 59d278eb9..eebb2364d 100644 --- a/crates/ra_assists/src/handlers/invert_if.rs +++ b/crates/ra_assists/src/handlers/invert_if.rs @@ -6,7 +6,7 @@ use ra_syntax::{ use crate::{ assist_context::{AssistContext, Assists}, utils::invert_boolean_expression, - AssistId, + AssistId, AssistKind, }; // Assist: invert_if @@ -54,7 +54,7 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let else_node = else_block.syntax(); let else_range = else_node.text_range(); let then_range = then_node.text_range(); - acc.add(AssistId("invert_if"), "Invert if", if_range, |edit| { + acc.add(AssistId("invert_if"), AssistKind::RefactorRewrite, "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 ac0b3035c..b0458e17f 100644 --- a/crates/ra_assists/src/handlers/merge_imports.rs +++ b/crates/ra_assists/src/handlers/merge_imports.rs @@ -8,7 +8,7 @@ use ra_syntax::{ use crate::{ assist_context::{AssistContext, Assists}, - AssistId, + AssistId, AssistKind, }; // Assist: merge_imports @@ -56,9 +56,15 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<() }; let target = tree.syntax().text_range(); - acc.add(AssistId("merge_imports"), "Merge imports", target, |builder| { - builder.rewrite(rewriter); - }) + acc.add( + AssistId("merge_imports"), + AssistKind::RefactorRewrite, + "Merge imports", + target, + |builder| { + builder.rewrite(rewriter); + }, + ) } fn next_prev() -> impl Iterator { diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs index 90ce66378..f0f11a046 100644 --- a/crates/ra_assists/src/handlers/merge_match_arms.rs +++ b/crates/ra_assists/src/handlers/merge_match_arms.rs @@ -6,7 +6,7 @@ use ra_syntax::{ Direction, }; -use crate::{AssistContext, AssistId, Assists, TextRange}; +use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange}; // Assist: merge_match_arms // @@ -59,25 +59,31 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option return None; } - acc.add(AssistId("merge_match_arms"), "Merge match arms", current_text_range, |edit| { - let pats = if arms_to_merge.iter().any(contains_placeholder) { - "_".into() - } else { - arms_to_merge - .iter() - .filter_map(ast::MatchArm::pat) - .map(|x| x.syntax().to_string()) - .collect::>() - .join(" | ") - }; - - let arm = format!("{} => {}", pats, current_expr.syntax().text()); - - let start = arms_to_merge.first().unwrap().syntax().text_range().start(); - let end = arms_to_merge.last().unwrap().syntax().text_range().end(); - - edit.replace(TextRange::new(start, end), arm); - }) + acc.add( + AssistId("merge_match_arms"), + AssistKind::RefactorRewrite, + "Merge match arms", + current_text_range, + |edit| { + let pats = if arms_to_merge.iter().any(contains_placeholder) { + "_".into() + } else { + arms_to_merge + .iter() + .filter_map(ast::MatchArm::pat) + .map(|x| x.syntax().to_string()) + .collect::>() + .join(" | ") + }; + + let arm = format!("{} => {}", pats, current_expr.syntax().text()); + + let start = arms_to_merge.first().unwrap().syntax().text_range().start(); + let end = arms_to_merge.last().unwrap().syntax().text_range().end(); + + edit.replace(TextRange::new(start, end), arm); + }, + ) } fn contains_placeholder(a: &ast::MatchArm) -> bool { diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs index be2a7eddc..bcedd39a8 100644 --- a/crates/ra_assists/src/handlers/move_bounds.rs +++ b/crates/ra_assists/src/handlers/move_bounds.rs @@ -5,7 +5,7 @@ use ra_syntax::{ T, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: move_bounds_to_where_clause // @@ -50,29 +50,37 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext }; let target = type_param_list.syntax().text_range(); - acc.add(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 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); - }) + acc.add( + AssistId("move_bounds_to_where_clause"), + AssistKind::RefactorRewrite, + "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 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); + }, + ) } 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 7edcf0748..7f3aaf4f7 100644 --- a/crates/ra_assists/src/handlers/move_guard.rs +++ b/crates/ra_assists/src/handlers/move_guard.rs @@ -3,7 +3,7 @@ use ra_syntax::{ SyntaxKind::WHITESPACE, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: move_guard_to_arm_body // @@ -40,17 +40,23 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext) -> let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); let target = guard.syntax().text_range(); - acc.add(AssistId("move_guard_to_arm_body"), "Move guard to arm body", target, |edit| { - match space_before_guard { - Some(element) if element.kind() == WHITESPACE => { - edit.delete(element.text_range()); - } - _ => (), - }; + acc.add( + AssistId("move_guard_to_arm_body"), + AssistKind::RefactorExtract, + "Move guard to arm body", + target, + |edit| { + match space_before_guard { + Some(element) if element.kind() == WHITESPACE => { + edit.delete(element.text_range()); + } + _ => (), + }; - edit.delete(guard.syntax().text_range()); - edit.replace_node_and_indent(arm_expr.syntax(), buf); - }) + edit.delete(guard.syntax().text_range()); + edit.replace_node_and_indent(arm_expr.syntax(), buf); + }, + ) } // Assist: move_arm_cond_to_match_guard @@ -101,6 +107,7 @@ pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContex let target = if_expr.syntax().text_range(); acc.add( AssistId("move_arm_cond_to_match_guard"), + AssistKind::RefactorRewrite, "Move condition to match guard", target, |edit| { diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs index d22d0aa55..8d0dac528 100644 --- a/crates/ra_assists/src/handlers/raw_string.rs +++ b/crates/ra_assists/src/handlers/raw_string.rs @@ -5,7 +5,7 @@ use ra_syntax::{ TextSize, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: make_raw_string // @@ -26,14 +26,23 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext) -> Option< let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?; let value = token.value()?; let target = token.syntax().text_range(); - acc.add(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() { - hashes.push('#'); - } - edit.replace(token.syntax().text_range(), format!("r{}\"{}\"{}", hashes, value, hashes)); - }) + acc.add( + AssistId("make_raw_string"), + AssistKind::RefactorRewrite, + "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() { + hashes.push('#'); + } + edit.replace( + token.syntax().text_range(), + format!("r{}\"{}\"{}", hashes, value, hashes), + ); + }, + ) } // Assist: make_usual_string @@ -55,11 +64,17 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Optio let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?; let value = token.value()?; let target = token.syntax().text_range(); - acc.add(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)); - }) + acc.add( + AssistId("make_usual_string"), + AssistKind::RefactorRewrite, + "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)); + }, + ) } // Assist: add_hash @@ -80,7 +95,7 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Optio pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let token = ctx.find_token_at_offset(RAW_STRING)?; let target = token.text_range(); - acc.add(AssistId("add_hash"), "Add # to raw string", target, |edit| { + acc.add(AssistId("add_hash"), AssistKind::Refactor, "Add # to raw string", target, |edit| { edit.insert(token.text_range().start() + TextSize::of('r'), "#"); edit.insert(token.text_range().end(), "#"); }) @@ -109,18 +124,24 @@ pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> return None; } let target = token.text_range(); - acc.add(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 - // no more hash, escape - let internal_str = &result[1..result.len() - 1]; - format!("\"{}\"", internal_str.escape_default().to_string()) - } else { - result.to_owned() - }; - edit.replace(token.text_range(), format!("r{}", result)); - }) + acc.add( + AssistId("remove_hash"), + AssistKind::RefactorRewrite, + "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 + // no more hash, escape + let internal_str = &result[1..result.len() - 1]; + format!("\"{}\"", internal_str.escape_default().to_string()) + } else { + result.to_owned() + }; + edit.replace(token.text_range(), format!("r{}", result)); + }, + ) } fn count_hashes(s: &str) -> usize { diff --git a/crates/ra_assists/src/handlers/remove_dbg.rs b/crates/ra_assists/src/handlers/remove_dbg.rs index 961ee1731..e5571676f 100644 --- a/crates/ra_assists/src/handlers/remove_dbg.rs +++ b/crates/ra_assists/src/handlers/remove_dbg.rs @@ -3,7 +3,7 @@ use ra_syntax::{ TextSize, T, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: remove_dbg // @@ -38,7 +38,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { }; let target = macro_call.syntax().text_range(); - acc.add(AssistId("remove_dbg"), "Remove dbg!()", target, |builder| { + acc.add(AssistId("remove_dbg"), AssistKind::Refactor, "Remove dbg!()", target, |builder| { builder.replace(macro_range, macro_content); }) } diff --git a/crates/ra_assists/src/handlers/remove_mut.rs b/crates/ra_assists/src/handlers/remove_mut.rs index fe4eada03..a8173694a 100644 --- a/crates/ra_assists/src/handlers/remove_mut.rs +++ b/crates/ra_assists/src/handlers/remove_mut.rs @@ -1,6 +1,6 @@ use ra_syntax::{SyntaxKind, TextRange, T}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: remove_mut // @@ -26,7 +26,13 @@ pub(crate) fn remove_mut(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { }; let target = mut_token.text_range(); - acc.add(AssistId("remove_mut"), "Remove `mut` keyword", target, |builder| { - builder.delete(TextRange::new(delete_from, delete_to)); - }) + acc.add( + AssistId("remove_mut"), + AssistKind::Refactor, + "Remove `mut` keyword", + target, + |builder| { + builder.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 b8cf30e7f..4a542a5d7 100644 --- a/crates/ra_assists/src/handlers/reorder_fields.rs +++ b/crates/ra_assists/src/handlers/reorder_fields.rs @@ -5,7 +5,7 @@ use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; use ra_ide_db::RootDatabase; use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: reorder_fields // @@ -42,11 +42,17 @@ fn reorder(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { } let target = record.syntax().text_range(); - acc.add(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()); - } - }) + acc.add( + AssistId("reorder_fields"), + AssistKind::RefactorRewrite, + "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()); + } + }, + ) } fn get_fields_kind(node: &SyntaxNode) -> Vec { 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 dfcd787de..9ef121a4c 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 @@ -8,7 +8,7 @@ use ra_syntax::{ AstNode, }; -use crate::{utils::TryEnum, AssistContext, AssistId, Assists}; +use crate::{utils::TryEnum, AssistContext, AssistId, AssistKind, Assists}; // Assist: replace_if_let_with_match // @@ -48,29 +48,36 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext) }; let target = if_expr.syntax().text_range(); - acc.add(AssistId("replace_if_let_with_match"), "Replace with match", target, move |edit| { - let match_expr = { - let then_arm = { - let then_block = then_block.reset_indent().indent(IndentLevel(1)); - let then_expr = unwrap_trivial_block(then_block); - make::match_arm(vec![pat.clone()], then_expr) + acc.add( + AssistId("replace_if_let_with_match"), + AssistKind::RefactorRewrite, + "Replace with match", + target, + move |edit| { + let match_expr = { + let then_arm = { + let then_block = then_block.reset_indent().indent(IndentLevel(1)); + let then_expr = unwrap_trivial_block(then_block); + make::match_arm(vec![pat.clone()], then_expr) + }; + let else_arm = { + let pattern = ctx + .sema + .type_of_pat(&pat) + .and_then(|ty| TryEnum::from_ty(&ctx.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) + }; + let match_expr = + make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])); + match_expr.indent(IndentLevel::from_node(if_expr.syntax())) }; - let else_arm = { - let pattern = ctx - .sema - .type_of_pat(&pat) - .and_then(|ty| TryEnum::from_ty(&ctx.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) - }; - let match_expr = make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])); - match_expr.indent(IndentLevel::from_node(if_expr.syntax())) - }; - edit.replace_ast::(if_expr.into(), match_expr); - }) + 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 761557ac0..174ff1fb4 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 @@ -9,7 +9,7 @@ use ra_syntax::{ AstNode, T, }; -use crate::{utils::TryEnum, AssistContext, AssistId, Assists}; +use crate::{utils::TryEnum, AssistContext, AssistId, AssistKind, Assists}; // Assist: replace_let_with_if_let // @@ -44,24 +44,32 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> let happy_variant = TryEnum::from_ty(&ctx.sema, &ty).map(|it| it.happy_case()); let target = let_kw.text_range(); - acc.add(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( - make::path_unqualified(make::path_segment(make::name_ref(var_name))), - once(make::placeholder_pat().into()), - ) - .into(), - }; - let block = make::block_expr(None, None).indent(IndentLevel::from_node(let_stmt.syntax())); - let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block); - let stmt = make::expr_stmt(if_); + acc.add( + AssistId("replace_let_with_if_let"), + AssistKind::RefactorRewrite, + "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( + make::path_unqualified(make::path_segment(make::name_ref(var_name))), + once(make::placeholder_pat().into()), + ) + .into(), + }; + let block = + make::block_expr(None, None).indent(IndentLevel::from_node(let_stmt.syntax())); + let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block); + let stmt = make::expr_stmt(if_); - let placeholder = stmt.syntax().descendants().find_map(ast::PlaceholderPat::cast).unwrap(); - let stmt = stmt.replace_descendant(placeholder.into(), original_pat); + let placeholder = + stmt.syntax().descendants().find_map(ast::PlaceholderPat::cast).unwrap(); + let stmt = stmt.replace_descendant(placeholder.into(), original_pat); - edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); - }) + edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); + }, + ) } #[cfg(test)] 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 b4784c333..5e06f7f0e 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 @@ -3,7 +3,7 @@ use ra_syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SmolStr, SyntaxNo use crate::{ utils::{find_insert_use_container, insert_use_statement}, - AssistContext, AssistId, Assists, + AssistContext, AssistId, AssistKind, Assists, }; // Assist: replace_qualified_name_with_use @@ -38,6 +38,7 @@ pub(crate) fn replace_qualified_name_with_use( let target = path.syntax().text_range(); acc.add( AssistId("replace_qualified_name_with_use"), + AssistKind::RefactorRewrite, "Replace qualified path with use", target, |builder| { 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 cff7dfb81..5f9705be1 100644 --- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs +++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs @@ -11,7 +11,7 @@ use ra_syntax::{ use crate::{ utils::{render_snippet, Cursor, TryEnum}, - AssistContext, AssistId, Assists, + AssistContext, AssistId, AssistKind, Assists, }; // Assist: replace_unwrap_with_match @@ -46,37 +46,44 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext) 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(); - acc.add(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", target, |builder| { - 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(); + acc.add( + AssistId("replace_unwrap_with_match"), + AssistKind::RefactorRewrite, + "Replace unwrap with match", + target, + |builder| { + 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::expr_unreachable(); - let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); + let unreachable_call = make::expr_unreachable(); + 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) - .indent(IndentLevel::from_node(method_call.syntax())); + let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); + let match_expr = make::expr_match(caller.clone(), match_arm_list) + .indent(IndentLevel::from_node(method_call.syntax())); - let range = method_call.syntax().text_range(); - match ctx.config.snippet_cap { - Some(cap) => { - let err_arm = match_expr - .syntax() - .descendants() - .filter_map(ast::MatchArm::cast) - .last() - .unwrap(); - let snippet = - render_snippet(cap, match_expr.syntax(), Cursor::Before(err_arm.syntax())); - builder.replace_snippet(cap, range, snippet) + let range = method_call.syntax().text_range(); + match ctx.config.snippet_cap { + Some(cap) => { + let err_arm = match_expr + .syntax() + .descendants() + .filter_map(ast::MatchArm::cast) + .last() + .unwrap(); + let snippet = + render_snippet(cap, match_expr.syntax(), Cursor::Before(err_arm.syntax())); + builder.replace_snippet(cap, range, snippet) + } + None => builder.replace(range, match_expr.to_string()), } - None => builder.replace(range, match_expr.to_string()), - } - }) + }, + ) } #[cfg(test)] diff --git a/crates/ra_assists/src/handlers/split_import.rs b/crates/ra_assists/src/handlers/split_import.rs index 38aa199a0..c0cf8d923 100644 --- a/crates/ra_assists/src/handlers/split_import.rs +++ b/crates/ra_assists/src/handlers/split_import.rs @@ -2,7 +2,7 @@ use std::iter::successors; use ra_syntax::{ast, AstNode, T}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: split_import // @@ -28,7 +28,7 @@ pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> } let target = colon_colon.text_range(); - acc.add(AssistId("split_import"), "Split import", target, |edit| { + acc.add(AssistId("split_import"), AssistKind::RefactorExtract, "Split import", target, |edit| { edit.replace_ast(use_tree, new_tree); }) } diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs index 1fb13f481..a66fba7c3 100644 --- a/crates/ra_assists/src/handlers/unwrap_block.rs +++ b/crates/ra_assists/src/handlers/unwrap_block.rs @@ -7,7 +7,7 @@ use ra_syntax::{ AstNode, TextRange, T, }; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: unwrap_block // @@ -50,35 +50,47 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> let ancestor_then_branch = ancestor.then_branch()?; let target = then_branch.syntax().text_range(); - return acc.add(assist_id, assist_label, target, |edit| { - let range_to_del_else_if = TextRange::new( - ancestor_then_branch.syntax().text_range().end(), - l_curly_token.text_range().start(), - ); - let range_to_del_rest = TextRange::new( - then_branch.syntax().text_range().end(), - if_expr.syntax().text_range().end(), - ); - - edit.delete(range_to_del_rest); - edit.delete(range_to_del_else_if); - edit.replace( - target, - update_expr_string(then_branch.to_string(), &[' ', '{']), - ); - }); + return acc.add( + assist_id, + AssistKind::Refactor, + assist_label, + target, + |edit| { + let range_to_del_else_if = TextRange::new( + ancestor_then_branch.syntax().text_range().end(), + l_curly_token.text_range().start(), + ); + let range_to_del_rest = TextRange::new( + then_branch.syntax().text_range().end(), + if_expr.syntax().text_range().end(), + ); + + edit.delete(range_to_del_rest); + edit.delete(range_to_del_else_if); + edit.replace( + target, + update_expr_string(then_branch.to_string(), &[' ', '{']), + ); + }, + ); } } else { let target = block.syntax().text_range(); - return acc.add(assist_id, assist_label, target, |edit| { - let range_to_del = TextRange::new( - then_branch.syntax().text_range().end(), - l_curly_token.text_range().start(), - ); + return acc.add( + assist_id, + AssistKind::RefactorRewrite, + assist_label, + target, + |edit| { + let range_to_del = TextRange::new( + then_branch.syntax().text_range().end(), + l_curly_token.text_range().start(), + ); - edit.delete(range_to_del); - edit.replace(target, update_expr_string(block.to_string(), &[' ', '{'])); - }); + edit.delete(range_to_del); + edit.replace(target, update_expr_string(block.to_string(), &[' ', '{'])); + }, + ); } } _ => return None, @@ -86,7 +98,7 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> let unwrapped = unwrap_trivial_block(block); let target = unwrapped.syntax().text_range(); - acc.add(assist_id, assist_label, target, |builder| { + acc.add(assist_id, AssistKind::RefactorRewrite, assist_label, target, |builder| { builder.replace( parent.syntax().text_range(), update_expr_string(unwrapped.to_string(), &[' ', '{', '\n']), diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 1745f44a5..dd26e192f 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -37,6 +37,7 @@ pub struct GroupLabel(pub String); #[derive(Debug, Clone)] pub struct Assist { pub id: AssistId, + pub kind: AssistKind, /// Short description of the assist, as shown in the UI. pub label: String, pub group: Option, @@ -51,6 +52,18 @@ pub struct ResolvedAssist { pub source_change: SourceChange, } +#[derive(Debug, Copy, Clone)] +pub enum AssistKind { + None, + QuickFix, + Refactor, + RefactorExtract, + RefactorInline, + RefactorRewrite, + Source, + OrganizeImports, +} + impl Assist { /// Return all the assists applicable at the given position. /// @@ -86,13 +99,14 @@ impl Assist { pub(crate) fn new( id: AssistId, + kind: AssistKind, label: String, group: Option, target: TextRange, ) -> Assist { // FIXME: make fields private, so that this invariant can't be broken assert!(label.starts_with(|c: char| c.is_uppercase())); - Assist { id, label, group, target } + Assist { id, kind, label, group, target } } } -- cgit v1.2.3