mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
File builder growndwork
This commit is contained in:
parent
9c804accf1
commit
9e4c288201
3 changed files with 120 additions and 0 deletions
|
@ -32,6 +32,12 @@ impl From<TextUnit> for u32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<u32> for TextUnit {
|
||||
fn from(tu: u32) -> TextUnit {
|
||||
TextUnit::new(tu)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<TextUnit> for TextUnit {
|
||||
type Output = TextUnit;
|
||||
fn add(self, rhs: TextUnit) -> TextUnit {
|
||||
|
|
111
src/tree/file_builder.rs
Normal file
111
src/tree/file_builder.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use {SyntaxKind, TextUnit, TextRange};
|
||||
use super::{NodeData, NodeIdx, File};
|
||||
|
||||
pub struct FileBuilder {
|
||||
text: String,
|
||||
nodes: Vec<NodeData>,
|
||||
in_progress: Vec<(NodeIdx, Option<NodeIdx>)>, // (parent, last_child)
|
||||
pos: TextUnit,
|
||||
}
|
||||
|
||||
impl FileBuilder {
|
||||
pub fn new(text: String) -> FileBuilder {
|
||||
FileBuilder {
|
||||
text,
|
||||
nodes: Vec::new(),
|
||||
in_progress: Vec::new(),
|
||||
pos: TextUnit::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(self) -> File {
|
||||
assert!(self.in_progress.is_empty());
|
||||
assert!(self.pos == (self.text.len() as u32).into());
|
||||
File {
|
||||
text: self.text,
|
||||
nodes: self.nodes,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
|
||||
let leaf = NodeData {
|
||||
kind,
|
||||
range: TextRange::from_len(self.pos, len),
|
||||
parent: None,
|
||||
first_child: None,
|
||||
next_sibling: None,
|
||||
};
|
||||
self.pos += len;
|
||||
let id = self.push_child(leaf);
|
||||
self.add_len(id);
|
||||
}
|
||||
|
||||
pub fn start_internal(&mut self, kind: SyntaxKind) {
|
||||
let node = NodeData {
|
||||
kind,
|
||||
range: TextRange::from_len(self.pos, 0.into()),
|
||||
parent: None,
|
||||
first_child: None,
|
||||
next_sibling: None,
|
||||
};
|
||||
let id = if self.in_progress.is_empty() {
|
||||
self.new_node(node)
|
||||
} else {
|
||||
self.push_child(node)
|
||||
};
|
||||
self.in_progress.push((id, None))
|
||||
}
|
||||
|
||||
pub fn finish_internal(&mut self) {
|
||||
let (id, _) = self.in_progress.pop().unwrap();
|
||||
if !self.in_progress.is_empty() {
|
||||
self.add_len(id);
|
||||
}
|
||||
}
|
||||
|
||||
fn new_node(&mut self, data: NodeData) -> NodeIdx {
|
||||
let id = NodeIdx(self.nodes.len() as u32);
|
||||
self.nodes.push(data);
|
||||
id
|
||||
}
|
||||
|
||||
fn push_child(&mut self, mut child: NodeData) -> NodeIdx {
|
||||
child.parent = Some(self.current_id());
|
||||
let id = self.new_node(child);
|
||||
if let Some(sibling) = self.current_sibling() {
|
||||
fill(&mut sibling.next_sibling, id);
|
||||
return id
|
||||
}
|
||||
fill(&mut self.current_parent().first_child, id);
|
||||
id
|
||||
}
|
||||
|
||||
fn add_len(&mut self, child: NodeIdx) {
|
||||
let range = self.nodes[child.0 as usize].range;
|
||||
grow(&mut self.current_parent().range, range);
|
||||
}
|
||||
|
||||
fn current_id(&self) -> NodeIdx {
|
||||
self.in_progress.last().unwrap().0
|
||||
}
|
||||
|
||||
fn current_parent(&mut self) -> &mut NodeData {
|
||||
let NodeIdx(idx) = self.current_id();
|
||||
&mut self.nodes[idx as usize]
|
||||
}
|
||||
|
||||
fn current_sibling(&mut self) -> Option<&mut NodeData> {
|
||||
let NodeIdx(idx) = self.in_progress.last().unwrap().1?;
|
||||
Some(&mut self.nodes[idx as usize])
|
||||
}
|
||||
}
|
||||
|
||||
fn fill<T>(slot: &mut Option<T>, value: T) {
|
||||
assert!(slot.is_none());
|
||||
*slot = Some(value);
|
||||
}
|
||||
|
||||
fn grow(left: &mut TextRange, right: TextRange) {
|
||||
assert_eq!(left.end(), right.start());
|
||||
*left = TextRange::from_to(left.start(), right.end())
|
||||
}
|
|
@ -3,6 +3,9 @@ use syntax_kinds::syntax_info;
|
|||
|
||||
use std::fmt;
|
||||
|
||||
mod file_builder;
|
||||
pub use self::file_builder::FileBuilder;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct SyntaxKind(pub(crate) u32);
|
||||
|
||||
|
|
Loading…
Reference in a new issue