mirror of
https://github.com/helix-editor/tree-house.git
synced 2025-10-06 00:12:46 +02:00
add locals prototype
This commit is contained in:
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -190,6 +190,7 @@ dependencies = [
|
||||
"cov-mark",
|
||||
"hashbrown",
|
||||
"indexmap",
|
||||
"kstring",
|
||||
"once_cell",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
@@ -239,6 +240,15 @@ version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "kstring"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1"
|
||||
dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
|
@@ -22,6 +22,7 @@ regex-cursor = "0.1.4"
|
||||
slab = "0.4.9"
|
||||
unicode-width = { version = "=0.1.12", optional = true }
|
||||
pretty_assertions = { version = "1.4.0", optional = true }
|
||||
kstring = "2.0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
cov-mark = "2.0.0"
|
||||
|
@@ -25,6 +25,7 @@ mod tests;
|
||||
// mod pretty_print;
|
||||
#[cfg(feature = "fixtures")]
|
||||
pub mod fixtures;
|
||||
pub mod locals;
|
||||
pub mod query_iter;
|
||||
pub mod text_object;
|
||||
// mod tree_cursor;
|
||||
|
128
highlighter/src/locals.rs
Normal file
128
highlighter/src/locals.rs
Normal file
@@ -0,0 +1,128 @@
|
||||
use std::ops::Index;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use kstring::KString;
|
||||
|
||||
use crate::highlighter::Highlight;
|
||||
use crate::Range;
|
||||
|
||||
/// A layer represent a single a single syntax tree that reprsents (part of)
|
||||
/// a file parsed with a tree-sitter grammar. See [`Syntax`]
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub struct Scope(u32);
|
||||
|
||||
impl Scope {
|
||||
const ROOT: Scope = Scope(0);
|
||||
fn idx(self) -> usize {
|
||||
self.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Locals {
|
||||
scopes: Vec<ScopeData>,
|
||||
}
|
||||
|
||||
impl Locals {
|
||||
// pub(crate) fn new(range: Range<usize>) -> Locals {
|
||||
// Locals {
|
||||
// scopes: vec![ScopeData {
|
||||
// defs: todo!(),
|
||||
// range: todo!(),
|
||||
// children: todo!(),
|
||||
// inherit: todo!(),
|
||||
// parent: todo!(),
|
||||
// }],
|
||||
// }
|
||||
// }
|
||||
pub fn lookup_reference(&self, mut scope: Scope, name: &str) -> Option<Highlight> {
|
||||
loop {
|
||||
let scope_data = &self[scope];
|
||||
if let Some(&highlight) = scope_data.defs.get(name) {
|
||||
return Some(highlight);
|
||||
}
|
||||
if !scope_data.inherit {
|
||||
break;
|
||||
}
|
||||
scope = scope_data.parent?;
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn scope_cursor(&self, pos: u32) -> ScopeCursor<'_> {
|
||||
let mut scope = Scope::ROOT;
|
||||
let mut scope_stack = Vec::with_capacity(8);
|
||||
loop {
|
||||
let scope_data = &self[scope];
|
||||
let child_idx = scope_data
|
||||
.children
|
||||
.partition_point(|&child| pos < self[child].range.end);
|
||||
scope_stack.push((scope, child_idx as u32));
|
||||
let Some(&child) = scope_data.children.get(child_idx) else {
|
||||
break;
|
||||
};
|
||||
if pos < self[child].range.start {
|
||||
break;
|
||||
}
|
||||
scope = child;
|
||||
}
|
||||
ScopeCursor {
|
||||
locals: self,
|
||||
scope_stack,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<Scope> for Locals {
|
||||
type Output = ScopeData;
|
||||
|
||||
fn index(&self, scope: Scope) -> &ScopeData {
|
||||
&self.scopes[scope.idx()]
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScopeCursor<'a> {
|
||||
pub locals: &'a Locals,
|
||||
scope_stack: Vec<(Scope, u32)>,
|
||||
}
|
||||
|
||||
impl ScopeCursor<'_> {
|
||||
pub fn advance(&mut self, to: u32) -> Scope {
|
||||
let (mut active_scope, mut child_idx) = self.scope_stack.pop().unwrap();
|
||||
loop {
|
||||
let scope_data = &self.locals[active_scope];
|
||||
if to < scope_data.range.end {
|
||||
break;
|
||||
}
|
||||
(active_scope, child_idx) = self.scope_stack.pop().unwrap();
|
||||
child_idx += 1;
|
||||
}
|
||||
'outer: loop {
|
||||
let scope_data = &self.locals[active_scope];
|
||||
loop {
|
||||
let Some(&child) = scope_data.children.get(child_idx as usize) else {
|
||||
break 'outer;
|
||||
};
|
||||
if self.locals[child].range.start > to {
|
||||
break 'outer;
|
||||
}
|
||||
if to < self.locals[child].range.end {
|
||||
self.scope_stack.push((active_scope, child_idx));
|
||||
active_scope = child;
|
||||
child_idx = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.scope_stack.push((active_scope, child_idx));
|
||||
active_scope
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScopeData {
|
||||
defs: HashMap<KString, Highlight>,
|
||||
range: Range,
|
||||
children: Box<[Scope]>,
|
||||
inherit: bool,
|
||||
parent: Option<Scope>,
|
||||
}
|
Reference in New Issue
Block a user