Skip to content

Commit f6e05a7

Browse files
committed
handle replace_with_many and replace_all
1 parent f03f95f commit f6e05a7

File tree

2 files changed

+97
-16
lines changed

2 files changed

+97
-16
lines changed

src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
use std::{
88
num::NonZeroU32,
9+
ops::RangeInclusive,
910
sync::atomic::{AtomicU32, Ordering},
1011
};
1112

@@ -76,6 +77,26 @@ impl SyntaxEditor {
7677
self.changes.push(Change::Replace(old.syntax_element(), Some(new.syntax_element())));
7778
}
7879

80+
pub fn replace_with_many(&mut self, old: impl Element, new: Vec<SyntaxElement>) {
81+
let old = old.syntax_element();
82+
debug_assert!(is_ancestor_or_self_of_element(&old, &self.root));
83+
debug_assert!(
84+
!(matches!(&old, SyntaxElement::Node(node) if node == &self.root) && new.len() > 1),
85+
"cannot replace root node with many elements"
86+
);
87+
self.changes.push(Change::ReplaceWithMany(old.syntax_element(), new));
88+
}
89+
90+
pub fn replace_all(&mut self, range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
91+
if range.start() == range.end() {
92+
self.replace_with_many(range.start(), new);
93+
return;
94+
}
95+
96+
debug_assert!(is_ancestor_or_self_of_element(range.start(), &self.root));
97+
self.changes.push(Change::ReplaceAll(range, new))
98+
}
99+
79100
pub fn finish(self) -> SyntaxEdit {
80101
edit_algo::apply_edits(self)
81102
}
@@ -186,10 +207,17 @@ impl Position {
186207

187208
#[derive(Debug)]
188209
enum Change {
210+
/// Inserts a single element at the specified position.
189211
Insert(Position, SyntaxElement),
212+
/// Inserts many elements in-order at the specified position.
190213
InsertAll(Position, Vec<SyntaxElement>),
191214
/// Represents both a replace single element and a delete element operation.
192215
Replace(SyntaxElement, Option<SyntaxElement>),
216+
/// Replaces a single element with many elements.
217+
ReplaceWithMany(SyntaxElement, Vec<SyntaxElement>),
218+
/// Replaces a range of elements with another list of elements.
219+
/// Range will always have start != end.
220+
ReplaceAll(RangeInclusive<SyntaxElement>, Vec<SyntaxElement>),
193221
}
194222

195223
impl Change {
@@ -202,32 +230,37 @@ impl Change {
202230
),
203231
PositionRepr::After(child) => TextRange::at(child.text_range().end(), 0.into()),
204232
},
205-
Change::Replace(target, _) => target.text_range(),
233+
Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => target.text_range(),
234+
Change::ReplaceAll(range, _) => {
235+
range.start().text_range().cover(range.end().text_range())
236+
}
206237
}
207238
}
208239

209240
fn target_parent(&self) -> SyntaxNode {
210241
match self {
211242
Change::Insert(target, _) | Change::InsertAll(target, _) => target.parent(),
212-
Change::Replace(SyntaxElement::Node(target), _) => {
213-
target.parent().unwrap_or_else(|| target.clone())
214-
}
215-
Change::Replace(SyntaxElement::Token(target), _) => target.parent().unwrap(),
243+
Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => match target {
244+
SyntaxElement::Node(target) => target.parent().unwrap_or_else(|| target.clone()),
245+
SyntaxElement::Token(target) => target.parent().unwrap(),
246+
},
247+
Change::ReplaceAll(target, _) => target.start().parent().unwrap(),
216248
}
217249
}
218250

219251
fn change_kind(&self) -> ChangeKind {
220252
match self {
221253
Change::Insert(_, _) | Change::InsertAll(_, _) => ChangeKind::Insert,
222-
Change::Replace(_, _) => ChangeKind::Replace,
254+
Change::Replace(_, _) | Change::ReplaceWithMany(_, _) => ChangeKind::Replace,
255+
Change::ReplaceAll(_, _) => ChangeKind::ReplaceRange,
223256
}
224257
}
225258
}
226259

227260
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
228261
enum ChangeKind {
229262
Insert,
230-
// TODO: deal with replace spans
263+
ReplaceRange,
231264
Replace,
232265
}
233266

