mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Owned&Borrowed nodes
HOLLY COW, UNLIKE C++, WE CAN BE GENERIC WRT OWNERSHIP/BORROWING, SO WE CAN BOTH MAKE SYNTAX NODES OWNED (WHICH IS CONVENIENT) AND BORROWED (WHICH IS CONVENIENT FOR LOCAL PROCESSING, BC YOU DON'T NEED TO BUMP REFCOUNTS).
This commit is contained in:
parent
83acbc06bd
commit
ae849cf134
@ -27,7 +27,7 @@ mod syntax_kinds;
|
||||
pub use {
|
||||
text_unit::{TextRange, TextUnit},
|
||||
syntax_kinds::SyntaxKind,
|
||||
yellow::{SyntaxNode},
|
||||
yellow::{SyntaxNode, SyntaxNodeRef},
|
||||
lexer::{tokenize, Token},
|
||||
};
|
||||
|
||||
@ -48,16 +48,17 @@ pub mod utils {
|
||||
collections::BTreeSet
|
||||
};
|
||||
|
||||
use {SyntaxNode, SyntaxError};
|
||||
use {SyntaxNode, SyntaxNodeRef, SyntaxError};
|
||||
|
||||
/// Parse a file and create a string representation of the resulting parse tree.
|
||||
pub fn dump_tree_green(syntax: &SyntaxNode) -> String {
|
||||
let syntax = syntax.borrow();
|
||||
let mut errors: BTreeSet<_> = syntax.root.errors.iter().cloned().collect();
|
||||
let mut result = String::new();
|
||||
go(syntax, &mut result, 0, &mut errors);
|
||||
return result;
|
||||
|
||||
fn go(node: &SyntaxNode, buff: &mut String, level: usize, errors: &mut BTreeSet<SyntaxError>) {
|
||||
fn go(node: SyntaxNodeRef, buff: &mut String, level: usize, errors: &mut BTreeSet<SyntaxError>) {
|
||||
buff.push_str(&String::from(" ").repeat(level));
|
||||
write!(buff, "{:?}\n", node).unwrap();
|
||||
let my_errors: Vec<_> = errors.iter().filter(|e| e.offset == node.range().start())
|
||||
@ -68,7 +69,7 @@ pub mod utils {
|
||||
write!(buff, "err: `{}`\n", err.message).unwrap();
|
||||
}
|
||||
|
||||
for child in node.children().iter() {
|
||||
for child in node.children() {
|
||||
go(child, buff, level + 1, errors)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use {
|
||||
SyntaxKind, TextRange, TextUnit,
|
||||
yellow::{SyntaxNode, GreenNode, GreenNodeBuilder, SyntaxError},
|
||||
yellow::{SyntaxNode, SyntaxRoot, GreenNode, GreenNodeBuilder, SyntaxError},
|
||||
parser::Sink
|
||||
};
|
||||
|
||||
@ -57,7 +57,8 @@ impl Sink for GreenBuilder {
|
||||
}
|
||||
|
||||
fn finish(self) -> SyntaxNode {
|
||||
SyntaxNode::new(self.root.unwrap(), self.errors)
|
||||
let root = SyntaxRoot::new(self.root.unwrap(), self.errors);
|
||||
SyntaxNode::new_owned(root)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ mod builder;
|
||||
pub(crate) use self::{
|
||||
green::{GreenNode, GreenNodeBuilder},
|
||||
red::RedNode,
|
||||
syntax::SyntaxError,
|
||||
syntax::{SyntaxError, SyntaxRoot},
|
||||
builder::GreenBuilder,
|
||||
};
|
||||
pub use self::syntax::SyntaxNode;
|
||||
pub use self::syntax::{SyntaxNode, SyntaxNodeRef};
|
||||
|
@ -10,17 +10,28 @@ use {
|
||||
yellow::{RedNode, GreenNode},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SyntaxNode {
|
||||
pub(crate) root: SyntaxRoot,
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SyntaxNode<ROOT: ::std::ops::Deref<Target=SyntaxRoot> + Clone = Arc<SyntaxRoot>> {
|
||||
pub(crate) root: ROOT,
|
||||
// guaranteed to be alive bc SyntaxRoot holds a strong ref
|
||||
red: ptr::NonNull<RedNode>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SyntaxRoot {
|
||||
red: Arc<RedNode>,
|
||||
pub(crate) errors: Arc<Vec<SyntaxError>>,
|
||||
red: RedNode,
|
||||
pub(crate) errors: Vec<SyntaxError>,
|
||||
}
|
||||
|
||||
impl SyntaxRoot {
|
||||
pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot {
|
||||
SyntaxRoot {
|
||||
red: RedNode::new_root(green),
|
||||
errors,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
@ -29,13 +40,21 @@ pub(crate) struct SyntaxError {
|
||||
pub(crate) offset: TextUnit,
|
||||
}
|
||||
|
||||
impl SyntaxNode {
|
||||
pub(crate) fn new(root: GreenNode, errors: Vec<SyntaxError>) -> SyntaxNode {
|
||||
let red = Arc::new(RedNode::new_root(root));
|
||||
let red_weak: ptr::NonNull<RedNode> = (&*red).into();
|
||||
let root = SyntaxRoot { red, errors: Arc::new(errors) };
|
||||
impl SyntaxNode<Arc<SyntaxRoot>> {
|
||||
pub(crate) fn new_owned(root: SyntaxRoot) -> Self {
|
||||
let root = Arc::new(root);
|
||||
let red_weak = ptr::NonNull::from(&root.red);
|
||||
SyntaxNode { root, red: red_weak }
|
||||
}
|
||||
}
|
||||
|
||||
impl<ROOT: ::std::ops::Deref<Target=SyntaxRoot> + Clone> SyntaxNode<ROOT> {
|
||||
pub fn borrow<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> {
|
||||
SyntaxNode {
|
||||
root: &*self.root,
|
||||
red: ptr::NonNull::clone(&self.red),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> SyntaxKind {
|
||||
self.red().green().kind()
|
||||
@ -53,7 +72,7 @@ impl SyntaxNode {
|
||||
self.red().green().text()
|
||||
}
|
||||
|
||||
pub fn children(&self) -> Vec<SyntaxNode> {
|
||||
pub fn children(&self) -> Vec<SyntaxNode<ROOT>> {
|
||||
let red = self.red();
|
||||
let n_children = red.n_children();
|
||||
let mut res = Vec::with_capacity(n_children);
|
||||
@ -71,7 +90,7 @@ impl SyntaxNode {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SyntaxNode {
|
||||
impl<ROOT: ::std::ops::Deref<Target=SyntaxRoot> + Clone> fmt::Debug for SyntaxNode<ROOT> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
|
||||
if has_short_text(self.kind()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user