Unnamed repository; edit this file 'description' to name the repository.
handle merging two syntax editors together
DropDemBits 2024-09-02
parent 883e429 · commit db64919
-rw-r--r--crates/syntax/src/syntax_editor.rs15
-rw-r--r--crates/syntax/src/syntax_editor/mapping.rs38
2 files changed, 39 insertions, 14 deletions
diff --git a/crates/syntax/src/syntax_editor.rs b/crates/syntax/src/syntax_editor.rs
index 240bba7b48..42373eba82 100644
--- a/crates/syntax/src/syntax_editor.rs
+++ b/crates/syntax/src/syntax_editor.rs
@@ -37,8 +37,17 @@ impl SyntaxEditor {
self.annotations.push((element.syntax_element(), annotation))
}
- pub fn combine(&mut self, other: SyntaxEditor) {
- todo!()
+ pub fn merge(&mut self, mut other: SyntaxEditor) {
+ debug_assert!(
+ self.root == other.root || other.root.ancestors().any(|node| node == self.root),
+ "{:?} is not in the same tree as {:?}",
+ other.root,
+ self.root
+ );
+
+ self.changes.append(&mut other.changes);
+ self.mappings.merge(other.mappings);
+ self.annotations.append(&mut other.annotations);
}
pub fn delete(&mut self, element: impl Element) {
@@ -290,7 +299,7 @@ mod tests {
}
#[test]
- fn it() {
+ fn basic_usage() {
let root = make::match_arm(
[make::wildcard_pat().into()],
None,
diff --git a/crates/syntax/src/syntax_editor/mapping.rs b/crates/syntax/src/syntax_editor/mapping.rs
index 11c7b395b3..8a79f7e186 100644
--- a/crates/syntax/src/syntax_editor/mapping.rs
+++ b/crates/syntax/src/syntax_editor/mapping.rs
@@ -14,7 +14,7 @@ pub struct SyntaxMapping {
// mappings -> parents
entry_parents: Vec<SyntaxNode>,
- node_mappings: FxHashMap<SyntaxNode, (u32, u32)>,
+ node_mappings: FxHashMap<SyntaxNode, MappingEntry>,
}
impl SyntaxMapping {
@@ -80,11 +80,10 @@ impl SyntaxMapping {
return None;
}
- if let Some(next) = self.upmap_node(&parent) {
- Some((parent.index(), next))
- } else {
- Some((parent.index(), parent))
- }
+ Some((parent.index(), match self.upmap_node(&parent) {
+ Some(next) => next,
+ None => parent
+ }))
}).map(|(i, _)| i).collect::<Vec<_>>()
} else {
vec![]
@@ -100,7 +99,7 @@ impl SyntaxMapping {
.children_with_tokens()
.nth(index)
.and_then(|it| it.into_node())
- .expect("yep");
+ .expect("equivalent ancestor node should be present in target tree");
}
debug_assert_eq!(child.kind(), target.kind());
@@ -109,7 +108,7 @@ impl SyntaxMapping {
}
pub fn upmap_node(&self, input: &SyntaxNode) -> Option<SyntaxNode> {
- let (parent, child_slot) = self.node_mappings.get(input)?;
+ let MappingEntry { parent, child_slot } = self.node_mappings.get(input)?;
let output = self.entry_parents[*parent as usize]
.children_with_tokens()
@@ -121,14 +120,25 @@ impl SyntaxMapping {
Some(output)
}
+ pub fn merge(&mut self, mut other: SyntaxMapping) {
+ // Remap other's entry parents to be after the current list of entry parents
+ let remap_base: u32 = self.entry_parents.len().try_into().unwrap();
+
+ self.entry_parents.append(&mut other.entry_parents);
+ self.node_mappings.extend(other.node_mappings.into_iter().map(|(node, entry)| {
+ (node, MappingEntry { parent: entry.parent + remap_base, ..entry })
+ }));
+ }
+
fn add_mapping(&mut self, syntax_mapping: SyntaxMappingBuilder) {
let SyntaxMappingBuilder { parent_node, node_mappings } = syntax_mapping;
- let parent_entry: u32 = self.entry_parents.len() as u32;
+ let parent_entry: u32 = self.entry_parents.len().try_into().unwrap();
self.entry_parents.push(parent_node);
- let node_entries =
- node_mappings.into_iter().map(|(node, slot)| (node, (parent_entry, slot)));
+ let node_entries = node_mappings
+ .into_iter()
+ .map(|(node, slot)| (node, MappingEntry { parent: parent_entry, child_slot: slot }));
self.node_mappings.extend(node_entries);
}
@@ -172,3 +182,9 @@ impl SyntaxMappingBuilder {
editor.mappings.add_mapping(self);
}
}
+
+#[derive(Debug, Clone, Copy)]
+struct MappingEntry {
+ parent: u32,
+ child_slot: u32,
+}