diff options
author | Aleksey Kladov <[email protected]> | 2020-02-09 14:32:53 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-02-09 15:03:54 +0000 |
commit | 9769c5140c9c406a4cc880e698593a6c4bcc6826 (patch) | |
tree | bb0bf39dee21d5720e5f1070b09805dfbc120cd9 /crates/ra_assists/src/lib.rs | |
parent | fb99831cb044e5fbf171bdd950a7486a01ce0d51 (diff) |
Simplify Assists interface
Instead of building a physical tree structure, just "tag" related
assists with the same group
Diffstat (limited to 'crates/ra_assists/src/lib.rs')
-rw-r--r-- | crates/ra_assists/src/lib.rs | 64 |
1 files changed, 15 insertions, 49 deletions
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index f79189ae8..828a8e9e8 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -12,9 +12,6 @@ mod doc_tests; | |||
12 | mod utils; | 12 | mod utils; |
13 | pub mod ast_transform; | 13 | pub mod ast_transform; |
14 | 14 | ||
15 | use std::cmp::Ordering; | ||
16 | |||
17 | use either::Either; | ||
18 | use ra_db::FileRange; | 15 | use ra_db::FileRange; |
19 | use ra_ide_db::RootDatabase; | 16 | use ra_ide_db::RootDatabase; |
20 | use ra_syntax::{TextRange, TextUnit}; | 17 | use ra_syntax::{TextRange, TextUnit}; |
@@ -35,6 +32,9 @@ pub struct AssistLabel { | |||
35 | pub id: AssistId, | 32 | pub id: AssistId, |
36 | } | 33 | } |
37 | 34 | ||
35 | #[derive(Clone, Debug)] | ||
36 | pub struct GroupLabel(pub String); | ||
37 | |||
38 | impl AssistLabel { | 38 | impl AssistLabel { |
39 | pub(crate) fn new(label: String, id: AssistId) -> AssistLabel { | 39 | pub(crate) fn new(label: String, id: AssistId) -> AssistLabel { |
40 | // FIXME: make fields private, so that this invariant can't be broken | 40 | // FIXME: make fields private, so that this invariant can't be broken |
@@ -45,7 +45,6 @@ impl AssistLabel { | |||
45 | 45 | ||
46 | #[derive(Debug, Clone)] | 46 | #[derive(Debug, Clone)] |
47 | pub struct AssistAction { | 47 | pub struct AssistAction { |
48 | pub label: Option<String>, | ||
49 | pub edit: TextEdit, | 48 | pub edit: TextEdit, |
50 | pub cursor_position: Option<TextUnit>, | 49 | pub cursor_position: Option<TextUnit>, |
51 | // FIXME: This belongs to `AssistLabel` | 50 | // FIXME: This belongs to `AssistLabel` |
@@ -55,16 +54,8 @@ pub struct AssistAction { | |||
55 | #[derive(Debug, Clone)] | 54 | #[derive(Debug, Clone)] |
56 | pub struct ResolvedAssist { | 55 | pub struct ResolvedAssist { |
57 | pub label: AssistLabel, | 56 | pub label: AssistLabel, |
58 | pub action_data: Either<AssistAction, Vec<AssistAction>>, | 57 | pub group_label: Option<GroupLabel>, |
59 | } | 58 | pub action: AssistAction, |
60 | |||
61 | impl ResolvedAssist { | ||
62 | pub fn get_first_action(&self) -> AssistAction { | ||
63 | match &self.action_data { | ||
64 | Either::Left(action) => action.clone(), | ||
65 | Either::Right(actions) => actions[0].clone(), | ||
66 | } | ||
67 | } | ||
68 | } | 59 | } |
69 | 60 | ||
70 | /// Return all the assists applicable at the given position. | 61 | /// Return all the assists applicable at the given position. |
@@ -76,10 +67,8 @@ pub fn unresolved_assists(db: &RootDatabase, range: FileRange) -> Vec<AssistLabe | |||
76 | handlers::all() | 67 | handlers::all() |
77 | .iter() | 68 | .iter() |
78 | .filter_map(|f| f(ctx.clone())) | 69 | .filter_map(|f| f(ctx.clone())) |
79 | .map(|a| match a { | 70 | .flat_map(|it| it.0) |
80 | Assist::Unresolved { label } => label, | 71 | .map(|a| a.label) |
81 | Assist::Resolved { .. } => unreachable!(), | ||
82 | }) | ||
83 | .collect() | 72 | .collect() |
84 | } | 73 | } |
85 | 74 | ||
@@ -92,24 +81,13 @@ pub fn resolved_assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssi | |||
92 | let mut a = handlers::all() | 81 | let mut a = handlers::all() |
93 | .iter() | 82 | .iter() |
94 | .filter_map(|f| f(ctx.clone())) | 83 | .filter_map(|f| f(ctx.clone())) |
95 | .map(|a| match a { | 84 | .flat_map(|it| it.0) |
96 | Assist::Resolved { assist } => assist, | 85 | .map(|it| it.into_resolved().unwrap()) |
97 | Assist::Unresolved { .. } => unreachable!(), | ||
98 | }) | ||
99 | .collect::<Vec<_>>(); | 86 | .collect::<Vec<_>>(); |
100 | sort_assists(&mut a); | 87 | a.sort_by_key(|it| it.action.target.map_or(TextUnit::from(!0u32), |it| it.len())); |
101 | a | 88 | a |
102 | } | 89 | } |
103 | 90 | ||
104 | fn sort_assists(assists: &mut [ResolvedAssist]) { | ||
105 | assists.sort_by(|a, b| match (a.get_first_action().target, b.get_first_action().target) { | ||
106 | (Some(a), Some(b)) => a.len().cmp(&b.len()), | ||
107 | (Some(_), None) => Ordering::Less, | ||
108 | (None, Some(_)) => Ordering::Greater, | ||
109 | (None, None) => Ordering::Equal, | ||
110 | }); | ||
111 | } | ||
112 | |||
113 | mod handlers { | 91 | mod handlers { |
114 | use crate::AssistHandler; | 92 | use crate::AssistHandler; |
115 | 93 | ||
@@ -184,7 +162,7 @@ mod helpers { | |||
184 | use ra_syntax::TextRange; | 162 | use ra_syntax::TextRange; |
185 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; | 163 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; |
186 | 164 | ||
187 | use crate::{Assist, AssistCtx, AssistHandler}; | 165 | use crate::{AssistCtx, AssistHandler}; |
188 | 166 | ||
189 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { | 167 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { |
190 | let (mut db, file_id) = RootDatabase::with_single_file(text); | 168 | let (mut db, file_id) = RootDatabase::with_single_file(text); |
@@ -202,10 +180,7 @@ mod helpers { | |||
202 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | 180 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; |
203 | let assist = | 181 | let assist = |
204 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | 182 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); |
205 | let action = match assist { | 183 | let action = assist.0[0].action.clone().unwrap(); |
206 | Assist::Unresolved { .. } => unreachable!(), | ||
207 | Assist::Resolved { assist } => assist.get_first_action(), | ||
208 | }; | ||
209 | 184 | ||
210 | let actual = action.edit.apply(&before); | 185 | let actual = action.edit.apply(&before); |
211 | let actual_cursor_pos = match action.cursor_position { | 186 | let actual_cursor_pos = match action.cursor_position { |
@@ -225,10 +200,7 @@ mod helpers { | |||
225 | let frange = FileRange { file_id, range }; | 200 | let frange = FileRange { file_id, range }; |
226 | let assist = | 201 | let assist = |
227 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | 202 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); |
228 | let action = match assist { | 203 | let action = assist.0[0].action.clone().unwrap(); |
229 | Assist::Unresolved { .. } => unreachable!(), | ||
230 | Assist::Resolved { assist } => assist.get_first_action(), | ||
231 | }; | ||
232 | 204 | ||
233 | let mut actual = action.edit.apply(&before); | 205 | let mut actual = action.edit.apply(&before); |
234 | if let Some(pos) = action.cursor_position { | 206 | if let Some(pos) = action.cursor_position { |
@@ -244,10 +216,7 @@ mod helpers { | |||
244 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | 216 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; |
245 | let assist = | 217 | let assist = |
246 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | 218 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); |
247 | let action = match assist { | 219 | let action = assist.0[0].action.clone().unwrap(); |
248 | Assist::Unresolved { .. } => unreachable!(), | ||
249 | Assist::Resolved { assist } => assist.get_first_action(), | ||
250 | }; | ||
251 | 220 | ||
252 | let range = action.target.expect("expected target on action"); | 221 | let range = action.target.expect("expected target on action"); |
253 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | 222 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); |
@@ -259,10 +228,7 @@ mod helpers { | |||
259 | let frange = FileRange { file_id, range }; | 228 | let frange = FileRange { file_id, range }; |
260 | let assist = | 229 | let assist = |
261 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | 230 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); |
262 | let action = match assist { | 231 | let action = assist.0[0].action.clone().unwrap(); |
263 | Assist::Unresolved { .. } => unreachable!(), | ||
264 | Assist::Resolved { assist } => assist.get_first_action(), | ||
265 | }; | ||
266 | 232 | ||
267 | let range = action.target.expect("expected target on action"); | 233 | let range = action.target.expect("expected target on action"); |
268 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | 234 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); |