Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 8104457

Browse files
committed
support insert{_all}
1 parent e4bce98 commit 8104457

File tree

2 files changed

+88
-11
lines changed

2 files changed

+88
-11
lines changed

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ impl SyntaxEditor {
5050
self.annotations.append(&mut other.annotations);
5151
}
5252

53+
pub fn insert(&mut self, position: Position, element: impl Element) {
54+
self.changes.push(Change::Insert(position, element.syntax_element()))
55+
}
56+
57+
pub fn insert_all(&mut self, position: Position, elements: Vec<SyntaxElement>) {
58+
self.changes.push(Change::InsertAll(position, elements))
59+
}
60+
5361
pub fn delete(&mut self, element: impl Element) {
5462
self.changes.push(Change::Replace(element.syntax_element(), None));
5563
}
@@ -117,6 +125,19 @@ pub struct Position {
117125
repr: PositionRepr,
118126
}
119127

128+
impl Position {
129+
pub(crate) fn parent(&self) -> SyntaxNode {
130+
self.place().0
131+
}
132+
133+
pub(crate) fn place(&self) -> (SyntaxNode, usize) {
134+
match &self.repr {
135+
PositionRepr::FirstChild(parent) => (parent.clone(), 0),
136+
PositionRepr::After(child) => (child.parent().unwrap(), child.index() + 1),
137+
}
138+
}
139+
}
140+
120141
#[derive(Debug)]
121142
enum PositionRepr {
122143
FirstChild(SyntaxNode),
@@ -155,25 +176,36 @@ impl Position {
155176

156177
#[derive(Debug)]
157178
enum Change {
179+
Insert(Position, SyntaxElement),
180+
InsertAll(Position, Vec<SyntaxElement>),
158181
/// Represents both a replace single element and a delete element operation.
159182
Replace(SyntaxElement, Option<SyntaxElement>),
160183
}
161184

162185
impl Change {
163186
fn target_range(&self) -> TextRange {
164187
match self {
188+
Change::Insert(target, _) | Change::InsertAll(target, _) => match &target.repr {
189+
PositionRepr::FirstChild(parent) => TextRange::at(
190+
parent.first_child_or_token().unwrap().text_range().start(),
191+
0.into(),
192+
),
193+
PositionRepr::After(child) => TextRange::at(child.text_range().end(), 0.into()),
194+
},
165195
Change::Replace(target, _) => target.text_range(),
166196
}
167197
}
168198

169199
fn target_parent(&self) -> SyntaxNode {
170200
match self {
201+
Change::Insert(target, _) | Change::InsertAll(target, _) => target.parent(),
171202
Change::Replace(target, _) => target.parent().unwrap(),
172203
}
173204
}
174205

175206
fn change_kind(&self) -> ChangeKind {
176207
match self {
208+
Change::Insert(_, _) | Change::InsertAll(_, _) => ChangeKind::Insert,
177209
Change::Replace(_, _) => ChangeKind::Replace,
178210
}
179211
}

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

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use rowan::TextRange;
44
use rustc_hash::{FxHashMap, FxHashSet};
55

66
use crate::{
7-
syntax_editor::{mapping::MissingMapping, Change, ChangeKind},
8-
ted, SyntaxElement, SyntaxNode, SyntaxNodePtr,
7+
syntax_editor::{mapping::MissingMapping, Change, ChangeKind, Position, PositionRepr},
8+
SyntaxElement, SyntaxNode, SyntaxNodePtr,
99
};
1010

1111
use super::{SyntaxEdit, SyntaxEditor};
@@ -94,6 +94,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
9494

9595
// Add to changed ancestors, if applicable
9696
match change {
97+
Change::Insert(_, _) | Change::InsertAll(_, _) => {}
9798
Change::Replace(target, _) => {
9899
changed_ancestors.push_back(ChangedAncestor::single(target, change_index))
99100
}
@@ -106,23 +107,46 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
106107

107108
for index in independent_changes {
108109
match &mut changes[index as usize] {
109-
Change::Replace(target, new_node) => {
110+
Change::Insert(target, _) | Change::InsertAll(target, _) => {
111+
match &mut target.repr {
112+
PositionRepr::FirstChild(parent) => {
113+
*parent = tree_mutator.make_syntax_mut(parent);
114+
}
115+
PositionRepr::After(child) => {
116+
*child = tree_mutator.make_element_mut(child);
117+
}
118+
};
119+
}
120+
Change::Replace(target, _) => {
110121
*target = tree_mutator.make_element_mut(target);
111-
112-
if let Some(new_node) = new_node {
113-
changed_elements.push(new_node.clone());
114-
}
115122
}
116123
}
124+
125+
// Collect changed elements
126+
match &changes[index as usize] {
127+
Change::Insert(_, element) => changed_elements.push(element.clone()),
128+
Change::InsertAll(_, elements) => changed_elements.extend(elements.iter().cloned()),
129+
Change::Replace(_, Some(element)) => changed_elements.push(element.clone()),
130+
Change::Replace(_, None) => {}
131+
}
117132
}
118133

119134
for DependentChange { parent, child } in dependent_changes.into_iter() {
120135
let (input_ancestor, output_ancestor) = match &changes[parent as usize] {
121-
// insert? unreachable
136+
// No change will depend on an insert since changes can only depend on nodes in the root tree
137+
Change::Insert(_, _) | Change::InsertAll(_, _) => unreachable!(),
122138
Change::Replace(target, Some(new_target)) => {
123139
(to_owning_node(target), to_owning_node(new_target))
124140
}
125-
Change::Replace(_, None) => continue, // silently drop outdated change
141+
// Silently drop outdated change
142+
Change::Replace(_, None) => continue,
143+
};
144+
145+
let upmap_target_node = |target: &SyntaxNode| {
146+
match mappings.upmap_child(target, &input_ancestor, &output_ancestor) {
147+
Ok(it) => it,
148+
Err(MissingMapping(current)) => unreachable!("no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"),
149+
}
126150
};
127151

128152
let upmap_target = |target: &SyntaxElement| {
@@ -133,6 +157,14 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
133157
};
134158

135159
match &mut changes[child as usize] {
160+
Change::Insert(target, _) | Change::InsertAll(target, _) => match &mut target.repr {
161+
PositionRepr::FirstChild(parent) => {
162+
*parent = upmap_target_node(parent);
163+
}
164+
PositionRepr::After(child) => {
165+
*child = upmap_target(child);
166+
}
167+
},
136168
Change::Replace(target, _) => {
137169
*target = upmap_target(&target);
138170
}
@@ -142,8 +174,21 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
142174
// Apply changes
143175
for change in changes {
144176
match change {
145-
Change::Replace(target, None) => ted::remove(target),
146-
Change::Replace(target, Some(new_target)) => ted::replace(target, new_target),
177+
Change::Insert(position, element) => {
178+
let (parent, index) = position.place();
179+
parent.splice_children(index..index, vec![element]);
180+
}
181+
Change::InsertAll(position, elements) => {
182+
let (parent, index) = position.place();
183+
parent.splice_children(index..index, elements);
184+
}
185+
Change::Replace(target, None) => {
186+
target.detach();
187+
}
188+
Change::Replace(target, Some(new_target)) => {
189+
let parent = target.parent().unwrap();
190+
parent.splice_children(target.index()..target.index() + 1, vec![new_target]);
191+
}
147192
}
148193
}
149194

0 commit comments

Comments
 (0)