Avoid optimizing trivia for now

This commit is contained in:
Aleksey Kladov 2018-07-29 16:19:16 +03:00
parent 415c891d64
commit 13c6a5c4b0
5 changed files with 158 additions and 240 deletions

View file

@ -1,13 +1,12 @@
use std::sync::Arc;
use {
SyntaxKind, TextRange, TextUnit,
yellow::{SyntaxNode, GreenNode, SyntaxError},
yellow::{SyntaxNode, GreenNode, GreenNodeBuilder, SyntaxError},
parser::Sink
};
pub(crate) struct GreenBuilder {
text: String,
stack: Vec<GreenNode>,
stack: Vec<GreenNodeBuilder>,
pos: TextUnit,
root: Option<GreenNode>,
errors: Vec<SyntaxError>,
@ -33,24 +32,21 @@ impl Sink for GreenBuilder {
fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
let range = TextRange::offset_len(self.pos, len);
self.pos += len;
let text = self.text[range].to_owned();
let text = &self.text[range];
let leaf = GreenNodeBuilder::new_leaf(kind, text);
let parent = self.stack.last_mut().unwrap();
if kind.is_trivia() {
parent.push_trivia(kind, text);
} else {
let node = GreenNode::new_leaf(kind, text);
parent.push_child(Arc::new(node));
}
parent.push_child(leaf)
}
fn start_internal(&mut self, kind: SyntaxKind) {
self.stack.push(GreenNode::new_branch(kind))
self.stack.push(GreenNodeBuilder::new_internal(kind))
}
fn finish_internal(&mut self) {
let node = self.stack.pop().unwrap();
let builder = self.stack.pop().unwrap();
let node = builder.build();
if let Some(parent) = self.stack.last_mut() {
parent.push_child(Arc::new(node))
parent.push_child(node);
} else {
self.root = Some(node);
}
@ -61,7 +57,7 @@ impl Sink for GreenBuilder {
}
fn finish(self) -> SyntaxNode {
SyntaxNode::new(Arc::new(self.root.unwrap()), self.errors)
SyntaxNode::new(self.root.unwrap(), self.errors)
}
}

View file

@ -1,187 +1,159 @@
use std::sync::Arc;
use text_unit::TextUnit;
use SyntaxKind;
use {SyntaxKind::{self, *}, TextUnit};
type TokenText = String;
#[derive(Debug)]
pub(crate) struct GreenNode {
kind: SyntaxKind,
data: GreenNodeData,
#[derive(Clone, Debug)]
pub(crate) enum GreenNode {
Leaf(GreenLeaf),
Branch(Arc<GreenBranch>),
}
impl GreenNode {
pub(crate) fn new_leaf(kind: SyntaxKind, text: TokenText) -> GreenNode {
GreenNode {
kind,
data: GreenNodeData::Leaf(GreenLeaf { text }),
pub fn kind(&self) -> SyntaxKind {
match self {
GreenNode::Leaf(l) => l.kind(),
GreenNode::Branch(b) => b.kind(),
}
}
pub(crate) fn new_branch(
kind: SyntaxKind,
) -> GreenNode {
let branch = GreenBranch {
text_len: 0.into(),
leading_trivia: Trivias::default(),
children: Vec::new(),
};
GreenNode {
kind,
data: GreenNodeData::Branch(branch),
pub fn text_len(&self) -> TextUnit {
match self {
GreenNode::Leaf(l) => l.text_len(),
GreenNode::Branch(b) => b.text_len(),
}
}
pub(crate) fn push_trivia(&mut self, kind: SyntaxKind, text: TokenText) {
let branch = match &mut self.data {
GreenNodeData::Branch(branch) => branch,
_ => panic!()
};
branch.text_len += TextUnit::of_str(&text);
let leading = &mut branch.leading_trivia;
branch.children.last_mut().map(|(_, t)| t).unwrap_or(leading)
.push(Arc::new(GreenTrivia { kind, text }));
}
pub(crate) fn push_child(&mut self, node: Arc<GreenNode>) {
let branch = match &mut self.data {
GreenNodeData::Branch(branch) => branch,
_ => panic!()
};
branch.text_len += node.text_len();
branch.children.push((node, Trivias::default()));
}
pub(crate) fn kind(&self) -> SyntaxKind {
self.kind
}
pub(crate) fn text_len(&self) -> TextUnit {
match &self.data {
GreenNodeData::Leaf(l) => l.text_len(),
GreenNodeData::Branch(b) => b.text_len(),
pub fn children(&self) -> &[GreenNode] {
match self {
GreenNode::Leaf(_) => &[],
GreenNode::Branch(b) => b.children(),
}
}
pub(crate) fn text(&self) -> String {
pub fn text(&self) -> String {
let mut buff = String::new();
go(self, &mut buff);
return buff;
fn go(node: &GreenNode, buff: &mut String) {
match &node.data {
GreenNodeData::Leaf(l) => buff.push_str(&l.text),
GreenNodeData::Branch(branch) => {
add_trivia(&branch.leading_trivia, buff);
branch.children.iter().for_each(|(child, trivias)| {
go(child, buff);
add_trivia(trivias, buff);
})
match node {
GreenNode::Leaf(l) => buff.push_str(&l.text()),
GreenNode::Branch(b) => {
b.children().iter().for_each(|child| go(child, buff))
}
}
}
fn add_trivia(trivias: &Trivias, buff: &mut String) {
trivias.iter().for_each(|t| buff.push_str(&t.text))
}
}
pub(crate) fn n_children(&self) -> usize {
match &self.data {
GreenNodeData::Leaf(_) => 0,
GreenNodeData::Branch(branch) => branch.children.len(),
pub(crate) struct GreenNodeBuilder {
kind: SyntaxKind,
children: Vec<GreenNode>,
}
impl GreenNodeBuilder {
pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode {
GreenNode::Leaf(GreenLeaf::new(kind, text))
}
pub(crate) fn new_internal(kind: SyntaxKind) -> GreenNodeBuilder {
GreenNodeBuilder {
kind,
children: Vec::new(),
}
}
pub(crate) fn nth_child(&self, idx: usize) -> &Arc<GreenNode> {
match &self.data {
GreenNodeData::Leaf(_) => panic!("leaf nodes have no children"),
GreenNodeData::Branch(branch) => &branch.children[idx].0,
pub(crate) fn push_child(&mut self, node: GreenNode) {
self.children.push(node)
}
pub(crate) fn build(self) -> GreenNode {
let branch = GreenBranch::new(self.kind, self.children);
GreenNode::Branch(Arc::new(branch))
}
}
pub(crate) fn nth_trivias(&self, idx: usize) -> &Trivias {
match &self.data {
GreenNodeData::Leaf(_) => panic!("leaf nodes have no children"),
GreenNodeData::Branch(branch) => if idx == 0 {
&branch.leading_trivia
} else {
&branch.children[idx - 1].1
#[test]
fn assert_send_sync() {
fn f<T: Send + Sync>() {}
f::<GreenNode>();
}
#[derive(Clone, Debug)]
pub(crate) enum GreenLeaf {
Whitespace {
newlines: u8,
spaces: u8,
},
Token {
kind: SyntaxKind,
text: Arc<str>,
},
}
impl GreenLeaf {
fn new(kind: SyntaxKind, text: &str) -> Self {
if kind == WHITESPACE {
let newlines = text.bytes().take_while(|&b| b == b'\n').count();
let spaces = text[newlines..].bytes().take_while(|&b| b == b' ').count();
if newlines + spaces == text.len() && newlines <= N_NEWLINES && spaces <= N_SPACES {
return GreenLeaf::Whitespace { newlines: newlines as u8, spaces: spaces as u8 };
}
}
GreenLeaf::Token { kind, text: text.to_owned().into_boxed_str().into() }
}
pub(crate) fn is_leaf(&self) -> bool {
match self.data {
GreenNodeData::Leaf(_) => true,
GreenNodeData::Branch(_) => false
}
pub(crate) fn kind(&self) -> SyntaxKind {
match self {
GreenLeaf::Whitespace { .. } => WHITESPACE,
GreenLeaf::Token { kind, .. } => *kind,
}
}
#[derive(Debug)]
enum GreenNodeData {
Leaf(GreenLeaf),
Branch(GreenBranch),
pub(crate) fn text(&self) -> &str {
match self {
&GreenLeaf::Whitespace { newlines, spaces } => {
let newlines = newlines as usize;
let spaces = spaces as usize;
assert!(newlines <= N_NEWLINES && spaces <= N_SPACES);
&WS[N_NEWLINES - newlines..N_NEWLINES + spaces]
}
GreenLeaf::Token { text, .. } => text,
}
}
#[derive(Debug)]
struct GreenLeaf {
text: TokenText
pub(crate) fn text_len(&self) -> TextUnit {
TextUnit::of_str(self.text())
}
}
#[derive(Debug)]
struct GreenBranch {
const N_NEWLINES: usize = 16;
const N_SPACES: usize = 64;
const WS: &str =
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n ";
#[derive(Clone, Debug)]
pub(crate) struct GreenBranch {
text_len: TextUnit,
leading_trivia: Trivias,
children: Vec<(Arc<GreenNode>, Trivias)>,
kind: SyntaxKind,
children: Vec<GreenNode>,
}
#[derive(Debug)]
pub(crate) struct GreenTrivia {
pub(crate) kind: SyntaxKind,
pub(crate) text: TokenText,
impl GreenBranch {
fn new(kind: SyntaxKind, children: Vec<GreenNode>) -> GreenBranch {
let text_len = children.iter().map(|x| x.text_len()).sum::<TextUnit>();
GreenBranch { text_len, kind, children }
}
type Trivias = Vec<Arc<GreenTrivia>>;
pub(crate) trait TextLen {
fn text_len(&self) -> TextUnit;
pub fn kind(&self) -> SyntaxKind {
self.kind
}
impl TextLen for GreenTrivia {
fn text_len(&self) -> TextUnit {
TextUnit::of_str(&self.text)
}
}
impl<T: TextLen> TextLen for Arc<T> {
fn text_len(&self) -> TextUnit {
let this: &T = self;
this.text_len()
}
}
impl TextLen for GreenNode {
fn text_len(&self) -> TextUnit {
self.text_len()
}
}
impl TextLen for GreenLeaf {
fn text_len(&self) -> TextUnit {
TextUnit::of_str(&self.text)
}
}
impl TextLen for GreenBranch {
fn text_len(&self) -> TextUnit {
pub fn text_len(&self) -> TextUnit {
self.text_len
}
pub fn children(&self) -> &[GreenNode] {
self.children.as_slice()
}
}
impl<T: TextLen> TextLen for [T] {
fn text_len(&self) -> TextUnit {
self.iter().map(TextLen::text_len).sum()
}
}

View file

@ -8,7 +8,7 @@ use std::{
mem
};
pub(crate) use self::{
green::{GreenNode, TextLen},
green::{GreenNode, GreenNodeBuilder},
red::RedNode,
syntax::SyntaxError,
builder::GreenBuilder,

View file

@ -1,12 +1,12 @@
use std::sync::{Arc, RwLock};
use {
TextUnit,
yellow::{Ptr, GreenNode, TextLen}
yellow::{Ptr, GreenNode},
};
#[derive(Debug)]
pub(crate) struct RedNode {
green: Arc<GreenNode>,
green: GreenNode,
parent: Option<ParentData>,
children: RwLock<Vec<Option<Arc<RedNode>>>>,
}
@ -20,30 +20,30 @@ struct ParentData {
impl RedNode {
pub fn new_root(
green: Arc<GreenNode>,
green: GreenNode,
) -> RedNode {
RedNode::new(green, None)
}
fn new_child(
green: Arc<GreenNode>,
green: GreenNode,
parent: Ptr<RedNode>,
start_offset: TextUnit,
index_in_parent: usize
index_in_parent: usize,
) -> RedNode {
let parent_data = ParentData {
parent,
start_offset,
index_in_parent
index_in_parent,
};
RedNode::new(green, Some(parent_data))
}
fn new(
green: Arc<GreenNode>,
green: GreenNode,
parent: Option<ParentData>,
) -> RedNode {
let children = vec![None; green.n_children()];
let children = vec![None; green.children().len()];
RedNode { green, parent, children: RwLock::new(children) }
}
@ -59,29 +59,22 @@ impl RedNode {
}
pub(crate) fn n_children(&self) -> usize {
self.green.n_children()
self.green.children().len()
}
pub(crate) fn nth_child(&self, me: Ptr<RedNode>, n: usize) -> Arc<RedNode> {
match &self.children.read().unwrap()[n] {
pub(crate) fn nth_child(&self, me: Ptr<RedNode>, idx: usize) -> Arc<RedNode> {
match &self.children.read().unwrap()[idx] {
Some(child) => return child.clone(),
None => (),
}
let mut children = self.children.write().unwrap();
if children[n].is_none() {
let start_offset = {
let mut acc = self.start_offset();
for i in 0..n {
acc += self.green.nth_trivias(i).text_len();
acc += self.green.nth_child(i).text_len();
if children[idx].is_none() {
let green_children = self.green.children();
let start_offset = self.start_offset()
+ green_children[..idx].iter().map(|x| x.text_len()).sum::<TextUnit>();
let child = RedNode::new_child(green_children[idx].clone(), me, start_offset, idx);
children[idx] = Some(Arc::new(child))
}
acc += self.green.nth_trivias(n).text_len();
acc
};
let green = self.green.nth_child(n).clone();
let child = RedNode::new_child(green, me, start_offset, n);
children[n] = Some(Arc::new(child))
}
children[n].as_ref().unwrap().clone()
children[idx].as_ref().unwrap().clone()
}
}

View file

@ -6,14 +6,13 @@ use std::{
use {
TextRange, TextUnit,
SyntaxKind::{self, *},
yellow::{Ptr, RedNode, GreenNode, TextLen},
yellow::{Ptr, RedNode, GreenNode},
};
#[derive(Clone)]
pub struct SyntaxNode {
pub(crate) root: SyntaxRoot,
red: Ptr<RedNode>,
trivia_pos: Option<(usize, usize)>,
}
#[derive(Clone)]
@ -29,80 +28,38 @@ pub(crate) struct SyntaxError {
}
impl SyntaxNode {
pub(crate) fn new(root: Arc<GreenNode>, errors: Vec<SyntaxError>) -> SyntaxNode {
pub(crate) fn new(root: GreenNode, errors: Vec<SyntaxError>) -> SyntaxNode {
let root = Arc::new(RedNode::new_root(root));
let red = Ptr::new(&root);
let root = SyntaxRoot { red: root, errors: Arc::new(errors) };
SyntaxNode { root, red, trivia_pos: None }
SyntaxNode { root, red }
}
pub fn kind(&self) -> SyntaxKind {
let green = self.red().green();
match self.trivia_pos {
None => green.kind(),
Some((i, j)) => green.nth_trivias(i)[j].kind
}
self.red().green().kind()
}
pub fn range(&self) -> TextRange {
let red = self.red();
let green = red.green();
match self.trivia_pos {
None => TextRange::offset_len(red.start_offset(), red.green().text_len()),
Some((i, j)) => {
let trivias = green.nth_trivias(i);
let offset = if i == 0 {
red.start_offset()
} else {
let prev_child = red.nth_child(Ptr::clone(&self.red), i - 1);
let mut offset = prev_child.start_offset() + prev_child.green().text_len();
for k in 0..j {
offset += &trivias[k].text_len();
}
offset
};
TextRange::offset_len(offset, trivias[j].text_len())
}
}
TextRange::offset_len(
red.start_offset(),
red.green().text_len(),
)
}
pub fn text(&self) -> String {
let green = self.red().green();
match self.trivia_pos {
None => green.text(),
Some((i, j)) => green.nth_trivias(i)[j].text.clone()
}
self.red().green().text()
}
pub fn children(&self) -> Vec<SyntaxNode> {
let mut res = Vec::new();
let red = self.red();
let green = red.green();
if green.is_leaf() || self.trivia_pos.is_some() {
return Vec::new();
}
for (j, _) in green.nth_trivias(0).iter().enumerate() {
res.push(SyntaxNode {
root: self.root.clone(),
red: Ptr::clone(&self.red),
trivia_pos: Some((0, j)),
})
}
let n_children = red.n_children();
let mut res = Vec::with_capacity(n_children);
for i in 0..n_children {
res.push(SyntaxNode {
root: self.root.clone(),
red: Ptr::new(&red.nth_child(Ptr::clone(&self.red), i)),
trivia_pos: None,
});
for (j, _) in green.nth_trivias(i + 1).iter().enumerate() {
res.push(SyntaxNode {
root: self.root.clone(),
red: self.red.clone(),
trivia_pos: Some((i + 1, j)),
})
}
}
res
}