diff options
author | Aleksey Kladov <[email protected]> | 2020-05-06 11:51:28 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-05-06 11:51:28 +0100 |
commit | 233f01c9ba555e5d06f336cb0ff64e7a83e4a23a (patch) | |
tree | 7922dca3f7c4133e2616257be537428337e479d6 /crates | |
parent | ede8906844e206f252810d58533538cf1fb326d4 (diff) |
Move target to AssistLabel
Target is used for assists sorting, so we need it before we compute
the action.
Diffstat (limited to 'crates')
36 files changed, 292 insertions, 256 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 83dd270c6..600e5689c 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -94,9 +94,10 @@ impl<'a> AssistCtx<'a> { | |||
94 | self, | 94 | self, |
95 | id: AssistId, | 95 | id: AssistId, |
96 | label: impl Into<String>, | 96 | label: impl Into<String>, |
97 | target: TextRange, | ||
97 | f: impl FnOnce(&mut ActionBuilder), | 98 | f: impl FnOnce(&mut ActionBuilder), |
98 | ) -> Option<Assist> { | 99 | ) -> Option<Assist> { |
99 | let label = AssistLabel::new(id, label.into(), None); | 100 | let label = AssistLabel::new(id, label.into(), None, target); |
100 | 101 | ||
101 | let mut info = AssistInfo::new(label); | 102 | let mut info = AssistInfo::new(label); |
102 | if self.should_compute_edit { | 103 | if self.should_compute_edit { |
@@ -152,9 +153,10 @@ impl<'a> AssistGroup<'a> { | |||
152 | &mut self, | 153 | &mut self, |
153 | id: AssistId, | 154 | id: AssistId, |
154 | label: impl Into<String>, | 155 | label: impl Into<String>, |
156 | target: TextRange, | ||
155 | f: impl FnOnce(&mut ActionBuilder), | 157 | f: impl FnOnce(&mut ActionBuilder), |
156 | ) { | 158 | ) { |
157 | let label = AssistLabel::new(id, label.into(), Some(self.group.clone())); | 159 | let label = AssistLabel::new(id, label.into(), Some(self.group.clone()), target); |
158 | 160 | ||
159 | let mut info = AssistInfo::new(label).with_group(self.group.clone()); | 161 | let mut info = AssistInfo::new(label).with_group(self.group.clone()); |
160 | if self.ctx.should_compute_edit { | 162 | if self.ctx.should_compute_edit { |
@@ -181,7 +183,6 @@ impl<'a> AssistGroup<'a> { | |||
181 | pub(crate) struct ActionBuilder<'a, 'b> { | 183 | pub(crate) struct ActionBuilder<'a, 'b> { |
182 | edit: TextEditBuilder, | 184 | edit: TextEditBuilder, |
183 | cursor_position: Option<TextSize>, | 185 | cursor_position: Option<TextSize>, |
184 | target: Option<TextRange>, | ||
185 | file: AssistFile, | 186 | file: AssistFile, |
186 | ctx: &'a AssistCtx<'b>, | 187 | ctx: &'a AssistCtx<'b>, |
187 | } | 188 | } |
@@ -191,7 +192,6 @@ impl<'a, 'b> ActionBuilder<'a, 'b> { | |||
191 | Self { | 192 | Self { |
192 | edit: TextEditBuilder::default(), | 193 | edit: TextEditBuilder::default(), |
193 | cursor_position: None, | 194 | cursor_position: None, |
194 | target: None, | ||
195 | file: AssistFile::default(), | 195 | file: AssistFile::default(), |
196 | ctx, | 196 | ctx, |
197 | } | 197 | } |
@@ -237,14 +237,6 @@ impl<'a, 'b> ActionBuilder<'a, 'b> { | |||
237 | self.cursor_position = Some(offset) | 237 | self.cursor_position = Some(offset) |
238 | } | 238 | } |
239 | 239 | ||
240 | /// Specify that the assist should be active withing the `target` range. | ||
241 | /// | ||
242 | /// Target ranges are used to sort assists: the smaller the target range, | ||
243 | /// the more specific assist is, and so it should be sorted first. | ||
244 | pub(crate) fn target(&mut self, target: TextRange) { | ||
245 | self.target = Some(target) | ||
246 | } | ||
247 | |||
248 | /// Get access to the raw `TextEditBuilder`. | 240 | /// Get access to the raw `TextEditBuilder`. |
249 | pub(crate) fn text_edit_builder(&mut self) -> &mut TextEditBuilder { | 241 | pub(crate) fn text_edit_builder(&mut self) -> &mut TextEditBuilder { |
250 | &mut self.edit | 242 | &mut self.edit |
@@ -267,7 +259,6 @@ impl<'a, 'b> ActionBuilder<'a, 'b> { | |||
267 | AssistAction { | 259 | AssistAction { |
268 | edit: self.edit.finish(), | 260 | edit: self.edit.finish(), |
269 | cursor_position: self.cursor_position, | 261 | cursor_position: self.cursor_position, |
270 | target: self.target, | ||
271 | file: self.file, | 262 | file: self.file, |
272 | } | 263 | } |
273 | } | 264 | } |
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs index b72f7aeac..869d4dc04 100644 --- a/crates/ra_assists/src/handlers/add_custom_impl.rs +++ b/crates/ra_assists/src/handlers/add_custom_impl.rs | |||
@@ -48,9 +48,8 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { | |||
48 | let label = | 48 | let label = |
49 | format!("Add custom impl '{}' for '{}'", trait_token.text().as_str(), annotated_name); | 49 | format!("Add custom impl '{}' for '{}'", trait_token.text().as_str(), annotated_name); |
50 | 50 | ||
51 | ctx.add_assist(AssistId("add_custom_impl"), label, |edit| { | 51 | let target = attr.syntax().text_range(); |
52 | edit.target(attr.syntax().text_range()); | 52 | ctx.add_assist(AssistId("add_custom_impl"), label, target, |edit| { |
53 | |||
54 | let new_attr_input = input | 53 | let new_attr_input = input |
55 | .syntax() | 54 | .syntax() |
56 | .descendants_with_tokens() | 55 | .descendants_with_tokens() |
diff --git a/crates/ra_assists/src/handlers/add_derive.rs b/crates/ra_assists/src/handlers/add_derive.rs index 3629dac6b..2a6bb1cae 100644 --- a/crates/ra_assists/src/handlers/add_derive.rs +++ b/crates/ra_assists/src/handlers/add_derive.rs | |||
@@ -27,7 +27,8 @@ use crate::{Assist, AssistCtx, AssistId}; | |||
27 | pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> { | 27 | pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> { |
28 | let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; | 28 | let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; |
29 | let node_start = derive_insertion_offset(&nominal)?; | 29 | let node_start = derive_insertion_offset(&nominal)?; |
30 | ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", |edit| { | 30 | let target = nominal.syntax().text_range(); |
31 | ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", target, |edit| { | ||
31 | let derive_attr = nominal | 32 | let derive_attr = nominal |
32 | .attrs() | 33 | .attrs() |
33 | .filter_map(|x| x.as_simple_call()) | 34 | .filter_map(|x| x.as_simple_call()) |
@@ -41,7 +42,6 @@ pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> { | |||
41 | } | 42 | } |
42 | Some(tt) => tt.syntax().text_range().end() - TextSize::of(')'), | 43 | Some(tt) => tt.syntax().text_range().end() - TextSize::of(')'), |
43 | }; | 44 | }; |
44 | edit.target(nominal.syntax().text_range()); | ||
45 | edit.set_cursor(offset) | 45 | edit.set_cursor(offset) |
46 | }) | 46 | }) |
47 | } | 47 | } |
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index e39e1f4f3..a59ec16b2 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs | |||
@@ -62,8 +62,8 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> { | |||
62 | ctx.add_assist( | 62 | ctx.add_assist( |
63 | AssistId("add_explicit_type"), | 63 | AssistId("add_explicit_type"), |
64 | format!("Insert explicit type '{}'", new_type_string), | 64 | format!("Insert explicit type '{}'", new_type_string), |
65 | pat_range, | ||
65 | |edit| { | 66 | |edit| { |
66 | edit.target(pat_range); | ||
67 | if let Some(ascribed_ty) = ascribed_ty { | 67 | if let Some(ascribed_ty) = ascribed_ty { |
68 | edit.replace(ascribed_ty.syntax().text_range(), new_type_string); | 68 | edit.replace(ascribed_ty.syntax().text_range(), new_type_string); |
69 | } else { | 69 | } else { |
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs index ee0d5ce98..81deb3dfa 100644 --- a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs +++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs | |||
@@ -47,9 +47,11 @@ pub(crate) fn add_from_impl_for_enum(ctx: AssistCtx) -> Option<Assist> { | |||
47 | return None; | 47 | return None; |
48 | } | 48 | } |
49 | 49 | ||
50 | let target = variant.syntax().text_range(); | ||
50 | ctx.add_assist( | 51 | ctx.add_assist( |
51 | AssistId("add_from_impl_for_enum"), | 52 | AssistId("add_from_impl_for_enum"), |
52 | "Add From impl for this enum variant", | 53 | "Add From impl for this enum variant", |
54 | target, | ||
53 | |edit| { | 55 | |edit| { |
54 | let start_offset = variant.parent_enum().syntax().text_range().end(); | 56 | let start_offset = variant.parent_enum().syntax().text_range().end(); |
55 | let mut buf = String::new(); | 57 | let mut buf = String::new(); |
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs index cb2afc863..76c0f9783 100644 --- a/crates/ra_assists/src/handlers/add_function.rs +++ b/crates/ra_assists/src/handlers/add_function.rs | |||
@@ -57,9 +57,9 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> { | |||
57 | 57 | ||
58 | let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; | 58 | let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; |
59 | 59 | ||
60 | ctx.add_assist(AssistId("add_function"), "Add function", |edit| { | 60 | let target = call.syntax().text_range(); |
61 | edit.target(call.syntax().text_range()); | 61 | // TODO: assert here? |
62 | 62 | ctx.add_assist(AssistId("add_function"), "Add function", target, |edit| { | |
63 | if let Some(function_template) = function_builder.render() { | 63 | if let Some(function_template) = function_builder.render() { |
64 | edit.set_file(function_template.file); | 64 | edit.set_file(function_template.file); |
65 | edit.set_cursor(function_template.cursor_offset); | 65 | edit.set_cursor(function_template.cursor_offset); |
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index 3d390c20b..557344ebb 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs | |||
@@ -28,33 +28,40 @@ use crate::{Assist, AssistCtx, AssistId}; | |||
28 | pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> { | 28 | pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> { |
29 | let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; | 29 | let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; |
30 | let name = nominal.name()?; | 30 | let name = nominal.name()?; |
31 | ctx.add_assist(AssistId("add_impl"), format!("Implement {}", name.text().as_str()), |edit| { | 31 | let target = nominal.syntax().text_range(); |
32 | edit.target(nominal.syntax().text_range()); | 32 | ctx.add_assist( |
33 | let type_params = nominal.type_param_list(); | 33 | AssistId("add_impl"), |
34 | let start_offset = nominal.syntax().text_range().end(); | 34 | format!("Implement {}", name.text().as_str()), |
35 | let mut buf = String::new(); | 35 | target, |
36 | buf.push_str("\n\nimpl"); | 36 | |edit| { |
37 | if let Some(type_params) = &type_params { | 37 | let type_params = nominal.type_param_list(); |
38 | format_to!(buf, "{}", type_params.syntax()); | 38 | let start_offset = nominal.syntax().text_range().end(); |
39 | } | 39 | let mut buf = String::new(); |
40 | buf.push_str(" "); | 40 | buf.push_str("\n\nimpl"); |
41 | buf.push_str(name.text().as_str()); | 41 | if let Some(type_params) = &type_params { |
42 | if let Some(type_params) = type_params { | 42 | format_to!(buf, "{}", type_params.syntax()); |
43 | let lifetime_params = type_params | 43 | } |
44 | .lifetime_params() | 44 | buf.push_str(" "); |
45 | .filter_map(|it| it.lifetime_token()) | 45 | buf.push_str(name.text().as_str()); |
46 | .map(|it| it.text().clone()); | 46 | if let Some(type_params) = type_params { |
47 | let type_params = | 47 | let lifetime_params = type_params |
48 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); | 48 | .lifetime_params() |
49 | .filter_map(|it| it.lifetime_token()) | ||
50 | .map(|it| it.text().clone()); | ||
51 | let type_params = type_params | ||
52 | .type_params() | ||
53 | .filter_map(|it| it.name()) | ||
54 | .map(|it| it.text().clone()); | ||
49 | 55 | ||
50 | let generic_params = lifetime_params.chain(type_params).sep_by(", "); | 56 | let generic_params = lifetime_params.chain(type_params).sep_by(", "); |
51 | format_to!(buf, "<{}>", generic_params) | 57 | format_to!(buf, "<{}>", generic_params) |
52 | } | 58 | } |
53 | buf.push_str(" {\n"); | 59 | buf.push_str(" {\n"); |
54 | edit.set_cursor(start_offset + TextSize::of(&buf)); | 60 | edit.set_cursor(start_offset + TextSize::of(&buf)); |
55 | buf.push_str("\n}"); | 61 | buf.push_str("\n}"); |
56 | edit.insert(start_offset, buf); | 62 | edit.insert(start_offset, buf); |
57 | }) | 63 | }, |
64 | ) | ||
58 | } | 65 | } |
59 | 66 | ||
60 | #[cfg(test)] | 67 | #[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 f7a101503..7df786590 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs | |||
@@ -107,10 +107,10 @@ fn add_missing_impl_members_inner( | |||
107 | label: &'static str, | 107 | label: &'static str, |
108 | ) -> Option<Assist> { | 108 | ) -> Option<Assist> { |
109 | let _p = ra_prof::profile("add_missing_impl_members_inner"); | 109 | let _p = ra_prof::profile("add_missing_impl_members_inner"); |
110 | let impl_node = ctx.find_node_at_offset::<ast::ImplDef>()?; | 110 | let impl_def = ctx.find_node_at_offset::<ast::ImplDef>()?; |
111 | let impl_item_list = impl_node.item_list()?; | 111 | let impl_item_list = impl_def.item_list()?; |
112 | 112 | ||
113 | let trait_ = resolve_target_trait(&ctx.sema, &impl_node)?; | 113 | let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?; |
114 | 114 | ||
115 | let def_name = |item: &ast::AssocItem| -> Option<SmolStr> { | 115 | let def_name = |item: &ast::AssocItem| -> Option<SmolStr> { |
116 | match item { | 116 | match item { |
@@ -121,7 +121,7 @@ fn add_missing_impl_members_inner( | |||
121 | .map(|it| it.text().clone()) | 121 | .map(|it| it.text().clone()) |
122 | }; | 122 | }; |
123 | 123 | ||
124 | let missing_items = get_missing_assoc_items(&ctx.sema, &impl_node) | 124 | let missing_items = get_missing_assoc_items(&ctx.sema, &impl_def) |
125 | .iter() | 125 | .iter() |
126 | .map(|i| match i { | 126 | .map(|i| match i { |
127 | hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db).value), | 127 | hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db).value), |
@@ -143,13 +143,13 @@ fn add_missing_impl_members_inner( | |||
143 | } | 143 | } |
144 | 144 | ||
145 | let sema = ctx.sema; | 145 | let sema = ctx.sema; |
146 | 146 | let target = impl_def.syntax().text_range(); | |
147 | ctx.add_assist(AssistId(assist_id), label, |edit| { | 147 | ctx.add_assist(AssistId(assist_id), label, target, |edit| { |
148 | let n_existing_items = impl_item_list.assoc_items().count(); | 148 | let n_existing_items = impl_item_list.assoc_items().count(); |
149 | let source_scope = sema.scope_for_def(trait_); | 149 | let source_scope = sema.scope_for_def(trait_); |
150 | let target_scope = sema.scope(impl_item_list.syntax()); | 150 | let target_scope = sema.scope(impl_item_list.syntax()); |
151 | let ast_transform = QualifyPaths::new(&target_scope, &source_scope) | 151 | let ast_transform = QualifyPaths::new(&target_scope, &source_scope) |
152 | .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_node)); | 152 | .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_def)); |
153 | let items = missing_items | 153 | let items = missing_items |
154 | .into_iter() | 154 | .into_iter() |
155 | .map(|it| ast_transform::apply(&*ast_transform, it)) | 155 | .map(|it| ast_transform::apply(&*ast_transform, it)) |
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index 1b5d604d1..1c3f8435a 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs | |||
@@ -41,9 +41,8 @@ pub(crate) fn add_new(ctx: AssistCtx) -> Option<Assist> { | |||
41 | // Return early if we've found an existing new fn | 41 | // Return early if we've found an existing new fn |
42 | let impl_def = find_struct_impl(&ctx, &strukt)?; | 42 | let impl_def = find_struct_impl(&ctx, &strukt)?; |
43 | 43 | ||
44 | ctx.add_assist(AssistId("add_new"), "Add default constructor", |edit| { | 44 | let target = strukt.syntax().text_range(); |
45 | edit.target(strukt.syntax().text_range()); | 45 | ctx.add_assist(AssistId("add_new"), "Add default constructor", target, |edit| { |
46 | |||
47 | let mut buf = String::with_capacity(512); | 46 | let mut buf = String::with_capacity(512); |
48 | 47 | ||
49 | if impl_def.is_some() { | 48 | if impl_def.is_some() { |
diff --git a/crates/ra_assists/src/handlers/apply_demorgan.rs b/crates/ra_assists/src/handlers/apply_demorgan.rs index a0c48d872..a5b26e5b9 100644 --- a/crates/ra_assists/src/handlers/apply_demorgan.rs +++ b/crates/ra_assists/src/handlers/apply_demorgan.rs | |||
@@ -39,8 +39,7 @@ pub(crate) fn apply_demorgan(ctx: AssistCtx) -> Option<Assist> { | |||
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 | ctx.add_assist(AssistId("apply_demorgan"), "Apply De Morgan's law", |edit| { | 42 | ctx.add_assist(AssistId("apply_demorgan"), "Apply De Morgan's law", op_range, |edit| { |
43 | edit.target(op_range); | ||
44 | edit.replace(op_range, opposite_op); | 43 | edit.replace(op_range, opposite_op); |
45 | edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); | 44 | edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); |
46 | edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); | 45 | edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); |
diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs index 9e4171ccd..2224b9714 100644 --- a/crates/ra_assists/src/handlers/auto_import.rs +++ b/crates/ra_assists/src/handlers/auto_import.rs | |||
@@ -48,8 +48,7 @@ pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { | |||
48 | let range = ctx.sema.original_range(&auto_import_assets.syntax_under_caret).range; | 48 | let range = ctx.sema.original_range(&auto_import_assets.syntax_under_caret).range; |
49 | let mut group = ctx.add_assist_group(auto_import_assets.get_import_group_message()); | 49 | let mut group = ctx.add_assist_group(auto_import_assets.get_import_group_message()); |
50 | for import in proposed_imports { | 50 | for import in proposed_imports { |
51 | group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| { | 51 | group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), range, |edit| { |
52 | edit.target(range); | ||
53 | insert_use_statement(&auto_import_assets.syntax_under_caret, &import, edit); | 52 | insert_use_statement(&auto_import_assets.syntax_under_caret, &import, edit); |
54 | }); | 53 | }); |
55 | } | 54 | } |
diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index 6ac1f8e69..489db83e6 100644 --- a/crates/ra_assists/src/handlers/change_visibility.rs +++ b/crates/ra_assists/src/handlers/change_visibility.rs | |||
@@ -66,11 +66,15 @@ fn add_vis(ctx: AssistCtx) -> Option<Assist> { | |||
66 | return None; | 66 | return None; |
67 | }; | 67 | }; |
68 | 68 | ||
69 | ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub(crate)", |edit| { | 69 | ctx.add_assist( |
70 | edit.target(target); | 70 | AssistId("change_visibility"), |
71 | edit.insert(offset, "pub(crate) "); | 71 | "Change visibility to pub(crate)", |
72 | edit.set_cursor(offset); | 72 | target, |
73 | }) | 73 | |edit| { |
74 | edit.insert(offset, "pub(crate) "); | ||
75 | edit.set_cursor(offset); | ||
76 | }, | ||
77 | ) | ||
74 | } | 78 | } |
75 | 79 | ||
76 | fn vis_offset(node: &SyntaxNode) -> TextSize { | 80 | fn vis_offset(node: &SyntaxNode) -> TextSize { |
@@ -86,22 +90,28 @@ fn vis_offset(node: &SyntaxNode) -> TextSize { | |||
86 | 90 | ||
87 | fn change_vis(ctx: AssistCtx, vis: ast::Visibility) -> Option<Assist> { | 91 | fn change_vis(ctx: AssistCtx, vis: ast::Visibility) -> Option<Assist> { |
88 | if vis.syntax().text() == "pub" { | 92 | if vis.syntax().text() == "pub" { |
93 | let target = vis.syntax().text_range(); | ||
89 | return ctx.add_assist( | 94 | return ctx.add_assist( |
90 | AssistId("change_visibility"), | 95 | AssistId("change_visibility"), |
91 | "Change Visibility to pub(crate)", | 96 | "Change Visibility to pub(crate)", |
97 | target, | ||
92 | |edit| { | 98 | |edit| { |
93 | edit.target(vis.syntax().text_range()); | ||
94 | edit.replace(vis.syntax().text_range(), "pub(crate)"); | 99 | edit.replace(vis.syntax().text_range(), "pub(crate)"); |
95 | edit.set_cursor(vis.syntax().text_range().start()) | 100 | edit.set_cursor(vis.syntax().text_range().start()) |
96 | }, | 101 | }, |
97 | ); | 102 | ); |
98 | } | 103 | } |
99 | if vis.syntax().text() == "pub(crate)" { | 104 | if vis.syntax().text() == "pub(crate)" { |
100 | return ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub", |edit| { | 105 | let target = vis.syntax().text_range(); |
101 | edit.target(vis.syntax().text_range()); | 106 | return ctx.add_assist( |
102 | edit.replace(vis.syntax().text_range(), "pub"); | 107 | AssistId("change_visibility"), |
103 | edit.set_cursor(vis.syntax().text_range().start()); | 108 | "Change visibility to pub", |
104 | }); | 109 | target, |
110 | |edit| { | ||
111 | edit.replace(vis.syntax().text_range(), "pub"); | ||
112 | edit.set_cursor(vis.syntax().text_range().start()); | ||
113 | }, | ||
114 | ); | ||
105 | } | 115 | } |
106 | None | 116 | None |
107 | } | 117 | } |
diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs index 55ccc37b0..4bd6040b2 100644 --- a/crates/ra_assists/src/handlers/early_return.rs +++ b/crates/ra_assists/src/handlers/early_return.rs | |||
@@ -95,89 +95,94 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> { | |||
95 | then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; | 95 | then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; |
96 | let cursor_position = ctx.frange.range.start(); | 96 | let cursor_position = ctx.frange.range.start(); |
97 | 97 | ||
98 | ctx.add_assist(AssistId("convert_to_guarded_return"), "Convert to guarded return", |edit| { | 98 | let target = if_expr.syntax().text_range(); |
99 | let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); | 99 | ctx.add_assist( |
100 | let new_block = match if_let_pat { | 100 | AssistId("convert_to_guarded_return"), |
101 | None => { | 101 | "Convert to guarded return", |
102 | // If. | 102 | target, |
103 | let new_expr = { | 103 | |edit| { |
104 | let then_branch = | 104 | let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); |
105 | make::block_expr(once(make::expr_stmt(early_expression).into()), None); | 105 | let new_block = match if_let_pat { |
106 | let cond = invert_boolean_expression(cond_expr); | 106 | None => { |
107 | let e = make::expr_if(make::condition(cond, None), then_branch); | 107 | // If. |
108 | if_indent_level.increase_indent(e) | 108 | let new_expr = { |
109 | }; | 109 | let then_branch = |
110 | replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) | 110 | make::block_expr(once(make::expr_stmt(early_expression).into()), None); |
111 | } | 111 | let cond = invert_boolean_expression(cond_expr); |
112 | Some((path, bound_ident)) => { | 112 | let e = make::expr_if(make::condition(cond, None), then_branch); |
113 | // If-let. | 113 | if_indent_level.increase_indent(e) |
114 | let match_expr = { | ||
115 | let happy_arm = { | ||
116 | let pat = make::tuple_struct_pat( | ||
117 | path, | ||
118 | once(make::bind_pat(make::name("it")).into()), | ||
119 | ); | ||
120 | let expr = { | ||
121 | let name_ref = make::name_ref("it"); | ||
122 | let segment = make::path_segment(name_ref); | ||
123 | let path = make::path_unqualified(segment); | ||
124 | make::expr_path(path) | ||
125 | }; | ||
126 | make::match_arm(once(pat.into()), expr) | ||
127 | }; | 114 | }; |
115 | replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) | ||
116 | } | ||
117 | Some((path, bound_ident)) => { | ||
118 | // If-let. | ||
119 | let match_expr = { | ||
120 | let happy_arm = { | ||
121 | let pat = make::tuple_struct_pat( | ||
122 | path, | ||
123 | once(make::bind_pat(make::name("it")).into()), | ||
124 | ); | ||
125 | let expr = { | ||
126 | let name_ref = make::name_ref("it"); | ||
127 | let segment = make::path_segment(name_ref); | ||
128 | let path = make::path_unqualified(segment); | ||
129 | make::expr_path(path) | ||
130 | }; | ||
131 | make::match_arm(once(pat.into()), expr) | ||
132 | }; | ||
128 | 133 | ||
129 | let sad_arm = make::match_arm( | 134 | let sad_arm = make::match_arm( |
130 | // FIXME: would be cool to use `None` or `Err(_)` if appropriate | 135 | // FIXME: would be cool to use `None` or `Err(_)` if appropriate |
131 | once(make::placeholder_pat().into()), | 136 | once(make::placeholder_pat().into()), |
132 | early_expression, | 137 | early_expression, |
133 | ); | 138 | ); |
134 | 139 | ||
135 | make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) | 140 | make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) |
136 | }; | 141 | }; |
137 | 142 | ||
138 | let let_stmt = make::let_stmt( | 143 | let let_stmt = make::let_stmt( |
139 | make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), | 144 | make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), |
140 | Some(match_expr), | 145 | Some(match_expr), |
146 | ); | ||
147 | let let_stmt = if_indent_level.increase_indent(let_stmt); | ||
148 | replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) | ||
149 | } | ||
150 | }; | ||
151 | edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); | ||
152 | edit.set_cursor(cursor_position); | ||
153 | |||
154 | fn replace( | ||
155 | new_expr: &SyntaxNode, | ||
156 | then_block: &ast::BlockExpr, | ||
157 | parent_block: &ast::BlockExpr, | ||
158 | if_expr: &ast::IfExpr, | ||
159 | ) -> SyntaxNode { | ||
160 | let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone()); | ||
161 | let end_of_then = then_block_items.syntax().last_child_or_token().unwrap(); | ||
162 | let end_of_then = | ||
163 | if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { | ||
164 | end_of_then.prev_sibling_or_token().unwrap() | ||
165 | } else { | ||
166 | end_of_then | ||
167 | }; | ||
168 | let mut then_statements = new_expr.children_with_tokens().chain( | ||
169 | then_block_items | ||
170 | .syntax() | ||
171 | .children_with_tokens() | ||
172 | .skip(1) | ||
173 | .take_while(|i| *i != end_of_then), | ||
141 | ); | 174 | ); |
142 | let let_stmt = if_indent_level.increase_indent(let_stmt); | 175 | replace_children( |
143 | replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) | 176 | &parent_block.syntax(), |
177 | RangeInclusive::new( | ||
178 | if_expr.clone().syntax().clone().into(), | ||
179 | if_expr.syntax().clone().into(), | ||
180 | ), | ||
181 | &mut then_statements, | ||
182 | ) | ||
144 | } | 183 | } |
145 | }; | 184 | }, |
146 | edit.target(if_expr.syntax().text_range()); | 185 | ) |
147 | edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); | ||
148 | edit.set_cursor(cursor_position); | ||
149 | |||
150 | fn replace( | ||
151 | new_expr: &SyntaxNode, | ||
152 | then_block: &ast::BlockExpr, | ||
153 | parent_block: &ast::BlockExpr, | ||
154 | if_expr: &ast::IfExpr, | ||
155 | ) -> SyntaxNode { | ||
156 | let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone()); | ||
157 | let end_of_then = then_block_items.syntax().last_child_or_token().unwrap(); | ||
158 | let end_of_then = | ||
159 | if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { | ||
160 | end_of_then.prev_sibling_or_token().unwrap() | ||
161 | } else { | ||
162 | end_of_then | ||
163 | }; | ||
164 | let mut then_statements = new_expr.children_with_tokens().chain( | ||
165 | then_block_items | ||
166 | .syntax() | ||
167 | .children_with_tokens() | ||
168 | .skip(1) | ||
169 | .take_while(|i| *i != end_of_then), | ||
170 | ); | ||
171 | replace_children( | ||
172 | &parent_block.syntax(), | ||
173 | RangeInclusive::new( | ||
174 | if_expr.clone().syntax().clone().into(), | ||
175 | if_expr.syntax().clone().into(), | ||
176 | ), | ||
177 | &mut then_statements, | ||
178 | ) | ||
179 | } | ||
180 | }) | ||
181 | } | 186 | } |
182 | 187 | ||
183 | #[cfg(test)] | 188 | #[cfg(test)] |
diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs index 1f9cd5585..7c8f8bdf2 100644 --- a/crates/ra_assists/src/handlers/fill_match_arms.rs +++ b/crates/ra_assists/src/handlers/fill_match_arms.rs | |||
@@ -92,10 +92,9 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option<Assist> { | |||
92 | return None; | 92 | return None; |
93 | } | 93 | } |
94 | 94 | ||
95 | ctx.add_assist(AssistId("fill_match_arms"), "Fill match arms", |edit| { | 95 | let target = match_expr.syntax().text_range(); |
96 | ctx.add_assist(AssistId("fill_match_arms"), "Fill match arms", target, |edit| { | ||
96 | let new_arm_list = match_arm_list.remove_placeholder().append_arms(missing_arms); | 97 | let new_arm_list = match_arm_list.remove_placeholder().append_arms(missing_arms); |
97 | |||
98 | edit.target(match_expr.syntax().text_range()); | ||
99 | edit.set_cursor(expr.syntax().text_range().start()); | 98 | edit.set_cursor(expr.syntax().text_range().start()); |
100 | edit.replace_ast(match_arm_list, new_arm_list); | 99 | edit.replace_ast(match_arm_list, new_arm_list); |
101 | }) | 100 | }) |
diff --git a/crates/ra_assists/src/handlers/flip_binexpr.rs b/crates/ra_assists/src/handlers/flip_binexpr.rs index 41db963dc..cb7264d7b 100644 --- a/crates/ra_assists/src/handlers/flip_binexpr.rs +++ b/crates/ra_assists/src/handlers/flip_binexpr.rs | |||
@@ -33,8 +33,7 @@ pub(crate) fn flip_binexpr(ctx: AssistCtx) -> Option<Assist> { | |||
33 | return None; | 33 | return None; |
34 | } | 34 | } |
35 | 35 | ||
36 | ctx.add_assist(AssistId("flip_binexpr"), "Flip binary expression", |edit| { | 36 | ctx.add_assist(AssistId("flip_binexpr"), "Flip binary expression", op_range, |edit| { |
37 | edit.target(op_range); | ||
38 | if let FlipAction::FlipAndReplaceOp(new_op) = action { | 37 | if let FlipAction::FlipAndReplaceOp(new_op) = action { |
39 | edit.replace(op_range, new_op); | 38 | edit.replace(op_range, new_op); |
40 | } | 39 | } |
diff --git a/crates/ra_assists/src/handlers/flip_comma.rs b/crates/ra_assists/src/handlers/flip_comma.rs index e65c9a41d..24982ae22 100644 --- a/crates/ra_assists/src/handlers/flip_comma.rs +++ b/crates/ra_assists/src/handlers/flip_comma.rs | |||
@@ -28,8 +28,7 @@ pub(crate) fn flip_comma(ctx: AssistCtx) -> Option<Assist> { | |||
28 | return None; | 28 | return None; |
29 | } | 29 | } |
30 | 30 | ||
31 | ctx.add_assist(AssistId("flip_comma"), "Flip comma", |edit| { | 31 | ctx.add_assist(AssistId("flip_comma"), "Flip comma", comma.text_range(), |edit| { |
32 | edit.target(comma.text_range()); | ||
33 | edit.replace(prev.text_range(), next.to_string()); | 32 | edit.replace(prev.text_range(), next.to_string()); |
34 | edit.replace(next.text_range(), prev.to_string()); | 33 | edit.replace(next.text_range(), prev.to_string()); |
35 | }) | 34 | }) |
diff --git a/crates/ra_assists/src/handlers/flip_trait_bound.rs b/crates/ra_assists/src/handlers/flip_trait_bound.rs index f186da585..6a3b2df67 100644 --- a/crates/ra_assists/src/handlers/flip_trait_bound.rs +++ b/crates/ra_assists/src/handlers/flip_trait_bound.rs | |||
@@ -32,8 +32,8 @@ pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option<Assist> { | |||
32 | non_trivia_sibling(plus.clone().into(), Direction::Next)?, | 32 | non_trivia_sibling(plus.clone().into(), Direction::Next)?, |
33 | ); | 33 | ); |
34 | 34 | ||
35 | ctx.add_assist(AssistId("flip_trait_bound"), "Flip trait bounds", |edit| { | 35 | let target = plus.text_range(); |
36 | edit.target(plus.text_range()); | 36 | ctx.add_assist(AssistId("flip_trait_bound"), "Flip trait bounds", target, |edit| { |
37 | edit.replace(before.text_range(), after.to_string()); | 37 | edit.replace(before.text_range(), after.to_string()); |
38 | edit.replace(after.text_range(), before.to_string()); | 38 | edit.replace(after.text_range(), before.to_string()); |
39 | }) | 39 | }) |
diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index 5f3b8dfd1..e5765c845 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs | |||
@@ -106,9 +106,11 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> { | |||
106 | let init_str = initializer_expr.syntax().text().to_string(); | 106 | let init_str = initializer_expr.syntax().text().to_string(); |
107 | let init_in_paren = format!("({})", &init_str); | 107 | let init_in_paren = format!("({})", &init_str); |
108 | 108 | ||
109 | let target = bind_pat.syntax().text_range(); | ||
109 | ctx.add_assist( | 110 | ctx.add_assist( |
110 | AssistId("inline_local_variable"), | 111 | AssistId("inline_local_variable"), |
111 | "Inline variable", | 112 | "Inline variable", |
113 | target, | ||
112 | move |edit: &mut ActionBuilder| { | 114 | move |edit: &mut ActionBuilder| { |
113 | edit.delete(delete_range); | 115 | edit.delete(delete_range); |
114 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { | 116 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { |
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index 9c2c20b22..3c340ff3b 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs | |||
@@ -42,7 +42,8 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> { | |||
42 | if indent.kind() != WHITESPACE { | 42 | if indent.kind() != WHITESPACE { |
43 | return None; | 43 | return None; |
44 | } | 44 | } |
45 | ctx.add_assist(AssistId("introduce_variable"), "Extract into variable", move |edit| { | 45 | let target = expr.syntax().text_range(); |
46 | ctx.add_assist(AssistId("introduce_variable"), "Extract into variable", target, move |edit| { | ||
46 | let mut buf = String::new(); | 47 | let mut buf = String::new(); |
47 | 48 | ||
48 | let cursor_offset = if wrap_in_block { | 49 | let cursor_offset = if wrap_in_block { |
@@ -79,7 +80,6 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> { | |||
79 | buf.push_str(text); | 80 | buf.push_str(text); |
80 | } | 81 | } |
81 | 82 | ||
82 | edit.target(expr.syntax().text_range()); | ||
83 | edit.replace(expr.syntax().text_range(), "var_name".to_string()); | 83 | edit.replace(expr.syntax().text_range(), "var_name".to_string()); |
84 | edit.insert(anchor_stmt.text_range().start(), buf); | 84 | edit.insert(anchor_stmt.text_range().start(), buf); |
85 | if wrap_in_block { | 85 | if wrap_in_block { |
diff --git a/crates/ra_assists/src/handlers/invert_if.rs b/crates/ra_assists/src/handlers/invert_if.rs index 303c1806d..b16271443 100644 --- a/crates/ra_assists/src/handlers/invert_if.rs +++ b/crates/ra_assists/src/handlers/invert_if.rs | |||
@@ -47,8 +47,7 @@ pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> { | |||
47 | let else_node = else_block.syntax(); | 47 | let else_node = else_block.syntax(); |
48 | let else_range = else_node.text_range(); | 48 | let else_range = else_node.text_range(); |
49 | let then_range = then_node.text_range(); | 49 | let then_range = then_node.text_range(); |
50 | return ctx.add_assist(AssistId("invert_if"), "Invert if", |edit| { | 50 | return ctx.add_assist(AssistId("invert_if"), "Invert if", if_range, |edit| { |
51 | edit.target(if_range); | ||
52 | edit.replace(cond_range, flip_cond.syntax().text()); | 51 | edit.replace(cond_range, flip_cond.syntax().text()); |
53 | edit.replace(else_range, then_node.text()); | 52 | edit.replace(else_range, then_node.text()); |
54 | edit.replace(then_range, else_node.text()); | 53 | 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 9a2083609..de74d83d8 100644 --- a/crates/ra_assists/src/handlers/merge_imports.rs +++ b/crates/ra_assists/src/handlers/merge_imports.rs | |||
@@ -52,7 +52,8 @@ pub(crate) fn merge_imports(ctx: AssistCtx) -> Option<Assist> { | |||
52 | } | 52 | } |
53 | }; | 53 | }; |
54 | 54 | ||
55 | ctx.add_assist(AssistId("merge_imports"), "Merge imports", |edit| { | 55 | let target = tree.syntax().text_range(); |
56 | ctx.add_assist(AssistId("merge_imports"), "Merge imports", target, |edit| { | ||
56 | edit.rewrite(rewriter); | 57 | edit.rewrite(rewriter); |
57 | // FIXME: we only need because our diff is imprecise | 58 | // FIXME: we only need because our diff is imprecise |
58 | edit.set_cursor(offset); | 59 | edit.set_cursor(offset); |
diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs index 9ae099b41..7c4d9d55d 100644 --- a/crates/ra_assists/src/handlers/merge_match_arms.rs +++ b/crates/ra_assists/src/handlers/merge_match_arms.rs | |||
@@ -70,7 +70,7 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> { | |||
70 | return None; | 70 | return None; |
71 | } | 71 | } |
72 | 72 | ||
73 | ctx.add_assist(AssistId("merge_match_arms"), "Merge match arms", |edit| { | 73 | ctx.add_assist(AssistId("merge_match_arms"), "Merge match arms", current_text_range, |edit| { |
74 | let pats = if arms_to_merge.iter().any(contains_placeholder) { | 74 | let pats = if arms_to_merge.iter().any(contains_placeholder) { |
75 | "_".into() | 75 | "_".into() |
76 | } else { | 76 | } else { |
@@ -87,7 +87,6 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> { | |||
87 | let start = arms_to_merge.first().unwrap().syntax().text_range().start(); | 87 | let start = arms_to_merge.first().unwrap().syntax().text_range().start(); |
88 | let end = arms_to_merge.last().unwrap().syntax().text_range().end(); | 88 | let end = arms_to_merge.last().unwrap().syntax().text_range().end(); |
89 | 89 | ||
90 | edit.target(current_text_range); | ||
91 | edit.set_cursor(match cursor_pos { | 90 | edit.set_cursor(match cursor_pos { |
92 | CursorPos::InExpr(back_offset) => start + TextSize::of(&arm) - back_offset, | 91 | CursorPos::InExpr(back_offset) => start + TextSize::of(&arm) - back_offset, |
93 | CursorPos::InPat(offset) => offset, | 92 | CursorPos::InPat(offset) => offset, |
diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs index 89956aea9..44e50cb6e 100644 --- a/crates/ra_assists/src/handlers/move_bounds.rs +++ b/crates/ra_assists/src/handlers/move_bounds.rs | |||
@@ -49,30 +49,37 @@ pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> { | |||
49 | } | 49 | } |
50 | }; | 50 | }; |
51 | 51 | ||
52 | ctx.add_assist(AssistId("move_bounds_to_where_clause"), "Move to where clause", |edit| { | 52 | let target = type_param_list.syntax().text_range(); |
53 | let new_params = type_param_list | 53 | ctx.add_assist( |
54 | .type_params() | 54 | AssistId("move_bounds_to_where_clause"), |
55 | .filter(|it| it.type_bound_list().is_some()) | 55 | "Move to where clause", |
56 | .map(|type_param| { | 56 | target, |
57 | let without_bounds = type_param.remove_bounds(); | 57 | |edit| { |
58 | (type_param, without_bounds) | 58 | let new_params = type_param_list |
59 | }); | 59 | .type_params() |
60 | 60 | .filter(|it| it.type_bound_list().is_some()) | |
61 | let new_type_param_list = type_param_list.replace_descendants(new_params); | 61 | .map(|type_param| { |
62 | edit.replace_ast(type_param_list.clone(), new_type_param_list); | 62 | let without_bounds = type_param.remove_bounds(); |
63 | 63 | (type_param, without_bounds) | |
64 | let where_clause = { | 64 | }); |
65 | let predicates = type_param_list.type_params().filter_map(build_predicate); | 65 | |
66 | make::where_clause(predicates) | 66 | let new_type_param_list = type_param_list.replace_descendants(new_params); |
67 | }; | 67 | edit.replace_ast(type_param_list.clone(), new_type_param_list); |
68 | 68 | ||
69 | let to_insert = match anchor.prev_sibling_or_token() { | 69 | let where_clause = { |
70 | Some(ref elem) if elem.kind() == WHITESPACE => format!("{} ", where_clause.syntax()), | 70 | let predicates = type_param_list.type_params().filter_map(build_predicate); |
71 | _ => format!(" {}", where_clause.syntax()), | 71 | make::where_clause(predicates) |
72 | }; | 72 | }; |
73 | edit.insert(anchor.text_range().start(), to_insert); | 73 | |
74 | edit.target(type_param_list.syntax().text_range()); | 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 f2aa7e594..29bc9a9ff 100644 --- a/crates/ra_assists/src/handlers/move_guard.rs +++ b/crates/ra_assists/src/handlers/move_guard.rs | |||
@@ -40,8 +40,8 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option<Assist> { | |||
40 | let arm_expr = match_arm.expr()?; | 40 | let arm_expr = match_arm.expr()?; |
41 | let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); | 41 | let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); |
42 | 42 | ||
43 | ctx.add_assist(AssistId("move_guard_to_arm_body"), "Move guard to arm body", |edit| { | 43 | let target = guard.syntax().text_range(); |
44 | edit.target(guard.syntax().text_range()); | 44 | ctx.add_assist(AssistId("move_guard_to_arm_body"), "Move guard to arm body", target, |edit| { |
45 | let offseting_amount = match space_before_guard.and_then(|it| it.into_token()) { | 45 | let offseting_amount = match space_before_guard.and_then(|it| it.into_token()) { |
46 | Some(tok) => { | 46 | Some(tok) => { |
47 | if ast::Whitespace::cast(tok.clone()).is_some() { | 47 | if ast::Whitespace::cast(tok.clone()).is_some() { |
@@ -108,11 +108,12 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> { | |||
108 | 108 | ||
109 | let buf = format!(" if {}", cond.syntax().text()); | 109 | let buf = format!(" if {}", cond.syntax().text()); |
110 | 110 | ||
111 | let target = if_expr.syntax().text_range(); | ||
111 | ctx.add_assist( | 112 | ctx.add_assist( |
112 | AssistId("move_arm_cond_to_match_guard"), | 113 | AssistId("move_arm_cond_to_match_guard"), |
113 | "Move condition to match guard", | 114 | "Move condition to match guard", |
115 | target, | ||
114 | |edit| { | 116 | |edit| { |
115 | edit.target(if_expr.syntax().text_range()); | ||
116 | let then_only_expr = then_block.statements().next().is_none(); | 117 | let then_only_expr = then_block.statements().next().is_none(); |
117 | 118 | ||
118 | match &then_block.expr() { | 119 | match &then_block.expr() { |
diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs index 542f7a637..155c679b4 100644 --- a/crates/ra_assists/src/handlers/raw_string.rs +++ b/crates/ra_assists/src/handlers/raw_string.rs | |||
@@ -25,8 +25,8 @@ use crate::{Assist, AssistCtx, AssistId}; | |||
25 | pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option<Assist> { | 25 | pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option<Assist> { |
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 | ctx.add_assist(AssistId("make_raw_string"), "Rewrite as raw string", |edit| { | 28 | let target = token.syntax().text_range(); |
29 | edit.target(token.syntax().text_range()); | 29 | ctx.add_assist(AssistId("make_raw_string"), "Rewrite as raw string", target, |edit| { |
30 | let max_hash_streak = count_hashes(&value); | 30 | let max_hash_streak = count_hashes(&value); |
31 | let mut hashes = String::with_capacity(max_hash_streak + 1); | 31 | let mut hashes = String::with_capacity(max_hash_streak + 1); |
32 | for _ in 0..hashes.capacity() { | 32 | for _ in 0..hashes.capacity() { |
@@ -54,8 +54,8 @@ pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option<Assist> { | |||
54 | pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option<Assist> { | 54 | pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option<Assist> { |
55 | let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?; | 55 | let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?; |
56 | let value = token.value()?; | 56 | let value = token.value()?; |
57 | ctx.add_assist(AssistId("make_usual_string"), "Rewrite as regular string", |edit| { | 57 | let target = token.syntax().text_range(); |
58 | edit.target(token.syntax().text_range()); | 58 | ctx.add_assist(AssistId("make_usual_string"), "Rewrite as regular string", target, |edit| { |
59 | // parse inside string to escape `"` | 59 | // parse inside string to escape `"` |
60 | let escaped = value.escape_default().to_string(); | 60 | let escaped = value.escape_default().to_string(); |
61 | edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); | 61 | edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); |
@@ -79,8 +79,8 @@ pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option<Assist> { | |||
79 | // ``` | 79 | // ``` |
80 | pub(crate) fn add_hash(ctx: AssistCtx) -> Option<Assist> { | 80 | pub(crate) fn add_hash(ctx: AssistCtx) -> Option<Assist> { |
81 | let token = ctx.find_token_at_offset(RAW_STRING)?; | 81 | let token = ctx.find_token_at_offset(RAW_STRING)?; |
82 | ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| { | 82 | let target = token.text_range(); |
83 | edit.target(token.text_range()); | 83 | ctx.add_assist(AssistId("add_hash"), "Add # to raw string", target, |edit| { |
84 | edit.insert(token.text_range().start() + TextSize::of('r'), "#"); | 84 | edit.insert(token.text_range().start() + TextSize::of('r'), "#"); |
85 | edit.insert(token.text_range().end(), "#"); | 85 | edit.insert(token.text_range().end(), "#"); |
86 | }) | 86 | }) |
@@ -108,8 +108,8 @@ pub(crate) fn remove_hash(ctx: AssistCtx) -> Option<Assist> { | |||
108 | // no hash to remove | 108 | // no hash to remove |
109 | return None; | 109 | return None; |
110 | } | 110 | } |
111 | ctx.add_assist(AssistId("remove_hash"), "Remove hash from raw string", |edit| { | 111 | let target = token.text_range(); |
112 | edit.target(token.text_range()); | 112 | ctx.add_assist(AssistId("remove_hash"), "Remove hash from raw string", target, |edit| { |
113 | let result = &text[2..text.len() - 1]; | 113 | let result = &text[2..text.len() - 1]; |
114 | let result = if result.starts_with('\"') { | 114 | let result = if result.starts_with('\"') { |
115 | // FIXME: this logic is wrong, not only the last has has to handled specially | 115 | // FIXME: this logic is wrong, not only the last has has to handled specially |
diff --git a/crates/ra_assists/src/handlers/remove_dbg.rs b/crates/ra_assists/src/handlers/remove_dbg.rs index ddfb21a7e..e6e02f2ae 100644 --- a/crates/ra_assists/src/handlers/remove_dbg.rs +++ b/crates/ra_assists/src/handlers/remove_dbg.rs | |||
@@ -57,8 +57,8 @@ pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option<Assist> { | |||
57 | text.slice(without_parens).to_string() | 57 | text.slice(without_parens).to_string() |
58 | }; | 58 | }; |
59 | 59 | ||
60 | ctx.add_assist(AssistId("remove_dbg"), "Remove dbg!()", |edit| { | 60 | let target = macro_call.syntax().text_range(); |
61 | edit.target(macro_call.syntax().text_range()); | 61 | ctx.add_assist(AssistId("remove_dbg"), "Remove dbg!()", target, |edit| { |
62 | edit.replace(macro_range, macro_content); | 62 | edit.replace(macro_range, macro_content); |
63 | edit.set_cursor(cursor_pos); | 63 | edit.set_cursor(cursor_pos); |
64 | }) | 64 | }) |
diff --git a/crates/ra_assists/src/handlers/remove_mut.rs b/crates/ra_assists/src/handlers/remove_mut.rs index e598023b2..9f72f879d 100644 --- a/crates/ra_assists/src/handlers/remove_mut.rs +++ b/crates/ra_assists/src/handlers/remove_mut.rs | |||
@@ -25,7 +25,8 @@ pub(crate) fn remove_mut(ctx: AssistCtx) -> Option<Assist> { | |||
25 | _ => mut_token.text_range().end(), | 25 | _ => mut_token.text_range().end(), |
26 | }; | 26 | }; |
27 | 27 | ||
28 | ctx.add_assist(AssistId("remove_mut"), "Remove `mut` keyword", |edit| { | 28 | let target = mut_token.text_range(); |
29 | ctx.add_assist(AssistId("remove_mut"), "Remove `mut` keyword", target, |edit| { | ||
29 | edit.set_cursor(delete_from); | 30 | edit.set_cursor(delete_from); |
30 | edit.delete(TextRange::new(delete_from, delete_to)); | 31 | edit.delete(TextRange::new(delete_from, delete_to)); |
31 | }) | 32 | }) |
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs index a57e327b8..0b930dea2 100644 --- a/crates/ra_assists/src/handlers/reorder_fields.rs +++ b/crates/ra_assists/src/handlers/reorder_fields.rs | |||
@@ -50,11 +50,11 @@ fn reorder<R: AstNode>(ctx: AssistCtx) -> Option<Assist> { | |||
50 | return None; | 50 | return None; |
51 | } | 51 | } |
52 | 52 | ||
53 | ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", |edit| { | 53 | let target = record.syntax().text_range(); |
54 | ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", target, |edit| { | ||
54 | for (old, new) in fields.iter().zip(&sorted_fields) { | 55 | for (old, new) in fields.iter().zip(&sorted_fields) { |
55 | algo::diff(old, new).into_text_edit(edit.text_edit_builder()); | 56 | algo::diff(old, new).into_text_edit(edit.text_edit_builder()); |
56 | } | 57 | } |
57 | edit.target(record.syntax().text_range()) | ||
58 | }) | 58 | }) |
59 | } | 59 | } |
60 | 60 | ||
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 d0df3b84e..2eb8348f8 100644 --- a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs +++ b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs | |||
@@ -44,30 +44,35 @@ pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> { | |||
44 | }; | 44 | }; |
45 | 45 | ||
46 | let sema = ctx.sema; | 46 | let sema = ctx.sema; |
47 | ctx.add_assist(AssistId("replace_if_let_with_match"), "Replace with match", move |edit| { | 47 | let target = if_expr.syntax().text_range(); |
48 | let match_expr = { | 48 | ctx.add_assist( |
49 | let then_arm = { | 49 | AssistId("replace_if_let_with_match"), |
50 | let then_expr = unwrap_trivial_block(then_block); | 50 | "Replace with match", |
51 | make::match_arm(vec![pat.clone()], then_expr) | 51 | target, |
52 | move |edit| { | ||
53 | let match_expr = { | ||
54 | let then_arm = { | ||
55 | let then_expr = unwrap_trivial_block(then_block); | ||
56 | make::match_arm(vec![pat.clone()], then_expr) | ||
57 | }; | ||
58 | let else_arm = { | ||
59 | let pattern = sema | ||
60 | .type_of_pat(&pat) | ||
61 | .and_then(|ty| TryEnum::from_ty(sema, &ty)) | ||
62 | .map(|it| it.sad_pattern()) | ||
63 | .unwrap_or_else(|| make::placeholder_pat().into()); | ||
64 | let else_expr = unwrap_trivial_block(else_block); | ||
65 | make::match_arm(vec![pattern], else_expr) | ||
66 | }; | ||
67 | make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])) | ||
52 | }; | 68 | }; |
53 | let else_arm = { | ||
54 | let pattern = sema | ||
55 | .type_of_pat(&pat) | ||
56 | .and_then(|ty| TryEnum::from_ty(sema, &ty)) | ||
57 | .map(|it| it.sad_pattern()) | ||
58 | .unwrap_or_else(|| make::placeholder_pat().into()); | ||
59 | let else_expr = unwrap_trivial_block(else_block); | ||
60 | make::match_arm(vec![pattern], else_expr) | ||
61 | }; | ||
62 | make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])) | ||
63 | }; | ||
64 | 69 | ||
65 | let match_expr = IndentLevel::from_node(if_expr.syntax()).increase_indent(match_expr); | 70 | let match_expr = IndentLevel::from_node(if_expr.syntax()).increase_indent(match_expr); |
66 | 71 | ||
67 | edit.target(if_expr.syntax().text_range()); | 72 | edit.set_cursor(if_expr.syntax().text_range().start()); |
68 | edit.set_cursor(if_expr.syntax().text_range().start()); | 73 | edit.replace_ast::<ast::Expr>(if_expr.into(), match_expr); |
69 | edit.replace_ast::<ast::Expr>(if_expr.into(), match_expr); | 74 | }, |
70 | }) | 75 | ) |
71 | } | 76 | } |
72 | 77 | ||
73 | #[cfg(test)] | 78 | #[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 dc4d16055..a5509a567 100644 --- a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs +++ b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs | |||
@@ -47,7 +47,8 @@ pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option<Assist> { | |||
47 | let ty = ctx.sema.type_of_expr(&init)?; | 47 | let ty = ctx.sema.type_of_expr(&init)?; |
48 | let happy_variant = TryEnum::from_ty(ctx.sema, &ty).map(|it| it.happy_case()); | 48 | let happy_variant = TryEnum::from_ty(ctx.sema, &ty).map(|it| it.happy_case()); |
49 | 49 | ||
50 | ctx.add_assist(AssistId("replace_let_with_if_let"), "Replace with if-let", |edit| { | 50 | let target = let_kw.text_range(); |
51 | ctx.add_assist(AssistId("replace_let_with_if_let"), "Replace with if-let", target, |edit| { | ||
51 | let with_placeholder: ast::Pat = match happy_variant { | 52 | let with_placeholder: ast::Pat = match happy_variant { |
52 | None => make::placeholder_pat().into(), | 53 | None => make::placeholder_pat().into(), |
53 | Some(var_name) => make::tuple_struct_pat( | 54 | Some(var_name) => make::tuple_struct_pat( |
@@ -67,7 +68,6 @@ pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option<Assist> { | |||
67 | let stmt = stmt.replace_descendant(placeholder.into(), original_pat); | 68 | let stmt = stmt.replace_descendant(placeholder.into(), original_pat); |
68 | 69 | ||
69 | edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); | 70 | edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); |
70 | edit.target(let_kw.text_range()); | ||
71 | edit.set_cursor(target_offset); | 71 | edit.set_cursor(target_offset); |
72 | }) | 72 | }) |
73 | } | 73 | } |
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 624178924..fd41da64b 100644 --- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -33,9 +33,11 @@ pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option<Assist> | |||
33 | return None; | 33 | return None; |
34 | } | 34 | } |
35 | 35 | ||
36 | let target = path.syntax().text_range(); | ||
36 | ctx.add_assist( | 37 | ctx.add_assist( |
37 | AssistId("replace_qualified_name_with_use"), | 38 | AssistId("replace_qualified_name_with_use"), |
38 | "Replace qualified path with use", | 39 | "Replace qualified path with use", |
40 | target, | ||
39 | |edit| { | 41 | |edit| { |
40 | let path_to_import = hir_path.mod_path().clone(); | 42 | let path_to_import = hir_path.mod_path().clone(); |
41 | insert_use_statement(path.syntax(), &path_to_import, edit); | 43 | insert_use_statement(path.syntax(), &path_to_import, edit); |
diff --git a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs index dcb471edb..c6b73da67 100644 --- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs +++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs | |||
@@ -38,26 +38,32 @@ pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> { | |||
38 | let caller = method_call.expr()?; | 38 | let caller = method_call.expr()?; |
39 | let ty = ctx.sema.type_of_expr(&caller)?; | 39 | let ty = ctx.sema.type_of_expr(&caller)?; |
40 | let happy_variant = TryEnum::from_ty(ctx.sema, &ty)?.happy_case(); | 40 | let happy_variant = TryEnum::from_ty(ctx.sema, &ty)?.happy_case(); |
41 | let target = method_call.syntax().text_range(); | ||
42 | ctx.add_assist( | ||
43 | AssistId("replace_unwrap_with_match"), | ||
44 | "Replace unwrap with match", | ||
45 | target, | ||
46 | |edit| { | ||
47 | let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); | ||
48 | let it = make::bind_pat(make::name("a")).into(); | ||
49 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); | ||
41 | 50 | ||
42 | ctx.add_assist(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", |edit| { | 51 | let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); |
43 | let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); | 52 | let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); |
44 | let it = make::bind_pat(make::name("a")).into(); | ||
45 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); | ||
46 | 53 | ||
47 | let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); | 54 | let unreachable_call = make::unreachable_macro_call().into(); |
48 | let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); | 55 | let err_arm = |
56 | make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); | ||
49 | 57 | ||
50 | let unreachable_call = make::unreachable_macro_call().into(); | 58 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); |
51 | let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); | 59 | let match_expr = make::expr_match(caller.clone(), match_arm_list); |
60 | let match_expr = | ||
61 | IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr); | ||
52 | 62 | ||
53 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); | 63 | edit.set_cursor(caller.syntax().text_range().start()); |
54 | let match_expr = make::expr_match(caller.clone(), match_arm_list); | 64 | edit.replace_ast::<ast::Expr>(method_call.into(), match_expr); |
55 | let match_expr = IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr); | 65 | }, |
56 | 66 | ) | |
57 | edit.target(method_call.syntax().text_range()); | ||
58 | edit.set_cursor(caller.syntax().text_range().start()); | ||
59 | edit.replace_ast::<ast::Expr>(method_call.into(), match_expr); | ||
60 | }) | ||
61 | } | 67 | } |
62 | 68 | ||
63 | #[cfg(test)] | 69 | #[cfg(test)] |
diff --git a/crates/ra_assists/src/handlers/split_import.rs b/crates/ra_assists/src/handlers/split_import.rs index a59f2f76f..d49563974 100644 --- a/crates/ra_assists/src/handlers/split_import.rs +++ b/crates/ra_assists/src/handlers/split_import.rs | |||
@@ -28,8 +28,8 @@ pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> { | |||
28 | } | 28 | } |
29 | let cursor = ctx.frange.range.start(); | 29 | let cursor = ctx.frange.range.start(); |
30 | 30 | ||
31 | ctx.add_assist(AssistId("split_import"), "Split import", |edit| { | 31 | let target = colon_colon.text_range(); |
32 | edit.target(colon_colon.text_range()); | 32 | ctx.add_assist(AssistId("split_import"), "Split import", target, |edit| { |
33 | edit.replace_ast(use_tree, new_tree); | 33 | edit.replace_ast(use_tree, new_tree); |
34 | edit.set_cursor(cursor); | 34 | edit.set_cursor(cursor); |
35 | }) | 35 | }) |
diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs index 89992117d..6df927abb 100644 --- a/crates/ra_assists/src/handlers/unwrap_block.rs +++ b/crates/ra_assists/src/handlers/unwrap_block.rs | |||
@@ -57,9 +57,9 @@ pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option<Assist> { | |||
57 | } | 57 | } |
58 | }; | 58 | }; |
59 | 59 | ||
60 | ctx.add_assist(AssistId("unwrap_block"), "Unwrap block", |edit| { | 60 | let target = expr_to_unwrap.syntax().text_range(); |
61 | ctx.add_assist(AssistId("unwrap_block"), "Unwrap block", target, |edit| { | ||
61 | edit.set_cursor(expr.syntax().text_range().start()); | 62 | edit.set_cursor(expr.syntax().text_range().start()); |
62 | edit.target(expr_to_unwrap.syntax().text_range()); | ||
63 | 63 | ||
64 | let pat_start: &[_] = &[' ', '{', '\n']; | 64 | let pat_start: &[_] = &[' ', '{', '\n']; |
65 | let expr_to_unwrap = expr_to_unwrap.to_string(); | 65 | let expr_to_unwrap = expr_to_unwrap.to_string(); |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index b794b021d..f4f37614f 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -36,16 +36,24 @@ pub struct AssistLabel { | |||
36 | /// Short description of the assist, as shown in the UI. | 36 | /// Short description of the assist, as shown in the UI. |
37 | pub label: String, | 37 | pub label: String, |
38 | pub group: Option<GroupLabel>, | 38 | pub group: Option<GroupLabel>, |
39 | /// Target ranges are used to sort assists: the smaller the target range, | ||
40 | /// the more specific assist is, and so it should be sorted first. | ||
41 | pub target: TextRange, | ||
39 | } | 42 | } |
40 | 43 | ||
41 | #[derive(Clone, Debug)] | 44 | #[derive(Clone, Debug)] |
42 | pub struct GroupLabel(pub String); | 45 | pub struct GroupLabel(pub String); |
43 | 46 | ||
44 | impl AssistLabel { | 47 | impl AssistLabel { |
45 | pub(crate) fn new(id: AssistId, label: String, group: Option<GroupLabel>) -> AssistLabel { | 48 | pub(crate) fn new( |
49 | id: AssistId, | ||
50 | label: String, | ||
51 | group: Option<GroupLabel>, | ||
52 | target: TextRange, | ||
53 | ) -> AssistLabel { | ||
46 | // FIXME: make fields private, so that this invariant can't be broken | 54 | // FIXME: make fields private, so that this invariant can't be broken |
47 | assert!(label.starts_with(|c: char| c.is_uppercase())); | 55 | assert!(label.starts_with(|c: char| c.is_uppercase())); |
48 | AssistLabel { id, label, group } | 56 | AssistLabel { id, label, group, target } |
49 | } | 57 | } |
50 | } | 58 | } |
51 | 59 | ||
@@ -53,8 +61,6 @@ impl AssistLabel { | |||
53 | pub struct AssistAction { | 61 | pub struct AssistAction { |
54 | pub edit: TextEdit, | 62 | pub edit: TextEdit, |
55 | pub cursor_position: Option<TextSize>, | 63 | pub cursor_position: Option<TextSize>, |
56 | // FIXME: This belongs to `AssistLabel` | ||
57 | pub target: Option<TextRange>, | ||
58 | pub file: AssistFile, | 64 | pub file: AssistFile, |
59 | } | 65 | } |
60 | 66 | ||
@@ -104,7 +110,7 @@ pub fn resolved_assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssi | |||
104 | .flat_map(|it| it.0) | 110 | .flat_map(|it| it.0) |
105 | .map(|it| it.into_resolved().unwrap()) | 111 | .map(|it| it.into_resolved().unwrap()) |
106 | .collect::<Vec<_>>(); | 112 | .collect::<Vec<_>>(); |
107 | a.sort_by_key(|it| it.action.target.map_or(TextSize::from(!0u32), |it| it.len())); | 113 | a.sort_by_key(|it| it.label.target.len()); |
108 | a | 114 | a |
109 | } | 115 | } |
110 | 116 | ||
diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs index 483e11931..dd9026df6 100644 --- a/crates/ra_assists/src/tests.rs +++ b/crates/ra_assists/src/tests.rs | |||
@@ -118,8 +118,7 @@ fn check(assist: Handler, before: &str, expected: ExpectedResult) { | |||
118 | assert_eq_text!(after, &actual); | 118 | assert_eq_text!(after, &actual); |
119 | } | 119 | } |
120 | (Some(assist), ExpectedResult::Target(target)) => { | 120 | (Some(assist), ExpectedResult::Target(target)) => { |
121 | let action = assist.0[0].action.clone().unwrap(); | 121 | let range = assist.0[0].label.target; |
122 | let range = action.target.expect("expected target on action"); | ||
123 | assert_eq_text!(&text_without_caret[range], target); | 122 | assert_eq_text!(&text_without_caret[range], target); |
124 | } | 123 | } |
125 | (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"), | 124 | (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"), |