aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/yellow
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-10-02 15:14:56 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-10-02 15:14:56 +0100
commit7ffc114dab6d1e25ead195a5937cd4f9ca51ef2c (patch)
treee8bab3ea497a8e7207a24e481361bdd56ed81eaa /crates/ra_syntax/src/yellow
parentcd9c5f4ab205e092b87be6affe6d7e78d877dbf0 (diff)
parenta261a1836ba02a1c091c5165795dc165ca399a87 (diff)
Merge #85
85: start moving syntax tree to a separate crate r=matklad a=matklad WIP Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src/yellow')
-rw-r--r--crates/ra_syntax/src/yellow/builder.rs32
-rw-r--r--crates/ra_syntax/src/yellow/green.rs90
-rw-r--r--crates/ra_syntax/src/yellow/mod.rs174
-rw-r--r--crates/ra_syntax/src/yellow/red.rs113
-rw-r--r--crates/ra_syntax/src/yellow/syntax.rs215
-rw-r--r--crates/ra_syntax/src/yellow/syntax_text.rs2
6 files changed, 119 insertions, 507 deletions
diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs
index e4ab37899..35dbaec05 100644
--- a/crates/ra_syntax/src/yellow/builder.rs
+++ b/crates/ra_syntax/src/yellow/builder.rs
@@ -1,15 +1,15 @@
1use rowan::GreenNodeBuilder;
1use { 2use {
2 parser_impl::Sink, 3 parser_impl::Sink,
3 yellow::{GreenNode, SyntaxError}, 4 yellow::{GreenNode, SyntaxError, RaTypes},
4 SyntaxKind, TextRange, TextUnit, 5 SyntaxKind, TextRange, TextUnit,
5}; 6};
6 7
7pub(crate) struct GreenBuilder<'a> { 8pub(crate) struct GreenBuilder<'a> {
8 text: &'a str, 9 text: &'a str,
9 parents: Vec<(SyntaxKind, usize)>,
10 children: Vec<GreenNode>,
11 pos: TextUnit, 10 pos: TextUnit,
12 errors: Vec<SyntaxError>, 11 errors: Vec<SyntaxError>,
12 inner: GreenNodeBuilder<RaTypes>,
13} 13}
14 14
15impl<'a> Sink<'a> for GreenBuilder<'a> { 15impl<'a> Sink<'a> for GreenBuilder<'a> {
@@ -18,35 +18,25 @@ impl<'a> Sink<'a> for GreenBuilder<'a> {
18 fn new(text: &'a str) -> Self { 18 fn new(text: &'a str) -> Self {
19 GreenBuilder { 19 GreenBuilder {
20 text, 20 text,
21 parents: Vec::new(),
22 children: Vec::new(),
23 pos: 0.into(), 21 pos: 0.into(),
24 errors: Vec::new(), 22 errors: Vec::new(),
23 inner: GreenNodeBuilder::new(),
25 } 24 }
26 } 25 }
27 26
28 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) { 27 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
29 let range = TextRange::offset_len(self.pos, len); 28 let range = TextRange::offset_len(self.pos, len);
30 self.pos += len; 29 self.pos += len;
31 let text = &self.text[range]; 30 let text = self.text[range].into();
32 self.children.push( 31 self.inner.leaf(kind, text);
33 GreenNode::new_leaf(kind, text)
34 );
35 } 32 }
36 33
37 fn start_internal(&mut self, kind: SyntaxKind) { 34 fn start_internal(&mut self, kind: SyntaxKind) {
38 let len = self.children.len(); 35 self.inner.start_internal(kind)
39 self.parents.push((kind, len));
40 } 36 }
41 37
42 fn finish_internal(&mut self) { 38 fn finish_internal(&mut self) {
43 let (kind, first_child) = self.parents.pop().unwrap(); 39 self.inner.finish_internal();
44 let children: Vec<_> = self.children
45 .drain(first_child..)
46 .collect();
47 self.children.push(
48 GreenNode::new_branch(kind, children.into_boxed_slice())
49 );
50 } 40 }
51 41
52 fn error(&mut self, message: String) { 42 fn error(&mut self, message: String) {
@@ -56,9 +46,7 @@ impl<'a> Sink<'a> for GreenBuilder<'a> {
56 }) 46 })
57 } 47 }
58 48
59 fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) { 49 fn finish(self) -> (GreenNode, Vec<SyntaxError>) {
60 assert_eq!(self.children.len(), 1); 50 (self.inner.finish(), self.errors)
61 let root = self.children.pop().unwrap();
62 (root, self.errors)
63 } 51 }
64} 52}
diff --git a/crates/ra_syntax/src/yellow/green.rs b/crates/ra_syntax/src/yellow/green.rs
deleted file mode 100644
index 8fb691643..000000000
--- a/crates/ra_syntax/src/yellow/green.rs
+++ /dev/null
@@ -1,90 +0,0 @@
1use std::sync::Arc;
2
3use smol_str::SmolStr;
4
5use {SyntaxKind, TextUnit};
6
7#[derive(Clone, Debug)]
8pub(crate) enum GreenNode {
9 Leaf {
10 kind: SyntaxKind,
11 text: SmolStr,
12 },
13 Branch(Arc<GreenBranch>),
14}
15
16impl GreenNode {
17 pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode {
18 GreenNode::Leaf { kind, text: SmolStr::new(text) }
19 }
20
21 pub(crate) fn new_branch(kind: SyntaxKind, children: Box<[GreenNode]>) -> GreenNode {
22 GreenNode::Branch(Arc::new(GreenBranch::new(kind, children)))
23 }
24
25 pub fn kind(&self) -> SyntaxKind {
26 match self {
27 GreenNode::Leaf { kind, .. } => *kind,
28 GreenNode::Branch(b) => b.kind(),
29 }
30 }
31
32 pub fn text_len(&self) -> TextUnit {
33 match self {
34 GreenNode::Leaf { text, .. } => TextUnit::from(text.len() as u32),
35 GreenNode::Branch(b) => b.text_len(),
36 }
37 }
38
39 pub fn children(&self) -> &[GreenNode] {
40 match self {
41 GreenNode::Leaf { .. } => &[],
42 GreenNode::Branch(b) => b.children(),
43 }
44 }
45
46 pub fn leaf_text_ref(&self) -> Option<&SmolStr> {
47 match self {
48 GreenNode::Leaf { text, .. } => Some(text),
49 GreenNode::Branch(_) => None,
50 }
51 }
52}
53
54#[derive(Clone, Debug)]
55pub(crate) struct GreenBranch {
56 text_len: TextUnit,
57 kind: SyntaxKind,
58 children: Box<[GreenNode]>,
59}
60
61impl GreenBranch {
62 fn new(kind: SyntaxKind, children: Box<[GreenNode]>) -> GreenBranch {
63 let text_len = children.iter().map(|x| x.text_len()).sum::<TextUnit>();
64 GreenBranch {
65 text_len,
66 kind,
67 children,
68 }
69 }
70
71 pub fn kind(&self) -> SyntaxKind {
72 self.kind
73 }
74
75 pub fn text_len(&self) -> TextUnit {
76 self.text_len
77 }
78
79 pub fn children(&self) -> &[GreenNode] {
80 &*self.children
81 }
82}
83
84#[test]
85fn test_sizes() {
86 use std::mem::size_of;
87 println!("GreenBranch = {}", size_of::<GreenBranch>());
88 println!("GreenNode = {}", size_of::<GreenNode>());
89 println!("SmolStr = {}", size_of::<SmolStr>());
90}
diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow/mod.rs
index 0596e702f..c621b1d6a 100644
--- a/crates/ra_syntax/src/yellow/mod.rs
+++ b/crates/ra_syntax/src/yellow/mod.rs
@@ -1,100 +1,142 @@
1mod builder; 1mod builder;
2mod green;
3mod red;
4mod syntax;
5mod syntax_text; 2mod syntax_text;
6 3
7use std::{ 4use std::{
8 sync::Arc, 5 fmt,
9 ptr, 6 hash::{Hash, Hasher},
10};
11pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError, SyntaxNodeChildren};
12pub(crate) use self::{
13 builder::GreenBuilder,
14 green::GreenNode,
15 red::RedNode,
16 syntax_text::SyntaxText,
17}; 7};
8use rowan::Types;
9use {SyntaxKind, TextUnit, TextRange, SmolStr};
10use self::syntax_text::SyntaxText;
18 11
19#[derive(Debug)] 12pub use rowan::{TreeRoot};
20pub struct SyntaxRoot { 13pub(crate) use self::builder::GreenBuilder;
21 red: RedNode, 14
22 pub(crate) errors: Vec<SyntaxError>, 15#[derive(Debug, Clone, Copy)]
16pub enum RaTypes {}
17impl Types for RaTypes {
18 type Kind = SyntaxKind;
19 type RootData = Vec<SyntaxError>;
23} 20}
24 21
25pub trait TreeRoot: Clone + Send + Sync { 22pub type OwnedRoot = ::rowan::OwnedRoot<RaTypes>;
26 fn borrowed(&self) -> RefRoot; 23pub type RefRoot<'a> = ::rowan::RefRoot<'a, RaTypes>;
27 fn owned(&self) -> OwnedRoot; 24
25pub type GreenNode = ::rowan::GreenNode<RaTypes>;
28 26
29 #[doc(hidden)] 27#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
30 fn syntax_root(&self) -> &SyntaxRoot; 28pub struct SyntaxError {
29 pub msg: String,
30 pub offset: TextUnit,
31} 31}
32#[derive(Clone, Debug)]
33pub struct OwnedRoot(Arc<SyntaxRoot>);
34#[derive(Clone, Copy, Debug)]
35pub struct RefRoot<'a>(&'a OwnedRoot); // TODO: shared_from_this instead of double indirection
36 32
37impl<'a> RefRoot<'a> { 33#[derive(Clone, Copy)]
38 fn syntax_root(&self) -> &'a SyntaxRoot { 34pub struct SyntaxNode<R: TreeRoot<RaTypes> = OwnedRoot>(
39 self.0.syntax_root() 35 ::rowan::SyntaxNode<RaTypes, R>,
36);
37pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>;
38
39impl<R1, R2> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2>
40where
41 R1: TreeRoot<RaTypes>,
42 R2: TreeRoot<RaTypes>,
43{
44 fn eq(&self, other: &SyntaxNode<R1>) -> bool {
45 self.0 == other.0
40 } 46 }
41} 47}
42 48
43impl TreeRoot for OwnedRoot { 49impl<R: TreeRoot<RaTypes>> Eq for SyntaxNode<R> {}
44 fn borrowed(&self) -> RefRoot { 50impl<R: TreeRoot<RaTypes>> Hash for SyntaxNode<R> {
45 RefRoot(&self) 51 fn hash<H: Hasher>(&self, state: &mut H) {
46 } 52 self.0.hash(state)
47 fn owned(&self) -> OwnedRoot {
48 self.clone()
49 } 53 }
54}
50 55
51 fn syntax_root(&self) -> &SyntaxRoot { 56impl SyntaxNode<OwnedRoot> {
52 &*self.0 57 pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxNode {
58 SyntaxNode(::rowan::SyntaxNode::new(green, errors))
59 }
60}
61impl<'a> SyntaxNode<RefRoot<'a>> {
62 pub fn leaf_text(self) -> Option<&'a SmolStr> {
63 self.0.leaf_text()
53 } 64 }
54} 65}
55 66
56impl<'a> TreeRoot for RefRoot<'a> { 67impl<R: TreeRoot<RaTypes>> SyntaxNode<R> {
57 fn borrowed(&self) -> RefRoot { 68 pub(crate) fn root_data(&self) -> &Vec<SyntaxError> {
58 *self 69 self.0.root_data()
70 }
71 pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
72 self.0.replace_with(replacement)
73 }
74 pub fn borrowed<'a>(&'a self) -> SyntaxNode<RefRoot<'a>> {
75 SyntaxNode(self.0.borrowed())
76 }
77 pub fn owned(&self) -> SyntaxNode<OwnedRoot> {
78 SyntaxNode(self.0.owned())
79 }
80 pub fn kind(&self) -> SyntaxKind {
81 self.0.kind()
59 } 82 }
60 fn owned(&self) -> OwnedRoot { 83 pub fn range(&self) -> TextRange {
61 self.0.clone() 84 self.0.range()
62 } 85 }
63 fn syntax_root(&self) -> &SyntaxRoot { 86 pub fn text(&self) -> SyntaxText {
64 self.0.syntax_root() 87 SyntaxText::new(self.borrowed())
88 }
89 pub fn is_leaf(&self) -> bool {
90 self.0.is_leaf()
91 }
92 pub fn parent(&self) -> Option<SyntaxNode<R>> {
93 self.0.parent().map(SyntaxNode)
94 }
95 pub fn first_child(&self) -> Option<SyntaxNode<R>> {
96 self.0.first_child().map(SyntaxNode)
97 }
98 pub fn last_child(&self) -> Option<SyntaxNode<R>> {
99 self.0.last_child().map(SyntaxNode)
100 }
101 pub fn next_sibling(&self) -> Option<SyntaxNode<R>> {
102 self.0.next_sibling().map(SyntaxNode)
103 }
104 pub fn prev_sibling(&self) -> Option<SyntaxNode<R>> {
105 self.0.prev_sibling().map(SyntaxNode)
106 }
107 pub fn children(&self) -> SyntaxNodeChildren<R> {
108 SyntaxNodeChildren(self.0.children())
65 } 109 }
66} 110}
67 111
68impl SyntaxRoot { 112impl<R: TreeRoot<RaTypes>> fmt::Debug for SyntaxNode<R> {
69 pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot { 113 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
70 SyntaxRoot { 114 write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
71 red: RedNode::new_root(green), 115 if has_short_text(self.kind()) {
72 errors, 116 write!(fmt, " \"{}\"", self.text())?;
73 } 117 }
118 Ok(())
74 } 119 }
75} 120}
76 121
77#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 122#[derive(Debug)]
78pub(crate) struct RedPtr(ptr::NonNull<RedNode>); 123pub struct SyntaxNodeChildren<R: TreeRoot<RaTypes>>(
79 124 ::rowan::SyntaxNodeChildren<RaTypes, R>
80unsafe impl Send for RedPtr {} 125);
81
82unsafe impl Sync for RedPtr {}
83 126
84impl RedPtr { 127impl<R: TreeRoot<RaTypes>> Iterator for SyntaxNodeChildren<R> {
85 fn new(red: &RedNode) -> RedPtr { 128 type Item = SyntaxNode<R>;
86 RedPtr(red.into())
87 }
88 129
89 unsafe fn get<'a>(self, _root: &'a SyntaxRoot) -> &'a RedNode { 130 fn next(&mut self) -> Option<SyntaxNode<R>> {
90 &*self.0.as_ptr() 131 self.0.next().map(SyntaxNode)
91 } 132 }
92} 133}
93 134
94#[test] 135
95fn assert_send_sync() { 136fn has_short_text(kind: SyntaxKind) -> bool {
96 fn f<T: Send + Sync>() {} 137 use SyntaxKind::*;
97 f::<GreenNode>(); 138 match kind {
98 f::<RedNode>(); 139 IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,
99 f::<SyntaxNode>(); 140 _ => false,
141 }
100} 142}
diff --git a/crates/ra_syntax/src/yellow/red.rs b/crates/ra_syntax/src/yellow/red.rs
deleted file mode 100644
index 84cfe4fba..000000000
--- a/crates/ra_syntax/src/yellow/red.rs
+++ /dev/null
@@ -1,113 +0,0 @@
1use parking_lot::RwLock;
2use {yellow::{GreenNode, RedPtr}, TextUnit};
3
4#[derive(Debug)]
5pub(crate) struct RedNode {
6 green: GreenNode,
7 parent: Option<ParentData>,
8 children: RwLock<Box<[RedChild]>>,
9}
10
11#[derive(Debug)]
12enum RedChild {
13 Zigot(TextUnit),
14 Child(RedNode)
15}
16
17impl RedChild {
18 fn set(&mut self, node: RedNode) -> &RedNode {
19 match self {
20 RedChild::Child(node) => return node,
21 RedChild::Zigot(_) => {
22 *self = RedChild::Child(node);
23 match self {
24 RedChild::Child(node) => return node,
25 RedChild::Zigot(_) => unreachable!()
26 }
27 }
28 }
29 }
30}
31
32#[derive(Debug)]
33struct ParentData {
34 parent: RedPtr,
35 start_offset: TextUnit,
36 index_in_parent: usize,
37}
38
39impl RedNode {
40 pub fn new_root(green: GreenNode) -> RedNode {
41 RedNode::new(green, None)
42 }
43
44 fn new_child(
45 green: GreenNode,
46 parent: RedPtr,
47 start_offset: TextUnit,
48 index_in_parent: usize,
49 ) -> RedNode {
50 let parent_data = ParentData {
51 parent,
52 start_offset,
53 index_in_parent,
54 };
55 RedNode::new(green, Some(parent_data))
56 }
57
58 fn new(green: GreenNode, parent: Option<ParentData>) -> RedNode {
59 let mut start_offset = parent.as_ref().map(|it| it.start_offset).unwrap_or(0.into());
60 let children = green.children()
61 .iter()
62 .map(|child| {
63 let off = start_offset;
64 start_offset += child.text_len();
65 RedChild::Zigot(off)
66 })
67 .collect::<Vec<_>>()
68 .into_boxed_slice();
69 RedNode {
70 green,
71 parent,
72 children: RwLock::new(children),
73 }
74 }
75
76 pub(crate) fn green(&self) -> &GreenNode {
77 &self.green
78 }
79
80 pub(crate) fn start_offset(&self) -> TextUnit {
81 match &self.parent {
82 None => 0.into(),
83 Some(p) => p.start_offset,
84 }
85 }
86
87 pub(crate) fn n_children(&self) -> usize {
88 self.green.children().len()
89 }
90
91 pub(crate) fn get_child(&self, idx: usize) -> Option<RedPtr> {
92 if idx >= self.n_children() {
93 return None;
94 }
95 let start_offset = match &self.children.read()[idx] {
96 RedChild::Child(child) => return Some(RedPtr::new(child)),
97 RedChild::Zigot(start_offset) => *start_offset,
98 };
99 let green_children = self.green.children();
100 let child =
101 RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx);
102 let mut children = self.children.write();
103 let child = children[idx].set(child);
104 Some(RedPtr::new(child))
105 }
106
107 pub(crate) fn parent(&self) -> Option<RedPtr> {
108 Some(self.parent.as_ref()?.parent)
109 }
110 pub(crate) fn index_in_parent(&self) -> Option<usize> {
111 Some(self.parent.as_ref()?.index_in_parent)
112 }
113}
diff --git a/crates/ra_syntax/src/yellow/syntax.rs b/crates/ra_syntax/src/yellow/syntax.rs
deleted file mode 100644
index 1d99cab4a..000000000
--- a/crates/ra_syntax/src/yellow/syntax.rs
+++ /dev/null
@@ -1,215 +0,0 @@
1use std::{
2 fmt, sync::Arc,
3 hash::{Hasher, Hash},
4 ops::Range,
5};
6
7use smol_str::SmolStr;
8
9use {
10 yellow::{GreenNode, RedNode, TreeRoot, SyntaxRoot, RedPtr, RefRoot, OwnedRoot, SyntaxText},
11 SyntaxKind::{self, *},
12 TextRange, TextUnit,
13};
14
15
16#[derive(Clone, Copy)]
17pub struct SyntaxNode<R: TreeRoot = OwnedRoot> {
18 pub(crate) root: R,
19 // Guaranteed to not dangle, because `root` holds a
20 // strong reference to red's ancestor
21 red: RedPtr,
22}
23
24unsafe impl<R: TreeRoot> Send for SyntaxNode<R> {}
25unsafe impl<R: TreeRoot> Sync for SyntaxNode<R> {}
26
27impl<R1: TreeRoot, R2: TreeRoot> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> {
28 fn eq(&self, other: &SyntaxNode<R1>) -> bool {
29 self.red == other.red
30 }
31}
32
33impl<R: TreeRoot> Eq for SyntaxNode<R> {}
34impl<R: TreeRoot> Hash for SyntaxNode<R> {
35 fn hash<H: Hasher>(&self, state: &mut H) {
36 self.red.hash(state)
37 }
38}
39
40pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>;
41
42#[test]
43fn syntax_node_ref_is_copy() {
44 fn assert_copy<T: Copy>(){}
45 assert_copy::<SyntaxNodeRef>()
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
49pub struct SyntaxError {
50 pub msg: String,
51 pub offset: TextUnit,
52}
53
54impl SyntaxNode<OwnedRoot> {
55 pub(crate) fn new_owned(root: SyntaxRoot) -> Self {
56 let root = OwnedRoot(Arc::new(root));
57 let red = RedPtr::new(&root.syntax_root().red);
58 SyntaxNode { root, red }
59 }
60}
61
62impl<'a> SyntaxNode<RefRoot<'a>> {
63 pub(crate) fn leaf_text_ref(self) -> Option<&'a SmolStr> {
64 let red = unsafe { self.red.get(self.root.syntax_root()) };
65 red.green().leaf_text_ref()
66 }
67}
68
69impl<R: TreeRoot> SyntaxNode<R> {
70 pub fn borrowed<'a>(&'a self) -> SyntaxNodeRef<'a> {
71 SyntaxNode {
72 root: self.root.borrowed(),
73 red: self.red,
74 }
75 }
76
77 pub fn owned(&self) -> SyntaxNode {
78 SyntaxNode {
79 root: self.root.owned(),
80 red: self.red,
81 }
82 }
83
84 pub fn kind(&self) -> SyntaxKind {
85 self.red().green().kind()
86 }
87
88 pub fn range(&self) -> TextRange {
89 let red = self.red();
90 TextRange::offset_len(red.start_offset(), red.green().text_len())
91 }
92
93 pub fn text(&self) -> SyntaxText {
94 SyntaxText::new(self.borrowed())
95 }
96
97 pub fn children(&self) -> SyntaxNodeChildren<R> {
98 SyntaxNodeChildren {
99 parent: self.clone(),
100 iter: (0..self.red().n_children())
101 }
102 }
103
104 pub fn parent(&self) -> Option<SyntaxNode<R>> {
105 let parent = self.red().parent()?;
106 Some(SyntaxNode {
107 root: self.root.clone(),
108 red: parent,
109 })
110 }
111
112 pub fn first_child(&self) -> Option<SyntaxNode<R>> {
113 let red = self.red().get_child(0)?;
114 Some(SyntaxNode { root: self.root.clone(), red })
115 }
116
117 pub fn last_child(&self) -> Option<SyntaxNode<R>> {
118 let n = self.red().n_children();
119 let n = n.checked_sub(1)?;
120 let red = self.red().get_child(n)?;
121 Some(SyntaxNode { root: self.root.clone(), red })
122 }
123
124 pub fn next_sibling(&self) -> Option<SyntaxNode<R>> {
125 let red = self.red();
126 let parent = self.parent()?;
127 let next_sibling_idx = red.index_in_parent()? + 1;
128 let sibling_red = parent.red().get_child(next_sibling_idx)?;
129 Some(SyntaxNode {
130 root: self.root.clone(),
131 red: sibling_red,
132 })
133 }
134
135 pub fn prev_sibling(&self) -> Option<SyntaxNode<R>> {
136 let red = self.red();
137 let parent = self.parent()?;
138 let prev_sibling_idx = red.index_in_parent()?.checked_sub(1)?;
139 let sibling_red = parent.red().get_child(prev_sibling_idx)?;
140 Some(SyntaxNode {
141 root: self.root.clone(),
142 red: sibling_red,
143 })
144 }
145
146 pub fn is_leaf(&self) -> bool {
147 self.first_child().is_none()
148 }
149
150 pub fn leaf_text(&self) -> Option<SmolStr> {
151 self.borrowed().leaf_text_ref().map(|it| it.clone())
152 }
153
154 pub(crate) fn replace_with(&self, green: GreenNode) -> GreenNode {
155 assert_eq!(self.kind(), green.kind());
156 match self.parent() {
157 None => green,
158 Some(parent) => {
159 let children: Vec<_> = parent.children().map(|child| {
160 if child == *self {
161 green.clone()
162 } else {
163 child.red().green().clone()
164 }
165 }).collect();
166 let new_parent = GreenNode::new_branch(
167 parent.kind(),
168 children.into_boxed_slice(),
169 );
170 parent.replace_with(new_parent)
171 },
172 }
173 }
174
175 fn red(&self) -> &RedNode {
176 unsafe { self.red.get(self.root.syntax_root()) }
177 }
178}
179
180impl<R: TreeRoot> fmt::Debug for SyntaxNode<R> {
181 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
182 write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
183 if has_short_text(self.kind()) {
184 write!(fmt, " \"{}\"", self.text())?;
185 }
186 Ok(())
187 }
188}
189
190#[derive(Debug)]
191pub struct SyntaxNodeChildren<R: TreeRoot> {
192 parent: SyntaxNode<R>,
193 iter: Range<usize>,
194}
195
196impl<R: TreeRoot> Iterator for SyntaxNodeChildren<R> {
197 type Item = SyntaxNode<R>;
198
199 fn next(&mut self) -> Option<SyntaxNode<R>> {
200 self.iter.next().map(|i| {
201 let red = self.parent.red();
202 SyntaxNode {
203 root: self.parent.root.clone(),
204 red: red.get_child(i).unwrap(),
205 }
206 })
207 }
208}
209
210fn has_short_text(kind: SyntaxKind) -> bool {
211 match kind {
212 IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,
213 _ => false,
214 }
215}
diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs
index 280bedd78..affd7f9c7 100644
--- a/crates/ra_syntax/src/yellow/syntax_text.rs
+++ b/crates/ra_syntax/src/yellow/syntax_text.rs
@@ -25,7 +25,7 @@ impl<'a> SyntaxText<'a> {
25 let range = self.range; 25 let range = self.range;
26 preorder(self.node) 26 preorder(self.node)
27 .filter_map(move |node| { 27 .filter_map(move |node| {
28 let text = node.leaf_text_ref()?; 28 let text = node.leaf_text()?;
29 let range = intersect(range, node.range())?; 29 let range = intersect(range, node.range())?;
30 let range = range - node.range().start(); 30 let range = range - node.range().start();
31 Some(&text[range]) 31 Some(&text[range])