mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-12 13:28:13 +00:00
handle merging two syntax editors together
This commit is contained in:
parent
883e429179
commit
db649195e9
2 changed files with 39 additions and 14 deletions
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue