Add content_is_unique metadata to syntax nodes

accurate_ancestors_v2
Wilfred Hughes 2022-07-18 21:32:16 +07:00
parent a4ef836b66
commit a05535aa1c
1 changed files with 34 additions and 0 deletions

@ -61,6 +61,9 @@ pub struct SyntaxInfo<'a> {
///
/// Values are sequential, not hashes. Collisions never occur.
content_id: Cell<u32>,
/// Is this the only node with this content? Ignores nodes on the
/// other side.
content_is_unique: Cell<bool>,
}
impl<'a> SyntaxInfo<'a> {
@ -75,6 +78,7 @@ impl<'a> SyntaxInfo<'a> {
num_after: Cell::new(0),
unique_id: Cell::new(NonZeroU32::new(u32::MAX).unwrap()),
content_id: Cell::new(0),
content_is_unique: Cell::new(false),
}
}
}
@ -421,6 +425,7 @@ fn init_info_on_side<'a>(roots: &[&'a Syntax<'a>], next_id: &mut SyntaxId) {
set_num_ancestors(roots, 0);
set_num_after(roots, 0);
set_unique_id(roots, next_id);
set_content_is_unique(roots);
}
fn set_unique_id(nodes: &[&Syntax], next_id: &mut SyntaxId) {
@ -434,6 +439,35 @@ fn set_unique_id(nodes: &[&Syntax], next_id: &mut SyntaxId) {
}
}
/// Assumes that `set_content_id` has already run.
fn find_nodes_with_unique_content(nodes: &[&Syntax], counts: &mut HashMap<u32, usize>) {
for node in nodes {
*counts.entry(node.content_id()).or_insert(0) += 1;
if let List { children, .. } = node {
find_nodes_with_unique_content(children, counts);
}
}
}
fn set_content_is_unique_from_counts(nodes: &[&Syntax], counts: &HashMap<u32, usize>) {
for node in nodes {
let count = counts
.get(&node.content_id())
.expect("Count should be present");
node.info().content_is_unique.set(*count == 1);
if let List { children, .. } = node {
set_content_is_unique_from_counts(children, counts);
}
}
}
fn set_content_is_unique(nodes: &[&Syntax]) {
let mut counts = HashMap::new();
find_nodes_with_unique_content(nodes, &mut counts);
set_content_is_unique_from_counts(nodes, &counts);
}
fn set_prev_sibling<'a>(nodes: &[&'a Syntax<'a>]) {
for (i, node) in nodes.iter().enumerate() {
if i == 0 {