Skip to content

Commit

Permalink
chore: deduplicate GritQL snippets (#4153)
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjr authored Oct 7, 2024
1 parent 2f0d5c7 commit bae50d1
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
- 'crates/**_parser/**/*.rs'
- 'crates/**_formatter/**/*.rs'
- 'crates/**_analyze/**/*.rs'
- 'crates/biome_grit_patterns/**/*.rs'
push:
branches:
- main
Expand All @@ -19,6 +20,7 @@ on:
- 'crates/**_parser/**/*.rs'
- 'crates/**_formatter/**/*.rs'
- 'crates/**_analyze/**/*.rs'
- 'crates/biome_grit_patterns/**/*.rs'

env:
RUST_LOG: info
Expand Down
37 changes: 25 additions & 12 deletions crates/biome_grit_patterns/src/grit_target_language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,19 +187,32 @@ impl GritTargetLanguage {

pub fn parse_snippet_contexts(&self, source: &str) -> Vec<SnippetTree<GritTargetTree>> {
let source = self.substitute_metavariable_prefix(source);
self.snippet_context_strings()
.iter()
.map(|(pre, post)| self.get_parser().parse_snippet(pre, &source, post))
.filter(|result| {
result
.tree

let mut snippet_trees: Vec<SnippetTree<GritTargetTree>> = Vec::new();
for (pre, post) in self.snippet_context_strings() {
let parse_result = self.get_parser().parse_snippet(pre, &source, post);

let has_errors = parse_result
.tree
.root_node()
.descendants()
.map_or(false, |mut descendants| {
descendants.any(|descendant| descendant.kind().is_bogus())
});
if has_errors {
continue;
}

if !snippet_trees.iter().any(|tree| {
tree.tree
.root_node()
.descendants()
.map_or(false, |mut descendants| {
!descendants.any(|descendant| descendant.kind().is_bogus())
})
})
.collect()
.matches_kinds_recursively_with(&parse_result.tree.root_node())
}) {
snippet_trees.push(parse_result);
}
}

snippet_trees
}
}

Expand Down
46 changes: 46 additions & 0 deletions crates/biome_grit_patterns/src/grit_target_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,52 @@ impl<'a> GritTargetNode<'a> {
let trimmed_range = self.text_trimmed_range();
&self.source()[trimmed_range.start().into()..trimmed_range.end().into()]
}

/// Matches the `kind` of this node, and those of all its children, with
/// those of another node.
///
/// This is a relatively cheap way to discover whether two parsed snippets
/// are identical when they were parsed from the same source string, but
/// with different contexts. In that use case, we already know the snippet
/// is essentially the same, but we only detect a meaningful difference in
/// context by looking for a variance in node kinds.
pub fn matches_kinds_recursively_with(&self, other: &Self) -> bool {
let mut cursor_a = self.walk();
let mut cursor_b = other.walk();

// Are we navigating back up? If so, we shouldn't try to visit any
// children until we've visited another sibling, or we'd run in circles.
let mut up = false;

loop {
if cursor_a.node().kind() != cursor_b.node().kind() {
break false;
}

if !up && cursor_a.goto_first_child() {
if !cursor_b.goto_first_child() {
break false;
}
} else if cursor_a.goto_next_sibling() {
if cursor_b.goto_first_child() || !cursor_b.goto_next_sibling() {
break false;
}

up = false;
} else if cursor_a.goto_parent() {
if (!up && cursor_b.goto_first_child())
|| cursor_b.goto_next_sibling()
|| !cursor_b.goto_parent()
{
break false;
}

up = true;
} else {
break true;
}
}
}
}

impl<'a> Debug for GritTargetNode<'a> {
Expand Down

0 comments on commit bae50d1

Please sign in to comment.