aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src/assist_context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src/assist_context.rs')
-rw-r--r--crates/assists/src/assist_context.rs64
1 files changed, 22 insertions, 42 deletions
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs
index 69499ea32..4f59d39a9 100644
--- a/crates/assists/src/assist_context.rs
+++ b/crates/assists/src/assist_context.rs
@@ -4,10 +4,10 @@ use std::mem;
4 4
5use algo::find_covering_element; 5use algo::find_covering_element;
6use hir::Semantics; 6use hir::Semantics;
7use ide_db::base_db::{FileId, FileRange}; 7use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange};
8use ide_db::{ 8use 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};
13use syntax::{ 13use syntax::{
@@ -19,7 +19,7 @@ use text_edit::{TextEdit, TextEditBuilder};
19 19
20use crate::{ 20use crate::{
21 assist_config::{AssistConfig, SnippetCap}, 21 assist_config::{AssistConfig, SnippetCap},
22 Assist, AssistId, AssistKind, GroupLabel, ResolvedAssist, 22 Assist, AssistId, AssistKind, GroupLabel,
23}; 23};
24 24
25/// `AssistContext` allows to apply an assist or check if it could be applied. 25/// `AssistContext` allows to apply an assist or check if it could be applied.
@@ -105,46 +105,23 @@ impl<'a> AssistContext<'a> {
105pub(crate) struct Assists { 105pub(crate) struct Assists {
106 resolve: bool, 106 resolve: bool,
107 file: FileId, 107 file: FileId,
108 buf: Vec<(Assist, Option<SourceChange>)>, 108 buf: Vec<Assist>,
109 allowed: Option<Vec<AssistKind>>, 109 allowed: Option<Vec<AssistKind>>,
110} 110}
111 111
112impl Assists { 112impl Assists {
113 pub(crate) fn new_resolved(ctx: &AssistContext) -> Assists { 113 pub(crate) fn new(ctx: &AssistContext, resolve: bool) -> Assists {
114 Assists { 114 Assists {
115 resolve: true, 115 resolve,
116 file: ctx.frange.file_id, 116 file: ctx.frange.file_id,
117 buf: Vec::new(), 117 buf: Vec::new(),
118 allowed: ctx.config.allowed.clone(), 118 allowed: ctx.config.allowed.clone(),
119 } 119 }
120 } 120 }
121 121
122 pub(crate) fn new_unresolved(ctx: &AssistContext) -> Assists { 122 pub(crate) fn finish(mut self) -> Vec<Assist> {
123 Assists { 123 self.buf.sort_by_key(|assist| assist.target.len());
124 resolve: false, 124 self.buf
125 file: ctx.frange.file_id,
126 buf: Vec::new(),
127 allowed: ctx.config.allowed.clone(),
128 }
129 }
130
131 pub(crate) fn finish_unresolved(self) -> Vec<Assist> {
132 assert!(!self.resolve);
133 self.finish()
134 .into_iter()
135 .map(|(label, edit)| {
136 assert!(edit.is_none());
137 label
138 })
139 .collect()
140 }
141
142 pub(crate) fn finish_resolved(self) -> Vec<ResolvedAssist> {
143 assert!(self.resolve);
144 self.finish()
145 .into_iter()
146 .map(|(label, edit)| ResolvedAssist { assist: label, source_change: edit.unwrap() })
147 .collect()
148 } 125 }
149 126
150 pub(crate) fn add( 127 pub(crate) fn add(
@@ -158,7 +135,7 @@ impl Assists {
158 return None; 135 return None;
159 } 136 }
160 let label = Label::new(label.into()); 137 let label = Label::new(label.into());
161 let assist = Assist { id, label, group: None, target }; 138 let assist = Assist { id, label, group: None, target, source_change: None };
162 self.add_impl(assist, f) 139 self.add_impl(assist, f)
163 } 140 }
164 141
@@ -174,11 +151,11 @@ impl Assists {
174 return None; 151 return None;
175 } 152 }
176 let label = Label::new(label.into()); 153 let label = Label::new(label.into());
177 let assist = Assist { id, label, group: Some(group.clone()), target }; 154 let assist = Assist { id, label, group: Some(group.clone()), target, source_change: None };
178 self.add_impl(assist, f) 155 self.add_impl(assist, f)
179 } 156 }
180 157
181 fn add_impl(&mut self, assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> { 158 fn add_impl(&mut self, mut assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
182 let source_change = if self.resolve { 159 let source_change = if self.resolve {
183 let mut builder = AssistBuilder::new(self.file); 160 let mut builder = AssistBuilder::new(self.file);
184 f(&mut builder); 161 f(&mut builder);
@@ -186,16 +163,12 @@ impl Assists {
186 } else { 163 } else {
187 None 164 None
188 }; 165 };
166 assist.source_change = source_change.clone();
189 167
190 self.buf.push((assist, source_change)); 168 self.buf.push(assist);
191 Some(()) 169 Some(())
192 } 170 }
193 171
194 fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> {
195 self.buf.sort_by_key(|(label, _edit)| label.target.len());
196 self.buf
197 }
198
199 fn is_allowed(&self, id: &AssistId) -> bool { 172 fn is_allowed(&self, id: &AssistId) -> bool {
200 match &self.allowed { 173 match &self.allowed {
201 Some(allowed) => allowed.iter().any(|kind| kind.contains(id.1)), 174 Some(allowed) => allowed.iter().any(|kind| kind.contains(id.1)),
@@ -209,6 +182,7 @@ pub(crate) struct AssistBuilder {
209 file_id: FileId, 182 file_id: FileId,
210 is_snippet: bool, 183 is_snippet: bool,
211 source_file_edits: Vec<SourceFileEdit>, 184 source_file_edits: Vec<SourceFileEdit>,
185 file_system_edits: Vec<FileSystemEdit>,
212} 186}
213 187
214impl AssistBuilder { 188impl AssistBuilder {
@@ -218,6 +192,7 @@ impl AssistBuilder {
218 file_id, 192 file_id,
219 is_snippet: false, 193 is_snippet: false,
220 source_file_edits: Vec::default(), 194 source_file_edits: Vec::default(),
195 file_system_edits: Vec::default(),
221 } 196 }
222 } 197 }
223 198
@@ -282,12 +257,17 @@ impl AssistBuilder {
282 algo::diff(&node, &new).into_text_edit(&mut self.edit); 257 algo::diff(&node, &new).into_text_edit(&mut self.edit);
283 } 258 }
284 } 259 }
260 pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into<String>) {
261 let file_system_edit =
262 FileSystemEdit::CreateFile { dst: dst.clone(), initial_contents: content.into() };
263 self.file_system_edits.push(file_system_edit);
264 }
285 265
286 fn finish(mut self) -> SourceChange { 266 fn finish(mut self) -> SourceChange {
287 self.commit(); 267 self.commit();
288 SourceChange { 268 SourceChange {
289 source_file_edits: mem::take(&mut self.source_file_edits), 269 source_file_edits: mem::take(&mut self.source_file_edits),
290 file_system_edits: Default::default(), 270 file_system_edits: mem::take(&mut self.file_system_edits),
291 is_snippet: self.is_snippet, 271 is_snippet: self.is_snippet,
292 } 272 }
293 } 273 }