aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/assist_context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/assist_context.rs')
-rw-r--r--crates/ra_assists/src/assist_context.rs48
1 files changed, 38 insertions, 10 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index 3640bb4d2..3407df856 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -19,7 +19,7 @@ use ra_text_edit::TextEditBuilder;
19 19
20use crate::{ 20use crate::{
21 assist_config::{AssistConfig, SnippetCap}, 21 assist_config::{AssistConfig, SnippetCap},
22 Assist, AssistId, GroupLabel, ResolvedAssist, 22 Assist, AssistId, AssistKind, GroupLabel, ResolvedAssist,
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.
@@ -103,14 +103,26 @@ pub(crate) struct Assists {
103 resolve: bool, 103 resolve: bool,
104 file: FileId, 104 file: FileId,
105 buf: Vec<(Assist, Option<SourceChange>)>, 105 buf: Vec<(Assist, Option<SourceChange>)>,
106 allowed: Option<Vec<AssistKind>>,
106} 107}
107 108
108impl Assists { 109impl Assists {
109 pub(crate) fn new_resolved(ctx: &AssistContext) -> Assists { 110 pub(crate) fn new_resolved(ctx: &AssistContext) -> Assists {
110 Assists { resolve: true, file: ctx.frange.file_id, buf: Vec::new() } 111 Assists {
112 resolve: true,
113 file: ctx.frange.file_id,
114 buf: Vec::new(),
115 allowed: ctx.config.allowed.clone(),
116 }
111 } 117 }
118
112 pub(crate) fn new_unresolved(ctx: &AssistContext) -> Assists { 119 pub(crate) fn new_unresolved(ctx: &AssistContext) -> Assists {
113 Assists { resolve: false, file: ctx.frange.file_id, buf: Vec::new() } 120 Assists {
121 resolve: false,
122 file: ctx.frange.file_id,
123 buf: Vec::new(),
124 allowed: ctx.config.allowed.clone(),
125 }
114 } 126 }
115 127
116 pub(crate) fn finish_unresolved(self) -> Vec<Assist> { 128 pub(crate) fn finish_unresolved(self) -> Vec<Assist> {
@@ -139,9 +151,13 @@ impl Assists {
139 target: TextRange, 151 target: TextRange,
140 f: impl FnOnce(&mut AssistBuilder), 152 f: impl FnOnce(&mut AssistBuilder),
141 ) -> Option<()> { 153 ) -> Option<()> {
154 if !self.is_allowed(&id) {
155 return None;
156 }
142 let label = Assist::new(id, label.into(), None, target); 157 let label = Assist::new(id, label.into(), None, target);
143 self.add_impl(label, f) 158 self.add_impl(label, f)
144 } 159 }
160
145 pub(crate) fn add_group( 161 pub(crate) fn add_group(
146 &mut self, 162 &mut self,
147 group: &GroupLabel, 163 group: &GroupLabel,
@@ -150,9 +166,14 @@ impl Assists {
150 target: TextRange, 166 target: TextRange,
151 f: impl FnOnce(&mut AssistBuilder), 167 f: impl FnOnce(&mut AssistBuilder),
152 ) -> Option<()> { 168 ) -> Option<()> {
169 if !self.is_allowed(&id) {
170 return None;
171 }
172
153 let label = Assist::new(id, label.into(), Some(group.clone()), target); 173 let label = Assist::new(id, label.into(), Some(group.clone()), target);
154 self.add_impl(label, f) 174 self.add_impl(label, f)
155 } 175 }
176
156 fn add_impl(&mut self, label: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> { 177 fn add_impl(&mut self, label: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
157 let source_change = if self.resolve { 178 let source_change = if self.resolve {
158 let mut builder = AssistBuilder::new(self.file); 179 let mut builder = AssistBuilder::new(self.file);
@@ -170,13 +191,20 @@ impl Assists {
170 self.buf.sort_by_key(|(label, _edit)| label.target.len()); 191 self.buf.sort_by_key(|(label, _edit)| label.target.len());
171 self.buf 192 self.buf
172 } 193 }
194
195 fn is_allowed(&self, id: &AssistId) -> bool {
196 match &self.allowed {
197 Some(allowed) => allowed.iter().any(|kind| kind.contains(id.1)),
198 None => true,
199 }
200 }
173} 201}
174 202
175pub(crate) struct AssistBuilder { 203pub(crate) struct AssistBuilder {
176 edit: TextEditBuilder, 204 edit: TextEditBuilder,
177 file_id: FileId, 205 file_id: FileId,
178 is_snippet: bool, 206 is_snippet: bool,
179 edits: Vec<SourceFileEdit>, 207 change: SourceChange,
180} 208}
181 209
182impl AssistBuilder { 210impl AssistBuilder {
@@ -185,7 +213,7 @@ impl AssistBuilder {
185 edit: TextEditBuilder::default(), 213 edit: TextEditBuilder::default(),
186 file_id, 214 file_id,
187 is_snippet: false, 215 is_snippet: false,
188 edits: Vec::new(), 216 change: SourceChange::default(),
189 } 217 }
190 } 218 }
191 219
@@ -197,8 +225,8 @@ impl AssistBuilder {
197 let edit = mem::take(&mut self.edit).finish(); 225 let edit = mem::take(&mut self.edit).finish();
198 if !edit.is_empty() { 226 if !edit.is_empty() {
199 let new_edit = SourceFileEdit { file_id: self.file_id, edit }; 227 let new_edit = SourceFileEdit { file_id: self.file_id, edit };
200 assert!(!self.edits.iter().any(|it| it.file_id == new_edit.file_id)); 228 assert!(!self.change.source_file_edits.iter().any(|it| it.file_id == new_edit.file_id));
201 self.edits.push(new_edit); 229 self.change.source_file_edits.push(new_edit);
202 } 230 }
203 } 231 }
204 232
@@ -265,10 +293,10 @@ impl AssistBuilder {
265 293
266 fn finish(mut self) -> SourceChange { 294 fn finish(mut self) -> SourceChange {
267 self.commit(); 295 self.commit();
268 let mut res: SourceChange = mem::take(&mut self.edits).into(); 296 let mut change = mem::take(&mut self.change);
269 if self.is_snippet { 297 if self.is_snippet {
270 res.is_snippet = true; 298 change.is_snippet = true;
271 } 299 }
272 res 300 change
273 } 301 }
274} 302}