From a1761d9b1b1895338a3d00c2f0f03cdf7ef4199d Mon Sep 17 00:00:00 2001 From: Evgeny Kropotin Date: Thu, 11 Sep 2025 13:55:07 -0700 Subject: [PATCH 1/2] perf: optimize TreeSitterWalker cursor usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace per-node cursor creation with single reusable cursor for tree traversal. This eliminates repeated allocations and improves performance for large documents. Changes: - Create single TreeCursor in walk() method instead of per-node cursors - Refactor walk_pre_order and walk_post_order to use cursor navigation - Use goto_first_child/goto_next_sibling/goto_parent for efficient traversal - Maintain correct pre-order and post-order semantics 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .claude/commands/publish.md | 3 -- .claude/commands/review.md | 1 - .../quickmark-core/src/tree_sitter_walker.rs | 35 ++++++++++++++----- 3 files changed, 26 insertions(+), 13 deletions(-) delete mode 100644 .claude/commands/publish.md delete mode 100644 .claude/commands/review.md diff --git a/.claude/commands/publish.md b/.claude/commands/publish.md deleted file mode 100644 index e48bd94..0000000 --- a/.claude/commands/publish.md +++ /dev/null @@ -1,3 +0,0 @@ -1. Commit all unstaged files -2. Squash commits which were not yet published on the remote. -3. Generate the final commit message based on the diff with the remote branch, from which the current branch is originated. diff --git a/.claude/commands/review.md b/.claude/commands/review.md deleted file mode 100644 index fd37aa2..0000000 --- a/.claude/commands/review.md +++ /dev/null @@ -1 +0,0 @@ -Review the code changes in the current branch, ensuring they adhere to the coding standards outlined in CLAUDE.md. diff --git a/crates/quickmark-core/src/tree_sitter_walker.rs b/crates/quickmark-core/src/tree_sitter_walker.rs index 3c0bd9c..772ea64 100644 --- a/crates/quickmark-core/src/tree_sitter_walker.rs +++ b/crates/quickmark-core/src/tree_sitter_walker.rs @@ -25,25 +25,42 @@ impl<'a> TreeSitterWalker<'a> { } pub fn walk(&self, mut callback: impl FnMut(Node)) { - let root = self.tree.root_node(); + let mut cursor = self.tree.walk(); match self.order { - TraversalOrder::PreOrder => self.walk_pre_order(root, &mut callback), - TraversalOrder::PostOrder => self.walk_post_order(root, &mut callback), + TraversalOrder::PreOrder => self.walk_pre_order(&mut cursor, &mut callback), + TraversalOrder::PostOrder => self.walk_post_order(&mut cursor, &mut callback), } } #[allow(clippy::only_used_in_recursion)] - fn walk_pre_order(&self, node: Node, callback: &mut impl FnMut(Node)) { + fn walk_pre_order(&self, cursor: &mut tree_sitter::TreeCursor, callback: &mut impl FnMut(Node)) { + let node = cursor.node(); callback(node); - for child in node.children(&mut node.walk()) { - self.walk_pre_order(child, callback); + + if cursor.goto_first_child() { + loop { + self.walk_pre_order(cursor, callback); + if !cursor.goto_next_sibling() { + break; + } + } + cursor.goto_parent(); } } + #[allow(clippy::only_used_in_recursion)] - fn walk_post_order(&self, node: Node, callback: &mut impl FnMut(Node)) { - for child in node.children(&mut node.walk()) { - self.walk_post_order(child, callback); + fn walk_post_order(&self, cursor: &mut tree_sitter::TreeCursor, callback: &mut impl FnMut(Node)) { + if cursor.goto_first_child() { + loop { + self.walk_post_order(cursor, callback); + if !cursor.goto_next_sibling() { + break; + } + } + cursor.goto_parent(); } + + let node = cursor.node(); callback(node); } } From 6bec010b846e7eff44e80c0a557b48577de10559 Mon Sep 17 00:00:00 2001 From: Evgeny Kropotin Date: Thu, 11 Sep 2025 13:59:51 -0700 Subject: [PATCH 2/2] chore: fix formatting --- .../quickmark-core/src/tree_sitter_walker.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/crates/quickmark-core/src/tree_sitter_walker.rs b/crates/quickmark-core/src/tree_sitter_walker.rs index 772ea64..e091a9a 100644 --- a/crates/quickmark-core/src/tree_sitter_walker.rs +++ b/crates/quickmark-core/src/tree_sitter_walker.rs @@ -33,10 +33,14 @@ impl<'a> TreeSitterWalker<'a> { } #[allow(clippy::only_used_in_recursion)] - fn walk_pre_order(&self, cursor: &mut tree_sitter::TreeCursor, callback: &mut impl FnMut(Node)) { + fn walk_pre_order( + &self, + cursor: &mut tree_sitter::TreeCursor, + callback: &mut impl FnMut(Node), + ) { let node = cursor.node(); callback(node); - + if cursor.goto_first_child() { loop { self.walk_pre_order(cursor, callback); @@ -47,9 +51,13 @@ impl<'a> TreeSitterWalker<'a> { cursor.goto_parent(); } } - + #[allow(clippy::only_used_in_recursion)] - fn walk_post_order(&self, cursor: &mut tree_sitter::TreeCursor, callback: &mut impl FnMut(Node)) { + fn walk_post_order( + &self, + cursor: &mut tree_sitter::TreeCursor, + callback: &mut impl FnMut(Node), + ) { if cursor.goto_first_child() { loop { self.walk_post_order(cursor, callback); @@ -59,7 +67,7 @@ impl<'a> TreeSitterWalker<'a> { } cursor.goto_parent(); } - + let node = cursor.node(); callback(node); }