diff options
-rw-r--r-- | crates/assists/src/assist_context.rs | 14 | ||||
-rw-r--r-- | crates/assists/src/tests.rs | 60 |
2 files changed, 59 insertions, 15 deletions
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs index 69499ea32..cd22cf17d 100644 --- a/crates/assists/src/assist_context.rs +++ b/crates/assists/src/assist_context.rs | |||
@@ -4,10 +4,10 @@ use std::mem; | |||
4 | 4 | ||
5 | use algo::find_covering_element; | 5 | use algo::find_covering_element; |
6 | use hir::Semantics; | 6 | use hir::Semantics; |
7 | use ide_db::base_db::{FileId, FileRange}; | 7 | use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange}; |
8 | use ide_db::{ | 8 | use ide_db::{ |
9 | label::Label, | 9 | label::Label, |
10 | source_change::{SourceChange, SourceFileEdit}, | 10 | source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, |
11 | RootDatabase, | 11 | RootDatabase, |
12 | }; | 12 | }; |
13 | use syntax::{ | 13 | use syntax::{ |
@@ -209,6 +209,7 @@ pub(crate) struct AssistBuilder { | |||
209 | file_id: FileId, | 209 | file_id: FileId, |
210 | is_snippet: bool, | 210 | is_snippet: bool, |
211 | source_file_edits: Vec<SourceFileEdit>, | 211 | source_file_edits: Vec<SourceFileEdit>, |
212 | file_system_edits: Vec<FileSystemEdit>, | ||
212 | } | 213 | } |
213 | 214 | ||
214 | impl AssistBuilder { | 215 | impl AssistBuilder { |
@@ -218,6 +219,7 @@ impl AssistBuilder { | |||
218 | file_id, | 219 | file_id, |
219 | is_snippet: false, | 220 | is_snippet: false, |
220 | source_file_edits: Vec::default(), | 221 | source_file_edits: Vec::default(), |
222 | file_system_edits: Vec::default(), | ||
221 | } | 223 | } |
222 | } | 224 | } |
223 | 225 | ||
@@ -282,12 +284,18 @@ impl AssistBuilder { | |||
282 | algo::diff(&node, &new).into_text_edit(&mut self.edit); | 284 | algo::diff(&node, &new).into_text_edit(&mut self.edit); |
283 | } | 285 | } |
284 | } | 286 | } |
287 | pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into<String>) { | ||
288 | let file_system_edit = FileSystemEdit::CreateFile { dst: dst.clone() }; | ||
289 | self.file_system_edits.push(file_system_edit); | ||
290 | self.edit_file(dst.anchor); | ||
291 | self.insert(TextSize::from(0), content) | ||
292 | } | ||
285 | 293 | ||
286 | fn finish(mut self) -> SourceChange { | 294 | fn finish(mut self) -> SourceChange { |
287 | self.commit(); | 295 | self.commit(); |
288 | SourceChange { | 296 | SourceChange { |
289 | source_file_edits: mem::take(&mut self.source_file_edits), | 297 | source_file_edits: mem::take(&mut self.source_file_edits), |
290 | file_system_edits: Default::default(), | 298 | file_system_edits: mem::take(&mut self.file_system_edits), |
291 | is_snippet: self.is_snippet, | 299 | is_snippet: self.is_snippet, |
292 | } | 300 | } |
293 | } | 301 | } |
diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs index 709a34d03..9002040ce 100644 --- a/crates/assists/src/tests.rs +++ b/crates/assists/src/tests.rs | |||
@@ -2,6 +2,7 @@ mod generated; | |||
2 | 2 | ||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; | 4 | use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; |
5 | use ide_db::source_change::FileSystemEdit; | ||
5 | use ide_db::RootDatabase; | 6 | use ide_db::RootDatabase; |
6 | use syntax::TextRange; | 7 | use syntax::TextRange; |
7 | use test_utils::{assert_eq_text, extract_offset, extract_range}; | 8 | use test_utils::{assert_eq_text, extract_offset, extract_range}; |
@@ -47,7 +48,7 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) { | |||
47 | let before = db.file_text(file_id).to_string(); | 48 | let before = db.file_text(file_id).to_string(); |
48 | let frange = FileRange { file_id, range: selection.into() }; | 49 | let frange = FileRange { file_id, range: selection.into() }; |
49 | 50 | ||
50 | let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange) | 51 | let assist = Assist::resolved(&db, &AssistConfig::default(), frange) |
51 | .into_iter() | 52 | .into_iter() |
52 | .find(|assist| assist.assist.id.0 == assist_id) | 53 | .find(|assist| assist.assist.id.0 == assist_id) |
53 | .unwrap_or_else(|| { | 54 | .unwrap_or_else(|| { |
@@ -63,9 +64,12 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) { | |||
63 | }); | 64 | }); |
64 | 65 | ||
65 | let actual = { | 66 | let actual = { |
66 | let change = assist.source_change.source_file_edits.pop().unwrap(); | ||
67 | let mut actual = before; | 67 | let mut actual = before; |
68 | change.edit.apply(&mut actual); | 68 | for source_file_edit in assist.source_change.source_file_edits { |
69 | if source_file_edit.file_id == file_id { | ||
70 | source_file_edit.edit.apply(&mut actual) | ||
71 | } | ||
72 | } | ||
69 | actual | 73 | actual |
70 | }; | 74 | }; |
71 | assert_eq_text!(&after, &actual); | 75 | assert_eq_text!(&after, &actual); |
@@ -99,20 +103,52 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: | |||
99 | (Some(assist), ExpectedResult::After(after)) => { | 103 | (Some(assist), ExpectedResult::After(after)) => { |
100 | let mut source_change = assist.source_change; | 104 | let mut source_change = assist.source_change; |
101 | assert!(!source_change.source_file_edits.is_empty()); | 105 | assert!(!source_change.source_file_edits.is_empty()); |
102 | let skip_header = source_change.source_file_edits.len() == 1; | 106 | let skip_header = source_change.source_file_edits.len() == 1 |
107 | && source_change.file_system_edits.len() == 0; | ||
103 | source_change.source_file_edits.sort_by_key(|it| it.file_id); | 108 | source_change.source_file_edits.sort_by_key(|it| it.file_id); |
104 | 109 | ||
110 | let mut created_file_ids = Vec::new(); | ||
105 | let mut buf = String::new(); | 111 | let mut buf = String::new(); |
112 | for file_system_edit in source_change.file_system_edits.clone() { | ||
113 | match file_system_edit { | ||
114 | FileSystemEdit::CreateFile { dst } => { | ||
115 | created_file_ids.push(dst.anchor); | ||
116 | } | ||
117 | _ => (), | ||
118 | } | ||
119 | } | ||
120 | |||
106 | for source_file_edit in source_change.source_file_edits { | 121 | for source_file_edit in source_change.source_file_edits { |
107 | let mut text = db.file_text(source_file_edit.file_id).as_ref().to_owned(); | 122 | if created_file_ids.contains(&source_file_edit.file_id) { |
108 | source_file_edit.edit.apply(&mut text); | 123 | let target_dst = source_change |
109 | if !skip_header { | 124 | .file_system_edits |
110 | let sr = db.file_source_root(source_file_edit.file_id); | 125 | .iter() |
111 | let sr = db.source_root(sr); | 126 | .find_map(|f| match f { |
112 | let path = sr.path_for_file(&source_file_edit.file_id).unwrap(); | 127 | FileSystemEdit::CreateFile { dst } => { |
113 | format_to!(buf, "//- {}\n", path) | 128 | if dst.anchor == source_file_edit.file_id { |
129 | Some(&dst.path) | ||
130 | } else { | ||
131 | None | ||
132 | } | ||
133 | } | ||
134 | _ => None, | ||
135 | }) | ||
136 | .unwrap(); | ||
137 | format_to!(buf, "//- {}\n", target_dst); | ||
138 | let mut text = String::new(); | ||
139 | source_file_edit.edit.apply(&mut text); | ||
140 | buf.push_str(&text); | ||
141 | } else { | ||
142 | let mut text = db.file_text(source_file_edit.file_id).as_ref().to_owned(); | ||
143 | source_file_edit.edit.apply(&mut text); | ||
144 | if !skip_header { | ||
145 | let sr = db.file_source_root(source_file_edit.file_id); | ||
146 | let sr = db.source_root(sr); | ||
147 | let path = sr.path_for_file(&source_file_edit.file_id).unwrap(); | ||
148 | format_to!(buf, "//- {}\n", path) | ||
149 | } | ||
150 | buf.push_str(&text); | ||
114 | } | 151 | } |
115 | buf.push_str(&text); | ||
116 | } | 152 | } |
117 | 153 | ||
118 | assert_eq_text!(after, &buf); | 154 | assert_eq_text!(after, &buf); |