use locals::Locals;
use ropey::RopeSlice;
use slab::Slab;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::time::Duration;
use tree_sitter::{IncompatibleGrammarError, Node, Tree};
pub use crate::config::{read_query, LanguageConfig, LanguageLoader};
pub use crate::injections_query::{InjectionLanguageMarker, InjectionsQuery};
use crate::parse::LayerUpdateFlags;
pub use crate::query_iter::{CapturedMatch, QueryMatchIter, QueryMatchIterEvent};
pub use crate::tree_cursor::TreeCursor;
pub use tree_sitter;
mod config;
pub mod highlighter;
mod injections_query;
mod parse;
#[cfg(all(test, feature = "fixtures"))]
mod tests;
#[cfg(feature = "fixtures")]
pub mod fixtures;
pub mod locals;
pub mod query_iter;
pub mod text_object;
mod tree_cursor;
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct Layer(u32);
impl Layer {
fn idx(self) -> usize {
self.0 as usize
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Language(pub u32);
impl Language {
pub fn new(idx: u32) -> Language {
Language(idx)
}
pub fn idx(self) -> usize {
self.0 as usize
}
}
#[derive(Debug, Clone)]
pub struct Syntax {
layers: Slab<LayerData>,
root: Layer,
}
impl Syntax {
pub fn new(
source: RopeSlice,
language: Language,
timeout: Duration,
loader: &impl LanguageLoader,
) -> Result<Self, Error> {
let root_layer = LayerData {
parse_tree: None,
language,
flags: LayerUpdateFlags::default(),
ranges: vec![tree_sitter::Range::new(
tree_sitter::Point::ZERO,
tree_sitter::Point::MAX,
0,
u32::MAX,
)],
injections: Vec::new(),
parent: None,
locals: Locals::default(),
};
let mut layers = Slab::with_capacity(32);
let root = layers.insert(root_layer);
let mut syntax = Self {
root: Layer(root as u32),
layers,
};
syntax.update(source, timeout, &[], loader).map(|_| syntax)
}
pub fn layer(&self, layer: Layer) -> &LayerData {
&self.layers[layer.idx()]
}
fn layer_mut(&mut self, layer: Layer) -> &mut LayerData {
&mut self.layers[layer.idx()]
}
pub fn root(&self) -> Layer {
self.root
}
pub fn tree(&self) -> &Tree {
self.layer(self.root)
.tree()
.expect("`Syntax::new` would err if the root layer's tree could not be parsed")
}
#[inline]
pub fn tree_for_byte_range(&self, start: u32, end: u32) -> &Tree {
self.layer_and_tree_for_byte_range(start, end).1
}
pub(crate) fn layer_and_tree_for_byte_range(&self, start: u32, end: u32) -> (Layer, &Tree) {
let mut layer = self.layer_for_byte_range(start, end);
loop {
if let Some(tree) = self.layer(layer).tree() {
return (layer, tree);
}
if let Some(parent) = self.layer(layer).parent {
layer = parent;
}
}
}
#[inline]
pub fn named_descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Node<'_>> {
self.tree_for_byte_range(start, end)
.root_node()
.named_descendant_for_byte_range(start, end)
}
#[inline]
pub fn descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Node<'_>> {
self.tree_for_byte_range(start, end)
.root_node()
.descendant_for_byte_range(start, end)
}
pub fn layer_for_byte_range(&self, start: u32, end: u32) -> Layer {
self.layers_for_byte_range(start, end)
.last()
.expect("always includes the root layer")
}
pub fn layers_for_byte_range(&self, start: u32, end: u32) -> impl Iterator<Item = Layer> + '_ {
let mut parent_injection_layer = self.root;
std::iter::once(self.root).chain(std::iter::from_fn(move || {
let layer = &self.layers[parent_injection_layer.idx()];
let injection_at_start = layer.injection_at_byte_idx(start)?;
let injection_at_end = layer.injection_at_byte_idx(end)?;
(injection_at_start.layer == injection_at_end.layer).then(|| {
parent_injection_layer = injection_at_start.layer;
injection_at_start.layer
})
}))
}
pub fn walk(&self) -> TreeCursor<'_> {
TreeCursor::new(self)
}
}
#[derive(Debug, Clone)]
pub struct Injection {
pub range: Range,
pub layer: Layer,
matched_node_range: Range,
}
#[derive(Debug, Clone)]
pub struct LayerData {
pub language: Language,
parse_tree: Option<Tree>,
ranges: Vec<tree_sitter::Range>,
injections: Vec<Injection>,
flags: LayerUpdateFlags,
parent: Option<Layer>,
locals: Locals,
}
impl PartialEq for LayerData {
fn eq(&self, other: &Self) -> bool {
self.parent == other.parent
&& self.language == other.language
&& self.ranges == other.ranges
}
}
impl Hash for LayerData {
fn hash<H: Hasher>(&self, state: &mut H) {
self.parent.hash(state);
self.language.hash(state);
self.ranges.hash(state);
}
}
impl LayerData {
pub fn tree(&self) -> Option<&Tree> {
self.parse_tree.as_ref()
}
pub fn injection_at_byte_idx(&self, idx: u32) -> Option<&Injection> {
self.injections_at_byte_idx(idx)
.next()
.filter(|injection| injection.range.start <= idx)
}
pub fn injections_at_byte_idx(&self, idx: u32) -> impl Iterator<Item = &Injection> {
let i = self
.injections
.partition_point(|range| range.range.end <= idx);
self.injections[i..].iter()
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
Timeout,
ExceededMaximumSize,
InvalidRanges,
Unknown,
NoRootConfig,
IncompatibleGrammar(Language, IncompatibleGrammarError),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Timeout => f.write_str("configured timeout was exceeded"),
Self::ExceededMaximumSize => f.write_str("input text exceeds the maximum allowed size"),
Self::InvalidRanges => f.write_str("invalid ranges"),
Self::Unknown => f.write_str("an unknown error occurred"),
Self::NoRootConfig => f.write_str(
"`LanguageLoader::get_config` for the root layer language returned `None`",
),
Self::IncompatibleGrammar(language, IncompatibleGrammarError { abi_version }) => {
write!(
f,
"failed to load grammar for language {language:?} with ABI version {abi_version}"
)
}
}
}
}
pub const TREE_SITTER_MATCH_LIMIT: u32 = 256;
type Range = std::ops::Range<u32>;
#[cfg(test)]
mod unit_tests {
use super::{Injection, Language, Layer, LayerData};
use crate::locals::Locals;
use crate::parse::LayerUpdateFlags;
fn make_injection(start: u32, end: u32) -> Injection {
Injection {
range: start..end,
layer: Layer(0),
matched_node_range: start..end,
}
}
fn layer_with_injections(injections: Vec<Injection>) -> LayerData {
LayerData {
language: Language(0),
parse_tree: None,
ranges: vec![],
injections,
flags: LayerUpdateFlags::default(),
parent: None,
locals: Locals::default(),
}
}
#[test]
fn injection_at_byte_idx_exclusive_end() {
let layer = layer_with_injections(vec![make_injection(5, 10)]);
assert!(layer.injection_at_byte_idx(9).is_some());
assert!(layer.injection_at_byte_idx(10).is_none());
}
#[test]
fn injection_at_byte_idx_adjacent() {
let layer = layer_with_injections(vec![make_injection(0, 10), make_injection(10, 20)]);
let inj = layer.injection_at_byte_idx(10).unwrap();
assert_eq!(inj.range, 10..20);
}
}