From 50132db4c676a7dac105dba7fa966edafaa1d209 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 7 Jan 2018 10:10:35 +0300 Subject: Store syntax errors --- src/tree/file_builder.rs | 5 +++- src/tree/mod.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 6 deletions(-) (limited to 'src/tree') diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs index da8b8f824..83aa4186f 100644 --- a/src/tree/file_builder.rs +++ b/src/tree/file_builder.rs @@ -1,5 +1,5 @@ use {SyntaxKind, TextUnit, TextRange}; -use super::{NodeData, NodeIdx, File}; +use super::{NodeData, SyntaxErrorData, NodeIdx, File}; pub trait Sink { fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); @@ -11,6 +11,7 @@ pub trait Sink { pub struct FileBuilder { text: String, nodes: Vec, + errors: Vec, in_progress: Vec<(NodeIdx, Option)>, // (parent, last_child) pos: TextUnit, } @@ -58,6 +59,7 @@ impl FileBuilder { FileBuilder { text, nodes: Vec::new(), + errors: Vec::new(), in_progress: Vec::new(), pos: TextUnit::new(0), } @@ -75,6 +77,7 @@ impl FileBuilder { File { text: self.text, nodes: self.nodes, + errors: self.errors, } } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 7a5d429a3..00d33cbc7 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -36,6 +36,7 @@ pub struct Token { pub struct File { text: String, nodes: Vec, + errors: Vec, } impl File { @@ -72,6 +73,14 @@ impl<'f> Node<'f> { Children { next: self.as_node(self.data().first_child) } } + pub fn SyntaxErrors(&self) -> SyntaxErrors<'f> { + let pos = self.file.errors.iter().position(|e| e.node == self.idx); + let next = pos + .map(|i| ErrorIdx(i as u32)) + .map(|idx| SyntaxError { file: self.file, idx }); + SyntaxErrors { next } + } + fn data(&self) -> &'f NodeData { &self.file.nodes[self.idx] } @@ -81,7 +90,41 @@ impl<'f> Node<'f> { } } +impl<'f> fmt::Debug for Node<'f> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}@{:?}", self.kind(), self.range()) + } +} +#[derive(Clone, Copy)] +pub struct SyntaxError<'f> { + file: &'f File, + idx: ErrorIdx, +} + +impl<'f> SyntaxError<'f> { + pub fn message(&self) -> &'f str { + self.data().message.as_str() + } + + fn data(&self) -> &'f SyntaxErrorData { + &self.file.errors[self.idx] + } + + fn next(&self) -> Option> { + if self.file.errors.len() == self.idx.0 as usize { + return None; + } + let result = SyntaxError { + file: self.file, + idx: ErrorIdx(self.idx.0 + 1) + }; + if result.data().node != self.data().node { + return None; + } + Some(result) + } +} pub struct Children<'f> { next: Option>, @@ -97,7 +140,22 @@ impl<'f> Iterator for Children<'f> { } } -#[derive(Clone, Copy)] +pub struct SyntaxErrors<'f> { + next: Option>, +} + +impl<'f> Iterator for SyntaxErrors<'f> { + type Item = SyntaxError<'f>; + + fn next(&mut self) -> Option> { + let next = self.next; + self.next = next.as_ref().and_then(SyntaxError::next); + next + } +} + + +#[derive(Clone, Copy, PartialEq, Eq)] struct NodeIdx(u32); struct NodeData { @@ -122,8 +180,18 @@ impl ::std::ops::IndexMut for Vec { } } -impl<'f> fmt::Debug for Node<'f> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}@{:?}", self.kind(), self.range()) +#[derive(Clone, Copy)] +struct ErrorIdx(u32); + +struct SyntaxErrorData { + node: NodeIdx, + message: String, +} + +impl ::std::ops::Index for Vec { + type Output = SyntaxErrorData; + + fn index(&self, ErrorIdx(idx): ErrorIdx) -> &SyntaxErrorData { + &self[idx as usize] } -} \ No newline at end of file +} -- cgit v1.2.3