Skip to content

Commit

Permalink
Merge #81
Browse files Browse the repository at this point in the history
81: Store relative offsets in green nodes r=matklad a=matklad

bors r+

Co-authored-by: Aleksey Kladov <[email protected]>
  • Loading branch information
bors[bot] and matklad authored Jan 15, 2021
2 parents 5cf7c24 + 52af0db commit 7a86fe3
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 279 deletions.
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
[package]
name = "rowan"
version = "0.10.0"
version = "0.10.1"
authors = ["Aleksey Kladov <[email protected]>"]
repository = "https://github.com/rust-analyzer/rowan"
license = "MIT OR Apache-2.0"
description = "Library for generic lossless syntax trees"
edition = "2018"

[dependencies]
erasable = "1.2.1"
rustc-hash = "1.0.1"
serde = { version = "1.0.89", optional = true, default-features = false }
slice-dst = "1.4.1"
smol_str = "0.1.10"
text-size = "1.0.0"
text-size = "1.1.0"
triomphe = "0.1.1"

serde = { version = "1.0.89", optional = true, default-features = false }

[dev-dependencies]
m_lexer = "0.0.4"
Expand Down
24 changes: 24 additions & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ impl<L: Language> SyntaxNode<L> {
pub fn new_root(green: GreenNode) -> SyntaxNode<L> {
SyntaxNode::from(cursor::SyntaxNode::new_root(green))
}
/// Returns a green tree, equal to the green tree this node
/// belongs two, except with this node substitute. The complexity
/// of operation is proportional to the depth of the tree
pub fn replace_with(&self, replacement: GreenNode) -> GreenNode {
self.raw.replace_with(replacement)
}
Expand Down Expand Up @@ -217,10 +220,12 @@ impl<L: Language> SyntaxNode<L> {
self.raw.prev_sibling_or_token().map(NodeOrToken::from)
}

/// Return the leftmost token in the subtree of this node.
pub fn first_token(&self) -> Option<SyntaxToken<L>> {
self.raw.first_token().map(SyntaxToken::from)
}

/// Return the rightmost token in the subtree of this node.
pub fn last_token(&self) -> Option<SyntaxToken<L>> {
self.raw.last_token().map(SyntaxToken::from)
}
Expand All @@ -244,24 +249,41 @@ impl<L: Language> SyntaxNode<L> {
self.raw.descendants_with_tokens().map(NodeOrToken::from)
}

/// Traverse the subtree rooted at the current node (including the current
/// node) in preorder, excluding tokens.
pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<SyntaxNode<L>>> {
self.raw.preorder().map(|event| event.map(SyntaxNode::from))
}

/// Traverse the subtree rooted at the current node (including the current
/// node) in preorder, including tokens.
pub fn preorder_with_tokens(&self) -> impl Iterator<Item = WalkEvent<SyntaxElement<L>>> {
self.raw.preorder_with_tokens().map(|event| event.map(NodeOrToken::from))
}

/// Find a token in the subtree corresponding to this node, which covers the offset.
/// Precondition: offset must be withing node's range.
pub fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken<L>> {
self.raw.token_at_offset(offset).map(SyntaxToken::from)
}

/// Return the deepest node or token in the current subtree that fully
/// contains the range. If the range is empty and is contained in two leaf
/// nodes, either one can be returned. Precondition: range must be contained
/// withing the current node
pub fn covering_element(&self, range: TextRange) -> SyntaxElement<L> {
NodeOrToken::from(self.raw.covering_element(range))
}

pub fn child_or_token_at_range(&self, range: TextRange) -> Option<SyntaxElement<L>> {
self.raw.child_or_token_at_range(range).map(SyntaxElement::from)
}
}

impl<L: Language> SyntaxToken<L> {
/// Returns a green tree, equal to the green tree this token
/// belongs two, except with this token substitute. The complexity
/// of operation is proportional to the depth of the tree
pub fn replace_with(&self, new_token: GreenToken) -> GreenNode {
self.raw.replace_with(new_token)
}
Expand Down Expand Up @@ -305,10 +327,12 @@ impl<L: Language> SyntaxToken<L> {
self.raw.siblings_with_tokens(direction).map(SyntaxElement::from)
}

/// Next token in the tree (i.e, not necessary a sibling).
pub fn next_token(&self) -> Option<SyntaxToken<L>> {
self.raw.next_token().map(SyntaxToken::from)
}

/// Previous token in the tree (i.e, not necessary a sibling).
pub fn prev_token(&self) -> Option<SyntaxToken<L>> {
self.raw.prev_token().map(SyntaxToken::from)
}
Expand Down
60 changes: 22 additions & 38 deletions src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,23 +209,12 @@ impl SyntaxNode {
SyntaxNode::new(data)
}

/// Returns a green tree, equal to the green tree this node
/// belongs two, except with this node substitute. The complexity
/// of operation is proportional to the depth of the tree
pub fn replace_with(&self, replacement: GreenNode) -> GreenNode {
assert_eq!(self.kind(), replacement.kind());
match self.0.kind.as_child() {
None => replacement,
Some((parent, me, _offset)) => {
let mut replacement = Some(replacement);
let children = parent.green().children().enumerate().map(|(i, child)| {
if i as u32 == me {
replacement.take().unwrap().into()
} else {
child.cloned()
}
});
let new_parent = GreenNode::new(parent.kind(), children);
let new_parent = parent.green().replace_child(me as usize, replacement.into());
parent.replace_with(new_parent)
}
}
Expand Down Expand Up @@ -342,13 +331,11 @@ impl SyntaxNode {
Some(SyntaxElement::new(element, parent.clone(), index as u32, offset))
}

/// Return the leftmost token in the subtree of this node
#[inline]
pub fn first_token(&self) -> Option<SyntaxToken> {
self.first_child_or_token()?.first_token()
}

/// Return the rightmost token in the subtree of this node
#[inline]
pub fn last_token(&self) -> Option<SyntaxToken> {
self.last_child_or_token()?.last_token()
Expand Down Expand Up @@ -386,8 +373,6 @@ impl SyntaxNode {
})
}

/// Traverse the subtree rooted at the current node (including the current
/// node) in preorder, excluding tokens.
#[inline]
pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<SyntaxNode>> {
let this = self.clone();
Expand All @@ -411,8 +396,6 @@ impl SyntaxNode {
})
}

