type_sitter_lib/node/tree.rs
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)
}
}