diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-07-03 13:44:09 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-07-03 13:44:09 +0100 |
commit | f51b0cfdd6c23dd57a0a11154179730171c0425d (patch) | |
tree | f856e6b751b23a20d68e9df5350ec39d5e8ee85b | |
parent | ef6a6d75d5dba2825e6b90e67e0b147a5f7158e1 (diff) | |
parent | 4c9347ecc3356748c52847a29d5e53a65778dc13 (diff) |
Merge #5116
5116: Categorize assists r=matklad a=kjeremy
Categorize assists so that editors can use them. Follows the LSP spec pretty close (and some things may need adjustments) but this populates the Refactor menu in vscode and pushes quickfixes through again.
This is a prerequisite to filtering out assists that the client doesn't care about.
Fixes #4147
Co-authored-by: Jeremy Kolb <[email protected]>
Co-authored-by: kjeremy <[email protected]>
43 files changed, 593 insertions, 442 deletions
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs index fa70c8496..acb07e36a 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; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | assist_context::{AssistContext, Assists}, | 10 | assist_context::{AssistContext, Assists}, |
11 | AssistId, | 11 | AssistId, AssistKind, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | // Assist: add_custom_impl | 14 | // Assist: add_custom_impl |
@@ -52,7 +52,7 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
52 | format!("Add custom impl `{}` for `{}`", trait_token.text().as_str(), annotated_name); | 52 | format!("Add custom impl `{}` for `{}`", trait_token.text().as_str(), annotated_name); |
53 | 53 | ||
54 | let target = attr.syntax().text_range(); | 54 | let target = attr.syntax().text_range(); |
55 | acc.add(AssistId("add_custom_impl"), label, target, |builder| { | 55 | acc.add(AssistId("add_custom_impl", AssistKind::Refactor), label, target, |builder| { |
56 | let new_attr_input = input | 56 | let new_attr_input = input |
57 | .syntax() | 57 | .syntax() |
58 | .descendants_with_tokens() | 58 | .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..e2b94e7f8 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::{ | |||
4 | TextSize, | 4 | TextSize, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use crate::{AssistContext, AssistId, Assists}; | 7 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
8 | 8 | ||
9 | // Assist: add_derive | 9 | // Assist: add_derive |
10 | // | 10 | // |
@@ -29,7 +29,7 @@ pub(crate) fn add_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
29 | let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; | 29 | let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; |
30 | let node_start = derive_insertion_offset(&nominal)?; | 30 | let node_start = derive_insertion_offset(&nominal)?; |
31 | let target = nominal.syntax().text_range(); | 31 | let target = nominal.syntax().text_range(); |
32 | acc.add(AssistId("add_derive"), "Add `#[derive]`", target, |builder| { | 32 | acc.add(AssistId("add_derive", AssistKind::None), "Add `#[derive]`", target, |builder| { |
33 | let derive_attr = nominal | 33 | let derive_attr = nominal |
34 | .attrs() | 34 | .attrs() |
35 | .filter_map(|x| x.as_simple_call()) | 35 | .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..39a5321d1 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::{ | |||
4 | TextRange, | 4 | TextRange, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use crate::{AssistContext, AssistId, Assists}; | 7 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
8 | 8 | ||
9 | // Assist: add_explicit_type | 9 | // Assist: add_explicit_type |
10 | // | 10 | // |
@@ -59,7 +59,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
59 | 59 | ||
60 | let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?; | 60 | let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?; |
61 | acc.add( | 61 | acc.add( |
62 | AssistId("add_explicit_type"), | 62 | AssistId("add_explicit_type", AssistKind::RefactorRewrite), |
63 | format!("Insert explicit type `{}`", inferred_type), | 63 | format!("Insert explicit type `{}`", inferred_type), |
64 | pat_range, | 64 | pat_range, |
65 | |builder| match ascribed_ty { | 65 | |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..a324670ed 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; | |||
2 | use ra_syntax::ast::{self, AstNode, NameOwner}; | 2 | use ra_syntax::ast::{self, AstNode, NameOwner}; |
3 | use test_utils::mark; | 3 | use test_utils::mark; |
4 | 4 | ||
5 | use crate::{utils::FamousDefs, AssistContext, AssistId, Assists}; | 5 | use crate::{utils::FamousDefs, AssistContext, AssistId, AssistKind, Assists}; |
6 | 6 | ||
7 | // Assist: add_from_impl_for_enum | 7 | // Assist: add_from_impl_for_enum |
8 | // | 8 | // |
@@ -45,7 +45,7 @@ pub(crate) fn add_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> | |||
45 | 45 | ||
46 | let target = variant.syntax().text_range(); | 46 | let target = variant.syntax().text_range(); |
47 | acc.add( | 47 | acc.add( |
48 | AssistId("add_from_impl_for_enum"), | 48 | AssistId("add_from_impl_for_enum", AssistKind::Refactor), |
49 | "Add From impl for this enum variant", | 49 | "Add From impl for this enum variant", |
50 | target, | 50 | target, |
51 | |edit| { | 51 | |edit| { |
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs index fc4e82309..7150eb53a 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}; | |||
13 | use crate::{ | 13 | use crate::{ |
14 | assist_config::SnippetCap, | 14 | assist_config::SnippetCap, |
15 | utils::{render_snippet, Cursor}, | 15 | utils::{render_snippet, Cursor}, |
16 | AssistContext, AssistId, Assists, | 16 | AssistContext, AssistId, AssistKind, Assists, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | // Assist: add_function | 19 | // Assist: add_function |
@@ -62,7 +62,7 @@ pub(crate) fn add_function(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
62 | let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; | 62 | let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; |
63 | 63 | ||
64 | let target = call.syntax().text_range(); | 64 | let target = call.syntax().text_range(); |
65 | acc.add(AssistId("add_function"), "Add function", target, |builder| { | 65 | acc.add(AssistId("add_function", AssistKind::None), "Add function", target, |builder| { |
66 | let function_template = function_builder.render(); | 66 | let function_template = function_builder.render(); |
67 | builder.edit_file(function_template.file); | 67 | builder.edit_file(function_template.file); |
68 | let new_fn = function_template.to_string(ctx.config.snippet_cap); | 68 | let new_fn = function_template.to_string(ctx.config.snippet_cap); |
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index eceba7d0a..2f603ef9c 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; | 1 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; |
2 | use stdx::{format_to, SepBy}; | 2 | use stdx::{format_to, SepBy}; |
3 | 3 | ||
4 | use crate::{AssistContext, AssistId, Assists}; | 4 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
5 | 5 | ||
6 | // Assist: add_impl | 6 | // Assist: add_impl |
7 | // | 7 | // |
@@ -26,38 +26,45 @@ pub(crate) fn add_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
26 | let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; | 26 | let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; |
27 | let name = nominal.name()?; | 27 | let name = nominal.name()?; |
28 | let target = nominal.syntax().text_range(); | 28 | let target = nominal.syntax().text_range(); |
29 | acc.add(AssistId("add_impl"), format!("Implement {}", name.text().as_str()), target, |edit| { | 29 | acc.add( |
30 | let type_params = nominal.type_param_list(); | 30 | AssistId("add_impl", AssistKind::Refactor), |
31 | let start_offset = nominal.syntax().text_range().end(); | 31 | format!("Implement {}", name.text().as_str()), |
32 | let mut buf = String::new(); | 32 | target, |
33 | buf.push_str("\n\nimpl"); | 33 | |edit| { |
34 | if let Some(type_params) = &type_params { | 34 | let type_params = nominal.type_param_list(); |
35 | format_to!(buf, "{}", type_params.syntax()); | 35 | let start_offset = nominal.syntax().text_range().end(); |
36 | } | 36 | let mut buf = String::new(); |
37 | buf.push_str(" "); | 37 | buf.push_str("\n\nimpl"); |
38 | buf.push_str(name.text().as_str()); | 38 | if let Some(type_params) = &type_params { |
39 | if let Some(type_params) = type_params { | 39 | format_to!(buf, "{}", type_params.syntax()); |
40 | let lifetime_params = type_params | 40 | } |
41 | .lifetime_params() | 41 | buf.push_str(" "); |
42 | .filter_map(|it| it.lifetime_token()) | 42 | buf.push_str(name.text().as_str()); |
43 | .map(|it| it.text().clone()); | 43 | if let Some(type_params) = type_params { |
44 | let type_params = | 44 | let lifetime_params = type_params |
45 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); | 45 | .lifetime_params() |
46 | .filter_map(|it| it.lifetime_token()) | ||
47 | .map(|it| it.text().clone()); | ||
48 | let type_params = type_params | ||
49 | .type_params() | ||
50 | .filter_map(|it| it.name()) | ||
51 | .map(|it| it.text().clone()); | ||
46 | 52 | ||
47 | let generic_params = lifetime_params.chain(type_params).sep_by(", "); | 53 | let generic_params = lifetime_params.chain(type_params).sep_by(", "); |
48 | format_to!(buf, "<{}>", generic_params) | 54 | format_to!(buf, "<{}>", generic_params) |
49 | } | ||
50 | match ctx.config.snippet_cap { | ||
51 | Some(cap) => { | ||
52 | buf.push_str(" {\n $0\n}"); | ||
53 | edit.insert_snippet(cap, start_offset, buf); | ||
54 | } | 55 | } |
55 | None => { | 56 | match ctx.config.snippet_cap { |
56 | buf.push_str(" {\n}"); | 57 | Some(cap) => { |
57 | edit.insert(start_offset, buf); | 58 | buf.push_str(" {\n $0\n}"); |
59 | edit.insert_snippet(cap, start_offset, buf); | ||
60 | } | ||
61 | None => { | ||
62 | buf.push_str(" {\n}"); | ||
63 | edit.insert(start_offset, buf); | ||
64 | } | ||
58 | } | 65 | } |
59 | } | 66 | }, |
60 | }) | 67 | ) |
61 | } | 68 | } |
62 | 69 | ||
63 | #[cfg(test)] | 70 | #[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..d6aaf53f1 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::{ | |||
12 | assist_context::{AssistContext, Assists}, | 12 | assist_context::{AssistContext, Assists}, |
13 | ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, | 13 | ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, |
14 | utils::{get_missing_assoc_items, render_snippet, resolve_target_trait, Cursor}, | 14 | utils::{get_missing_assoc_items, render_snippet, resolve_target_trait, Cursor}, |
15 | AssistId, | 15 | AssistId, AssistKind, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | #[derive(PartialEq)] | 18 | #[derive(PartialEq)] |
@@ -147,7 +147,7 @@ fn add_missing_impl_members_inner( | |||
147 | } | 147 | } |
148 | 148 | ||
149 | let target = impl_def.syntax().text_range(); | 149 | let target = impl_def.syntax().text_range(); |
150 | acc.add(AssistId(assist_id), label, target, |builder| { | 150 | acc.add(AssistId(assist_id, AssistKind::QuickFix), label, target, |builder| { |
151 | let n_existing_items = impl_item_list.assoc_items().count(); | 151 | let n_existing_items = impl_item_list.assoc_items().count(); |
152 | let source_scope = ctx.sema.scope_for_def(trait_); | 152 | let source_scope = ctx.sema.scope_for_def(trait_); |
153 | let target_scope = ctx.sema.scope(impl_item_list.syntax()); | 153 | 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..0b3d29c7c 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::{ | |||
7 | }; | 7 | }; |
8 | use stdx::{format_to, SepBy}; | 8 | use stdx::{format_to, SepBy}; |
9 | 9 | ||
10 | use crate::{AssistContext, AssistId, Assists}; | 10 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
11 | 11 | ||
12 | // Assist: add_new | 12 | // Assist: add_new |
13 | // | 13 | // |
@@ -42,7 +42,7 @@ pub(crate) fn add_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
42 | let impl_def = find_struct_impl(&ctx, &strukt)?; | 42 | let impl_def = find_struct_impl(&ctx, &strukt)?; |
43 | 43 | ||
44 | let target = strukt.syntax().text_range(); | 44 | let target = strukt.syntax().text_range(); |
45 | acc.add(AssistId("add_new"), "Add default constructor", target, |builder| { | 45 | acc.add(AssistId("add_new", AssistKind::None), "Add default constructor", target, |builder| { |
46 | let mut buf = String::with_capacity(512); | 46 | let mut buf = String::with_capacity(512); |
47 | 47 | ||
48 | if impl_def.is_some() { | 48 | if impl_def.is_some() { |
diff --git a/crates/ra_assists/src/handlers/add_turbo_fish.rs b/crates/ra_assists/src/handlers/add_turbo_fish.rs index 26acf81f2..f7e1a7b05 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; | |||
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | assist_context::{AssistContext, Assists}, | 6 | assist_context::{AssistContext, Assists}, |
7 | AssistId, | 7 | AssistId, AssistKind, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | // Assist: add_turbo_fish | 10 | // Assist: add_turbo_fish |
@@ -45,12 +45,15 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
45 | mark::hit!(add_turbo_fish_non_generic); | 45 | mark::hit!(add_turbo_fish_non_generic); |
46 | return None; | 46 | return None; |
47 | } | 47 | } |
48 | acc.add(AssistId("add_turbo_fish"), "Add `::<>`", ident.text_range(), |builder| { | 48 | acc.add( |
49 | match ctx.config.snippet_cap { | 49 | AssistId("add_turbo_fish", AssistKind::RefactorRewrite), |
50 | "Add `::<>`", | ||
51 | ident.text_range(), | ||
52 | |builder| match ctx.config.snippet_cap { | ||
50 | Some(cap) => builder.insert_snippet(cap, ident.text_range().end(), "::<${0:_}>"), | 53 | Some(cap) => builder.insert_snippet(cap, ident.text_range().end(), "::<${0:_}>"), |
51 | None => builder.insert(ident.text_range().end(), "::<_>"), | 54 | None => builder.insert(ident.text_range().end(), "::<_>"), |
52 | } | 55 | }, |
53 | }) | 56 | ) |
54 | } | 57 | } |
55 | 58 | ||
56 | #[cfg(test)] | 59 | #[cfg(test)] |
diff --git a/crates/ra_assists/src/handlers/apply_demorgan.rs b/crates/ra_assists/src/handlers/apply_demorgan.rs index 233e8fb8e..de701f8b8 100644 --- a/crates/ra_assists/src/handlers/apply_demorgan.rs +++ b/crates/ra_assists/src/handlers/apply_demorgan.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_syntax::ast::{self, AstNode}; | 1 | use ra_syntax::ast::{self, AstNode}; |
2 | 2 | ||
3 | use crate::{utils::invert_boolean_expression, AssistContext, AssistId, Assists}; | 3 | use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists}; |
4 | 4 | ||
5 | // Assist: apply_demorgan | 5 | // Assist: apply_demorgan |
6 | // | 6 | // |
@@ -39,11 +39,16 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
39 | let rhs_range = rhs.syntax().text_range(); | 39 | let rhs_range = rhs.syntax().text_range(); |
40 | let not_rhs = invert_boolean_expression(rhs); | 40 | let not_rhs = invert_boolean_expression(rhs); |
41 | 41 | ||
42 | acc.add(AssistId("apply_demorgan"), "Apply De Morgan's law", op_range, |edit| { | 42 | acc.add( |
43 | edit.replace(op_range, opposite_op); | 43 | AssistId("apply_demorgan", AssistKind::RefactorRewrite), |
44 | edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); | 44 | "Apply De Morgan's law", |
45 | edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); | 45 | op_range, |
46 | }) | 46 | |edit| { |
47 | edit.replace(op_range, opposite_op); | ||
48 | edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); | ||
49 | edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); | ||
50 | }, | ||
51 | ) | ||
47 | } | 52 | } |
48 | 53 | ||
49 | // Return the opposite text for a given logical operator, if it makes sense | 54 | // 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..947be3b9b 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::{ | |||
13 | }; | 13 | }; |
14 | use rustc_hash::FxHashSet; | 14 | use rustc_hash::FxHashSet; |
15 | 15 | ||
16 | use crate::{utils::insert_use_statement, AssistContext, AssistId, Assists, GroupLabel}; | 16 | use crate::{ |
17 | utils::insert_use_statement, AssistContext, AssistId, AssistKind, Assists, GroupLabel, | ||
18 | }; | ||
17 | 19 | ||
18 | // Assist: auto_import | 20 | // Assist: auto_import |
19 | // | 21 | // |
@@ -46,7 +48,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
46 | for import in proposed_imports { | 48 | for import in proposed_imports { |
47 | acc.add_group( | 49 | acc.add_group( |
48 | &group, | 50 | &group, |
49 | AssistId("auto_import"), | 51 | AssistId("auto_import", AssistKind::QuickFix), |
50 | format!("Import `{}`", &import), | 52 | format!("Import `{}`", &import), |
51 | range, | 53 | range, |
52 | |builder| { | 54 | |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..24e5f6963 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::{ | |||
3 | AstNode, SyntaxNode, | 3 | AstNode, SyntaxNode, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{AssistContext, AssistId, Assists}; | 6 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
7 | use test_utils::mark; | 7 | use test_utils::mark; |
8 | 8 | ||
9 | // Assist: change_return_type_to_result | 9 | // Assist: change_return_type_to_result |
@@ -35,7 +35,7 @@ pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContex | |||
35 | let block_expr = &fn_def.body()?; | 35 | let block_expr = &fn_def.body()?; |
36 | 36 | ||
37 | acc.add( | 37 | acc.add( |
38 | AssistId("change_return_type_to_result"), | 38 | AssistId("change_return_type_to_result", AssistKind::RefactorRewrite), |
39 | "Change return type to Result", | 39 | "Change return type to Result", |
40 | type_ref.syntax().text_range(), | 40 | type_ref.syntax().text_range(), |
41 | |builder| { | 41 | |builder| { |
diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index 157c7b665..703ee2143 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::{ | |||
6 | }; | 6 | }; |
7 | use test_utils::mark; | 7 | use test_utils::mark; |
8 | 8 | ||
9 | use crate::{utils::vis_offset, AssistContext, AssistId, Assists}; | 9 | use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; |
10 | 10 | ||
11 | // Assist: change_visibility | 11 | // Assist: change_visibility |
12 | // | 12 | // |
@@ -62,16 +62,21 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
62 | return None; | 62 | return None; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | acc.add(AssistId("change_visibility"), "Change visibility to pub(crate)", target, |edit| { | 65 | acc.add( |
66 | edit.insert(offset, "pub(crate) "); | 66 | AssistId("change_visibility", AssistKind::RefactorRewrite), |
67 | }) | 67 | "Change visibility to pub(crate)", |
68 | target, | ||
69 | |edit| { | ||
70 | edit.insert(offset, "pub(crate) "); | ||
71 | }, | ||
72 | ) | ||
68 | } | 73 | } |
69 | 74 | ||
70 | fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { | 75 | fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { |
71 | if vis.syntax().text() == "pub" { | 76 | if vis.syntax().text() == "pub" { |
72 | let target = vis.syntax().text_range(); | 77 | let target = vis.syntax().text_range(); |
73 | return acc.add( | 78 | return acc.add( |
74 | AssistId("change_visibility"), | 79 | AssistId("change_visibility", AssistKind::RefactorRewrite), |
75 | "Change Visibility to pub(crate)", | 80 | "Change Visibility to pub(crate)", |
76 | target, | 81 | target, |
77 | |edit| { | 82 | |edit| { |
@@ -82,7 +87,7 @@ fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { | |||
82 | if vis.syntax().text() == "pub(crate)" { | 87 | if vis.syntax().text() == "pub(crate)" { |
83 | let target = vis.syntax().text_range(); | 88 | let target = vis.syntax().text_range(); |
84 | return acc.add( | 89 | return acc.add( |
85 | AssistId("change_visibility"), | 90 | AssistId("change_visibility", AssistKind::RefactorRewrite), |
86 | "Change visibility to pub", | 91 | "Change visibility to pub", |
87 | target, | 92 | target, |
88 | |edit| { | 93 | |edit| { |
diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs index dfade7432..330459f3c 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::{ | |||
15 | use crate::{ | 15 | use crate::{ |
16 | assist_context::{AssistContext, Assists}, | 16 | assist_context::{AssistContext, Assists}, |
17 | utils::invert_boolean_expression, | 17 | utils::invert_boolean_expression, |
18 | AssistId, | 18 | AssistId, AssistKind, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | // Assist: convert_to_guarded_return | 21 | // Assist: convert_to_guarded_return |
@@ -99,86 +99,92 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) | |||
99 | then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; | 99 | then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; |
100 | 100 | ||
101 | let target = if_expr.syntax().text_range(); | 101 | let target = if_expr.syntax().text_range(); |
102 | acc.add(AssistId("convert_to_guarded_return"), "Convert to guarded return", target, |edit| { | 102 | acc.add( |
103 | let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); | 103 | AssistId("convert_to_guarded_return", AssistKind::RefactorRewrite), |
104 | let new_block = match if_let_pat { | 104 | "Convert to guarded return", |
105 | None => { | 105 | target, |
106 | // If. | 106 | |edit| { |
107 | let new_expr = { | 107 | let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); |
108 | let then_branch = | 108 | let new_block = match if_let_pat { |
109 | make::block_expr(once(make::expr_stmt(early_expression).into()), None); | 109 | None => { |
110 | let cond = invert_boolean_expression(cond_expr); | 110 | // If. |
111 | make::expr_if(make::condition(cond, None), then_branch).indent(if_indent_level) | 111 | let new_expr = { |
112 | }; | 112 | let then_branch = |
113 | replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) | 113 | make::block_expr(once(make::expr_stmt(early_expression).into()), None); |
114 | } | 114 | let cond = invert_boolean_expression(cond_expr); |
115 | Some((path, bound_ident)) => { | 115 | make::expr_if(make::condition(cond, None), then_branch) |
116 | // If-let. | 116 | .indent(if_indent_level) |
117 | let match_expr = { | ||
118 | let happy_arm = { | ||
119 | let pat = make::tuple_struct_pat( | ||
120 | path, | ||
121 | once(make::bind_pat(make::name("it")).into()), | ||
122 | ); | ||
123 | let expr = { | ||
124 | let name_ref = make::name_ref("it"); | ||
125 | let segment = make::path_segment(name_ref); | ||
126 | let path = make::path_unqualified(segment); | ||
127 | make::expr_path(path) | ||
128 | }; | ||
129 | make::match_arm(once(pat.into()), expr) | ||
130 | }; | 117 | }; |
118 | replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) | ||
119 | } | ||
120 | Some((path, bound_ident)) => { | ||
121 | // If-let. | ||
122 | let match_expr = { | ||
123 | let happy_arm = { | ||
124 | let pat = make::tuple_struct_pat( | ||
125 | path, | ||
126 | once(make::bind_pat(make::name("it")).into()), | ||
127 | ); | ||
128 | let expr = { | ||
129 | let name_ref = make::name_ref("it"); | ||
130 | let segment = make::path_segment(name_ref); | ||
131 | let path = make::path_unqualified(segment); | ||
132 | make::expr_path(path) | ||
133 | }; | ||
134 | make::match_arm(once(pat.into()), expr) | ||
135 | }; | ||
131 | 136 | ||
132 | let sad_arm = make::match_arm( | 137 | let sad_arm = make::match_arm( |
133 | // FIXME: would be cool to use `None` or `Err(_)` if appropriate | 138 | // FIXME: would be cool to use `None` or `Err(_)` if appropriate |
134 | once(make::placeholder_pat().into()), | 139 | once(make::placeholder_pat().into()), |
135 | early_expression, | 140 | early_expression, |
136 | ); | 141 | ); |
137 | 142 | ||
138 | make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) | 143 | make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) |
139 | }; | 144 | }; |
140 | 145 | ||
141 | let let_stmt = make::let_stmt( | 146 | let let_stmt = make::let_stmt( |
142 | make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), | 147 | make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), |
143 | Some(match_expr), | 148 | Some(match_expr), |
149 | ); | ||
150 | let let_stmt = let_stmt.indent(if_indent_level); | ||
151 | replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) | ||
152 | } | ||
153 | }; | ||
154 | edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); | ||
155 | |||
156 | fn replace( | ||
157 | new_expr: &SyntaxNode, | ||
158 | then_block: &ast::BlockExpr, | ||
159 | parent_block: &ast::BlockExpr, | ||
160 | if_expr: &ast::IfExpr, | ||
161 | ) -> SyntaxNode { | ||
162 | let then_block_items = then_block.dedent(IndentLevel(1)); | ||
163 | let end_of_then = then_block_items.syntax().last_child_or_token().unwrap(); | ||
164 | let end_of_then = | ||
165 | if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { | ||
166 | end_of_then.prev_sibling_or_token().unwrap() | ||
167 | } else { | ||
168 | end_of_then | ||
169 | }; | ||
170 | let mut then_statements = new_expr.children_with_tokens().chain( | ||
171 | then_block_items | ||
172 | .syntax() | ||
173 | .children_with_tokens() | ||
174 | .skip(1) | ||
175 | .take_while(|i| *i != end_of_then), | ||
144 | ); | 176 | ); |
145 | let let_stmt = let_stmt.indent(if_indent_level); | 177 | replace_children( |
146 | replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) | 178 | &parent_block.syntax(), |
179 | RangeInclusive::new( | ||
180 | if_expr.clone().syntax().clone().into(), | ||
181 | if_expr.syntax().clone().into(), | ||
182 | ), | ||
183 | &mut then_statements, | ||
184 | ) | ||
147 | } | 185 | } |
148 | }; | 186 | }, |
149 | edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); | 187 | ) |
150 | |||
151 | fn replace( | ||
152 | new_expr: &SyntaxNode, | ||
153 | then_block: &ast::BlockExpr, | ||
154 | parent_block: &ast::BlockExpr, | ||
155 | if_expr: &ast::IfExpr, | ||
156 | ) -> SyntaxNode { | ||
157 | let then_block_items = then_block.dedent(IndentLevel(1)); | ||
158 | let end_of_then = then_block_items.syntax().last_child_or_token().unwrap(); | ||
159 | let end_of_then = | ||
160 | if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { | ||
161 | end_of_then.prev_sibling_or_token().unwrap() | ||
162 | } else { | ||
163 | end_of_then | ||
164 | }; | ||
165 | let mut then_statements = new_expr.children_with_tokens().chain( | ||
166 | then_block_items | ||
167 | .syntax() | ||
168 | .children_with_tokens() | ||
169 | .skip(1) | ||
170 | .take_while(|i| *i != end_of_then), | ||
171 | ); | ||
172 | replace_children( | ||
173 | &parent_block.syntax(), | ||
174 | RangeInclusive::new( | ||
175 | if_expr.clone().syntax().clone().into(), | ||
176 | if_expr.syntax().clone().into(), | ||
177 | ), | ||
178 | &mut then_statements, | ||
179 | ) | ||
180 | } | ||
181 | }) | ||
182 | } | 188 | } |
183 | 189 | ||
184 | #[cfg(test)] | 190 | #[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..2b8e273b3 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::{ | |||
10 | use rustc_hash::FxHashSet; | 10 | use rustc_hash::FxHashSet; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | assist_context::AssistBuilder, utils::insert_use_statement, AssistContext, AssistId, Assists, | 13 | assist_context::AssistBuilder, utils::insert_use_statement, AssistContext, AssistId, |
14 | AssistKind, Assists, | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | // Assist: extract_struct_from_enum_variant | 17 | // Assist: extract_struct_from_enum_variant |
@@ -48,7 +49,7 @@ pub(crate) fn extract_struct_from_enum_variant( | |||
48 | let current_module = enum_hir.module(ctx.db()); | 49 | let current_module = enum_hir.module(ctx.db()); |
49 | let target = variant.syntax().text_range(); | 50 | let target = variant.syntax().text_range(); |
50 | acc.add( | 51 | acc.add( |
51 | AssistId("extract_struct_from_enum_variant"), | 52 | AssistId("extract_struct_from_enum_variant", AssistKind::RefactorRewrite), |
52 | "Extract struct from enum variant", | 53 | "Extract struct from enum variant", |
53 | target, | 54 | target, |
54 | |builder| { | 55 | |builder| { |
diff --git a/crates/ra_assists/src/handlers/extract_variable.rs b/crates/ra_assists/src/handlers/extract_variable.rs index c4150d2bb..481baf1a4 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::{ | |||
9 | use stdx::format_to; | 9 | use stdx::format_to; |
10 | use test_utils::mark; | 10 | use test_utils::mark; |
11 | 11 | ||
12 | use crate::{AssistContext, AssistId, Assists}; | 12 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
13 | 13 | ||
14 | // Assist: extract_variable | 14 | // Assist: extract_variable |
15 | // | 15 | // |
@@ -43,80 +43,85 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
43 | return None; | 43 | return None; |
44 | } | 44 | } |
45 | let target = expr.syntax().text_range(); | 45 | let target = expr.syntax().text_range(); |
46 | acc.add(AssistId("extract_variable"), "Extract into variable", target, move |edit| { | 46 | acc.add( |
47 | let field_shorthand = match expr.syntax().parent().and_then(ast::RecordField::cast) { | 47 | AssistId("extract_variable", AssistKind::RefactorExtract), |
48 | Some(field) => field.name_ref(), | 48 | "Extract into variable", |
49 | None => None, | 49 | target, |
50 | }; | 50 | move |edit| { |
51 | 51 | let field_shorthand = match expr.syntax().parent().and_then(ast::RecordField::cast) { | |
52 | let mut buf = String::new(); | 52 | Some(field) => field.name_ref(), |
53 | 53 | None => None, | |
54 | let var_name = match &field_shorthand { | 54 | }; |
55 | Some(it) => it.to_string(), | 55 | |
56 | None => "var_name".to_string(), | 56 | let mut buf = String::new(); |
57 | }; | 57 | |
58 | let expr_range = match &field_shorthand { | 58 | let var_name = match &field_shorthand { |
59 | Some(it) => it.syntax().text_range().cover(expr.syntax().text_range()), | 59 | Some(it) => it.to_string(), |
60 | None => expr.syntax().text_range(), | 60 | None => "var_name".to_string(), |
61 | }; | 61 | }; |
62 | 62 | let expr_range = match &field_shorthand { | |
63 | if wrap_in_block { | 63 | Some(it) => it.syntax().text_range().cover(expr.syntax().text_range()), |
64 | format_to!(buf, "{{ let {} = ", var_name); | 64 | None => expr.syntax().text_range(), |
65 | } else { | 65 | }; |
66 | format_to!(buf, "let {} = ", var_name); | 66 | |
67 | }; | 67 | if wrap_in_block { |
68 | format_to!(buf, "{}", expr.syntax()); | 68 | format_to!(buf, "{{ let {} = ", var_name); |
69 | 69 | } else { | |
70 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); | 70 | format_to!(buf, "let {} = ", var_name); |
71 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { | 71 | }; |
72 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) | 72 | format_to!(buf, "{}", expr.syntax()); |
73 | } else { | 73 | |
74 | false | 74 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); |
75 | }; | 75 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { |
76 | if is_full_stmt { | 76 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) |
77 | mark::hit!(test_extract_var_expr_stmt); | 77 | } else { |
78 | if full_stmt.unwrap().semicolon_token().is_none() { | 78 | false |
79 | buf.push_str(";"); | 79 | }; |
80 | if is_full_stmt { | ||
81 | mark::hit!(test_extract_var_expr_stmt); | ||
82 | if full_stmt.unwrap().semicolon_token().is_none() { | ||
83 | buf.push_str(";"); | ||
84 | } | ||
85 | match ctx.config.snippet_cap { | ||
86 | Some(cap) => { | ||
87 | let snip = buf | ||
88 | .replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); | ||
89 | edit.replace_snippet(cap, expr_range, snip) | ||
90 | } | ||
91 | None => edit.replace(expr_range, buf), | ||
92 | } | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | buf.push_str(";"); | ||
97 | |||
98 | // We want to maintain the indent level, | ||
99 | // but we do not want to duplicate possible | ||
100 | // extra newlines in the indent block | ||
101 | let text = indent.text(); | ||
102 | if text.starts_with('\n') { | ||
103 | buf.push_str("\n"); | ||
104 | buf.push_str(text.trim_start_matches('\n')); | ||
105 | } else { | ||
106 | buf.push_str(text); | ||
80 | } | 107 | } |
108 | |||
109 | edit.replace(expr_range, var_name.clone()); | ||
110 | let offset = anchor_stmt.text_range().start(); | ||
81 | match ctx.config.snippet_cap { | 111 | match ctx.config.snippet_cap { |
82 | Some(cap) => { | 112 | Some(cap) => { |
83 | let snip = | 113 | let snip = |
84 | buf.replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); | 114 | buf.replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); |
85 | edit.replace_snippet(cap, expr_range, snip) | 115 | edit.insert_snippet(cap, offset, snip) |
86 | } | 116 | } |
87 | None => edit.replace(expr_range, buf), | 117 | None => edit.insert(offset, buf), |
88 | } | 118 | } |
89 | return; | ||
90 | } | ||
91 | 119 | ||
92 | buf.push_str(";"); | 120 | if wrap_in_block { |
93 | 121 | edit.insert(anchor_stmt.text_range().end(), " }"); | |
94 | // We want to maintain the indent level, | ||
95 | // but we do not want to duplicate possible | ||
96 | // extra newlines in the indent block | ||
97 | let text = indent.text(); | ||
98 | if text.starts_with('\n') { | ||
99 | buf.push_str("\n"); | ||
100 | buf.push_str(text.trim_start_matches('\n')); | ||
101 | } else { | ||
102 | buf.push_str(text); | ||
103 | } | ||
104 | |||
105 | edit.replace(expr_range, var_name.clone()); | ||
106 | let offset = anchor_stmt.text_range().start(); | ||
107 | match ctx.config.snippet_cap { | ||
108 | Some(cap) => { | ||
109 | let snip = | ||
110 | buf.replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); | ||
111 | edit.insert_snippet(cap, offset, snip) | ||
112 | } | 122 | } |
113 | None => edit.insert(offset, buf), | 123 | }, |
114 | } | 124 | ) |
115 | |||
116 | if wrap_in_block { | ||
117 | edit.insert(anchor_stmt.text_range().end(), " }"); | ||
118 | } | ||
119 | }) | ||
120 | } | 125 | } |
121 | 126 | ||
122 | /// Check whether the node is a valid expression which can be extracted to a variable. | 127 | /// 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..511355e07 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; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | utils::{render_snippet, Cursor, FamousDefs}, | 10 | utils::{render_snippet, Cursor, FamousDefs}, |
11 | AssistContext, AssistId, Assists, | 11 | AssistContext, AssistId, AssistKind, Assists, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | // Assist: fill_match_arms | 14 | // Assist: fill_match_arms |
@@ -103,24 +103,29 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
103 | } | 103 | } |
104 | 104 | ||
105 | let target = match_expr.syntax().text_range(); | 105 | let target = match_expr.syntax().text_range(); |
106 | acc.add(AssistId("fill_match_arms"), "Fill match arms", target, |builder| { | 106 | acc.add( |
107 | let new_arm_list = match_arm_list.remove_placeholder(); | 107 | AssistId("fill_match_arms", AssistKind::QuickFix), |
108 | let n_old_arms = new_arm_list.arms().count(); | 108 | "Fill match arms", |
109 | let new_arm_list = new_arm_list.append_arms(missing_arms); | 109 | target, |
110 | let first_new_arm = new_arm_list.arms().nth(n_old_arms); | 110 | |builder| { |
111 | let old_range = match_arm_list.syntax().text_range(); | 111 | let new_arm_list = match_arm_list.remove_placeholder(); |
112 | match (first_new_arm, ctx.config.snippet_cap) { | 112 | let n_old_arms = new_arm_list.arms().count(); |
113 | (Some(first_new_arm), Some(cap)) => { | 113 | let new_arm_list = new_arm_list.append_arms(missing_arms); |
114 | let snippet = render_snippet( | 114 | let first_new_arm = new_arm_list.arms().nth(n_old_arms); |
115 | cap, | 115 | let old_range = match_arm_list.syntax().text_range(); |
116 | new_arm_list.syntax(), | 116 | match (first_new_arm, ctx.config.snippet_cap) { |
117 | Cursor::Before(first_new_arm.syntax()), | 117 | (Some(first_new_arm), Some(cap)) => { |
118 | ); | 118 | let snippet = render_snippet( |
119 | builder.replace_snippet(cap, old_range, snippet); | 119 | cap, |
120 | } | 120 | new_arm_list.syntax(), |
121 | _ => builder.replace(old_range, new_arm_list.to_string()), | 121 | Cursor::Before(first_new_arm.syntax()), |
122 | } | 122 | ); |
123 | }) | 123 | builder.replace_snippet(cap, old_range, snippet); |
124 | } | ||
125 | _ => builder.replace(old_range, new_arm_list.to_string()), | ||
126 | } | ||
127 | }, | ||
128 | ) | ||
124 | } | 129 | } |
125 | 130 | ||
126 | fn is_variant_missing(existing_arms: &mut Vec<MatchArm>, var: &Pat) -> bool { | 131 | fn is_variant_missing(existing_arms: &mut Vec<MatchArm>, 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..e212557c8 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}; | |||
2 | use ra_db::FileId; | 2 | use ra_db::FileId; |
3 | use ra_syntax::{ast, AstNode, TextRange, TextSize}; | 3 | use ra_syntax::{ast, AstNode, TextRange, TextSize}; |
4 | 4 | ||
5 | use crate::{utils::vis_offset, AssistContext, AssistId, Assists}; | 5 | use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; |
6 | 6 | ||
7 | // FIXME: this really should be a fix for diagnostic, rather than an assist. | 7 | // FIXME: this really should be a fix for diagnostic, rather than an assist. |
8 | 8 | ||
@@ -58,7 +58,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O | |||
58 | Some(name) => format!("Change visibility of {} to {}", name, missing_visibility), | 58 | Some(name) => format!("Change visibility of {} to {}", name, missing_visibility), |
59 | }; | 59 | }; |
60 | 60 | ||
61 | acc.add(AssistId("fix_visibility"), assist_label, target, |builder| { | 61 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { |
62 | builder.edit_file(target_file); | 62 | builder.edit_file(target_file); |
63 | match ctx.config.snippet_cap { | 63 | match ctx.config.snippet_cap { |
64 | Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | 64 | 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) -> | |||
101 | let assist_label = | 101 | let assist_label = |
102 | format!("Change visibility of {}.{} to {}", parent_name, target_name, missing_visibility); | 102 | format!("Change visibility of {}.{} to {}", parent_name, target_name, missing_visibility); |
103 | 103 | ||
104 | acc.add(AssistId("fix_visibility"), assist_label, target, |builder| { | 104 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { |
105 | builder.edit_file(target_file); | 105 | builder.edit_file(target_file); |
106 | match ctx.config.snippet_cap { | 106 | match ctx.config.snippet_cap { |
107 | Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | 107 | 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..3cd532650 100644 --- a/crates/ra_assists/src/handlers/flip_binexpr.rs +++ b/crates/ra_assists/src/handlers/flip_binexpr.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_syntax::ast::{AstNode, BinExpr, BinOp}; | 1 | use ra_syntax::ast::{AstNode, BinExpr, BinOp}; |
2 | 2 | ||
3 | use crate::{AssistContext, AssistId, Assists}; | 3 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
4 | 4 | ||
5 | // Assist: flip_binexpr | 5 | // Assist: flip_binexpr |
6 | // | 6 | // |
@@ -33,13 +33,18 @@ pub(crate) fn flip_binexpr(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
33 | return None; | 33 | return None; |
34 | } | 34 | } |
35 | 35 | ||
36 | acc.add(AssistId("flip_binexpr"), "Flip binary expression", op_range, |edit| { | 36 | acc.add( |
37 | if let FlipAction::FlipAndReplaceOp(new_op) = action { | 37 | AssistId("flip_binexpr", AssistKind::RefactorRewrite), |
38 | edit.replace(op_range, new_op); | 38 | "Flip binary expression", |
39 | } | 39 | op_range, |
40 | edit.replace(lhs.text_range(), rhs.text()); | 40 | |edit| { |
41 | edit.replace(rhs.text_range(), lhs.text()); | 41 | if let FlipAction::FlipAndReplaceOp(new_op) = action { |
42 | }) | 42 | edit.replace(op_range, new_op); |
43 | } | ||
44 | edit.replace(lhs.text_range(), rhs.text()); | ||
45 | edit.replace(rhs.text_range(), lhs.text()); | ||
46 | }, | ||
47 | ) | ||
43 | } | 48 | } |
44 | 49 | ||
45 | enum FlipAction { | 50 | enum FlipAction { |
diff --git a/crates/ra_assists/src/handlers/flip_comma.rs b/crates/ra_assists/src/handlers/flip_comma.rs index a57a1c463..55a971dc7 100644 --- a/crates/ra_assists/src/handlers/flip_comma.rs +++ b/crates/ra_assists/src/handlers/flip_comma.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_syntax::{algo::non_trivia_sibling, Direction, T}; | 1 | use ra_syntax::{algo::non_trivia_sibling, Direction, T}; |
2 | 2 | ||
3 | use crate::{AssistContext, AssistId, Assists}; | 3 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
4 | 4 | ||
5 | // Assist: flip_comma | 5 | // Assist: flip_comma |
6 | // | 6 | // |
@@ -28,10 +28,15 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
28 | return None; | 28 | return None; |
29 | } | 29 | } |
30 | 30 | ||
31 | acc.add(AssistId("flip_comma"), "Flip comma", comma.text_range(), |edit| { | 31 | acc.add( |
32 | edit.replace(prev.text_range(), next.to_string()); | 32 | AssistId("flip_comma", AssistKind::RefactorRewrite), |
33 | edit.replace(next.text_range(), prev.to_string()); | 33 | "Flip comma", |
34 | }) | 34 | comma.text_range(), |
35 | |edit| { | ||
36 | edit.replace(prev.text_range(), next.to_string()); | ||
37 | edit.replace(next.text_range(), prev.to_string()); | ||
38 | }, | ||
39 | ) | ||
35 | } | 40 | } |
36 | 41 | ||
37 | #[cfg(test)] | 42 | #[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..1234f4d29 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::{ | |||
4 | Direction, T, | 4 | Direction, T, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use crate::{AssistContext, AssistId, Assists}; | 7 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
8 | 8 | ||
9 | // Assist: flip_trait_bound | 9 | // Assist: flip_trait_bound |
10 | // | 10 | // |
@@ -33,10 +33,15 @@ pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
33 | ); | 33 | ); |
34 | 34 | ||
35 | let target = plus.text_range(); | 35 | let target = plus.text_range(); |
36 | acc.add(AssistId("flip_trait_bound"), "Flip trait bounds", target, |edit| { | 36 | acc.add( |
37 | edit.replace(before.text_range(), after.to_string()); | 37 | AssistId("flip_trait_bound", AssistKind::RefactorRewrite), |
38 | edit.replace(after.text_range(), before.to_string()); | 38 | "Flip trait bounds", |
39 | }) | 39 | target, |
40 | |edit| { | ||
41 | edit.replace(before.text_range(), after.to_string()); | ||
42 | edit.replace(after.text_range(), before.to_string()); | ||
43 | }, | ||
44 | ) | ||
40 | } | 45 | } |
41 | 46 | ||
42 | #[cfg(test)] | 47 | #[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..2fdfabaf5 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; | |||
7 | 7 | ||
8 | use crate::{ | 8 | use crate::{ |
9 | assist_context::{AssistContext, Assists}, | 9 | assist_context::{AssistContext, Assists}, |
10 | AssistId, | 10 | AssistId, AssistKind, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | // Assist: inline_local_variable | 13 | // Assist: inline_local_variable |
@@ -110,13 +110,19 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O | |||
110 | let init_in_paren = format!("({})", &init_str); | 110 | let init_in_paren = format!("({})", &init_str); |
111 | 111 | ||
112 | let target = bind_pat.syntax().text_range(); | 112 | let target = bind_pat.syntax().text_range(); |
113 | acc.add(AssistId("inline_local_variable"), "Inline variable", target, move |builder| { | 113 | acc.add( |
114 | builder.delete(delete_range); | 114 | AssistId("inline_local_variable", AssistKind::RefactorInline), |
115 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { | 115 | "Inline variable", |
116 | let replacement = if should_wrap { init_in_paren.clone() } else { init_str.clone() }; | 116 | target, |
117 | builder.replace(desc.file_range.range, replacement) | 117 | move |builder| { |
118 | } | 118 | builder.delete(delete_range); |
119 | }) | 119 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { |
120 | let replacement = | ||
121 | if should_wrap { init_in_paren.clone() } else { init_str.clone() }; | ||
122 | builder.replace(desc.file_range.range, replacement) | ||
123 | } | ||
124 | }, | ||
125 | ) | ||
120 | } | 126 | } |
121 | 127 | ||
122 | #[cfg(test)] | 128 | #[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..967593031 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::{ | |||
4 | }; | 4 | }; |
5 | use rustc_hash::FxHashSet; | 5 | use rustc_hash::FxHashSet; |
6 | 6 | ||
7 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, Assists}; | 7 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists}; |
8 | 8 | ||
9 | static ASSIST_NAME: &str = "introduce_named_lifetime"; | 9 | static ASSIST_NAME: &str = "introduce_named_lifetime"; |
10 | static ASSIST_LABEL: &str = "Introduce named lifetime"; | 10 | static ASSIST_LABEL: &str = "Introduce named lifetime"; |
@@ -83,7 +83,7 @@ fn generate_fn_def_assist( | |||
83 | _ => return None, | 83 | _ => return None, |
84 | } | 84 | } |
85 | }; | 85 | }; |
86 | acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| { | 86 | acc.add(AssistId(ASSIST_NAME, AssistKind::Refactor), ASSIST_LABEL, lifetime_loc, |builder| { |
87 | add_lifetime_param(fn_def, builder, end_of_fn_ident, new_lifetime_param); | 87 | add_lifetime_param(fn_def, builder, end_of_fn_ident, new_lifetime_param); |
88 | builder.replace(lifetime_loc, format!("'{}", new_lifetime_param)); | 88 | builder.replace(lifetime_loc, format!("'{}", new_lifetime_param)); |
89 | loc_needing_lifetime.map(|loc| builder.insert(loc, format!("'{} ", new_lifetime_param))); | 89 | loc_needing_lifetime.map(|loc| builder.insert(loc, format!("'{} ", new_lifetime_param))); |
@@ -98,7 +98,7 @@ fn generate_impl_def_assist( | |||
98 | ) -> Option<()> { | 98 | ) -> Option<()> { |
99 | let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.type_param_list())?; | 99 | let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.type_param_list())?; |
100 | let end_of_impl_kw = impl_def.impl_token()?.text_range().end(); | 100 | let end_of_impl_kw = impl_def.impl_token()?.text_range().end(); |
101 | acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| { | 101 | acc.add(AssistId(ASSIST_NAME, AssistKind::Refactor), ASSIST_LABEL, lifetime_loc, |builder| { |
102 | add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param); | 102 | add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param); |
103 | builder.replace(lifetime_loc, format!("'{}", new_lifetime_param)); | 103 | builder.replace(lifetime_loc, format!("'{}", new_lifetime_param)); |
104 | }) | 104 | }) |
diff --git a/crates/ra_assists/src/handlers/invert_if.rs b/crates/ra_assists/src/handlers/invert_if.rs index 59d278eb9..bbe3f3643 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::{ | |||
6 | use crate::{ | 6 | use crate::{ |
7 | assist_context::{AssistContext, Assists}, | 7 | assist_context::{AssistContext, Assists}, |
8 | utils::invert_boolean_expression, | 8 | utils::invert_boolean_expression, |
9 | AssistId, | 9 | AssistId, AssistKind, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | // Assist: invert_if | 12 | // Assist: invert_if |
@@ -54,7 +54,7 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
54 | let else_node = else_block.syntax(); | 54 | let else_node = else_block.syntax(); |
55 | let else_range = else_node.text_range(); | 55 | let else_range = else_node.text_range(); |
56 | let then_range = then_node.text_range(); | 56 | let then_range = then_node.text_range(); |
57 | acc.add(AssistId("invert_if"), "Invert if", if_range, |edit| { | 57 | acc.add(AssistId("invert_if", AssistKind::RefactorRewrite), "Invert if", if_range, |edit| { |
58 | edit.replace(cond_range, flip_cond.syntax().text()); | 58 | edit.replace(cond_range, flip_cond.syntax().text()); |
59 | edit.replace(else_range, then_node.text()); | 59 | edit.replace(else_range, then_node.text()); |
60 | edit.replace(then_range, else_node.text()); | 60 | 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..1beccb61c 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::{ | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | assist_context::{AssistContext, Assists}, | 10 | assist_context::{AssistContext, Assists}, |
11 | AssistId, | 11 | AssistId, AssistKind, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | // Assist: merge_imports | 14 | // Assist: merge_imports |
@@ -56,9 +56,14 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | let target = tree.syntax().text_range(); | 58 | let target = tree.syntax().text_range(); |
59 | acc.add(AssistId("merge_imports"), "Merge imports", target, |builder| { | 59 | acc.add( |
60 | builder.rewrite(rewriter); | 60 | AssistId("merge_imports", AssistKind::RefactorRewrite), |
61 | }) | 61 | "Merge imports", |
62 | target, | ||
63 | |builder| { | ||
64 | builder.rewrite(rewriter); | ||
65 | }, | ||
66 | ) | ||
62 | } | 67 | } |
63 | 68 | ||
64 | fn next_prev() -> impl Iterator<Item = Direction> { | 69 | fn next_prev() -> impl Iterator<Item = Direction> { |
diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs index 90ce66378..186a1f618 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::{ | |||
6 | Direction, | 6 | Direction, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | use crate::{AssistContext, AssistId, Assists, TextRange}; | 9 | use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange}; |
10 | 10 | ||
11 | // Assist: merge_match_arms | 11 | // Assist: merge_match_arms |
12 | // | 12 | // |
@@ -59,25 +59,30 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
59 | return None; | 59 | return None; |
60 | } | 60 | } |
61 | 61 | ||
62 | acc.add(AssistId("merge_match_arms"), "Merge match arms", current_text_range, |edit| { | 62 | acc.add( |
63 | let pats = if arms_to_merge.iter().any(contains_placeholder) { | 63 | AssistId("merge_match_arms", AssistKind::RefactorRewrite), |
64 | "_".into() | 64 | "Merge match arms", |
65 | } else { | 65 | current_text_range, |
66 | arms_to_merge | 66 | |edit| { |
67 | .iter() | 67 | let pats = if arms_to_merge.iter().any(contains_placeholder) { |
68 | .filter_map(ast::MatchArm::pat) | 68 | "_".into() |
69 | .map(|x| x.syntax().to_string()) | 69 | } else { |
70 | .collect::<Vec<String>>() | 70 | arms_to_merge |
71 | .join(" | ") | 71 | .iter() |
72 | }; | 72 | .filter_map(ast::MatchArm::pat) |
73 | 73 | .map(|x| x.syntax().to_string()) | |
74 | let arm = format!("{} => {}", pats, current_expr.syntax().text()); | 74 | .collect::<Vec<String>>() |
75 | 75 | .join(" | ") | |
76 | let start = arms_to_merge.first().unwrap().syntax().text_range().start(); | 76 | }; |
77 | let end = arms_to_merge.last().unwrap().syntax().text_range().end(); | 77 | |
78 | 78 | let arm = format!("{} => {}", pats, current_expr.syntax().text()); | |
79 | edit.replace(TextRange::new(start, end), arm); | 79 | |
80 | }) | 80 | let start = arms_to_merge.first().unwrap().syntax().text_range().start(); |
81 | let end = arms_to_merge.last().unwrap().syntax().text_range().end(); | ||
82 | |||
83 | edit.replace(TextRange::new(start, end), arm); | ||
84 | }, | ||
85 | ) | ||
81 | } | 86 | } |
82 | 87 | ||
83 | fn contains_placeholder(a: &ast::MatchArm) -> bool { | 88 | 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..ba3dafb99 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::{ | |||
5 | T, | 5 | T, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::{AssistContext, AssistId, Assists}; | 8 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
9 | 9 | ||
10 | // Assist: move_bounds_to_where_clause | 10 | // Assist: move_bounds_to_where_clause |
11 | // | 11 | // |
@@ -50,29 +50,36 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | let target = type_param_list.syntax().text_range(); | 52 | let target = type_param_list.syntax().text_range(); |
53 | acc.add(AssistId("move_bounds_to_where_clause"), "Move to where clause", target, |edit| { | 53 | acc.add( |
54 | let new_params = type_param_list | 54 | AssistId("move_bounds_to_where_clause", AssistKind::RefactorRewrite), |
55 | .type_params() | 55 | "Move to where clause", |
56 | .filter(|it| it.type_bound_list().is_some()) | 56 | target, |
57 | .map(|type_param| { | 57 | |edit| { |
58 | let without_bounds = type_param.remove_bounds(); | 58 | let new_params = type_param_list |
59 | (type_param, without_bounds) | 59 | .type_params() |
60 | }); | 60 | .filter(|it| it.type_bound_list().is_some()) |
61 | 61 | .map(|type_param| { | |
62 | let new_type_param_list = type_param_list.replace_descendants(new_params); | 62 | let without_bounds = type_param.remove_bounds(); |
63 | edit.replace_ast(type_param_list.clone(), new_type_param_list); | 63 | (type_param, without_bounds) |
64 | 64 | }); | |
65 | let where_clause = { | 65 | |
66 | let predicates = type_param_list.type_params().filter_map(build_predicate); | 66 | let new_type_param_list = type_param_list.replace_descendants(new_params); |
67 | make::where_clause(predicates) | 67 | edit.replace_ast(type_param_list.clone(), new_type_param_list); |
68 | }; | 68 | |
69 | 69 | let where_clause = { | |
70 | let to_insert = match anchor.prev_sibling_or_token() { | 70 | let predicates = type_param_list.type_params().filter_map(build_predicate); |
71 | Some(ref elem) if elem.kind() == WHITESPACE => format!("{} ", where_clause.syntax()), | 71 | make::where_clause(predicates) |
72 | _ => format!(" {}", where_clause.syntax()), | 72 | }; |
73 | }; | 73 | |
74 | edit.insert(anchor.text_range().start(), to_insert); | 74 | let to_insert = match anchor.prev_sibling_or_token() { |
75 | }) | 75 | Some(ref elem) if elem.kind() == WHITESPACE => { |
76 | format!("{} ", where_clause.syntax()) | ||
77 | } | ||
78 | _ => format!(" {}", where_clause.syntax()), | ||
79 | }; | ||
80 | edit.insert(anchor.text_range().start(), to_insert); | ||
81 | }, | ||
82 | ) | ||
76 | } | 83 | } |
77 | 84 | ||
78 | fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> { | 85 | fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> { |
diff --git a/crates/ra_assists/src/handlers/move_guard.rs b/crates/ra_assists/src/handlers/move_guard.rs index 7edcf0748..4060d34c6 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::{ | |||
3 | SyntaxKind::WHITESPACE, | 3 | SyntaxKind::WHITESPACE, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{AssistContext, AssistId, Assists}; | 6 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
7 | 7 | ||
8 | // Assist: move_guard_to_arm_body | 8 | // Assist: move_guard_to_arm_body |
9 | // | 9 | // |
@@ -40,17 +40,22 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext) -> | |||
40 | let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); | 40 | let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); |
41 | 41 | ||
42 | let target = guard.syntax().text_range(); | 42 | let target = guard.syntax().text_range(); |
43 | acc.add(AssistId("move_guard_to_arm_body"), "Move guard to arm body", target, |edit| { | 43 | acc.add( |
44 | match space_before_guard { | 44 | AssistId("move_guard_to_arm_body", AssistKind::RefactorRewrite), |
45 | Some(element) if element.kind() == WHITESPACE => { | 45 | "Move guard to arm body", |
46 | edit.delete(element.text_range()); | 46 | target, |
47 | } | 47 | |edit| { |
48 | _ => (), | 48 | match space_before_guard { |
49 | }; | 49 | Some(element) if element.kind() == WHITESPACE => { |
50 | edit.delete(element.text_range()); | ||
51 | } | ||
52 | _ => (), | ||
53 | }; | ||
50 | 54 | ||
51 | edit.delete(guard.syntax().text_range()); | 55 | edit.delete(guard.syntax().text_range()); |
52 | edit.replace_node_and_indent(arm_expr.syntax(), buf); | 56 | edit.replace_node_and_indent(arm_expr.syntax(), buf); |
53 | }) | 57 | }, |
58 | ) | ||
54 | } | 59 | } |
55 | 60 | ||
56 | // Assist: move_arm_cond_to_match_guard | 61 | // Assist: move_arm_cond_to_match_guard |
@@ -100,7 +105,7 @@ pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContex | |||
100 | 105 | ||
101 | let target = if_expr.syntax().text_range(); | 106 | let target = if_expr.syntax().text_range(); |
102 | acc.add( | 107 | acc.add( |
103 | AssistId("move_arm_cond_to_match_guard"), | 108 | AssistId("move_arm_cond_to_match_guard", AssistKind::RefactorRewrite), |
104 | "Move condition to match guard", | 109 | "Move condition to match guard", |
105 | target, | 110 | target, |
106 | |edit| { | 111 | |edit| { |
diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs index d22d0aa55..96679e160 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::{ | |||
5 | TextSize, | 5 | TextSize, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::{AssistContext, AssistId, Assists}; | 8 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
9 | 9 | ||
10 | // Assist: make_raw_string | 10 | // Assist: make_raw_string |
11 | // | 11 | // |
@@ -26,14 +26,22 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
26 | let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?; | 26 | let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?; |
27 | let value = token.value()?; | 27 | let value = token.value()?; |
28 | let target = token.syntax().text_range(); | 28 | let target = token.syntax().text_range(); |
29 | acc.add(AssistId("make_raw_string"), "Rewrite as raw string", target, |edit| { | 29 | acc.add( |
30 | let max_hash_streak = count_hashes(&value); | 30 | AssistId("make_raw_string", AssistKind::RefactorRewrite), |
31 | let mut hashes = String::with_capacity(max_hash_streak + 1); | 31 | "Rewrite as raw string", |
32 | for _ in 0..hashes.capacity() { | 32 | target, |
33 | hashes.push('#'); | 33 | |edit| { |
34 | } | 34 | let max_hash_streak = count_hashes(&value); |
35 | edit.replace(token.syntax().text_range(), format!("r{}\"{}\"{}", hashes, value, hashes)); | 35 | let mut hashes = String::with_capacity(max_hash_streak + 1); |
36 | }) | 36 | for _ in 0..hashes.capacity() { |
37 | hashes.push('#'); | ||
38 | } | ||
39 | edit.replace( | ||
40 | token.syntax().text_range(), | ||
41 | format!("r{}\"{}\"{}", hashes, value, hashes), | ||
42 | ); | ||
43 | }, | ||
44 | ) | ||
37 | } | 45 | } |
38 | 46 | ||
39 | // Assist: make_usual_string | 47 | // Assist: make_usual_string |
@@ -55,11 +63,16 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
55 | let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?; | 63 | let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?; |
56 | let value = token.value()?; | 64 | let value = token.value()?; |
57 | let target = token.syntax().text_range(); | 65 | let target = token.syntax().text_range(); |
58 | acc.add(AssistId("make_usual_string"), "Rewrite as regular string", target, |edit| { | 66 | acc.add( |
59 | // parse inside string to escape `"` | 67 | AssistId("make_usual_string", AssistKind::RefactorRewrite), |
60 | let escaped = value.escape_default().to_string(); | 68 | "Rewrite as regular string", |
61 | edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); | 69 | target, |
62 | }) | 70 | |edit| { |
71 | // parse inside string to escape `"` | ||
72 | let escaped = value.escape_default().to_string(); | ||
73 | edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); | ||
74 | }, | ||
75 | ) | ||
63 | } | 76 | } |
64 | 77 | ||
65 | // Assist: add_hash | 78 | // Assist: add_hash |
@@ -80,7 +93,7 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
80 | pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 93 | pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
81 | let token = ctx.find_token_at_offset(RAW_STRING)?; | 94 | let token = ctx.find_token_at_offset(RAW_STRING)?; |
82 | let target = token.text_range(); | 95 | let target = token.text_range(); |
83 | acc.add(AssistId("add_hash"), "Add # to raw string", target, |edit| { | 96 | acc.add(AssistId("add_hash", AssistKind::Refactor), "Add # to raw string", target, |edit| { |
84 | edit.insert(token.text_range().start() + TextSize::of('r'), "#"); | 97 | edit.insert(token.text_range().start() + TextSize::of('r'), "#"); |
85 | edit.insert(token.text_range().end(), "#"); | 98 | edit.insert(token.text_range().end(), "#"); |
86 | }) | 99 | }) |
@@ -109,18 +122,23 @@ pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
109 | return None; | 122 | return None; |
110 | } | 123 | } |
111 | let target = token.text_range(); | 124 | let target = token.text_range(); |
112 | acc.add(AssistId("remove_hash"), "Remove hash from raw string", target, |edit| { | 125 | acc.add( |
113 | let result = &text[2..text.len() - 1]; | 126 | AssistId("remove_hash", AssistKind::RefactorRewrite), |
114 | let result = if result.starts_with('\"') { | 127 | "Remove hash from raw string", |
115 | // FIXME: this logic is wrong, not only the last has has to handled specially | 128 | target, |
116 | // no more hash, escape | 129 | |edit| { |
117 | let internal_str = &result[1..result.len() - 1]; | 130 | let result = &text[2..text.len() - 1]; |
118 | format!("\"{}\"", internal_str.escape_default().to_string()) | 131 | let result = if result.starts_with('\"') { |
119 | } else { | 132 | // FIXME: this logic is wrong, not only the last has has to handled specially |
120 | result.to_owned() | 133 | // no more hash, escape |
121 | }; | 134 | let internal_str = &result[1..result.len() - 1]; |
122 | edit.replace(token.text_range(), format!("r{}", result)); | 135 | format!("\"{}\"", internal_str.escape_default().to_string()) |
123 | }) | 136 | } else { |
137 | result.to_owned() | ||
138 | }; | ||
139 | edit.replace(token.text_range(), format!("r{}", result)); | ||
140 | }, | ||
141 | ) | ||
124 | } | 142 | } |
125 | 143 | ||
126 | fn count_hashes(s: &str) -> usize { | 144 | 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..a616cca57 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::{ | |||
3 | TextSize, T, | 3 | TextSize, T, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{AssistContext, AssistId, Assists}; | 6 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
7 | 7 | ||
8 | // Assist: remove_dbg | 8 | // Assist: remove_dbg |
9 | // | 9 | // |
@@ -38,7 +38,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | let target = macro_call.syntax().text_range(); | 40 | let target = macro_call.syntax().text_range(); |
41 | acc.add(AssistId("remove_dbg"), "Remove dbg!()", target, |builder| { | 41 | acc.add(AssistId("remove_dbg", AssistKind::Refactor), "Remove dbg!()", target, |builder| { |
42 | builder.replace(macro_range, macro_content); | 42 | builder.replace(macro_range, macro_content); |
43 | }) | 43 | }) |
44 | } | 44 | } |
diff --git a/crates/ra_assists/src/handlers/remove_mut.rs b/crates/ra_assists/src/handlers/remove_mut.rs index fe4eada03..ef55c354e 100644 --- a/crates/ra_assists/src/handlers/remove_mut.rs +++ b/crates/ra_assists/src/handlers/remove_mut.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_syntax::{SyntaxKind, TextRange, T}; | 1 | use ra_syntax::{SyntaxKind, TextRange, T}; |
2 | 2 | ||
3 | use crate::{AssistContext, AssistId, Assists}; | 3 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
4 | 4 | ||
5 | // Assist: remove_mut | 5 | // Assist: remove_mut |
6 | // | 6 | // |
@@ -26,7 +26,12 @@ pub(crate) fn remove_mut(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | let target = mut_token.text_range(); | 28 | let target = mut_token.text_range(); |
29 | acc.add(AssistId("remove_mut"), "Remove `mut` keyword", target, |builder| { | 29 | acc.add( |
30 | builder.delete(TextRange::new(delete_from, delete_to)); | 30 | AssistId("remove_mut", AssistKind::Refactor), |
31 | }) | 31 | "Remove `mut` keyword", |
32 | target, | ||
33 | |builder| { | ||
34 | builder.delete(TextRange::new(delete_from, delete_to)); | ||
35 | }, | ||
36 | ) | ||
32 | } | 37 | } |
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs index b8cf30e7f..2ac1c56cf 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}; | |||
5 | use ra_ide_db::RootDatabase; | 5 | use ra_ide_db::RootDatabase; |
6 | use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; | 6 | use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; |
7 | 7 | ||
8 | use crate::{AssistContext, AssistId, Assists}; | 8 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
9 | 9 | ||
10 | // Assist: reorder_fields | 10 | // Assist: reorder_fields |
11 | // | 11 | // |
@@ -42,11 +42,16 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
42 | } | 42 | } |
43 | 43 | ||
44 | let target = record.syntax().text_range(); | 44 | let target = record.syntax().text_range(); |
45 | acc.add(AssistId("reorder_fields"), "Reorder record fields", target, |edit| { | 45 | acc.add( |
46 | for (old, new) in fields.iter().zip(&sorted_fields) { | 46 | AssistId("reorder_fields", AssistKind::RefactorRewrite), |
47 | algo::diff(old, new).into_text_edit(edit.text_edit_builder()); | 47 | "Reorder record fields", |
48 | } | 48 | target, |
49 | }) | 49 | |edit| { |
50 | for (old, new) in fields.iter().zip(&sorted_fields) { | ||
51 | algo::diff(old, new).into_text_edit(edit.text_edit_builder()); | ||
52 | } | ||
53 | }, | ||
54 | ) | ||
50 | } | 55 | } |
51 | 56 | ||
52 | fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { | 57 | fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { |
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..b7e30a7f2 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::{ | |||
8 | AstNode, | 8 | AstNode, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{utils::TryEnum, AssistContext, AssistId, Assists}; | 11 | use crate::{utils::TryEnum, AssistContext, AssistId, AssistKind, Assists}; |
12 | 12 | ||
13 | // Assist: replace_if_let_with_match | 13 | // Assist: replace_if_let_with_match |
14 | // | 14 | // |
@@ -48,29 +48,35 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext) | |||
48 | }; | 48 | }; |
49 | 49 | ||
50 | let target = if_expr.syntax().text_range(); | 50 | let target = if_expr.syntax().text_range(); |
51 | acc.add(AssistId("replace_if_let_with_match"), "Replace with match", target, move |edit| { | 51 | acc.add( |
52 | let match_expr = { | 52 | AssistId("replace_if_let_with_match", AssistKind::RefactorRewrite), |
53 | let then_arm = { | 53 | "Replace with match", |
54 | let then_block = then_block.reset_indent().indent(IndentLevel(1)); | 54 | target, |
55 | let then_expr = unwrap_trivial_block(then_block); | 55 | move |edit| { |
56 | make::match_arm(vec![pat.clone()], then_expr) | 56 | let match_expr = { |
57 | let then_arm = { | ||
58 | let then_block = then_block.reset_indent().indent(IndentLevel(1)); | ||
59 | let then_expr = unwrap_trivial_block(then_block); | ||
60 | make::match_arm(vec![pat.clone()], then_expr) | ||
61 | }; | ||
62 | let else_arm = { | ||
63 | let pattern = ctx | ||
64 | .sema | ||
65 | .type_of_pat(&pat) | ||
66 | .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty)) | ||
67 | .map(|it| it.sad_pattern()) | ||
68 | .unwrap_or_else(|| make::placeholder_pat().into()); | ||
69 | let else_expr = unwrap_trivial_block(else_block); | ||
70 | make::match_arm(vec![pattern], else_expr) | ||
71 | }; | ||
72 | let match_expr = | ||
73 | make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])); | ||
74 | match_expr.indent(IndentLevel::from_node(if_expr.syntax())) | ||
57 | }; | 75 | }; |
58 | let else_arm = { | ||
59 | let pattern = ctx | ||
60 | .sema | ||
61 | .type_of_pat(&pat) | ||
62 | .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty)) | ||
63 | .map(|it| it.sad_pattern()) | ||
64 | .unwrap_or_else(|| make::placeholder_pat().into()); | ||
65 | let else_expr = unwrap_trivial_block(else_block); | ||
66 | make::match_arm(vec![pattern], else_expr) | ||
67 | }; | ||
68 | let match_expr = make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])); | ||
69 | match_expr.indent(IndentLevel::from_node(if_expr.syntax())) | ||
70 | }; | ||
71 | 76 | ||
72 | edit.replace_ast::<ast::Expr>(if_expr.into(), match_expr); | 77 | edit.replace_ast::<ast::Expr>(if_expr.into(), match_expr); |
73 | }) | 78 | }, |
79 | ) | ||
74 | } | 80 | } |
75 | 81 | ||
76 | #[cfg(test)] | 82 | #[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..a49292c97 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::{ | |||
9 | AstNode, T, | 9 | AstNode, T, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{utils::TryEnum, AssistContext, AssistId, Assists}; | 12 | use crate::{utils::TryEnum, AssistContext, AssistId, AssistKind, Assists}; |
13 | 13 | ||
14 | // Assist: replace_let_with_if_let | 14 | // Assist: replace_let_with_if_let |
15 | // | 15 | // |
@@ -44,24 +44,31 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> | |||
44 | let happy_variant = TryEnum::from_ty(&ctx.sema, &ty).map(|it| it.happy_case()); | 44 | let happy_variant = TryEnum::from_ty(&ctx.sema, &ty).map(|it| it.happy_case()); |
45 | 45 | ||
46 | let target = let_kw.text_range(); | 46 | let target = let_kw.text_range(); |
47 | acc.add(AssistId("replace_let_with_if_let"), "Replace with if-let", target, |edit| { | 47 | acc.add( |
48 | let with_placeholder: ast::Pat = match happy_variant { | 48 | AssistId("replace_let_with_if_let", AssistKind::RefactorRewrite), |
49 | None => make::placeholder_pat().into(), | 49 | "Replace with if-let", |
50 | Some(var_name) => make::tuple_struct_pat( | 50 | target, |
51 | make::path_unqualified(make::path_segment(make::name_ref(var_name))), | 51 | |edit| { |
52 | once(make::placeholder_pat().into()), | 52 | let with_placeholder: ast::Pat = match happy_variant { |
53 | ) | 53 | None => make::placeholder_pat().into(), |
54 | .into(), | 54 | Some(var_name) => make::tuple_struct_pat( |
55 | }; | 55 | make::path_unqualified(make::path_segment(make::name_ref(var_name))), |
56 | let block = make::block_expr(None, None).indent(IndentLevel::from_node(let_stmt.syntax())); | 56 | once(make::placeholder_pat().into()), |
57 | let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block); | 57 | ) |
58 | let stmt = make::expr_stmt(if_); | 58 | .into(), |
59 | }; | ||
60 | let block = | ||
61 | make::block_expr(None, None).indent(IndentLevel::from_node(let_stmt.syntax())); | ||
62 | let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block); | ||
63 | let stmt = make::expr_stmt(if_); | ||
59 | 64 | ||
60 | let placeholder = stmt.syntax().descendants().find_map(ast::PlaceholderPat::cast).unwrap(); | 65 | let placeholder = |
61 | let stmt = stmt.replace_descendant(placeholder.into(), original_pat); | 66 | stmt.syntax().descendants().find_map(ast::PlaceholderPat::cast).unwrap(); |
67 | let stmt = stmt.replace_descendant(placeholder.into(), original_pat); | ||
62 | 68 | ||
63 | edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); | 69 | edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); |
64 | }) | 70 | }, |
71 | ) | ||
65 | } | 72 | } |
66 | 73 | ||
67 | #[cfg(test)] | 74 | #[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..dfd314abf 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 | |||
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | utils::{find_insert_use_container, insert_use_statement}, | 5 | utils::{find_insert_use_container, insert_use_statement}, |
6 | AssistContext, AssistId, Assists, | 6 | AssistContext, AssistId, AssistKind, Assists, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | // Assist: replace_qualified_name_with_use | 9 | // Assist: replace_qualified_name_with_use |
@@ -37,7 +37,7 @@ pub(crate) fn replace_qualified_name_with_use( | |||
37 | 37 | ||
38 | let target = path.syntax().text_range(); | 38 | let target = path.syntax().text_range(); |
39 | acc.add( | 39 | acc.add( |
40 | AssistId("replace_qualified_name_with_use"), | 40 | AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite), |
41 | "Replace qualified path with use", | 41 | "Replace qualified path with use", |
42 | target, | 42 | target, |
43 | |builder| { | 43 | |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..e5a4bb23c 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::{ | |||
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | utils::{render_snippet, Cursor, TryEnum}, | 13 | utils::{render_snippet, Cursor, TryEnum}, |
14 | AssistContext, AssistId, Assists, | 14 | AssistContext, AssistId, AssistKind, Assists, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | // Assist: replace_unwrap_with_match | 17 | // Assist: replace_unwrap_with_match |
@@ -46,37 +46,43 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext) | |||
46 | let ty = ctx.sema.type_of_expr(&caller)?; | 46 | let ty = ctx.sema.type_of_expr(&caller)?; |
47 | let happy_variant = TryEnum::from_ty(&ctx.sema, &ty)?.happy_case(); | 47 | let happy_variant = TryEnum::from_ty(&ctx.sema, &ty)?.happy_case(); |
48 | let target = method_call.syntax().text_range(); | 48 | let target = method_call.syntax().text_range(); |
49 | acc.add(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", target, |builder| { | 49 | acc.add( |
50 | let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); | 50 | AssistId("replace_unwrap_with_match", AssistKind::RefactorRewrite), |
51 | let it = make::bind_pat(make::name("a")).into(); | 51 | "Replace unwrap with match", |
52 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); | 52 | target, |
53 | |builder| { | ||
54 | let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); | ||
55 | let it = make::bind_pat(make::name("a")).into(); | ||
56 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); | ||
53 | 57 | ||
54 | let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); | 58 | let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); |
55 | let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); | 59 | let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); |
56 | 60 | ||
57 | let unreachable_call = make::expr_unreachable(); | 61 | let unreachable_call = make::expr_unreachable(); |
58 | let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); | 62 | let err_arm = |
63 | make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); | ||
59 | 64 | ||
60 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); | 65 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); |
61 | let match_expr = make::expr_match(caller.clone(), match_arm_list) | 66 | let match_expr = make::expr_match(caller.clone(), match_arm_list) |
62 | .indent(IndentLevel::from_node(method_call.syntax())); | 67 | .indent(IndentLevel::from_node(method_call.syntax())); |
63 | 68 | ||
64 | let range = method_call.syntax().text_range(); | 69 | let range = method_call.syntax().text_range(); |
65 | match ctx.config.snippet_cap { | 70 | match ctx.config.snippet_cap { |
66 | Some(cap) => { | 71 | Some(cap) => { |
67 | let err_arm = match_expr | 72 | let err_arm = match_expr |
68 | .syntax() | 73 | .syntax() |
69 | .descendants() | 74 | .descendants() |
70 | .filter_map(ast::MatchArm::cast) | 75 | .filter_map(ast::MatchArm::cast) |
71 | .last() | 76 | .last() |
72 | .unwrap(); | 77 | .unwrap(); |
73 | let snippet = | 78 | let snippet = |
74 | render_snippet(cap, match_expr.syntax(), Cursor::Before(err_arm.syntax())); | 79 | render_snippet(cap, match_expr.syntax(), Cursor::Before(err_arm.syntax())); |
75 | builder.replace_snippet(cap, range, snippet) | 80 | builder.replace_snippet(cap, range, snippet) |
81 | } | ||
82 | None => builder.replace(range, match_expr.to_string()), | ||
76 | } | 83 | } |
77 | None => builder.replace(range, match_expr.to_string()), | 84 | }, |
78 | } | 85 | ) |
79 | }) | ||
80 | } | 86 | } |
81 | 87 | ||
82 | #[cfg(test)] | 88 | #[cfg(test)] |
diff --git a/crates/ra_assists/src/handlers/split_import.rs b/crates/ra_assists/src/handlers/split_import.rs index 38aa199a0..4ca5c3ca1 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; | |||
2 | 2 | ||
3 | use ra_syntax::{ast, AstNode, T}; | 3 | use ra_syntax::{ast, AstNode, T}; |
4 | 4 | ||
5 | use crate::{AssistContext, AssistId, Assists}; | 5 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
6 | 6 | ||
7 | // Assist: split_import | 7 | // Assist: split_import |
8 | // | 8 | // |
@@ -28,7 +28,7 @@ pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
28 | } | 28 | } |
29 | 29 | ||
30 | let target = colon_colon.text_range(); | 30 | let target = colon_colon.text_range(); |
31 | acc.add(AssistId("split_import"), "Split import", target, |edit| { | 31 | acc.add(AssistId("split_import", AssistKind::RefactorRewrite), "Split import", target, |edit| { |
32 | edit.replace_ast(use_tree, new_tree); | 32 | edit.replace_ast(use_tree, new_tree); |
33 | }) | 33 | }) |
34 | } | 34 | } |
diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs index 1fb13f481..8b38695a9 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::{ | |||
7 | AstNode, TextRange, T, | 7 | AstNode, TextRange, T, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | use crate::{AssistContext, AssistId, Assists}; | 10 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
11 | 11 | ||
12 | // Assist: unwrap_block | 12 | // Assist: unwrap_block |
13 | // | 13 | // |
@@ -27,7 +27,7 @@ use crate::{AssistContext, AssistId, Assists}; | |||
27 | // } | 27 | // } |
28 | // ``` | 28 | // ``` |
29 | pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 29 | pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
30 | let assist_id = AssistId("unwrap_block"); | 30 | let assist_id = AssistId("unwrap_block", AssistKind::RefactorRewrite); |
31 | let assist_label = "Unwrap block"; | 31 | let assist_label = "Unwrap block"; |
32 | 32 | ||
33 | let l_curly_token = ctx.find_token_at_offset(T!['{'])?; | 33 | let l_curly_token = ctx.find_token_at_offset(T!['{'])?; |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 1745f44a5..65cda95ee 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -26,10 +26,20 @@ pub(crate) use crate::assist_context::{AssistContext, Assists}; | |||
26 | 26 | ||
27 | pub use assist_config::AssistConfig; | 27 | pub use assist_config::AssistConfig; |
28 | 28 | ||
29 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
30 | pub enum AssistKind { | ||
31 | None, | ||
32 | QuickFix, | ||
33 | Refactor, | ||
34 | RefactorExtract, | ||
35 | RefactorInline, | ||
36 | RefactorRewrite, | ||
37 | } | ||
38 | |||
29 | /// Unique identifier of the assist, should not be shown to the user | 39 | /// Unique identifier of the assist, should not be shown to the user |
30 | /// directly. | 40 | /// directly. |
31 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 41 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
32 | pub struct AssistId(pub &'static str); | 42 | pub struct AssistId(pub &'static str, pub AssistKind); |
33 | 43 | ||
34 | #[derive(Clone, Debug)] | 44 | #[derive(Clone, Debug)] |
35 | pub struct GroupLabel(pub String); | 45 | pub struct GroupLabel(pub String); |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 8660278f1..dcfa186dc 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -76,7 +76,7 @@ pub use crate::{ | |||
76 | }; | 76 | }; |
77 | 77 | ||
78 | pub use hir::{Documentation, Semantics}; | 78 | pub use hir::{Documentation, Semantics}; |
79 | pub use ra_assists::{Assist, AssistConfig, AssistId, ResolvedAssist}; | 79 | pub use ra_assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist}; |
80 | pub use ra_db::{ | 80 | pub use ra_db::{ |
81 | Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot, | 81 | Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot, |
82 | SourceRootId, | 82 | SourceRootId, |
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 673795e78..070ad5e68 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs | |||
@@ -112,8 +112,6 @@ fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProvi | |||
112 | lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(), | 112 | lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(), |
113 | lsp_types::code_action_kind::REFACTOR_INLINE.to_string(), | 113 | lsp_types::code_action_kind::REFACTOR_INLINE.to_string(), |
114 | lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(), | 114 | lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(), |
115 | lsp_types::code_action_kind::SOURCE.to_string(), | ||
116 | lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(), | ||
117 | ]), | 115 | ]), |
118 | work_done_progress_options: Default::default(), | 116 | work_done_progress_options: Default::default(), |
119 | }) | 117 | }) |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 652a44694..2312a6e4d 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -4,9 +4,9 @@ use std::path::{self, Path}; | |||
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | use ra_db::{FileId, FileRange}; | 5 | use ra_db::{FileId, FileRange}; |
6 | use ra_ide::{ | 6 | use ra_ide::{ |
7 | Assist, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, FoldKind, | 7 | Assist, AssistKind, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, |
8 | FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, Indel, | 8 | FoldKind, FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, |
9 | InlayHint, InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess, | 9 | Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess, |
10 | ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, | 10 | ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, |
11 | }; | 11 | }; |
12 | use ra_syntax::{SyntaxKind, TextRange, TextSize}; | 12 | use ra_syntax::{SyntaxKind, TextRange, TextSize}; |
@@ -627,6 +627,18 @@ pub(crate) fn call_hierarchy_item( | |||
627 | Ok(lsp_types::CallHierarchyItem { name, kind, tags: None, detail, uri, range, selection_range }) | 627 | Ok(lsp_types::CallHierarchyItem { name, kind, tags: None, detail, uri, range, selection_range }) |
628 | } | 628 | } |
629 | 629 | ||
630 | pub(crate) fn code_action_kind(kind: AssistKind) -> String { | ||
631 | match kind { | ||
632 | AssistKind::None => lsp_types::code_action_kind::EMPTY, | ||
633 | AssistKind::QuickFix => lsp_types::code_action_kind::QUICKFIX, | ||
634 | AssistKind::Refactor => lsp_types::code_action_kind::REFACTOR, | ||
635 | AssistKind::RefactorExtract => lsp_types::code_action_kind::REFACTOR_EXTRACT, | ||
636 | AssistKind::RefactorInline => lsp_types::code_action_kind::REFACTOR_INLINE, | ||
637 | AssistKind::RefactorRewrite => lsp_types::code_action_kind::REFACTOR_REWRITE, | ||
638 | } | ||
639 | .to_string() | ||
640 | } | ||
641 | |||
630 | pub(crate) fn unresolved_code_action( | 642 | pub(crate) fn unresolved_code_action( |
631 | snap: &GlobalStateSnapshot, | 643 | snap: &GlobalStateSnapshot, |
632 | assist: Assist, | 644 | assist: Assist, |
@@ -636,7 +648,7 @@ pub(crate) fn unresolved_code_action( | |||
636 | title: assist.label, | 648 | title: assist.label, |
637 | id: Some(format!("{}:{}", assist.id.0.to_owned(), index.to_string())), | 649 | id: Some(format!("{}:{}", assist.id.0.to_owned(), index.to_string())), |
638 | group: assist.group.filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0), | 650 | group: assist.group.filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0), |
639 | kind: Some(String::new()), | 651 | kind: Some(code_action_kind(assist.id.1)), |
640 | edit: None, | 652 | edit: None, |
641 | command: None, | 653 | command: None, |
642 | }; | 654 | }; |
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 3e5915c28..41ffac7b3 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts | |||
@@ -66,7 +66,7 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient | |||
66 | return Promise.resolve(null); | 66 | return Promise.resolve(null); |
67 | }); | 67 | }); |
68 | }, | 68 | }, |
69 | // Using custom handling of CodeActions where each code action is resloved lazily | 69 | // Using custom handling of CodeActions where each code action is resolved lazily |
70 | // That's why we are not waiting for any command or edits | 70 | // That's why we are not waiting for any command or edits |
71 | async provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken, _next: lc.ProvideCodeActionsSignature) { | 71 | async provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken, _next: lc.ProvideCodeActionsSignature) { |
72 | const params: lc.CodeActionParams = { | 72 | const params: lc.CodeActionParams = { |
@@ -87,7 +87,8 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient | |||
87 | continue; | 87 | continue; |
88 | } | 88 | } |
89 | assert(isCodeActionWithoutEditsAndCommands(item), "We don't expect edits or commands here"); | 89 | assert(isCodeActionWithoutEditsAndCommands(item), "We don't expect edits or commands here"); |
90 | const action = new vscode.CodeAction(item.title); | 90 | const kind = client.protocol2CodeConverter.asCodeActionKind((item as any).kind); |
91 | const action = new vscode.CodeAction(item.title, kind); | ||
91 | const group = (item as any).group; | 92 | const group = (item as any).group; |
92 | const id = (item as any).id; | 93 | const id = (item as any).id; |
93 | const resolveParams: ra.ResolveCodeActionParams = { | 94 | const resolveParams: ra.ResolveCodeActionParams = { |
@@ -116,6 +117,7 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient | |||
116 | result[index] = items[0]; | 117 | result[index] = items[0]; |
117 | } else { | 118 | } else { |
118 | const action = new vscode.CodeAction(group); | 119 | const action = new vscode.CodeAction(group); |
120 | action.kind = items[0].kind; | ||
119 | action.command = { | 121 | action.command = { |
120 | command: "rust-analyzer.applyActionGroup", | 122 | command: "rust-analyzer.applyActionGroup", |
121 | title: "", | 123 | title: "", |