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
use crate::{raw, InputEdit, LanguageRef, Node, NodeResult, Range, TreeCursor};
#[cfg(feature = "yak-sitter")]
use std::iter::Once;
use std::marker::PhantomData;
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
#[cfg(windows)]
use std::os::windows::io::AsRawHandle;
#[cfg(feature = "yak-sitter")]
use std::path::Path;
#[cfg(feature = "yak-sitter")]
use tree_sitter::TextProvider;
#[derive(Clone, Debug)]
#[repr(transparent)]
pub struct Tree<Root: Node<'static>>(pub raw::Tree, PhantomData<Root>);
impl<Root: Node<'static>> Tree<Root> {
/// Convert a tree-sitter tree into a typed tree by specifying the correct root node type.
///
/// This will succeed even if `Root` is not the language's root node, because
/// [`root_node`](Self::root_node) checks that the root node is the correct type.
pub fn wrap(tree: raw::Tree) -> Self {
Self(tree, PhantomData)
}
/// Version of [`wrap`](Self::wrap) for an immutable reference.
pub fn wrap_ref(tree: &raw::Tree) -> &Self {
// SAFETY: Same repr
unsafe { &*(tree as *const raw::Tree as *const Self) }
}
/// Version of [`wrap`](Self::wrap) for a mutable reference.
pub fn wrap_mut(tree: &mut raw::Tree) -> &mut Self {
// SAFETY: Same repr
unsafe { &mut *(tree as *mut raw::Tree as *mut Self) }
}
/// Get the underlying text. This includes text which isn't in the [`Self::included_ranges`]
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn text(&self) -> &str {
self.0.text()
}
/// Get the path the tree is associated with, if any.
///
/// The path may be virtual, it's used for stable node comparison between trees.
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn path(&self) -> Option<&Path> {
self.0.path()
}
/// Get the root node of this tree.
///
/// Returns `Err` if the root is the wrong type, which may happen even if the language is
/// correct if the entire tree is an error node.
pub fn root_node(&self) -> NodeResult<'_, Root::WithLifetime<'_>> {
Root::WithLifetime::try_from_raw(self.0.root_node())
}
/// Create a cursor starting at the root node
#[inline]
pub fn walk(&self) -> TreeCursor<'_> {
TreeCursor(self.0.walk())
}
/// Get the included ranges used to parse the tree
#[inline]
pub fn included_ranges(&self) -> Vec<Range> {
self.0.included_ranges()
}
/// Get the changed ranges. See [`tree_sitter::Tree::changed_ranges`]
#[inline]
pub fn changed_ranges(&self, other: &Tree<Root>) -> impl ExactSizeIterator<Item = Range> {
self.0.changed_ranges(&other.0)
}
/// Get the language used to parse the tree.
#[inline]
pub fn language(&self) -> LanguageRef<'_> {
self.0.language()
}
//noinspection RsIncorrectFunctionArgumentCount - IntelliJ inspection bug.
/// Print a dot graph of the tree to the given file. See [`tree_sitter::Tree::print_dot_graph`]
#[inline]
pub fn print_dot_graph(
&self,
#[cfg(unix)] file: &impl AsRawFd,
#[cfg(windows)] file: &impl AsRawHandle,
) {
self.0.print_dot_graph(file)
}
/// Edit the tree. See [`tree_sitter::Tree::edit`]
#[inline]
pub fn edit(&mut self, edit: &InputEdit) {
self.0.edit(edit)
}
}
#[cfg(feature = "yak-sitter")]
impl<'tree, Root: Node<'static>> TextProvider<&'tree str> for &'tree Tree<Root> {
type I = Once<&'tree str>;
fn text(&mut self, node: tree_sitter::Node) -> Self::I {
TextProvider::text(&mut &self.0, node)
}
}