aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/algo.rs41
-rw-r--r--crates/ra_syntax/src/ast.rs802
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs252
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs303
-rw-r--r--crates/ra_syntax/src/ast/generated.rs650
-rw-r--r--crates/ra_syntax/src/ast/tokens.rs113
-rw-r--r--crates/ra_syntax/src/ast/traits.rs154
-rw-r--r--crates/ra_syntax/src/grammar.ron76
-rw-r--r--crates/ra_syntax/src/lib.rs34
-rw-r--r--crates/ra_syntax/src/parsing/reparsing.rs142
-rw-r--r--crates/ra_syntax/src/parsing/text_tree_sink.rs28
-rw-r--r--crates/ra_syntax/src/string_lexing.rs338
-rw-r--r--crates/ra_syntax/src/string_lexing/parser.rs168
-rw-r--r--crates/ra_syntax/src/string_lexing/string.rs222
-rw-r--r--crates/ra_syntax/src/syntax_node.rs296
-rw-r--r--crates/ra_syntax/src/syntax_text.rs15
-rw-r--r--crates/ra_syntax/src/validation.rs18
-rw-r--r--crates/ra_syntax/src/validation/byte.rs8
-rw-r--r--crates/ra_syntax/src/validation/byte_string.rs8
-rw-r--r--crates/ra_syntax/src/validation/char.rs8
-rw-r--r--crates/ra_syntax/src/validation/string.rs8
21 files changed, 1838 insertions, 1846 deletions
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index e2b4f0388..06b45135c 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -1,18 +1,14 @@
1pub mod visit; 1pub mod visit;
2 2
3use rowan::TransparentNewType; 3use crate::{SyntaxNode, TextRange, TextUnit, AstNode, Direction, SyntaxToken, SyntaxElement};
4 4
5use crate::{SyntaxNode, TextRange, TextUnit, AstNode, Direction}; 5pub use rowan::TokenAtOffset;
6 6
7pub use rowan::LeafAtOffset; 7pub fn find_token_at_offset(node: &SyntaxNode, offset: TextUnit) -> TokenAtOffset<SyntaxToken> {
8 8 match node.0.token_at_offset(offset) {
9pub fn find_leaf_at_offset(node: &SyntaxNode, offset: TextUnit) -> LeafAtOffset<&SyntaxNode> { 9 TokenAtOffset::None => TokenAtOffset::None,
10 match node.0.leaf_at_offset(offset) { 10 TokenAtOffset::Single(n) => TokenAtOffset::Single(n.into()),
11 LeafAtOffset::None => LeafAtOffset::None, 11 TokenAtOffset::Between(l, r) => TokenAtOffset::Between(l.into(), r.into()),
12 LeafAtOffset::Single(n) => LeafAtOffset::Single(SyntaxNode::from_repr(n)),
13 LeafAtOffset::Between(l, r) => {
14 LeafAtOffset::Between(SyntaxNode::from_repr(l), SyntaxNode::from_repr(r))
15 }
16 } 12 }
17} 13}
18 14
@@ -26,16 +22,29 @@ pub fn find_leaf_at_offset(node: &SyntaxNode, offset: TextUnit) -> LeafAtOffset<
26/// 22///
27/// then the left node will be silently preferred. 23/// then the left node will be silently preferred.
28pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> { 24pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> {
29 find_leaf_at_offset(syntax, offset).find_map(|leaf| leaf.ancestors().find_map(N::cast)) 25 find_token_at_offset(syntax, offset)
26 .find_map(|leaf| leaf.parent().ancestors().find_map(N::cast))
30} 27}
31 28
32/// Finds the first sibling in the given direction which is not `trivia` 29/// Finds the first sibling in the given direction which is not `trivia`
33pub fn non_trivia_sibling(node: &SyntaxNode, direction: Direction) -> Option<&SyntaxNode> { 30pub fn non_trivia_sibling(element: SyntaxElement, direction: Direction) -> Option<SyntaxElement> {
34 node.siblings(direction).skip(1).find(|node| !node.kind().is_trivia()) 31 return match element {
32 SyntaxElement::Node(node) => node.siblings_with_tokens(direction).skip(1).find(not_trivia),
33 SyntaxElement::Token(token) => {
34 token.siblings_with_tokens(direction).skip(1).find(not_trivia)
35 }
36 };
37
38 fn not_trivia(element: &SyntaxElement) -> bool {
39 match element {
40 SyntaxElement::Node(_) => true,
41 SyntaxElement::Token(token) => !token.kind().is_trivia(),
42 }
43 }
35} 44}
36 45
37pub fn find_covering_node(root: &SyntaxNode, range: TextRange) -> &SyntaxNode { 46pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxElement {
38 SyntaxNode::from_repr(root.0.covering_node(range)) 47 root.0.covering_node(range).into()
39} 48}
40 49
41// Replace with `std::iter::successors` in `1.34.0` 50// Replace with `std::iter::successors` in `1.34.0`
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index a6fac07c4..9f5c41b0c 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -1,15 +1,24 @@
1//! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s 1//! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s
2
2mod generated; 3mod generated;
4mod traits;
5mod tokens;
6mod extensions;
7mod expr_extensions;
3 8
4use std::marker::PhantomData; 9use std::marker::PhantomData;
5 10
6use itertools::Itertools;
7
8pub use self::generated::*;
9use crate::{ 11use crate::{
10 syntax_node::{SyntaxNode, SyntaxNodeChildren, TreeArc, RaTypes}, 12 syntax_node::{SyntaxNode, SyntaxNodeChildren, TreeArc, RaTypes, SyntaxToken},
11 SmolStr, 13 SmolStr,
12 SyntaxKind::*, 14};
15
16pub use self::{
17 generated::*,
18 traits::*,
19 tokens::*,
20 extensions::{PathSegmentKind, StructKind, SelfParamKind},
21 expr_extensions::{ElseBranch, PrefixOp, BinOp, LiteralKind},
13}; 22};
14 23
15/// The main trait to go from untyped `SyntaxNode` to a typed ast. The 24/// The main trait to go from untyped `SyntaxNode` to a typed ast. The
@@ -25,412 +34,18 @@ pub trait AstNode:
25 fn syntax(&self) -> &SyntaxNode; 34 fn syntax(&self) -> &SyntaxNode;
26} 35}
27 36
28pub trait AstToken: AstNode { 37/// Like `AstNode`, but wraps tokens rather than interior nodes.
29 fn text(&self) -> &SmolStr { 38pub trait AstToken<'a> {
30 self.syntax().leaf_text().unwrap() 39 fn cast(token: SyntaxToken<'a>) -> Option<Self>
31 } 40 where
32} 41 Self: Sized;
33 42 fn syntax(&self) -> SyntaxToken<'a>;
34pub trait TypeAscriptionOwner: AstNode { 43 fn text(&self) -> &'a SmolStr {
35 fn ascribed_type(&self) -> Option<&TypeRef> { 44 self.syntax().text()
36 child_opt(self)
37 }
38}
39
40pub trait NameOwner: AstNode {
41 fn name(&self) -> Option<&Name> {
42 child_opt(self)
43 }
44}
45
46pub trait VisibilityOwner: AstNode {
47 fn visibility(&self) -> Option<&Visibility> {
48 child_opt(self)
49 }
50}
51
52pub trait LoopBodyOwner: AstNode {
53 fn loop_body(&self) -> Option<&Block> {
54 child_opt(self)
55 }
56}
57
58pub trait ArgListOwner: AstNode {
59 fn arg_list(&self) -> Option<&ArgList> {
60 child_opt(self)
61 }
62}
63
64pub trait FnDefOwner: AstNode {
65 fn functions(&self) -> AstChildren<FnDef> {
66 children(self)
67 }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum ItemOrMacro<'a> {
72 Item(&'a ModuleItem),
73 Macro(&'a MacroCall),
74}
75
76pub trait ModuleItemOwner: AstNode {
77 fn items(&self) -> AstChildren<ModuleItem> {
78 children(self)
79 }
80 fn items_with_macros(&self) -> ItemOrMacroIter {
81 ItemOrMacroIter(self.syntax().children())
82 }
83}
84
85#[derive(Debug)]
86pub struct ItemOrMacroIter<'a>(SyntaxNodeChildren<'a>);
87
88impl<'a> Iterator for ItemOrMacroIter<'a> {
89 type Item = ItemOrMacro<'a>;
90 fn next(&mut self) -> Option<ItemOrMacro<'a>> {
91 loop {
92 let n = self.0.next()?;
93 if let Some(item) = ModuleItem::cast(n) {
94 return Some(ItemOrMacro::Item(item));
95 }
96 if let Some(call) = MacroCall::cast(n) {
97 return Some(ItemOrMacro::Macro(call));
98 }
99 }
100 }
101}
102
103pub trait TypeParamsOwner: AstNode {
104 fn type_param_list(&self) -> Option<&TypeParamList> {
105 child_opt(self)
106 }
107
108 fn where_clause(&self) -> Option<&WhereClause> {
109 child_opt(self)
110 }
111}
112
113pub trait AttrsOwner: AstNode {
114 fn attrs(&self) -> AstChildren<Attr> {
115 children(self)
116 }
117 fn has_atom_attr(&self, atom: &str) -> bool {
118 self.attrs().filter_map(|x| x.as_atom()).any(|x| x == atom)
119 }
120}
121
122pub trait DocCommentsOwner: AstNode {
123 fn doc_comments(&self) -> AstChildren<Comment> {
124 children(self)
125 }
126
127 /// Returns the textual content of a doc comment block as a single string.
128 /// That is, strips leading `///` (+ optional 1 character of whitespace)
129 /// and joins lines.
130 fn doc_comment_text(&self) -> Option<std::string::String> {
131 let docs = self
132 .doc_comments()
133 .filter(|comment| comment.is_doc_comment())
134 .map(|comment| {
135 let prefix_len = comment.prefix().len();
136
137 let line = comment.text().as_str();
138
139 // Determine if the prefix or prefix + 1 char is stripped
140 let pos =
141 if line.chars().nth(prefix_len).map(|c| c.is_whitespace()).unwrap_or(false) {
142 prefix_len + 1
143 } else {
144 prefix_len
145 };
146
147 line[pos..].to_owned()
148 })
149 .join("\n");
150
151 if docs.is_empty() {
152 None
153 } else {
154 Some(docs)
155 }
156 }
157}
158
159impl Attr {
160 pub fn is_inner(&self) -> bool {
161 let tt = match self.value() {
162 None => return false,
163 Some(tt) => tt,
164 };
165
166 let prev = match tt.syntax().prev_sibling() {
167 None => return false,
168 Some(prev) => prev,
169 };
170
171 prev.kind() == EXCL
172 }
173
174 pub fn as_atom(&self) -> Option<SmolStr> {
175 let tt = self.value()?;
176 let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?;
177 if attr.kind() == IDENT {
178 Some(attr.leaf_text().unwrap().clone())
179 } else {
180 None
181 }
182 }
183
184 pub fn as_call(&self) -> Option<(SmolStr, &TokenTree)> {
185 let tt = self.value()?;
186 let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?;
187 let args = TokenTree::cast(args)?;
188 if attr.kind() == IDENT {
189 Some((attr.leaf_text().unwrap().clone(), args))
190 } else {
191 None
192 }
193 }
194
195 pub fn as_named(&self) -> Option<SmolStr> {
196 let tt = self.value()?;
197 let attr = tt.syntax().children().nth(1)?;
198 if attr.kind() == IDENT {
199 Some(attr.leaf_text().unwrap().clone())
200 } else {
201 None
202 }
203 }
204}
205
206impl Comment {
207 pub fn flavor(&self) -> CommentFlavor {
208 let text = self.text();
209 if text.starts_with("///") {
210 CommentFlavor::Doc
211 } else if text.starts_with("//!") {
212 CommentFlavor::ModuleDoc
213 } else if text.starts_with("//") {
214 CommentFlavor::Line
215 } else {
216 CommentFlavor::Multiline
217 }
218 }
219
220 pub fn is_doc_comment(&self) -> bool {
221 self.flavor().is_doc_comment()
222 }
223
224 pub fn prefix(&self) -> &'static str {
225 self.flavor().prefix()
226 }
227
228 pub fn count_newlines_lazy(&self) -> impl Iterator<Item = &()> {
229 self.text().chars().filter(|&c| c == '\n').map(|_| &())
230 }
231
232 pub fn has_newlines(&self) -> bool {
233 self.count_newlines_lazy().count() > 0
234 }
235}
236
237#[derive(Debug, PartialEq, Eq)]
238pub enum CommentFlavor {
239 Line,
240 Doc,
241 ModuleDoc,
242 Multiline,
243}
244
245impl CommentFlavor {
246 pub fn prefix(&self) -> &'static str {
247 use self::CommentFlavor::*;
248 match *self {
249 Line => "//",
250 Doc => "///",
251 ModuleDoc => "//!",
252 Multiline => "/*",
253 }
254 }
255
256 pub fn is_doc_comment(&self) -> bool {
257 match self {
258 CommentFlavor::Doc | CommentFlavor::ModuleDoc => true,
259 _ => false,
260 }
261 }
262}
263
264impl Whitespace {
265 pub fn count_newlines_lazy(&self) -> impl Iterator<Item = &()> {
266 self.text().chars().filter(|&c| c == '\n').map(|_| &())
267 }
268
269 pub fn has_newlines(&self) -> bool {
270 self.text().contains('\n')
271 }
272}
273
274impl Name {
275 pub fn text(&self) -> &SmolStr {
276 let ident = self.syntax().first_child().unwrap();
277 ident.leaf_text().unwrap()
278 }
279}
280
281impl NameRef {
282 pub fn text(&self) -> &SmolStr {
283 let ident = self.syntax().first_child().unwrap();
284 ident.leaf_text().unwrap()
285 }
286}
287
288impl ImplBlock {
289 pub fn target_type(&self) -> Option<&TypeRef> {
290 match self.target() {
291 (Some(t), None) | (_, Some(t)) => Some(t),
292 _ => None,
293 }
294 }
295
296 pub fn target_trait(&self) -> Option<&TypeRef> {
297 match self.target() {
298 (Some(t), Some(_)) => Some(t),
299 _ => None,
300 }
301 }
302
303 fn target(&self) -> (Option<&TypeRef>, Option<&TypeRef>) {
304 let mut types = children(self);
305 let first = types.next();
306 let second = types.next();
307 (first, second)
308 }
309}
310
311impl Module {
312 pub fn has_semi(&self) -> bool {
313 match self.syntax().last_child() {
314 None => false,
315 Some(node) => node.kind() == SEMI,
316 }
317 }
318}
319
320impl LetStmt {
321 pub fn has_semi(&self) -> bool {
322 match self.syntax().last_child() {
323 None => false,
324 Some(node) => node.kind() == SEMI,
325 }
326 }
327}
328
329#[derive(Debug, Clone, PartialEq, Eq)]
330pub enum ElseBranchFlavor<'a> {
331 Block(&'a Block),
332 IfExpr(&'a IfExpr),
333}
334
335impl IfExpr {
336 pub fn then_branch(&self) -> Option<&Block> {
337 self.blocks().nth(0)
338 }
339 pub fn else_branch(&self) -> Option<ElseBranchFlavor> {
340 let res = match self.blocks().nth(1) {
341 Some(block) => ElseBranchFlavor::Block(block),
342 None => {
343 let elif: &IfExpr = child_opt(self)?;
344 ElseBranchFlavor::IfExpr(elif)
345 }
346 };
347 Some(res)
348 }
349
350 fn blocks(&self) -> AstChildren<Block> {
351 children(self)
352 }
353}
354
355impl ExprStmt {
356 pub fn has_semi(&self) -> bool {
357 match self.syntax().last_child() {
358 None => false,
359 Some(node) => node.kind() == SEMI,
360 }
361 }
362}
363
364#[derive(Debug, Clone, Copy, PartialEq, Eq)]
365pub enum PathSegmentKind<'a> {
366 Name(&'a NameRef),
367 SelfKw,
368 SuperKw,
369 CrateKw,
370}
371
372impl PathSegment {
373 pub fn parent_path(&self) -> &Path {
374 self.syntax().parent().and_then(Path::cast).expect("segments are always nested in paths")
375 }
376
377 pub fn kind(&self) -> Option<PathSegmentKind> {
378 let res = if let Some(name_ref) = self.name_ref() {
379 PathSegmentKind::Name(name_ref)
380 } else {
381 match self.syntax().first_child()?.kind() {
382 SELF_KW => PathSegmentKind::SelfKw,
383 SUPER_KW => PathSegmentKind::SuperKw,
384 CRATE_KW => PathSegmentKind::CrateKw,
385 _ => return None,
386 }
387 };
388 Some(res)
389 }
390
391 pub fn has_colon_colon(&self) -> bool {
392 match self.syntax.first_child().map(|s| s.kind()) {
393 Some(COLONCOLON) => true,
394 _ => false,
395 }
396 }
397}
398
399impl Path {
400 pub fn parent_path(&self) -> Option<&Path> {
401 self.syntax().parent().and_then(Path::cast)
402 }
403}
404
405impl UseTree {
406 pub fn has_star(&self) -> bool {
407 self.syntax().children().any(|it| it.kind() == STAR)
408 }
409}
410
411impl UseTreeList {
412 pub fn parent_use_tree(&self) -> &UseTree {
413 self.syntax()
414 .parent()
415 .and_then(UseTree::cast)
416 .expect("UseTreeLists are always nested in UseTrees")
417 }
418}
419
420impl RefPat {
421 pub fn is_mut(&self) -> bool {
422 self.syntax().children().any(|n| n.kind() == MUT_KW)
423 } 45 }
424} 46}
425 47
426fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> { 48/// An iterator over `SyntaxNode` children of a particular AST type.
427 children(parent).next()
428}
429
430fn children<P: AstNode, C: AstNode>(parent: &P) -> AstChildren<C> {
431 AstChildren::new(parent.syntax())
432}
433
434#[derive(Debug)] 49#[derive(Debug)]
435pub struct AstChildren<'a, N> { 50pub struct AstChildren<'a, N> {
436 inner: SyntaxNodeChildren<'a>, 51 inner: SyntaxNodeChildren<'a>,
@@ -446,310 +61,16 @@ impl<'a, N> AstChildren<'a, N> {
446impl<'a, N: AstNode + 'a> Iterator for AstChildren<'a, N> { 61impl<'a, N: AstNode + 'a> Iterator for AstChildren<'a, N> {
447 type Item = &'a N; 62 type Item = &'a N;
448 fn next(&mut self) -> Option<&'a N> { 63 fn next(&mut self) -> Option<&'a N> {
449 loop { 64 self.inner.by_ref().find_map(N::cast)
450 if let Some(n) = N::cast(self.inner.next()?) {
451 return Some(n);
452 }
453 }
454 }
455}
456
457#[derive(Debug, Clone, PartialEq, Eq)]
458pub enum StructFlavor<'a> {
459 Tuple(&'a PosFieldDefList),
460 Named(&'a NamedFieldDefList),
461 Unit,
462}
463
464impl StructFlavor<'_> {
465 fn from_node<N: AstNode>(node: &N) -> StructFlavor {
466 if let Some(nfdl) = child_opt::<_, NamedFieldDefList>(node) {
467 StructFlavor::Named(nfdl)
468 } else if let Some(pfl) = child_opt::<_, PosFieldDefList>(node) {
469 StructFlavor::Tuple(pfl)
470 } else {
471 StructFlavor::Unit
472 }
473 } 65 }
474} 66}
475 67
476impl StructDef { 68fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> {
477 pub fn flavor(&self) -> StructFlavor { 69 children(parent).next()
478 StructFlavor::from_node(self)
479 }
480}
481
482impl EnumVariant {
483 pub fn parent_enum(&self) -> &EnumDef {
484 self.syntax()
485 .parent()
486 .and_then(|it| it.parent())
487 .and_then(EnumDef::cast)
488 .expect("EnumVariants are always nested in Enums")
489 }
490 pub fn flavor(&self) -> StructFlavor {
491 StructFlavor::from_node(self)
492 }
493}
494
495impl PointerType {
496 pub fn is_mut(&self) -> bool {
497 self.syntax().children().any(|n| n.kind() == MUT_KW)
498 }
499}
500
501impl ReferenceType {
502 pub fn is_mut(&self) -> bool {
503 self.syntax().children().any(|n| n.kind() == MUT_KW)
504 }
505}
506
507impl RefExpr {
508 pub fn is_mut(&self) -> bool {
509 self.syntax().children().any(|n| n.kind() == MUT_KW)
510 }
511}
512
513#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
514pub enum PrefixOp {
515 /// The `*` operator for dereferencing
516 Deref,
517 /// The `!` operator for logical inversion
518 Not,
519 /// The `-` operator for negation
520 Neg,
521}
522
523impl PrefixExpr {
524 pub fn op_kind(&self) -> Option<PrefixOp> {
525 match self.syntax().first_child()?.kind() {
526 STAR => Some(PrefixOp::Deref),
527 EXCL => Some(PrefixOp::Not),
528 MINUS => Some(PrefixOp::Neg),
529 _ => None,
530 }
531 }
532
533 pub fn op(&self) -> Option<&SyntaxNode> {
534 self.syntax().first_child()
535 }
536}
537
538#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
539pub enum BinOp {
540 /// The `||` operator for boolean OR
541 BooleanOr,
542 /// The `&&` operator for boolean AND
543 BooleanAnd,
544 /// The `==` operator for equality testing
545 EqualityTest,
546 /// The `!=` operator for equality testing
547 NegatedEqualityTest,
548 /// The `<=` operator for lesser-equal testing
549 LesserEqualTest,
550 /// The `>=` operator for greater-equal testing
551 GreaterEqualTest,
552 /// The `<` operator for comparison
553 LesserTest,
554 /// The `>` operator for comparison
555 GreaterTest,
556 /// The `+` operator for addition
557 Addition,
558 /// The `*` operator for multiplication
559 Multiplication,
560 /// The `-` operator for subtraction
561 Subtraction,
562 /// The `/` operator for division
563 Division,
564 /// The `%` operator for remainder after division
565 Remainder,
566 /// The `<<` operator for left shift
567 LeftShift,
568 /// The `>>` operator for right shift
569 RightShift,
570 /// The `^` operator for bitwise XOR
571 BitwiseXor,
572 /// The `|` operator for bitwise OR
573 BitwiseOr,
574 /// The `&` operator for bitwise AND
575 BitwiseAnd,
576 /// The `..` operator for right-open ranges
577 RangeRightOpen,
578 /// The `..=` operator for right-closed ranges
579 RangeRightClosed,
580 /// The `=` operator for assignment
581 Assignment,
582 /// The `+=` operator for assignment after addition
583 AddAssign,
584 /// The `/=` operator for assignment after division
585 DivAssign,
586 /// The `*=` operator for assignment after multiplication
587 MulAssign,
588 /// The `%=` operator for assignment after remainders
589 RemAssign,
590 /// The `>>=` operator for assignment after shifting right
591 ShrAssign,
592 /// The `<<=` operator for assignment after shifting left
593 ShlAssign,
594 /// The `-=` operator for assignment after subtraction
595 SubAssign,
596 /// The `|=` operator for assignment after bitwise OR
597 BitOrAssign,
598 /// The `&=` operator for assignment after bitwise AND
599 BitAndAssign,
600 /// The `^=` operator for assignment after bitwise XOR
601 BitXorAssign,
602}
603
604impl BinExpr {
605 fn op_details(&self) -> Option<(&SyntaxNode, BinOp)> {
606 self.syntax().children().find_map(|c| match c.kind() {
607 PIPEPIPE => Some((c, BinOp::BooleanOr)),
608 AMPAMP => Some((c, BinOp::BooleanAnd)),
609 EQEQ => Some((c, BinOp::EqualityTest)),
610 NEQ => Some((c, BinOp::NegatedEqualityTest)),
611 LTEQ => Some((c, BinOp::LesserEqualTest)),
612 GTEQ => Some((c, BinOp::GreaterEqualTest)),
613 L_ANGLE => Some((c, BinOp::LesserTest)),
614 R_ANGLE => Some((c, BinOp::GreaterTest)),
615 PLUS => Some((c, BinOp::Addition)),
616 STAR => Some((c, BinOp::Multiplication)),
617 MINUS => Some((c, BinOp::Subtraction)),
618 SLASH => Some((c, BinOp::Division)),
619 PERCENT => Some((c, BinOp::Remainder)),
620 SHL => Some((c, BinOp::LeftShift)),
621 SHR => Some((c, BinOp::RightShift)),
622 CARET => Some((c, BinOp::BitwiseXor)),
623 PIPE => Some((c, BinOp::BitwiseOr)),
624 AMP => Some((c, BinOp::BitwiseAnd)),
625 DOTDOT => Some((c, BinOp::RangeRightOpen)),
626 DOTDOTEQ => Some((c, BinOp::RangeRightClosed)),
627 EQ => Some((c, BinOp::Assignment)),
628 PLUSEQ => Some((c, BinOp::AddAssign)),
629 SLASHEQ => Some((c, BinOp::DivAssign)),
630 STAREQ => Some((c, BinOp::MulAssign)),
631 PERCENTEQ => Some((c, BinOp::RemAssign)),
632 SHREQ => Some((c, BinOp::ShrAssign)),
633 SHLEQ => Some((c, BinOp::ShlAssign)),
634 MINUSEQ => Some((c, BinOp::SubAssign)),
635 PIPEEQ => Some((c, BinOp::BitOrAssign)),
636 AMPEQ => Some((c, BinOp::BitAndAssign)),
637 CARETEQ => Some((c, BinOp::BitXorAssign)),
638 _ => None,
639 })
640 }
641
642 pub fn op_kind(&self) -> Option<BinOp> {
643 self.op_details().map(|t| t.1)
644 }
645
646 pub fn op(&self) -> Option<&SyntaxNode> {
647 self.op_details().map(|t| t.0)
648 }
649
650 pub fn lhs(&self) -> Option<&Expr> {
651 children(self).nth(0)
652 }
653
654 pub fn rhs(&self) -> Option<&Expr> {
655 children(self).nth(1)
656 }
657
658 pub fn sub_exprs(&self) -> (Option<&Expr>, Option<&Expr>) {
659 let mut children = children(self);
660 let first = children.next();
661 let second = children.next();
662 (first, second)
663 }
664}
665
666#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
667pub enum SelfParamFlavor {
668 /// self
669 Owned,
670 /// &self
671 Ref,
672 /// &mut self
673 MutRef,
674}
675
676impl SelfParam {
677 pub fn flavor(&self) -> SelfParamFlavor {
678 let borrowed = self.syntax().children().any(|n| n.kind() == AMP);
679 if borrowed {
680 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
681 if self.syntax().children().skip_while(|n| n.kind() != AMP).any(|n| n.kind() == MUT_KW)
682 {
683 SelfParamFlavor::MutRef
684 } else {
685 SelfParamFlavor::Ref
686 }
687 } else {
688 SelfParamFlavor::Owned
689 }
690 }
691}
692
693#[derive(Clone, Debug, PartialEq, Eq, Hash)]
694pub enum LiteralFlavor {
695 String,
696 ByteString,
697 Char,
698 Byte,
699 IntNumber { suffix: Option<SmolStr> },
700 FloatNumber { suffix: Option<SmolStr> },
701 Bool,
702}
703
704impl LiteralExpr {
705 pub fn flavor(&self) -> LiteralFlavor {
706 let syntax = self.syntax();
707 match syntax.kind() {
708 INT_NUMBER => {
709 let allowed_suffix_list = [
710 "isize", "i128", "i64", "i32", "i16", "i8", "usize", "u128", "u64", "u32",
711 "u16", "u8",
712 ];
713 let text = syntax.text().to_string();
714 let suffix = allowed_suffix_list
715 .iter()
716 .find(|&s| text.ends_with(s))
717 .map(|&suf| SmolStr::new(suf));
718 LiteralFlavor::IntNumber { suffix: suffix }
719 }
720 FLOAT_NUMBER => {
721 let allowed_suffix_list = ["f64", "f32"];
722 let text = syntax.text().to_string();
723 let suffix = allowed_suffix_list
724 .iter()
725 .find(|&s| text.ends_with(s))
726 .map(|&suf| SmolStr::new(suf));
727 LiteralFlavor::FloatNumber { suffix: suffix }
728 }
729 STRING | RAW_STRING => LiteralFlavor::String,
730 TRUE_KW | FALSE_KW => LiteralFlavor::Bool,
731 BYTE_STRING | RAW_BYTE_STRING => LiteralFlavor::ByteString,
732 CHAR => LiteralFlavor::Char,
733 BYTE => LiteralFlavor::Byte,
734 _ => unreachable!(),
735 }
736 }
737}
738
739impl NamedField {
740 pub fn parent_struct_lit(&self) -> &StructLit {
741 self.syntax().ancestors().find_map(StructLit::cast).unwrap()
742 }
743} 70}
744 71
745impl BindPat { 72fn children<P: AstNode, C: AstNode>(parent: &P) -> AstChildren<C> {
746 pub fn is_mutable(&self) -> bool { 73 AstChildren::new(parent.syntax())
747 self.syntax().children().any(|n| n.kind() == MUT_KW)
748 }
749
750 pub fn is_ref(&self) -> bool {
751 self.syntax().children().any(|n| n.kind() == REF_KW)
752 }
753} 74}
754 75
755#[test] 76#[test]
@@ -793,3 +114,70 @@ fn test_doc_comment_preserves_indents() {
793 let module = file.syntax().descendants().find_map(Module::cast).unwrap(); 114 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
794 assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap()); 115 assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap());
795} 116}
117
118#[test]
119fn test_where_predicates() {
120 fn assert_bound(text: &str, bound: Option<&TypeBound>) {
121 assert_eq!(text, bound.unwrap().syntax().text().to_string());
122 }
123
124 let file = SourceFile::parse(
125 r#"
126fn foo()
127where
128 T: Clone + Copy + Debug + 'static,
129 'a: 'b + 'c,
130 Iterator::Item: 'a + Debug,
131 Iterator::Item: Debug + 'a,
132 <T as Iterator>::Item: Debug + 'a,
133 for<'a> F: Fn(&'a str)
134{}
135 "#,
136 );
137 let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap();
138
139 let mut predicates = where_clause.predicates();
140
141 let pred = predicates.next().unwrap();
142 let mut bounds = pred.type_bound_list().unwrap().bounds();
143
144 assert_eq!("T", pred.type_ref().unwrap().syntax().text().to_string());
145 assert_bound("Clone", bounds.next());
146 assert_bound("Copy", bounds.next());
147 assert_bound("Debug", bounds.next());
148 assert_bound("'static", bounds.next());
149
150 let pred = predicates.next().unwrap();
151 let mut bounds = pred.type_bound_list().unwrap().bounds();
152
153 assert_eq!("'a", pred.lifetime_token().unwrap().text());
154
155 assert_bound("'b", bounds.next());
156 assert_bound("'c", bounds.next());
157
158 let pred = predicates.next().unwrap();
159 let mut bounds = pred.type_bound_list().unwrap().bounds();
160
161 assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string());
162 assert_bound("'a", bounds.next());
163
164 let pred = predicates.next().unwrap();
165 let mut bounds = pred.type_bound_list().unwrap().bounds();
166
167 assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string());
168 assert_bound("Debug", bounds.next());
169 assert_bound("'a", bounds.next());
170
171 let pred = predicates.next().unwrap();
172 let mut bounds = pred.type_bound_list().unwrap().bounds();
173
174 assert_eq!("<T as Iterator>::Item", pred.type_ref().unwrap().syntax().text().to_string());
175 assert_bound("Debug", bounds.next());
176 assert_bound("'a", bounds.next());
177
178 let pred = predicates.next().unwrap();
179 let mut bounds = pred.type_bound_list().unwrap().bounds();
180
181 assert_eq!("for<'a> F", pred.type_ref().unwrap().syntax().text().to_string());
182 assert_bound("Fn(&'a str)", bounds.next());
183}
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
new file mode 100644
index 000000000..1d8313810
--- /dev/null
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -0,0 +1,252 @@
1//! Various extension methods to ast Expr Nodes, which are hard to code-generate.
2
3use crate::{
4 SyntaxToken, SyntaxElement, SmolStr,
5 ast::{self, AstNode, AstChildren, children, child_opt},
6 SyntaxKind::*
7};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum ElseBranch<'a> {
11 Block(&'a ast::Block),
12 IfExpr(&'a ast::IfExpr),
13}
14
15impl ast::IfExpr {
16 pub fn then_branch(&self) -> Option<&ast::Block> {
17 self.blocks().nth(0)
18 }
19 pub fn else_branch(&self) -> Option<ElseBranch> {
20 let res = match self.blocks().nth(1) {
21 Some(block) => ElseBranch::Block(block),
22 None => {
23 let elif: &ast::IfExpr = child_opt(self)?;
24 ElseBranch::IfExpr(elif)
25 }
26 };
27 Some(res)
28 }
29
30 fn blocks(&self) -> AstChildren<ast::Block> {
31 children(self)
32 }
33}
34
35impl ast::RefExpr {
36 pub fn is_mut(&self) -> bool {
37 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
38 }
39}
40
41#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
42pub enum PrefixOp {
43 /// The `*` operator for dereferencing
44 Deref,
45 /// The `!` operator for logical inversion
46 Not,
47 /// The `-` operator for negation
48 Neg,
49}
50
51impl ast::PrefixExpr {
52 pub fn op_kind(&self) -> Option<PrefixOp> {
53 match self.op_token()?.kind() {
54 STAR => Some(PrefixOp::Deref),
55 EXCL => Some(PrefixOp::Not),
56 MINUS => Some(PrefixOp::Neg),
57 _ => None,
58 }
59 }
60
61 pub fn op_token(&self) -> Option<SyntaxToken> {
62 self.syntax().first_child_or_token()?.as_token()
63 }
64}
65
66#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
67pub enum BinOp {
68 /// The `||` operator for boolean OR
69 BooleanOr,
70 /// The `&&` operator for boolean AND
71 BooleanAnd,
72 /// The `==` operator for equality testing
73 EqualityTest,
74 /// The `!=` operator for equality testing
75 NegatedEqualityTest,
76 /// The `<=` operator for lesser-equal testing
77 LesserEqualTest,
78 /// The `>=` operator for greater-equal testing
79 GreaterEqualTest,
80 /// The `<` operator for comparison
81 LesserTest,
82 /// The `>` operator for comparison
83 GreaterTest,
84 /// The `+` operator for addition
85 Addition,
86 /// The `*` operator for multiplication
87 Multiplication,
88 /// The `-` operator for subtraction
89 Subtraction,
90 /// The `/` operator for division
91 Division,
92 /// The `%` operator for remainder after division
93 Remainder,
94 /// The `<<` operator for left shift
95 LeftShift,
96 /// The `>>` operator for right shift
97 RightShift,
98 /// The `^` operator for bitwise XOR
99 BitwiseXor,
100 /// The `|` operator for bitwise OR
101 BitwiseOr,
102 /// The `&` operator for bitwise AND
103 BitwiseAnd,
104 /// The `..` operator for right-open ranges
105 RangeRightOpen,
106 /// The `..=` operator for right-closed ranges
107 RangeRightClosed,
108 /// The `=` operator for assignment
109 Assignment,
110 /// The `+=` operator for assignment after addition
111 AddAssign,
112 /// The `/=` operator for assignment after division
113 DivAssign,
114 /// The `*=` operator for assignment after multiplication
115 MulAssign,
116 /// The `%=` operator for assignment after remainders
117 RemAssign,
118 /// The `>>=` operator for assignment after shifting right
119 ShrAssign,
120 /// The `<<=` operator for assignment after shifting left
121 ShlAssign,
122 /// The `-=` operator for assignment after subtraction
123 SubAssign,
124 /// The `|=` operator for assignment after bitwise OR
125 BitOrAssign,
126 /// The `&=` operator for assignment after bitwise AND
127 BitAndAssign,
128 /// The `^=` operator for assignment after bitwise XOR
129 BitXorAssign,
130}
131
132impl ast::BinExpr {
133 fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
134 self.syntax().children_with_tokens().filter_map(|it| it.as_token()).find_map(|c| {
135 match c.kind() {
136 PIPEPIPE => Some((c, BinOp::BooleanOr)),
137 AMPAMP => Some((c, BinOp::BooleanAnd)),
138 EQEQ => Some((c, BinOp::EqualityTest)),
139 NEQ => Some((c, BinOp::NegatedEqualityTest)),
140 LTEQ => Some((c, BinOp::LesserEqualTest)),
141 GTEQ => Some((c, BinOp::GreaterEqualTest)),
142 L_ANGLE => Some((c, BinOp::LesserTest)),
143 R_ANGLE => Some((c, BinOp::GreaterTest)),
144 PLUS => Some((c, BinOp::Addition)),
145 STAR => Some((c, BinOp::Multiplication)),
146 MINUS => Some((c, BinOp::Subtraction)),
147 SLASH => Some((c, BinOp::Division)),
148 PERCENT => Some((c, BinOp::Remainder)),
149 SHL => Some((c, BinOp::LeftShift)),
150 SHR => Some((c, BinOp::RightShift)),
151 CARET => Some((c, BinOp::BitwiseXor)),
152 PIPE => Some((c, BinOp::BitwiseOr)),
153 AMP => Some((c, BinOp::BitwiseAnd)),
154 DOTDOT => Some((c, BinOp::RangeRightOpen)),
155 DOTDOTEQ => Some((c, BinOp::RangeRightClosed)),
156 EQ => Some((c, BinOp::Assignment)),
157 PLUSEQ => Some((c, BinOp::AddAssign)),
158 SLASHEQ => Some((c, BinOp::DivAssign)),
159 STAREQ => Some((c, BinOp::MulAssign)),
160 PERCENTEQ => Some((c, BinOp::RemAssign)),
161 SHREQ => Some((c, BinOp::ShrAssign)),
162 SHLEQ => Some((c, BinOp::ShlAssign)),
163 MINUSEQ => Some((c, BinOp::SubAssign)),
164 PIPEEQ => Some((c, BinOp::BitOrAssign)),
165 AMPEQ => Some((c, BinOp::BitAndAssign)),
166 CARETEQ => Some((c, BinOp::BitXorAssign)),
167 _ => None,
168 }
169 })
170 }
171
172 pub fn op_kind(&self) -> Option<BinOp> {
173 self.op_details().map(|t| t.1)
174 }
175
176 pub fn op_token(&self) -> Option<SyntaxToken> {
177 self.op_details().map(|t| t.0)
178 }
179
180 pub fn lhs(&self) -> Option<&ast::Expr> {
181 children(self).nth(0)
182 }
183
184 pub fn rhs(&self) -> Option<&ast::Expr> {
185 children(self).nth(1)
186 }
187
188 pub fn sub_exprs(&self) -> (Option<&ast::Expr>, Option<&ast::Expr>) {
189 let mut children = children(self);
190 let first = children.next();
191 let second = children.next();
192 (first, second)
193 }
194}
195
196#[derive(Clone, Debug, PartialEq, Eq, Hash)]
197pub enum LiteralKind {
198 String,
199 ByteString,
200 Char,
201 Byte,
202 IntNumber { suffix: Option<SmolStr> },
203 FloatNumber { suffix: Option<SmolStr> },
204 Bool,
205}
206
207impl ast::Literal {
208 pub fn token(&self) -> SyntaxToken {
209 match self.syntax().first_child_or_token().unwrap() {
210 SyntaxElement::Token(token) => token,
211 _ => unreachable!(),
212 }
213 }
214
215 pub fn kind(&self) -> LiteralKind {
216 match self.token().kind() {
217 INT_NUMBER => {
218 let allowed_suffix_list = [
219 "isize", "i128", "i64", "i32", "i16", "i8", "usize", "u128", "u64", "u32",
220 "u16", "u8",
221 ];
222 let text = self.token().text().to_string();
223 let suffix = allowed_suffix_list
224 .iter()
225 .find(|&s| text.ends_with(s))
226 .map(|&suf| SmolStr::new(suf));
227 LiteralKind::IntNumber { suffix }
228 }
229 FLOAT_NUMBER => {
230 let allowed_suffix_list = ["f64", "f32"];
231 let text = self.token().text().to_string();
232 let suffix = allowed_suffix_list
233 .iter()
234 .find(|&s| text.ends_with(s))
235 .map(|&suf| SmolStr::new(suf));
236 LiteralKind::FloatNumber { suffix: suffix }
237 }
238 STRING | RAW_STRING => LiteralKind::String,
239 TRUE_KW | FALSE_KW => LiteralKind::Bool,
240 BYTE_STRING | RAW_BYTE_STRING => LiteralKind::ByteString,
241 CHAR => LiteralKind::Char,
242 BYTE => LiteralKind::Byte,
243 _ => unreachable!(),
244 }
245 }
246}
247
248impl ast::NamedField {
249 pub fn parent_struct_lit(&self) -> &ast::StructLit {
250 self.syntax().ancestors().find_map(ast::StructLit::cast).unwrap()
251 }
252}
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
new file mode 100644
index 000000000..aec57c380
--- /dev/null
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -0,0 +1,303 @@
1//! Various extension methods to ast Nodes, which are hard to code-generate.
2//! Extensions for various expressions live in a sibling `expr_extensions` module.
3
4use itertools::Itertools;
5
6use crate::{
7 SmolStr, SyntaxToken,
8 ast::{self, AstNode, children, child_opt},
9 SyntaxKind::*,
10};
11
12impl ast::Name {
13 pub fn text(&self) -> &SmolStr {
14 let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap();
15 ident.text()
16 }
17}
18
19impl ast::NameRef {
20 pub fn text(&self) -> &SmolStr {
21 let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap();
22 ident.text()
23 }
24}
25
26impl ast::Attr {
27 pub fn is_inner(&self) -> bool {
28 let tt = match self.value() {
29 None => return false,
30 Some(tt) => tt,
31 };
32
33 let prev = match tt.syntax().prev_sibling() {
34 None => return false,
35 Some(prev) => prev,
36 };
37
38 prev.kind() == EXCL
39 }
40
41 pub fn as_atom(&self) -> Option<SmolStr> {
42 let tt = self.value()?;
43 let (_bra, attr, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
44 if attr.kind() == IDENT {
45 Some(attr.as_token()?.text().clone())
46 } else {
47 None
48 }
49 }
50
51 pub fn as_call(&self) -> Option<(SmolStr, &ast::TokenTree)> {
52 let tt = self.value()?;
53 let (_bra, attr, args, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
54 let args = ast::TokenTree::cast(args.as_node()?)?;
55 if attr.kind() == IDENT {
56 Some((attr.as_token()?.text().clone(), args))
57 } else {
58 None
59 }
60 }
61
62 pub fn as_named(&self) -> Option<SmolStr> {
63 let tt = self.value()?;
64 let attr = tt.syntax().children_with_tokens().nth(1)?;
65 if attr.kind() == IDENT {
66 Some(attr.as_token()?.text().clone())
67 } else {
68 None
69 }
70 }
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum PathSegmentKind<'a> {
75 Name(&'a ast::NameRef),
76 SelfKw,
77 SuperKw,
78 CrateKw,
79}
80
81impl ast::PathSegment {
82 pub fn parent_path(&self) -> &ast::Path {
83 self.syntax()
84 .parent()
85 .and_then(ast::Path::cast)
86 .expect("segments are always nested in paths")
87 }
88
89 pub fn kind(&self) -> Option<PathSegmentKind> {
90 let res = if let Some(name_ref) = self.name_ref() {
91 PathSegmentKind::Name(name_ref)
92 } else {
93 match self.syntax().first_child_or_token()?.kind() {
94 SELF_KW => PathSegmentKind::SelfKw,
95 SUPER_KW => PathSegmentKind::SuperKw,
96 CRATE_KW => PathSegmentKind::CrateKw,
97 _ => return None,
98 }
99 };
100 Some(res)
101 }
102
103 pub fn has_colon_colon(&self) -> bool {
104 match self.syntax.first_child_or_token().map(|s| s.kind()) {
105 Some(COLONCOLON) => true,
106 _ => false,
107 }
108 }
109}
110
111impl ast::Path {
112 pub fn parent_path(&self) -> Option<&ast::Path> {
113 self.syntax().parent().and_then(ast::Path::cast)
114 }
115}
116
117impl ast::Module {
118 pub fn has_semi(&self) -> bool {
119 match self.syntax().last_child_or_token() {
120 None => false,
121 Some(node) => node.kind() == SEMI,
122 }
123 }
124}
125
126impl ast::UseTree {
127 pub fn has_star(&self) -> bool {
128 self.syntax().children_with_tokens().any(|it| it.kind() == STAR)
129 }
130}
131
132impl ast::UseTreeList {
133 pub fn parent_use_tree(&self) -> &ast::UseTree {
134 self.syntax()
135 .parent()
136 .and_then(ast::UseTree::cast)
137 .expect("UseTreeLists are always nested in UseTrees")
138 }
139}
140
141impl ast::ImplBlock {
142 pub fn target_type(&self) -> Option<&ast::TypeRef> {
143 match self.target() {
144 (Some(t), None) | (_, Some(t)) => Some(t),
145 _ => None,
146 }
147 }
148
149 pub fn target_trait(&self) -> Option<&ast::TypeRef> {
150 match self.target() {
151 (Some(t), Some(_)) => Some(t),
152 _ => None,
153 }
154 }
155
156 fn target(&self) -> (Option<&ast::TypeRef>, Option<&ast::TypeRef>) {
157 let mut types = children(self);
158 let first = types.next();
159 let second = types.next();
160 (first, second)
161 }
162}
163
164#[derive(Debug, Clone, PartialEq, Eq)]
165pub enum StructKind<'a> {
166 Tuple(&'a ast::PosFieldDefList),
167 Named(&'a ast::NamedFieldDefList),
168 Unit,
169}
170
171impl StructKind<'_> {
172 fn from_node<N: AstNode>(node: &N) -> StructKind {
173 if let Some(nfdl) = child_opt::<_, ast::NamedFieldDefList>(node) {
174 StructKind::Named(nfdl)
175 } else if let Some(pfl) = child_opt::<_, ast::PosFieldDefList>(node) {
176 StructKind::Tuple(pfl)
177 } else {
178 StructKind::Unit
179 }
180 }
181}
182
183impl ast::StructDef {
184 pub fn kind(&self) -> StructKind {
185 StructKind::from_node(self)
186 }
187}
188
189impl ast::EnumVariant {
190 pub fn parent_enum(&self) -> &ast::EnumDef {
191 self.syntax()
192 .parent()
193 .and_then(|it| it.parent())
194 .and_then(ast::EnumDef::cast)
195 .expect("EnumVariants are always nested in Enums")
196 }
197 pub fn kind(&self) -> StructKind {
198 StructKind::from_node(self)
199 }
200}
201
202impl ast::LetStmt {
203 pub fn has_semi(&self) -> bool {
204 match self.syntax().last_child_or_token() {
205 None => false,
206 Some(node) => node.kind() == SEMI,
207 }
208 }
209}
210
211impl ast::ExprStmt {
212 pub fn has_semi(&self) -> bool {
213 match self.syntax().last_child_or_token() {
214 None => false,
215 Some(node) => node.kind() == SEMI,
216 }
217 }
218}
219
220impl ast::RefPat {
221 pub fn is_mut(&self) -> bool {
222 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
223 }
224}
225
226impl ast::BindPat {
227 pub fn is_mutable(&self) -> bool {
228 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
229 }
230
231 pub fn is_ref(&self) -> bool {
232 self.syntax().children_with_tokens().any(|n| n.kind() == REF_KW)
233 }
234}
235
236impl ast::PointerType {
237 pub fn is_mut(&self) -> bool {
238 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
239 }
240}
241
242impl ast::ReferenceType {
243 pub fn is_mut(&self) -> bool {
244 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
245 }
246}
247
248#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
249pub enum SelfParamKind {
250 /// self
251 Owned,
252 /// &self
253 Ref,
254 /// &mut self
255 MutRef,
256}
257
258impl ast::SelfParam {
259 pub fn self_kw_token(&self) -> SyntaxToken {
260 self.syntax()
261 .children_with_tokens()
262 .filter_map(|it| it.as_token())
263 .find(|it| it.kind() == SELF_KW)
264 .expect("invalid tree: self param must have self")
265 }
266
267 pub fn kind(&self) -> SelfParamKind {
268 let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == AMP);
269 if borrowed {
270 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
271 if self
272 .syntax()
273 .children_with_tokens()
274 .skip_while(|n| n.kind() != AMP)
275 .any(|n| n.kind() == MUT_KW)
276 {
277 SelfParamKind::MutRef
278 } else {
279 SelfParamKind::Ref
280 }
281 } else {
282 SelfParamKind::Owned
283 }
284 }
285}
286
287impl ast::LifetimeParam {
288 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
289 self.syntax()
290 .children_with_tokens()
291 .filter_map(|it| it.as_token())
292 .find(|it| it.kind() == LIFETIME)
293 }
294}
295
296impl ast::WherePred {
297 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
298 self.syntax()
299 .children_with_tokens()
300 .filter_map(|it| it.as_token())
301 .find(|it| it.kind() == LIFETIME)
302 }
303}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 84f39cda1..0376c91c8 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -376,64 +376,6 @@ impl BreakExpr {
376 } 376 }
377} 377}
378 378
379// Byte
380#[derive(Debug, PartialEq, Eq, Hash)]
381#[repr(transparent)]
382pub struct Byte {
383 pub(crate) syntax: SyntaxNode,
384}
385unsafe impl TransparentNewType for Byte {
386 type Repr = rowan::SyntaxNode<RaTypes>;
387}
388
389impl AstNode for Byte {
390 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
391 match syntax.kind() {
392 BYTE => Some(Byte::from_repr(syntax.into_repr())),
393 _ => None,
394 }
395 }
396 fn syntax(&self) -> &SyntaxNode { &self.syntax }
397}
398
399impl ToOwned for Byte {
400 type Owned = TreeArc<Byte>;
401 fn to_owned(&self) -> TreeArc<Byte> { TreeArc::cast(self.syntax.to_owned()) }
402}
403
404
405impl ast::AstToken for Byte {}
406impl Byte {}
407
408// ByteString
409#[derive(Debug, PartialEq, Eq, Hash)]
410#[repr(transparent)]
411pub struct ByteString {
412 pub(crate) syntax: SyntaxNode,
413}
414unsafe impl TransparentNewType for ByteString {
415 type Repr = rowan::SyntaxNode<RaTypes>;
416}
417
418impl AstNode for ByteString {
419 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
420 match syntax.kind() {
421 BYTE_STRING => Some(ByteString::from_repr(syntax.into_repr())),
422 _ => None,
423 }
424 }
425 fn syntax(&self) -> &SyntaxNode { &self.syntax }
426}
427
428impl ToOwned for ByteString {
429 type Owned = TreeArc<ByteString>;
430 fn to_owned(&self) -> TreeArc<ByteString> { TreeArc::cast(self.syntax.to_owned()) }
431}
432
433
434impl ast::AstToken for ByteString {}
435impl ByteString {}
436
437// CallExpr 379// CallExpr
438#[derive(Debug, PartialEq, Eq, Hash)] 380#[derive(Debug, PartialEq, Eq, Hash)]
439#[repr(transparent)] 381#[repr(transparent)]
@@ -503,64 +445,6 @@ impl CastExpr {
503 } 445 }
504} 446}
505 447
506// Char
507#[derive(Debug, PartialEq, Eq, Hash)]
508#[repr(transparent)]
509pub struct Char {
510 pub(crate) syntax: SyntaxNode,
511}
512unsafe impl TransparentNewType for Char {
513 type Repr = rowan::SyntaxNode<RaTypes>;
514}
515
516impl AstNode for Char {
517 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
518 match syntax.kind() {
519 CHAR => Some(Char::from_repr(syntax.into_repr())),
520 _ => None,
521 }
522 }
523 fn syntax(&self) -> &SyntaxNode { &self.syntax }
524}
525
526impl ToOwned for Char {
527 type Owned = TreeArc<Char>;
528 fn to_owned(&self) -> TreeArc<Char> { TreeArc::cast(self.syntax.to_owned()) }
529}
530
531
532impl ast::AstToken for Char {}
533impl Char {}
534
535// Comment
536#[derive(Debug, PartialEq, Eq, Hash)]
537#[repr(transparent)]
538pub struct Comment {
539 pub(crate) syntax: SyntaxNode,
540}
541unsafe impl TransparentNewType for Comment {
542 type Repr = rowan::SyntaxNode<RaTypes>;
543}
544
545impl AstNode for Comment {
546 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
547 match syntax.kind() {
548 COMMENT => Some(Comment::from_repr(syntax.into_repr())),
549 _ => None,
550 }
551 }
552 fn syntax(&self) -> &SyntaxNode { &self.syntax }
553}
554
555impl ToOwned for Comment {
556 type Owned = TreeArc<Comment>;
557 fn to_owned(&self) -> TreeArc<Comment> { TreeArc::cast(self.syntax.to_owned()) }
558}
559
560
561impl ast::AstToken for Comment {}
562impl Comment {}
563
564// Condition 448// Condition
565#[derive(Debug, PartialEq, Eq, Hash)] 449#[derive(Debug, PartialEq, Eq, Hash)]
566#[repr(transparent)] 450#[repr(transparent)]
@@ -689,6 +573,7 @@ impl ToOwned for DynTraitType {
689} 573}
690 574
691 575
576impl ast::TypeBoundsOwner for DynTraitType {}
692impl DynTraitType {} 577impl DynTraitType {}
693 578
694// EnumDef 579// EnumDef
@@ -834,6 +719,7 @@ pub enum ExprKind<'a> {
834 RangeExpr(&'a RangeExpr), 719 RangeExpr(&'a RangeExpr),
835 BinExpr(&'a BinExpr), 720 BinExpr(&'a BinExpr),
836 Literal(&'a Literal), 721 Literal(&'a Literal),
722 MacroCall(&'a MacroCall),
837} 723}
838impl<'a> From<&'a TupleExpr> for &'a Expr { 724impl<'a> From<&'a TupleExpr> for &'a Expr {
839 fn from(n: &'a TupleExpr) -> &'a Expr { 725 fn from(n: &'a TupleExpr) -> &'a Expr {
@@ -970,6 +856,11 @@ impl<'a> From<&'a Literal> for &'a Expr {
970 Expr::cast(&n.syntax).unwrap() 856 Expr::cast(&n.syntax).unwrap()
971 } 857 }
972} 858}
859impl<'a> From<&'a MacroCall> for &'a Expr {
860 fn from(n: &'a MacroCall) -> &'a Expr {
861 Expr::cast(&n.syntax).unwrap()
862 }
863}
973 864
974 865
975impl AstNode for Expr { 866impl AstNode for Expr {
@@ -1001,7 +892,8 @@ impl AstNode for Expr {
1001 | PREFIX_EXPR 892 | PREFIX_EXPR
1002 | RANGE_EXPR 893 | RANGE_EXPR
1003 | BIN_EXPR 894 | BIN_EXPR
1004 | LITERAL => Some(Expr::from_repr(syntax.into_repr())), 895 | LITERAL
896 | MACRO_CALL => Some(Expr::from_repr(syntax.into_repr())),
1005 _ => None, 897 _ => None,
1006 } 898 }
1007 } 899 }
@@ -1043,6 +935,7 @@ impl Expr {
1043 RANGE_EXPR => ExprKind::RangeExpr(RangeExpr::cast(&self.syntax).unwrap()), 935 RANGE_EXPR => ExprKind::RangeExpr(RangeExpr::cast(&self.syntax).unwrap()),
1044 BIN_EXPR => ExprKind::BinExpr(BinExpr::cast(&self.syntax).unwrap()), 936 BIN_EXPR => ExprKind::BinExpr(BinExpr::cast(&self.syntax).unwrap()),
1045 LITERAL => ExprKind::Literal(Literal::cast(&self.syntax).unwrap()), 937 LITERAL => ExprKind::Literal(Literal::cast(&self.syntax).unwrap()),
938 MACRO_CALL => ExprKind::MacroCall(MacroCall::cast(&self.syntax).unwrap()),
1046 _ => unreachable!(), 939 _ => unreachable!(),
1047 } 940 }
1048 } 941 }
@@ -1118,35 +1011,6 @@ impl ExternCrateItem {
1118 } 1011 }
1119} 1012}
1120 1013
1121// FalseKw
1122#[derive(Debug, PartialEq, Eq, Hash)]
1123#[repr(transparent)]
1124pub struct FalseKw {
1125 pub(crate) syntax: SyntaxNode,
1126}
1127unsafe impl TransparentNewType for FalseKw {
1128 type Repr = rowan::SyntaxNode<RaTypes>;
1129}
1130
1131impl AstNode for FalseKw {
1132 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1133 match syntax.kind() {
1134 FALSE_KW => Some(FalseKw::from_repr(syntax.into_repr())),
1135 _ => None,
1136 }
1137 }
1138 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1139}
1140
1141impl ToOwned for FalseKw {
1142 type Owned = TreeArc<FalseKw>;
1143 fn to_owned(&self) -> TreeArc<FalseKw> { TreeArc::cast(self.syntax.to_owned()) }
1144}
1145
1146
1147impl ast::AstToken for FalseKw {}
1148impl FalseKw {}
1149
1150// FieldExpr 1014// FieldExpr
1151#[derive(Debug, PartialEq, Eq, Hash)] 1015#[derive(Debug, PartialEq, Eq, Hash)]
1152#[repr(transparent)] 1016#[repr(transparent)]
@@ -1252,35 +1116,6 @@ impl FieldPatList {
1252 } 1116 }
1253} 1117}
1254 1118
1255// FloatNumber
1256#[derive(Debug, PartialEq, Eq, Hash)]
1257#[repr(transparent)]
1258pub struct FloatNumber {
1259 pub(crate) syntax: SyntaxNode,
1260}
1261unsafe impl TransparentNewType for FloatNumber {
1262 type Repr = rowan::SyntaxNode<RaTypes>;
1263}
1264
1265impl AstNode for FloatNumber {
1266 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1267 match syntax.kind() {
1268 FLOAT_NUMBER => Some(FloatNumber::from_repr(syntax.into_repr())),
1269 _ => None,
1270 }
1271 }
1272 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1273}
1274
1275impl ToOwned for FloatNumber {
1276 type Owned = TreeArc<FloatNumber>;
1277 fn to_owned(&self) -> TreeArc<FloatNumber> { TreeArc::cast(self.syntax.to_owned()) }
1278}
1279
1280
1281impl ast::AstToken for FloatNumber {}
1282impl FloatNumber {}
1283
1284// FnDef 1119// FnDef
1285#[derive(Debug, PartialEq, Eq, Hash)] 1120#[derive(Debug, PartialEq, Eq, Hash)]
1286#[repr(transparent)] 1121#[repr(transparent)]
@@ -1585,6 +1420,7 @@ impl ToOwned for ImplTraitType {
1585} 1420}
1586 1421
1587 1422
1423impl ast::TypeBoundsOwner for ImplTraitType {}
1588impl ImplTraitType {} 1424impl ImplTraitType {}
1589 1425
1590// IndexExpr 1426// IndexExpr
@@ -1615,35 +1451,6 @@ impl ToOwned for IndexExpr {
1615 1451
1616impl IndexExpr {} 1452impl IndexExpr {}
1617 1453
1618// IntNumber
1619#[derive(Debug, PartialEq, Eq, Hash)]
1620#[repr(transparent)]
1621pub struct IntNumber {
1622 pub(crate) syntax: SyntaxNode,
1623}
1624unsafe impl TransparentNewType for IntNumber {
1625 type Repr = rowan::SyntaxNode<RaTypes>;
1626}
1627
1628impl AstNode for IntNumber {
1629 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1630 match syntax.kind() {
1631 INT_NUMBER => Some(IntNumber::from_repr(syntax.into_repr())),
1632 _ => None,
1633 }
1634 }
1635 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1636}
1637
1638impl ToOwned for IntNumber {
1639 type Owned = TreeArc<IntNumber>;
1640 fn to_owned(&self) -> TreeArc<IntNumber> { TreeArc::cast(self.syntax.to_owned()) }
1641}
1642
1643
1644impl ast::AstToken for IntNumber {}
1645impl IntNumber {}
1646
1647// ItemList 1454// ItemList
1648#[derive(Debug, PartialEq, Eq, Hash)] 1455#[derive(Debug, PartialEq, Eq, Hash)]
1649#[repr(transparent)] 1456#[repr(transparent)]
@@ -1779,35 +1586,6 @@ impl LetStmt {
1779 } 1586 }
1780} 1587}
1781 1588
1782// Lifetime
1783#[derive(Debug, PartialEq, Eq, Hash)]
1784#[repr(transparent)]
1785pub struct Lifetime {
1786 pub(crate) syntax: SyntaxNode,
1787}
1788unsafe impl TransparentNewType for Lifetime {
1789 type Repr = rowan::SyntaxNode<RaTypes>;
1790}
1791
1792impl AstNode for Lifetime {
1793 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1794 match syntax.kind() {
1795 LIFETIME => Some(Lifetime::from_repr(syntax.into_repr())),
1796 _ => None,
1797 }
1798 }
1799 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1800}
1801
1802impl ToOwned for Lifetime {
1803 type Owned = TreeArc<Lifetime>;
1804 fn to_owned(&self) -> TreeArc<Lifetime> { TreeArc::cast(self.syntax.to_owned()) }
1805}
1806
1807
1808impl ast::AstToken for Lifetime {}
1809impl Lifetime {}
1810
1811// LifetimeArg 1589// LifetimeArg
1812#[derive(Debug, PartialEq, Eq, Hash)] 1590#[derive(Debug, PartialEq, Eq, Hash)]
1813#[repr(transparent)] 1591#[repr(transparent)]
@@ -1834,11 +1612,7 @@ impl ToOwned for LifetimeArg {
1834} 1612}
1835 1613
1836 1614
1837impl LifetimeArg { 1615impl LifetimeArg {}
1838 pub fn lifetime(&self) -> Option<&Lifetime> {
1839 super::child_opt(self)
1840 }
1841}
1842 1616
1843// LifetimeParam 1617// LifetimeParam
1844#[derive(Debug, PartialEq, Eq, Hash)] 1618#[derive(Debug, PartialEq, Eq, Hash)]
@@ -1867,11 +1641,7 @@ impl ToOwned for LifetimeParam {
1867 1641
1868 1642
1869impl ast::AttrsOwner for LifetimeParam {} 1643impl ast::AttrsOwner for LifetimeParam {}
1870impl LifetimeParam { 1644impl LifetimeParam {}
1871 pub fn lifetime(&self) -> Option<&Lifetime> {
1872 super::child_opt(self)
1873 }
1874}
1875 1645
1876// Literal 1646// Literal
1877#[derive(Debug, PartialEq, Eq, Hash)] 1647#[derive(Debug, PartialEq, Eq, Hash)]
@@ -1899,130 +1669,7 @@ impl ToOwned for Literal {
1899} 1669}
1900 1670
1901 1671
1902impl Literal { 1672impl Literal {}
1903 pub fn literal_expr(&self) -> Option<&LiteralExpr> {
1904 super::child_opt(self)
1905 }
1906}
1907
1908// LiteralExpr
1909#[derive(Debug, PartialEq, Eq, Hash)]
1910#[repr(transparent)]
1911pub struct LiteralExpr {
1912 pub(crate) syntax: SyntaxNode,
1913}
1914unsafe impl TransparentNewType for LiteralExpr {
1915 type Repr = rowan::SyntaxNode<RaTypes>;
1916}
1917
1918#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1919pub enum LiteralExprKind<'a> {
1920 String(&'a String),
1921 ByteString(&'a ByteString),
1922 RawString(&'a RawString),
1923 RawByteString(&'a RawByteString),
1924 Char(&'a Char),
1925 Byte(&'a Byte),
1926 IntNumber(&'a IntNumber),
1927 FloatNumber(&'a FloatNumber),
1928 TrueKw(&'a TrueKw),
1929 FalseKw(&'a FalseKw),
1930}
1931impl<'a> From<&'a String> for &'a LiteralExpr {
1932 fn from(n: &'a String) -> &'a LiteralExpr {
1933 LiteralExpr::cast(&n.syntax).unwrap()
1934 }
1935}
1936impl<'a> From<&'a ByteString> for &'a LiteralExpr {
1937 fn from(n: &'a ByteString) -> &'a LiteralExpr {
1938 LiteralExpr::cast(&n.syntax).unwrap()
1939 }
1940}
1941impl<'a> From<&'a RawString> for &'a LiteralExpr {
1942 fn from(n: &'a RawString) -> &'a LiteralExpr {
1943 LiteralExpr::cast(&n.syntax).unwrap()
1944 }
1945}
1946impl<'a> From<&'a RawByteString> for &'a LiteralExpr {
1947 fn from(n: &'a RawByteString) -> &'a LiteralExpr {
1948 LiteralExpr::cast(&n.syntax).unwrap()
1949 }
1950}
1951impl<'a> From<&'a Char> for &'a LiteralExpr {
1952 fn from(n: &'a Char) -> &'a LiteralExpr {
1953 LiteralExpr::cast(&n.syntax).unwrap()
1954 }
1955}
1956impl<'a> From<&'a Byte> for &'a LiteralExpr {
1957 fn from(n: &'a Byte) -> &'a LiteralExpr {
1958 LiteralExpr::cast(&n.syntax).unwrap()
1959 }
1960}
1961impl<'a> From<&'a IntNumber> for &'a LiteralExpr {
1962 fn from(n: &'a IntNumber) -> &'a LiteralExpr {
1963 LiteralExpr::cast(&n.syntax).unwrap()
1964 }
1965}
1966impl<'a> From<&'a FloatNumber> for &'a LiteralExpr {
1967 fn from(n: &'a FloatNumber) -> &'a LiteralExpr {
1968 LiteralExpr::cast(&n.syntax).unwrap()
1969 }
1970}
1971impl<'a> From<&'a TrueKw> for &'a LiteralExpr {
1972 fn from(n: &'a TrueKw) -> &'a LiteralExpr {
1973 LiteralExpr::cast(&n.syntax).unwrap()
1974 }
1975}
1976impl<'a> From<&'a FalseKw> for &'a LiteralExpr {
1977 fn from(n: &'a FalseKw) -> &'a LiteralExpr {
1978 LiteralExpr::cast(&n.syntax).unwrap()
1979 }
1980}
1981
1982
1983impl AstNode for LiteralExpr {
1984 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1985 match syntax.kind() {
1986 | STRING
1987 | BYTE_STRING
1988 | RAW_STRING
1989 | RAW_BYTE_STRING
1990 | CHAR
1991 | BYTE
1992 | INT_NUMBER
1993 | FLOAT_NUMBER
1994 | TRUE_KW
1995 | FALSE_KW => Some(LiteralExpr::from_repr(syntax.into_repr())),
1996 _ => None,
1997 }
1998 }
1999 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2000}
2001
2002impl ToOwned for LiteralExpr {
2003 type Owned = TreeArc<LiteralExpr>;
2004 fn to_owned(&self) -> TreeArc<LiteralExpr> { TreeArc::cast(self.syntax.to_owned()) }
2005}
2006
2007impl LiteralExpr {
2008 pub fn kind(&self) -> LiteralExprKind {
2009 match self.syntax.kind() {
2010 STRING => LiteralExprKind::String(String::cast(&self.syntax).unwrap()),
2011 BYTE_STRING => LiteralExprKind::ByteString(ByteString::cast(&self.syntax).unwrap()),
2012 RAW_STRING => LiteralExprKind::RawString(RawString::cast(&self.syntax).unwrap()),
2013 RAW_BYTE_STRING => LiteralExprKind::RawByteString(RawByteString::cast(&self.syntax).unwrap()),
2014 CHAR => LiteralExprKind::Char(Char::cast(&self.syntax).unwrap()),
2015 BYTE => LiteralExprKind::Byte(Byte::cast(&self.syntax).unwrap()),
2016 INT_NUMBER => LiteralExprKind::IntNumber(IntNumber::cast(&self.syntax).unwrap()),
2017 FLOAT_NUMBER => LiteralExprKind::FloatNumber(FloatNumber::cast(&self.syntax).unwrap()),
2018 TRUE_KW => LiteralExprKind::TrueKw(TrueKw::cast(&self.syntax).unwrap()),
2019 FALSE_KW => LiteralExprKind::FalseKw(FalseKw::cast(&self.syntax).unwrap()),
2020 _ => unreachable!(),
2021 }
2022 }
2023}
2024
2025impl LiteralExpr {}
2026 1673
2027// LiteralPat 1674// LiteralPat
2028#[derive(Debug, PartialEq, Eq, Hash)] 1675#[derive(Debug, PartialEq, Eq, Hash)]
@@ -3406,64 +3053,6 @@ impl ToOwned for RangePat {
3406 3053
3407impl RangePat {} 3054impl RangePat {}
3408 3055
3409// RawByteString
3410#[derive(Debug, PartialEq, Eq, Hash)]
3411#[repr(transparent)]
3412pub struct RawByteString {
3413 pub(crate) syntax: SyntaxNode,
3414}
3415unsafe impl TransparentNewType for RawByteString {
3416 type Repr = rowan::SyntaxNode<RaTypes>;
3417}
3418
3419impl AstNode for RawByteString {
3420 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3421 match syntax.kind() {
3422 RAW_BYTE_STRING => Some(RawByteString::from_repr(syntax.into_repr())),
3423 _ => None,
3424 }
3425 }
3426 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3427}
3428
3429impl ToOwned for RawByteString {
3430 type Owned = TreeArc<RawByteString>;
3431 fn to_owned(&self) -> TreeArc<RawByteString> { TreeArc::cast(self.syntax.to_owned()) }
3432}
3433
3434
3435impl ast::AstToken for RawByteString {}
3436impl RawByteString {}
3437
3438// RawString
3439#[derive(Debug, PartialEq, Eq, Hash)]
3440#[repr(transparent)]
3441pub struct RawString {
3442 pub(crate) syntax: SyntaxNode,
3443}
3444unsafe impl TransparentNewType for RawString {
3445 type Repr = rowan::SyntaxNode<RaTypes>;
3446}
3447
3448impl AstNode for RawString {
3449 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3450 match syntax.kind() {
3451 RAW_STRING => Some(RawString::from_repr(syntax.into_repr())),
3452 _ => None,
3453 }
3454 }
3455 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3456}
3457
3458impl ToOwned for RawString {
3459 type Owned = TreeArc<RawString>;
3460 fn to_owned(&self) -> TreeArc<RawString> { TreeArc::cast(self.syntax.to_owned()) }
3461}
3462
3463
3464impl ast::AstToken for RawString {}
3465impl RawString {}
3466
3467// RefExpr 3056// RefExpr
3468#[derive(Debug, PartialEq, Eq, Hash)] 3057#[derive(Debug, PartialEq, Eq, Hash)]
3469#[repr(transparent)] 3058#[repr(transparent)]
@@ -3624,34 +3213,6 @@ impl ReturnExpr {
3624 } 3213 }
3625} 3214}
3626 3215
3627// SelfKw
3628#[derive(Debug, PartialEq, Eq, Hash)]
3629#[repr(transparent)]
3630pub struct SelfKw {
3631 pub(crate) syntax: SyntaxNode,
3632}
3633unsafe impl TransparentNewType for SelfKw {
3634 type Repr = rowan::SyntaxNode<RaTypes>;
3635}
3636
3637impl AstNode for SelfKw {
3638 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3639 match syntax.kind() {
3640 SELF_KW => Some(SelfKw::from_repr(syntax.into_repr())),
3641 _ => None,
3642 }
3643 }
3644 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3645}
3646
3647impl ToOwned for SelfKw {
3648 type Owned = TreeArc<SelfKw>;
3649 fn to_owned(&self) -> TreeArc<SelfKw> { TreeArc::cast(self.syntax.to_owned()) }
3650}
3651
3652
3653impl SelfKw {}
3654
3655// SelfParam 3216// SelfParam
3656#[derive(Debug, PartialEq, Eq, Hash)] 3217#[derive(Debug, PartialEq, Eq, Hash)]
3657#[repr(transparent)] 3218#[repr(transparent)]
@@ -3679,11 +3240,7 @@ impl ToOwned for SelfParam {
3679 3240
3680 3241
3681impl ast::TypeAscriptionOwner for SelfParam {} 3242impl ast::TypeAscriptionOwner for SelfParam {}
3682impl SelfParam { 3243impl SelfParam {}
3683 pub fn self_kw(&self) -> Option<&SelfKw> {
3684 super::child_opt(self)
3685 }
3686}
3687 3244
3688// SlicePat 3245// SlicePat
3689#[derive(Debug, PartialEq, Eq, Hash)] 3246#[derive(Debug, PartialEq, Eq, Hash)]
@@ -3872,35 +3429,6 @@ impl Stmt {
3872 3429
3873impl Stmt {} 3430impl Stmt {}
3874 3431
3875// String
3876#[derive(Debug, PartialEq, Eq, Hash)]
3877#[repr(transparent)]
3878pub struct String {
3879 pub(crate) syntax: SyntaxNode,
3880}
3881unsafe impl TransparentNewType for String {
3882 type Repr = rowan::SyntaxNode<RaTypes>;
3883}
3884
3885impl AstNode for String {
3886 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3887 match syntax.kind() {
3888 STRING => Some(String::from_repr(syntax.into_repr())),
3889 _ => None,
3890 }
3891 }
3892 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3893}
3894
3895impl ToOwned for String {
3896 type Owned = TreeArc<String>;
3897 fn to_owned(&self) -> TreeArc<String> { TreeArc::cast(self.syntax.to_owned()) }
3898}
3899
3900
3901impl ast::AstToken for String {}
3902impl String {}
3903
3904// StructDef 3432// StructDef
3905#[derive(Debug, PartialEq, Eq, Hash)] 3433#[derive(Debug, PartialEq, Eq, Hash)]
3906#[repr(transparent)] 3434#[repr(transparent)]
@@ -4069,41 +3597,13 @@ impl ast::NameOwner for TraitDef {}
4069impl ast::AttrsOwner for TraitDef {} 3597impl ast::AttrsOwner for TraitDef {}
4070impl ast::DocCommentsOwner for TraitDef {} 3598impl ast::DocCommentsOwner for TraitDef {}
4071impl ast::TypeParamsOwner for TraitDef {} 3599impl ast::TypeParamsOwner for TraitDef {}
3600impl ast::TypeBoundsOwner for TraitDef {}
4072impl TraitDef { 3601impl TraitDef {
4073 pub fn item_list(&self) -> Option<&ItemList> { 3602 pub fn item_list(&self) -> Option<&ItemList> {
4074 super::child_opt(self) 3603 super::child_opt(self)
4075 } 3604 }
4076} 3605}
4077 3606
4078// TrueKw
4079#[derive(Debug, PartialEq, Eq, Hash)]
4080#[repr(transparent)]
4081pub struct TrueKw {
4082 pub(crate) syntax: SyntaxNode,
4083}
4084unsafe impl TransparentNewType for TrueKw {
4085 type Repr = rowan::SyntaxNode<RaTypes>;
4086}
4087
4088impl AstNode for TrueKw {
4089 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
4090 match syntax.kind() {
4091 TRUE_KW => Some(TrueKw::from_repr(syntax.into_repr())),
4092 _ => None,
4093 }
4094 }
4095 fn syntax(&self) -> &SyntaxNode { &self.syntax }
4096}
4097
4098impl ToOwned for TrueKw {
4099 type Owned = TreeArc<TrueKw>;
4100 fn to_owned(&self) -> TreeArc<TrueKw> { TreeArc::cast(self.syntax.to_owned()) }
4101}
4102
4103
4104impl ast::AstToken for TrueKw {}
4105impl TrueKw {}
4106
4107// TryExpr 3607// TryExpr
4108#[derive(Debug, PartialEq, Eq, Hash)] 3608#[derive(Debug, PartialEq, Eq, Hash)]
4109#[repr(transparent)] 3609#[repr(transparent)]
@@ -4299,6 +3799,7 @@ impl ast::NameOwner for TypeAliasDef {}
4299impl ast::TypeParamsOwner for TypeAliasDef {} 3799impl ast::TypeParamsOwner for TypeAliasDef {}
4300impl ast::AttrsOwner for TypeAliasDef {} 3800impl ast::AttrsOwner for TypeAliasDef {}
4301impl ast::DocCommentsOwner for TypeAliasDef {} 3801impl ast::DocCommentsOwner for TypeAliasDef {}
3802impl ast::TypeBoundsOwner for TypeAliasDef {}
4302impl TypeAliasDef { 3803impl TypeAliasDef {
4303 pub fn type_ref(&self) -> Option<&TypeRef> { 3804 pub fn type_ref(&self) -> Option<&TypeRef> {
4304 super::child_opt(self) 3805 super::child_opt(self)
@@ -4377,6 +3878,70 @@ impl TypeArgList {
4377 } 3878 }
4378} 3879}
4379 3880
3881// TypeBound
3882#[derive(Debug, PartialEq, Eq, Hash)]
3883#[repr(transparent)]
3884pub struct TypeBound {
3885 pub(crate) syntax: SyntaxNode,
3886}
3887unsafe impl TransparentNewType for TypeBound {
3888 type Repr = rowan::SyntaxNode<RaTypes>;
3889}
3890
3891impl AstNode for TypeBound {
3892 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3893 match syntax.kind() {
3894 TYPE_BOUND => Some(TypeBound::from_repr(syntax.into_repr())),
3895 _ => None,
3896 }
3897 }
3898 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3899}
3900
3901impl ToOwned for TypeBound {
3902 type Owned = TreeArc<TypeBound>;
3903 fn to_owned(&self) -> TreeArc<TypeBound> { TreeArc::cast(self.syntax.to_owned()) }
3904}
3905
3906
3907impl TypeBound {
3908 pub fn type_ref(&self) -> Option<&TypeRef> {
3909 super::child_opt(self)
3910 }
3911}
3912
3913// TypeBoundList
3914#[derive(Debug, PartialEq, Eq, Hash)]
3915#[repr(transparent)]
3916pub struct TypeBoundList {
3917 pub(crate) syntax: SyntaxNode,
3918}
3919unsafe impl TransparentNewType for TypeBoundList {
3920 type Repr = rowan::SyntaxNode<RaTypes>;
3921}
3922
3923impl AstNode for TypeBoundList {
3924 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3925 match syntax.kind() {
3926 TYPE_BOUND_LIST => Some(TypeBoundList::from_repr(syntax.into_repr())),
3927 _ => None,
3928 }
3929 }
3930 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3931}
3932
3933impl ToOwned for TypeBoundList {
3934 type Owned = TreeArc<TypeBoundList>;
3935 fn to_owned(&self) -> TreeArc<TypeBoundList> { TreeArc::cast(self.syntax.to_owned()) }
3936}
3937
3938
3939impl TypeBoundList {
3940 pub fn bounds(&self) -> impl Iterator<Item = &TypeBound> {
3941 super::children(self)
3942 }
3943}
3944
4380// TypeParam 3945// TypeParam
4381#[derive(Debug, PartialEq, Eq, Hash)] 3946#[derive(Debug, PartialEq, Eq, Hash)]
4382#[repr(transparent)] 3947#[repr(transparent)]
@@ -4405,6 +3970,7 @@ impl ToOwned for TypeParam {
4405 3970
4406impl ast::NameOwner for TypeParam {} 3971impl ast::NameOwner for TypeParam {}
4407impl ast::AttrsOwner for TypeParam {} 3972impl ast::AttrsOwner for TypeParam {}
3973impl ast::TypeBoundsOwner for TypeParam {}
4408impl TypeParam {} 3974impl TypeParam {}
4409 3975
4410// TypeParamList 3976// TypeParamList
@@ -4745,67 +4311,75 @@ impl ToOwned for WhereClause {
4745} 4311}
4746 4312
4747 4313
4748impl WhereClause {} 4314impl WhereClause {
4315 pub fn predicates(&self) -> impl Iterator<Item = &WherePred> {
4316 super::children(self)
4317 }
4318}
4749 4319
4750// WhileExpr 4320// WherePred
4751#[derive(Debug, PartialEq, Eq, Hash)] 4321#[derive(Debug, PartialEq, Eq, Hash)]
4752#[repr(transparent)] 4322#[repr(transparent)]
4753pub struct WhileExpr { 4323pub struct WherePred {
4754 pub(crate) syntax: SyntaxNode, 4324 pub(crate) syntax: SyntaxNode,
4755} 4325}
4756unsafe impl TransparentNewType for WhileExpr { 4326unsafe impl TransparentNewType for WherePred {
4757 type Repr = rowan::SyntaxNode<RaTypes>; 4327 type Repr = rowan::SyntaxNode<RaTypes>;
4758} 4328}
4759 4329
4760impl AstNode for WhileExpr { 4330impl AstNode for WherePred {
4761 fn cast(syntax: &SyntaxNode) -> Option<&Self> { 4331 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
4762 match syntax.kind() { 4332 match syntax.kind() {
4763 WHILE_EXPR => Some(WhileExpr::from_repr(syntax.into_repr())), 4333 WHERE_PRED => Some(WherePred::from_repr(syntax.into_repr())),
4764 _ => None, 4334 _ => None,
4765 } 4335 }
4766 } 4336 }
4767 fn syntax(&self) -> &SyntaxNode { &self.syntax } 4337 fn syntax(&self) -> &SyntaxNode { &self.syntax }
4768} 4338}
4769 4339
4770impl ToOwned for WhileExpr { 4340impl ToOwned for WherePred {
4771 type Owned = TreeArc<WhileExpr>; 4341 type Owned = TreeArc<WherePred>;
4772 fn to_owned(&self) -> TreeArc<WhileExpr> { TreeArc::cast(self.syntax.to_owned()) } 4342 fn to_owned(&self) -> TreeArc<WherePred> { TreeArc::cast(self.syntax.to_owned()) }
4773} 4343}
4774 4344
4775 4345
4776impl ast::LoopBodyOwner for WhileExpr {} 4346impl ast::TypeBoundsOwner for WherePred {}
4777impl WhileExpr { 4347impl WherePred {
4778 pub fn condition(&self) -> Option<&Condition> { 4348 pub fn type_ref(&self) -> Option<&TypeRef> {
4779 super::child_opt(self) 4349 super::child_opt(self)
4780 } 4350 }
4781} 4351}
4782 4352
4783// Whitespace 4353// WhileExpr
4784#[derive(Debug, PartialEq, Eq, Hash)] 4354#[derive(Debug, PartialEq, Eq, Hash)]
4785#[repr(transparent)] 4355#[repr(transparent)]
4786pub struct Whitespace { 4356pub struct WhileExpr {
4787 pub(crate) syntax: SyntaxNode, 4357 pub(crate) syntax: SyntaxNode,
4788} 4358}
4789unsafe impl TransparentNewType for Whitespace { 4359unsafe impl TransparentNewType for WhileExpr {
4790 type Repr = rowan::SyntaxNode<RaTypes>; 4360 type Repr = rowan::SyntaxNode<RaTypes>;
4791} 4361}
4792 4362
4793impl AstNode for Whitespace { 4363impl AstNode for WhileExpr {
4794 fn cast(syntax: &SyntaxNode) -> Option<&Self> { 4364 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
4795 match syntax.kind() { 4365 match syntax.kind() {
4796 WHITESPACE => Some(Whitespace::from_repr(syntax.into_repr())), 4366 WHILE_EXPR => Some(WhileExpr::from_repr(syntax.into_repr())),
4797 _ => None, 4367 _ => None,
4798 } 4368 }
4799 } 4369 }
4800 fn syntax(&self) -> &SyntaxNode { &self.syntax } 4370 fn syntax(&self) -> &SyntaxNode { &self.syntax }
4801} 4371}
4802 4372
4803impl ToOwned for Whitespace { 4373impl ToOwned for WhileExpr {
4804 type Owned = TreeArc<Whitespace>; 4374 type Owned = TreeArc<WhileExpr>;
4805 fn to_owned(&self) -> TreeArc<Whitespace> { TreeArc::cast(self.syntax.to_owned()) } 4375 fn to_owned(&self) -> TreeArc<WhileExpr> { TreeArc::cast(self.syntax.to_owned()) }
4806} 4376}
4807 4377
4808 4378
4809impl ast::AstToken for Whitespace {} 4379impl ast::LoopBodyOwner for WhileExpr {}
4810impl Whitespace {} 4380impl WhileExpr {
4381 pub fn condition(&self) -> Option<&Condition> {
4382 super::child_opt(self)
4383 }
4384}
4811 4385
diff --git a/crates/ra_syntax/src/ast/tokens.rs b/crates/ra_syntax/src/ast/tokens.rs
new file mode 100644
index 000000000..08882ea69
--- /dev/null
+++ b/crates/ra_syntax/src/ast/tokens.rs
@@ -0,0 +1,113 @@
1//! There are many AstNodes, but only a few tokens, so we hand-write them here.
2
3use crate::{
4 SyntaxToken,
5 SyntaxKind::{COMMENT, WHITESPACE},
6 ast::AstToken,
7};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub struct Comment<'a>(SyntaxToken<'a>);
11
12impl<'a> AstToken<'a> for Comment<'a> {
13 fn cast(token: SyntaxToken<'a>) -> Option<Self> {
14 if token.kind() == COMMENT {
15 Some(Comment(token))
16 } else {
17 None
18 }
19 }
20 fn syntax(&self) -> SyntaxToken<'a> {
21 self.0
22 }
23}
24
25impl<'a> Comment<'a> {
26 pub fn kind(&self) -> CommentKind {
27 kind_by_prefix(self.text())
28 }
29
30 pub fn prefix(&self) -> &'static str {
31 prefix_by_kind(self.kind())
32 }
33}
34
35#[derive(Debug, PartialEq, Eq, Clone, Copy)]
36pub struct CommentKind {
37 pub shape: CommentShape,
38 pub doc: Option<CommentPlacement>,
39}
40
41#[derive(Debug, PartialEq, Eq, Clone, Copy)]
42pub enum CommentShape {
43 Line,
44 Block,
45}
46
47impl CommentShape {
48 pub fn is_line(self) -> bool {
49 self == CommentShape::Line
50 }
51
52 pub fn is_block(self) -> bool {
53 self == CommentShape::Block
54 }
55}
56
57#[derive(Debug, PartialEq, Eq, Clone, Copy)]
58pub enum CommentPlacement {
59 Inner,
60 Outer,
61}
62
63const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = {
64 use {CommentShape::*, CommentPlacement::*};
65 &[
66 ("///", CommentKind { shape: Line, doc: Some(Outer) }),
67 ("//!", CommentKind { shape: Line, doc: Some(Inner) }),
68 ("/**", CommentKind { shape: Block, doc: Some(Outer) }),
69 ("/*!", CommentKind { shape: Block, doc: Some(Inner) }),
70 ("//", CommentKind { shape: Line, doc: None }),
71 ("/*", CommentKind { shape: Block, doc: None }),
72 ]
73};
74
75fn kind_by_prefix(text: &str) -> CommentKind {
76 for (prefix, kind) in COMMENT_PREFIX_TO_KIND.iter() {
77 if text.starts_with(prefix) {
78 return *kind;
79 }
80 }
81 panic!("bad comment text: {:?}", text)
82}
83
84fn prefix_by_kind(kind: CommentKind) -> &'static str {
85 for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() {
86 if *k == kind {
87 return prefix;
88 }
89 }
90 unreachable!()
91}
92
93pub struct Whitespace<'a>(SyntaxToken<'a>);
94
95impl<'a> AstToken<'a> for Whitespace<'a> {
96 fn cast(token: SyntaxToken<'a>) -> Option<Self> {
97 if token.kind() == WHITESPACE {
98 Some(Whitespace(token))
99 } else {
100 None
101 }
102 }
103 fn syntax(&self) -> SyntaxToken<'a> {
104 self.0
105 }
106}
107
108impl<'a> Whitespace<'a> {
109 pub fn spans_multiple_lines(&self) -> bool {
110 let text = self.text();
111 text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n'))
112 }
113}
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs
new file mode 100644
index 000000000..aaf07d731
--- /dev/null
+++ b/crates/ra_syntax/src/ast/traits.rs
@@ -0,0 +1,154 @@
1//! Various traits that are implemented by ast nodes.
2//!
3//! The implementations are usually trivial, and live in generated.rs
4
5use itertools::Itertools;
6
7use crate::{
8 syntax_node::{SyntaxNodeChildren, SyntaxElementChildren},
9 ast::{self, child_opt, children, AstNode, AstToken, AstChildren},
10};
11
12pub trait TypeAscriptionOwner: AstNode {
13 fn ascribed_type(&self) -> Option<&ast::TypeRef> {
14 child_opt(self)
15 }
16}
17
18pub trait NameOwner: AstNode {
19 fn name(&self) -> Option<&ast::Name> {
20 child_opt(self)
21 }
22}
23
24pub trait VisibilityOwner: AstNode {
25 fn visibility(&self) -> Option<&ast::Visibility> {
26 child_opt(self)
27 }
28}
29
30pub trait LoopBodyOwner: AstNode {
31 fn loop_body(&self) -> Option<&ast::Block> {
32 child_opt(self)
33 }
34}
35
36pub trait ArgListOwner: AstNode {
37 fn arg_list(&self) -> Option<&ast::ArgList> {
38 child_opt(self)
39 }
40}
41
42pub trait FnDefOwner: AstNode {
43 fn functions(&self) -> AstChildren<ast::FnDef> {
44 children(self)
45 }
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum ItemOrMacro<'a> {
50 Item(&'a ast::ModuleItem),
51 Macro(&'a ast::MacroCall),
52}
53
54pub trait ModuleItemOwner: AstNode {
55 fn items(&self) -> AstChildren<ast::ModuleItem> {
56 children(self)
57 }
58 fn items_with_macros(&self) -> ItemOrMacroIter {
59 ItemOrMacroIter(self.syntax().children())
60 }
61}
62
63#[derive(Debug)]
64pub struct ItemOrMacroIter<'a>(SyntaxNodeChildren<'a>);
65
66impl<'a> Iterator for ItemOrMacroIter<'a> {
67 type Item = ItemOrMacro<'a>;
68 fn next(&mut self) -> Option<ItemOrMacro<'a>> {
69 loop {
70 let n = self.0.next()?;
71 if let Some(item) = ast::ModuleItem::cast(n) {
72 return Some(ItemOrMacro::Item(item));
73 }
74 if let Some(call) = ast::MacroCall::cast(n) {
75 return Some(ItemOrMacro::Macro(call));
76 }
77 }
78 }
79}
80
81pub trait TypeParamsOwner: AstNode {
82 fn type_param_list(&self) -> Option<&ast::TypeParamList> {
83 child_opt(self)
84 }
85
86 fn where_clause(&self) -> Option<&ast::WhereClause> {
87 child_opt(self)
88 }
89}
90
91pub trait TypeBoundsOwner: AstNode {
92 fn type_bound_list(&self) -> Option<&ast::TypeBoundList> {
93 child_opt(self)
94 }
95}
96
97pub trait AttrsOwner: AstNode {
98 fn attrs(&self) -> AstChildren<ast::Attr> {
99 children(self)
100 }
101 fn has_atom_attr(&self, atom: &str) -> bool {
102 self.attrs().filter_map(|x| x.as_atom()).any(|x| x == atom)
103 }
104}
105
106pub trait DocCommentsOwner: AstNode {
107 fn doc_comments(&self) -> CommentIter {
108 CommentIter { iter: self.syntax().children_with_tokens() }
109 }
110
111 /// Returns the textual content of a doc comment block as a single string.
112 /// That is, strips leading `///` (+ optional 1 character of whitespace)
113 /// and joins lines.
114 fn doc_comment_text(&self) -> Option<String> {
115 let mut has_comments = false;
116 let docs = self
117 .doc_comments()
118 .filter(|comment| comment.kind().doc.is_some())
119 .map(|comment| {
120 has_comments = true;
121 let prefix_len = comment.prefix().len();
122
123 let line = comment.text().as_str();
124
125 // Determine if the prefix or prefix + 1 char is stripped
126 let pos =
127 if line.chars().nth(prefix_len).map(|c| c.is_whitespace()).unwrap_or(false) {
128 prefix_len + 1
129 } else {
130 prefix_len
131 };
132
133 line[pos..].to_owned()
134 })
135 .join("\n");
136
137 if has_comments {
138 Some(docs)
139 } else {
140 None
141 }
142 }
143}
144
145pub struct CommentIter<'a> {
146 iter: SyntaxElementChildren<'a>,
147}
148
149impl<'a> Iterator for CommentIter<'a> {
150 type Item = ast::Comment<'a>;
151 fn next(&mut self) -> Option<ast::Comment<'a>> {
152 self.iter.by_ref().find_map(|el| el.as_token().and_then(ast::Comment::cast))
153 }
154}
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index a21c3917d..0a35e25d5 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -243,6 +243,8 @@ Grammar(
243 "PARAM", 243 "PARAM",
244 "SELF_PARAM", 244 "SELF_PARAM",
245 "ARG_LIST", 245 "ARG_LIST",
246 "TYPE_BOUND",
247 "TYPE_BOUND_LIST",
246 ], 248 ],
247 ast: { 249 ast: {
248 "SourceFile": ( 250 "SourceFile": (
@@ -293,7 +295,7 @@ Grammar(
293 "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ), 295 "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ),
294 "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner", "AttrsOwner"], options: ["Expr"] ), 296 "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner", "AttrsOwner"], options: ["Expr"] ),
295 "TraitDef": ( 297 "TraitDef": (
296 traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner", "TypeParamsOwner"], 298 traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner", "TypeParamsOwner", "TypeBoundsOwner"],
297 options: ["ItemList"] 299 options: ["ItemList"]
298 ), 300 ),
299 "Module": ( 301 "Module": (
@@ -332,7 +334,8 @@ Grammar(
332 "NameOwner", 334 "NameOwner",
333 "TypeParamsOwner", 335 "TypeParamsOwner",
334 "AttrsOwner", 336 "AttrsOwner",
335 "DocCommentsOwner" 337 "DocCommentsOwner",
338 "TypeBoundsOwner",
336 ], 339 ],
337 options: ["TypeRef"] 340 options: ["TypeRef"]
338 ), 341 ),
@@ -349,8 +352,12 @@ Grammar(
349 "PlaceholderType": (), 352 "PlaceholderType": (),
350 "FnPointerType": (options: ["ParamList", "RetType"]), 353 "FnPointerType": (options: ["ParamList", "RetType"]),
351 "ForType": (options: ["TypeRef"]), 354 "ForType": (options: ["TypeRef"]),
352 "ImplTraitType": (), 355 "ImplTraitType": (
353 "DynTraitType": (), 356 traits: ["TypeBoundsOwner"],
357 ),
358 "DynTraitType": (
359 traits: ["TypeBoundsOwner"],
360 ),
354 361
355 "TypeRef": ( enum: [ 362 "TypeRef": ( enum: [
356 "ParenType", 363 "ParenType",
@@ -458,31 +465,7 @@ Grammar(
458 "RangeExpr": (), 465 "RangeExpr": (),
459 "BinExpr": (), 466 "BinExpr": (),
460 467
461 "IntNumber": ( traits: ["AstToken"] ), 468 "Literal": (),
462 "FloatNumber": ( traits: ["AstToken"] ),
463 "String": ( traits: ["AstToken"] ),
464 "RawString": ( traits: ["AstToken"] ),
465 "Byte": ( traits: ["AstToken"] ),
466 "RawByteString": ( traits: ["AstToken"] ),
467 "ByteString": ( traits: ["AstToken"] ),
468 "Char": ( traits: ["AstToken"] ),
469 "TrueKw": ( traits: ["AstToken"] ),
470 "FalseKw": ( traits: ["AstToken"] ),
471 "LiteralExpr": (
472 enum: [
473 "String",
474 "ByteString",
475 "RawString",
476 "RawByteString",
477 "Char",
478 "Byte",
479 "IntNumber",
480 "FloatNumber",
481 "TrueKw",
482 "FalseKw",
483 ]
484 ),
485 "Literal": (options: ["LiteralExpr"]),
486 469
487 "Expr": ( 470 "Expr": (
488 enum: [ 471 enum: [
@@ -513,6 +496,7 @@ Grammar(
513 "RangeExpr", 496 "RangeExpr",
514 "BinExpr", 497 "BinExpr",
515 "Literal", 498 "Literal",
499 "MacroCall",
516 ], 500 ],
517 ), 501 ),
518 502
@@ -573,13 +557,33 @@ Grammar(
573 ["lifetime_params", "LifetimeParam" ], 557 ["lifetime_params", "LifetimeParam" ],
574 ] 558 ]
575 ), 559 ),
576 "TypeParam": ( traits: ["NameOwner", "AttrsOwner"] ), 560 "TypeParam": ( traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner"] ),
577 "LifetimeParam": ( 561 "LifetimeParam": (
578 options: [ "Lifetime"],
579 traits: ["AttrsOwner"], 562 traits: ["AttrsOwner"],
580 ), 563 ),
581 "Lifetime": ( traits: ["AstToken"] ), 564 "TypeBound": (
582 "WhereClause": (), 565 options: [
566 "TypeRef",
567 ]
568 ),
569 "TypeBoundList": (
570 collections: [
571 ["bounds", "TypeBound"],
572 ]
573 ),
574 "WherePred": (
575 options: [
576 "TypeRef",
577 ],
578 traits: [
579 "TypeBoundsOwner",
580 ],
581 ),
582 "WhereClause": (
583 collections: [
584 ["predicates", "WherePred"],
585 ],
586 ),
583 "ExprStmt": ( 587 "ExprStmt": (
584 options: [ ["expr", "Expr"] ] 588 options: [ ["expr", "Expr"] ]
585 ), 589 ),
@@ -614,12 +618,10 @@ Grammar(
614 ] 618 ]
615 ), 619 ),
616 "SelfParam": ( 620 "SelfParam": (
617 options: ["SelfKw"],
618 traits: [ 621 traits: [
619 "TypeAscriptionOwner", 622 "TypeAscriptionOwner",
620 ] 623 ]
621 ), 624 ),
622 "SelfKw": (),
623 "Param": ( 625 "Param": (
624 options: [ "Pat" ], 626 options: [ "Pat" ],
625 traits: [ 627 traits: [
@@ -663,8 +665,6 @@ Grammar(
663 ]), 665 ]),
664 "TypeArg": (options: ["TypeRef"]), 666 "TypeArg": (options: ["TypeRef"]),
665 "AssocTypeArg": (options: ["NameRef", "TypeRef"]), 667 "AssocTypeArg": (options: ["NameRef", "TypeRef"]),
666 "LifetimeArg": (options: ["Lifetime"]), 668 "LifetimeArg": (),
667 "Comment": ( traits: ["AstToken"] ),
668 "Whitespace": ( traits: ["AstToken"] ),
669 }, 669 },
670) 670)
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 4f3020440..e1088e296 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -38,7 +38,7 @@ pub use crate::{
38 ast::AstNode, 38 ast::AstNode,
39 syntax_error::{SyntaxError, SyntaxErrorKind, Location}, 39 syntax_error::{SyntaxError, SyntaxErrorKind, Location},
40 syntax_text::SyntaxText, 40 syntax_text::SyntaxText,
41 syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc, SyntaxTreeBuilder}, 41 syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc, SyntaxTreeBuilder, SyntaxElement, SyntaxToken},
42 ptr::{SyntaxNodePtr, AstPtr}, 42 ptr::{SyntaxNodePtr, AstPtr},
43 parsing::{tokenize, Token}, 43 parsing::{tokenize, Token},
44}; 44};
@@ -70,7 +70,7 @@ impl SourceFile {
70 70
71 pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<TreeArc<SourceFile>> { 71 pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<TreeArc<SourceFile>> {
72 parsing::incremental_reparse(self.syntax(), edit, self.errors()) 72 parsing::incremental_reparse(self.syntax(), edit, self.errors())
73 .map(|(green_node, errors)| SourceFile::new(green_node, errors)) 73 .map(|(green_node, errors, _reparsed_range)| SourceFile::new(green_node, errors))
74 } 74 }
75 75
76 fn full_reparse(&self, edit: &AtomTextEdit) -> TreeArc<SourceFile> { 76 fn full_reparse(&self, edit: &AtomTextEdit) -> TreeArc<SourceFile> {
@@ -179,15 +179,23 @@ fn api_walkthrough() {
179 179
180 // There's a bunch of traversal methods on `SyntaxNode`: 180 // There's a bunch of traversal methods on `SyntaxNode`:
181 assert_eq!(expr_syntax.parent(), Some(block.syntax())); 181 assert_eq!(expr_syntax.parent(), Some(block.syntax()));
182 assert_eq!(block.syntax().first_child().map(|it| it.kind()), Some(SyntaxKind::L_CURLY)); 182 assert_eq!(
183 assert_eq!(expr_syntax.next_sibling().map(|it| it.kind()), Some(SyntaxKind::WHITESPACE)); 183 block.syntax().first_child_or_token().map(|it| it.kind()),
184 Some(SyntaxKind::L_CURLY)
185 );
186 assert_eq!(
187 expr_syntax.next_sibling_or_token().map(|it| it.kind()),
188 Some(SyntaxKind::WHITESPACE)
189 );
184 190
185 // As well as some iterator helpers: 191 // As well as some iterator helpers:
186 let f = expr_syntax.ancestors().find_map(ast::FnDef::cast); 192 let f = expr_syntax.ancestors().find_map(ast::FnDef::cast);
187 assert_eq!(f, Some(&*func)); 193 assert_eq!(f, Some(&*func));
188 assert!(expr_syntax.siblings(Direction::Next).any(|it| it.kind() == SyntaxKind::R_CURLY)); 194 assert!(expr_syntax
195 .siblings_with_tokens(Direction::Next)
196 .any(|it| it.kind() == SyntaxKind::R_CURLY));
189 assert_eq!( 197 assert_eq!(
190 expr_syntax.descendants().count(), 198 expr_syntax.descendants_with_tokens().count(),
191 8, // 5 tokens `1`, ` `, `+`, ` `, `!` 199 8, // 5 tokens `1`, ` `, `+`, ` `, `!`
192 // 2 child literal expressions: `1`, `1` 200 // 2 child literal expressions: `1`, `1`
193 // 1 the node itself: `1 + 1` 201 // 1 the node itself: `1 + 1`
@@ -196,16 +204,14 @@ fn api_walkthrough() {
196 // There's also a `preorder` method with a more fine-grained iteration control: 204 // There's also a `preorder` method with a more fine-grained iteration control:
197 let mut buf = String::new(); 205 let mut buf = String::new();
198 let mut indent = 0; 206 let mut indent = 0;
199 for event in expr_syntax.preorder() { 207 for event in expr_syntax.preorder_with_tokens() {
200 match event { 208 match event {
201 WalkEvent::Enter(node) => { 209 WalkEvent::Enter(node) => {
202 buf += &format!( 210 let text = match node {
203 "{:indent$}{:?} {:?}\n", 211 SyntaxElement::Node(it) => it.text().to_string(),
204 " ", 212 SyntaxElement::Token(it) => it.text().to_string(),
205 node.text(), 213 };
206 node.kind(), 214 buf += &format!("{:indent$}{:?} {:?}\n", " ", text, node.kind(), indent = indent);
207 indent = indent
208 );
209 indent += 2; 215 indent += 2;
210 } 216 }
211 WalkEvent::Leave(_) => indent -= 2, 217 WalkEvent::Leave(_) => indent -= 2,
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs
index 7e7f914f5..69887f500 100644
--- a/crates/ra_syntax/src/parsing/reparsing.rs
+++ b/crates/ra_syntax/src/parsing/reparsing.rs
@@ -12,7 +12,7 @@ use ra_parser::Reparser;
12use crate::{ 12use crate::{
13 SyntaxKind::*, TextRange, TextUnit, SyntaxError, 13 SyntaxKind::*, TextRange, TextUnit, SyntaxError,
14 algo, 14 algo,
15 syntax_node::{GreenNode, SyntaxNode}, 15 syntax_node::{GreenNode, SyntaxNode, GreenToken, SyntaxElement},
16 parsing::{ 16 parsing::{
17 text_token_source::TextTokenSource, 17 text_token_source::TextTokenSource,
18 text_tree_sink::TextTreeSink, 18 text_tree_sink::TextTreeSink,
@@ -24,60 +24,62 @@ pub(crate) fn incremental_reparse(
24 node: &SyntaxNode, 24 node: &SyntaxNode,
25 edit: &AtomTextEdit, 25 edit: &AtomTextEdit,
26 errors: Vec<SyntaxError>, 26 errors: Vec<SyntaxError>,
27) -> Option<(GreenNode, Vec<SyntaxError>)> { 27) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
28 let (node, green, new_errors) = 28 if let Some((green, old_range)) = reparse_token(node, &edit) {
29 reparse_leaf(node, &edit).or_else(|| reparse_block(node, &edit))?; 29 return Some((green, merge_errors(errors, Vec::new(), old_range, edit), old_range));
30 let green_root = node.replace_with(green); 30 }
31 let errors = merge_errors(errors, new_errors, node, edit); 31
32 Some((green_root, errors)) 32 if let Some((green, new_errors, old_range)) = reparse_block(node, &edit) {
33 return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
34 }
35 None
33} 36}
34 37
35fn reparse_leaf<'node>( 38fn reparse_token<'node>(
36 root: &'node SyntaxNode, 39 root: &'node SyntaxNode,
37 edit: &AtomTextEdit, 40 edit: &AtomTextEdit,
38) -> Option<(&'node SyntaxNode, GreenNode, Vec<SyntaxError>)> { 41) -> Option<(GreenNode, TextRange)> {
39 let node = algo::find_covering_node(root, edit.delete); 42 let token = algo::find_covering_element(root, edit.delete).as_token()?;
40 match node.kind() { 43 match token.kind() {
41 WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => { 44 WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => {
42 if node.kind() == WHITESPACE || node.kind() == COMMENT { 45 if token.kind() == WHITESPACE || token.kind() == COMMENT {
43 // removing a new line may extends previous token 46 // removing a new line may extends previous token
44 if node.text().to_string()[edit.delete - node.range().start()].contains('\n') { 47 if token.text().to_string()[edit.delete - token.range().start()].contains('\n') {
45 return None; 48 return None;
46 } 49 }
47 } 50 }
48 51
49 let text = get_text_after_edit(node, &edit); 52 let text = get_text_after_edit(token.into(), &edit);
50 let tokens = tokenize(&text); 53 let lex_tokens = tokenize(&text);
51 let token = match tokens[..] { 54 let lex_token = match lex_tokens[..] {
52 [token] if token.kind == node.kind() => token, 55 [lex_token] if lex_token.kind == token.kind() => lex_token,
53 _ => return None, 56 _ => return None,
54 }; 57 };
55 58
56 if token.kind == IDENT && is_contextual_kw(&text) { 59 if lex_token.kind == IDENT && is_contextual_kw(&text) {
57 return None; 60 return None;
58 } 61 }
59 62
60 if let Some(next_char) = root.text().char_at(node.range().end()) { 63 if let Some(next_char) = root.text().char_at(token.range().end()) {
61 let tokens_with_next_char = tokenize(&format!("{}{}", text, next_char)); 64 let tokens_with_next_char = tokenize(&format!("{}{}", text, next_char));
62 if tokens_with_next_char.len() == 1 { 65 if tokens_with_next_char.len() == 1 {
63 return None; 66 return None;
64 } 67 }
65 } 68 }
66 69
67 let green = GreenNode::new_leaf(node.kind(), text.into()); 70 let new_token = GreenToken::new(token.kind(), text.into());
68 let new_errors = vec![]; 71 Some((token.replace_with(new_token), token.range()))
69 Some((node, green, new_errors))
70 } 72 }
71 _ => None, 73 _ => None,
72 } 74 }
73} 75}
74 76
75fn reparse_block<'node>( 77fn reparse_block<'node>(
76 node: &'node SyntaxNode, 78 root: &'node SyntaxNode,
77 edit: &AtomTextEdit, 79 edit: &AtomTextEdit,
78) -> Option<(&'node SyntaxNode, GreenNode, Vec<SyntaxError>)> { 80) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
79 let (node, reparser) = find_reparsable_node(node, edit.delete)?; 81 let (node, reparser) = find_reparsable_node(root, edit.delete)?;
80 let text = get_text_after_edit(node, &edit); 82 let text = get_text_after_edit(node.into(), &edit);
81 let tokens = tokenize(&text); 83 let tokens = tokenize(&text);
82 if !is_balanced(&tokens) { 84 if !is_balanced(&tokens) {
83 return None; 85 return None;
@@ -86,12 +88,16 @@ fn reparse_block<'node>(
86 let mut tree_sink = TextTreeSink::new(&text, &tokens); 88 let mut tree_sink = TextTreeSink::new(&text, &tokens);
87 reparser.parse(&token_source, &mut tree_sink); 89 reparser.parse(&token_source, &mut tree_sink);
88 let (green, new_errors) = tree_sink.finish(); 90 let (green, new_errors) = tree_sink.finish();
89 Some((node, green, new_errors)) 91 Some((node.replace_with(green), new_errors, node.range()))
90} 92}
91 93
92fn get_text_after_edit(node: &SyntaxNode, edit: &AtomTextEdit) -> String { 94fn get_text_after_edit(element: SyntaxElement, edit: &AtomTextEdit) -> String {
93 let edit = AtomTextEdit::replace(edit.delete - node.range().start(), edit.insert.clone()); 95 let edit = AtomTextEdit::replace(edit.delete - element.range().start(), edit.insert.clone());
94 edit.apply(node.text().to_string()) 96 let text = match element {
97 SyntaxElement::Token(token) => token.text().to_string(),
98 SyntaxElement::Node(node) => node.text().to_string(),
99 };
100 edit.apply(text)
95} 101}
96 102
97fn is_contextual_kw(text: &str) -> bool { 103fn is_contextual_kw(text: &str) -> bool {
@@ -102,9 +108,13 @@ fn is_contextual_kw(text: &str) -> bool {
102} 108}
103 109
104fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(&SyntaxNode, Reparser)> { 110fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(&SyntaxNode, Reparser)> {
105 let node = algo::find_covering_node(node, range); 111 let node = algo::find_covering_element(node, range);
106 node.ancestors().find_map(|node| { 112 let mut ancestors = match node {
107 let first_child = node.first_child().map(|it| it.kind()); 113 SyntaxElement::Token(it) => it.parent().ancestors(),
114 SyntaxElement::Node(it) => it.ancestors(),
115 };
116 ancestors.find_map(|node| {
117 let first_child = node.first_child_or_token().map(|it| it.kind());
108 let parent = node.parent().map(|it| it.kind()); 118 let parent = node.parent().map(|it| it.kind());
109 Reparser::for_node(node.kind(), first_child, parent).map(|r| (node, r)) 119 Reparser::for_node(node.kind(), first_child, parent).map(|r| (node, r))
110 }) 120 })
@@ -136,19 +146,19 @@ fn is_balanced(tokens: &[Token]) -> bool {
136fn merge_errors( 146fn merge_errors(
137 old_errors: Vec<SyntaxError>, 147 old_errors: Vec<SyntaxError>,
138 new_errors: Vec<SyntaxError>, 148 new_errors: Vec<SyntaxError>,
139 old_node: &SyntaxNode, 149 old_range: TextRange,
140 edit: &AtomTextEdit, 150 edit: &AtomTextEdit,
141) -> Vec<SyntaxError> { 151) -> Vec<SyntaxError> {
142 let mut res = Vec::new(); 152 let mut res = Vec::new();
143 for e in old_errors { 153 for e in old_errors {
144 if e.offset() <= old_node.range().start() { 154 if e.offset() <= old_range.start() {
145 res.push(e) 155 res.push(e)
146 } else if e.offset() >= old_node.range().end() { 156 } else if e.offset() >= old_range.end() {
147 res.push(e.add_offset(TextUnit::of_str(&edit.insert), edit.delete.len())); 157 res.push(e.add_offset(TextUnit::of_str(&edit.insert), edit.delete.len()));
148 } 158 }
149 } 159 }
150 for e in new_errors { 160 for e in new_errors {
151 res.push(e.add_offset(old_node.range().start(), 0.into())); 161 res.push(e.add_offset(old_range.start(), 0.into()));
152 } 162 }
153 res 163 res
154} 164}
@@ -160,13 +170,7 @@ mod tests {
160 use crate::{SourceFile, AstNode}; 170 use crate::{SourceFile, AstNode};
161 use super::*; 171 use super::*;
162 172
163 fn do_check<F>(before: &str, replace_with: &str, reparser: F) 173 fn do_check(before: &str, replace_with: &str, reparsed_len: u32) {
164 where
165 for<'a> F: Fn(
166 &'a SyntaxNode,
167 &AtomTextEdit,
168 ) -> Option<(&'a SyntaxNode, GreenNode, Vec<SyntaxError>)>,
169 {
170 let (range, before) = extract_range(before); 174 let (range, before) = extract_range(before);
171 let edit = AtomTextEdit::replace(range, replace_with.to_owned()); 175 let edit = AtomTextEdit::replace(range, replace_with.to_owned());
172 let after = edit.apply(before.clone()); 176 let after = edit.apply(before.clone());
@@ -175,23 +179,20 @@ mod tests {
175 let incrementally_reparsed = { 179 let incrementally_reparsed = {
176 let f = SourceFile::parse(&before); 180 let f = SourceFile::parse(&before);
177 let edit = AtomTextEdit { delete: range, insert: replace_with.to_string() }; 181 let edit = AtomTextEdit { delete: range, insert: replace_with.to_string() };
178 let (node, green, new_errors) = 182 let (green, new_errors, range) =
179 reparser(f.syntax(), &edit).expect("cannot incrementally reparse"); 183 incremental_reparse(f.syntax(), &edit, f.errors()).unwrap();
180 let green_root = node.replace_with(green); 184 assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length");
181 let errors = super::merge_errors(f.errors(), new_errors, node, &edit); 185 SourceFile::new(green, new_errors)
182 SourceFile::new(green_root, errors)
183 }; 186 };
184 187
185 assert_eq_text!( 188 assert_eq_text!(
186 &fully_reparsed.syntax().debug_dump(), 189 &fully_reparsed.syntax().debug_dump(),
187 &incrementally_reparsed.syntax().debug_dump(), 190 &incrementally_reparsed.syntax().debug_dump(),
188 ) 191 );
189 } 192 }
190 193
191 #[test] 194 #[test] // FIXME: some test here actually test token reparsing
192 fn reparse_block_tests() { 195 fn reparse_block_tests() {
193 let do_check = |before, replace_to| do_check(before, replace_to, reparse_block);
194
195 do_check( 196 do_check(
196 r" 197 r"
197fn foo() { 198fn foo() {
@@ -199,6 +200,7 @@ fn foo() {
199} 200}
200", 201",
201 "baz", 202 "baz",
203 3,
202 ); 204 );
203 do_check( 205 do_check(
204 r" 206 r"
@@ -207,6 +209,7 @@ fn foo() {
207} 209}
208", 210",
209 "baz", 211 "baz",
212 25,
210 ); 213 );
211 do_check( 214 do_check(
212 r" 215 r"
@@ -215,6 +218,7 @@ struct Foo {
215} 218}
216", 219",
217 ",\n g: (),", 220 ",\n g: (),",
221 14,
218 ); 222 );
219 do_check( 223 do_check(
220 r" 224 r"
@@ -225,6 +229,7 @@ fn foo {
225} 229}
226", 230",
227 "62", 231 "62",
232 31, // FIXME: reparse only int literal here
228 ); 233 );
229 do_check( 234 do_check(
230 r" 235 r"
@@ -233,7 +238,9 @@ mod foo {
233} 238}
234", 239",
235 "bar", 240 "bar",
241 11,
236 ); 242 );
243
237 do_check( 244 do_check(
238 r" 245 r"
239trait Foo { 246trait Foo {
@@ -241,6 +248,7 @@ trait Foo {
241} 248}
242", 249",
243 "Output", 250 "Output",
251 3,
244 ); 252 );
245 do_check( 253 do_check(
246 r" 254 r"
@@ -249,13 +257,9 @@ impl IntoIterator<Item=i32> for Foo {
249} 257}
250", 258",
251 "n next(", 259 "n next(",
260 9,
252 ); 261 );
253 do_check( 262 do_check(r"use a::b::{foo,<|>,bar<|>};", "baz", 10);
254 r"
255use a::b::{foo,<|>,bar<|>};
256 ",
257 "baz",
258 );
259 do_check( 263 do_check(
260 r" 264 r"
261pub enum A { 265pub enum A {
@@ -263,12 +267,14 @@ pub enum A {
263} 267}
264", 268",
265 "\nBar;\n", 269 "\nBar;\n",
270 11,
266 ); 271 );
267 do_check( 272 do_check(
268 r" 273 r"
269foo!{a, b<|><|> d} 274foo!{a, b<|><|> d}
270", 275",
271 ", c[3]", 276 ", c[3]",
277 8,
272 ); 278 );
273 do_check( 279 do_check(
274 r" 280 r"
@@ -277,6 +283,7 @@ fn foo() {
277} 283}
278", 284",
279 "123", 285 "123",
286 14,
280 ); 287 );
281 do_check( 288 do_check(
282 r" 289 r"
@@ -285,54 +292,60 @@ extern {
285} 292}
286", 293",
287 " exit(code: c_int)", 294 " exit(code: c_int)",
295 11,
288 ); 296 );
289 } 297 }
290 298
291 #[test] 299 #[test]
292 fn reparse_leaf_tests() { 300 fn reparse_token_tests() {
293 let do_check = |before, replace_to| do_check(before, replace_to, reparse_leaf);
294
295 do_check( 301 do_check(
296 r"<|><|> 302 r"<|><|>
297fn foo() -> i32 { 1 } 303fn foo() -> i32 { 1 }
298", 304",
299 "\n\n\n \n", 305 "\n\n\n \n",
306 1,
300 ); 307 );
301 do_check( 308 do_check(
302 r" 309 r"
303fn foo() -> <|><|> {} 310fn foo() -> <|><|> {}
304", 311",
305 " \n", 312 " \n",
313 2,
306 ); 314 );
307 do_check( 315 do_check(
308 r" 316 r"
309fn <|>foo<|>() -> i32 { 1 } 317fn <|>foo<|>() -> i32 { 1 }
310", 318",
311 "bar", 319 "bar",
320 3,
312 ); 321 );
313 do_check( 322 do_check(
314 r" 323 r"
315fn foo<|><|>foo() { } 324fn foo<|><|>foo() { }
316", 325",
317 "bar", 326 "bar",
327 6,
318 ); 328 );
319 do_check( 329 do_check(
320 r" 330 r"
321fn foo /* <|><|> */ () {} 331fn foo /* <|><|> */ () {}
322", 332",
323 "some comment", 333 "some comment",
334 6,
324 ); 335 );
325 do_check( 336 do_check(
326 r" 337 r"
327fn baz <|><|> () {} 338fn baz <|><|> () {}
328", 339",
329 " \t\t\n\n", 340 " \t\t\n\n",
341 2,
330 ); 342 );
331 do_check( 343 do_check(
332 r" 344 r"
333fn baz <|><|> () {} 345fn baz <|><|> () {}
334", 346",
335 " \t\t\n\n", 347 " \t\t\n\n",
348 2,
336 ); 349 );
337 do_check( 350 do_check(
338 r" 351 r"
@@ -340,24 +353,28 @@ fn baz <|><|> () {}
340mod { } 353mod { }
341", 354",
342 "c", 355 "c",
356 14,
343 ); 357 );
344 do_check( 358 do_check(
345 r#" 359 r#"
346fn -> &str { "Hello<|><|>" } 360fn -> &str { "Hello<|><|>" }
347"#, 361"#,
348 ", world", 362 ", world",
363 7,
349 ); 364 );
350 do_check( 365 do_check(
351 r#" 366 r#"
352fn -> &str { // "Hello<|><|>" 367fn -> &str { // "Hello<|><|>"
353"#, 368"#,
354 ", world", 369 ", world",
370 10,
355 ); 371 );
356 do_check( 372 do_check(
357 r##" 373 r##"
358fn -> &str { r#"Hello<|><|>"# 374fn -> &str { r#"Hello<|><|>"#
359"##, 375"##,
360 ", world", 376 ", world",
377 10,
361 ); 378 );
362 do_check( 379 do_check(
363 r" 380 r"
@@ -367,6 +384,7 @@ enum Foo {
367} 384}
368", 385",
369 "Clone", 386 "Clone",
387 4,
370 ); 388 );
371 } 389 }
372} 390}
diff --git a/crates/ra_syntax/src/parsing/text_tree_sink.rs b/crates/ra_syntax/src/parsing/text_tree_sink.rs
index b17d06c61..71fc515f2 100644
--- a/crates/ra_syntax/src/parsing/text_tree_sink.rs
+++ b/crates/ra_syntax/src/parsing/text_tree_sink.rs
@@ -28,10 +28,10 @@ enum State {
28} 28}
29 29
30impl<'a> TreeSink for TextTreeSink<'a> { 30impl<'a> TreeSink for TextTreeSink<'a> {
31 fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) { 31 fn token(&mut self, kind: SyntaxKind, n_tokens: u8) {
32 match mem::replace(&mut self.state, State::Normal) { 32 match mem::replace(&mut self.state, State::Normal) {
33 State::PendingStart => unreachable!(), 33 State::PendingStart => unreachable!(),
34 State::PendingFinish => self.inner.finish_branch(), 34 State::PendingFinish => self.inner.finish_node(),
35 State::Normal => (), 35 State::Normal => (),
36 } 36 }
37 self.eat_trivias(); 37 self.eat_trivias();
@@ -40,18 +40,18 @@ impl<'a> TreeSink for TextTreeSink<'a> {
40 .iter() 40 .iter()
41 .map(|it| it.len) 41 .map(|it| it.len)
42 .sum::<TextUnit>(); 42 .sum::<TextUnit>();
43 self.do_leaf(kind, len, n_tokens); 43 self.do_token(kind, len, n_tokens);
44 } 44 }
45 45
46 fn start_branch(&mut self, kind: SyntaxKind) { 46 fn start_node(&mut self, kind: SyntaxKind) {
47 match mem::replace(&mut self.state, State::Normal) { 47 match mem::replace(&mut self.state, State::Normal) {
48 State::PendingStart => { 48 State::PendingStart => {
49 self.inner.start_branch(kind); 49 self.inner.start_node(kind);
50 // No need to attach trivias to previous node: there is no 50 // No need to attach trivias to previous node: there is no
51 // previous node. 51 // previous node.
52 return; 52 return;
53 } 53 }
54 State::PendingFinish => self.inner.finish_branch(), 54 State::PendingFinish => self.inner.finish_node(),
55 State::Normal => (), 55 State::Normal => (),
56 } 56 }
57 57
@@ -71,14 +71,14 @@ impl<'a> TreeSink for TextTreeSink<'a> {
71 n_attached_trivias(kind, leading_trivias) 71 n_attached_trivias(kind, leading_trivias)
72 }; 72 };
73 self.eat_n_trivias(n_trivias - n_attached_trivias); 73 self.eat_n_trivias(n_trivias - n_attached_trivias);
74 self.inner.start_branch(kind); 74 self.inner.start_node(kind);
75 self.eat_n_trivias(n_attached_trivias); 75 self.eat_n_trivias(n_attached_trivias);
76 } 76 }
77 77
78 fn finish_branch(&mut self) { 78 fn finish_node(&mut self) {
79 match mem::replace(&mut self.state, State::PendingFinish) { 79 match mem::replace(&mut self.state, State::PendingFinish) {
80 State::PendingStart => unreachable!(), 80 State::PendingStart => unreachable!(),
81 State::PendingFinish => self.inner.finish_branch(), 81 State::PendingFinish => self.inner.finish_node(),
82 State::Normal => (), 82 State::Normal => (),
83 } 83 }
84 } 84 }
@@ -104,7 +104,7 @@ impl<'a> TextTreeSink<'a> {
104 match mem::replace(&mut self.state, State::Normal) { 104 match mem::replace(&mut self.state, State::Normal) {
105 State::PendingFinish => { 105 State::PendingFinish => {
106 self.eat_trivias(); 106 self.eat_trivias();
107 self.inner.finish_branch() 107 self.inner.finish_node()
108 } 108 }
109 State::PendingStart | State::Normal => unreachable!(), 109 State::PendingStart | State::Normal => unreachable!(),
110 } 110 }
@@ -117,7 +117,7 @@ impl<'a> TextTreeSink<'a> {
117 if !token.kind.is_trivia() { 117 if !token.kind.is_trivia() {
118 break; 118 break;
119 } 119 }
120 self.do_leaf(token.kind, token.len, 1); 120 self.do_token(token.kind, token.len, 1);
121 } 121 }
122 } 122 }
123 123
@@ -125,16 +125,16 @@ impl<'a> TextTreeSink<'a> {
125 for _ in 0..n { 125 for _ in 0..n {
126 let token = self.tokens[self.token_pos]; 126 let token = self.tokens[self.token_pos];
127 assert!(token.kind.is_trivia()); 127 assert!(token.kind.is_trivia());
128 self.do_leaf(token.kind, token.len, 1); 128 self.do_token(token.kind, token.len, 1);
129 } 129 }
130 } 130 }
131 131
132 fn do_leaf(&mut self, kind: SyntaxKind, len: TextUnit, n_tokens: usize) { 132 fn do_token(&mut self, kind: SyntaxKind, len: TextUnit, n_tokens: usize) {
133 let range = TextRange::offset_len(self.text_pos, len); 133 let range = TextRange::offset_len(self.text_pos, len);
134 let text: SmolStr = self.text[range].into(); 134 let text: SmolStr = self.text[range].into();
135 self.text_pos += len; 135 self.text_pos += len;
136 self.token_pos += n_tokens; 136 self.token_pos += n_tokens;
137 self.inner.leaf(kind, text); 137 self.inner.token(kind, text);
138 } 138 }
139} 139}
140 140
diff --git a/crates/ra_syntax/src/string_lexing.rs b/crates/ra_syntax/src/string_lexing.rs
index 349733f3f..4c3eea3d2 100644
--- a/crates/ra_syntax/src/string_lexing.rs
+++ b/crates/ra_syntax/src/string_lexing.rs
@@ -1,7 +1,333 @@
1mod parser; 1use crate::{TextRange, TextUnit};
2mod string; 2use self::StringComponentKind::*;
3 3
4pub use self::{ 4#[derive(Debug, Eq, PartialEq, Clone)]
5 parser::{StringComponent, StringComponentKind}, 5pub(crate) struct StringComponent {
6 string::{parse_string_literal, parse_char_literal, parse_byte_literal, parse_byte_string_literal}, 6 pub(crate) range: TextRange,
7}; 7 pub(crate) kind: StringComponentKind,
8}
9
10#[derive(Debug, Eq, PartialEq, Clone)]
11pub(crate) enum StringComponentKind {
12 IgnoreNewline,
13 CodePoint,
14 AsciiEscape,
15 AsciiCodeEscape,
16 UnicodeEscape,
17}
18
19pub(crate) fn parse_quoted_literal(
20 prefix: Option<char>,
21 quote: char,
22 src: &str,
23) -> StringComponentIter {
24 let prefix = prefix.map(|p| match p {
25 'b' => b'b',
26 _ => panic!("invalid prefix"),
27 });
28 let quote = match quote {
29 '\'' => b'\'',
30 '"' => b'"',
31 _ => panic!("invalid quote"),
32 };
33 StringComponentIter { src, prefix, quote, pos: 0, has_closing_quote: false, suffix: None }
34}
35
36pub(crate) struct StringComponentIter<'a> {
37 src: &'a str,
38 prefix: Option<u8>,
39 quote: u8,
40 pos: usize,
41 pub(crate) has_closing_quote: bool,
42 pub(crate) suffix: Option<TextRange>,
43}
44
45impl<'a> Iterator for StringComponentIter<'a> {
46 type Item = StringComponent;
47 fn next(&mut self) -> Option<StringComponent> {
48 if self.pos == 0 {
49 if let Some(prefix) = self.prefix {
50 assert!(
51 self.advance() == prefix as char,
52 "literal should start with a {:?}",
53 prefix as char,
54 );
55 }
56 assert!(
57 self.advance() == self.quote as char,
58 "literal should start with a {:?}",
59 self.quote as char,
60 );
61 }
62
63 if let Some(component) = self.parse_component() {
64 return Some(component);
65 }
66
67 // We get here when there are no char components left to parse
68 if self.peek() == Some(self.quote as char) {
69 self.advance();
70 self.has_closing_quote = true;
71 if let Some(range) = self.parse_suffix() {
72 self.suffix = Some(range);
73 }
74 }
75
76 assert!(
77 self.peek() == None,
78 "literal should leave no unparsed input: src = {:?}, pos = {}, length = {}",
79 self.src,
80 self.pos,
81 self.src.len()
82 );
83
84 None
85 }
86}
87
88impl<'a> StringComponentIter<'a> {
89 fn peek(&self) -> Option<char> {
90 if self.pos == self.src.len() {
91 return None;
92 }
93
94 self.src[self.pos..].chars().next()
95 }
96
97 fn advance(&mut self) -> char {
98 let next = self.peek().expect("cannot advance if end of input is reached");
99 self.pos += next.len_utf8();
100 next
101 }
102
103 fn parse_component(&mut self) -> Option<StringComponent> {
104 let next = self.peek()?;
105
106 // Ignore string close
107 if next == self.quote as char {
108 return None;
109 }
110
111 let start = self.start_range();
112 self.advance();
113
114 if next == '\\' {
115 // Strings can use `\` to ignore newlines, so we first try to parse one of those
116 // before falling back to parsing char escapes
117 if self.quote == b'"' {
118 if let Some(component) = self.parse_ignore_newline(start) {
119 return Some(component);
120 }
121 }
122
123 Some(self.parse_escape(start))
124 } else {
125 Some(self.finish_component(start, CodePoint))
126 }
127 }
128
129 fn parse_ignore_newline(&mut self, start: TextUnit) -> Option<StringComponent> {
130 // In string literals, when a `\` occurs immediately before the newline, the `\`,
131 // the newline, and all whitespace at the beginning of the next line are ignored
132 match self.peek() {
133 Some('\n') | Some('\r') => {
134 self.skip_whitespace();
135 Some(self.finish_component(start, IgnoreNewline))
136 }
137 _ => None,
138 }
139 }
140
141 fn skip_whitespace(&mut self) {
142 while self.peek().map(|c| c.is_whitespace()) == Some(true) {
143 self.advance();
144 }
145 }
146
147 fn parse_escape(&mut self, start: TextUnit) -> StringComponent {
148 if self.peek().is_none() {
149 return self.finish_component(start, AsciiEscape);
150 }
151
152 let next = self.advance();
153 match next {
154 'x' => self.parse_ascii_code_escape(start),
155 'u' => self.parse_unicode_escape(start),
156 _ => self.finish_component(start, AsciiEscape),
157 }
158 }
159
160 fn parse_unicode_escape(&mut self, start: TextUnit) -> StringComponent {
161 match self.peek() {
162 Some('{') => {
163 self.advance();
164
165 // Parse anything until we reach `}`
166 while let Some(next) = self.peek() {
167 self.advance();
168 if next == '}' {
169 break;
170 }
171 }
172
173 self.finish_component(start, UnicodeEscape)
174 }
175 Some(_) | None => self.finish_component(start, UnicodeEscape),
176 }
177 }
178
179 fn parse_ascii_code_escape(&mut self, start: TextUnit) -> StringComponent {
180 let code_start = self.pos;
181 while let Some(next) = self.peek() {
182 if next == '\'' || (self.pos - code_start == 2) {
183 break;
184 }
185
186 self.advance();
187 }
188 self.finish_component(start, AsciiCodeEscape)
189 }
190
191 fn parse_suffix(&mut self) -> Option<TextRange> {
192 let start = self.start_range();
193 let _ = self.peek()?;
194 while let Some(_) = self.peek() {
195 self.advance();
196 }
197 Some(self.finish_range(start))
198 }
199
200 fn start_range(&self) -> TextUnit {
201 TextUnit::from_usize(self.pos)
202 }
203
204 fn finish_range(&self, start: TextUnit) -> TextRange {
205 TextRange::from_to(start, TextUnit::from_usize(self.pos))
206 }
207
208 fn finish_component(&self, start: TextUnit, kind: StringComponentKind) -> StringComponent {
209 let range = self.finish_range(start);
210 StringComponent { range, kind }
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 fn parse(src: &str) -> (bool, Vec<StringComponent>) {
219 let component_iterator = &mut parse_quoted_literal(None, '\'', src);
220 let components: Vec<_> = component_iterator.collect();
221 (component_iterator.has_closing_quote, components)
222 }
223
224 fn unclosed_char_component(src: &str) -> StringComponent {
225 let (has_closing_quote, components) = parse(src);
226 assert!(!has_closing_quote, "char should not have closing quote");
227 assert!(components.len() == 1);
228 components[0].clone()
229 }
230
231 fn closed_char_component(src: &str) -> StringComponent {
232 let (has_closing_quote, components) = parse(src);
233 assert!(has_closing_quote, "char should have closing quote");
234 assert!(components.len() == 1, "Literal: {}\nComponents: {:#?}", src, components);
235 components[0].clone()
236 }
237
238 fn closed_char_components(src: &str) -> Vec<StringComponent> {
239 let (has_closing_quote, components) = parse(src);
240 assert!(has_closing_quote, "char should have closing quote");
241 components
242 }
243
244 fn range_closed(src: &str) -> TextRange {
245 TextRange::from_to(1.into(), (src.len() as u32 - 1).into())
246 }
247
248 fn range_unclosed(src: &str) -> TextRange {
249 TextRange::from_to(1.into(), (src.len() as u32).into())
250 }
251
252 #[test]
253 fn test_unicode_escapes() {
254 let unicode_escapes = &[r"{DEAD}", "{BEEF}", "{FF}", "{}", ""];
255 for escape in unicode_escapes {
256 let escape_sequence = format!(r"'\u{}'", escape);
257 let component = closed_char_component(&escape_sequence);
258 let expected_range = range_closed(&escape_sequence);
259 assert_eq!(component.kind, UnicodeEscape);
260 assert_eq!(component.range, expected_range);
261 }
262 }
263
264 #[test]
265 fn test_unicode_escapes_unclosed() {
266 let unicode_escapes = &["{DEAD", "{BEEF", "{FF"];
267 for escape in unicode_escapes {
268 let escape_sequence = format!(r"'\u{}'", escape);
269 let component = unclosed_char_component(&escape_sequence);
270 let expected_range = range_unclosed(&escape_sequence);
271 assert_eq!(component.kind, UnicodeEscape);
272 assert_eq!(component.range, expected_range);
273 }
274 }
275
276 #[test]
277 fn test_empty_char() {
278 let (has_closing_quote, components) = parse("''");
279 assert!(has_closing_quote, "char should have closing quote");
280 assert!(components.len() == 0);
281 }
282
283 #[test]
284 fn test_unclosed_char() {
285 let component = unclosed_char_component("'a");
286 assert!(component.kind == CodePoint);
287 assert!(component.range == TextRange::from_to(1.into(), 2.into()));
288 }
289
290 #[test]
291 fn test_digit_escapes() {
292 let literals = &[r"", r"5", r"55"];
293
294 for literal in literals {
295 let lit_text = format!(r"'\x{}'", literal);
296 let component = closed_char_component(&lit_text);
297 assert!(component.kind == AsciiCodeEscape);
298 assert!(component.range == range_closed(&lit_text));
299 }
300
301 // More than 2 digits starts a new codepoint
302 let components = closed_char_components(r"'\x555'");
303 assert!(components.len() == 2);
304 assert!(components[1].kind == CodePoint);
305 }
306
307 #[test]
308 fn test_ascii_escapes() {
309 let literals = &[
310 r"\'", "\\\"", // equivalent to \"
311 r"\n", r"\r", r"\t", r"\\", r"\0",
312 ];
313
314 for literal in literals {
315 let lit_text = format!("'{}'", literal);
316 let component = closed_char_component(&lit_text);
317 assert!(component.kind == AsciiEscape);
318 assert!(component.range == range_closed(&lit_text));
319 }
320 }
321
322 #[test]
323 fn test_no_escapes() {
324 let literals = &['"', 'n', 'r', 't', '0', 'x', 'u'];
325
326 for &literal in literals {
327 let lit_text = format!("'{}'", literal);
328 let component = closed_char_component(&lit_text);
329 assert!(component.kind == CodePoint);
330 assert!(component.range == range_closed(&lit_text));
331 }
332 }
333}
diff --git a/crates/ra_syntax/src/string_lexing/parser.rs b/crates/ra_syntax/src/string_lexing/parser.rs
deleted file mode 100644
index 7469eb903..000000000
--- a/crates/ra_syntax/src/string_lexing/parser.rs
+++ /dev/null
@@ -1,168 +0,0 @@
1use rowan::{TextRange, TextUnit};
2
3use self::StringComponentKind::*;
4
5pub struct Parser<'a> {
6 pub(super) quote: u8,
7 pub(super) src: &'a str,
8 pub(super) pos: usize,
9}
10
11impl<'a> Parser<'a> {
12 pub fn new(src: &'a str, quote: u8) -> Parser<'a> {
13 Parser { quote, src, pos: 0 }
14 }
15
16 // Utility methods
17
18 pub fn peek(&self) -> Option<char> {
19 if self.pos == self.src.len() {
20 return None;
21 }
22
23 self.src[self.pos..].chars().next()
24 }
25
26 pub fn advance(&mut self) -> char {
27 let next = self.peek().expect("cannot advance if end of input is reached");
28 self.pos += next.len_utf8();
29 next
30 }
31
32 pub fn skip_whitespace(&mut self) {
33 while self.peek().map(|c| c.is_whitespace()) == Some(true) {
34 self.advance();
35 }
36 }
37
38 pub fn get_pos(&self) -> TextUnit {
39 (self.pos as u32).into()
40 }
41
42 // Char parsing methods
43
44 fn parse_unicode_escape(&mut self, start: TextUnit) -> StringComponent {
45 match self.peek() {
46 Some('{') => {
47 self.advance();
48
49 // Parse anything until we reach `}`
50 while let Some(next) = self.peek() {
51 self.advance();
52 if next == '}' {
53 break;
54 }
55 }
56
57 let end = self.get_pos();
58 StringComponent::new(TextRange::from_to(start, end), UnicodeEscape)
59 }
60 Some(_) | None => {
61 let end = self.get_pos();
62 StringComponent::new(TextRange::from_to(start, end), UnicodeEscape)
63 }
64 }
65 }
66
67 fn parse_ascii_code_escape(&mut self, start: TextUnit) -> StringComponent {
68 let code_start = self.get_pos();
69 while let Some(next) = self.peek() {
70 if next == '\'' || (self.get_pos() - code_start == 2.into()) {
71 break;
72 }
73
74 self.advance();
75 }
76
77 let end = self.get_pos();
78 StringComponent::new(TextRange::from_to(start, end), AsciiCodeEscape)
79 }
80
81 fn parse_escape(&mut self, start: TextUnit) -> StringComponent {
82 if self.peek().is_none() {
83 return StringComponent::new(TextRange::from_to(start, self.get_pos()), AsciiEscape);
84 }
85
86 let next = self.advance();
87 let end = self.get_pos();
88 let range = TextRange::from_to(start, end);
89 match next {
90 'x' => self.parse_ascii_code_escape(start),
91 'u' => self.parse_unicode_escape(start),
92 _ => StringComponent::new(range, AsciiEscape),
93 }
94 }
95
96 pub fn parse_ignore_newline(&mut self, start: TextUnit) -> Option<StringComponent> {
97 // In string literals, when a `\` occurs immediately before the newline, the `\`,
98 // the newline, and all whitespace at the beginning of the next line are ignored
99 match self.peek() {
100 Some('\n') | Some('\r') => {
101 self.skip_whitespace();
102 Some(StringComponent::new(
103 TextRange::from_to(start, self.get_pos()),
104 StringComponentKind::IgnoreNewline,
105 ))
106 }
107 _ => None,
108 }
109 }
110
111 pub fn parse_component(&mut self) -> Option<StringComponent> {
112 let next = self.peek()?;
113
114 // Ignore string close
115 if next == self.quote as char {
116 return None;
117 }
118
119 let start = self.get_pos();
120 self.advance();
121
122 if next == '\\' {
123 // Strings can use `\` to ignore newlines, so we first try to parse one of those
124 // before falling back to parsing char escapes
125 if self.quote == b'"' {
126 if let Some(component) = self.parse_ignore_newline(start) {
127 return Some(component);
128 }
129 }
130
131 Some(self.parse_escape(start))
132 } else {
133 let end = self.get_pos();
134 Some(StringComponent::new(TextRange::from_to(start, end), CodePoint))
135 }
136 }
137
138 pub fn parse_suffix(&mut self) -> Option<TextRange> {
139 let start = self.get_pos();
140 let _ = self.peek()?;
141 while let Some(_) = self.peek() {
142 self.advance();
143 }
144 let end = self.get_pos();
145 Some(TextRange::from_to(start, end))
146 }
147}
148
149#[derive(Debug, Eq, PartialEq, Clone)]
150pub struct StringComponent {
151 pub range: TextRange,
152 pub kind: StringComponentKind,
153}
154
155impl StringComponent {
156 fn new(range: TextRange, kind: StringComponentKind) -> StringComponent {
157 StringComponent { range, kind }
158 }
159}
160
161#[derive(Debug, Eq, PartialEq, Clone)]
162pub enum StringComponentKind {
163 IgnoreNewline,
164 CodePoint,
165 AsciiEscape,
166 AsciiCodeEscape,
167 UnicodeEscape,
168}
diff --git a/crates/ra_syntax/src/string_lexing/string.rs b/crates/ra_syntax/src/string_lexing/string.rs
deleted file mode 100644
index a4742a0d1..000000000
--- a/crates/ra_syntax/src/string_lexing/string.rs
+++ /dev/null
@@ -1,222 +0,0 @@
1use crate::{
2 TextRange,
3 string_lexing::{
4 parser::Parser,
5 StringComponent,
6}};
7
8pub fn parse_string_literal(src: &str) -> StringComponentIterator {
9 StringComponentIterator {
10 parser: Parser::new(src, b'"'),
11 has_closing_quote: false,
12 suffix: None,
13 prefix: None,
14 quote: b'"',
15 }
16}
17
18pub fn parse_byte_string_literal(src: &str) -> StringComponentIterator {
19 StringComponentIterator {
20 parser: Parser::new(src, b'"'),
21 has_closing_quote: false,
22 suffix: None,
23 prefix: Some(b'b'),
24 quote: b'"',
25 }
26}
27
28pub fn parse_char_literal(src: &str) -> StringComponentIterator {
29 StringComponentIterator {
30 parser: Parser::new(src, b'\''),
31 has_closing_quote: false,
32 suffix: None,
33 prefix: None,
34 quote: b'\'',
35 }
36}
37
38pub fn parse_byte_literal(src: &str) -> StringComponentIterator {
39 StringComponentIterator {
40 parser: Parser::new(src, b'\''),
41 has_closing_quote: false,
42 suffix: None,
43 prefix: Some(b'b'),
44 quote: b'\'',
45 }
46}
47
48pub struct StringComponentIterator<'a> {
49 parser: Parser<'a>,
50 pub has_closing_quote: bool,
51 pub suffix: Option<TextRange>,
52 prefix: Option<u8>,
53 quote: u8,
54}
55
56impl<'a> Iterator for StringComponentIterator<'a> {
57 type Item = StringComponent;
58 fn next(&mut self) -> Option<StringComponent> {
59 if self.parser.pos == 0 {
60 if let Some(prefix) = self.prefix {
61 assert!(
62 self.parser.advance() == prefix as char,
63 "literal should start with a {:?}",
64 prefix as char,
65 );
66 }
67 assert!(
68 self.parser.advance() == self.quote as char,
69 "literal should start with a {:?}",
70 self.quote as char,
71 );
72 }
73
74 if let Some(component) = self.parser.parse_component() {
75 return Some(component);
76 }
77
78 // We get here when there are no char components left to parse
79 if self.parser.peek() == Some(self.quote as char) {
80 self.parser.advance();
81 self.has_closing_quote = true;
82 if let Some(range) = self.parser.parse_suffix() {
83 self.suffix = Some(range);
84 }
85 }
86
87 assert!(
88 self.parser.peek() == None,
89 "literal should leave no unparsed input: src = {:?}, pos = {}, length = {}",
90 self.parser.src,
91 self.parser.pos,
92 self.parser.src.len()
93 );
94
95 None
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use rowan::TextRange;
102 use crate::string_lexing::{
103 StringComponent,
104 StringComponentKind::*,
105};
106
107 fn parse(src: &str) -> (bool, Vec<StringComponent>) {
108 let component_iterator = &mut super::parse_char_literal(src);
109 let components: Vec<_> = component_iterator.collect();
110 (component_iterator.has_closing_quote, components)
111 }
112
113 fn unclosed_char_component(src: &str) -> StringComponent {
114 let (has_closing_quote, components) = parse(src);
115 assert!(!has_closing_quote, "char should not have closing quote");
116 assert!(components.len() == 1);
117 components[0].clone()
118 }
119
120 fn closed_char_component(src: &str) -> StringComponent {
121 let (has_closing_quote, components) = parse(src);
122 assert!(has_closing_quote, "char should have closing quote");
123 assert!(components.len() == 1, "Literal: {}\nComponents: {:#?}", src, components);
124 components[0].clone()
125 }
126
127 fn closed_char_components(src: &str) -> Vec<StringComponent> {
128 let (has_closing_quote, components) = parse(src);
129 assert!(has_closing_quote, "char should have closing quote");
130 components
131 }
132
133 fn range_closed(src: &str) -> TextRange {
134 TextRange::from_to(1.into(), (src.len() as u32 - 1).into())
135 }
136
137 fn range_unclosed(src: &str) -> TextRange {
138 TextRange::from_to(1.into(), (src.len() as u32).into())
139 }
140
141 #[test]
142 fn test_unicode_escapes() {
143 let unicode_escapes = &[r"{DEAD}", "{BEEF}", "{FF}", "{}", ""];
144 for escape in unicode_escapes {
145 let escape_sequence = format!(r"'\u{}'", escape);
146 let component = closed_char_component(&escape_sequence);
147 let expected_range = range_closed(&escape_sequence);
148 assert_eq!(component.kind, UnicodeEscape);
149 assert_eq!(component.range, expected_range);
150 }
151 }
152
153 #[test]
154 fn test_unicode_escapes_unclosed() {
155 let unicode_escapes = &["{DEAD", "{BEEF", "{FF"];
156 for escape in unicode_escapes {
157 let escape_sequence = format!(r"'\u{}'", escape);
158 let component = unclosed_char_component(&escape_sequence);
159 let expected_range = range_unclosed(&escape_sequence);
160 assert_eq!(component.kind, UnicodeEscape);
161 assert_eq!(component.range, expected_range);
162 }
163 }
164
165 #[test]
166 fn test_empty_char() {
167 let (has_closing_quote, components) = parse("''");
168 assert!(has_closing_quote, "char should have closing quote");
169 assert!(components.len() == 0);
170 }
171
172 #[test]
173 fn test_unclosed_char() {
174 let component = unclosed_char_component("'a");
175 assert!(component.kind == CodePoint);
176 assert!(component.range == TextRange::from_to(1.into(), 2.into()));
177 }
178
179 #[test]
180 fn test_digit_escapes() {
181 let literals = &[r"", r"5", r"55"];
182
183 for literal in literals {
184 let lit_text = format!(r"'\x{}'", literal);
185 let component = closed_char_component(&lit_text);
186 assert!(component.kind == AsciiCodeEscape);
187 assert!(component.range == range_closed(&lit_text));
188 }
189
190 // More than 2 digits starts a new codepoint
191 let components = closed_char_components(r"'\x555'");
192 assert!(components.len() == 2);
193 assert!(components[1].kind == CodePoint);
194 }
195
196 #[test]
197 fn test_ascii_escapes() {
198 let literals = &[
199 r"\'", "\\\"", // equivalent to \"
200 r"\n", r"\r", r"\t", r"\\", r"\0",
201 ];
202
203 for literal in literals {
204 let lit_text = format!("'{}'", literal);
205 let component = closed_char_component(&lit_text);
206 assert!(component.kind == AsciiEscape);
207 assert!(component.range == range_closed(&lit_text));
208 }
209 }
210
211 #[test]
212 fn test_no_escapes() {
213 let literals = &['"', 'n', 'r', 't', '0', 'x', 'u'];
214
215 for &literal in literals {
216 let lit_text = format!("'{}'", literal);
217 let component = closed_char_component(&lit_text);
218 assert!(component.kind == CodePoint);
219 assert!(component.range == range_closed(&lit_text));
220 }
221 }
222}
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs
index e5b4cdb11..a88a348ad 100644
--- a/crates/ra_syntax/src/syntax_node.rs
+++ b/crates/ra_syntax/src/syntax_node.rs
@@ -29,6 +29,9 @@ impl Types for RaTypes {
29} 29}
30 30
31pub(crate) type GreenNode = rowan::GreenNode<RaTypes>; 31pub(crate) type GreenNode = rowan::GreenNode<RaTypes>;
32pub(crate) type GreenToken = rowan::GreenToken<RaTypes>;
33#[allow(unused)]
34pub(crate) type GreenElement = rowan::GreenElement<RaTypes>;
32 35
33/// Marker trait for CST and AST nodes 36/// Marker trait for CST and AST nodes
34pub trait SyntaxNodeWrapper: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>> {} 37pub trait SyntaxNodeWrapper: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>> {}
@@ -113,11 +116,13 @@ impl ToOwned for SyntaxNode {
113 116
114impl fmt::Debug for SyntaxNode { 117impl fmt::Debug for SyntaxNode {
115 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 118 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
116 write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; 119 write!(fmt, "{:?}@{:?}", self.kind(), self.range())
117 if has_short_text(self.kind()) { 120 }
118 write!(fmt, " \"{}\"", self.text())?; 121}
119 } 122
120 Ok(()) 123impl fmt::Display for SyntaxNode {
124 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
125 fmt::Display::fmt(&self.text(), fmt)
121 } 126 }
122} 127}
123 128
@@ -145,14 +150,6 @@ impl SyntaxNode {
145 SyntaxText::new(self) 150 SyntaxText::new(self)
146 } 151 }
147 152
148 pub fn is_leaf(&self) -> bool {
149 self.0.is_leaf()
150 }
151
152 pub fn leaf_text(&self) -> Option<&SmolStr> {
153 self.0.leaf_text()
154 }
155
156 pub fn parent(&self) -> Option<&SyntaxNode> { 153 pub fn parent(&self) -> Option<&SyntaxNode> {
157 self.0.parent().map(SyntaxNode::from_repr) 154 self.0.parent().map(SyntaxNode::from_repr)
158 } 155 }
@@ -161,22 +158,50 @@ impl SyntaxNode {
161 self.0.first_child().map(SyntaxNode::from_repr) 158 self.0.first_child().map(SyntaxNode::from_repr)
162 } 159 }
163 160
161 pub fn first_child_or_token(&self) -> Option<SyntaxElement> {
162 self.0.first_child_or_token().map(SyntaxElement::from)
163 }
164
164 pub fn last_child(&self) -> Option<&SyntaxNode> { 165 pub fn last_child(&self) -> Option<&SyntaxNode> {
165 self.0.last_child().map(SyntaxNode::from_repr) 166 self.0.last_child().map(SyntaxNode::from_repr)
166 } 167 }
167 168
169 pub fn last_child_or_token(&self) -> Option<SyntaxElement> {
170 self.0.last_child_or_token().map(SyntaxElement::from)
171 }
172
168 pub fn next_sibling(&self) -> Option<&SyntaxNode> { 173 pub fn next_sibling(&self) -> Option<&SyntaxNode> {
169 self.0.next_sibling().map(SyntaxNode::from_repr) 174 self.0.next_sibling().map(SyntaxNode::from_repr)
170 } 175 }
171 176
177 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
178 self.0.next_sibling_or_token().map(SyntaxElement::from)
179 }
180
172 pub fn prev_sibling(&self) -> Option<&SyntaxNode> { 181 pub fn prev_sibling(&self) -> Option<&SyntaxNode> {
173 self.0.prev_sibling().map(SyntaxNode::from_repr) 182 self.0.prev_sibling().map(SyntaxNode::from_repr)
174 } 183 }
175 184
185 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
186 self.0.prev_sibling_or_token().map(SyntaxElement::from)
187 }
188
176 pub fn children(&self) -> SyntaxNodeChildren { 189 pub fn children(&self) -> SyntaxNodeChildren {
177 SyntaxNodeChildren(self.0.children()) 190 SyntaxNodeChildren(self.0.children())
178 } 191 }
179 192
193 pub fn children_with_tokens(&self) -> SyntaxElementChildren {
194 SyntaxElementChildren(self.0.children_with_tokens())
195 }
196
197 pub fn first_token(&self) -> Option<SyntaxToken> {
198 self.0.first_token().map(SyntaxToken::from)
199 }
200
201 pub fn last_token(&self) -> Option<SyntaxToken> {
202 self.0.last_token().map(SyntaxToken::from)
203 }
204
180 pub fn ancestors(&self) -> impl Iterator<Item = &SyntaxNode> { 205 pub fn ancestors(&self) -> impl Iterator<Item = &SyntaxNode> {
181 crate::algo::generate(Some(self), |&node| node.parent()) 206 crate::algo::generate(Some(self), |&node| node.parent())
182 } 207 }
@@ -188,6 +213,13 @@ impl SyntaxNode {
188 }) 213 })
189 } 214 }
190 215
216 pub fn descendants_with_tokens(&self) -> impl Iterator<Item = SyntaxElement> {
217 self.preorder_with_tokens().filter_map(|event| match event {
218 WalkEvent::Enter(it) => Some(it),
219 WalkEvent::Leave(_) => None,
220 })
221 }
222
191 pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = &SyntaxNode> { 223 pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = &SyntaxNode> {
192 crate::algo::generate(Some(self), move |&node| match direction { 224 crate::algo::generate(Some(self), move |&node| match direction {
193 Direction::Next => node.next_sibling(), 225 Direction::Next => node.next_sibling(),
@@ -195,6 +227,17 @@ impl SyntaxNode {
195 }) 227 })
196 } 228 }
197 229
230 pub fn siblings_with_tokens(
231 &self,
232 direction: Direction,
233 ) -> impl Iterator<Item = SyntaxElement> {
234 let me: SyntaxElement = self.into();
235 crate::algo::generate(Some(me), move |el| match direction {
236 Direction::Next => el.next_sibling_or_token(),
237 Direction::Prev => el.prev_sibling_or_token(),
238 })
239 }
240
198 pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<&SyntaxNode>> { 241 pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<&SyntaxNode>> {
199 self.0.preorder().map(|event| match event { 242 self.0.preorder().map(|event| match event {
200 WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode::from_repr(n)), 243 WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode::from_repr(n)),
@@ -202,6 +245,13 @@ impl SyntaxNode {
202 }) 245 })
203 } 246 }
204 247
248 pub fn preorder_with_tokens(&self) -> impl Iterator<Item = WalkEvent<SyntaxElement>> {
249 self.0.preorder_with_tokens().map(|event| match event {
250 WalkEvent::Enter(n) => WalkEvent::Enter(n.into()),
251 WalkEvent::Leave(n) => WalkEvent::Leave(n.into()),
252 })
253 }
254
205 pub fn memory_size_of_subtree(&self) -> usize { 255 pub fn memory_size_of_subtree(&self) -> usize {
206 self.0.memory_size_of_subtree() 256 self.0.memory_size_of_subtree()
207 } 257 }
@@ -223,17 +273,20 @@ impl SyntaxNode {
223 }; 273 };
224 } 274 }
225 275
226 for event in self.preorder() { 276 for event in self.preorder_with_tokens() {
227 match event { 277 match event {
228 WalkEvent::Enter(node) => { 278 WalkEvent::Enter(element) => {
229 indent!(); 279 indent!();
230 writeln!(buf, "{:?}", node).unwrap(); 280 match element {
231 if node.first_child().is_none() { 281 SyntaxElement::Node(node) => writeln!(buf, "{:?}", node).unwrap(),
232 let off = node.range().end(); 282 SyntaxElement::Token(token) => {
233 while err_pos < errors.len() && errors[err_pos].offset() <= off { 283 writeln!(buf, "{:?}", token).unwrap();
234 indent!(); 284 let off = token.range().end();
235 writeln!(buf, "err: `{}`", errors[err_pos]).unwrap(); 285 while err_pos < errors.len() && errors[err_pos].offset() <= off {
236 err_pos += 1; 286 indent!();
287 writeln!(buf, "err: `{}`", errors[err_pos]).unwrap();
288 err_pos += 1;
289 }
237 } 290 }
238 } 291 }
239 level += 1; 292 level += 1;
@@ -255,7 +308,179 @@ impl SyntaxNode {
255 } 308 }
256 309
257 pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { 310 pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
258 self.0.replace_self(replacement) 311 self.0.replace_with(replacement)
312 }
313}
314
315#[derive(Clone, Copy, PartialEq, Eq, Hash)]
316pub struct SyntaxToken<'a>(pub(crate) rowan::SyntaxToken<'a, RaTypes>);
317
318//FIXME: always output text
319impl<'a> fmt::Debug for SyntaxToken<'a> {
320 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
321 write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
322 if self.text().len() < 25 {
323 return write!(fmt, " {:?}", self.text());
324 }
325 let text = self.text().as_str();
326 for idx in 21..25 {
327 if text.is_char_boundary(idx) {
328 let text = format!("{} ...", &text[..idx]);
329 return write!(fmt, " {:?}", text);
330 }
331 }
332 unreachable!()
333 }
334}
335
336impl<'a> fmt::Display for SyntaxToken<'a> {
337 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
338 fmt::Display::fmt(self.text(), fmt)
339 }
340}
341
342impl<'a> From<rowan::SyntaxToken<'a, RaTypes>> for SyntaxToken<'a> {
343 fn from(t: rowan::SyntaxToken<'a, RaTypes>) -> Self {
344 SyntaxToken(t)
345 }
346}
347
348impl<'a> SyntaxToken<'a> {
349 pub fn kind(&self) -> SyntaxKind {
350 self.0.kind()
351 }
352
353 pub fn text(&self) -> &'a SmolStr {
354 self.0.text()
355 }
356
357 pub fn range(&self) -> TextRange {
358 self.0.range()
359 }
360
361 pub fn parent(&self) -> &'a SyntaxNode {
362 SyntaxNode::from_repr(self.0.parent())
363 }
364
365 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
366 self.0.next_sibling_or_token().map(SyntaxElement::from)
367 }
368
369 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
370 self.0.prev_sibling_or_token().map(SyntaxElement::from)
371 }
372
373 pub fn siblings_with_tokens(
374 &self,
375 direction: Direction,
376 ) -> impl Iterator<Item = SyntaxElement<'a>> {
377 let me: SyntaxElement = (*self).into();
378 crate::algo::generate(Some(me), move |el| match direction {
379 Direction::Next => el.next_sibling_or_token(),
380 Direction::Prev => el.prev_sibling_or_token(),
381 })
382 }
383
384 pub fn next_token(&self) -> Option<SyntaxToken<'a>> {
385 self.0.next_token().map(SyntaxToken::from)
386 }
387
388 pub fn prev_token(&self) -> Option<SyntaxToken<'a>> {
389 self.0.prev_token().map(SyntaxToken::from)
390 }
391
392 pub(crate) fn replace_with(&self, new_token: GreenToken) -> GreenNode {
393 self.0.replace_with(new_token)
394 }
395}
396
397#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
398pub enum SyntaxElement<'a> {
399 Node(&'a SyntaxNode),
400 Token(SyntaxToken<'a>),
401}
402
403impl<'a> fmt::Display for SyntaxElement<'a> {
404 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
405 match self {
406 SyntaxElement::Node(it) => fmt::Display::fmt(it, fmt),
407 SyntaxElement::Token(it) => fmt::Display::fmt(it, fmt),
408 }
409 }
410}
411
412impl<'a> SyntaxElement<'a> {
413 pub fn kind(&self) -> SyntaxKind {
414 match self {
415 SyntaxElement::Node(it) => it.kind(),
416 SyntaxElement::Token(it) => it.kind(),
417 }
418 }
419
420 pub fn as_node(&self) -> Option<&'a SyntaxNode> {
421 match self {
422 SyntaxElement::Node(node) => Some(*node),
423 SyntaxElement::Token(_) => None,
424 }
425 }
426
427 pub fn as_token(&self) -> Option<SyntaxToken<'a>> {
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<'a>> {
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<'a>> {
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 = &'a SyntaxNode> {
449 match self {
450 SyntaxElement::Node(it) => it,
451 SyntaxElement::Token(it) => it.parent(),
452 }
453 .ancestors()
454 }
455}
456
457impl<'a> From<rowan::SyntaxElement<'a, RaTypes>> for SyntaxElement<'a> {
458 fn from(el: rowan::SyntaxElement<'a, RaTypes>) -> Self {
459 match el {
460 rowan::SyntaxElement::Node(n) => SyntaxElement::Node(SyntaxNode::from_repr(n)),
461 rowan::SyntaxElement::Token(t) => SyntaxElement::Token(t.into()),
462 }
463 }
464}
465
466impl<'a> From<&'a SyntaxNode> for SyntaxElement<'a> {
467 fn from(node: &'a SyntaxNode) -> SyntaxElement<'a> {
468 SyntaxElement::Node(node)
469 }
470}
471
472impl<'a> From<SyntaxToken<'a>> for SyntaxElement<'a> {
473 fn from(token: SyntaxToken<'a>) -> SyntaxElement<'a> {
474 SyntaxElement::Token(token)
475 }
476}
477
478impl<'a> SyntaxElement<'a> {
479 pub fn range(&self) -> TextRange {
480 match self {
481 SyntaxElement::Node(it) => it.range(),
482 SyntaxElement::Token(it) => it.range(),
483 }
259 } 484 }
260} 485}
261 486
@@ -270,11 +495,14 @@ impl<'a> Iterator for SyntaxNodeChildren<'a> {
270 } 495 }
271} 496}
272 497
273fn has_short_text(kind: SyntaxKind) -> bool { 498#[derive(Debug)]
274 use crate::SyntaxKind::*; 499pub struct SyntaxElementChildren<'a>(rowan::SyntaxElementChildren<'a, RaTypes>);
275 match kind { 500
276 IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, 501impl<'a> Iterator for SyntaxElementChildren<'a> {
277 _ => false, 502 type Item = SyntaxElement<'a>;
503
504 fn next(&mut self) -> Option<SyntaxElement<'a>> {
505 self.0.next().map(SyntaxElement::from)
278 } 506 }
279} 507}
280 508
@@ -304,16 +532,16 @@ impl SyntaxTreeBuilder {
304 node 532 node
305 } 533 }
306 534
307 pub fn leaf(&mut self, kind: SyntaxKind, text: SmolStr) { 535 pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) {
308 self.inner.leaf(kind, text) 536 self.inner.token(kind, text)
309 } 537 }
310 538
311 pub fn start_branch(&mut self, kind: SyntaxKind) { 539 pub fn start_node(&mut self, kind: SyntaxKind) {
312 self.inner.start_internal(kind) 540 self.inner.start_node(kind)
313 } 541 }
314 542
315 pub fn finish_branch(&mut self) { 543 pub fn finish_node(&mut self) {
316 self.inner.finish_internal() 544 self.inner.finish_node()
317 } 545 }
318 546
319 pub fn error(&mut self, error: ParseError, text_pos: TextUnit) { 547 pub fn error(&mut self, error: ParseError, text_pos: TextUnit) {
diff --git a/crates/ra_syntax/src/syntax_text.rs b/crates/ra_syntax/src/syntax_text.rs
index 84e5b231a..6bb2ff461 100644
--- a/crates/ra_syntax/src/syntax_text.rs
+++ b/crates/ra_syntax/src/syntax_text.rs
@@ -1,6 +1,6 @@
1use std::{fmt, ops}; 1use std::{fmt, ops};
2 2
3use crate::{SyntaxNode, TextRange, TextUnit}; 3use crate::{SyntaxNode, TextRange, TextUnit, SyntaxElement};
4 4
5#[derive(Clone)] 5#[derive(Clone)]
6pub struct SyntaxText<'a> { 6pub struct SyntaxText<'a> {
@@ -15,11 +15,14 @@ impl<'a> SyntaxText<'a> {
15 15
16 pub fn chunks(&self) -> impl Iterator<Item = &'a str> { 16 pub fn chunks(&self) -> impl Iterator<Item = &'a str> {
17 let range = self.range; 17 let range = self.range;
18 self.node.descendants().filter_map(move |node| { 18 self.node.descendants_with_tokens().filter_map(move |el| match el {
19 let text = node.leaf_text()?; 19 SyntaxElement::Token(t) => {
20 let range = range.intersection(&node.range())?; 20 let text = t.text();
21 let range = range - node.range().start(); 21 let range = range.intersection(&t.range())?;
22 Some(&text[range]) 22 let range = range - t.range().start();
23 Some(&text[range])
24 }
25 SyntaxElement::Node(_) => None,
23 }) 26 })
24 } 27 }
25 28
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index 69f344d65..fc534df83 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -6,7 +6,7 @@ mod block;
6 6
7use crate::{ 7use crate::{
8 SourceFile, SyntaxError, AstNode, SyntaxNode, 8 SourceFile, SyntaxError, AstNode, SyntaxNode,
9 SyntaxKind::{L_CURLY, R_CURLY}, 9 SyntaxKind::{L_CURLY, R_CURLY, BYTE, BYTE_STRING, STRING, CHAR},
10 ast, 10 ast,
11 algo::visit::{visitor_ctx, VisitorCtx}, 11 algo::visit::{visitor_ctx, VisitorCtx},
12}; 12};
@@ -15,16 +15,24 @@ pub(crate) fn validate(file: &SourceFile) -> Vec<SyntaxError> {
15 let mut errors = Vec::new(); 15 let mut errors = Vec::new();
16 for node in file.syntax().descendants() { 16 for node in file.syntax().descendants() {
17 let _ = visitor_ctx(&mut errors) 17 let _ = visitor_ctx(&mut errors)
18 .visit::<ast::Byte, _>(byte::validate_byte_node) 18 .visit::<ast::Literal, _>(validate_literal)
19 .visit::<ast::ByteString, _>(byte_string::validate_byte_string_node)
20 .visit::<ast::Char, _>(char::validate_char_node)
21 .visit::<ast::String, _>(string::validate_string_node)
22 .visit::<ast::Block, _>(block::validate_block_node) 19 .visit::<ast::Block, _>(block::validate_block_node)
23 .accept(node); 20 .accept(node);
24 } 21 }
25 errors 22 errors
26} 23}
27 24
25// FIXME: kill duplication
26fn validate_literal(literal: &ast::Literal, acc: &mut Vec<SyntaxError>) {
27 match literal.token().kind() {
28 BYTE => byte::validate_byte_node(literal.token(), acc),
29 BYTE_STRING => byte_string::validate_byte_string_node(literal.token(), acc),
30 STRING => string::validate_string_node(literal.token(), acc),
31 CHAR => char::validate_char_node(literal.token(), acc),
32 _ => (),
33 }
34}
35
28pub(crate) fn validate_block_structure(root: &SyntaxNode) { 36pub(crate) fn validate_block_structure(root: &SyntaxNode) {
29 let mut stack = Vec::new(); 37 let mut stack = Vec::new();
30 for node in root.descendants() { 38 for node in root.descendants() {
diff --git a/crates/ra_syntax/src/validation/byte.rs b/crates/ra_syntax/src/validation/byte.rs
index 838e7a65f..f653e65d0 100644
--- a/crates/ra_syntax/src/validation/byte.rs
+++ b/crates/ra_syntax/src/validation/byte.rs
@@ -1,18 +1,18 @@
1//! Validation of byte literals 1//! Validation of byte literals
2 2
3use crate::{ 3use crate::{
4 ast::{self, AstNode, AstToken},
5 string_lexing::{self, StringComponentKind}, 4 string_lexing::{self, StringComponentKind},
6 TextRange, 5 TextRange,
7 validation::char, 6 validation::char,
8 SyntaxError, 7 SyntaxError,
9 SyntaxErrorKind::*, 8 SyntaxErrorKind::*,
9 SyntaxToken,
10}; 10};
11 11
12pub(super) fn validate_byte_node(node: &ast::Byte, errors: &mut Vec<SyntaxError>) { 12pub(super) fn validate_byte_node(node: SyntaxToken, errors: &mut Vec<SyntaxError>) {
13 let literal_text = node.text(); 13 let literal_text = node.text();
14 let literal_range = node.syntax().range(); 14 let literal_range = node.range();
15 let mut components = string_lexing::parse_byte_literal(literal_text); 15 let mut components = string_lexing::parse_quoted_literal(Some('b'), '\'', literal_text);
16 let mut len = 0; 16 let mut len = 0;
17 for component in &mut components { 17 for component in &mut components {
18 len += 1; 18 len += 1;
diff --git a/crates/ra_syntax/src/validation/byte_string.rs b/crates/ra_syntax/src/validation/byte_string.rs
index 64c7054a1..1d48c2d9b 100644
--- a/crates/ra_syntax/src/validation/byte_string.rs
+++ b/crates/ra_syntax/src/validation/byte_string.rs
@@ -1,16 +1,16 @@
1use crate::{ 1use crate::{
2 ast::{self, AstNode, AstToken},
3 string_lexing::{self, StringComponentKind}, 2 string_lexing::{self, StringComponentKind},
4 SyntaxError, 3 SyntaxError,
5 SyntaxErrorKind::*, 4 SyntaxErrorKind::*,
5 SyntaxToken,
6}; 6};
7 7
8use super::byte; 8use super::byte;
9 9
10pub(crate) fn validate_byte_string_node(node: &ast::ByteString, errors: &mut Vec<SyntaxError>) { 10pub(crate) fn validate_byte_string_node(node: SyntaxToken, errors: &mut Vec<SyntaxError>) {
11 let literal_text = node.text(); 11 let literal_text = node.text();
12 let literal_range = node.syntax().range(); 12 let literal_range = node.range();
13 let mut components = string_lexing::parse_byte_string_literal(literal_text); 13 let mut components = string_lexing::parse_quoted_literal(Some('b'), '"', literal_text);
14 for component in &mut components { 14 for component in &mut components {
15 let range = component.range + literal_range.start(); 15 let range = component.range + literal_range.start();
16 16
diff --git a/crates/ra_syntax/src/validation/char.rs b/crates/ra_syntax/src/validation/char.rs
index c874e5d08..0f1885873 100644
--- a/crates/ra_syntax/src/validation/char.rs
+++ b/crates/ra_syntax/src/validation/char.rs
@@ -5,17 +5,17 @@ use std::u32;
5use arrayvec::ArrayString; 5use arrayvec::ArrayString;
6 6
7use crate::{ 7use crate::{
8 ast::{self, AstNode, AstToken},
9 string_lexing::{self, StringComponentKind}, 8 string_lexing::{self, StringComponentKind},
10 TextRange, 9 TextRange,
11 SyntaxError, 10 SyntaxError,
12 SyntaxErrorKind::*, 11 SyntaxErrorKind::*,
12 SyntaxToken,
13}; 13};
14 14
15pub(super) fn validate_char_node(node: &ast::Char, errors: &mut Vec<SyntaxError>) { 15pub(super) fn validate_char_node(node: SyntaxToken, errors: &mut Vec<SyntaxError>) {
16 let literal_text = node.text(); 16 let literal_text = node.text();
17 let literal_range = node.syntax().range(); 17 let literal_range = node.range();
18 let mut components = string_lexing::parse_char_literal(literal_text); 18 let mut components = string_lexing::parse_quoted_literal(None, '\'', literal_text);
19 let mut len = 0; 19 let mut len = 0;
20 for component in &mut components { 20 for component in &mut components {
21 len += 1; 21 len += 1;
diff --git a/crates/ra_syntax/src/validation/string.rs b/crates/ra_syntax/src/validation/string.rs
index d857d088c..fc2f1b992 100644
--- a/crates/ra_syntax/src/validation/string.rs
+++ b/crates/ra_syntax/src/validation/string.rs
@@ -1,16 +1,16 @@
1use crate::{ 1use crate::{
2 ast::{self, AstNode, AstToken},
3 string_lexing, 2 string_lexing,
4 SyntaxError, 3 SyntaxError,
5 SyntaxErrorKind::*, 4 SyntaxErrorKind::*,
5 SyntaxToken,
6}; 6};
7 7
8use super::char; 8use super::char;
9 9
10pub(crate) fn validate_string_node(node: &ast::String, errors: &mut Vec<SyntaxError>) { 10pub(crate) fn validate_string_node(node: SyntaxToken, errors: &mut Vec<SyntaxError>) {
11 let literal_text = node.text(); 11 let literal_text = node.text();
12 let literal_range = node.syntax().range(); 12 let literal_range = node.range();
13 let mut components = string_lexing::parse_string_literal(literal_text); 13 let mut components = string_lexing::parse_quoted_literal(None, '"', literal_text);
14 for component in &mut components { 14 for component in &mut components {
15 let range = component.range + literal_range.start(); 15 let range = component.range + literal_range.start();
16 16