reovim_plugin_treesitter/
parser.rs

1//! Buffer parser state management and incremental parsing
2
3use tree_sitter::{InputEdit, Parser, Tree};
4
5/// Parser state for a single buffer
6pub struct BufferParser {
7    /// The tree-sitter parser instance
8    parser: Parser,
9    /// Current parse tree (None if never parsed or parse failed)
10    tree: Option<Tree>,
11    /// Language ID of this parser
12    language_id: String,
13    /// Version counter for cache invalidation
14    version: u64,
15}
16
17impl BufferParser {
18    /// Create a new parser for the given language
19    ///
20    /// Returns None if parser setup fails
21    #[must_use]
22    pub fn new(language: &tree_sitter::Language, language_id: &str) -> Option<Self> {
23        let mut parser = Parser::new();
24        parser.set_language(language).ok()?;
25
26        Some(Self {
27            parser,
28            tree: None,
29            language_id: language_id.to_string(),
30            version: 0,
31        })
32    }
33
34    /// Get the language ID
35    #[must_use]
36    pub fn language_id(&self) -> &str {
37        &self.language_id
38    }
39
40    /// Get the current version
41    #[must_use]
42    pub const fn version(&self) -> u64 {
43        self.version
44    }
45
46    /// Get the current parse tree
47    #[must_use]
48    pub const fn tree(&self) -> Option<&Tree> {
49        self.tree.as_ref()
50    }
51
52    /// Perform a full parse of the buffer content
53    ///
54    /// This replaces any existing parse tree
55    pub fn parse_full(&mut self, content: &str) -> Option<&Tree> {
56        self.tree = self.parser.parse(content, None);
57        self.version = self.version.wrapping_add(1);
58        self.tree.as_ref()
59    }
60
61    /// Perform an incremental parse after an edit
62    ///
63    /// The `edit` describes what changed in the document.
64    /// Returns the new parse tree, or None if parsing failed.
65    pub fn parse_incremental(&mut self, content: &str, edit: &InputEdit) -> Option<&Tree> {
66        // Apply the edit to the existing tree if we have one
67        if let Some(ref mut tree) = self.tree {
68            tree.edit(edit);
69        }
70
71        // Re-parse with the old tree for incremental parsing
72        self.tree = self.parser.parse(content, self.tree.as_ref());
73        self.version = self.version.wrapping_add(1);
74        self.tree.as_ref()
75    }
76
77    /// Check if we have a valid parse tree
78    #[must_use]
79    pub const fn has_tree(&self) -> bool {
80        self.tree.is_some()
81    }
82}