src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
6161
.zip(changes.iter().skip(1))
6262
.filter(|(l, r)| {
6363
// We only care about checking for disjoint replace ranges
64-
l.change_kind() == ChangeKind::Replace && r.change_kind() == ChangeKind::Replace
64+
matches!(
65+
(l.change_kind(), r.change_kind()),
66+
(
67+
ChangeKind::Replace | ChangeKind::ReplaceRange,
68+
ChangeKind::Replace | ChangeKind::ReplaceRange
69+
)
70+
)
6571
})
6672
.all(|(l, r)| {
6773
get_node_depth(l.target_parent()) != get_node_depth(r.target_parent())
@@ -97,6 +103,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
97103
// Pop off any ancestors that aren't applicable
98104
changed_ancestors.drain((index + 1)..);
99105

106+
// FIXME: Resolve changes that depend on a range of elements
100107
let ancestor = &changed_ancestors[index];
101108

102109
dependent_changes.push(DependentChange {
@@ -115,9 +122,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
115122
// Add to changed ancestors, if applicable
116123
match change {
117124
Change::Insert(_, _) | Change::InsertAll(_, _) => {}
118-
Change::Replace(target, _) => {
125+
Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
119126
changed_ancestors.push_back(ChangedAncestor::single(target, change_index))
120127
}
128+
Change::ReplaceAll(range, _) => {
129+
changed_ancestors.push_back(ChangedAncestor::multiple(range, change_index))
130+
}
121131
}
122132
}
123133

@@ -137,9 +147,15 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
137147
}
138148
};
139149
}
140-
Change::Replace(target, _) => {
150+
Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
141151
*target = tree_mutator.make_element_mut(target);
142152
}
153+
Change::ReplaceAll(range, _) => {
154+
let start = tree_mutator.make_element_mut(range.start());
155+
let end = tree_mutator.make_element_mut(range.end());
156+
157+
*range = start..=end;
158+
}
143159
}
144160

145161
// Collect changed elements
@@ -148,6 +164,10 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
148164
Change::InsertAll(_, elements) => changed_elements.extend(elements.iter().cloned()),
149165
Change::Replace(_, Some(element)) => changed_elements.push(element.clone()),
150166
Change::Replace(_, None) => {}
167+
Change::ReplaceWithMany(_, elements) => {
168+
changed_elements.extend(elements.iter().cloned())
169+
}
170+
Change::ReplaceAll(_, elements) => changed_elements.extend(elements.iter().cloned()),
151171
}
152172
}
153173

@@ -160,6 +180,9 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
160180
}
161181
// Silently drop outdated change
162182
Change::Replace(_, None) => continue,
183+
Change::ReplaceAll(_, _) | Change::ReplaceWithMany(_, _) => {
184+
unimplemented!("cannot resolve changes that depend on replacing many elements")
185+
}
163186
};
164187

165188
let upmap_target_node = |target: &SyntaxNode| {
@@ -185,9 +208,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
185208
*child = upmap_target(child);
186209
}
187210
},
188-
Change::Replace(target, _) => {
211+
Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
189212
*target = upmap_target(&target);
190213
}
214+
Change::ReplaceAll(range, _) => {
215+
*range = upmap_target(range.start())..=upmap_target(range.end());
216+
}
191217
}
192218
}
193219

@@ -214,6 +240,16 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
214240
let parent = target.parent().unwrap();
215241
parent.splice_children(target.index()..target.index() + 1, vec![new_target]);
216242
}
243+
Change::ReplaceWithMany(target, elements) => {
244+
let parent = target.parent().unwrap();
245+
parent.splice_children(target.index()..target.index() + 1, elements);
246+
}
247+
Change::ReplaceAll(range, elements) => {
248+
let start = range.start().index();
249+
let end = range.end().index();
250+
let parent = range.start().parent().unwrap();
251+
parent.splice_children(start..end + 1, elements);
252+
}
217253
}
218254
}
219255

@@ -252,7 +288,7 @@ struct ChangedAncestor {
252288

253289
enum ChangedAncestorKind {
254290
Single { node: SyntaxNode },
255-
Range { changed_nodes: RangeInclusive<SyntaxNode>, in_parent: SyntaxNode },
291+
Range { _changed_elements: RangeInclusive<SyntaxElement>, in_parent: SyntaxNode },
256292
}
257293

258294
impl ChangedAncestor {
@@ -267,13 +303,25 @@ impl ChangedAncestor {
267303
Self { kind, change_index }
268304
}
269305

306+
fn multiple(range: &RangeInclusive<SyntaxElement>, change_index: usize) -> Self {
307+
Self {
308+
kind: ChangedAncestorKind::Range {
309+
_changed_elements: range.clone(),
310+
in_parent: range.start().parent().unwrap(),
311+
},
312+
change_index,
313+
}
314+
}
315+
270316
fn affected_range(&self) -> TextRange {
271317
match &self.kind {
272318
ChangedAncestorKind::Single { node } => node.text_range(),
273-
ChangedAncestorKind::Range { changed_nodes, in_parent: _ } => TextRange::new(
274-
changed_nodes.start().text_range().start(),
275-
changed_nodes.end().text_range().end(),
276-
),
319+
ChangedAncestorKind::Range { _changed_elements: changed_nodes, in_parent: _ } => {
320+
TextRange::new(
321+
changed_nodes.start().text_range().start(),
322+
changed_nodes.end().text_range().end(),
323+
)
324+
}
277325
}
278326
}
279327
}

0 commit comments

Comments
 (0)