From 7c67612b8a894187fa3b64725531a5459f9211bf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Aug 2018 22:33:29 +0300 Subject: organizize --- crates/libsyntax2/src/yellow/syntax.rs | 122 +++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 crates/libsyntax2/src/yellow/syntax.rs (limited to 'crates/libsyntax2/src/yellow/syntax.rs') diff --git a/crates/libsyntax2/src/yellow/syntax.rs b/crates/libsyntax2/src/yellow/syntax.rs new file mode 100644 index 000000000..6e33310f1 --- /dev/null +++ b/crates/libsyntax2/src/yellow/syntax.rs @@ -0,0 +1,122 @@ +use std::{fmt, sync::Arc}; + +use { + yellow::{RedNode, TreeRoot, SyntaxRoot, RedPtr}, + SyntaxKind::{self, *}, + TextRange, TextUnit, +}; + + +#[derive(Clone, Copy)] +pub struct SyntaxNode> { + pub(crate) root: R, + // Guaranteed to not dangle, because `root` holds a + // strong reference to red's ancestor + red: RedPtr, +} + +unsafe impl Send for SyntaxNode {} +unsafe impl Sync for SyntaxNode {} + +impl PartialEq> for SyntaxNode { + fn eq(&self, other: &SyntaxNode) -> bool { + self.red == other.red + } +} + +impl Eq for SyntaxNode {} + +pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] +pub struct SyntaxError { + pub msg: String, + pub offset: TextUnit, +} + +impl SyntaxNode> { + pub(crate) fn new_owned(root: SyntaxRoot) -> Self { + let root = Arc::new(root); + let red = RedPtr::new(&root.red); + SyntaxNode { root, red } + } +} + +impl SyntaxNode { + pub fn as_ref<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> { + SyntaxNode { + root: &*self.root, + red: self.red, + } + } + + pub fn kind(&self) -> SyntaxKind { + self.red().green().kind() + } + + pub fn range(&self) -> TextRange { + let red = self.red(); + TextRange::offset_len(red.start_offset(), red.green().text_len()) + } + + pub fn text(&self) -> String { + self.red().green().text() + } + + pub fn children<'a>(&'a self) -> impl Iterator> + 'a { + let red = self.red(); + let n_children = red.n_children(); + (0..n_children).map(move |i| SyntaxNode { + root: self.root.clone(), + red: red.get_child(i).unwrap(), + }) + } + + pub fn parent(&self) -> Option> { + let parent = self.red().parent()?; + Some(SyntaxNode { + root: self.root.clone(), + red: parent, + }) + } + + pub fn first_child(&self) -> Option> { + self.children().next() + } + + pub fn next_sibling(&self) -> Option> { + let red = self.red(); + let parent = self.parent()?; + let next_sibling_idx = red.index_in_parent()? + 1; + let sibling_red = parent.red().get_child(next_sibling_idx)?; + Some(SyntaxNode { + root: self.root.clone(), + red: sibling_red, + }) + } + + pub fn is_leaf(&self) -> bool { + self.first_child().is_none() + } + + fn red(&self) -> &RedNode { + unsafe { self.red.get(&self.root) } + } +} + +impl fmt::Debug for SyntaxNode { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; + if has_short_text(self.kind()) { + write!(fmt, " \"{}\"", self.text())?; + } + Ok(()) + } +} + +fn has_short_text(kind: SyntaxKind) -> bool { + match kind { + IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, + _ => false, + } +} -- cgit v1.2.3