aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/lib.rs')
-rw-r--r--crates/ra_assists/src/lib.rs95
1 files changed, 29 insertions, 66 deletions
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index ab77b46a9..38599d4f1 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -7,15 +7,16 @@
7 7
8mod assist_ctx; 8mod assist_ctx;
9mod marks; 9mod marks;
10#[cfg(test)]
11mod doc_tests;
10 12
11use hir::db::HirDatabase; 13use hir::db::HirDatabase;
12use itertools::Itertools;
13use ra_db::FileRange; 14use ra_db::FileRange;
14use ra_syntax::{TextRange, TextUnit}; 15use ra_syntax::{TextRange, TextUnit};
15use ra_text_edit::TextEdit; 16use ra_text_edit::TextEdit;
16 17
17pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; 18pub(crate) use crate::assist_ctx::{Assist, AssistCtx};
18pub use crate::assists::auto_import::auto_import_text_edit; 19pub use crate::assists::add_import::auto_import_text_edit;
19 20
20/// Unique identifier of the assist, should not be shown to the user 21/// Unique identifier of the assist, should not be shown to the user
21/// directly. 22/// directly.
@@ -36,7 +37,7 @@ pub struct AssistAction {
36 pub target: Option<TextRange>, 37 pub target: Option<TextRange>,
37} 38}
38 39
39/// Return all the assists eapplicable at the given position. 40/// Return all the assists applicable at the given position.
40/// 41///
41/// Assists are returned in the "unresolved" state, that is only labels are 42/// Assists are returned in the "unresolved" state, that is only labels are
42/// returned, without actual edits. 43/// returned, without actual edits.
@@ -49,10 +50,10 @@ where
49 .iter() 50 .iter()
50 .filter_map(|f| f(ctx.clone())) 51 .filter_map(|f| f(ctx.clone()))
51 .map(|a| match a { 52 .map(|a| match a {
52 Assist::Unresolved(labels) => labels, 53 Assist::Unresolved { label } => label,
53 Assist::Resolved(..) => unreachable!(), 54 Assist::Resolved { .. } => unreachable!(),
54 }) 55 })
55 .concat() 56 .collect()
56 }) 57 })
57} 58}
58 59
@@ -71,10 +72,10 @@ where
71 .iter() 72 .iter()
72 .filter_map(|f| f(ctx.clone())) 73 .filter_map(|f| f(ctx.clone()))
73 .map(|a| match a { 74 .map(|a| match a {
74 Assist::Resolved(labels_actions) => labels_actions, 75 Assist::Resolved { label, action } => (label, action),
75 Assist::Unresolved(..) => unreachable!(), 76 Assist::Unresolved { .. } => unreachable!(),
76 }) 77 })
77 .concat(); 78 .collect::<Vec<_>>();
78 a.sort_by(|a, b| match (a.1.target, b.1.target) { 79 a.sort_by(|a, b| match (a.1.target, b.1.target) {
79 (Some(a), Some(b)) => a.len().cmp(&b.len()), 80 (Some(a), Some(b)) => a.len().cmp(&b.len()),
80 (Some(_), None) => Ordering::Less, 81 (Some(_), None) => Ordering::Less,
@@ -95,6 +96,7 @@ mod assists {
95 mod apply_demorgan; 96 mod apply_demorgan;
96 mod flip_comma; 97 mod flip_comma;
97 mod flip_binexpr; 98 mod flip_binexpr;
99 mod flip_trait_bound;
98 mod change_visibility; 100 mod change_visibility;
99 mod fill_match_arms; 101 mod fill_match_arms;
100 mod merge_match_arms; 102 mod merge_match_arms;
@@ -104,7 +106,7 @@ mod assists {
104 mod replace_if_let_with_match; 106 mod replace_if_let_with_match;
105 mod split_import; 107 mod split_import;
106 mod remove_dbg; 108 mod remove_dbg;
107 pub(crate) mod auto_import; 109 pub(crate) mod add_import;
108 mod add_missing_impl_members; 110 mod add_missing_impl_members;
109 mod move_guard; 111 mod move_guard;
110 mod move_bounds; 112 mod move_bounds;
@@ -121,11 +123,12 @@ mod assists {
121 merge_match_arms::merge_match_arms, 123 merge_match_arms::merge_match_arms,
122 flip_comma::flip_comma, 124 flip_comma::flip_comma,
123 flip_binexpr::flip_binexpr, 125 flip_binexpr::flip_binexpr,
126 flip_trait_bound::flip_trait_bound,
124 introduce_variable::introduce_variable, 127 introduce_variable::introduce_variable,
125 replace_if_let_with_match::replace_if_let_with_match, 128 replace_if_let_with_match::replace_if_let_with_match,
126 split_import::split_import, 129 split_import::split_import,
127 remove_dbg::remove_dbg, 130 remove_dbg::remove_dbg,
128 auto_import::auto_import, 131 add_import::add_import,
129 add_missing_impl_members::add_missing_impl_members, 132 add_missing_impl_members::add_missing_impl_members,
130 add_missing_impl_members::add_missing_default_members, 133 add_missing_impl_members::add_missing_default_members,
131 inline_local_variable::inline_local_varialbe, 134 inline_local_variable::inline_local_varialbe,
@@ -155,51 +158,17 @@ mod helpers {
155 before: &str, 158 before: &str,
156 after: &str, 159 after: &str,
157 ) { 160 ) {
158 check_assist_nth_action(assist, before, after, 0)
159 }
160
161 pub(crate) fn check_assist_range(
162 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
163 before: &str,
164 after: &str,
165 ) {
166 check_assist_range_nth_action(assist, before, after, 0)
167 }
168
169 pub(crate) fn check_assist_target(
170 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
171 before: &str,
172 target: &str,
173 ) {
174 check_assist_target_nth_action(assist, before, target, 0)
175 }
176
177 pub(crate) fn check_assist_range_target(
178 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
179 before: &str,
180 target: &str,
181 ) {
182 check_assist_range_target_nth_action(assist, before, target, 0)
183 }
184
185 pub(crate) fn check_assist_nth_action(
186 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
187 before: &str,
188 after: &str,
189 index: usize,
190 ) {
191 let (before_cursor_pos, before) = extract_offset(before); 161 let (before_cursor_pos, before) = extract_offset(before);
192 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 162 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
193 let frange = 163 let frange =
194 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; 164 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
195 let assist = 165 let assist =
196 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); 166 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
197 let labels_actions = match assist { 167 let action = match assist {
198 Assist::Unresolved(_) => unreachable!(), 168 Assist::Unresolved { .. } => unreachable!(),
199 Assist::Resolved(labels_actions) => labels_actions, 169 Assist::Resolved { action, .. } => action,
200 }; 170 };
201 171
202 let (_, action) = labels_actions.get(index).expect("expect assist action at index");
203 let actual = action.edit.apply(&before); 172 let actual = action.edit.apply(&before);
204 let actual_cursor_pos = match action.cursor_position { 173 let actual_cursor_pos = match action.cursor_position {
205 None => action 174 None => action
@@ -212,23 +181,21 @@ mod helpers {
212 assert_eq_text!(after, &actual); 181 assert_eq_text!(after, &actual);
213 } 182 }
214 183
215 pub(crate) fn check_assist_range_nth_action( 184 pub(crate) fn check_assist_range(
216 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 185 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
217 before: &str, 186 before: &str,
218 after: &str, 187 after: &str,
219 index: usize,
220 ) { 188 ) {
221 let (range, before) = extract_range(before); 189 let (range, before) = extract_range(before);
222 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 190 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
223 let frange = FileRange { file_id, range }; 191 let frange = FileRange { file_id, range };
224 let assist = 192 let assist =
225 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); 193 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
226 let labels_actions = match assist { 194 let action = match assist {
227 Assist::Unresolved(_) => unreachable!(), 195 Assist::Unresolved { .. } => unreachable!(),
228 Assist::Resolved(labels_actions) => labels_actions, 196 Assist::Resolved { action, .. } => action,
229 }; 197 };
230 198
231 let (_, action) = labels_actions.get(index).expect("expect assist action at index");
232 let mut actual = action.edit.apply(&before); 199 let mut actual = action.edit.apply(&before);
233 if let Some(pos) = action.cursor_position { 200 if let Some(pos) = action.cursor_position {
234 actual = add_cursor(&actual, pos); 201 actual = add_cursor(&actual, pos);
@@ -236,11 +203,10 @@ mod helpers {
236 assert_eq_text!(after, &actual); 203 assert_eq_text!(after, &actual);
237 } 204 }
238 205
239 pub(crate) fn check_assist_target_nth_action( 206 pub(crate) fn check_assist_target(
240 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 207 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
241 before: &str, 208 before: &str,
242 target: &str, 209 target: &str,
243 index: usize,
244 ) { 210 ) {
245 let (before_cursor_pos, before) = extract_offset(before); 211 let (before_cursor_pos, before) = extract_offset(before);
246 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 212 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
@@ -248,33 +214,30 @@ mod helpers {
248 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; 214 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
249 let assist = 215 let assist =
250 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); 216 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
251 let labels_actions = match assist { 217 let action = match assist {
252 Assist::Unresolved(_) => unreachable!(), 218 Assist::Unresolved { .. } => unreachable!(),
253 Assist::Resolved(labels_actions) => labels_actions, 219 Assist::Resolved { action, .. } => action,
254 }; 220 };
255 221
256 let (_, action) = labels_actions.get(index).expect("expect assist action at index");
257 let range = action.target.expect("expected target on action"); 222 let range = action.target.expect("expected target on action");
258 assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); 223 assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target);
259 } 224 }
260 225
261 pub(crate) fn check_assist_range_target_nth_action( 226 pub(crate) fn check_assist_range_target(
262 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 227 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
263 before: &str, 228 before: &str,
264 target: &str, 229 target: &str,
265 index: usize,
266 ) { 230 ) {
267 let (range, before) = extract_range(before); 231 let (range, before) = extract_range(before);
268 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 232 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
269 let frange = FileRange { file_id, range }; 233 let frange = FileRange { file_id, range };
270 let assist = 234 let assist =
271 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); 235 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
272 let labels_actions = match assist { 236 let action = match assist {
273 Assist::Unresolved(_) => unreachable!(), 237 Assist::Unresolved { .. } => unreachable!(),
274 Assist::Resolved(labels_actions) => labels_actions, 238 Assist::Resolved { action, .. } => action,
275 }; 239 };
276 240
277 let (_, action) = labels_actions.get(index).expect("expect assist action at index");
278 let range = action.target.expect("expected target on action"); 241 let range = action.target.expect("expected target on action");
279 assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); 242 assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target);
280 } 243 }