aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src/assist_context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src/assist_context.rs')
-rw-r--r--crates/ide_assists/src/assist_context.rs49
1 files changed, 32 insertions, 17 deletions
diff --git a/crates/ide_assists/src/assist_context.rs b/crates/ide_assists/src/assist_context.rs
index 8714e4978..112939948 100644
--- a/crates/ide_assists/src/assist_context.rs
+++ b/crates/ide_assists/src/assist_context.rs
@@ -19,7 +19,9 @@ use syntax::{
19}; 19};
20use text_edit::{TextEdit, TextEditBuilder}; 20use text_edit::{TextEdit, TextEditBuilder};
21 21
22use crate::{assist_config::AssistConfig, Assist, AssistId, AssistKind, GroupLabel}; 22use crate::{
23 assist_config::AssistConfig, Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel,
24};
23 25
24/// `AssistContext` allows to apply an assist or check if it could be applied. 26/// `AssistContext` allows to apply an assist or check if it could be applied.
25/// 27///
@@ -105,14 +107,14 @@ impl<'a> AssistContext<'a> {
105} 107}
106 108
107pub(crate) struct Assists { 109pub(crate) struct Assists {
108 resolve: bool,
109 file: FileId, 110 file: FileId,
111 resolve: AssistResolveStrategy,
110 buf: Vec<Assist>, 112 buf: Vec<Assist>,
111 allowed: Option<Vec<AssistKind>>, 113 allowed: Option<Vec<AssistKind>>,
112} 114}
113 115
114impl Assists { 116impl Assists {
115 pub(crate) fn new(ctx: &AssistContext, resolve: bool) -> Assists { 117 pub(crate) fn new(ctx: &AssistContext, resolve: AssistResolveStrategy) -> Assists {
116 Assists { 118 Assists {
117 resolve, 119 resolve,
118 file: ctx.frange.file_id, 120 file: ctx.frange.file_id,
@@ -158,7 +160,7 @@ impl Assists {
158 } 160 }
159 161
160 fn add_impl(&mut self, mut assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> { 162 fn add_impl(&mut self, mut assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
161 let source_change = if self.resolve { 163 let source_change = if self.resolve.should_resolve(&assist.id) {
162 let mut builder = AssistBuilder::new(self.file); 164 let mut builder = AssistBuilder::new(self.file);
163 f(&mut builder); 165 f(&mut builder);
164 Some(builder.finish()) 166 Some(builder.finish())
@@ -185,7 +187,29 @@ pub(crate) struct AssistBuilder {
185 source_change: SourceChange, 187 source_change: SourceChange,
186 188
187 /// Maps the original, immutable `SyntaxNode` to a `clone_for_update` twin. 189 /// Maps the original, immutable `SyntaxNode` to a `clone_for_update` twin.
188 mutated_tree: Option<(SyntaxNode, SyntaxNode)>, 190 mutated_tree: Option<TreeMutator>,
191}
192
193pub(crate) struct TreeMutator {
194 immutable: SyntaxNode,
195 mutable_clone: SyntaxNode,
196}
197
198impl TreeMutator {
199 pub(crate) fn new(immutable: &SyntaxNode) -> TreeMutator {
200 let immutable = immutable.ancestors().last().unwrap();
201 let mutable_clone = immutable.clone_for_update();
202 TreeMutator { immutable, mutable_clone }
203 }
204
205 pub(crate) fn make_mut<N: AstNode>(&self, node: &N) -> N {
206 N::cast(self.make_syntax_mut(node.syntax())).unwrap()
207 }
208
209 pub(crate) fn make_syntax_mut(&self, node: &SyntaxNode) -> SyntaxNode {
210 let ptr = SyntaxNodePtr::new(node);
211 ptr.to_node(&self.mutable_clone)
212 }
189} 213}
190 214
191impl AssistBuilder { 215impl AssistBuilder {
@@ -204,8 +228,8 @@ impl AssistBuilder {
204 } 228 }
205 229
206 fn commit(&mut self) { 230 fn commit(&mut self) {
207 if let Some((old, new)) = self.mutated_tree.take() { 231 if let Some(tm) = self.mutated_tree.take() {
208 algo::diff(&old, &new).into_text_edit(&mut self.edit) 232 algo::diff(&tm.immutable, &tm.mutable_clone).into_text_edit(&mut self.edit)
209 } 233 }
210 234
211 let edit = mem::take(&mut self.edit).finish(); 235 let edit = mem::take(&mut self.edit).finish();
@@ -228,16 +252,7 @@ impl AssistBuilder {
228 /// phase, and then get their mutable couterparts using `make_mut` in the 252 /// phase, and then get their mutable couterparts using `make_mut` in the
229 /// mutable state. 253 /// mutable state.
230 pub(crate) fn make_mut(&mut self, node: SyntaxNode) -> SyntaxNode { 254 pub(crate) fn make_mut(&mut self, node: SyntaxNode) -> SyntaxNode {
231 let root = &self 255 self.mutated_tree.get_or_insert_with(|| TreeMutator::new(&node)).make_syntax_mut(&node)
232 .mutated_tree
233 .get_or_insert_with(|| {
234 let immutable = node.ancestors().last().unwrap();
235 let mutable = immutable.clone_for_update();
236 (immutable, mutable)
237 })
238 .1;
239 let ptr = SyntaxNodePtr::new(&&node);
240 ptr.to_node(root)
241 } 256 }
242 257
243 /// Remove specified `range` of text. 258 /// Remove specified `range` of text.