diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-03-25 07:42:30 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-03-25 07:42:30 +0000 |
commit | 4132fbf3a08c9de2e28a50bc29a2c37a7c1a42fc (patch) | |
tree | 6d4e43864187b101ee956d3fa25cb5346f5d0f1b /crates | |
parent | 8fd18fddea49ff988818a96f5f116ef660a3b6c4 (diff) | |
parent | 4d26bae46db1e4d7a72f9808e7d19ea11fd3bd7d (diff) |
Merge #1041
1041: Add convenience functions to SourceChange for creating single edits r=matklad a=vipentti
Fixes #1018
Co-authored-by: Ville Penttinen <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_ide_api/src/assists.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide_api/src/diagnostics.rs | 27 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 90 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references.rs | 14 | ||||
-rw-r--r-- | crates/ra_ide_api/src/typing.rs | 26 |
5 files changed, 105 insertions, 63 deletions
diff --git a/crates/ra_ide_api/src/assists.rs b/crates/ra_ide_api/src/assists.rs index 3c0475a51..355c0a42a 100644 --- a/crates/ra_ide_api/src/assists.rs +++ b/crates/ra_ide_api/src/assists.rs | |||
@@ -17,14 +17,9 @@ pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> { | |||
17 | let file_id = frange.file_id; | 17 | let file_id = frange.file_id; |
18 | let file_edit = SourceFileEdit { file_id, edit: action.edit }; | 18 | let file_edit = SourceFileEdit { file_id, edit: action.edit }; |
19 | let id = label.id; | 19 | let id = label.id; |
20 | let change = SourceChange { | 20 | let change = SourceChange::source_file_edit(label.label, file_edit).with_cursor_opt( |
21 | label: label.label, | 21 | action.cursor_position.map(|offset| FilePosition { offset, file_id }), |
22 | source_file_edits: vec![file_edit], | 22 | ); |
23 | file_system_edits: vec![], | ||
24 | cursor_position: action | ||
25 | .cursor_position | ||
26 | .map(|offset| FilePosition { offset, file_id }), | ||
27 | }; | ||
28 | Assist { id, change } | 23 | Assist { id, change } |
29 | }) | 24 | }) |
30 | .collect() | 25 | .collect() |
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index b9dc424c6..156f28ca3 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs | |||
@@ -71,12 +71,10 @@ fn check_unnecessary_braces_in_use_statement( | |||
71 | range, | 71 | range, |
72 | message: format!("Unnecessary braces in use statement"), | 72 | message: format!("Unnecessary braces in use statement"), |
73 | severity: Severity::WeakWarning, | 73 | severity: Severity::WeakWarning, |
74 | fix: Some(SourceChange { | 74 | fix: Some(SourceChange::source_file_edit( |
75 | label: "Remove unnecessary braces".to_string(), | 75 | "Remove unnecessary braces", |
76 | source_file_edits: vec![SourceFileEdit { file_id, edit }], | 76 | SourceFileEdit { file_id, edit }, |
77 | file_system_edits: Vec::new(), | 77 | )), |
78 | cursor_position: None, | ||
79 | }), | ||
80 | }); | 78 | }); |
81 | } | 79 | } |
82 | 80 | ||
@@ -119,12 +117,10 @@ fn check_struct_shorthand_initialization( | |||
119 | range: named_field.syntax().range(), | 117 | range: named_field.syntax().range(), |
120 | message: format!("Shorthand struct initialization"), | 118 | message: format!("Shorthand struct initialization"), |
121 | severity: Severity::WeakWarning, | 119 | severity: Severity::WeakWarning, |
122 | fix: Some(SourceChange { | 120 | fix: Some(SourceChange::source_file_edit( |
123 | label: "use struct shorthand initialization".to_string(), | 121 | "use struct shorthand initialization", |
124 | source_file_edits: vec![SourceFileEdit { file_id, edit }], | 122 | SourceFileEdit { file_id, edit }, |
125 | file_system_edits: Vec::new(), | 123 | )), |
126 | cursor_position: None, | ||
127 | }), | ||
128 | }); | 124 | }); |
129 | } | 125 | } |
130 | } | 126 | } |
@@ -144,12 +140,7 @@ fn check_module( | |||
144 | Problem::UnresolvedModule { candidate } => { | 140 | Problem::UnresolvedModule { candidate } => { |
145 | let create_file = | 141 | let create_file = |
146 | FileSystemEdit::CreateFile { source_root, path: candidate.clone() }; | 142 | FileSystemEdit::CreateFile { source_root, path: candidate.clone() }; |
147 | let fix = SourceChange { | 143 | let fix = SourceChange::file_system_edit("create module", create_file); |
148 | label: "create module".to_string(), | ||
149 | source_file_edits: Vec::new(), | ||
150 | file_system_edits: vec![create_file], | ||
151 | cursor_position: None, | ||
152 | }; | ||
153 | Diagnostic { | 144 | Diagnostic { |
154 | range: name_node.range(), | 145 | range: name_node.range(), |
155 | message: "unresolved module".to_string(), | 146 | message: "unresolved module".to_string(), |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 99f18b6b8..8aa3eb088 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -97,6 +97,79 @@ pub struct SourceChange { | |||
97 | pub cursor_position: Option<FilePosition>, | 97 | pub cursor_position: Option<FilePosition>, |
98 | } | 98 | } |
99 | 99 | ||
100 | impl SourceChange { | ||
101 | /// Creates a new SourceChange with the given label | ||
102 | /// from the edits. | ||
103 | pub(crate) fn from_edits<L: Into<String>>( | ||
104 | label: L, | ||
105 | source_file_edits: Vec<SourceFileEdit>, | ||
106 | file_system_edits: Vec<FileSystemEdit>, | ||
107 | ) -> Self { | ||
108 | SourceChange { | ||
109 | label: label.into(), | ||
110 | source_file_edits, | ||
111 | file_system_edits, | ||
112 | cursor_position: None, | ||
113 | } | ||
114 | } | ||
115 | |||
116 | /// Creates a new SourceChange with the given label, | ||
117 | /// containing only the given `SourceFileEdits`. | ||
118 | pub(crate) fn source_file_edits<L: Into<String>>(label: L, edits: Vec<SourceFileEdit>) -> Self { | ||
119 | SourceChange { | ||
120 | label: label.into(), | ||
121 | source_file_edits: edits, | ||
122 | file_system_edits: vec![], | ||
123 | cursor_position: None, | ||
124 | } | ||
125 | } | ||
126 | |||
127 | /// Creates a new SourceChange with the given label, | ||
128 | /// containing only the given `FileSystemEdits`. | ||
129 | pub(crate) fn file_system_edits<L: Into<String>>(label: L, edits: Vec<FileSystemEdit>) -> Self { | ||
130 | SourceChange { | ||
131 | label: label.into(), | ||
132 | source_file_edits: vec![], | ||
133 | file_system_edits: edits, | ||
134 | cursor_position: None, | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /// Creates a new SourceChange with the given label, | ||
139 | /// containing only a single `SourceFileEdit`. | ||
140 | pub(crate) fn source_file_edit<L: Into<String>>(label: L, edit: SourceFileEdit) -> Self { | ||
141 | SourceChange::source_file_edits(label, vec![edit]) | ||
142 | } | ||
143 | |||
144 | /// Creates a new SourceChange with the given label | ||
145 | /// from the given `FileId` and `TextEdit` | ||
146 | pub(crate) fn source_file_edit_from<L: Into<String>>( | ||
147 | label: L, | ||
148 | file_id: FileId, | ||
149 | edit: TextEdit, | ||
150 | ) -> Self { | ||
151 | SourceChange::source_file_edit(label, SourceFileEdit { file_id, edit }) | ||
152 | } | ||
153 | |||
154 | /// Creates a new SourceChange with the given label | ||
155 | /// from the given `FileId` and `TextEdit` | ||
156 | pub(crate) fn file_system_edit<L: Into<String>>(label: L, edit: FileSystemEdit) -> Self { | ||
157 | SourceChange::file_system_edits(label, vec![edit]) | ||
158 | } | ||
159 | |||
160 | /// Sets the cursor position to the given `FilePosition` | ||
161 | pub(crate) fn with_cursor(mut self, cursor_position: FilePosition) -> Self { | ||
162 | self.cursor_position = Some(cursor_position); | ||
163 | self | ||
164 | } | ||
165 | |||
166 | /// Sets the cursor position to the given `FilePosition` | ||
167 | pub(crate) fn with_cursor_opt(mut self, cursor_position: Option<FilePosition>) -> Self { | ||
168 | self.cursor_position = cursor_position; | ||
169 | self | ||
170 | } | ||
171 | } | ||
172 | |||
100 | #[derive(Debug)] | 173 | #[derive(Debug)] |
101 | pub struct SourceFileEdit { | 174 | pub struct SourceFileEdit { |
102 | pub file_id: FileId, | 175 | pub file_id: FileId, |
@@ -285,12 +358,7 @@ impl Analysis { | |||
285 | file_id: frange.file_id, | 358 | file_id: frange.file_id, |
286 | edit: join_lines::join_lines(&file, frange.range), | 359 | edit: join_lines::join_lines(&file, frange.range), |
287 | }; | 360 | }; |
288 | SourceChange { | 361 | SourceChange::source_file_edit("join lines", file_edit) |
289 | label: "join lines".to_string(), | ||
290 | source_file_edits: vec![file_edit], | ||
291 | file_system_edits: vec![], | ||
292 | cursor_position: None, | ||
293 | } | ||
294 | } | 362 | } |
295 | 363 | ||
296 | /// Returns an edit which should be applied when opening a new line, fixing | 364 | /// Returns an edit which should be applied when opening a new line, fixing |
@@ -305,12 +373,10 @@ impl Analysis { | |||
305 | pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> { | 373 | pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> { |
306 | let file = self.db.parse(position.file_id); | 374 | let file = self.db.parse(position.file_id); |
307 | let edit = typing::on_eq_typed(&file, position.offset)?; | 375 | let edit = typing::on_eq_typed(&file, position.offset)?; |
308 | Some(SourceChange { | 376 | Some(SourceChange::source_file_edit( |
309 | label: "add semicolon".to_string(), | 377 | "add semicolon", |
310 | source_file_edits: vec![SourceFileEdit { edit, file_id: position.file_id }], | 378 | SourceFileEdit { edit, file_id: position.file_id }, |
311 | file_system_edits: vec![], | 379 | )) |
312 | cursor_position: None, | ||
313 | }) | ||
314 | } | 380 | } |
315 | 381 | ||
316 | /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately. | 382 | /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately. |
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index b7784e577..22741445a 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs | |||
@@ -187,12 +187,7 @@ fn rename_mod( | |||
187 | }; | 187 | }; |
188 | source_file_edits.push(edit); | 188 | source_file_edits.push(edit); |
189 | 189 | ||
190 | Some(SourceChange { | 190 | Some(SourceChange::from_edits("rename", source_file_edits, file_system_edits)) |
191 | label: "rename".to_string(), | ||
192 | source_file_edits, | ||
193 | file_system_edits, | ||
194 | cursor_position: None, | ||
195 | }) | ||
196 | } | 191 | } |
197 | 192 | ||
198 | fn rename_reference( | 193 | fn rename_reference( |
@@ -211,12 +206,7 @@ fn rename_reference( | |||
211 | return None; | 206 | return None; |
212 | } | 207 | } |
213 | 208 | ||
214 | Some(SourceChange { | 209 | Some(SourceChange::source_file_edits("rename", edit)) |
215 | label: "rename".to_string(), | ||
216 | source_file_edits: edit, | ||
217 | file_system_edits: Vec::new(), | ||
218 | cursor_position: None, | ||
219 | }) | ||
220 | } | 210 | } |
221 | 211 | ||
222 | #[cfg(test)] | 212 | #[cfg(test)] |
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs index 94b228466..501d44dbb 100644 --- a/crates/ra_ide_api/src/typing.rs +++ b/crates/ra_ide_api/src/typing.rs | |||
@@ -31,12 +31,14 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour | |||
31 | let cursor_position = position.offset + TextUnit::of_str(&inserted); | 31 | let cursor_position = position.offset + TextUnit::of_str(&inserted); |
32 | let mut edit = TextEditBuilder::default(); | 32 | let mut edit = TextEditBuilder::default(); |
33 | edit.insert(position.offset, inserted); | 33 | edit.insert(position.offset, inserted); |
34 | Some(SourceChange { | 34 | |
35 | label: "on enter".to_string(), | 35 | Some( |
36 | source_file_edits: vec![SourceFileEdit { edit: edit.finish(), file_id: position.file_id }], | 36 | SourceChange::source_file_edit( |
37 | file_system_edits: vec![], | 37 | "on enter", |
38 | cursor_position: Some(FilePosition { offset: cursor_position, file_id: position.file_id }), | 38 | SourceFileEdit { edit: edit.finish(), file_id: position.file_id }, |
39 | }) | 39 | ) |
40 | .with_cursor(FilePosition { offset: cursor_position, file_id: position.file_id }), | ||
41 | ) | ||
40 | } | 42 | } |
41 | 43 | ||
42 | fn node_indent<'a>(file: &'a SourceFile, node: &SyntaxNode) -> Option<&'a str> { | 44 | fn node_indent<'a>(file: &'a SourceFile, node: &SyntaxNode) -> Option<&'a str> { |
@@ -110,16 +112,14 @@ pub(crate) fn on_dot_typed(db: &RootDatabase, position: FilePosition) -> Option< | |||
110 | TextRange::from_to(position.offset - current_indent_len, position.offset), | 112 | TextRange::from_to(position.offset - current_indent_len, position.offset), |
111 | target_indent.into(), | 113 | target_indent.into(), |
112 | ); | 114 | ); |
113 | let res = SourceChange { | 115 | |
114 | label: "reindent dot".to_string(), | 116 | let res = SourceChange::source_file_edit_from("reindent dot", position.file_id, edit.finish()) |
115 | source_file_edits: vec![SourceFileEdit { edit: edit.finish(), file_id: position.file_id }], | 117 | .with_cursor(FilePosition { |
116 | file_system_edits: vec![], | ||
117 | cursor_position: Some(FilePosition { | ||
118 | offset: position.offset + target_indent_len - current_indent_len | 118 | offset: position.offset + target_indent_len - current_indent_len |
119 | + TextUnit::of_char('.'), | 119 | + TextUnit::of_char('.'), |
120 | file_id: position.file_id, | 120 | file_id: position.file_id, |
121 | }), | 121 | }); |
122 | }; | 122 | |
123 | Some(res) | 123 | Some(res) |
124 | } | 124 | } |
125 | 125 | ||