aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r--crates/ra_syntax/Cargo.toml2
-rw-r--r--crates/ra_syntax/src/algo.rs117
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs13
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs5
-rw-r--r--crates/ra_syntax/src/lib.rs16
-rw-r--r--crates/ra_syntax/src/parsing/reparsing.rs13
-rw-r--r--crates/ra_syntax/src/syntax_node.rs483
-rw-r--r--crates/ra_syntax/src/syntax_text.rs178
8 files changed, 147 insertions, 680 deletions
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml
index a5565de33..97b6b047f 100644
--- a/crates/ra_syntax/Cargo.toml
+++ b/crates/ra_syntax/Cargo.toml
@@ -10,7 +10,7 @@ repository = "https://github.com/rust-analyzer/rust-analyzer"
10[dependencies] 10[dependencies]
11unicode-xid = "0.1.0" 11unicode-xid = "0.1.0"
12itertools = "0.8.0" 12itertools = "0.8.0"
13rowan = "0.5.6" 13rowan = "0.6.0-pre.1"
14 14
15# ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here 15# ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here
16# to reduce number of compilations 16# to reduce number of compilations
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index f47e11e66..6bb46b021 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -1,17 +1,18 @@
1pub mod visit; 1pub mod visit;
2 2
3use std::ops::RangeInclusive;
4
3use itertools::Itertools; 5use itertools::Itertools;
4 6
5use crate::{AstNode, Direction, SyntaxElement, SyntaxNode, SyntaxToken, TextRange, TextUnit}; 7use crate::{
8 AstNode, Direction, InsertPosition, NodeOrToken, SourceFile, SyntaxElement, SyntaxNode,
9 SyntaxNodePtr, SyntaxToken, TextRange, TextUnit,
10};
6 11
7pub use rowan::TokenAtOffset; 12pub use rowan::TokenAtOffset;
8 13
9pub fn find_token_at_offset(node: &SyntaxNode, offset: TextUnit) -> TokenAtOffset<SyntaxToken> { 14pub fn find_token_at_offset(node: &SyntaxNode, offset: TextUnit) -> TokenAtOffset<SyntaxToken> {
10 match node.0.token_at_offset(offset) { 15 node.token_at_offset(offset)
11 TokenAtOffset::None => TokenAtOffset::None,
12 TokenAtOffset::Single(n) => TokenAtOffset::Single(SyntaxToken(n)),
13 TokenAtOffset::Between(l, r) => TokenAtOffset::Between(SyntaxToken(l), SyntaxToken(r)),
14 }
15} 16}
16 17
17/// Returns ancestors of the node at the offset, sorted by length. This should 18/// Returns ancestors of the node at the offset, sorted by length. This should
@@ -44,20 +45,110 @@ pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) ->
44/// Finds the first sibling in the given direction which is not `trivia` 45/// Finds the first sibling in the given direction which is not `trivia`
45pub fn non_trivia_sibling(element: SyntaxElement, direction: Direction) -> Option<SyntaxElement> { 46pub fn non_trivia_sibling(element: SyntaxElement, direction: Direction) -> Option<SyntaxElement> {
46 return match element { 47 return match element {
47 SyntaxElement::Node(node) => node.siblings_with_tokens(direction).skip(1).find(not_trivia), 48 NodeOrToken::Node(node) => node.siblings_with_tokens(direction).skip(1).find(not_trivia),
48 SyntaxElement::Token(token) => { 49 NodeOrToken::Token(token) => token.siblings_with_tokens(direction).skip(1).find(not_trivia),
49 token.siblings_with_tokens(direction).skip(1).find(not_trivia)
50 }
51 }; 50 };
52 51
53 fn not_trivia(element: &SyntaxElement) -> bool { 52 fn not_trivia(element: &SyntaxElement) -> bool {
54 match element { 53 match element {
55 SyntaxElement::Node(_) => true, 54 NodeOrToken::Node(_) => true,
56 SyntaxElement::Token(token) => !token.kind().is_trivia(), 55 NodeOrToken::Token(token) => !token.kind().is_trivia(),
57 } 56 }
58 } 57 }
59} 58}
60 59
61pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxElement { 60pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxElement {
62 SyntaxElement::new(root.0.covering_node(range)) 61 root.covering_element(range)
62}
63
64/// Adds specified children (tokens or nodes) to the current node at the
65/// specific position.
66///
67/// This is a type-unsafe low-level editing API, if you need to use it,
68/// prefer to create a type-safe abstraction on top of it instead.
69pub fn insert_children(
70 parent: &SyntaxNode,
71 position: InsertPosition<SyntaxElement>,
72 to_insert: impl Iterator<Item = SyntaxElement>,
73) -> SyntaxNode {
74 let mut delta = TextUnit::default();
75 let to_insert = to_insert.map(|element| {
76 delta += element.text_range().len();
77 to_green_element(element)
78 });
79
80 let old_children = parent.green().children();
81
82 let new_children = match &position {
83 InsertPosition::First => {
84 to_insert.chain(old_children.iter().cloned()).collect::<Box<[_]>>()
85 }
86 InsertPosition::Last => old_children.iter().cloned().chain(to_insert).collect::<Box<[_]>>(),
87 InsertPosition::Before(anchor) | InsertPosition::After(anchor) => {
88 let take_anchor = if let InsertPosition::After(_) = position { 1 } else { 0 };
89 let split_at = position_of_child(parent, anchor.clone()) + take_anchor;
90 let (before, after) = old_children.split_at(split_at);
91 before
92 .iter()
93 .cloned()
94 .chain(to_insert)
95 .chain(after.iter().cloned())
96 .collect::<Box<[_]>>()
97 }
98 };
99
100 with_children(parent, new_children)
101}
102
103/// Replaces all nodes in `to_delete` with nodes from `to_insert`
104///
105/// This is a type-unsafe low-level editing API, if you need to use it,
106/// prefer to create a type-safe abstraction on top of it instead.
107pub fn replace_children(
108 parent: &SyntaxNode,
109 to_delete: RangeInclusive<SyntaxElement>,
110 to_insert: impl Iterator<Item = SyntaxElement>,
111) -> SyntaxNode {
112 let start = position_of_child(parent, to_delete.start().clone());
113 let end = position_of_child(parent, to_delete.end().clone());
114 let old_children = parent.green().children();
115
116 let new_children = old_children[..start]
117 .iter()
118 .cloned()
119 .chain(to_insert.map(to_green_element))
120 .chain(old_children[end + 1..].iter().cloned())
121 .collect::<Box<[_]>>();
122 with_children(parent, new_children)
123}
124
125fn with_children(
126 parent: &SyntaxNode,
127 new_children: Box<[NodeOrToken<rowan::GreenNode, rowan::GreenToken>]>,
128) -> SyntaxNode {
129 let len = new_children.iter().map(|it| it.text_len()).sum::<TextUnit>();
130 let new_node =
131 rowan::GreenNode::new(rowan::cursor::SyntaxKind(parent.kind() as u16), new_children);
132 let new_file_node = parent.replace_with(new_node);
133 let file = SourceFile::new(new_file_node);
134
135 // FIXME: use a more elegant way to re-fetch the node (#1185), make
136 // `range` private afterwards
137 let mut ptr = SyntaxNodePtr::new(parent);
138 ptr.range = TextRange::offset_len(ptr.range().start(), len);
139 ptr.to_node(file.syntax()).to_owned()
140}
141
142fn position_of_child(parent: &SyntaxNode, child: SyntaxElement) -> usize {
143 parent
144 .children_with_tokens()
145 .position(|it| it == child)
146 .expect("element is not a child of current element")
147}
148
149fn to_green_element(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
150 match element {
151 NodeOrToken::Node(it) => it.green().clone().into(),
152 NodeOrToken::Token(it) => it.green().clone().into(),
153 }
63} 154}
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 139bd3ec0..f9190d877 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -2,7 +2,7 @@
2 2
3use crate::{ 3use crate::{
4 ast::{self, child_opt, children, AstChildren, AstNode}, 4 ast::{self, child_opt, children, AstChildren, AstNode},
5 SmolStr, SyntaxElement, 5 SmolStr,
6 SyntaxKind::*, 6 SyntaxKind::*,
7 SyntaxToken, T, 7 SyntaxToken, T,
8}; 8};
@@ -229,14 +229,11 @@ pub enum LiteralKind {
229 229
230impl ast::Literal { 230impl ast::Literal {
231 pub fn token(&self) -> SyntaxToken { 231 pub fn token(&self) -> SyntaxToken {
232 let elem = self 232 self.syntax()
233 .syntax()
234 .children_with_tokens() 233 .children_with_tokens()
235 .find(|e| e.kind() != ATTR && !e.kind().is_trivia()); 234 .find(|e| e.kind() != ATTR && !e.kind().is_trivia())
236 match elem { 235 .and_then(|e| e.into_token())
237 Some(SyntaxElement::Token(token)) => token, 236 .unwrap()
238 _ => unreachable!(),
239 }
240 } 237 }
241 238
242 pub fn kind(&self) -> LiteralKind { 239 pub fn kind(&self) -> LiteralKind {
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 753fc42c6..d4873b39a 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -24,10 +24,7 @@ impl ast::NameRef {
24} 24}
25 25
26fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { 26fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {
27 match node.0.green().children().first() { 27 node.green().children().first().and_then(|it| it.as_token()).unwrap().text()
28 Some(rowan::GreenElement::Token(it)) => it.text(),
29 _ => panic!(),
30 }
31} 28}
32 29
33impl ast::Attr { 30impl ast::Attr {
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 8af04c136..21c07d69a 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -20,7 +20,6 @@
20//! [Swift]: <https://github.com/apple/swift/blob/13d593df6f359d0cb2fc81cfaac273297c539455/lib/Syntax/README.md> 20//! [Swift]: <https://github.com/apple/swift/blob/13d593df6f359d0cb2fc81cfaac273297c539455/lib/Syntax/README.md>
21 21
22mod syntax_node; 22mod syntax_node;
23mod syntax_text;
24mod syntax_error; 23mod syntax_error;
25mod parsing; 24mod parsing;
26mod validation; 25mod validation;
@@ -43,14 +42,13 @@ pub use crate::{
43 ptr::{AstPtr, SyntaxNodePtr}, 42 ptr::{AstPtr, SyntaxNodePtr},
44 syntax_error::{Location, SyntaxError, SyntaxErrorKind}, 43 syntax_error::{Location, SyntaxError, SyntaxErrorKind},
45 syntax_node::{ 44 syntax_node::{
46 Direction, InsertPosition, SyntaxElement, SyntaxNode, SyntaxToken, SyntaxTreeBuilder, 45 Direction, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
47 WalkEvent, 46 SyntaxTreeBuilder, WalkEvent,
48 }, 47 },
49 syntax_text::SyntaxText,
50}; 48};
51pub use ra_parser::SyntaxKind; 49pub use ra_parser::SyntaxKind;
52pub use ra_parser::T; 50pub use ra_parser::T;
53pub use rowan::{SmolStr, TextRange, TextUnit}; 51pub use rowan::{SmolStr, SyntaxText, TextRange, TextUnit};
54 52
55/// `Parse` is the result of the parsing: a syntax tree and a collection of 53/// `Parse` is the result of the parsing: a syntax tree and a collection of
56/// errors. 54/// errors.
@@ -76,7 +74,7 @@ impl<T> Parse<T> {
76 } 74 }
77 75
78 pub fn syntax_node(&self) -> SyntaxNode { 76 pub fn syntax_node(&self) -> SyntaxNode {
79 SyntaxNode::new(self.green.clone()) 77 SyntaxNode::new_root(self.green.clone())
80 } 78 }
81} 79}
82 80
@@ -147,7 +145,7 @@ pub use crate::ast::SourceFile;
147 145
148impl SourceFile { 146impl SourceFile {
149 fn new(green: GreenNode) -> SourceFile { 147 fn new(green: GreenNode) -> SourceFile {
150 let root = SyntaxNode::new(green); 148 let root = SyntaxNode::new_root(green);
151 if cfg!(debug_assertions) { 149 if cfg!(debug_assertions) {
152 validation::validate_block_structure(&root); 150 validation::validate_block_structure(&root);
153 } 151 }
@@ -267,8 +265,8 @@ fn api_walkthrough() {
267 match event { 265 match event {
268 WalkEvent::Enter(node) => { 266 WalkEvent::Enter(node) => {
269 let text = match &node { 267 let text = match &node {
270 SyntaxElement::Node(it) => it.text().to_string(), 268 NodeOrToken::Node(it) => it.text().to_string(),
271 SyntaxElement::Token(it) => it.text().to_string(), 269 NodeOrToken::Token(it) => it.text().to_string(),
272 }; 270 };
273 buf += &format!("{:indent$}{:?} {:?}\n", " ", text, node.kind(), indent = indent); 271 buf += &format!("{:indent$}{:?} {:?}\n", " ", text, node.kind(), indent = indent);
274 indent += 2; 272 indent += 2;
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs
index 2f388bdfe..65b8aa10d 100644
--- a/crates/ra_syntax/src/parsing/reparsing.rs
+++ b/crates/ra_syntax/src/parsing/reparsing.rs
@@ -16,7 +16,7 @@ use crate::{
16 text_token_source::TextTokenSource, 16 text_token_source::TextTokenSource,
17 text_tree_sink::TextTreeSink, 17 text_tree_sink::TextTreeSink,
18 }, 18 },
19 syntax_node::{GreenNode, GreenToken, SyntaxElement, SyntaxNode}, 19 syntax_node::{GreenNode, GreenToken, NodeOrToken, SyntaxElement, SyntaxNode},
20 SyntaxError, 20 SyntaxError,
21 SyntaxKind::*, 21 SyntaxKind::*,
22 TextRange, TextUnit, T, 22 TextRange, TextUnit, T,
@@ -70,7 +70,8 @@ fn reparse_token<'node>(
70 } 70 }
71 } 71 }
72 72
73 let new_token = GreenToken::new(rowan::SyntaxKind(token.kind().into()), text.into()); 73 let new_token =
74 GreenToken::new(rowan::cursor::SyntaxKind(token.kind().into()), text.into());
74 Some((token.replace_with(new_token), token.text_range())) 75 Some((token.replace_with(new_token), token.text_range()))
75 } 76 }
76 _ => None, 77 _ => None,
@@ -98,8 +99,8 @@ fn get_text_after_edit(element: SyntaxElement, edit: &AtomTextEdit) -> String {
98 let edit = 99 let edit =
99 AtomTextEdit::replace(edit.delete - element.text_range().start(), edit.insert.clone()); 100 AtomTextEdit::replace(edit.delete - element.text_range().start(), edit.insert.clone());
100 let text = match element { 101 let text = match element {
101 SyntaxElement::Token(token) => token.text().to_string(), 102 NodeOrToken::Token(token) => token.text().to_string(),
102 SyntaxElement::Node(node) => node.text().to_string(), 103 NodeOrToken::Node(node) => node.text().to_string(),
103 }; 104 };
104 edit.apply(text) 105 edit.apply(text)
105} 106}
@@ -114,8 +115,8 @@ fn is_contextual_kw(text: &str) -> bool {
114fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(SyntaxNode, Reparser)> { 115fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(SyntaxNode, Reparser)> {
115 let node = algo::find_covering_element(node, range); 116 let node = algo::find_covering_element(node, range);
116 let mut ancestors = match node { 117 let mut ancestors = match node {
117 SyntaxElement::Token(it) => it.parent().ancestors(), 118 NodeOrToken::Token(it) => it.parent().ancestors(),
118 SyntaxElement::Node(it) => it.ancestors(), 119 NodeOrToken::Node(it) => it.ancestors(),
119 }; 120 };
120 ancestors.find_map(|node| { 121 ancestors.find_map(|node| {
121 let first_child = node.first_child_or_token().map(|it| it.kind()); 122 let first_child = node.first_child_or_token().map(|it| it.kind());
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs
index c42045d77..689dbefde 100644
--- a/crates/ra_syntax/src/syntax_node.rs
+++ b/crates/ra_syntax/src/syntax_node.rs
@@ -6,15 +6,12 @@
6//! The *real* implementation is in the (language-agnostic) `rowan` crate, this 6//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
7//! modules just wraps its API. 7//! modules just wraps its API.
8 8
9use std::{fmt, iter::successors, ops::RangeInclusive};
10
11use ra_parser::ParseError; 9use ra_parser::ParseError;
12use rowan::GreenNodeBuilder; 10use rowan::{GreenNodeBuilder, Language};
13 11
14use crate::{ 12use crate::{
15 syntax_error::{SyntaxError, SyntaxErrorKind}, 13 syntax_error::{SyntaxError, SyntaxErrorKind},
16 AstNode, Parse, SmolStr, SourceFile, SyntaxKind, SyntaxNodePtr, SyntaxText, TextRange, 14 Parse, SmolStr, SyntaxKind, TextUnit,
17 TextUnit,
18}; 15};
19 16
20pub use rowan::WalkEvent; 17pub use rowan::WalkEvent;
@@ -28,465 +25,27 @@ pub enum InsertPosition<T> {
28 After(T), 25 After(T),
29} 26}
30 27
31#[derive(PartialEq, Eq, Hash, Clone)] 28#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
32pub struct SyntaxNode(pub(crate) rowan::cursor::SyntaxNode); 29pub enum RustLanguage {}
33 30impl Language for RustLanguage {
34impl fmt::Debug for SyntaxNode { 31 type Kind = SyntaxKind;
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 if f.alternate() {
37 let mut level = 0;
38 for event in self.preorder_with_tokens() {
39 match event {
40 WalkEvent::Enter(element) => {
41 for _ in 0..level {
42 write!(f, " ")?;
43 }
44 match element {
45 SyntaxElement::Node(node) => writeln!(f, "{:?}", node)?,
46 SyntaxElement::Token(token) => writeln!(f, "{:?}", token)?,
47 }
48 level += 1;
49 }
50 WalkEvent::Leave(_) => level -= 1,
51 }
52 }
53 assert_eq!(level, 0);
54 Ok(())
55 } else {
56 write!(f, "{:?}@{:?}", self.kind(), self.text_range())
57 }
58 }
59}
60
61impl fmt::Display for SyntaxNode {
62 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
63 fmt::Display::fmt(&self.text(), fmt)
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum Direction {
69 Next,
70 Prev,
71}
72
73impl SyntaxNode {
74 pub(crate) fn new(green: GreenNode) -> SyntaxNode {
75 let inner = rowan::cursor::SyntaxNode::new_root(green);
76 SyntaxNode(inner)
77 }
78
79 pub fn kind(&self) -> SyntaxKind {
80 self.0.kind().0.into()
81 }
82
83 pub fn text_range(&self) -> TextRange {
84 self.0.text_range()
85 }
86
87 pub fn text(&self) -> SyntaxText {
88 SyntaxText::new(self.clone())
89 }
90
91 pub fn parent(&self) -> Option<SyntaxNode> {
92 self.0.parent().map(SyntaxNode)
93 }
94
95 pub fn first_child(&self) -> Option<SyntaxNode> {
96 self.0.first_child().map(SyntaxNode)
97 }
98
99 pub fn first_child_or_token(&self) -> Option<SyntaxElement> {
100 self.0.first_child_or_token().map(SyntaxElement::new)
101 }
102
103 pub fn last_child(&self) -> Option<SyntaxNode> {
104 self.0.last_child().map(SyntaxNode)
105 }
106
107 pub fn last_child_or_token(&self) -> Option<SyntaxElement> {
108 self.0.last_child_or_token().map(SyntaxElement::new)
109 }
110
111 pub fn next_sibling(&self) -> Option<SyntaxNode> {
112 self.0.next_sibling().map(SyntaxNode)
113 }
114
115 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
116 self.0.next_sibling_or_token().map(SyntaxElement::new)
117 }
118
119 pub fn prev_sibling(&self) -> Option<SyntaxNode> {
120 self.0.prev_sibling().map(SyntaxNode)
121 }
122
123 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
124 self.0.prev_sibling_or_token().map(SyntaxElement::new)
125 }
126
127 pub fn children(&self) -> SyntaxNodeChildren {
128 SyntaxNodeChildren(self.0.children())
129 }
130
131 pub fn children_with_tokens(&self) -> SyntaxElementChildren {
132 SyntaxElementChildren(self.0.children_with_tokens())
133 }
134
135 pub fn first_token(&self) -> Option<SyntaxToken> {
136 self.0.first_token().map(SyntaxToken)
137 }
138
139 pub fn last_token(&self) -> Option<SyntaxToken> {
140 self.0.last_token().map(SyntaxToken)
141 }
142
143 pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
144 successors(Some(self.clone()), |node| node.parent())
145 }
146
147 pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
148 self.preorder().filter_map(|event| match event {
149 WalkEvent::Enter(node) => Some(node),
150 WalkEvent::Leave(_) => None,
151 })
152 }
153
154 pub fn descendants_with_tokens(&self) -> impl Iterator<Item = SyntaxElement> {
155 self.preorder_with_tokens().filter_map(|event| match event {
156 WalkEvent::Enter(it) => Some(it),
157 WalkEvent::Leave(_) => None,
158 })
159 }
160
161 pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = SyntaxNode> {
162 successors(Some(self.clone()), move |node| match direction {
163 Direction::Next => node.next_sibling(),
164 Direction::Prev => node.prev_sibling(),
165 })
166 }
167
168 pub fn siblings_with_tokens(
169 &self,
170 direction: Direction,
171 ) -> impl Iterator<Item = SyntaxElement> {
172 let me: SyntaxElement = self.clone().into();
173 successors(Some(me), move |el| match direction {
174 Direction::Next => el.next_sibling_or_token(),
175 Direction::Prev => el.prev_sibling_or_token(),
176 })
177 }
178 32
179 pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<SyntaxNode>> { 33 fn kind_from_raw(raw: rowan::cursor::SyntaxKind) -> SyntaxKind {
180 self.0.preorder().map(|event| match event { 34 SyntaxKind::from(raw.0)
181 WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode(n)),
182 WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode(n)),
183 })
184 } 35 }
185 36
186 pub fn preorder_with_tokens(&self) -> impl Iterator<Item = WalkEvent<SyntaxElement>> { 37 fn kind_to_raw(kind: SyntaxKind) -> rowan::cursor::SyntaxKind {
187 self.0.preorder_with_tokens().map(|event| match event { 38 rowan::cursor::SyntaxKind(kind.into())
188 WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxElement::new(n)),
189 WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxElement::new(n)),
190 })
191 }
192
193 pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
194 self.0.replace_with(replacement)
195 }
196
197 /// Adds specified children (tokens or nodes) to the current node at the
198 /// specific position.
199 ///
200 /// This is a type-unsafe low-level editing API, if you need to use it,
201 /// prefer to create a type-safe abstraction on top of it instead.
202 pub fn insert_children(
203 &self,
204 position: InsertPosition<SyntaxElement>,
205 to_insert: impl Iterator<Item = SyntaxElement>,
206 ) -> SyntaxNode {
207 let mut delta = TextUnit::default();
208 let to_insert = to_insert.map(|element| {
209 delta += element.text_len();
210 to_green_element(element)
211 });
212
213 let old_children = self.0.green().children();
214
215 let new_children = match &position {
216 InsertPosition::First => {
217 to_insert.chain(old_children.iter().cloned()).collect::<Box<[_]>>()
218 }
219 InsertPosition::Last => {
220 old_children.iter().cloned().chain(to_insert).collect::<Box<[_]>>()
221 }
222 InsertPosition::Before(anchor) | InsertPosition::After(anchor) => {
223 let take_anchor = if let InsertPosition::After(_) = position { 1 } else { 0 };
224 let split_at = self.position_of_child(anchor.clone()) + take_anchor;
225 let (before, after) = old_children.split_at(split_at);
226 before
227 .iter()
228 .cloned()
229 .chain(to_insert)
230 .chain(after.iter().cloned())
231 .collect::<Box<[_]>>()
232 }
233 };
234
235 self.with_children(new_children)
236 }
237
238 /// Replaces all nodes in `to_delete` with nodes from `to_insert`
239 ///
240 /// This is a type-unsafe low-level editing API, if you need to use it,
241 /// prefer to create a type-safe abstraction on top of it instead.
242 pub fn replace_children(
243 &self,
244 to_delete: RangeInclusive<SyntaxElement>,
245 to_insert: impl Iterator<Item = SyntaxElement>,
246 ) -> SyntaxNode {
247 let start = self.position_of_child(to_delete.start().clone());
248 let end = self.position_of_child(to_delete.end().clone());
249 let old_children = self.0.green().children();
250
251 let new_children = old_children[..start]
252 .iter()
253 .cloned()
254 .chain(to_insert.map(to_green_element))
255 .chain(old_children[end + 1..].iter().cloned())
256 .collect::<Box<[_]>>();
257 self.with_children(new_children)
258 }
259
260 fn with_children(&self, new_children: Box<[rowan::GreenElement]>) -> SyntaxNode {
261 let len = new_children.iter().map(|it| it.text_len()).sum::<TextUnit>();
262 let new_node = GreenNode::new(rowan::SyntaxKind(self.kind() as u16), new_children);
263 let new_file_node = self.replace_with(new_node);
264 let file = SourceFile::new(new_file_node);
265
266 // FIXME: use a more elegant way to re-fetch the node (#1185), make
267 // `range` private afterwards
268 let mut ptr = SyntaxNodePtr::new(self);
269 ptr.range = TextRange::offset_len(ptr.range().start(), len);
270 ptr.to_node(file.syntax()).to_owned()
271 }
272
273 fn position_of_child(&self, child: SyntaxElement) -> usize {
274 self.children_with_tokens()
275 .position(|it| it == child)
276 .expect("element is not a child of current element")
277 } 39 }
278} 40}
279 41
280fn to_green_element(element: SyntaxElement) -> rowan::GreenElement { 42pub type SyntaxNode = rowan::SyntaxNode<RustLanguage>;
281 match element { 43pub type SyntaxToken = rowan::SyntaxToken<RustLanguage>;
282 SyntaxElement::Node(node) => node.0.green().clone().into(), 44pub type SyntaxElement = rowan::NodeOrToken<SyntaxNode, SyntaxToken>;
283 SyntaxElement::Token(tok) => { 45pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<RustLanguage>;
284 GreenToken::new(rowan::SyntaxKind(tok.kind() as u16), tok.text().clone()).into() 46pub type SyntaxElementChildren = rowan::SyntaxElementChildren<RustLanguage>;
285 }
286 }
287}
288
289#[derive(Clone, PartialEq, Eq, Hash)]
290pub struct SyntaxToken(pub(crate) rowan::cursor::SyntaxToken);
291
292impl fmt::Debug for SyntaxToken {
293 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
294 write!(fmt, "{:?}@{:?}", self.kind(), self.text_range())?;
295 if self.text().len() < 25 {
296 return write!(fmt, " {:?}", self.text());
297 }
298 let text = self.text().as_str();
299 for idx in 21..25 {
300 if text.is_char_boundary(idx) {
301 let text = format!("{} ...", &text[..idx]);
302 return write!(fmt, " {:?}", text);
303 }
304 }
305 unreachable!()
306 }
307}
308 47
309impl fmt::Display for SyntaxToken { 48pub use rowan::{Direction, NodeOrToken};
310 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
311 fmt::Display::fmt(self.text(), fmt)
312 }
313}
314
315impl SyntaxToken {
316 pub fn kind(&self) -> SyntaxKind {
317 self.0.kind().0.into()
318 }
319
320 pub fn text(&self) -> &SmolStr {
321 self.0.text()
322 }
323
324 pub fn text_range(&self) -> TextRange {
325 self.0.text_range()
326 }
327
328 pub fn parent(&self) -> SyntaxNode {
329 SyntaxNode(self.0.parent())
330 }
331
332 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
333 self.0.next_sibling_or_token().map(SyntaxElement::new)
334 }
335
336 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
337 self.0.prev_sibling_or_token().map(SyntaxElement::new)
338 }
339
340 pub fn siblings_with_tokens(
341 &self,
342 direction: Direction,
343 ) -> impl Iterator<Item = SyntaxElement> {
344 let me: SyntaxElement = self.clone().into();
345 successors(Some(me), move |el| match direction {
346 Direction::Next => el.next_sibling_or_token(),
347 Direction::Prev => el.prev_sibling_or_token(),
348 })
349 }
350
351 pub fn next_token(&self) -> Option<SyntaxToken> {
352 self.0.next_token().map(SyntaxToken)
353 }
354
355 pub fn prev_token(&self) -> Option<SyntaxToken> {
356 self.0.prev_token().map(SyntaxToken)
357 }
358
359 pub(crate) fn replace_with(&self, new_token: GreenToken) -> GreenNode {
360 self.0.replace_with(new_token)
361 }
362}
363
364#[derive(Debug, PartialEq, Eq, Hash, Clone)]
365pub enum SyntaxElement {
366 Node(SyntaxNode),
367 Token(SyntaxToken),
368}
369
370impl From<SyntaxNode> for SyntaxElement {
371 fn from(node: SyntaxNode) -> Self {
372 SyntaxElement::Node(node)
373 }
374}
375
376impl From<SyntaxToken> for SyntaxElement {
377 fn from(token: SyntaxToken) -> Self {
378 SyntaxElement::Token(token)
379 }
380}
381
382impl fmt::Display for SyntaxElement {
383 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
384 match self {
385 SyntaxElement::Node(it) => fmt::Display::fmt(it, fmt),
386 SyntaxElement::Token(it) => fmt::Display::fmt(it, fmt),
387 }
388 }
389}
390
391impl SyntaxElement {
392 pub(crate) fn new(el: rowan::cursor::SyntaxElement) -> Self {
393 match el {
394 rowan::cursor::SyntaxElement::Node(it) => SyntaxElement::Node(SyntaxNode(it)),
395 rowan::cursor::SyntaxElement::Token(it) => SyntaxElement::Token(SyntaxToken(it)),
396 }
397 }
398
399 pub fn kind(&self) -> SyntaxKind {
400 match self {
401 SyntaxElement::Node(it) => it.kind(),
402 SyntaxElement::Token(it) => it.kind(),
403 }
404 }
405
406 pub fn as_node(&self) -> Option<&SyntaxNode> {
407 match self {
408 SyntaxElement::Node(node) => Some(node),
409 SyntaxElement::Token(_) => None,
410 }
411 }
412
413 pub fn into_node(self) -> Option<SyntaxNode> {
414 match self {
415 SyntaxElement::Node(node) => Some(node),
416 SyntaxElement::Token(_) => None,
417 }
418 }
419
420 pub fn as_token(&self) -> Option<&SyntaxToken> {
421 match self {
422 SyntaxElement::Node(_) => None,
423 SyntaxElement::Token(token) => Some(token),
424 }
425 }
426
427 pub fn into_token(self) -> Option<SyntaxToken> {
428 match self {
429 SyntaxElement::Node(_) => None,
430 SyntaxElement::Token(token) => Some(token),
431 }
432 }
433
434 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
435 match self {
436 SyntaxElement::Node(it) => it.next_sibling_or_token(),
437 SyntaxElement::Token(it) => it.next_sibling_or_token(),
438 }
439 }
440
441 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
442 match self {
443 SyntaxElement::Node(it) => it.prev_sibling_or_token(),
444 SyntaxElement::Token(it) => it.prev_sibling_or_token(),
445 }
446 }
447
448 pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
449 match self {
450 SyntaxElement::Node(it) => it.clone(),
451 SyntaxElement::Token(it) => it.parent(),
452 }
453 .ancestors()
454 }
455
456 pub fn text_range(&self) -> TextRange {
457 match self {
458 SyntaxElement::Node(it) => it.text_range(),
459 SyntaxElement::Token(it) => it.text_range(),
460 }
461 }
462
463 fn text_len(&self) -> TextUnit {
464 match self {
465 SyntaxElement::Node(node) => node.0.green().text_len(),
466 SyntaxElement::Token(token) => TextUnit::of_str(token.0.text()),
467 }
468 }
469}
470
471#[derive(Clone, Debug)]
472pub struct SyntaxNodeChildren(rowan::cursor::SyntaxNodeChildren);
473
474impl Iterator for SyntaxNodeChildren {
475 type Item = SyntaxNode;
476 fn next(&mut self) -> Option<SyntaxNode> {
477 self.0.next().map(SyntaxNode)
478 }
479}
480
481#[derive(Clone, Debug)]
482pub struct SyntaxElementChildren(rowan::cursor::SyntaxElementChildren);
483
484impl Iterator for SyntaxElementChildren {
485 type Item = SyntaxElement;
486 fn next(&mut self) -> Option<SyntaxElement> {
487 self.0.next().map(SyntaxElement::new)
488 }
489}
490 49
491pub struct SyntaxTreeBuilder { 50pub struct SyntaxTreeBuilder {
492 errors: Vec<SyntaxError>, 51 errors: Vec<SyntaxError>,
@@ -507,19 +66,21 @@ impl SyntaxTreeBuilder {
507 66
508 pub fn finish(self) -> Parse<SyntaxNode> { 67 pub fn finish(self) -> Parse<SyntaxNode> {
509 let (green, errors) = self.finish_raw(); 68 let (green, errors) = self.finish_raw();
510 let node = SyntaxNode::new(green); 69 let node = SyntaxNode::new_root(green);
511 if cfg!(debug_assertions) { 70 if cfg!(debug_assertions) {
512 crate::validation::validate_block_structure(&node); 71 crate::validation::validate_block_structure(&node);
513 } 72 }
514 Parse::new(node.0.green().clone(), errors) 73 Parse::new(node.green().clone(), errors)
515 } 74 }
516 75
517 pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) { 76 pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) {
518 self.inner.token(rowan::SyntaxKind(kind.into()), text) 77 let kind = RustLanguage::kind_to_raw(kind);
78 self.inner.token(kind, text)
519 } 79 }
520 80
521 pub fn start_node(&mut self, kind: SyntaxKind) { 81 pub fn start_node(&mut self, kind: SyntaxKind) {
522 self.inner.start_node(rowan::SyntaxKind(kind.into())) 82 let kind = RustLanguage::kind_to_raw(kind);
83 self.inner.start_node(kind)
523 } 84 }
524 85
525 pub fn finish_node(&mut self) { 86 pub fn finish_node(&mut self) {
diff --git a/crates/ra_syntax/src/syntax_text.rs b/crates/ra_syntax/src/syntax_text.rs
deleted file mode 100644
index 652cb7a1e..000000000
--- a/crates/ra_syntax/src/syntax_text.rs
+++ /dev/null
@@ -1,178 +0,0 @@
1use std::{
2 fmt,
3 ops::{self, Bound},
4};
5
6use crate::{SmolStr, SyntaxElement, SyntaxNode, TextRange, TextUnit};
7
8#[derive(Clone)]
9pub struct SyntaxText {
10 node: SyntaxNode,
11 range: TextRange,
12}
13
14impl SyntaxText {
15 pub(crate) fn new(node: SyntaxNode) -> SyntaxText {
16 let range = node.text_range();
17 SyntaxText { node, range }
18 }
19
20 pub fn try_fold_chunks<T, F, E>(&self, init: T, mut f: F) -> Result<T, E>
21 where
22 F: FnMut(T, &str) -> Result<T, E>,
23 {
24 self.node.descendants_with_tokens().try_fold(init, move |acc, element| {
25 let res = match element {
26 SyntaxElement::Token(token) => {
27 let range = match self.range.intersection(&token.text_range()) {
28 None => return Ok(acc),
29 Some(it) => it,
30 };
31 let slice = if range == token.text_range() {
32 token.text()
33 } else {
34 let range = range - token.text_range().start();
35 &token.text()[range]
36 };
37 f(acc, slice)?
38 }
39 SyntaxElement::Node(_) => acc,
40 };
41 Ok(res)
42 })
43 }
44
45 pub fn try_for_each_chunk<F: FnMut(&str) -> Result<(), E>, E>(
46 &self,
47 mut f: F,
48 ) -> Result<(), E> {
49 self.try_fold_chunks((), move |(), chunk| f(chunk))
50 }
51
52 pub fn for_each_chunk<F: FnMut(&str)>(&self, mut f: F) {
53 enum Void {}
54 match self.try_for_each_chunk(|chunk| Ok::<(), Void>(f(chunk))) {
55 Ok(()) => (),
56 Err(void) => match void {},
57 }
58 }
59
60 pub fn to_smol_string(&self) -> SmolStr {
61 self.to_string().into()
62 }
63
64 pub fn contains_char(&self, c: char) -> bool {
65 self.try_for_each_chunk(|chunk| if chunk.contains(c) { Err(()) } else { Ok(()) }).is_err()
66 }
67
68 pub fn find_char(&self, c: char) -> Option<TextUnit> {
69 let mut acc: TextUnit = 0.into();
70 let res = self.try_for_each_chunk(|chunk| {
71 if let Some(pos) = chunk.find(c) {
72 let pos: TextUnit = (pos as u32).into();
73 return Err(acc + pos);
74 }
75 acc += TextUnit::of_str(chunk);
76 Ok(())
77 });
78 found(res)
79 }
80
81 pub fn len(&self) -> TextUnit {
82 self.range.len()
83 }
84
85 pub fn is_empty(&self) -> bool {
86 self.range.is_empty()
87 }
88
89 pub fn slice(&self, range: impl ops::RangeBounds<TextUnit>) -> SyntaxText {
90 let start = match range.start_bound() {
91 Bound::Included(&b) => b,
92 Bound::Excluded(_) => panic!("utf-aware slicing can't work this way"),
93 Bound::Unbounded => 0.into(),
94 };
95 let end = match range.end_bound() {
96 Bound::Included(_) => panic!("utf-aware slicing can't work this way"),
97 Bound::Excluded(&b) => b,
98 Bound::Unbounded => self.len(),
99 };
100 assert!(start <= end);
101 let len = end - start;
102 let start = self.range.start() + start;
103 let end = start + len;
104 assert!(
105 start <= end,
106 "invalid slice, range: {:?}, slice: {:?}",
107 self.range,
108 (range.start_bound(), range.end_bound()),
109 );
110 let range = TextRange::from_to(start, end);
111 assert!(
112 range.is_subrange(&self.range),
113 "invalid slice, range: {:?}, slice: {:?}",
114 self.range,
115 range,
116 );
117 SyntaxText { node: self.node.clone(), range }
118 }
119
120 pub fn char_at(&self, offset: impl Into<TextUnit>) -> Option<char> {
121 let offset = offset.into();
122 let mut start: TextUnit = 0.into();
123 let res = self.try_for_each_chunk(|chunk| {
124 let end = start + TextUnit::of_str(chunk);
125 if start <= offset && offset < end {
126 let off: usize = u32::from(offset - start) as usize;
127 return Err(chunk[off..].chars().next().unwrap());
128 }
129 start = end;
130 Ok(())
131 });
132 found(res)
133 }
134}
135
136fn found<T>(res: Result<(), T>) -> Option<T> {
137 match res {
138 Ok(()) => None,
139 Err(it) => Some(it),
140 }
141}
142
143impl fmt::Debug for SyntaxText {
144 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145 fmt::Debug::fmt(&self.to_string(), f)
146 }
147}
148
149impl fmt::Display for SyntaxText {
150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151 self.try_for_each_chunk(|chunk| fmt::Display::fmt(chunk, f))
152 }
153}
154
155impl From<SyntaxText> for String {
156 fn from(text: SyntaxText) -> String {
157 text.to_string()
158 }
159}
160
161impl PartialEq<str> for SyntaxText {
162 fn eq(&self, mut rhs: &str) -> bool {
163 self.try_for_each_chunk(|chunk| {
164 if !rhs.starts_with(chunk) {
165 return Err(());
166 }
167 rhs = &rhs[chunk.len()..];
168 Ok(())
169 })
170 .is_ok()
171 }
172}
173
174impl PartialEq<&'_ str> for SyntaxText {
175 fn eq(&self, rhs: &&str) -> bool {
176 self == *rhs
177 }
178}