/// Traverse the subtree rooted at the current node (including the current
/// node) in preorder, including tokens.
#[inline]
pub fn preorder_with_tokens<'a>(&'a self) -> impl Iterator<Item = WalkEvent<SyntaxElement>> {
let start: SyntaxElement = self.clone().into();
Expand All @@ -439,8 +422,6 @@ impl SyntaxNode {
})
}

/// Find a token in the subtree corresponding to this node, which covers the offset.
/// Precondition: offset must be withing node's range.
pub fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
// TODO: this could be faster if we first drill-down to node, and only
// then switch to token search. We should also replace explicit
Expand Down Expand Up @@ -478,10 +459,6 @@ impl SyntaxNode {
}
}

/// Return the deepest node or token in the current subtree that fully
/// contains the range. If the range is empty and is contained in two leaf
/// nodes, either one can be returned. Precondition: range must be contained
/// withing the current node
pub fn covering_element(&self, range: TextRange) -> SyntaxElement {
let mut res: SyntaxElement = self.clone().into();
loop {
Expand All @@ -493,28 +470,36 @@ impl SyntaxNode {
);
res = match &res {
NodeOrToken::Token(_) => return res,
NodeOrToken::Node(node) => {
match node
.children_with_tokens()
.find(|child| child.text_range().contains_range(range))
{
Some(child) => child,
None => return res,
}
}
NodeOrToken::Node(node) => match node.child_or_token_at_range(range) {
Some(it) => it,
None => return res,
},
};
}
}

pub fn child_or_token_at_range(&self, range: TextRange) -> Option<SyntaxElement> {
let start_offset = self.text_range().start();
let (index, offset, child) = self.green().child_at_range(range - start_offset)?;
let index = index as u32;
let offset = offset + start_offset;
let res: SyntaxElement = match child {
NodeOrToken::Node(node) => {
let data =
NodeData::new(Kind::Child { parent: self.clone(), index, offset }, node.into());
SyntaxNode::new(data).into()
}
NodeOrToken::Token(_token) => SyntaxToken::new(self.clone(), index, offset).into(),
};
Some(res)
}
}

impl SyntaxToken {
fn new(parent: SyntaxNode, index: u32, offset: TextSize) -> SyntaxToken {
SyntaxToken { parent, index, offset }
}

/// Returns a green tree, equal to the green tree this token
/// belongs two, except with this token substitute. The complexity
/// of operation is proportional to the depth of the tree
pub fn replace_with(&self, replacement: GreenToken) -> GreenNode {
assert_eq!(self.kind(), replacement.kind());
let mut replacement = Some(replacement);
Expand Down Expand Up @@ -588,7 +573,6 @@ impl SyntaxToken {
})
}

/// Next token in the tree (i.e, not necessary a sibling)
pub fn next_token(&self) -> Option<SyntaxToken> {
match self.next_sibling_or_token() {
Some(element) => element.first_token(),
Expand All @@ -599,7 +583,7 @@ impl SyntaxToken {
.and_then(|element| element.first_token()),
}
}
/// Previous token in the tree (i.e, not necessary a sibling)

pub fn prev_token(&self) -> Option<SyntaxToken> {
match self.prev_sibling_or_token() {
Some(element) => element.last_token(),
Expand Down
4 changes: 1 addition & 3 deletions src/green.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ mod token;
mod element;
mod builder;

use self::element::GreenElement;
pub(crate) use self::element::GreenElementRef;
use self::element::{GreenElement, PackedGreenElement};

pub use self::{
builder::{Checkpoint, GreenNodeBuilder, NodeCache},
Expand All @@ -26,7 +26,6 @@ mod tests {
f::<GreenNode>();
f::<GreenToken>();
f::<GreenElement>();
f::<PackedGreenElement>();
}

#[test]
Expand All @@ -36,6 +35,5 @@ mod tests {
eprintln!("GreenNode {}", size_of::<GreenNode>());
eprintln!("GreenToken {}", size_of::<GreenToken>());
eprintln!("GreenElement {}", size_of::<GreenElement>());
eprintln!("PackedGreenElement {}", size_of::<PackedGreenElement>());
}
}
Loading

0 comments on commit 7a86fe3

Please sign in to comment.