1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#[cfg(feature = "yak-sitter")]
use crate::TreeParseError;
use crate::{raw, IncludedRangesError, Language, LanguageError, Node, Range, Tree};
use std::marker::PhantomData;
#[cfg(feature = "yak-sitter")]
use std::path::Path;
/// A stateful object that this is used to produce a tree based on some source code.
#[repr(transparent)]
pub struct Parser<Root: Node<'static>>(pub raw::Parser, PhantomData<Root>);
impl<Root: Node<'static>> Parser<Root> {
/// Convert a tree-sitter parser into a typed parser by specifying the correct root node type.
///
/// This will succeed even if `Root` is not the language's root node, because
/// [`Tree::root_node`] checks that the root node is the correct type.
pub fn wrap(parser: raw::Parser) -> Self {
Self(parser, PhantomData)
}
/// Version of [`wrap`](Self::wrap) for an immutable reference.
pub fn wrap_ref(parser: &raw::Parser) -> &Self {
// SAFETY: Same repr
unsafe { &*(parser as *const raw::Parser as *const Self) }
}
/// Version of [`wrap`](Self::wrap) for a mutable reference.
pub fn wrap_mut(parser: &mut raw::Parser) -> &mut Self {
// SAFETY: Same repr
unsafe { &mut *(parser as *mut raw::Parser as *mut Self) }
}
/// Create a new parser for the given language. See
/// [tree-sitter's `Parser::set_language`](tree_sitter::Parser::set_language).
///
/// This will succeed even if `Root` is not the language's root node, because
/// [`Tree::root_node`] checks that the root node is the correct type.
///
/// If the language changes, the root node should change as well, so `set_language` isn't
/// exposed by this wrapper. Instead, unwrap the parser, call `set_language`, and re-wrap.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn new(language: &Language) -> Result<Self, LanguageError> {
Ok(Self(raw::Parser::new(language)?, PhantomData))
}
/// Create a new parser for the given language. See [`tree_sitter::Parser::set_language`]
#[inline]
#[cfg(not(feature = "yak-sitter"))]
pub fn new(language: &Language) -> Result<Self, LanguageError> {
let mut parser = raw::Parser::new();
parser.set_language(language)?;
Ok(Self(parser, PhantomData))
}
/// Set the ranges of text the parser should include when parsing. See
/// [`tree_sitter::Parser::set_included_ranges`]
#[inline]
pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
self.0.set_included_ranges(ranges)
}
/// Parse a file. See [`tree_sitter::Parser::parse`].
///
/// Additionally, file must be valid utf-8 or this will return `Err`. The file's path is used
/// for stable node comparison between trees.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn parse_file(
&mut self,
path: &Path,
old_tree: Option<&Tree<Root>>,
) -> Result<Tree<Root>, TreeParseError> {
self.0
.parse_file(path, old_tree.map(|t| &t.0))
.map(Tree::wrap)
}
/// Parse a string. See [`tree_sitter::Parser::parse`].
///
/// The path is stored as metadata that can be accessed from nodes. If you don't need this, pass
/// `None`.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn parse_string(
&mut self,
text: String,
path: Option<&Path>,
old_tree: Option<&Tree<Root>>,
) -> Result<Tree<Root>, TreeParseError> {
self.0
.parse_string(text, path, old_tree.map(|t| &t.0))
.map(Tree::wrap)
}
/// Parse a byte string. See [`tree_sitter::Parser::parse`].
///
/// Note that the wrappers expect and assume UTF-8, so this will fail if the text is not valid
/// UTF-8.
///
/// The path is stored as metadata that can be accessed from nodes. If you don't need this, pass
/// `None`.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn parse_bytes(
&mut self,
byte_text: Vec<u8>,
path: Option<&Path>,
old_tree: Option<&Tree<Root>>,
) -> Result<Tree<Root>, TreeParseError> {
self.0
.parse_bytes(byte_text, path, old_tree.map(|t| &t.0))
.map(Tree::wrap)
}
/// Parse a byte string. See [`tree_sitter::Parser::parse`]
#[inline]
#[cfg(not(feature = "yak-sitter"))]
pub fn parse(
&mut self,
text: impl AsRef<[u8]>,
old_tree: Option<&Tree<Root>>,
) -> Result<Tree<Root>, ()> {
self.0
.parse(text, old_tree.map(|t| &t.0))
.ok_or(())
.map(Tree::wrap)
}
}