handle merging two syntax editors together

This commit is contained in:
DropDemBits 2024-09-02 00:01:24 -04:00
parent 883e429179
commit db649195e9
No known key found for this signature in database
GPG key ID: 7FE02A6C1EDFA075
2 changed files with 39 additions and 14 deletions

View file

@ -37,8 +37,17 @@ impl SyntaxEditor {
self.annotations.push((element.syntax_element(), annotation)) self.annotations.push((element.syntax_element(), annotation))
} }
pub fn combine(&mut self, other: SyntaxEditor) { pub fn merge(&mut self, mut other: SyntaxEditor) {
todo!() 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) { pub fn delete(&mut self, element: impl Element) {
@ -290,7 +299,7 @@ mod tests {
} }
#[test] #[test]
fn it() { fn basic_usage() {
let root = make::match_arm( let root = make::match_arm(
[make::wildcard_pat().into()], [make::wildcard_pat().into()],
None, None,

View file

@ -14,7 +14,7 @@ pub struct SyntaxMapping {
// mappings -> parents // mappings -> parents
entry_parents: Vec<SyntaxNode>, entry_parents: Vec<SyntaxNode>,
node_mappings: FxHashMap<SyntaxNode, (u32, u32)>, node_mappings: FxHashMap<SyntaxNode, MappingEntry>,
} }
impl SyntaxMapping { impl SyntaxMapping {
@ -80,11 +80,10 @@ impl SyntaxMapping {
return None; return None;
} }
if let Some(next) = self.upmap_node(&parent) { Some((parent.index(), match self.upmap_node(&parent) {
Some((parent.index(), next)) Some(next) => next,
} else { None => parent
Some((parent.index(), parent)) }))
}
}).map(|(i, _)| i).collect::<Vec<_>>() }).map(|(i, _)| i).collect::<Vec<_>>()
} else { } else {
vec![] vec![]
@ -100,7 +99,7 @@ impl SyntaxMapping {
.children_with_tokens() .children_with_tokens()
.nth(index) .nth(index)
.and_then(|it| it.into_node()) .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()); debug_assert_eq!(child.kind(), target.kind());
@ -109,7 +108,7 @@ impl SyntaxMapping {
} }
pub fn upmap_node(&self, input: &SyntaxNode) -> Option<SyntaxNode> { 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] let output = self.entry_parents[*parent as usize]
.children_with_tokens() .children_with_tokens()
@ -121,14 +120,25 @@ impl SyntaxMapping {
Some(output) 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) { fn add_mapping(&mut self, syntax_mapping: SyntaxMappingBuilder) {
let SyntaxMappingBuilder { parent_node, node_mappings } = syntax_mapping; 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); self.entry_parents.push(parent_node);
let node_entries = let node_entries = node_mappings
node_mappings.into_iter().map(|(node, slot)| (node, (parent_entry, slot))); .into_iter()
.map(|(node, slot)| (node, MappingEntry { parent: parent_entry, child_slot: slot }));
self.node_mappings.extend(node_entries); self.node_mappings.extend(node_entries);
} }
@ -172,3 +182,9 @@ impl SyntaxMappingBuilder {
editor.mappings.add_mapping(self); editor.mappings.add_mapping(self);
} }
} }
#[derive(Debug, Clone, Copy)]
struct MappingEntry {
parent: u32,
child_slot: u32,
}