"drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "smol_str 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rowan 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"test_utils 0.1.0",
- "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "rowan"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smol_str 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.9"
"checksum relative-path 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e614f96449605730b4f7ad2c019e88c1652d730634b4eba07b810801856635e3"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
"checksum ron 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fa11b7a38511d46ff1959ae46ebb60bd8a746f17bdd0206b4c8de7559ac47b"
+"checksum rowan 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4a1a7366ece9deee5e7df8316a136d585d5c5042854c2297f7f1aee3014c9130"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7"
[workspace]
members = [ "crates/*" ]
+exclude = [ "crates/rowan"]
[profile.release]
debug = true
[dependencies]
unicode-xid = "0.1.0"
-text_unit = "0.1.4"
itertools = "0.7.8"
drop_bomb = "0.1.4"
parking_lot = "0.6.0"
-smol_str = "0.1.6"
+rowan = "0.1.0"
[dev-dependencies]
test_utils = { path = "../test_utils" }
use std::marker::PhantomData;
use itertools::Itertools;
-use smol_str::SmolStr;
use {
- SyntaxNodeRef, SyntaxKind::*,
+ SmolStr, SyntaxNodeRef, SyntaxKind::*,
yellow::{RefRoot, SyntaxNodeChildren},
};
pub use self::generated::*;
let tt = self.value()?;
let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?;
if attr.kind() == IDENT {
- Some(attr.leaf_text().unwrap())
+ Some(attr.leaf_text().unwrap().clone())
} else {
None
}
let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?;
let args = TokenTree::cast(args)?;
if attr.kind() == IDENT {
- Some((attr.leaf_text().unwrap(), args))
+ Some((attr.leaf_text().unwrap().clone(), args))
} else {
None
}
impl<'a> Lifetime<'a> {
pub fn text(&self) -> SmolStr {
- self.syntax().leaf_text().unwrap()
+ self.syntax().leaf_text().unwrap().clone()
}
}
pub fn text(&self) -> SmolStr {
let ident = self.syntax().first_child()
.unwrap();
- ident.leaf_text().unwrap()
+ ident.leaf_text().unwrap().clone()
}
}
pub fn text(&self) -> SmolStr {
let ident = self.syntax().first_child()
.unwrap();
- ident.leaf_text().unwrap()
+ ident.leaf_text().unwrap().clone()
}
}
extern crate unicode_xid;
extern crate drop_bomb;
extern crate parking_lot;
-extern crate smol_str;
-extern crate text_unit;
+extern crate rowan;
#[cfg(test)]
#[macro_use]
pub mod text_utils;
pub use {
- text_unit::{TextRange, TextUnit},
- smol_str::SmolStr,
+ rowan::{SmolStr, TextRange, TextUnit},
ast::AstNode,
lexer::{tokenize, Token},
syntax_kinds::SyntaxKind,
};
use {
- yellow::{GreenNode, SyntaxRoot},
+ yellow::{GreenNode},
};
#[derive(Clone, Debug, Hash)]
impl File {
fn new(green: GreenNode, errors: Vec<SyntaxError>) -> File {
- let root = SyntaxRoot::new(green, errors);
- let root = SyntaxNode::new_owned(root);
+ let root = SyntaxNode::new(green, errors);
if cfg!(debug_assertions) {
utils::validate_block_structure(root.borrowed());
}
self.root.borrowed()
}
pub fn errors(&self) -> Vec<SyntaxError> {
- self.syntax().root.syntax_root().errors.clone()
+ self.root.root_data().clone()
}
}
use algo;
use grammar;
use lexer::{tokenize, Token};
-use text_unit::{TextRange, TextUnit};
-use yellow::{self, SyntaxNodeRef, GreenNode, SyntaxError};
+use yellow::{self, GreenNode, SyntaxNodeRef, SyntaxError};
use parser_impl;
use parser_api::Parser;
use {
+ TextUnit, TextRange,
SyntaxKind::*,
};
use text_utils::replace_range;
return None;
}
- let green = GreenNode::new_leaf(node.kind(), &text);
+ let green = GreenNode::new_leaf(node.kind(), text.into());
let new_errors = vec![];
Some((node, green, new_errors))
}
}
", "Clone");
}
-}
\ No newline at end of file
+}
use std::fmt::Write;
use {
algo::walk::{preorder, walk, WalkEvent},
- SyntaxKind, File, SyntaxNodeRef, TreeRoot,
+ SyntaxKind, File, SyntaxNodeRef
};
/// Parse a file and create a string representation of the resulting parse tree.
pub fn dump_tree(syntax: SyntaxNodeRef) -> String {
- let mut errors: Vec<_> = syntax.root.syntax_root().errors.iter().cloned().collect();
+ let mut errors: Vec<_> = syntax.root_data().iter().cloned().collect();
errors.sort_by_key(|e| e.offset);
let mut err_pos = 0;
let mut level = 0;
+use rowan::GreenNodeBuilder;
use {
parser_impl::Sink,
- yellow::{GreenNode, SyntaxError},
+ yellow::{GreenNode, SyntaxError, RaTypes},
SyntaxKind, TextRange, TextUnit,
};
pub(crate) struct GreenBuilder<'a> {
text: &'a str,
- parents: Vec<(SyntaxKind, usize)>,
- children: Vec<GreenNode>,
pos: TextUnit,
errors: Vec<SyntaxError>,
+ inner: GreenNodeBuilder<RaTypes>,
}
impl<'a> Sink<'a> for GreenBuilder<'a> {
fn new(text: &'a str) -> Self {
GreenBuilder {
text,
- parents: Vec::new(),
- children: Vec::new(),
pos: 0.into(),
errors: Vec::new(),
+ inner: GreenNodeBuilder::new(),
}
}
fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
let range = TextRange::offset_len(self.pos, len);
self.pos += len;
- let text = &self.text[range];
- self.children.push(
- GreenNode::new_leaf(kind, text)
- );
+ let text = self.text[range].into();
+ self.inner.leaf(kind, text);
}
fn start_internal(&mut self, kind: SyntaxKind) {
- let len = self.children.len();
- self.parents.push((kind, len));
+ self.inner.start_internal(kind)
}
fn finish_internal(&mut self) {
- let (kind, first_child) = self.parents.pop().unwrap();
- let children: Vec<_> = self.children
- .drain(first_child..)
- .collect();
- self.children.push(
- GreenNode::new_branch(kind, children.into_boxed_slice())
- );
+ self.inner.finish_internal();
}
fn error(&mut self, message: String) {
})
}
- fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) {
- assert_eq!(self.children.len(), 1);
- let root = self.children.pop().unwrap();
- (root, self.errors)
+ fn finish(self) -> (GreenNode, Vec<SyntaxError>) {
+ (self.inner.finish(), self.errors)
}
}
+++ /dev/null
-use std::sync::Arc;
-
-use smol_str::SmolStr;
-
-use {SyntaxKind, TextUnit};
-
-#[derive(Clone, Debug)]
-pub(crate) enum GreenNode {
- Leaf {
- kind: SyntaxKind,
- text: SmolStr,
- },
- Branch(Arc<GreenBranch>),
-}
-
-impl GreenNode {
- pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode {
- GreenNode::Leaf { kind, text: SmolStr::new(text) }
- }
-
- pub(crate) fn new_branch(kind: SyntaxKind, children: Box<[GreenNode]>) -> GreenNode {
- GreenNode::Branch(Arc::new(GreenBranch::new(kind, children)))
- }
-
- pub fn kind(&self) -> SyntaxKind {
- match self {
- GreenNode::Leaf { kind, .. } => *kind,
- GreenNode::Branch(b) => b.kind(),
- }
- }
-
- pub fn text_len(&self) -> TextUnit {
- match self {
- GreenNode::Leaf { text, .. } => TextUnit::from(text.len() as u32),
- GreenNode::Branch(b) => b.text_len(),
- }
- }
-
- pub fn children(&self) -> &[GreenNode] {
- match self {
- GreenNode::Leaf { .. } => &[],
- GreenNode::Branch(b) => b.children(),
- }
- }
-
- pub fn leaf_text_ref(&self) -> Option<&SmolStr> {
- match self {
- GreenNode::Leaf { text, .. } => Some(text),
- GreenNode::Branch(_) => None,
- }
- }
-}
-
-#[derive(Clone, Debug)]
-pub(crate) struct GreenBranch {
- text_len: TextUnit,
- kind: SyntaxKind,
- children: Box<[GreenNode]>,
-}
-
-impl GreenBranch {
- fn new(kind: SyntaxKind, children: Box<[GreenNode]>) -> GreenBranch {
- let text_len = children.iter().map(|x| x.text_len()).sum::<TextUnit>();
- GreenBranch {
- text_len,
- kind,
- children,
- }
- }
-
- pub fn kind(&self) -> SyntaxKind {
- self.kind
- }
-
- pub fn text_len(&self) -> TextUnit {
- self.text_len
- }
-
- pub fn children(&self) -> &[GreenNode] {
- &*self.children
- }
-}
-
-#[test]
-fn test_sizes() {
- use std::mem::size_of;
- println!("GreenBranch = {}", size_of::<GreenBranch>());
- println!("GreenNode = {}", size_of::<GreenNode>());
- println!("SmolStr = {}", size_of::<SmolStr>());
-}
mod builder;
-mod green;
-mod red;
-mod syntax;
mod syntax_text;
use std::{
- sync::Arc,
- ptr,
-};
-pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError, SyntaxNodeChildren};
-pub(crate) use self::{
- builder::GreenBuilder,
- green::GreenNode,
- red::RedNode,
- syntax_text::SyntaxText,
+ fmt,
+ hash::{Hash, Hasher},
};
+use rowan::Types;
+use {SyntaxKind, TextUnit, TextRange, SmolStr};
+use self::syntax_text::SyntaxText;
-#[derive(Debug)]
-pub struct SyntaxRoot {
- red: RedNode,
- pub(crate) errors: Vec<SyntaxError>,
+pub use rowan::{TreeRoot};
+pub(crate) use self::builder::GreenBuilder;
+
+#[derive(Debug, Clone, Copy)]
+pub enum RaTypes {}
+impl Types for RaTypes {
+ type Kind = SyntaxKind;
+ type RootData = Vec<SyntaxError>;
}
-pub trait TreeRoot: Clone + Send + Sync {
- fn borrowed(&self) -> RefRoot;
- fn owned(&self) -> OwnedRoot;
+pub type OwnedRoot = ::rowan::OwnedRoot<RaTypes>;
+pub type RefRoot<'a> = ::rowan::RefRoot<'a, RaTypes>;
+
+pub type GreenNode = ::rowan::GreenNode<RaTypes>;
- #[doc(hidden)]
- fn syntax_root(&self) -> &SyntaxRoot;
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
+pub struct SyntaxError {
+ pub msg: String,
+ pub offset: TextUnit,
}
-#[derive(Clone, Debug)]
-pub struct OwnedRoot(Arc<SyntaxRoot>);
-#[derive(Clone, Copy, Debug)]
-pub struct RefRoot<'a>(&'a OwnedRoot); // TODO: shared_from_this instead of double indirection
-impl<'a> RefRoot<'a> {
- fn syntax_root(&self) -> &'a SyntaxRoot {
- self.0.syntax_root()
+#[derive(Clone, Copy)]
+pub struct SyntaxNode<R: TreeRoot<RaTypes> = OwnedRoot>(
+ ::rowan::SyntaxNode<RaTypes, R>,
+);
+pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>;
+
+impl<R1, R2> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2>
+where
+ R1: TreeRoot<RaTypes>,
+ R2: TreeRoot<RaTypes>,
+{
+ fn eq(&self, other: &SyntaxNode<R1>) -> bool {
+ self.0 == other.0
}
}
-impl TreeRoot for OwnedRoot {
- fn borrowed(&self) -> RefRoot {
- RefRoot(&self)
- }
- fn owned(&self) -> OwnedRoot {
- self.clone()
+impl<R: TreeRoot<RaTypes>> Eq for SyntaxNode<R> {}
+impl<R: TreeRoot<RaTypes>> Hash for SyntaxNode<R> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.0.hash(state)
}
+}
- fn syntax_root(&self) -> &SyntaxRoot {
- &*self.0
+impl SyntaxNode<OwnedRoot> {
+ pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxNode {
+ SyntaxNode(::rowan::SyntaxNode::new(green, errors))
+ }
+}
+impl<'a> SyntaxNode<RefRoot<'a>> {
+ pub fn leaf_text(self) -> Option<&'a SmolStr> {
+ self.0.leaf_text()
}
}
-impl<'a> TreeRoot for RefRoot<'a> {
- fn borrowed(&self) -> RefRoot {
- *self
+impl<R: TreeRoot<RaTypes>> SyntaxNode<R> {
+ pub(crate) fn root_data(&self) -> &Vec<SyntaxError> {
+ self.0.root_data()
+ }
+ pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
+ self.0.replace_with(replacement)
+ }
+ pub fn borrowed<'a>(&'a self) -> SyntaxNode<RefRoot<'a>> {
+ SyntaxNode(self.0.borrowed())
+ }
+ pub fn owned(&self) -> SyntaxNode<OwnedRoot> {
+ SyntaxNode(self.0.owned())
+ }
+ pub fn kind(&self) -> SyntaxKind {
+ self.0.kind()
}
- fn owned(&self) -> OwnedRoot {
- self.0.clone()
+ pub fn range(&self) -> TextRange {
+ self.0.range()
}
- fn syntax_root(&self) -> &SyntaxRoot {
- self.0.syntax_root()
+ pub fn text(&self) -> SyntaxText {
+ SyntaxText::new(self.borrowed())
+ }
+ pub fn is_leaf(&self) -> bool {
+ self.0.is_leaf()
+ }
+ pub fn parent(&self) -> Option<SyntaxNode<R>> {
+ self.0.parent().map(SyntaxNode)
+ }
+ pub fn first_child(&self) -> Option<SyntaxNode<R>> {
+ self.0.first_child().map(SyntaxNode)
+ }
+ pub fn last_child(&self) -> Option<SyntaxNode<R>> {
+ self.0.last_child().map(SyntaxNode)
+ }
+ pub fn next_sibling(&self) -> Option<SyntaxNode<R>> {
+ self.0.next_sibling().map(SyntaxNode)
+ }
+ pub fn prev_sibling(&self) -> Option<SyntaxNode<R>> {
+ self.0.prev_sibling().map(SyntaxNode)
+ }
+ pub fn children(&self) -> SyntaxNodeChildren<R> {
+ SyntaxNodeChildren(self.0.children())
}
}
-impl SyntaxRoot {
- pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot {
- SyntaxRoot {
- red: RedNode::new_root(green),
- errors,
+impl<R: TreeRoot<RaTypes>> fmt::Debug for SyntaxNode<R> {
+ 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(())
}
}
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
-pub(crate) struct RedPtr(ptr::NonNull<RedNode>);
-
-unsafe impl Send for RedPtr {}
-
-unsafe impl Sync for RedPtr {}
+#[derive(Debug)]
+pub struct SyntaxNodeChildren<R: TreeRoot<RaTypes>>(
+ ::rowan::SyntaxNodeChildren<RaTypes, R>
+);
-impl RedPtr {
- fn new(red: &RedNode) -> RedPtr {
- RedPtr(red.into())
- }
+impl<R: TreeRoot<RaTypes>> Iterator for SyntaxNodeChildren<R> {
+ type Item = SyntaxNode<R>;
- unsafe fn get<'a>(self, _root: &'a SyntaxRoot) -> &'a RedNode {
- &*self.0.as_ptr()
+ fn next(&mut self) -> Option<SyntaxNode<R>> {
+ self.0.next().map(SyntaxNode)
}
}
-#[test]
-fn assert_send_sync() {
- fn f<T: Send + Sync>() {}
- f::<GreenNode>();
- f::<RedNode>();
- f::<SyntaxNode>();
+
+fn has_short_text(kind: SyntaxKind) -> bool {
+ use SyntaxKind::*;
+ match kind {
+ IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,
+ _ => false,
+ }
}
+++ /dev/null
-use parking_lot::RwLock;
-use {yellow::{GreenNode, RedPtr}, TextUnit};
-
-#[derive(Debug)]
-pub(crate) struct RedNode {
- green: GreenNode,
- parent: Option<ParentData>,
- children: RwLock<Box<[RedChild]>>,
-}
-
-#[derive(Debug)]
-enum RedChild {
- Zigot(TextUnit),
- Child(RedNode)
-}
-
-impl RedChild {
- fn set(&mut self, node: RedNode) -> &RedNode {
- match self {
- RedChild::Child(node) => return node,
- RedChild::Zigot(_) => {
- *self = RedChild::Child(node);
- match self {
- RedChild::Child(node) => return node,
- RedChild::Zigot(_) => unreachable!()
- }
- }
- }
- }
-}
-
-#[derive(Debug)]
-struct ParentData {
- parent: RedPtr,
- start_offset: TextUnit,
- index_in_parent: usize,
-}
-
-impl RedNode {
- pub fn new_root(green: GreenNode) -> RedNode {
- RedNode::new(green, None)
- }
-
- fn new_child(
- green: GreenNode,
- parent: RedPtr,
- start_offset: TextUnit,
- index_in_parent: usize,
- ) -> RedNode {
- let parent_data = ParentData {
- parent,
- start_offset,
- index_in_parent,
- };
- RedNode::new(green, Some(parent_data))
- }
-
- fn new(green: GreenNode, parent: Option<ParentData>) -> RedNode {
- let mut start_offset = parent.as_ref().map(|it| it.start_offset).unwrap_or(0.into());
- let children = green.children()
- .iter()
- .map(|child| {
- let off = start_offset;
- start_offset += child.text_len();
- RedChild::Zigot(off)
- })
- .collect::<Vec<_>>()
- .into_boxed_slice();
- RedNode {
- green,
- parent,
- children: RwLock::new(children),
- }
- }
-
- pub(crate) fn green(&self) -> &GreenNode {
- &self.green
- }
-
- pub(crate) fn start_offset(&self) -> TextUnit {
- match &self.parent {
- None => 0.into(),
- Some(p) => p.start_offset,
- }
- }
-
- pub(crate) fn n_children(&self) -> usize {
- self.green.children().len()
- }
-
- pub(crate) fn get_child(&self, idx: usize) -> Option<RedPtr> {
- if idx >= self.n_children() {
- return None;
- }
- let start_offset = match &self.children.read()[idx] {
- RedChild::Child(child) => return Some(RedPtr::new(child)),
- RedChild::Zigot(start_offset) => *start_offset,
- };
- let green_children = self.green.children();
- let child =
- RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx);
- let mut children = self.children.write();
- let child = children[idx].set(child);
- Some(RedPtr::new(child))
- }
-
- pub(crate) fn parent(&self) -> Option<RedPtr> {
- Some(self.parent.as_ref()?.parent)
- }
- pub(crate) fn index_in_parent(&self) -> Option<usize> {
- Some(self.parent.as_ref()?.index_in_parent)
- }
-}
+++ /dev/null
-use std::{
- fmt, sync::Arc,
- hash::{Hasher, Hash},
- ops::Range,
-};
-
-use smol_str::SmolStr;
-
-use {
- yellow::{GreenNode, RedNode, TreeRoot, SyntaxRoot, RedPtr, RefRoot, OwnedRoot, SyntaxText},
- SyntaxKind::{self, *},
- TextRange, TextUnit,
-};
-
-
-#[derive(Clone, Copy)]
-pub struct SyntaxNode<R: TreeRoot = OwnedRoot> {
- pub(crate) root: R,
- // Guaranteed to not dangle, because `root` holds a
- // strong reference to red's ancestor
- red: RedPtr,
-}
-
-unsafe impl<R: TreeRoot> Send for SyntaxNode<R> {}
-unsafe impl<R: TreeRoot> Sync for SyntaxNode<R> {}
-
-impl<R1: TreeRoot, R2: TreeRoot> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> {
- fn eq(&self, other: &SyntaxNode<R1>) -> bool {
- self.red == other.red
- }
-}
-
-impl<R: TreeRoot> Eq for SyntaxNode<R> {}
-impl<R: TreeRoot> Hash for SyntaxNode<R> {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.red.hash(state)
- }
-}
-
-pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>;
-
-#[test]
-fn syntax_node_ref_is_copy() {
- fn assert_copy<T: Copy>(){}
- assert_copy::<SyntaxNodeRef>()
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
-pub struct SyntaxError {
- pub msg: String,
- pub offset: TextUnit,
-}
-
-impl SyntaxNode<OwnedRoot> {
- pub(crate) fn new_owned(root: SyntaxRoot) -> Self {
- let root = OwnedRoot(Arc::new(root));
- let red = RedPtr::new(&root.syntax_root().red);
- SyntaxNode { root, red }
- }
-}
-
-impl<'a> SyntaxNode<RefRoot<'a>> {
- pub(crate) fn leaf_text_ref(self) -> Option<&'a SmolStr> {
- let red = unsafe { self.red.get(self.root.syntax_root()) };
- red.green().leaf_text_ref()
- }
-}
-
-impl<R: TreeRoot> SyntaxNode<R> {
- pub fn borrowed<'a>(&'a self) -> SyntaxNodeRef<'a> {
- SyntaxNode {
- root: self.root.borrowed(),
- red: self.red,
- }
- }
-
- pub fn owned(&self) -> SyntaxNode {
- SyntaxNode {
- root: self.root.owned(),
- 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) -> SyntaxText {
- SyntaxText::new(self.borrowed())
- }
-
- pub fn children(&self) -> SyntaxNodeChildren<R> {
- SyntaxNodeChildren {
- parent: self.clone(),
- iter: (0..self.red().n_children())
- }
- }
-
- pub fn parent(&self) -> Option<SyntaxNode<R>> {
- let parent = self.red().parent()?;
- Some(SyntaxNode {
- root: self.root.clone(),
- red: parent,
- })
- }
-
- pub fn first_child(&self) -> Option<SyntaxNode<R>> {
- let red = self.red().get_child(0)?;
- Some(SyntaxNode { root: self.root.clone(), red })
- }
-
- pub fn last_child(&self) -> Option<SyntaxNode<R>> {
- let n = self.red().n_children();
- let n = n.checked_sub(1)?;
- let red = self.red().get_child(n)?;
- Some(SyntaxNode { root: self.root.clone(), red })
- }
-
- pub fn next_sibling(&self) -> Option<SyntaxNode<R>> {
- 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 prev_sibling(&self) -> Option<SyntaxNode<R>> {
- let red = self.red();
- let parent = self.parent()?;
- let prev_sibling_idx = red.index_in_parent()?.checked_sub(1)?;
- let sibling_red = parent.red().get_child(prev_sibling_idx)?;
- Some(SyntaxNode {
- root: self.root.clone(),
- red: sibling_red,
- })
- }
-
- pub fn is_leaf(&self) -> bool {
- self.first_child().is_none()
- }
-
- pub fn leaf_text(&self) -> Option<SmolStr> {
- self.borrowed().leaf_text_ref().map(|it| it.clone())
- }
-
- pub(crate) fn replace_with(&self, green: GreenNode) -> GreenNode {
- assert_eq!(self.kind(), green.kind());
- match self.parent() {
- None => green,
- Some(parent) => {
- let children: Vec<_> = parent.children().map(|child| {
- if child == *self {
- green.clone()
- } else {
- child.red().green().clone()
- }
- }).collect();
- let new_parent = GreenNode::new_branch(
- parent.kind(),
- children.into_boxed_slice(),
- );
- parent.replace_with(new_parent)
- },
- }
- }
-
- fn red(&self) -> &RedNode {
- unsafe { self.red.get(self.root.syntax_root()) }
- }
-}
-
-impl<R: TreeRoot> fmt::Debug for SyntaxNode<R> {
- 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(())
- }
-}
-
-#[derive(Debug)]
-pub struct SyntaxNodeChildren<R: TreeRoot> {
- parent: SyntaxNode<R>,
- iter: Range<usize>,
-}
-
-impl<R: TreeRoot> Iterator for SyntaxNodeChildren<R> {
- type Item = SyntaxNode<R>;
-
- fn next(&mut self) -> Option<SyntaxNode<R>> {
- self.iter.next().map(|i| {
- let red = self.parent.red();
- SyntaxNode {
- root: self.parent.root.clone(),
- red: red.get_child(i).unwrap(),
- }
- })
- }
-}
-
-fn has_short_text(kind: SyntaxKind) -> bool {
- match kind {
- IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,
- _ => false,
- }
-}
let range = self.range;
preorder(self.node)
.filter_map(move |node| {
- let text = node.leaf_text_ref()?;
+ let text = node.leaf_text()?;
let range = intersect(range, node.range())?;
let range = range - node.range().start();
Some(&text[range])