aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r--crates/ra_syntax/Cargo.toml2
-rw-r--r--crates/ra_syntax/src/algo.rs41
-rw-r--r--crates/ra_syntax/src/ast.rs317
-rw-r--r--crates/ra_syntax/src/ast/generated.rs627
-rw-r--r--crates/ra_syntax/src/grammar.ron74
-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/syntax_node.rs287
-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.rs6
-rw-r--r--crates/ra_syntax/src/validation/byte_string.rs6
-rw-r--r--crates/ra_syntax/src/validation/char.rs6
-rw-r--r--crates/ra_syntax/src/validation/string.rs6
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0024_many_type_parens.txt312
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0026_imp_recovery.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt38
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.txt23
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.txt38
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.txt49
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.txt32
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.txt108
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.txt48
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.txt65
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt51
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.txt49
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0076_function_where_clause.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0081_for_type.txt24
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs3
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt56
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0114_tuple_struct_where.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0001_struct_item.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt17
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.txt172
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0032_where_for.txt67
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt32
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt24
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0045_block_inner_attrs.txt54
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0049_async_block.rs5
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0049_async_block.txt35
49 files changed, 1704 insertions, 1296 deletions
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml
index 7e70dad3f..1a763fb47 100644
--- a/crates/ra_syntax/Cargo.toml
+++ b/crates/ra_syntax/Cargo.toml
@@ -13,7 +13,7 @@ unicode-xid = "0.1.0"
13itertools = "0.8.0" 13itertools = "0.8.0"
14drop_bomb = "0.1.4" 14drop_bomb = "0.1.4"
15parking_lot = "0.7.0" 15parking_lot = "0.7.0"
16rowan = "0.3.3" 16rowan = "0.4.0"
17 17
18# ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here 18# ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here
19# to reduce number of compilations 19# to reduce number of compilations
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..9a44afc67 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -7,7 +7,7 @@ use itertools::Itertools;
7 7
8pub use self::generated::*; 8pub use self::generated::*;
9use crate::{ 9use crate::{
10 syntax_node::{SyntaxNode, SyntaxNodeChildren, TreeArc, RaTypes}, 10 syntax_node::{SyntaxNode, SyntaxNodeChildren, TreeArc, RaTypes, SyntaxToken, SyntaxElement, SyntaxElementChildren},
11 SmolStr, 11 SmolStr,
12 SyntaxKind::*, 12 SyntaxKind::*,
13}; 13};
@@ -27,7 +27,8 @@ pub trait AstNode:
27 27
28pub trait AstToken: AstNode { 28pub trait AstToken: AstNode {
29 fn text(&self) -> &SmolStr { 29 fn text(&self) -> &SmolStr {
30 self.syntax().leaf_text().unwrap() 30 // self.syntax().leaf_text().unwrap()
31 unimplemented!()
31 } 32 }
32} 33}
33 34
@@ -110,6 +111,12 @@ pub trait TypeParamsOwner: AstNode {
110 } 111 }
111} 112}
112 113
114pub trait TypeBoundsOwner: AstNode {
115 fn type_bound_list(&self) -> Option<&TypeBoundList> {
116 child_opt(self)
117 }
118}
119
113pub trait AttrsOwner: AstNode { 120pub trait AttrsOwner: AstNode {
114 fn attrs(&self) -> AstChildren<Attr> { 121 fn attrs(&self) -> AstChildren<Attr> {
115 children(self) 122 children(self)
@@ -120,8 +127,8 @@ pub trait AttrsOwner: AstNode {
120} 127}
121 128
122pub trait DocCommentsOwner: AstNode { 129pub trait DocCommentsOwner: AstNode {
123 fn doc_comments(&self) -> AstChildren<Comment> { 130 fn doc_comments(&self) -> CommentIter {
124 children(self) 131 CommentIter { iter: self.syntax().children_with_tokens() }
125 } 132 }
126 133
127 /// Returns the textual content of a doc comment block as a single string. 134 /// Returns the textual content of a doc comment block as a single string.
@@ -173,9 +180,9 @@ impl Attr {
173 180
174 pub fn as_atom(&self) -> Option<SmolStr> { 181 pub fn as_atom(&self) -> Option<SmolStr> {
175 let tt = self.value()?; 182 let tt = self.value()?;
176 let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?; 183 let (_bra, attr, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
177 if attr.kind() == IDENT { 184 if attr.kind() == IDENT {
178 Some(attr.leaf_text().unwrap().clone()) 185 Some(attr.as_token()?.text().clone())
179 } else { 186 } else {
180 None 187 None
181 } 188 }
@@ -183,10 +190,10 @@ impl Attr {
183 190
184 pub fn as_call(&self) -> Option<(SmolStr, &TokenTree)> { 191 pub fn as_call(&self) -> Option<(SmolStr, &TokenTree)> {
185 let tt = self.value()?; 192 let tt = self.value()?;
186 let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?; 193 let (_bra, attr, args, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
187 let args = TokenTree::cast(args)?; 194 let args = TokenTree::cast(args.as_node()?)?;
188 if attr.kind() == IDENT { 195 if attr.kind() == IDENT {
189 Some((attr.leaf_text().unwrap().clone(), args)) 196 Some((attr.as_token()?.text().clone(), args))
190 } else { 197 } else {
191 None 198 None
192 } 199 }
@@ -194,16 +201,35 @@ impl Attr {
194 201
195 pub fn as_named(&self) -> Option<SmolStr> { 202 pub fn as_named(&self) -> Option<SmolStr> {
196 let tt = self.value()?; 203 let tt = self.value()?;
197 let attr = tt.syntax().children().nth(1)?; 204 let attr = tt.syntax().children_with_tokens().nth(1)?;
198 if attr.kind() == IDENT { 205 if attr.kind() == IDENT {
199 Some(attr.leaf_text().unwrap().clone()) 206 Some(attr.as_token()?.text().clone())
200 } else { 207 } else {
201 None 208 None
202 } 209 }
203 } 210 }
204} 211}
205 212
206impl Comment { 213#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
214pub struct Comment<'a>(SyntaxToken<'a>);
215
216impl<'a> Comment<'a> {
217 pub fn cast(token: SyntaxToken<'a>) -> Option<Self> {
218 if token.kind() == COMMENT {
219 Some(Comment(token))
220 } else {
221 None
222 }
223 }
224
225 pub fn syntax(&self) -> SyntaxToken<'a> {
226 self.0
227 }
228
229 pub fn text(&self) -> &'a SmolStr {
230 self.0.text()
231 }
232
207 pub fn flavor(&self) -> CommentFlavor { 233 pub fn flavor(&self) -> CommentFlavor {
208 let text = self.text(); 234 let text = self.text();
209 if text.starts_with("///") { 235 if text.starts_with("///") {
@@ -224,13 +250,16 @@ impl Comment {
224 pub fn prefix(&self) -> &'static str { 250 pub fn prefix(&self) -> &'static str {
225 self.flavor().prefix() 251 self.flavor().prefix()
226 } 252 }
253}
227 254
228 pub fn count_newlines_lazy(&self) -> impl Iterator<Item = &()> { 255pub struct CommentIter<'a> {
229 self.text().chars().filter(|&c| c == '\n').map(|_| &()) 256 iter: SyntaxElementChildren<'a>,
230 } 257}
231 258
232 pub fn has_newlines(&self) -> bool { 259impl<'a> Iterator for CommentIter<'a> {
233 self.count_newlines_lazy().count() > 0 260 type Item = Comment<'a>;
261 fn next(&mut self) -> Option<Comment<'a>> {
262 self.iter.by_ref().find_map(|el| el.as_token().and_then(Comment::cast))
234 } 263 }
235} 264}
236 265
@@ -261,27 +290,42 @@ impl CommentFlavor {
261 } 290 }
262} 291}
263 292
264impl Whitespace { 293pub struct Whitespace<'a>(SyntaxToken<'a>);
265 pub fn count_newlines_lazy(&self) -> impl Iterator<Item = &()> { 294
266 self.text().chars().filter(|&c| c == '\n').map(|_| &()) 295impl<'a> Whitespace<'a> {
296 pub fn cast(token: SyntaxToken<'a>) -> Option<Self> {
297 if token.kind() == WHITESPACE {
298 Some(Whitespace(token))
299 } else {
300 None
301 }
267 } 302 }
268 303
269 pub fn has_newlines(&self) -> bool { 304 pub fn syntax(&self) -> SyntaxToken<'a> {
270 self.text().contains('\n') 305 self.0
306 }
307
308 pub fn text(&self) -> &'a SmolStr {
309 self.0.text()
310 }
311
312 pub fn spans_multiple_lines(&self) -> bool {
313 let text = self.text();
314 text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n'))
271 } 315 }
272} 316}
273 317
274impl Name { 318impl Name {
275 pub fn text(&self) -> &SmolStr { 319 pub fn text(&self) -> &SmolStr {
276 let ident = self.syntax().first_child().unwrap(); 320 let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap();
277 ident.leaf_text().unwrap() 321 ident.text()
278 } 322 }
279} 323}
280 324
281impl NameRef { 325impl NameRef {
282 pub fn text(&self) -> &SmolStr { 326 pub fn text(&self) -> &SmolStr {
283 let ident = self.syntax().first_child().unwrap(); 327 let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap();
284 ident.leaf_text().unwrap() 328 ident.text()
285 } 329 }
286} 330}
287 331
@@ -310,7 +354,7 @@ impl ImplBlock {
310 354
311impl Module { 355impl Module {
312 pub fn has_semi(&self) -> bool { 356 pub fn has_semi(&self) -> bool {
313 match self.syntax().last_child() { 357 match self.syntax().last_child_or_token() {
314 None => false, 358 None => false,
315 Some(node) => node.kind() == SEMI, 359 Some(node) => node.kind() == SEMI,
316 } 360 }
@@ -319,7 +363,7 @@ impl Module {
319 363
320impl LetStmt { 364impl LetStmt {
321 pub fn has_semi(&self) -> bool { 365 pub fn has_semi(&self) -> bool {
322 match self.syntax().last_child() { 366 match self.syntax().last_child_or_token() {
323 None => false, 367 None => false,
324 Some(node) => node.kind() == SEMI, 368 Some(node) => node.kind() == SEMI,
325 } 369 }
@@ -354,7 +398,7 @@ impl IfExpr {
354 398
355impl ExprStmt { 399impl ExprStmt {
356 pub fn has_semi(&self) -> bool { 400 pub fn has_semi(&self) -> bool {
357 match self.syntax().last_child() { 401 match self.syntax().last_child_or_token() {
358 None => false, 402 None => false,
359 Some(node) => node.kind() == SEMI, 403 Some(node) => node.kind() == SEMI,
360 } 404 }
@@ -378,7 +422,7 @@ impl PathSegment {
378 let res = if let Some(name_ref) = self.name_ref() { 422 let res = if let Some(name_ref) = self.name_ref() {
379 PathSegmentKind::Name(name_ref) 423 PathSegmentKind::Name(name_ref)
380 } else { 424 } else {
381 match self.syntax().first_child()?.kind() { 425 match self.syntax().first_child_or_token()?.kind() {
382 SELF_KW => PathSegmentKind::SelfKw, 426 SELF_KW => PathSegmentKind::SelfKw,
383 SUPER_KW => PathSegmentKind::SuperKw, 427 SUPER_KW => PathSegmentKind::SuperKw,
384 CRATE_KW => PathSegmentKind::CrateKw, 428 CRATE_KW => PathSegmentKind::CrateKw,
@@ -389,7 +433,7 @@ impl PathSegment {
389 } 433 }
390 434
391 pub fn has_colon_colon(&self) -> bool { 435 pub fn has_colon_colon(&self) -> bool {
392 match self.syntax.first_child().map(|s| s.kind()) { 436 match self.syntax.first_child_or_token().map(|s| s.kind()) {
393 Some(COLONCOLON) => true, 437 Some(COLONCOLON) => true,
394 _ => false, 438 _ => false,
395 } 439 }
@@ -404,7 +448,7 @@ impl Path {
404 448
405impl UseTree { 449impl UseTree {
406 pub fn has_star(&self) -> bool { 450 pub fn has_star(&self) -> bool {
407 self.syntax().children().any(|it| it.kind() == STAR) 451 self.syntax().children_with_tokens().any(|it| it.kind() == STAR)
408 } 452 }
409} 453}
410 454
@@ -419,7 +463,7 @@ impl UseTreeList {
419 463
420impl RefPat { 464impl RefPat {
421 pub fn is_mut(&self) -> bool { 465 pub fn is_mut(&self) -> bool {
422 self.syntax().children().any(|n| n.kind() == MUT_KW) 466 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
423 } 467 }
424} 468}
425 469
@@ -494,19 +538,19 @@ impl EnumVariant {
494 538
495impl PointerType { 539impl PointerType {
496 pub fn is_mut(&self) -> bool { 540 pub fn is_mut(&self) -> bool {
497 self.syntax().children().any(|n| n.kind() == MUT_KW) 541 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
498 } 542 }
499} 543}
500 544
501impl ReferenceType { 545impl ReferenceType {
502 pub fn is_mut(&self) -> bool { 546 pub fn is_mut(&self) -> bool {
503 self.syntax().children().any(|n| n.kind() == MUT_KW) 547 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
504 } 548 }
505} 549}
506 550
507impl RefExpr { 551impl RefExpr {
508 pub fn is_mut(&self) -> bool { 552 pub fn is_mut(&self) -> bool {
509 self.syntax().children().any(|n| n.kind() == MUT_KW) 553 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
510 } 554 }
511} 555}
512 556
@@ -522,7 +566,7 @@ pub enum PrefixOp {
522 566
523impl PrefixExpr { 567impl PrefixExpr {
524 pub fn op_kind(&self) -> Option<PrefixOp> { 568 pub fn op_kind(&self) -> Option<PrefixOp> {
525 match self.syntax().first_child()?.kind() { 569 match self.op_token()?.kind() {
526 STAR => Some(PrefixOp::Deref), 570 STAR => Some(PrefixOp::Deref),
527 EXCL => Some(PrefixOp::Not), 571 EXCL => Some(PrefixOp::Not),
528 MINUS => Some(PrefixOp::Neg), 572 MINUS => Some(PrefixOp::Neg),
@@ -530,8 +574,8 @@ impl PrefixExpr {
530 } 574 }
531 } 575 }
532 576
533 pub fn op(&self) -> Option<&SyntaxNode> { 577 pub fn op_token(&self) -> Option<SyntaxToken> {
534 self.syntax().first_child() 578 self.syntax().first_child_or_token()?.as_token()
535 } 579 }
536} 580}
537 581
@@ -602,40 +646,42 @@ pub enum BinOp {
602} 646}
603 647
604impl BinExpr { 648impl BinExpr {
605 fn op_details(&self) -> Option<(&SyntaxNode, BinOp)> { 649 fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
606 self.syntax().children().find_map(|c| match c.kind() { 650 self.syntax().children_with_tokens().filter_map(|it| it.as_token()).find_map(|c| {
607 PIPEPIPE => Some((c, BinOp::BooleanOr)), 651 match c.kind() {
608 AMPAMP => Some((c, BinOp::BooleanAnd)), 652 PIPEPIPE => Some((c, BinOp::BooleanOr)),
609 EQEQ => Some((c, BinOp::EqualityTest)), 653 AMPAMP => Some((c, BinOp::BooleanAnd)),
610 NEQ => Some((c, BinOp::NegatedEqualityTest)), 654 EQEQ => Some((c, BinOp::EqualityTest)),
611 LTEQ => Some((c, BinOp::LesserEqualTest)), 655 NEQ => Some((c, BinOp::NegatedEqualityTest)),
612 GTEQ => Some((c, BinOp::GreaterEqualTest)), 656 LTEQ => Some((c, BinOp::LesserEqualTest)),
613 L_ANGLE => Some((c, BinOp::LesserTest)), 657 GTEQ => Some((c, BinOp::GreaterEqualTest)),
614 R_ANGLE => Some((c, BinOp::GreaterTest)), 658 L_ANGLE => Some((c, BinOp::LesserTest)),
615 PLUS => Some((c, BinOp::Addition)), 659 R_ANGLE => Some((c, BinOp::GreaterTest)),
616 STAR => Some((c, BinOp::Multiplication)), 660 PLUS => Some((c, BinOp::Addition)),
617 MINUS => Some((c, BinOp::Subtraction)), 661 STAR => Some((c, BinOp::Multiplication)),
618 SLASH => Some((c, BinOp::Division)), 662 MINUS => Some((c, BinOp::Subtraction)),
619 PERCENT => Some((c, BinOp::Remainder)), 663 SLASH => Some((c, BinOp::Division)),
620 SHL => Some((c, BinOp::LeftShift)), 664 PERCENT => Some((c, BinOp::Remainder)),
621 SHR => Some((c, BinOp::RightShift)), 665 SHL => Some((c, BinOp::LeftShift)),
622 CARET => Some((c, BinOp::BitwiseXor)), 666 SHR => Some((c, BinOp::RightShift)),
623 PIPE => Some((c, BinOp::BitwiseOr)), 667 CARET => Some((c, BinOp::BitwiseXor)),
624 AMP => Some((c, BinOp::BitwiseAnd)), 668 PIPE => Some((c, BinOp::BitwiseOr)),
625 DOTDOT => Some((c, BinOp::RangeRightOpen)), 669 AMP => Some((c, BinOp::BitwiseAnd)),
626 DOTDOTEQ => Some((c, BinOp::RangeRightClosed)), 670 DOTDOT => Some((c, BinOp::RangeRightOpen)),
627 EQ => Some((c, BinOp::Assignment)), 671 DOTDOTEQ => Some((c, BinOp::RangeRightClosed)),
628 PLUSEQ => Some((c, BinOp::AddAssign)), 672 EQ => Some((c, BinOp::Assignment)),
629 SLASHEQ => Some((c, BinOp::DivAssign)), 673 PLUSEQ => Some((c, BinOp::AddAssign)),
630 STAREQ => Some((c, BinOp::MulAssign)), 674 SLASHEQ => Some((c, BinOp::DivAssign)),
631 PERCENTEQ => Some((c, BinOp::RemAssign)), 675 STAREQ => Some((c, BinOp::MulAssign)),
632 SHREQ => Some((c, BinOp::ShrAssign)), 676 PERCENTEQ => Some((c, BinOp::RemAssign)),
633 SHLEQ => Some((c, BinOp::ShlAssign)), 677 SHREQ => Some((c, BinOp::ShrAssign)),
634 MINUSEQ => Some((c, BinOp::SubAssign)), 678 SHLEQ => Some((c, BinOp::ShlAssign)),
635 PIPEEQ => Some((c, BinOp::BitOrAssign)), 679 MINUSEQ => Some((c, BinOp::SubAssign)),
636 AMPEQ => Some((c, BinOp::BitAndAssign)), 680 PIPEEQ => Some((c, BinOp::BitOrAssign)),
637 CARETEQ => Some((c, BinOp::BitXorAssign)), 681 AMPEQ => Some((c, BinOp::BitAndAssign)),
638 _ => None, 682 CARETEQ => Some((c, BinOp::BitXorAssign)),
683 _ => None,
684 }
639 }) 685 })
640 } 686 }
641 687
@@ -643,7 +689,7 @@ impl BinExpr {
643 self.op_details().map(|t| t.1) 689 self.op_details().map(|t| t.1)
644 } 690 }
645 691
646 pub fn op(&self) -> Option<&SyntaxNode> { 692 pub fn op_token(&self) -> Option<SyntaxToken> {
647 self.op_details().map(|t| t.0) 693 self.op_details().map(|t| t.0)
648 } 694 }
649 695
@@ -674,11 +720,23 @@ pub enum SelfParamFlavor {
674} 720}
675 721
676impl SelfParam { 722impl SelfParam {
723 pub fn self_kw_token(&self) -> SyntaxToken {
724 self.syntax()
725 .children_with_tokens()
726 .filter_map(|it| it.as_token())
727 .find(|it| it.kind() == SELF_KW)
728 .expect("invalid tree: self param must have self")
729 }
730
677 pub fn flavor(&self) -> SelfParamFlavor { 731 pub fn flavor(&self) -> SelfParamFlavor {
678 let borrowed = self.syntax().children().any(|n| n.kind() == AMP); 732 let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == AMP);
679 if borrowed { 733 if borrowed {
680 // check for a `mut` coming after the & -- `mut &self` != `&mut self` 734 // 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) 735 if self
736 .syntax()
737 .children_with_tokens()
738 .skip_while(|n| n.kind() != AMP)
739 .any(|n| n.kind() == MUT_KW)
682 { 740 {
683 SelfParamFlavor::MutRef 741 SelfParamFlavor::MutRef
684 } else { 742 } else {
@@ -701,25 +759,31 @@ pub enum LiteralFlavor {
701 Bool, 759 Bool,
702} 760}
703 761
704impl LiteralExpr { 762impl Literal {
763 pub fn token(&self) -> SyntaxToken {
764 match self.syntax().first_child_or_token().unwrap() {
765 SyntaxElement::Token(token) => token,
766 _ => unreachable!(),
767 }
768 }
769
705 pub fn flavor(&self) -> LiteralFlavor { 770 pub fn flavor(&self) -> LiteralFlavor {
706 let syntax = self.syntax(); 771 match self.token().kind() {
707 match syntax.kind() {
708 INT_NUMBER => { 772 INT_NUMBER => {
709 let allowed_suffix_list = [ 773 let allowed_suffix_list = [
710 "isize", "i128", "i64", "i32", "i16", "i8", "usize", "u128", "u64", "u32", 774 "isize", "i128", "i64", "i32", "i16", "i8", "usize", "u128", "u64", "u32",
711 "u16", "u8", 775 "u16", "u8",
712 ]; 776 ];
713 let text = syntax.text().to_string(); 777 let text = self.token().text().to_string();
714 let suffix = allowed_suffix_list 778 let suffix = allowed_suffix_list
715 .iter() 779 .iter()
716 .find(|&s| text.ends_with(s)) 780 .find(|&s| text.ends_with(s))
717 .map(|&suf| SmolStr::new(suf)); 781 .map(|&suf| SmolStr::new(suf));
718 LiteralFlavor::IntNumber { suffix: suffix } 782 LiteralFlavor::IntNumber { suffix }
719 } 783 }
720 FLOAT_NUMBER => { 784 FLOAT_NUMBER => {
721 let allowed_suffix_list = ["f64", "f32"]; 785 let allowed_suffix_list = ["f64", "f32"];
722 let text = syntax.text().to_string(); 786 let text = self.token().text().to_string();
723 let suffix = allowed_suffix_list 787 let suffix = allowed_suffix_list
724 .iter() 788 .iter()
725 .find(|&s| text.ends_with(s)) 789 .find(|&s| text.ends_with(s))
@@ -744,11 +808,29 @@ impl NamedField {
744 808
745impl BindPat { 809impl BindPat {
746 pub fn is_mutable(&self) -> bool { 810 pub fn is_mutable(&self) -> bool {
747 self.syntax().children().any(|n| n.kind() == MUT_KW) 811 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
748 } 812 }
749 813
750 pub fn is_ref(&self) -> bool { 814 pub fn is_ref(&self) -> bool {
751 self.syntax().children().any(|n| n.kind() == REF_KW) 815 self.syntax().children_with_tokens().any(|n| n.kind() == REF_KW)
816 }
817}
818
819impl LifetimeParam {
820 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
821 self.syntax()
822 .children_with_tokens()
823 .filter_map(|it| it.as_token())
824 .find(|it| it.kind() == LIFETIME)
825 }
826}
827
828impl WherePred {
829 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
830 self.syntax()
831 .children_with_tokens()
832 .filter_map(|it| it.as_token())
833 .find(|it| it.kind() == LIFETIME)
752 } 834 }
753} 835}
754 836
@@ -793,3 +875,70 @@ fn test_doc_comment_preserves_indents() {
793 let module = file.syntax().descendants().find_map(Module::cast).unwrap(); 875 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()); 876 assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap());
795} 877}
878
879#[test]
880fn test_where_predicates() {
881 fn assert_bound(text: &str, bound: Option<&TypeBound>) {
882 assert_eq!(text, bound.unwrap().syntax().text().to_string());
883 }
884
885 let file = SourceFile::parse(
886 r#"
887fn foo()
888where
889 T: Clone + Copy + Debug + 'static,
890 'a: 'b + 'c,
891 Iterator::Item: 'a + Debug,
892 Iterator::Item: Debug + 'a,
893 <T as Iterator>::Item: Debug + 'a,
894 for<'a> F: Fn(&'a str)
895{}
896 "#,
897 );
898 let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap();
899
900 let mut predicates = where_clause.predicates();
901
902 let pred = predicates.next().unwrap();
903 let mut bounds = pred.type_bound_list().unwrap().bounds();
904
905 assert_eq!("T", pred.type_ref().unwrap().syntax().text().to_string());
906 assert_bound("Clone", bounds.next());
907 assert_bound("Copy", bounds.next());
908 assert_bound("Debug", bounds.next());
909 assert_bound("'static", bounds.next());
910
911 let pred = predicates.next().unwrap();
912 let mut bounds = pred.type_bound_list().unwrap().bounds();
913
914 assert_eq!("'a", pred.lifetime_token().unwrap().text());
915
916 assert_bound("'b", bounds.next());
917 assert_bound("'c", bounds.next());
918
919 let pred = predicates.next().unwrap();
920 let mut bounds = pred.type_bound_list().unwrap().bounds();
921
922 assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string());
923 assert_bound("'a", bounds.next());
924
925 let pred = predicates.next().unwrap();
926 let mut bounds = pred.type_bound_list().unwrap().bounds();
927
928 assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string());
929 assert_bound("Debug", bounds.next());
930 assert_bound("'a", bounds.next());
931
932 let pred = predicates.next().unwrap();
933 let mut bounds = pred.type_bound_list().unwrap().bounds();
934
935 assert_eq!("<T as Iterator>::Item", pred.type_ref().unwrap().syntax().text().to_string());
936 assert_bound("Debug", bounds.next());
937 assert_bound("'a", bounds.next());
938
939 let pred = predicates.next().unwrap();
940 let mut bounds = pred.type_bound_list().unwrap().bounds();
941
942 assert_eq!("for<'a> F", pred.type_ref().unwrap().syntax().text().to_string());
943 assert_bound("Fn(&'a str)", bounds.next());
944}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 47a37e4d1..4afe1a146 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)]
@@ -685,6 +569,7 @@ impl ToOwned for DynTraitType {
685} 569}
686 570
687 571
572impl ast::TypeBoundsOwner for DynTraitType {}
688impl DynTraitType {} 573impl DynTraitType {}
689 574
690// EnumDef 575// EnumDef
@@ -1114,35 +999,6 @@ impl ExternCrateItem {
1114 } 999 }
1115} 1000}
1116 1001
1117// FalseKw
1118#[derive(Debug, PartialEq, Eq, Hash)]
1119#[repr(transparent)]
1120pub struct FalseKw {
1121 pub(crate) syntax: SyntaxNode,
1122}
1123unsafe impl TransparentNewType for FalseKw {
1124 type Repr = rowan::SyntaxNode<RaTypes>;
1125}
1126
1127impl AstNode for FalseKw {
1128 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1129 match syntax.kind() {
1130 FALSE_KW => Some(FalseKw::from_repr(syntax.into_repr())),
1131 _ => None,
1132 }
1133 }
1134 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1135}
1136
1137impl ToOwned for FalseKw {
1138 type Owned = TreeArc<FalseKw>;
1139 fn to_owned(&self) -> TreeArc<FalseKw> { TreeArc::cast(self.syntax.to_owned()) }
1140}
1141
1142
1143impl ast::AstToken for FalseKw {}
1144impl FalseKw {}
1145
1146// FieldExpr 1002// FieldExpr
1147#[derive(Debug, PartialEq, Eq, Hash)] 1003#[derive(Debug, PartialEq, Eq, Hash)]
1148#[repr(transparent)] 1004#[repr(transparent)]
@@ -1248,35 +1104,6 @@ impl FieldPatList {
1248 } 1104 }
1249} 1105}
1250 1106
1251// FloatNumber
1252#[derive(Debug, PartialEq, Eq, Hash)]
1253#[repr(transparent)]
1254pub struct FloatNumber {
1255 pub(crate) syntax: SyntaxNode,
1256}
1257unsafe impl TransparentNewType for FloatNumber {
1258 type Repr = rowan::SyntaxNode<RaTypes>;
1259}
1260
1261impl AstNode for FloatNumber {
1262 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1263 match syntax.kind() {
1264 FLOAT_NUMBER => Some(FloatNumber::from_repr(syntax.into_repr())),
1265 _ => None,
1266 }
1267 }
1268 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1269}
1270
1271impl ToOwned for FloatNumber {
1272 type Owned = TreeArc<FloatNumber>;
1273 fn to_owned(&self) -> TreeArc<FloatNumber> { TreeArc::cast(self.syntax.to_owned()) }
1274}
1275
1276
1277impl ast::AstToken for FloatNumber {}
1278impl FloatNumber {}
1279
1280// FnDef 1107// FnDef
1281#[derive(Debug, PartialEq, Eq, Hash)] 1108#[derive(Debug, PartialEq, Eq, Hash)]
1282#[repr(transparent)] 1109#[repr(transparent)]
@@ -1581,6 +1408,7 @@ impl ToOwned for ImplTraitType {
1581} 1408}
1582 1409
1583 1410
1411impl ast::TypeBoundsOwner for ImplTraitType {}
1584impl ImplTraitType {} 1412impl ImplTraitType {}
1585 1413
1586// IndexExpr 1414// IndexExpr
@@ -1611,35 +1439,6 @@ impl ToOwned for IndexExpr {
1611 1439
1612impl IndexExpr {} 1440impl IndexExpr {}
1613 1441
1614// IntNumber
1615#[derive(Debug, PartialEq, Eq, Hash)]
1616#[repr(transparent)]
1617pub struct IntNumber {
1618 pub(crate) syntax: SyntaxNode,
1619}
1620unsafe impl TransparentNewType for IntNumber {
1621 type Repr = rowan::SyntaxNode<RaTypes>;
1622}
1623
1624impl AstNode for IntNumber {
1625 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1626 match syntax.kind() {
1627 INT_NUMBER => Some(IntNumber::from_repr(syntax.into_repr())),
1628 _ => None,
1629 }
1630 }
1631 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1632}
1633
1634impl ToOwned for IntNumber {
1635 type Owned = TreeArc<IntNumber>;
1636 fn to_owned(&self) -> TreeArc<IntNumber> { TreeArc::cast(self.syntax.to_owned()) }
1637}
1638
1639
1640impl ast::AstToken for IntNumber {}
1641impl IntNumber {}
1642
1643// ItemList 1442// ItemList
1644#[derive(Debug, PartialEq, Eq, Hash)] 1443#[derive(Debug, PartialEq, Eq, Hash)]
1645#[repr(transparent)] 1444#[repr(transparent)]
@@ -1775,35 +1574,6 @@ impl LetStmt {
1775 } 1574 }
1776} 1575}
1777 1576
1778// Lifetime
1779#[derive(Debug, PartialEq, Eq, Hash)]
1780#[repr(transparent)]
1781pub struct Lifetime {
1782 pub(crate) syntax: SyntaxNode,
1783}
1784unsafe impl TransparentNewType for Lifetime {
1785 type Repr = rowan::SyntaxNode<RaTypes>;
1786}
1787
1788impl AstNode for Lifetime {
1789 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1790 match syntax.kind() {
1791 LIFETIME => Some(Lifetime::from_repr(syntax.into_repr())),
1792 _ => None,
1793 }
1794 }
1795 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1796}
1797
1798impl ToOwned for Lifetime {
1799 type Owned = TreeArc<Lifetime>;
1800 fn to_owned(&self) -> TreeArc<Lifetime> { TreeArc::cast(self.syntax.to_owned()) }
1801}
1802
1803
1804impl ast::AstToken for Lifetime {}
1805impl Lifetime {}
1806
1807// LifetimeArg 1577// LifetimeArg
1808#[derive(Debug, PartialEq, Eq, Hash)] 1578#[derive(Debug, PartialEq, Eq, Hash)]
1809#[repr(transparent)] 1579#[repr(transparent)]
@@ -1830,11 +1600,7 @@ impl ToOwned for LifetimeArg {
1830} 1600}
1831 1601
1832 1602
1833impl LifetimeArg { 1603impl LifetimeArg {}
1834 pub fn lifetime(&self) -> Option<&Lifetime> {
1835 super::child_opt(self)
1836 }
1837}
1838 1604
1839// LifetimeParam 1605// LifetimeParam
1840#[derive(Debug, PartialEq, Eq, Hash)] 1606#[derive(Debug, PartialEq, Eq, Hash)]
@@ -1863,11 +1629,7 @@ impl ToOwned for LifetimeParam {
1863 1629
1864 1630
1865impl ast::AttrsOwner for LifetimeParam {} 1631impl ast::AttrsOwner for LifetimeParam {}
1866impl LifetimeParam { 1632impl LifetimeParam {}
1867 pub fn lifetime(&self) -> Option<&Lifetime> {
1868 super::child_opt(self)
1869 }
1870}
1871 1633
1872// Literal 1634// Literal
1873#[derive(Debug, PartialEq, Eq, Hash)] 1635#[derive(Debug, PartialEq, Eq, Hash)]
@@ -1895,130 +1657,7 @@ impl ToOwned for Literal {
1895} 1657}
1896 1658
1897 1659
1898impl Literal { 1660impl Literal {}
1899 pub fn literal_expr(&self) -> Option<&LiteralExpr> {
1900 super::child_opt(self)
1901 }
1902}
1903
1904// LiteralExpr
1905#[derive(Debug, PartialEq, Eq, Hash)]
1906#[repr(transparent)]
1907pub struct LiteralExpr {
1908 pub(crate) syntax: SyntaxNode,
1909}
1910unsafe impl TransparentNewType for LiteralExpr {
1911 type Repr = rowan::SyntaxNode<RaTypes>;
1912}
1913
1914#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1915pub enum LiteralExprKind<'a> {
1916 String(&'a String),
1917 ByteString(&'a ByteString),
1918 RawString(&'a RawString),
1919 RawByteString(&'a RawByteString),
1920 Char(&'a Char),
1921 Byte(&'a Byte),
1922 IntNumber(&'a IntNumber),
1923 FloatNumber(&'a FloatNumber),
1924 TrueKw(&'a TrueKw),
1925 FalseKw(&'a FalseKw),
1926}
1927impl<'a> From<&'a String> for &'a LiteralExpr {
1928 fn from(n: &'a String) -> &'a LiteralExpr {
1929 LiteralExpr::cast(&n.syntax).unwrap()
1930 }
1931}
1932impl<'a> From<&'a ByteString> for &'a LiteralExpr {
1933 fn from(n: &'a ByteString) -> &'a LiteralExpr {
1934 LiteralExpr::cast(&n.syntax).unwrap()
1935 }
1936}
1937impl<'a> From<&'a RawString> for &'a LiteralExpr {
1938 fn from(n: &'a RawString) -> &'a LiteralExpr {
1939 LiteralExpr::cast(&n.syntax).unwrap()
1940 }
1941}
1942impl<'a> From<&'a RawByteString> for &'a LiteralExpr {
1943 fn from(n: &'a RawByteString) -> &'a LiteralExpr {
1944 LiteralExpr::cast(&n.syntax).unwrap()
1945 }
1946}
1947impl<'a> From<&'a Char> for &'a LiteralExpr {
1948 fn from(n: &'a Char) -> &'a LiteralExpr {
1949 LiteralExpr::cast(&n.syntax).unwrap()
1950 }
1951}
1952impl<'a> From<&'a Byte> for &'a LiteralExpr {
1953 fn from(n: &'a Byte) -> &'a LiteralExpr {
1954 LiteralExpr::cast(&n.syntax).unwrap()
1955 }
1956}
1957impl<'a> From<&'a IntNumber> for &'a LiteralExpr {
1958 fn from(n: &'a IntNumber) -> &'a LiteralExpr {
1959 LiteralExpr::cast(&n.syntax).unwrap()
1960 }
1961}
1962impl<'a> From<&'a FloatNumber> for &'a LiteralExpr {
1963 fn from(n: &'a FloatNumber) -> &'a LiteralExpr {
1964 LiteralExpr::cast(&n.syntax).unwrap()
1965 }
1966}
1967impl<'a> From<&'a TrueKw> for &'a LiteralExpr {
1968 fn from(n: &'a TrueKw) -> &'a LiteralExpr {
1969 LiteralExpr::cast(&n.syntax).unwrap()
1970 }
1971}
1972impl<'a> From<&'a FalseKw> for &'a LiteralExpr {
1973 fn from(n: &'a FalseKw) -> &'a LiteralExpr {
1974 LiteralExpr::cast(&n.syntax).unwrap()
1975 }
1976}
1977
1978
1979impl AstNode for LiteralExpr {
1980 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1981 match syntax.kind() {
1982 | STRING
1983 | BYTE_STRING
1984 | RAW_STRING
1985 | RAW_BYTE_STRING
1986 | CHAR
1987 | BYTE
1988 | INT_NUMBER
1989 | FLOAT_NUMBER
1990 | TRUE_KW
1991 | FALSE_KW => Some(LiteralExpr::from_repr(syntax.into_repr())),
1992 _ => None,
1993 }
1994 }
1995 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1996}
1997
1998impl ToOwned for LiteralExpr {
1999 type Owned = TreeArc<LiteralExpr>;
2000 fn to_owned(&self) -> TreeArc<LiteralExpr> { TreeArc::cast(self.syntax.to_owned()) }
2001}
2002
2003impl LiteralExpr {
2004 pub fn kind(&self) -> LiteralExprKind {
2005 match self.syntax.kind() {
2006 STRING => LiteralExprKind::String(String::cast(&self.syntax).unwrap()),
2007 BYTE_STRING => LiteralExprKind::ByteString(ByteString::cast(&self.syntax).unwrap()),
2008 RAW_STRING => LiteralExprKind::RawString(RawString::cast(&self.syntax).unwrap()),
2009 RAW_BYTE_STRING => LiteralExprKind::RawByteString(RawByteString::cast(&self.syntax).unwrap()),
2010 CHAR => LiteralExprKind::Char(Char::cast(&self.syntax).unwrap()),
2011 BYTE => LiteralExprKind::Byte(Byte::cast(&self.syntax).unwrap()),
2012 INT_NUMBER => LiteralExprKind::IntNumber(IntNumber::cast(&self.syntax).unwrap()),
2013 FLOAT_NUMBER => LiteralExprKind::FloatNumber(FloatNumber::cast(&self.syntax).unwrap()),
2014 TRUE_KW => LiteralExprKind::TrueKw(TrueKw::cast(&self.syntax).unwrap()),
2015 FALSE_KW => LiteralExprKind::FalseKw(FalseKw::cast(&self.syntax).unwrap()),
2016 _ => unreachable!(),
2017 }
2018 }
2019}
2020
2021impl LiteralExpr {}
2022 1661
2023// LiteralPat 1662// LiteralPat
2024#[derive(Debug, PartialEq, Eq, Hash)] 1663#[derive(Debug, PartialEq, Eq, Hash)]
@@ -3402,64 +3041,6 @@ impl ToOwned for RangePat {
3402 3041
3403impl RangePat {} 3042impl RangePat {}
3404 3043
3405// RawByteString
3406#[derive(Debug, PartialEq, Eq, Hash)]
3407#[repr(transparent)]
3408pub struct RawByteString {
3409 pub(crate) syntax: SyntaxNode,
3410}
3411unsafe impl TransparentNewType for RawByteString {
3412 type Repr = rowan::SyntaxNode<RaTypes>;
3413}
3414
3415impl AstNode for RawByteString {
3416 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3417 match syntax.kind() {
3418 RAW_BYTE_STRING => Some(RawByteString::from_repr(syntax.into_repr())),
3419 _ => None,
3420 }
3421 }
3422 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3423}
3424
3425impl ToOwned for RawByteString {
3426 type Owned = TreeArc<RawByteString>;
3427 fn to_owned(&self) -> TreeArc<RawByteString> { TreeArc::cast(self.syntax.to_owned()) }
3428}
3429
3430
3431impl ast::AstToken for RawByteString {}
3432impl RawByteString {}
3433
3434// RawString
3435#[derive(Debug, PartialEq, Eq, Hash)]
3436#[repr(transparent)]
3437pub struct RawString {
3438 pub(crate) syntax: SyntaxNode,
3439}
3440unsafe impl TransparentNewType for RawString {
3441 type Repr = rowan::SyntaxNode<RaTypes>;
3442}
3443
3444impl AstNode for RawString {
3445 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3446 match syntax.kind() {
3447 RAW_STRING => Some(RawString::from_repr(syntax.into_repr())),
3448 _ => None,
3449 }
3450 }
3451 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3452}
3453
3454impl ToOwned for RawString {
3455 type Owned = TreeArc<RawString>;
3456 fn to_owned(&self) -> TreeArc<RawString> { TreeArc::cast(self.syntax.to_owned()) }
3457}
3458
3459
3460impl ast::AstToken for RawString {}
3461impl RawString {}
3462
3463// RefExpr 3044// RefExpr
3464#[derive(Debug, PartialEq, Eq, Hash)] 3045#[derive(Debug, PartialEq, Eq, Hash)]
3465#[repr(transparent)] 3046#[repr(transparent)]
@@ -3620,34 +3201,6 @@ impl ReturnExpr {
3620 } 3201 }
3621} 3202}
3622 3203
3623// SelfKw
3624#[derive(Debug, PartialEq, Eq, Hash)]
3625#[repr(transparent)]
3626pub struct SelfKw {
3627 pub(crate) syntax: SyntaxNode,
3628}
3629unsafe impl TransparentNewType for SelfKw {
3630 type Repr = rowan::SyntaxNode<RaTypes>;
3631}
3632
3633impl AstNode for SelfKw {
3634 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3635 match syntax.kind() {
3636 SELF_KW => Some(SelfKw::from_repr(syntax.into_repr())),
3637 _ => None,
3638 }
3639 }
3640 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3641}
3642
3643impl ToOwned for SelfKw {
3644 type Owned = TreeArc<SelfKw>;
3645 fn to_owned(&self) -> TreeArc<SelfKw> { TreeArc::cast(self.syntax.to_owned()) }
3646}
3647
3648
3649impl SelfKw {}
3650
3651// SelfParam 3204// SelfParam
3652#[derive(Debug, PartialEq, Eq, Hash)] 3205#[derive(Debug, PartialEq, Eq, Hash)]
3653#[repr(transparent)] 3206#[repr(transparent)]
@@ -3675,11 +3228,7 @@ impl ToOwned for SelfParam {
3675 3228
3676 3229
3677impl ast::TypeAscriptionOwner for SelfParam {} 3230impl ast::TypeAscriptionOwner for SelfParam {}
3678impl SelfParam { 3231impl SelfParam {}
3679 pub fn self_kw(&self) -> Option<&SelfKw> {
3680 super::child_opt(self)
3681 }
3682}
3683 3232
3684// SlicePat 3233// SlicePat
3685#[derive(Debug, PartialEq, Eq, Hash)] 3234#[derive(Debug, PartialEq, Eq, Hash)]
@@ -3864,35 +3413,6 @@ impl Stmt {
3864 3413
3865impl Stmt {} 3414impl Stmt {}
3866 3415
3867// String
3868#[derive(Debug, PartialEq, Eq, Hash)]
3869#[repr(transparent)]
3870pub struct String {
3871 pub(crate) syntax: SyntaxNode,
3872}
3873unsafe impl TransparentNewType for String {
3874 type Repr = rowan::SyntaxNode<RaTypes>;
3875}
3876
3877impl AstNode for String {
3878 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3879 match syntax.kind() {
3880 STRING => Some(String::from_repr(syntax.into_repr())),
3881 _ => None,
3882 }
3883 }
3884 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3885}
3886
3887impl ToOwned for String {
3888 type Owned = TreeArc<String>;
3889 fn to_owned(&self) -> TreeArc<String> { TreeArc::cast(self.syntax.to_owned()) }
3890}
3891
3892
3893impl ast::AstToken for String {}
3894impl String {}
3895
3896// StructDef 3416// StructDef
3897#[derive(Debug, PartialEq, Eq, Hash)] 3417#[derive(Debug, PartialEq, Eq, Hash)]
3898#[repr(transparent)] 3418#[repr(transparent)]
@@ -4061,41 +3581,13 @@ impl ast::NameOwner for TraitDef {}
4061impl ast::AttrsOwner for TraitDef {} 3581impl ast::AttrsOwner for TraitDef {}
4062impl ast::DocCommentsOwner for TraitDef {} 3582impl ast::DocCommentsOwner for TraitDef {}
4063impl ast::TypeParamsOwner for TraitDef {} 3583impl ast::TypeParamsOwner for TraitDef {}
3584impl ast::TypeBoundsOwner for TraitDef {}
4064impl TraitDef { 3585impl TraitDef {
4065 pub fn item_list(&self) -> Option<&ItemList> { 3586 pub fn item_list(&self) -> Option<&ItemList> {
4066 super::child_opt(self) 3587 super::child_opt(self)
4067 } 3588 }
4068} 3589}
4069 3590
4070// TrueKw
4071#[derive(Debug, PartialEq, Eq, Hash)]
4072#[repr(transparent)]
4073pub struct TrueKw {
4074 pub(crate) syntax: SyntaxNode,
4075}
4076unsafe impl TransparentNewType for TrueKw {
4077 type Repr = rowan::SyntaxNode<RaTypes>;
4078}
4079
4080impl AstNode for TrueKw {
4081 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
4082 match syntax.kind() {
4083 TRUE_KW => Some(TrueKw::from_repr(syntax.into_repr())),
4084 _ => None,
4085 }
4086 }
4087 fn syntax(&self) -> &SyntaxNode { &self.syntax }
4088}
4089
4090impl ToOwned for TrueKw {
4091 type Owned = TreeArc<TrueKw>;
4092 fn to_owned(&self) -> TreeArc<TrueKw> { TreeArc::cast(self.syntax.to_owned()) }
4093}
4094
4095
4096impl ast::AstToken for TrueKw {}
4097impl TrueKw {}
4098
4099// TryExpr 3591// TryExpr
4100#[derive(Debug, PartialEq, Eq, Hash)] 3592#[derive(Debug, PartialEq, Eq, Hash)]
4101#[repr(transparent)] 3593#[repr(transparent)]
@@ -4291,6 +3783,7 @@ impl ast::NameOwner for TypeAliasDef {}
4291impl ast::TypeParamsOwner for TypeAliasDef {} 3783impl ast::TypeParamsOwner for TypeAliasDef {}
4292impl ast::AttrsOwner for TypeAliasDef {} 3784impl ast::AttrsOwner for TypeAliasDef {}
4293impl ast::DocCommentsOwner for TypeAliasDef {} 3785impl ast::DocCommentsOwner for TypeAliasDef {}
3786impl ast::TypeBoundsOwner for TypeAliasDef {}
4294impl TypeAliasDef { 3787impl TypeAliasDef {
4295 pub fn type_ref(&self) -> Option<&TypeRef> { 3788 pub fn type_ref(&self) -> Option<&TypeRef> {
4296 super::child_opt(self) 3789 super::child_opt(self)
@@ -4369,6 +3862,70 @@ impl TypeArgList {
4369 } 3862 }
4370} 3863}
4371 3864
3865// TypeBound
3866#[derive(Debug, PartialEq, Eq, Hash)]
3867#[repr(transparent)]
3868pub struct TypeBound {
3869 pub(crate) syntax: SyntaxNode,
3870}
3871unsafe impl TransparentNewType for TypeBound {
3872 type Repr = rowan::SyntaxNode<RaTypes>;
3873}
3874
3875impl AstNode for TypeBound {
3876 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3877 match syntax.kind() {
3878 TYPE_BOUND => Some(TypeBound::from_repr(syntax.into_repr())),
3879 _ => None,
3880 }
3881 }
3882 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3883}
3884
3885impl ToOwned for TypeBound {
3886 type Owned = TreeArc<TypeBound>;
3887 fn to_owned(&self) -> TreeArc<TypeBound> { TreeArc::cast(self.syntax.to_owned()) }
3888}
3889
3890
3891impl TypeBound {
3892 pub fn type_ref(&self) -> Option<&TypeRef> {
3893 super::child_opt(self)
3894 }
3895}
3896
3897// TypeBoundList
3898#[derive(Debug, PartialEq, Eq, Hash)]
3899#[repr(transparent)]
3900pub struct TypeBoundList {
3901 pub(crate) syntax: SyntaxNode,
3902}
3903unsafe impl TransparentNewType for TypeBoundList {
3904 type Repr = rowan::SyntaxNode<RaTypes>;
3905}
3906
3907impl AstNode for TypeBoundList {
3908 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3909 match syntax.kind() {
3910 TYPE_BOUND_LIST => Some(TypeBoundList::from_repr(syntax.into_repr())),
3911 _ => None,
3912 }
3913 }
3914 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3915}
3916
3917impl ToOwned for TypeBoundList {
3918 type Owned = TreeArc<TypeBoundList>;
3919 fn to_owned(&self) -> TreeArc<TypeBoundList> { TreeArc::cast(self.syntax.to_owned()) }
3920}
3921
3922
3923impl TypeBoundList {
3924 pub fn bounds(&self) -> impl Iterator<Item = &TypeBound> {
3925 super::children(self)
3926 }
3927}
3928
4372// TypeParam 3929// TypeParam
4373#[derive(Debug, PartialEq, Eq, Hash)] 3930#[derive(Debug, PartialEq, Eq, Hash)]
4374#[repr(transparent)] 3931#[repr(transparent)]
@@ -4397,6 +3954,7 @@ impl ToOwned for TypeParam {
4397 3954
4398impl ast::NameOwner for TypeParam {} 3955impl ast::NameOwner for TypeParam {}
4399impl ast::AttrsOwner for TypeParam {} 3956impl ast::AttrsOwner for TypeParam {}
3957impl ast::TypeBoundsOwner for TypeParam {}
4400impl TypeParam {} 3958impl TypeParam {}
4401 3959
4402// TypeParamList 3960// TypeParamList
@@ -4737,7 +4295,44 @@ impl ToOwned for WhereClause {
4737} 4295}
4738 4296
4739 4297
4740impl WhereClause {} 4298impl WhereClause {
4299 pub fn predicates(&self) -> impl Iterator<Item = &WherePred> {
4300 super::children(self)
4301 }
4302}
4303
4304// WherePred
4305#[derive(Debug, PartialEq, Eq, Hash)]
4306#[repr(transparent)]
4307pub struct WherePred {
4308 pub(crate) syntax: SyntaxNode,
4309}
4310unsafe impl TransparentNewType for WherePred {
4311 type Repr = rowan::SyntaxNode<RaTypes>;
4312}
4313
4314impl AstNode for WherePred {
4315 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
4316 match syntax.kind() {
4317 WHERE_PRED => Some(WherePred::from_repr(syntax.into_repr())),
4318 _ => None,
4319 }
4320 }
4321 fn syntax(&self) -> &SyntaxNode { &self.syntax }
4322}
4323
4324impl ToOwned for WherePred {
4325 type Owned = TreeArc<WherePred>;
4326 fn to_owned(&self) -> TreeArc<WherePred> { TreeArc::cast(self.syntax.to_owned()) }
4327}
4328
4329
4330impl ast::TypeBoundsOwner for WherePred {}
4331impl WherePred {
4332 pub fn type_ref(&self) -> Option<&TypeRef> {
4333 super::child_opt(self)
4334 }
4335}
4741 4336
4742// WhileExpr 4337// WhileExpr
4743#[derive(Debug, PartialEq, Eq, Hash)] 4338#[derive(Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index ad6d74162..6d7a5a1cb 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": (
@@ -330,7 +332,8 @@ Grammar(
330 "NameOwner", 332 "NameOwner",
331 "TypeParamsOwner", 333 "TypeParamsOwner",
332 "AttrsOwner", 334 "AttrsOwner",
333 "DocCommentsOwner" 335 "DocCommentsOwner",
336 "TypeBoundsOwner",
334 ], 337 ],
335 options: ["TypeRef"] 338 options: ["TypeRef"]
336 ), 339 ),
@@ -347,8 +350,12 @@ Grammar(
347 "PlaceholderType": (), 350 "PlaceholderType": (),
348 "FnPointerType": (options: ["ParamList", "RetType"]), 351 "FnPointerType": (options: ["ParamList", "RetType"]),
349 "ForType": (options: ["TypeRef"]), 352 "ForType": (options: ["TypeRef"]),
350 "ImplTraitType": (), 353 "ImplTraitType": (
351 "DynTraitType": (), 354 traits: ["TypeBoundsOwner"],
355 ),
356 "DynTraitType": (
357 traits: ["TypeBoundsOwner"],
358 ),
352 359
353 "TypeRef": ( enum: [ 360 "TypeRef": ( enum: [
354 "ParenType", 361 "ParenType",
@@ -456,31 +463,7 @@ Grammar(
456 "RangeExpr": (), 463 "RangeExpr": (),
457 "BinExpr": (), 464 "BinExpr": (),
458 465
459 "IntNumber": ( traits: ["AstToken"] ), 466 "Literal": (),
460 "FloatNumber": ( traits: ["AstToken"] ),
461 "String": ( traits: ["AstToken"] ),
462 "RawString": ( traits: ["AstToken"] ),
463 "Byte": ( traits: ["AstToken"] ),
464 "RawByteString": ( traits: ["AstToken"] ),
465 "ByteString": ( traits: ["AstToken"] ),
466 "Char": ( traits: ["AstToken"] ),
467 "TrueKw": ( traits: ["AstToken"] ),
468 "FalseKw": ( traits: ["AstToken"] ),
469 "LiteralExpr": (
470 enum: [
471 "String",
472 "ByteString",
473 "RawString",
474 "RawByteString",
475 "Char",
476 "Byte",
477 "IntNumber",
478 "FloatNumber",
479 "TrueKw",
480 "FalseKw",
481 ]
482 ),
483 "Literal": (options: ["LiteralExpr"]),
484 467
485 "Expr": ( 468 "Expr": (
486 enum: [ 469 enum: [
@@ -571,13 +554,33 @@ Grammar(
571 ["lifetime_params", "LifetimeParam" ], 554 ["lifetime_params", "LifetimeParam" ],
572 ] 555 ]
573 ), 556 ),
574 "TypeParam": ( traits: ["NameOwner", "AttrsOwner"] ), 557 "TypeParam": ( traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner"] ),
575 "LifetimeParam": ( 558 "LifetimeParam": (
576 options: [ "Lifetime"],
577 traits: ["AttrsOwner"], 559 traits: ["AttrsOwner"],
578 ), 560 ),
579 "Lifetime": ( traits: ["AstToken"] ), 561 "TypeBound": (
580 "WhereClause": (), 562 options: [
563 "TypeRef",
564 ]
565 ),
566 "TypeBoundList": (
567 collections: [
568 ["bounds", "TypeBound"],
569 ]
570 ),
571 "WherePred": (
572 options: [
573 "TypeRef",
574 ],
575 traits: [
576 "TypeBoundsOwner",
577 ],
578 ),
579 "WhereClause": (
580 collections: [
581 ["predicates", "WherePred"],
582 ],
583 ),
581 "ExprStmt": ( 584 "ExprStmt": (
582 options: [ ["expr", "Expr"] ] 585 options: [ ["expr", "Expr"] ]
583 ), 586 ),
@@ -612,12 +615,10 @@ Grammar(
612 ] 615 ]
613 ), 616 ),
614 "SelfParam": ( 617 "SelfParam": (
615 options: ["SelfKw"],
616 traits: [ 618 traits: [
617 "TypeAscriptionOwner", 619 "TypeAscriptionOwner",
618 ] 620 ]
619 ), 621 ),
620 "SelfKw": (),
621 "Param": ( 622 "Param": (
622 options: [ "Pat" ], 623 options: [ "Pat" ],
623 traits: [ 624 traits: [
@@ -661,8 +662,7 @@ Grammar(
661 ]), 662 ]),
662 "TypeArg": (options: ["TypeRef"]), 663 "TypeArg": (options: ["TypeRef"]),
663 "AssocTypeArg": (options: ["NameRef", "TypeRef"]), 664 "AssocTypeArg": (options: ["NameRef", "TypeRef"]),
664 "LifetimeArg": (options: ["Lifetime"]), 665 "LifetimeArg": (),
665 "Comment": ( traits: ["AstToken"] ),
666 "Whitespace": ( traits: ["AstToken"] ), 666 "Whitespace": ( traits: ["AstToken"] ),
667 }, 667 },
668) 668)
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/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs
index e5b4cdb11..be181d0ae 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,172 @@ 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 has_short_text(self.kind()) {
323 write!(fmt, " \"{}\"", self.text())?;
324 }
325 Ok(())
326 }
327}
328
329impl<'a> fmt::Display for SyntaxToken<'a> {
330 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
331 fmt::Display::fmt(self.text(), fmt)
332 }
333}
334
335impl<'a> From<rowan::SyntaxToken<'a, RaTypes>> for SyntaxToken<'a> {
336 fn from(t: rowan::SyntaxToken<'a, RaTypes>) -> Self {
337 SyntaxToken(t)
338 }
339}
340
341impl<'a> SyntaxToken<'a> {
342 pub fn kind(&self) -> SyntaxKind {
343 self.0.kind()
344 }
345
346 pub fn text(&self) -> &'a SmolStr {
347 self.0.text()
348 }
349
350 pub fn range(&self) -> TextRange {
351 self.0.range()
352 }
353
354 pub fn parent(&self) -> &'a SyntaxNode {
355 SyntaxNode::from_repr(self.0.parent())
356 }
357
358 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
359 self.0.next_sibling_or_token().map(SyntaxElement::from)
360 }
361
362 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
363 self.0.prev_sibling_or_token().map(SyntaxElement::from)
364 }
365
366 pub fn siblings_with_tokens(
367 &self,
368 direction: Direction,
369 ) -> impl Iterator<Item = SyntaxElement<'a>> {
370 let me: SyntaxElement = (*self).into();
371 crate::algo::generate(Some(me), move |el| match direction {
372 Direction::Next => el.next_sibling_or_token(),
373 Direction::Prev => el.prev_sibling_or_token(),
374 })
375 }
376
377 pub fn next_token(&self) -> Option<SyntaxToken<'a>> {
378 self.0.next_token().map(SyntaxToken::from)
379 }
380
381 pub fn prev_token(&self) -> Option<SyntaxToken<'a>> {
382 self.0.prev_token().map(SyntaxToken::from)
383 }
384
385 pub(crate) fn replace_with(&self, new_token: GreenToken) -> GreenNode {
386 self.0.replace_with(new_token)
387 }
388}
389
390#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
391pub enum SyntaxElement<'a> {
392 Node(&'a SyntaxNode),
393 Token(SyntaxToken<'a>),
394}
395
396impl<'a> fmt::Display for SyntaxElement<'a> {
397 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
398 match self {
399 SyntaxElement::Node(it) => fmt::Display::fmt(it, fmt),
400 SyntaxElement::Token(it) => fmt::Display::fmt(it, fmt),
401 }
402 }
403}
404
405impl<'a> SyntaxElement<'a> {
406 pub fn kind(&self) -> SyntaxKind {
407 match self {
408 SyntaxElement::Node(it) => it.kind(),
409 SyntaxElement::Token(it) => it.kind(),
410 }
411 }
412
413 pub fn as_node(&self) -> Option<&'a SyntaxNode> {
414 match self {
415 SyntaxElement::Node(node) => Some(*node),
416 SyntaxElement::Token(_) => None,
417 }
418 }
419
420 pub fn as_token(&self) -> Option<SyntaxToken<'a>> {
421 match self {
422 SyntaxElement::Node(_) => None,
423 SyntaxElement::Token(token) => Some(*token),
424 }
425 }
426
427 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
428 match self {
429 SyntaxElement::Node(it) => it.next_sibling_or_token(),
430 SyntaxElement::Token(it) => it.next_sibling_or_token(),
431 }
432 }
433
434 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
435 match self {
436 SyntaxElement::Node(it) => it.prev_sibling_or_token(),
437 SyntaxElement::Token(it) => it.prev_sibling_or_token(),
438 }
439 }
440
441 pub fn ancestors(&self) -> impl Iterator<Item = &'a SyntaxNode> {
442 match self {
443 SyntaxElement::Node(it) => it,
444 SyntaxElement::Token(it) => it.parent(),
445 }
446 .ancestors()
447 }
448}
449
450impl<'a> From<rowan::SyntaxElement<'a, RaTypes>> for SyntaxElement<'a> {
451 fn from(el: rowan::SyntaxElement<'a, RaTypes>) -> Self {
452 match el {
453 rowan::SyntaxElement::Node(n) => SyntaxElement::Node(SyntaxNode::from_repr(n)),
454 rowan::SyntaxElement::Token(t) => SyntaxElement::Token(t.into()),
455 }
456 }
457}
458
459impl<'a> From<&'a SyntaxNode> for SyntaxElement<'a> {
460 fn from(node: &'a SyntaxNode) -> SyntaxElement<'a> {
461 SyntaxElement::Node(node)
462 }
463}
464
465impl<'a> From<SyntaxToken<'a>> for SyntaxElement<'a> {
466 fn from(token: SyntaxToken<'a>) -> SyntaxElement<'a> {
467 SyntaxElement::Token(token)
468 }
469}
470
471impl<'a> SyntaxElement<'a> {
472 pub fn range(&self) -> TextRange {
473 match self {
474 SyntaxElement::Node(it) => it.range(),
475 SyntaxElement::Token(it) => it.range(),
476 }
259 } 477 }
260} 478}
261 479
@@ -270,6 +488,17 @@ impl<'a> Iterator for SyntaxNodeChildren<'a> {
270 } 488 }
271} 489}
272 490
491#[derive(Debug)]
492pub struct SyntaxElementChildren<'a>(rowan::SyntaxElementChildren<'a, RaTypes>);
493
494impl<'a> Iterator for SyntaxElementChildren<'a> {
495 type Item = SyntaxElement<'a>;
496
497 fn next(&mut self) -> Option<SyntaxElement<'a>> {
498 self.0.next().map(SyntaxElement::from)
499 }
500}
501
273fn has_short_text(kind: SyntaxKind) -> bool { 502fn has_short_text(kind: SyntaxKind) -> bool {
274 use crate::SyntaxKind::*; 503 use crate::SyntaxKind::*;
275 match kind { 504 match kind {
@@ -304,16 +533,16 @@ impl SyntaxTreeBuilder {
304 node 533 node
305 } 534 }
306 535
307 pub fn leaf(&mut self, kind: SyntaxKind, text: SmolStr) { 536 pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) {
308 self.inner.leaf(kind, text) 537 self.inner.token(kind, text)
309 } 538 }
310 539
311 pub fn start_branch(&mut self, kind: SyntaxKind) { 540 pub fn start_node(&mut self, kind: SyntaxKind) {
312 self.inner.start_internal(kind) 541 self.inner.start_node(kind)
313 } 542 }
314 543
315 pub fn finish_branch(&mut self) { 544 pub fn finish_node(&mut self) {
316 self.inner.finish_internal() 545 self.inner.finish_node()
317 } 546 }
318 547
319 pub fn error(&mut self, error: ParseError, text_pos: TextUnit) { 548 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..290f80fc6 100644
--- a/crates/ra_syntax/src/validation/byte.rs
+++ b/crates/ra_syntax/src/validation/byte.rs
@@ -1,17 +1,17 @@
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_byte_literal(literal_text);
16 let mut len = 0; 16 let mut len = 0;
17 for component in &mut components { 17 for component in &mut components {
diff --git a/crates/ra_syntax/src/validation/byte_string.rs b/crates/ra_syntax/src/validation/byte_string.rs
index 64c7054a1..eae395e9d 100644
--- a/crates/ra_syntax/src/validation/byte_string.rs
+++ b/crates/ra_syntax/src/validation/byte_string.rs
@@ -1,15 +1,15 @@
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_byte_string_literal(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();
diff --git a/crates/ra_syntax/src/validation/char.rs b/crates/ra_syntax/src/validation/char.rs
index c874e5d08..a385accdd 100644
--- a/crates/ra_syntax/src/validation/char.rs
+++ b/crates/ra_syntax/src/validation/char.rs
@@ -5,16 +5,16 @@ 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_char_literal(literal_text);
19 let mut len = 0; 19 let mut len = 0;
20 for component in &mut components { 20 for component in &mut components {
diff --git a/crates/ra_syntax/src/validation/string.rs b/crates/ra_syntax/src/validation/string.rs
index d857d088c..f7f5c02c0 100644
--- a/crates/ra_syntax/src/validation/string.rs
+++ b/crates/ra_syntax/src/validation/string.rs
@@ -1,15 +1,15 @@
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_string_literal(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();
diff --git a/crates/ra_syntax/tests/data/parser/err/0024_many_type_parens.txt b/crates/ra_syntax/tests/data/parser/err/0024_many_type_parens.txt
index 8720fc6ea..45fa70593 100644
--- a/crates/ra_syntax/tests/data/parser/err/0024_many_type_parens.txt
+++ b/crates/ra_syntax/tests/data/parser/err/0024_many_type_parens.txt
@@ -11,47 +11,51 @@ SOURCE_FILE@[0; 240)
11 IDENT@[5; 6) "T" 11 IDENT@[5; 6) "T"
12 COLON@[6; 7) 12 COLON@[6; 7)
13 WHITESPACE@[7; 8) 13 WHITESPACE@[7; 8)
14 L_PAREN@[8; 9) 14 TYPE_BOUND_LIST@[8; 47)
15 PATH_TYPE@[9; 13) 15 TYPE_BOUND@[8; 14)
16 PATH@[9; 13) 16 L_PAREN@[8; 9)
17 PATH_SEGMENT@[9; 13) 17 PATH_TYPE@[9; 13)
18 NAME_REF@[9; 13) 18 PATH@[9; 13)
19 IDENT@[9; 13) "Copy" 19 PATH_SEGMENT@[9; 13)
20 R_PAREN@[13; 14) 20 NAME_REF@[9; 13)
21 WHITESPACE@[14; 15) 21 IDENT@[9; 13) "Copy"
22 PLUS@[15; 16) 22 R_PAREN@[13; 14)
23 WHITESPACE@[16; 17) 23 WHITESPACE@[14; 15)
24 L_PAREN@[17; 18) 24 PLUS@[15; 16)
25 QUESTION@[18; 19) 25 WHITESPACE@[16; 17)
26 PATH_TYPE@[19; 24) 26 TYPE_BOUND@[17; 25)
27 PATH@[19; 24) 27 L_PAREN@[17; 18)
28 PATH_SEGMENT@[19; 24) 28 QUESTION@[18; 19)
29 NAME_REF@[19; 24) 29 PATH_TYPE@[19; 24)
30 IDENT@[19; 24) "Sized" 30 PATH@[19; 24)
31 R_PAREN@[24; 25) 31 PATH_SEGMENT@[19; 24)
32 WHITESPACE@[25; 26) 32 NAME_REF@[19; 24)
33 PLUS@[26; 27) 33 IDENT@[19; 24) "Sized"
34 WHITESPACE@[27; 28) 34 R_PAREN@[24; 25)
35 L_PAREN@[28; 29) 35 WHITESPACE@[25; 26)
36 FOR_TYPE@[29; 46) 36 PLUS@[26; 27)
37 FOR_KW@[29; 32) 37 WHITESPACE@[27; 28)
38 TYPE_PARAM_LIST@[32; 36) 38 TYPE_BOUND@[28; 47)
39 L_ANGLE@[32; 33) 39 L_PAREN@[28; 29)
40 LIFETIME_PARAM@[33; 35) 40 FOR_TYPE@[29; 46)
41 LIFETIME@[33; 35) "'a" 41 FOR_KW@[29; 32)
42 R_ANGLE@[35; 36) 42 TYPE_PARAM_LIST@[32; 36)
43 WHITESPACE@[36; 37) 43 L_ANGLE@[32; 33)
44 PATH_TYPE@[37; 46) 44 LIFETIME_PARAM@[33; 35)
45 PATH@[37; 46) 45 LIFETIME@[33; 35) "'a"
46 PATH_SEGMENT@[37; 46) 46 R_ANGLE@[35; 36)
47 NAME_REF@[37; 42) 47 WHITESPACE@[36; 37)
48 IDENT@[37; 42) "Trait" 48 PATH_TYPE@[37; 46)
49 TYPE_ARG_LIST@[42; 46) 49 PATH@[37; 46)
50 L_ANGLE@[42; 43) 50 PATH_SEGMENT@[37; 46)
51 LIFETIME_ARG@[43; 45) 51 NAME_REF@[37; 42)
52 LIFETIME@[43; 45) "'a" 52 IDENT@[37; 42) "Trait"
53 R_ANGLE@[45; 46) 53 TYPE_ARG_LIST@[42; 46)
54 R_PAREN@[46; 47) 54 L_ANGLE@[42; 43)
55 LIFETIME_ARG@[43; 45)
56 LIFETIME@[43; 45) "'a"
57 R_ANGLE@[45; 46)
58 R_PAREN@[46; 47)
55 R_ANGLE@[47; 48) 59 R_ANGLE@[47; 48)
56 PARAM_LIST@[48; 50) 60 PARAM_LIST@[48; 50)
57 L_PAREN@[48; 49) 61 L_PAREN@[48; 49)
@@ -80,60 +84,65 @@ SOURCE_FILE@[0; 240)
80 UNDERSCORE@[75; 76) 84 UNDERSCORE@[75; 76)
81 COLON@[76; 77) 85 COLON@[76; 77)
82 WHITESPACE@[77; 78) 86 WHITESPACE@[77; 78)
83 PATH_TYPE@[78; 121) 87 DYN_TRAIT_TYPE@[78; 121)
84 PATH@[78; 88) 88 TYPE_BOUND_LIST@[78; 121)
85 PATH_SEGMENT@[78; 88) 89 TYPE_BOUND@[78; 88)
86 NAME_REF@[78; 81) 90 PATH_TYPE@[78; 88)
87 IDENT@[78; 81) "Box" 91 PATH@[78; 88)
88 TYPE_ARG_LIST@[81; 88) 92 PATH_SEGMENT@[78; 88)
89 L_ANGLE@[81; 82) 93 NAME_REF@[78; 81)
90 TYPE_ARG@[82; 88) 94 IDENT@[78; 81) "Box"
91 PAREN_TYPE@[82; 88) 95 TYPE_ARG_LIST@[81; 88)
92 L_PAREN@[82; 83) 96 L_ANGLE@[81; 82)
93 PATH_TYPE@[83; 87) 97 TYPE_ARG@[82; 88)
94 PATH@[83; 87) 98 PAREN_TYPE@[82; 88)
95 PATH_SEGMENT@[83; 87) 99 L_PAREN@[82; 83)
96 NAME_REF@[83; 87) 100 PATH_TYPE@[83; 87)
97 IDENT@[83; 87) "Copy" 101 PATH@[83; 87)
98 R_PAREN@[87; 88) 102 PATH_SEGMENT@[83; 87)
99 err: `expected COMMA` 103 NAME_REF@[83; 87)
100 err: `expected R_ANGLE` 104 IDENT@[83; 87) "Copy"
101 WHITESPACE@[88; 89) 105 R_PAREN@[87; 88)
102 PLUS@[89; 90) 106 err: `expected COMMA`
103 WHITESPACE@[90; 91) 107 err: `expected R_ANGLE`
104 L_PAREN@[91; 92) 108 WHITESPACE@[88; 89)
105 QUESTION@[92; 93) 109 PLUS@[89; 90)
106 PATH_TYPE@[93; 98) 110 WHITESPACE@[90; 91)
107 PATH@[93; 98) 111 TYPE_BOUND@[91; 99)
108 PATH_SEGMENT@[93; 98) 112 L_PAREN@[91; 92)
109 NAME_REF@[93; 98) 113 QUESTION@[92; 93)
110 IDENT@[93; 98) "Sized" 114 PATH_TYPE@[93; 98)
111 R_PAREN@[98; 99) 115 PATH@[93; 98)
112 WHITESPACE@[99; 100) 116 PATH_SEGMENT@[93; 98)
113 PLUS@[100; 101) 117 NAME_REF@[93; 98)
114 WHITESPACE@[101; 102) 118 IDENT@[93; 98) "Sized"
115 L_PAREN@[102; 103) 119 R_PAREN@[98; 99)
116 FOR_TYPE@[103; 120) 120 WHITESPACE@[99; 100)
117 FOR_KW@[103; 106) 121 PLUS@[100; 101)
118 TYPE_PARAM_LIST@[106; 110) 122 WHITESPACE@[101; 102)
119 L_ANGLE@[106; 107) 123 TYPE_BOUND@[102; 121)
120 LIFETIME_PARAM@[107; 109) 124 L_PAREN@[102; 103)
121 LIFETIME@[107; 109) "'a" 125 FOR_TYPE@[103; 120)
122 R_ANGLE@[109; 110) 126 FOR_KW@[103; 106)
123 WHITESPACE@[110; 111) 127 TYPE_PARAM_LIST@[106; 110)
124 PATH_TYPE@[111; 120) 128 L_ANGLE@[106; 107)
125 PATH@[111; 120) 129 LIFETIME_PARAM@[107; 109)
126 PATH_SEGMENT@[111; 120) 130 LIFETIME@[107; 109) "'a"
127 NAME_REF@[111; 116) 131 R_ANGLE@[109; 110)
128 IDENT@[111; 116) "Trait" 132 WHITESPACE@[110; 111)
129 TYPE_ARG_LIST@[116; 120) 133 PATH_TYPE@[111; 120)
130 L_ANGLE@[116; 117) 134 PATH@[111; 120)
131 LIFETIME_ARG@[117; 119) 135 PATH_SEGMENT@[111; 120)
132 LIFETIME@[117; 119) "'a" 136 NAME_REF@[111; 116)
133 R_ANGLE@[119; 120) 137 IDENT@[111; 116) "Trait"
134 R_PAREN@[120; 121) 138 TYPE_ARG_LIST@[116; 120)
135 err: `expected SEMI` 139 L_ANGLE@[116; 117)
136 err: `expected expression` 140 LIFETIME_ARG@[117; 119)
141 LIFETIME@[117; 119) "'a"
142 R_ANGLE@[119; 120)
143 R_PAREN@[120; 121)
144 err: `expected SEMI`
145 err: `expected expression`
137 EXPR_STMT@[121; 123) 146 EXPR_STMT@[121; 123)
138 ERROR@[121; 122) 147 ERROR@[121; 122)
139 R_ANGLE@[121; 122) 148 R_ANGLE@[121; 122)
@@ -247,60 +256,65 @@ SOURCE_FILE@[0; 240)
247 UNDERSCORE@[189; 190) 256 UNDERSCORE@[189; 190)
248 COLON@[190; 191) 257 COLON@[190; 191)
249 WHITESPACE@[191; 192) 258 WHITESPACE@[191; 192)
250 PATH_TYPE@[192; 235) 259 DYN_TRAIT_TYPE@[192; 235)
251 PATH@[192; 215) 260 TYPE_BOUND_LIST@[192; 235)
252 PATH_SEGMENT@[192; 215) 261 TYPE_BOUND@[192; 215)
253 NAME_REF@[192; 195) 262 PATH_TYPE@[192; 215)
254 IDENT@[192; 195) "Box" 263 PATH@[192; 215)
255 TYPE_ARG_LIST@[195; 215) 264 PATH_SEGMENT@[192; 215)
256 L_ANGLE@[195; 196) 265 NAME_REF@[192; 195)
257 TYPE_ARG@[196; 215) 266 IDENT@[192; 195) "Box"
258 PAREN_TYPE@[196; 215) 267 TYPE_ARG_LIST@[195; 215)
259 L_PAREN@[196; 197) 268 L_ANGLE@[195; 196)
260 FOR_TYPE@[197; 214) 269 TYPE_ARG@[196; 215)
261 FOR_KW@[197; 200) 270 PAREN_TYPE@[196; 215)
262 TYPE_PARAM_LIST@[200; 204) 271 L_PAREN@[196; 197)
263 L_ANGLE@[200; 201) 272 FOR_TYPE@[197; 214)
264 LIFETIME_PARAM@[201; 203) 273 FOR_KW@[197; 200)
265 LIFETIME@[201; 203) "'a" 274 TYPE_PARAM_LIST@[200; 204)
266 R_ANGLE@[203; 204) 275 L_ANGLE@[200; 201)
267 WHITESPACE@[204; 205) 276 LIFETIME_PARAM@[201; 203)
268 PATH_TYPE@[205; 214) 277 LIFETIME@[201; 203) "'a"
269 PATH@[205; 214) 278 R_ANGLE@[203; 204)
270 PATH_SEGMENT@[205; 214) 279 WHITESPACE@[204; 205)
271 NAME_REF@[205; 210) 280 PATH_TYPE@[205; 214)
272 IDENT@[205; 210) "Trait" 281 PATH@[205; 214)
273 TYPE_ARG_LIST@[210; 214) 282 PATH_SEGMENT@[205; 214)
274 L_ANGLE@[210; 211) 283 NAME_REF@[205; 210)
275 LIFETIME_ARG@[211; 213) 284 IDENT@[205; 210) "Trait"
276 LIFETIME@[211; 213) "'a" 285 TYPE_ARG_LIST@[210; 214)
277 R_ANGLE@[213; 214) 286 L_ANGLE@[210; 211)
278 R_PAREN@[214; 215) 287 LIFETIME_ARG@[211; 213)
279 err: `expected COMMA` 288 LIFETIME@[211; 213) "'a"
280 err: `expected R_ANGLE` 289 R_ANGLE@[213; 214)
281 WHITESPACE@[215; 216) 290 R_PAREN@[214; 215)
282 PLUS@[216; 217) 291 err: `expected COMMA`
283 WHITESPACE@[217; 218) 292 err: `expected R_ANGLE`
284 L_PAREN@[218; 219) 293 WHITESPACE@[215; 216)
285 PATH_TYPE@[219; 223) 294 PLUS@[216; 217)
286 PATH@[219; 223) 295 WHITESPACE@[217; 218)
287 PATH_SEGMENT@[219; 223) 296 TYPE_BOUND@[218; 224)
288 NAME_REF@[219; 223) 297 L_PAREN@[218; 219)
289 IDENT@[219; 223) "Copy" 298 PATH_TYPE@[219; 223)
290 R_PAREN@[223; 224) 299 PATH@[219; 223)
291 WHITESPACE@[224; 225) 300 PATH_SEGMENT@[219; 223)
292 PLUS@[225; 226) 301 NAME_REF@[219; 223)
293 WHITESPACE@[226; 227) 302 IDENT@[219; 223) "Copy"
294 L_PAREN@[227; 228) 303 R_PAREN@[223; 224)
295 QUESTION@[228; 229) 304 WHITESPACE@[224; 225)
296 PATH_TYPE@[229; 234) 305 PLUS@[225; 226)
297 PATH@[229; 234) 306 WHITESPACE@[226; 227)
298 PATH_SEGMENT@[229; 234) 307 TYPE_BOUND@[227; 235)
299 NAME_REF@[229; 234) 308 L_PAREN@[227; 228)
300 IDENT@[229; 234) "Sized" 309 QUESTION@[228; 229)
301 R_PAREN@[234; 235) 310 PATH_TYPE@[229; 234)
302 err: `expected SEMI` 311 PATH@[229; 234)
303 err: `expected expression` 312 PATH_SEGMENT@[229; 234)
313 NAME_REF@[229; 234)
314 IDENT@[229; 234) "Sized"
315 R_PAREN@[234; 235)
316 err: `expected SEMI`
317 err: `expected expression`
304 EXPR_STMT@[235; 237) 318 EXPR_STMT@[235; 237)
305 ERROR@[235; 236) 319 ERROR@[235; 236)
306 R_ANGLE@[235; 236) 320 R_ANGLE@[235; 236)
diff --git a/crates/ra_syntax/tests/data/parser/err/0026_imp_recovery.txt b/crates/ra_syntax/tests/data/parser/err/0026_imp_recovery.txt
index 9b5fadcf7..a6d1a59ef 100644
--- a/crates/ra_syntax/tests/data/parser/err/0026_imp_recovery.txt
+++ b/crates/ra_syntax/tests/data/parser/err/0026_imp_recovery.txt
@@ -8,11 +8,13 @@ SOURCE_FILE@[0; 38)
8 IDENT@[5; 6) "T" 8 IDENT@[5; 6) "T"
9 COLON@[6; 7) 9 COLON@[6; 7)
10 WHITESPACE@[7; 8) 10 WHITESPACE@[7; 8)
11 PATH_TYPE@[8; 13) 11 TYPE_BOUND_LIST@[8; 13)
12 PATH@[8; 13) 12 TYPE_BOUND@[8; 13)
13 PATH_SEGMENT@[8; 13) 13 PATH_TYPE@[8; 13)
14 NAME_REF@[8; 13) 14 PATH@[8; 13)
15 IDENT@[8; 13) "Clone" 15 PATH_SEGMENT@[8; 13)
16 NAME_REF@[8; 13)
17 IDENT@[8; 13) "Clone"
16 R_ANGLE@[13; 14) 18 R_ANGLE@[13; 14)
17 err: `expected trait or type` 19 err: `expected trait or type`
18 err: `expected `{`` 20 err: `expected `{``
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt
index 7c9e1e621..39cadffbc 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt
@@ -18,11 +18,13 @@ SOURCE_FILE@[0; 83)
18 IDENT@[18; 19) "A" 18 IDENT@[18; 19) "A"
19 COLON@[19; 20) 19 COLON@[19; 20)
20 WHITESPACE@[20; 21) 20 WHITESPACE@[20; 21)
21 PATH_TYPE@[21; 26) 21 TYPE_BOUND_LIST@[21; 26)
22 PATH@[21; 26) 22 TYPE_BOUND@[21; 26)
23 PATH_SEGMENT@[21; 26) 23 PATH_TYPE@[21; 26)
24 NAME_REF@[21; 26) 24 PATH@[21; 26)
25 IDENT@[21; 26) "Clone" 25 PATH_SEGMENT@[21; 26)
26 NAME_REF@[21; 26)
27 IDENT@[21; 26) "Clone"
26 SEMI@[26; 27) 28 SEMI@[26; 27)
27 WHITESPACE@[27; 32) 29 WHITESPACE@[27; 32)
28 CONST_DEF@[32; 45) 30 CONST_DEF@[32; 45)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt
index 41420ea92..8bc29564e 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt
@@ -33,24 +33,26 @@ SOURCE_FILE@[0; 49)
33 IDENT@[30; 31) "F" 33 IDENT@[30; 31) "F"
34 COLON@[31; 32) 34 COLON@[31; 32)
35 WHITESPACE@[32; 33) 35 WHITESPACE@[32; 33)
36 PATH_TYPE@[33; 44) 36 TYPE_BOUND_LIST@[33; 44)
37 PATH@[33; 44) 37 TYPE_BOUND@[33; 44)
38 PATH_SEGMENT@[33; 44) 38 PATH_TYPE@[33; 44)
39 NAME_REF@[33; 35) 39 PATH@[33; 44)
40 IDENT@[33; 35) "Fn" 40 PATH_SEGMENT@[33; 44)
41 PARAM_LIST@[35; 44) 41 NAME_REF@[33; 35)
42 L_PAREN@[35; 36) 42 IDENT@[33; 35) "Fn"
43 PARAM@[36; 43) 43 PARAM_LIST@[35; 44)
44 REFERENCE_TYPE@[36; 43) 44 L_PAREN@[35; 36)
45 AMP@[36; 37) 45 PARAM@[36; 43)
46 LIFETIME@[37; 39) "'a" 46 REFERENCE_TYPE@[36; 43)
47 WHITESPACE@[39; 40) 47 AMP@[36; 37)
48 PATH_TYPE@[40; 43) 48 LIFETIME@[37; 39) "'a"
49 PATH@[40; 43) 49 WHITESPACE@[39; 40)
50 PATH_SEGMENT@[40; 43) 50 PATH_TYPE@[40; 43)
51 NAME_REF@[40; 43) 51 PATH@[40; 43)
52 IDENT@[40; 43) "str" 52 PATH_SEGMENT@[40; 43)
53 R_PAREN@[43; 44) 53 NAME_REF@[40; 43)
54 IDENT@[40; 43) "str"
55 R_PAREN@[43; 44)
54 WHITESPACE@[44; 45) 56 WHITESPACE@[44; 45)
55 BLOCK@[45; 48) 57 BLOCK@[45; 48)
56 L_CURLY@[45; 46) 58 L_CURLY@[45; 46)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.txt
index b20f13267..0cbe7c56c 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.txt
@@ -11,19 +11,22 @@ SOURCE_FILE@[0; 28)
11 IDENT@[7; 8) "T" 11 IDENT@[7; 8) "T"
12 COLON@[8; 9) 12 COLON@[8; 9)
13 WHITESPACE@[9; 10) 13 WHITESPACE@[9; 10)
14 PATH_TYPE@[10; 22) 14 TYPE_BOUND_LIST@[10; 22)
15 PATH@[10; 15) 15 TYPE_BOUND@[10; 15)
16 PATH_SEGMENT@[10; 15) 16 PATH_TYPE@[10; 15)
17 NAME_REF@[10; 15) 17 PATH@[10; 15)
18 IDENT@[10; 15) "Clone" 18 PATH_SEGMENT@[10; 15)
19 NAME_REF@[10; 15)
20 IDENT@[10; 15) "Clone"
19 WHITESPACE@[15; 16) 21 WHITESPACE@[15; 16)
20 PLUS@[16; 17) 22 PLUS@[16; 17)
21 WHITESPACE@[17; 18) 23 WHITESPACE@[17; 18)
22 PATH_TYPE@[18; 22) 24 TYPE_BOUND@[18; 22)
23 PATH@[18; 22) 25 PATH_TYPE@[18; 22)
24 PATH_SEGMENT@[18; 22) 26 PATH@[18; 22)
25 NAME_REF@[18; 22) 27 PATH_SEGMENT@[18; 22)
26 IDENT@[18; 22) "Copy" 28 NAME_REF@[18; 22)
29 IDENT@[18; 22) "Copy"
27 R_ANGLE@[22; 23) 30 R_ANGLE@[22; 23)
28 PARAM_LIST@[23; 25) 31 PARAM_LIST@[23; 25)
29 L_PAREN@[23; 24) 32 L_PAREN@[23; 24)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.txt
index 745cf8798..81479d2ea 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.txt
@@ -11,26 +11,30 @@ SOURCE_FILE@[0; 35)
11 IDENT@[9; 10) "T" 11 IDENT@[9; 10) "T"
12 COLON@[10; 11) 12 COLON@[10; 11)
13 WHITESPACE@[11; 12) 13 WHITESPACE@[11; 12)
14 LIFETIME@[12; 14) "'a" 14 TYPE_BOUND_LIST@[12; 32)
15 WHITESPACE@[14; 15) 15 TYPE_BOUND@[12; 14)
16 PLUS@[15; 16) 16 LIFETIME@[12; 14) "'a"
17 WHITESPACE@[16; 17) 17 WHITESPACE@[14; 15)
18 QUESTION@[17; 18) 18 PLUS@[15; 16)
19 PATH_TYPE@[18; 32) 19 WHITESPACE@[16; 17)
20 PATH@[18; 23) 20 TYPE_BOUND@[17; 23)
21 PATH_SEGMENT@[18; 23) 21 QUESTION@[17; 18)
22 NAME_REF@[18; 23) 22 PATH_TYPE@[18; 23)
23 IDENT@[18; 23) "Sized" 23 PATH@[18; 23)
24 PATH_SEGMENT@[18; 23)
25 NAME_REF@[18; 23)
26 IDENT@[18; 23) "Sized"
24 WHITESPACE@[23; 24) 27 WHITESPACE@[23; 24)
25 PLUS@[24; 25) 28 PLUS@[24; 25)
26 WHITESPACE@[25; 26) 29 WHITESPACE@[25; 26)
27 L_PAREN@[26; 27) 30 TYPE_BOUND@[26; 32)
28 PATH_TYPE@[27; 31) 31 L_PAREN@[26; 27)
29 PATH@[27; 31) 32 PATH_TYPE@[27; 31)
30 PATH_SEGMENT@[27; 31) 33 PATH@[27; 31)
31 NAME_REF@[27; 31) 34 PATH_SEGMENT@[27; 31)
32 IDENT@[27; 31) "Copy" 35 NAME_REF@[27; 31)
33 R_PAREN@[31; 32) 36 IDENT@[27; 31) "Copy"
37 R_PAREN@[31; 32)
34 R_ANGLE@[32; 33) 38 R_ANGLE@[32; 33)
35 SEMI@[33; 34) 39 SEMI@[33; 34)
36 WHITESPACE@[34; 35) 40 WHITESPACE@[34; 35)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.txt
index 9a5f46bab..c99a03155 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.txt
@@ -16,11 +16,13 @@ SOURCE_FILE@[0; 31)
16 IDENT@[15; 18) "Foo" 16 IDENT@[15; 18) "Foo"
17 COLON@[18; 19) 17 COLON@[18; 19)
18 WHITESPACE@[19; 20) 18 WHITESPACE@[19; 20)
19 PATH_TYPE@[20; 24) 19 TYPE_BOUND_LIST@[20; 24)
20 PATH@[20; 24) 20 TYPE_BOUND@[20; 24)
21 PATH_SEGMENT@[20; 24) 21 PATH_TYPE@[20; 24)
22 NAME_REF@[20; 24) 22 PATH@[20; 24)
23 IDENT@[20; 24) "Copy" 23 PATH_SEGMENT@[20; 24)
24 NAME_REF@[20; 24)
25 IDENT@[20; 24) "Copy"
24 WHITESPACE@[24; 25) 26 WHITESPACE@[24; 25)
25 EQ@[25; 26) 27 EQ@[25; 26)
26 WHITESPACE@[26; 27) 28 WHITESPACE@[26; 27)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.txt
index 3b676fb4c..31dbbe96c 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.txt
@@ -10,31 +10,34 @@ SOURCE_FILE@[0; 43)
10 IMPL_TRAIT_TYPE@[9; 41) 10 IMPL_TRAIT_TYPE@[9; 41)
11 IMPL_KW@[9; 13) 11 IMPL_KW@[9; 13)
12 WHITESPACE@[13; 14) 12 WHITESPACE@[13; 14)
13 PATH_TYPE@[14; 41) 13 TYPE_BOUND_LIST@[14; 41)
14 PATH@[14; 36) 14 TYPE_BOUND@[14; 36)
15 PATH_SEGMENT@[14; 36) 15 PATH_TYPE@[14; 36)
16 NAME_REF@[14; 22) 16 PATH@[14; 36)
17 IDENT@[14; 22) "Iterator" 17 PATH_SEGMENT@[14; 36)
18 TYPE_ARG_LIST@[22; 36) 18 NAME_REF@[14; 22)
19 L_ANGLE@[22; 23) 19 IDENT@[14; 22) "Iterator"
20 ASSOC_TYPE_ARG@[23; 35) 20 TYPE_ARG_LIST@[22; 36)
21 NAME_REF@[23; 27) 21 L_ANGLE@[22; 23)
22 IDENT@[23; 27) "Item" 22 ASSOC_TYPE_ARG@[23; 35)
23 EQ@[27; 28) 23 NAME_REF@[23; 27)
24 PATH_TYPE@[28; 35) 24 IDENT@[23; 27) "Item"
25 PATH@[28; 35) 25 EQ@[27; 28)
26 PATH_SEGMENT@[28; 35) 26 PATH_TYPE@[28; 35)
27 NAME_REF@[28; 31) 27 PATH@[28; 35)
28 IDENT@[28; 31) "Foo" 28 PATH_SEGMENT@[28; 35)
29 TYPE_ARG_LIST@[31; 35) 29 NAME_REF@[28; 31)
30 L_ANGLE@[31; 32) 30 IDENT@[28; 31) "Foo"
31 LIFETIME_ARG@[32; 34) 31 TYPE_ARG_LIST@[31; 35)
32 LIFETIME@[32; 34) "'a" 32 L_ANGLE@[31; 32)
33 R_ANGLE@[34; 35) 33 LIFETIME_ARG@[32; 34)
34 R_ANGLE@[35; 36) 34 LIFETIME@[32; 34) "'a"
35 R_ANGLE@[34; 35)
36 R_ANGLE@[35; 36)
35 WHITESPACE@[36; 37) 37 WHITESPACE@[36; 37)
36 PLUS@[37; 38) 38 PLUS@[37; 38)
37 WHITESPACE@[38; 39) 39 WHITESPACE@[38; 39)
38 LIFETIME@[39; 41) "'a" 40 TYPE_BOUND@[39; 41)
41 LIFETIME@[39; 41) "'a"
39 SEMI@[41; 42) 42 SEMI@[41; 42)
40 WHITESPACE@[42; 43) 43 WHITESPACE@[42; 43)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.rs
index b571a5860..bfe8e4b36 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.rs
@@ -2,4 +2,5 @@ fn foo() {
2 82 as i32; 2 82 as i32;
3 81 as i8 + 1; 3 81 as i8 + 1;
4 79 as i16 - 1; 4 79 as i16 - 1;
5 0x36 as u8 <= 0x37;
5} 6}
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.txt
index cb56aef0b..875ed1abd 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 65) 1SOURCE_FILE@[0; 89)
2 FN_DEF@[0; 64) 2 FN_DEF@[0; 88)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 65)
8 L_PAREN@[6; 7) 8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8) 9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9) 10 WHITESPACE@[8; 9)
11 BLOCK@[9; 64) 11 BLOCK@[9; 88)
12 L_CURLY@[9; 10) 12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 15) 13 WHITESPACE@[10; 15)
14 EXPR_STMT@[15; 25) 14 EXPR_STMT@[15; 25)
@@ -64,6 +64,26 @@ SOURCE_FILE@[0; 65)
64 LITERAL@[60; 61) 64 LITERAL@[60; 61)
65 INT_NUMBER@[60; 61) "1" 65 INT_NUMBER@[60; 61) "1"
66 SEMI@[61; 62) 66 SEMI@[61; 62)
67 WHITESPACE@[62; 63) 67 WHITESPACE@[62; 67)
68 R_CURLY@[63; 64) 68 EXPR_STMT@[67; 86)
69 WHITESPACE@[64; 65) 69 BIN_EXPR@[67; 85)
70 CAST_EXPR@[67; 77)
71 LITERAL@[67; 71)
72 INT_NUMBER@[67; 71) "0x36"
73 WHITESPACE@[71; 72)
74 AS_KW@[72; 74)
75 WHITESPACE@[74; 75)
76 PATH_TYPE@[75; 77)
77 PATH@[75; 77)
78 PATH_SEGMENT@[75; 77)
79 NAME_REF@[75; 77)
80 IDENT@[75; 77) "u8"
81 WHITESPACE@[77; 78)
82 LTEQ@[78; 80)
83 WHITESPACE@[80; 81)
84 LITERAL@[81; 85)
85 INT_NUMBER@[81; 85) "0x37"
86 SEMI@[85; 86)
87 WHITESPACE@[86; 87)
88 R_CURLY@[87; 88)
89 WHITESPACE@[88; 89)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.rs
index 4385afca9..32761dd03 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.rs
@@ -1 +1,2 @@
1trait T<U>: Hash + Clone where U: Copy {} 1trait T<U>: Hash + Clone where U: Copy {}
2trait X<U: Debug + Display>: Hash + Clone where U: Copy {}
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.txt
index 333a737ec..56cfea5b3 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.txt
@@ -1,4 +1,4 @@
1SOURCE_FILE@[0; 42) 1SOURCE_FILE@[0; 101)
2 TRAIT_DEF@[0; 41) 2 TRAIT_DEF@[0; 41)
3 TRAIT_KW@[0; 5) 3 TRAIT_KW@[0; 5)
4 WHITESPACE@[5; 6) 4 WHITESPACE@[5; 6)
@@ -12,19 +12,22 @@ SOURCE_FILE@[0; 42)
12 R_ANGLE@[9; 10) 12 R_ANGLE@[9; 10)
13 COLON@[10; 11) 13 COLON@[10; 11)
14 WHITESPACE@[11; 12) 14 WHITESPACE@[11; 12)
15 PATH_TYPE@[12; 24) 15 TYPE_BOUND_LIST@[12; 24)
16 PATH@[12; 16) 16 TYPE_BOUND@[12; 16)
17 PATH_SEGMENT@[12; 16) 17 PATH_TYPE@[12; 16)
18 NAME_REF@[12; 16) 18 PATH@[12; 16)
19 IDENT@[12; 16) "Hash" 19 PATH_SEGMENT@[12; 16)
20 NAME_REF@[12; 16)
21 IDENT@[12; 16) "Hash"
20 WHITESPACE@[16; 17) 22 WHITESPACE@[16; 17)
21 PLUS@[17; 18) 23 PLUS@[17; 18)
22 WHITESPACE@[18; 19) 24 WHITESPACE@[18; 19)
23 PATH_TYPE@[19; 24) 25 TYPE_BOUND@[19; 24)
24 PATH@[19; 24) 26 PATH_TYPE@[19; 24)
25 PATH_SEGMENT@[19; 24) 27 PATH@[19; 24)
26 NAME_REF@[19; 24) 28 PATH_SEGMENT@[19; 24)
27 IDENT@[19; 24) "Clone" 29 NAME_REF@[19; 24)
30 IDENT@[19; 24) "Clone"
28 WHITESPACE@[24; 25) 31 WHITESPACE@[24; 25)
29 WHERE_CLAUSE@[25; 38) 32 WHERE_CLAUSE@[25; 38)
30 WHERE_KW@[25; 30) 33 WHERE_KW@[25; 30)
@@ -37,13 +40,86 @@ SOURCE_FILE@[0; 42)
37 IDENT@[31; 32) "U" 40 IDENT@[31; 32) "U"
38 COLON@[32; 33) 41 COLON@[32; 33)
39 WHITESPACE@[33; 34) 42 WHITESPACE@[33; 34)
40 PATH_TYPE@[34; 38) 43 TYPE_BOUND_LIST@[34; 38)
41 PATH@[34; 38) 44 TYPE_BOUND@[34; 38)
42 PATH_SEGMENT@[34; 38) 45 PATH_TYPE@[34; 38)
43 NAME_REF@[34; 38) 46 PATH@[34; 38)
44 IDENT@[34; 38) "Copy" 47 PATH_SEGMENT@[34; 38)
48 NAME_REF@[34; 38)
49 IDENT@[34; 38) "Copy"
45 WHITESPACE@[38; 39) 50 WHITESPACE@[38; 39)
46 ITEM_LIST@[39; 41) 51 ITEM_LIST@[39; 41)
47 L_CURLY@[39; 40) 52 L_CURLY@[39; 40)
48 R_CURLY@[40; 41) 53 R_CURLY@[40; 41)
49 WHITESPACE@[41; 42) 54 WHITESPACE@[41; 42)
55 TRAIT_DEF@[42; 100)
56 TRAIT_KW@[42; 47)
57 WHITESPACE@[47; 48)
58 NAME@[48; 49)
59 IDENT@[48; 49) "X"
60 TYPE_PARAM_LIST@[49; 69)
61 L_ANGLE@[49; 50)
62 TYPE_PARAM@[50; 68)
63 NAME@[50; 51)
64 IDENT@[50; 51) "U"
65 COLON@[51; 52)
66 WHITESPACE@[52; 53)
67 TYPE_BOUND_LIST@[53; 68)
68 TYPE_BOUND@[53; 58)
69 PATH_TYPE@[53; 58)
70 PATH@[53; 58)
71 PATH_SEGMENT@[53; 58)
72 NAME_REF@[53; 58)
73 IDENT@[53; 58) "Debug"
74 WHITESPACE@[58; 59)
75 PLUS@[59; 60)
76 WHITESPACE@[60; 61)
77 TYPE_BOUND@[61; 68)
78 PATH_TYPE@[61; 68)
79 PATH@[61; 68)
80 PATH_SEGMENT@[61; 68)
81 NAME_REF@[61; 68)
82 IDENT@[61; 68) "Display"
83 R_ANGLE@[68; 69)
84 COLON@[69; 70)
85 WHITESPACE@[70; 71)
86 TYPE_BOUND_LIST@[71; 83)
87 TYPE_BOUND@[71; 75)
88 PATH_TYPE@[71; 75)
89 PATH@[71; 75)
90 PATH_SEGMENT@[71; 75)
91 NAME_REF@[71; 75)
92 IDENT@[71; 75) "Hash"
93 WHITESPACE@[75; 76)
94 PLUS@[76; 77)
95 WHITESPACE@[77; 78)
96 TYPE_BOUND@[78; 83)
97 PATH_TYPE@[78; 83)
98 PATH@[78; 83)
99 PATH_SEGMENT@[78; 83)
100 NAME_REF@[78; 83)
101 IDENT@[78; 83) "Clone"
102 WHITESPACE@[83; 84)
103 WHERE_CLAUSE@[84; 97)
104 WHERE_KW@[84; 89)
105 WHITESPACE@[89; 90)
106 WHERE_PRED@[90; 97)
107 PATH_TYPE@[90; 91)
108 PATH@[90; 91)
109 PATH_SEGMENT@[90; 91)
110 NAME_REF@[90; 91)
111 IDENT@[90; 91) "U"
112 COLON@[91; 92)
113 WHITESPACE@[92; 93)
114 TYPE_BOUND_LIST@[93; 97)
115 TYPE_BOUND@[93; 97)
116 PATH_TYPE@[93; 97)
117 PATH@[93; 97)
118 PATH_SEGMENT@[93; 97)
119 NAME_REF@[93; 97)
120 IDENT@[93; 97) "Copy"
121 WHITESPACE@[97; 98)
122 ITEM_LIST@[98; 100)
123 L_CURLY@[98; 99)
124 R_CURLY@[99; 100)
125 WHITESPACE@[100; 101)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.txt
index 2ce7a6714..3786a787a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.txt
@@ -11,29 +11,31 @@ SOURCE_FILE@[0; 35)
11 IDENT@[7; 8) "F" 11 IDENT@[7; 8) "F"
12 COLON@[8; 9) 12 COLON@[8; 9)
13 WHITESPACE@[9; 10) 13 WHITESPACE@[9; 10)
14 PATH_TYPE@[10; 29) 14 TYPE_BOUND_LIST@[10; 29)
15 PATH@[10; 29) 15 TYPE_BOUND@[10; 29)
16 PATH_SEGMENT@[10; 29) 16 PATH_TYPE@[10; 29)
17 NAME_REF@[10; 15) 17 PATH@[10; 29)
18 IDENT@[10; 15) "FnMut" 18 PATH_SEGMENT@[10; 29)
19 PARAM_LIST@[15; 29) 19 NAME_REF@[10; 15)
20 L_PAREN@[15; 16) 20 IDENT@[10; 15) "FnMut"
21 PARAM@[16; 28) 21 PARAM_LIST@[15; 29)
22 REFERENCE_TYPE@[16; 28) 22 L_PAREN@[15; 16)
23 AMP@[16; 17) 23 PARAM@[16; 28)
24 MUT_KW@[17; 20) 24 REFERENCE_TYPE@[16; 28)
25 WHITESPACE@[20; 21) 25 AMP@[16; 17)
26 PATH_TYPE@[21; 28) 26 MUT_KW@[17; 20)
27 PATH@[21; 28) 27 WHITESPACE@[20; 21)
28 PATH_SEGMENT@[21; 28) 28 PATH_TYPE@[21; 28)
29 NAME_REF@[21; 24) 29 PATH@[21; 28)
30 IDENT@[21; 24) "Foo" 30 PATH_SEGMENT@[21; 28)
31 TYPE_ARG_LIST@[24; 28) 31 NAME_REF@[21; 24)
32 L_ANGLE@[24; 25) 32 IDENT@[21; 24) "Foo"
33 LIFETIME_ARG@[25; 27) 33 TYPE_ARG_LIST@[24; 28)
34 LIFETIME@[25; 27) "'a" 34 L_ANGLE@[24; 25)
35 R_ANGLE@[27; 28) 35 LIFETIME_ARG@[25; 27)
36 R_PAREN@[28; 29) 36 LIFETIME@[25; 27) "'a"
37 R_ANGLE@[27; 28)
38 R_PAREN@[28; 29)
37 R_ANGLE@[29; 30) 39 R_ANGLE@[29; 30)
38 PARAM_LIST@[30; 32) 40 PARAM_LIST@[30; 32)
39 L_PAREN@[30; 31) 41 L_PAREN@[30; 31)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.rs
index 215210e27..4bb0f63b7 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.rs
@@ -1 +1,2 @@
1fn foo() -> Box<T + 'f> {} 1fn foo() -> Box<T + 'f> {}
2fn foo() -> Box<dyn T + 'f> {}
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.txt
index 911a27ea1..6faf4d3b9 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.txt
@@ -1,4 +1,4 @@
1SOURCE_FILE@[0; 27) 1SOURCE_FILE@[0; 58)
2 FN_DEF@[0; 26) 2 FN_DEF@[0; 26)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
@@ -19,18 +19,63 @@ SOURCE_FILE@[0; 27)
19 TYPE_ARG_LIST@[15; 23) 19 TYPE_ARG_LIST@[15; 23)
20 L_ANGLE@[15; 16) 20 L_ANGLE@[15; 16)
21 TYPE_ARG@[16; 22) 21 TYPE_ARG@[16; 22)
22 PATH_TYPE@[16; 22) 22 DYN_TRAIT_TYPE@[16; 22)
23 PATH@[16; 17) 23 TYPE_BOUND_LIST@[16; 22)
24 PATH_SEGMENT@[16; 17) 24 TYPE_BOUND@[16; 17)
25 NAME_REF@[16; 17) 25 PATH_TYPE@[16; 17)
26 IDENT@[16; 17) "T" 26 PATH@[16; 17)
27 WHITESPACE@[17; 18) 27 PATH_SEGMENT@[16; 17)
28 PLUS@[18; 19) 28 NAME_REF@[16; 17)
29 WHITESPACE@[19; 20) 29 IDENT@[16; 17) "T"
30 LIFETIME@[20; 22) "'f" 30 WHITESPACE@[17; 18)
31 PLUS@[18; 19)
32 WHITESPACE@[19; 20)
33 TYPE_BOUND@[20; 22)
34 LIFETIME@[20; 22) "'f"
31 R_ANGLE@[22; 23) 35 R_ANGLE@[22; 23)
32 WHITESPACE@[23; 24) 36 WHITESPACE@[23; 24)
33 BLOCK@[24; 26) 37 BLOCK@[24; 26)
34 L_CURLY@[24; 25) 38 L_CURLY@[24; 25)
35 R_CURLY@[25; 26) 39 R_CURLY@[25; 26)
36 WHITESPACE@[26; 27) 40 WHITESPACE@[26; 27)
41 FN_DEF@[27; 57)
42 FN_KW@[27; 29)
43 WHITESPACE@[29; 30)
44 NAME@[30; 33)
45 IDENT@[30; 33) "foo"
46 PARAM_LIST@[33; 35)
47 L_PAREN@[33; 34)
48 R_PAREN@[34; 35)
49 WHITESPACE@[35; 36)
50 RET_TYPE@[36; 54)
51 THIN_ARROW@[36; 38)
52 WHITESPACE@[38; 39)
53 PATH_TYPE@[39; 54)
54 PATH@[39; 54)
55 PATH_SEGMENT@[39; 54)
56 NAME_REF@[39; 42)
57 IDENT@[39; 42) "Box"
58 TYPE_ARG_LIST@[42; 54)
59 L_ANGLE@[42; 43)
60 TYPE_ARG@[43; 53)
61 DYN_TRAIT_TYPE@[43; 53)
62 DYN_KW@[43; 46)
63 WHITESPACE@[46; 47)
64 TYPE_BOUND_LIST@[47; 53)
65 TYPE_BOUND@[47; 48)
66 PATH_TYPE@[47; 48)
67 PATH@[47; 48)
68 PATH_SEGMENT@[47; 48)
69 NAME_REF@[47; 48)
70 IDENT@[47; 48) "T"
71 WHITESPACE@[48; 49)
72 PLUS@[49; 50)
73 WHITESPACE@[50; 51)
74 TYPE_BOUND@[51; 53)
75 LIFETIME@[51; 53) "'f"
76 R_ANGLE@[53; 54)
77 WHITESPACE@[54; 55)
78 BLOCK@[55; 57)
79 L_CURLY@[55; 56)
80 R_CURLY@[56; 57)
81 WHITESPACE@[57; 58)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt
index 68485dc0b..77a62ab4d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt
@@ -15,11 +15,14 @@ SOURCE_FILE@[0; 116)
15 LIFETIME@[18; 20) "'a" 15 LIFETIME@[18; 20) "'a"
16 COLON@[20; 21) 16 COLON@[20; 21)
17 WHITESPACE@[21; 22) 17 WHITESPACE@[21; 22)
18 LIFETIME@[22; 24) "'b" 18 TYPE_BOUND_LIST@[22; 29)
19 WHITESPACE@[24; 25) 19 TYPE_BOUND@[22; 24)
20 PLUS@[25; 26) 20 LIFETIME@[22; 24) "'b"
21 WHITESPACE@[26; 27) 21 WHITESPACE@[24; 25)
22 LIFETIME@[27; 29) "'c" 22 PLUS@[25; 26)
23 WHITESPACE@[26; 27)
24 TYPE_BOUND@[27; 29)
25 LIFETIME@[27; 29) "'c"
23 COMMA@[29; 30) 26 COMMA@[29; 30)
24 WHITESPACE@[30; 34) 27 WHITESPACE@[30; 34)
25 WHERE_PRED@[34; 59) 28 WHERE_PRED@[34; 59)
@@ -30,22 +33,26 @@ SOURCE_FILE@[0; 116)
30 IDENT@[34; 35) "T" 33 IDENT@[34; 35) "T"
31 COLON@[35; 36) 34 COLON@[35; 36)
32 WHITESPACE@[36; 37) 35 WHITESPACE@[36; 37)
33 PATH_TYPE@[37; 59) 36 TYPE_BOUND_LIST@[37; 59)
34 PATH@[37; 42) 37 TYPE_BOUND@[37; 42)
35 PATH_SEGMENT@[37; 42) 38 PATH_TYPE@[37; 42)
36 NAME_REF@[37; 42) 39 PATH@[37; 42)
37 IDENT@[37; 42) "Clone" 40 PATH_SEGMENT@[37; 42)
41 NAME_REF@[37; 42)
42 IDENT@[37; 42) "Clone"
38 WHITESPACE@[42; 43) 43 WHITESPACE@[42; 43)
39 PLUS@[43; 44) 44 PLUS@[43; 44)
40 WHITESPACE@[44; 45) 45 WHITESPACE@[44; 45)
41 PATH_TYPE@[45; 59) 46 TYPE_BOUND@[45; 49)
42 PATH@[45; 49) 47 PATH_TYPE@[45; 49)
43 PATH_SEGMENT@[45; 49) 48 PATH@[45; 49)
44 NAME_REF@[45; 49) 49 PATH_SEGMENT@[45; 49)
45 IDENT@[45; 49) "Copy" 50 NAME_REF@[45; 49)
46 WHITESPACE@[49; 50) 51 IDENT@[45; 49) "Copy"
47 PLUS@[50; 51) 52 WHITESPACE@[49; 50)
48 WHITESPACE@[51; 52) 53 PLUS@[50; 51)
54 WHITESPACE@[51; 52)
55 TYPE_BOUND@[52; 59)
49 LIFETIME@[52; 59) "'static" 56 LIFETIME@[52; 59) "'static"
50 COMMA@[59; 60) 57 COMMA@[59; 60)
51 WHITESPACE@[60; 64) 58 WHITESPACE@[60; 64)
@@ -62,7 +69,9 @@ SOURCE_FILE@[0; 116)
62 IDENT@[74; 78) "Item" 69 IDENT@[74; 78) "Item"
63 COLON@[78; 79) 70 COLON@[78; 79)
64 WHITESPACE@[79; 80) 71 WHITESPACE@[79; 80)
65 LIFETIME@[80; 82) "'a" 72 TYPE_BOUND_LIST@[80; 82)
73 TYPE_BOUND@[80; 82)
74 LIFETIME@[80; 82) "'a"
66 COMMA@[82; 83) 75 COMMA@[82; 83)
67 WHITESPACE@[83; 87) 76 WHITESPACE@[83; 87)
68 WHERE_PRED@[87; 112) 77 WHERE_PRED@[87; 112)
@@ -91,7 +100,9 @@ SOURCE_FILE@[0; 116)
91 IDENT@[104; 108) "Item" 100 IDENT@[104; 108) "Item"
92 COLON@[108; 109) 101 COLON@[108; 109)
93 WHITESPACE@[109; 110) 102 WHITESPACE@[109; 110)
94 LIFETIME@[110; 112) "'a" 103 TYPE_BOUND_LIST@[110; 112)
104 TYPE_BOUND@[110; 112)
105 LIFETIME@[110; 112) "'a"
95 WHITESPACE@[112; 113) 106 WHITESPACE@[112; 113)
96 BLOCK@[113; 115) 107 BLOCK@[113; 115)
97 L_CURLY@[113; 114) 108 L_CURLY@[113; 114)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.txt
index f6a0967f2..e33d8ada1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.txt
@@ -10,31 +10,34 @@ SOURCE_FILE@[0; 42)
10 DYN_TRAIT_TYPE@[9; 40) 10 DYN_TRAIT_TYPE@[9; 40)
11 DYN_KW@[9; 12) 11 DYN_KW@[9; 12)
12 WHITESPACE@[12; 13) 12 WHITESPACE@[12; 13)
13 PATH_TYPE@[13; 40) 13 TYPE_BOUND_LIST@[13; 40)
14 PATH@[13; 35) 14 TYPE_BOUND@[13; 35)
15 PATH_SEGMENT@[13; 35) 15 PATH_TYPE@[13; 35)
16 NAME_REF@[13; 21) 16 PATH@[13; 35)
17 IDENT@[13; 21) "Iterator" 17 PATH_SEGMENT@[13; 35)
18 TYPE_ARG_LIST@[21; 35) 18 NAME_REF@[13; 21)
19 L_ANGLE@[21; 22) 19 IDENT@[13; 21) "Iterator"
20 ASSOC_TYPE_ARG@[22; 34) 20 TYPE_ARG_LIST@[21; 35)
21 NAME_REF@[22; 26) 21 L_ANGLE@[21; 22)
22 IDENT@[22; 26) "Item" 22 ASSOC_TYPE_ARG@[22; 34)
23 EQ@[26; 27) 23 NAME_REF@[22; 26)
24 PATH_TYPE@[27; 34) 24 IDENT@[22; 26) "Item"
25 PATH@[27; 34) 25 EQ@[26; 27)
26 PATH_SEGMENT@[27; 34) 26 PATH_TYPE@[27; 34)
27 NAME_REF@[27; 30) 27 PATH@[27; 34)
28 IDENT@[27; 30) "Foo" 28 PATH_SEGMENT@[27; 34)
29 TYPE_ARG_LIST@[30; 34) 29 NAME_REF@[27; 30)
30 L_ANGLE@[30; 31) 30 IDENT@[27; 30) "Foo"
31 LIFETIME_ARG@[31; 33) 31 TYPE_ARG_LIST@[30; 34)
32 LIFETIME@[31; 33) "'a" 32 L_ANGLE@[30; 31)
33 R_ANGLE@[33; 34) 33 LIFETIME_ARG@[31; 33)
34 R_ANGLE@[34; 35) 34 LIFETIME@[31; 33) "'a"
35 R_ANGLE@[33; 34)
36 R_ANGLE@[34; 35)
35 WHITESPACE@[35; 36) 37 WHITESPACE@[35; 36)
36 PLUS@[36; 37) 38 PLUS@[36; 37)
37 WHITESPACE@[37; 38) 39 WHITESPACE@[37; 38)
38 LIFETIME@[38; 40) "'a" 40 TYPE_BOUND@[38; 40)
41 LIFETIME@[38; 40) "'a"
39 SEMI@[40; 41) 42 SEMI@[40; 41)
40 WHITESPACE@[41; 42) 43 WHITESPACE@[41; 42)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0076_function_where_clause.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0076_function_where_clause.txt
index b58d09e35..1603b531e 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0076_function_where_clause.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0076_function_where_clause.txt
@@ -25,11 +25,13 @@ SOURCE_FILE@[0; 29)
25 IDENT@[18; 19) "T" 25 IDENT@[18; 19) "T"
26 COLON@[19; 20) 26 COLON@[19; 20)
27 WHITESPACE@[20; 21) 27 WHITESPACE@[20; 21)
28 PATH_TYPE@[21; 25) 28 TYPE_BOUND_LIST@[21; 25)
29 PATH@[21; 25) 29 TYPE_BOUND@[21; 25)
30 PATH_SEGMENT@[21; 25) 30 PATH_TYPE@[21; 25)
31 NAME_REF@[21; 25) 31 PATH@[21; 25)
32 IDENT@[21; 25) "Copy" 32 PATH_SEGMENT@[21; 25)
33 NAME_REF@[21; 25)
34 IDENT@[21; 25) "Copy"
33 WHITESPACE@[25; 26) 35 WHITESPACE@[25; 26)
34 BLOCK@[26; 28) 36 BLOCK@[26; 28)
35 L_CURLY@[26; 27) 37 L_CURLY@[26; 27)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0081_for_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0081_for_type.txt
index 568f61fb2..36c856cd7 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0081_for_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0081_for_type.txt
@@ -80,11 +80,13 @@ SOURCE_FILE@[0; 135)
80 IDENT@[65; 66) "T" 80 IDENT@[65; 66) "T"
81 COLON@[66; 67) 81 COLON@[66; 67)
82 WHITESPACE@[67; 68) 82 WHITESPACE@[67; 68)
83 PATH_TYPE@[68; 76) 83 TYPE_BOUND_LIST@[68; 76)
84 PATH@[68; 76) 84 TYPE_BOUND@[68; 76)
85 PATH_SEGMENT@[68; 76) 85 PATH_TYPE@[68; 76)
86 NAME_REF@[68; 76) 86 PATH@[68; 76)
87 IDENT@[68; 76) "Iterator" 87 PATH_SEGMENT@[68; 76)
88 NAME_REF@[68; 76)
89 IDENT@[68; 76) "Iterator"
88 WHITESPACE@[76; 77) 90 WHITESPACE@[76; 77)
89 BLOCK@[77; 79) 91 BLOCK@[77; 79)
90 L_CURLY@[77; 78) 92 L_CURLY@[77; 78)
@@ -143,11 +145,13 @@ SOURCE_FILE@[0; 135)
143 IDENT@[120; 121) "T" 145 IDENT@[120; 121) "T"
144 COLON@[121; 122) 146 COLON@[121; 122)
145 WHITESPACE@[122; 123) 147 WHITESPACE@[122; 123)
146 PATH_TYPE@[123; 131) 148 TYPE_BOUND_LIST@[123; 131)
147 PATH@[123; 131) 149 TYPE_BOUND@[123; 131)
148 PATH_SEGMENT@[123; 131) 150 PATH_TYPE@[123; 131)
149 NAME_REF@[123; 131) 151 PATH@[123; 131)
150 IDENT@[123; 131) "Iterator" 152 PATH_SEGMENT@[123; 131)
153 NAME_REF@[123; 131)
154 IDENT@[123; 131) "Iterator"
151 WHITESPACE@[131; 132) 155 WHITESPACE@[131; 132)
152 BLOCK@[132; 134) 156 BLOCK@[132; 134)
153 L_CURLY@[132; 133) 157 L_CURLY@[132; 133)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs
index c20d29751..075717823 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs
@@ -3,4 +3,7 @@ fn foo() {
3 || -> i32 { 92 }; 3 || -> i32 { 92 };
4 |x| x; 4 |x| x;
5 move |x: i32,| x; 5 move |x: i32,| x;
6 async || {};
7 move || {};
8 async move || {};
6} 9}
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt
index 98271c233..b885d239a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 79) 1SOURCE_FILE@[0; 134)
2 FN_DEF@[0; 78) 2 FN_DEF@[0; 133)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 79)
8 L_PAREN@[6; 7) 8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8) 9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9) 10 WHITESPACE@[8; 9)
11 BLOCK@[9; 78) 11 BLOCK@[9; 133)
12 L_CURLY@[9; 10) 12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 15) 13 WHITESPACE@[10; 15)
14 EXPR_STMT@[15; 21) 14 EXPR_STMT@[15; 21)
@@ -90,6 +90,50 @@ SOURCE_FILE@[0; 79)
90 NAME_REF@[74; 75) 90 NAME_REF@[74; 75)
91 IDENT@[74; 75) "x" 91 IDENT@[74; 75) "x"
92 SEMI@[75; 76) 92 SEMI@[75; 76)
93 WHITESPACE@[76; 77) 93 WHITESPACE@[76; 81)
94 R_CURLY@[77; 78) 94 EXPR_STMT@[81; 93)
95 WHITESPACE@[78; 79) 95 LAMBDA_EXPR@[81; 92)
96 ASYNC_KW@[81; 86)
97 WHITESPACE@[86; 87)
98 PARAM_LIST@[87; 89)
99 PIPE@[87; 88)
100 PIPE@[88; 89)
101 WHITESPACE@[89; 90)
102 BLOCK_EXPR@[90; 92)
103 BLOCK@[90; 92)
104 L_CURLY@[90; 91)
105 R_CURLY@[91; 92)
106 SEMI@[92; 93)
107 WHITESPACE@[93; 98)
108 EXPR_STMT@[98; 109)
109 LAMBDA_EXPR@[98; 108)
110 MOVE_KW@[98; 102)
111 WHITESPACE@[102; 103)
112 PARAM_LIST@[103; 105)
113 PIPE@[103; 104)
114 PIPE@[104; 105)
115 WHITESPACE@[105; 106)
116 BLOCK_EXPR@[106; 108)
117 BLOCK@[106; 108)
118 L_CURLY@[106; 107)
119 R_CURLY@[107; 108)
120 SEMI@[108; 109)
121 WHITESPACE@[109; 114)
122 EXPR_STMT@[114; 131)
123 LAMBDA_EXPR@[114; 130)
124 ASYNC_KW@[114; 119)
125 WHITESPACE@[119; 120)
126 MOVE_KW@[120; 124)
127 WHITESPACE@[124; 125)
128 PARAM_LIST@[125; 127)
129 PIPE@[125; 126)
130 PIPE@[126; 127)
131 WHITESPACE@[127; 128)
132 BLOCK_EXPR@[128; 130)
133 BLOCK@[128; 130)
134 L_CURLY@[128; 129)
135 R_CURLY@[129; 130)
136 SEMI@[130; 131)
137 WHITESPACE@[131; 132)
138 R_CURLY@[132; 133)
139 WHITESPACE@[133; 134)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0114_tuple_struct_where.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0114_tuple_struct_where.txt
index 4f439f21c..dec038fc1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0114_tuple_struct_where.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0114_tuple_struct_where.txt
@@ -31,11 +31,13 @@ SOURCE_FILE@[0; 53)
31 IDENT@[24; 25) "T" 31 IDENT@[24; 25) "T"
32 COLON@[25; 26) 32 COLON@[25; 26)
33 WHITESPACE@[26; 27) 33 WHITESPACE@[26; 27)
34 PATH_TYPE@[27; 32) 34 TYPE_BOUND_LIST@[27; 32)
35 PATH@[27; 32) 35 TYPE_BOUND@[27; 32)
36 PATH_SEGMENT@[27; 32) 36 PATH_TYPE@[27; 32)
37 NAME_REF@[27; 32) 37 PATH@[27; 32)
38 IDENT@[27; 32) "Clone" 38 PATH_SEGMENT@[27; 32)
39 NAME_REF@[27; 32)
40 IDENT@[27; 32) "Clone"
39 SEMI@[32; 33) 41 SEMI@[32; 33)
40 WHITESPACE@[33; 34) 42 WHITESPACE@[33; 34)
41 STRUCT_DEF@[34; 52) 43 STRUCT_DEF@[34; 52)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0001_struct_item.txt b/crates/ra_syntax/tests/data/parser/ok/0001_struct_item.txt
index 12497e1a9..b49206d80 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0001_struct_item.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0001_struct_item.txt
@@ -11,11 +11,13 @@ SOURCE_FILE@[0; 32)
11 IDENT@[9; 10) "T" 11 IDENT@[9; 10) "T"
12 COLON@[10; 11) 12 COLON@[10; 11)
13 WHITESPACE@[11; 12) 13 WHITESPACE@[11; 12)
14 PATH_TYPE@[12; 16) 14 TYPE_BOUND_LIST@[12; 16)
15 PATH@[12; 16) 15 TYPE_BOUND@[12; 16)
16 PATH_SEGMENT@[12; 16) 16 PATH_TYPE@[12; 16)
17 NAME_REF@[12; 16) 17 PATH@[12; 16)
18 IDENT@[12; 16) "Copy" 18 PATH_SEGMENT@[12; 16)
19 NAME_REF@[12; 16)
20 IDENT@[12; 16) "Copy"
19 R_ANGLE@[16; 17) 21 R_ANGLE@[16; 17)
20 WHITESPACE@[17; 18) 22 WHITESPACE@[17; 18)
21 NAMED_FIELD_DEF_LIST@[18; 31) 23 NAMED_FIELD_DEF_LIST@[18; 31)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.rs b/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.rs
index 3ce336676..ab81a608c 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.rs
+++ b/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.rs
@@ -1,2 +1,3 @@
1extern crate foo; 1extern crate foo;
2extern crate foo as bar; 2extern crate foo as bar;
3extern crate self as baz;
diff --git a/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt b/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt
index 5558d952e..0176260c1 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt
@@ -1,4 +1,4 @@
1SOURCE_FILE@[0; 43) 1SOURCE_FILE@[0; 69)
2 EXTERN_CRATE_ITEM@[0; 17) 2 EXTERN_CRATE_ITEM@[0; 17)
3 EXTERN_KW@[0; 6) 3 EXTERN_KW@[0; 6)
4 WHITESPACE@[6; 7) 4 WHITESPACE@[6; 7)
@@ -23,3 +23,18 @@ SOURCE_FILE@[0; 43)
23 IDENT@[38; 41) "bar" 23 IDENT@[38; 41) "bar"
24 SEMI@[41; 42) 24 SEMI@[41; 42)
25 WHITESPACE@[42; 43) 25 WHITESPACE@[42; 43)
26 EXTERN_CRATE_ITEM@[43; 68)
27 EXTERN_KW@[43; 49)
28 WHITESPACE@[49; 50)
29 CRATE_KW@[50; 55)
30 WHITESPACE@[55; 56)
31 SELF_KW@[56; 60)
32 SELF_KW@[56; 60)
33 WHITESPACE@[60; 61)
34 ALIAS@[61; 67)
35 AS_KW@[61; 63)
36 WHITESPACE@[63; 64)
37 NAME@[64; 67)
38 IDENT@[64; 67) "baz"
39 SEMI@[67; 68)
40 WHITESPACE@[68; 69)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.rs b/crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.rs
index a1b9f00a4..712898978 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.rs
+++ b/crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.rs
@@ -7,3 +7,4 @@ struct F<T: 'a + 'd + Clone>;
7struct G<T: Clone + Copy>; 7struct G<T: Clone + Copy>;
8struct H<T: ::Foo + self::Bar + 'a>; 8struct H<T: ::Foo + self::Bar + 'a>;
9struct I<T:, U:,>; 9struct I<T:, U:,>;
10struct K<'a: 'd, 'd: 'a + 'b, T: 'a + 'd + Clone>; \ No newline at end of file
diff --git a/crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.txt b/crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.txt
index b70a1d19a..04aaca4c4 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.txt
@@ -1,4 +1,4 @@
1SOURCE_FILE@[0; 200) 1SOURCE_FILE@[0; 250)
2 STRUCT_DEF@[0; 12) 2 STRUCT_DEF@[0; 12)
3 STRUCT_KW@[0; 6) 3 STRUCT_KW@[0; 6)
4 WHITESPACE@[6; 7) 4 WHITESPACE@[6; 7)
@@ -23,6 +23,7 @@ SOURCE_FILE@[0; 200)
23 NAME@[22; 23) 23 NAME@[22; 23)
24 IDENT@[22; 23) "T" 24 IDENT@[22; 23) "T"
25 COLON@[23; 24) 25 COLON@[23; 24)
26 TYPE_BOUND_LIST@[24; 24)
26 R_ANGLE@[24; 25) 27 R_ANGLE@[24; 25)
27 SEMI@[25; 26) 28 SEMI@[25; 26)
28 WHITESPACE@[26; 27) 29 WHITESPACE@[26; 27)
@@ -38,7 +39,9 @@ SOURCE_FILE@[0; 200)
38 IDENT@[36; 37) "T" 39 IDENT@[36; 37) "T"
39 COLON@[37; 38) 40 COLON@[37; 38)
40 WHITESPACE@[38; 39) 41 WHITESPACE@[38; 39)
41 LIFETIME@[39; 41) "'a" 42 TYPE_BOUND_LIST@[39; 41)
43 TYPE_BOUND@[39; 41)
44 LIFETIME@[39; 41) "'a"
42 R_ANGLE@[41; 42) 45 R_ANGLE@[41; 42)
43 SEMI@[42; 43) 46 SEMI@[42; 43)
44 WHITESPACE@[43; 44) 47 WHITESPACE@[43; 44)
@@ -54,9 +57,11 @@ SOURCE_FILE@[0; 200)
54 IDENT@[53; 54) "T" 57 IDENT@[53; 54) "T"
55 COLON@[54; 55) 58 COLON@[54; 55)
56 WHITESPACE@[55; 56) 59 WHITESPACE@[55; 56)
57 LIFETIME@[56; 58) "'a" 60 TYPE_BOUND_LIST@[56; 60)
58 WHITESPACE@[58; 59) 61 TYPE_BOUND@[56; 58)
59 PLUS@[59; 60) 62 LIFETIME@[56; 58) "'a"
63 WHITESPACE@[58; 59)
64 PLUS@[59; 60)
60 WHITESPACE@[60; 61) 65 WHITESPACE@[60; 61)
61 R_ANGLE@[61; 62) 66 R_ANGLE@[61; 62)
62 SEMI@[62; 63) 67 SEMI@[62; 63)
@@ -73,11 +78,14 @@ SOURCE_FILE@[0; 200)
73 IDENT@[73; 74) "T" 78 IDENT@[73; 74) "T"
74 COLON@[74; 75) 79 COLON@[74; 75)
75 WHITESPACE@[75; 76) 80 WHITESPACE@[75; 76)
76 LIFETIME@[76; 78) "'a" 81 TYPE_BOUND_LIST@[76; 83)
77 WHITESPACE@[78; 79) 82 TYPE_BOUND@[76; 78)
78 PLUS@[79; 80) 83 LIFETIME@[76; 78) "'a"
79 WHITESPACE@[80; 81) 84 WHITESPACE@[78; 79)
80 LIFETIME@[81; 83) "'d" 85 PLUS@[79; 80)
86 WHITESPACE@[80; 81)
87 TYPE_BOUND@[81; 83)
88 LIFETIME@[81; 83) "'d"
81 WHITESPACE@[83; 84) 89 WHITESPACE@[83; 84)
82 R_ANGLE@[84; 85) 90 R_ANGLE@[84; 85)
83 SEMI@[85; 86) 91 SEMI@[85; 86)
@@ -94,19 +102,23 @@ SOURCE_FILE@[0; 200)
94 IDENT@[96; 97) "T" 102 IDENT@[96; 97) "T"
95 COLON@[97; 98) 103 COLON@[97; 98)
96 WHITESPACE@[98; 99) 104 WHITESPACE@[98; 99)
97 LIFETIME@[99; 101) "'a" 105 TYPE_BOUND_LIST@[99; 114)
98 WHITESPACE@[101; 102) 106 TYPE_BOUND@[99; 101)
99 PLUS@[102; 103) 107 LIFETIME@[99; 101) "'a"
100 WHITESPACE@[103; 104) 108 WHITESPACE@[101; 102)
101 LIFETIME@[104; 106) "'d" 109 PLUS@[102; 103)
102 WHITESPACE@[106; 107) 110 WHITESPACE@[103; 104)
103 PLUS@[107; 108) 111 TYPE_BOUND@[104; 106)
104 WHITESPACE@[108; 109) 112 LIFETIME@[104; 106) "'d"
105 PATH_TYPE@[109; 114) 113 WHITESPACE@[106; 107)
106 PATH@[109; 114) 114 PLUS@[107; 108)
107 PATH_SEGMENT@[109; 114) 115 WHITESPACE@[108; 109)
108 NAME_REF@[109; 114) 116 TYPE_BOUND@[109; 114)
109 IDENT@[109; 114) "Clone" 117 PATH_TYPE@[109; 114)
118 PATH@[109; 114)
119 PATH_SEGMENT@[109; 114)
120 NAME_REF@[109; 114)
121 IDENT@[109; 114) "Clone"
110 R_ANGLE@[114; 115) 122 R_ANGLE@[114; 115)
111 SEMI@[115; 116) 123 SEMI@[115; 116)
112 WHITESPACE@[116; 117) 124 WHITESPACE@[116; 117)
@@ -122,19 +134,22 @@ SOURCE_FILE@[0; 200)
122 IDENT@[126; 127) "T" 134 IDENT@[126; 127) "T"
123 COLON@[127; 128) 135 COLON@[127; 128)
124 WHITESPACE@[128; 129) 136 WHITESPACE@[128; 129)
125 PATH_TYPE@[129; 141) 137 TYPE_BOUND_LIST@[129; 141)
126 PATH@[129; 134) 138 TYPE_BOUND@[129; 134)
127 PATH_SEGMENT@[129; 134) 139 PATH_TYPE@[129; 134)
128 NAME_REF@[129; 134) 140 PATH@[129; 134)
129 IDENT@[129; 134) "Clone" 141 PATH_SEGMENT@[129; 134)
142 NAME_REF@[129; 134)
143 IDENT@[129; 134) "Clone"
130 WHITESPACE@[134; 135) 144 WHITESPACE@[134; 135)
131 PLUS@[135; 136) 145 PLUS@[135; 136)
132 WHITESPACE@[136; 137) 146 WHITESPACE@[136; 137)
133 PATH_TYPE@[137; 141) 147 TYPE_BOUND@[137; 141)
134 PATH@[137; 141) 148 PATH_TYPE@[137; 141)
135 PATH_SEGMENT@[137; 141) 149 PATH@[137; 141)
136 NAME_REF@[137; 141) 150 PATH_SEGMENT@[137; 141)
137 IDENT@[137; 141) "Copy" 151 NAME_REF@[137; 141)
152 IDENT@[137; 141) "Copy"
138 R_ANGLE@[141; 142) 153 R_ANGLE@[141; 142)
139 SEMI@[142; 143) 154 SEMI@[142; 143)
140 WHITESPACE@[143; 144) 155 WHITESPACE@[143; 144)
@@ -150,27 +165,31 @@ SOURCE_FILE@[0; 200)
150 IDENT@[153; 154) "T" 165 IDENT@[153; 154) "T"
151 COLON@[154; 155) 166 COLON@[154; 155)
152 WHITESPACE@[155; 156) 167 WHITESPACE@[155; 156)
153 PATH_TYPE@[156; 178) 168 TYPE_BOUND_LIST@[156; 178)
154 PATH@[156; 161) 169 TYPE_BOUND@[156; 161)
155 PATH_SEGMENT@[156; 161) 170 PATH_TYPE@[156; 161)
156 COLONCOLON@[156; 158) 171 PATH@[156; 161)
157 NAME_REF@[158; 161) 172 PATH_SEGMENT@[156; 161)
158 IDENT@[158; 161) "Foo" 173 COLONCOLON@[156; 158)
174 NAME_REF@[158; 161)
175 IDENT@[158; 161) "Foo"
159 WHITESPACE@[161; 162) 176 WHITESPACE@[161; 162)
160 PLUS@[162; 163) 177 PLUS@[162; 163)
161 WHITESPACE@[163; 164) 178 WHITESPACE@[163; 164)
162 PATH_TYPE@[164; 178) 179 TYPE_BOUND@[164; 173)
163 PATH@[164; 173) 180 PATH_TYPE@[164; 173)
164 PATH@[164; 168) 181 PATH@[164; 173)
165 PATH_SEGMENT@[164; 168) 182 PATH@[164; 168)
166 SELF_KW@[164; 168) 183 PATH_SEGMENT@[164; 168)
167 COLONCOLON@[168; 170) 184 SELF_KW@[164; 168)
168 PATH_SEGMENT@[170; 173) 185 COLONCOLON@[168; 170)
169 NAME_REF@[170; 173) 186 PATH_SEGMENT@[170; 173)
170 IDENT@[170; 173) "Bar" 187 NAME_REF@[170; 173)
171 WHITESPACE@[173; 174) 188 IDENT@[170; 173) "Bar"
172 PLUS@[174; 175) 189 WHITESPACE@[173; 174)
173 WHITESPACE@[175; 176) 190 PLUS@[174; 175)
191 WHITESPACE@[175; 176)
192 TYPE_BOUND@[176; 178)
174 LIFETIME@[176; 178) "'a" 193 LIFETIME@[176; 178) "'a"
175 R_ANGLE@[178; 179) 194 R_ANGLE@[178; 179)
176 SEMI@[179; 180) 195 SEMI@[179; 180)
@@ -186,13 +205,64 @@ SOURCE_FILE@[0; 200)
186 NAME@[190; 191) 205 NAME@[190; 191)
187 IDENT@[190; 191) "T" 206 IDENT@[190; 191) "T"
188 COLON@[191; 192) 207 COLON@[191; 192)
208 TYPE_BOUND_LIST@[192; 192)
189 COMMA@[192; 193) 209 COMMA@[192; 193)
190 WHITESPACE@[193; 194) 210 WHITESPACE@[193; 194)
191 TYPE_PARAM@[194; 196) 211 TYPE_PARAM@[194; 196)
192 NAME@[194; 195) 212 NAME@[194; 195)
193 IDENT@[194; 195) "U" 213 IDENT@[194; 195) "U"
194 COLON@[195; 196) 214 COLON@[195; 196)
215 TYPE_BOUND_LIST@[196; 196)
195 COMMA@[196; 197) 216 COMMA@[196; 197)
196 R_ANGLE@[197; 198) 217 R_ANGLE@[197; 198)
197 SEMI@[198; 199) 218 SEMI@[198; 199)
198 WHITESPACE@[199; 200) 219 WHITESPACE@[199; 200)
220 STRUCT_DEF@[200; 250)
221 STRUCT_KW@[200; 206)
222 WHITESPACE@[206; 207)
223 NAME@[207; 208)
224 IDENT@[207; 208) "K"
225 TYPE_PARAM_LIST@[208; 249)
226 L_ANGLE@[208; 209)
227 LIFETIME_PARAM@[209; 215)
228 LIFETIME@[209; 211) "'a"
229 COLON@[211; 212)
230 WHITESPACE@[212; 213)
231 LIFETIME@[213; 215) "'d"
232 COMMA@[215; 216)
233 WHITESPACE@[216; 217)
234 LIFETIME_PARAM@[217; 228)
235 LIFETIME@[217; 219) "'d"
236 COLON@[219; 220)
237 WHITESPACE@[220; 221)
238 LIFETIME@[221; 223) "'a"
239 WHITESPACE@[223; 224)
240 PLUS@[224; 225)
241 WHITESPACE@[225; 226)
242 LIFETIME@[226; 228) "'b"
243 COMMA@[228; 229)
244 WHITESPACE@[229; 230)
245 TYPE_PARAM@[230; 248)
246 NAME@[230; 231)
247 IDENT@[230; 231) "T"
248 COLON@[231; 232)
249 WHITESPACE@[232; 233)
250 TYPE_BOUND_LIST@[233; 248)
251 TYPE_BOUND@[233; 235)
252 LIFETIME@[233; 235) "'a"
253 WHITESPACE@[235; 236)
254 PLUS@[236; 237)
255 WHITESPACE@[237; 238)
256 TYPE_BOUND@[238; 240)
257 LIFETIME@[238; 240) "'d"
258 WHITESPACE@[240; 241)
259 PLUS@[241; 242)
260 WHITESPACE@[242; 243)
261 TYPE_BOUND@[243; 248)
262 PATH_TYPE@[243; 248)
263 PATH@[243; 248)
264 PATH_SEGMENT@[243; 248)
265 NAME_REF@[243; 248)
266 IDENT@[243; 248) "Clone"
267 R_ANGLE@[248; 249)
268 SEMI@[249; 250)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0032_where_for.txt b/crates/ra_syntax/tests/data/parser/ok/0032_where_for.txt
index 150a9e483..7236d9e62 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0032_where_for.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0032_where_for.txt
@@ -25,43 +25,48 @@ SOURCE_FILE@[0; 116)
25 IDENT@[39; 42) "SER" 25 IDENT@[39; 42) "SER"
26 COLON@[42; 43) 26 COLON@[42; 43)
27 WHITESPACE@[43; 44) 27 WHITESPACE@[43; 44)
28 PATH_TYPE@[44; 111) 28 TYPE_BOUND_LIST@[44; 111)
29 PATH@[44; 53) 29 TYPE_BOUND@[44; 53)
30 PATH_SEGMENT@[44; 53) 30 PATH_TYPE@[44; 53)
31 NAME_REF@[44; 53) 31 PATH@[44; 53)
32 IDENT@[44; 53) "Serialize" 32 PATH_SEGMENT@[44; 53)
33 NAME_REF@[44; 53)
34 IDENT@[44; 53) "Serialize"
33 WHITESPACE@[53; 54) 35 WHITESPACE@[53; 54)
34 PLUS@[54; 55) 36 PLUS@[54; 55)
35 WHITESPACE@[55; 56) 37 WHITESPACE@[55; 56)
36 FOR_TYPE@[56; 81) 38 TYPE_BOUND@[56; 81)
37 FOR_KW@[56; 59) 39 FOR_TYPE@[56; 81)
38 TYPE_PARAM_LIST@[59; 64) 40 FOR_KW@[56; 59)
39 L_ANGLE@[59; 60) 41 TYPE_PARAM_LIST@[59; 64)
40 LIFETIME_PARAM@[60; 63) 42 L_ANGLE@[59; 60)
41 LIFETIME@[60; 63) "'de" 43 LIFETIME_PARAM@[60; 63)
42 R_ANGLE@[63; 64) 44 LIFETIME@[60; 63) "'de"
43 WHITESPACE@[64; 65) 45 R_ANGLE@[63; 64)
44 PATH_TYPE@[65; 81) 46 WHITESPACE@[64; 65)
45 PATH@[65; 81) 47 PATH_TYPE@[65; 81)
46 PATH_SEGMENT@[65; 81) 48 PATH@[65; 81)
47 NAME_REF@[65; 76) 49 PATH_SEGMENT@[65; 81)
48 IDENT@[65; 76) "Deserialize" 50 NAME_REF@[65; 76)
49 TYPE_ARG_LIST@[76; 81) 51 IDENT@[65; 76) "Deserialize"
50 L_ANGLE@[76; 77) 52 TYPE_ARG_LIST@[76; 81)
51 LIFETIME_ARG@[77; 80) 53 L_ANGLE@[76; 77)
52 LIFETIME@[77; 80) "'de" 54 LIFETIME_ARG@[77; 80)
53 R_ANGLE@[80; 81) 55 LIFETIME@[77; 80) "'de"
56 R_ANGLE@[80; 81)
54 WHITESPACE@[81; 82) 57 WHITESPACE@[81; 82)
55 PLUS@[82; 83) 58 PLUS@[82; 83)
56 WHITESPACE@[83; 84) 59 WHITESPACE@[83; 84)
57 PATH_TYPE@[84; 111) 60 TYPE_BOUND@[84; 93)
58 PATH@[84; 93) 61 PATH_TYPE@[84; 93)
59 PATH_SEGMENT@[84; 93) 62 PATH@[84; 93)
60 NAME_REF@[84; 93) 63 PATH_SEGMENT@[84; 93)
61 IDENT@[84; 93) "PartialEq" 64 NAME_REF@[84; 93)
62 WHITESPACE@[93; 94) 65 IDENT@[84; 93) "PartialEq"
63 PLUS@[94; 95) 66 WHITESPACE@[93; 94)
64 WHITESPACE@[95; 96) 67 PLUS@[94; 95)
68 WHITESPACE@[95; 96)
69 TYPE_BOUND@[96; 111)
65 PATH_TYPE@[96; 111) 70 PATH_TYPE@[96; 111)
66 PATH@[96; 111) 71 PATH@[96; 111)
67 PATH@[96; 104) 72 PATH@[96; 104)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt b/crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt
index f3987c3b7..580baaac5 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt
@@ -1694,21 +1694,23 @@ SOURCE_FILE@[0; 3813)
1694 IMPL_TRAIT_TYPE@[3063; 3083) 1694 IMPL_TRAIT_TYPE@[3063; 3083)
1695 IMPL_KW@[3063; 3067) 1695 IMPL_KW@[3063; 3067)
1696 WHITESPACE@[3067; 3068) 1696 WHITESPACE@[3067; 3068)
1697 PATH_TYPE@[3068; 3083) 1697 TYPE_BOUND_LIST@[3068; 3083)
1698 PATH@[3068; 3083) 1698 TYPE_BOUND@[3068; 3083)
1699 PATH@[3068; 3076) 1699 PATH_TYPE@[3068; 3083)
1700 PATH@[3068; 3071) 1700 PATH@[3068; 3083)
1701 PATH_SEGMENT@[3068; 3071) 1701 PATH@[3068; 3076)
1702 NAME_REF@[3068; 3071) 1702 PATH@[3068; 3071)
1703 IDENT@[3068; 3071) "std" 1703 PATH_SEGMENT@[3068; 3071)
1704 COLONCOLON@[3071; 3073) 1704 NAME_REF@[3068; 3071)
1705 PATH_SEGMENT@[3073; 3076) 1705 IDENT@[3068; 3071) "std"
1706 NAME_REF@[3073; 3076) 1706 COLONCOLON@[3071; 3073)
1707 IDENT@[3073; 3076) "fmt" 1707 PATH_SEGMENT@[3073; 3076)
1708 COLONCOLON@[3076; 3078) 1708 NAME_REF@[3073; 3076)
1709 PATH_SEGMENT@[3078; 3083) 1709 IDENT@[3073; 3076) "fmt"
1710 NAME_REF@[3078; 3083) 1710 COLONCOLON@[3076; 3078)
1711 IDENT@[3078; 3083) "Debug" 1711 PATH_SEGMENT@[3078; 3083)
1712 NAME_REF@[3078; 3083)
1713 IDENT@[3078; 3083) "Debug"
1712 WHITESPACE@[3083; 3084) 1714 WHITESPACE@[3083; 3084)
1713 BLOCK@[3084; 3514) 1715 BLOCK@[3084; 3514)
1714 L_CURLY@[3084; 3085) 1716 L_CURLY@[3084; 3085)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt b/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt
index 208e5e51c..93e26aaf6 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt
@@ -16,11 +16,13 @@ SOURCE_FILE@[0; 157)
16 IDENT@[73; 74) "S" 16 IDENT@[73; 74) "S"
17 COLON@[74; 75) 17 COLON@[74; 75)
18 WHITESPACE@[75; 76) 18 WHITESPACE@[75; 76)
19 PATH_TYPE@[76; 84) 19 TYPE_BOUND_LIST@[76; 84)
20 PATH@[76; 84) 20 TYPE_BOUND@[76; 84)
21 PATH_SEGMENT@[76; 84) 21 PATH_TYPE@[76; 84)
22 NAME_REF@[76; 84) 22 PATH@[76; 84)
23 IDENT@[76; 84) "Iterator" 23 PATH_SEGMENT@[76; 84)
24 NAME_REF@[76; 84)
25 IDENT@[76; 84) "Iterator"
24 R_ANGLE@[84; 85) 26 R_ANGLE@[84; 85)
25 PARAM_LIST@[85; 87) 27 PARAM_LIST@[85; 87)
26 L_PAREN@[85; 86) 28 L_PAREN@[85; 86)
@@ -64,11 +66,13 @@ SOURCE_FILE@[0; 157)
64 IDENT@[125; 129) "Item" 66 IDENT@[125; 129) "Item"
65 COLON@[129; 130) 67 COLON@[129; 130)
66 WHITESPACE@[130; 131) 68 WHITESPACE@[130; 131)
67 PATH_TYPE@[131; 133) 69 TYPE_BOUND_LIST@[131; 133)
68 PATH@[131; 133) 70 TYPE_BOUND@[131; 133)
69 PATH_SEGMENT@[131; 133) 71 PATH_TYPE@[131; 133)
70 NAME_REF@[131; 133) 72 PATH@[131; 133)
71 IDENT@[131; 133) "Eq" 73 PATH_SEGMENT@[131; 133)
74 NAME_REF@[131; 133)
75 IDENT@[131; 133) "Eq"
72 COMMA@[133; 134) 76 COMMA@[133; 134)
73 WHITESPACE@[134; 135) 77 WHITESPACE@[134; 135)
74 BLOCK@[135; 156) 78 BLOCK@[135; 156)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt
index 4842e9b90..fe3fca5cd 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt
@@ -29,11 +29,13 @@ SOURCE_FILE@[0; 34)
29 R_PAREN@[25; 26) 29 R_PAREN@[25; 26)
30 COLON@[26; 27) 30 COLON@[26; 27)
31 WHITESPACE@[27; 28) 31 WHITESPACE@[27; 28)
32 PATH_TYPE@[28; 31) 32 TYPE_BOUND_LIST@[28; 31)
33 PATH@[28; 31) 33 TYPE_BOUND@[28; 31)
34 PATH_SEGMENT@[28; 31) 34 PATH_TYPE@[28; 31)
35 NAME_REF@[28; 31) 35 PATH@[28; 31)
36 IDENT@[28; 31) "Foo" 36 PATH_SEGMENT@[28; 31)
37 NAME_REF@[28; 31)
38 IDENT@[28; 31) "Foo"
37 WHITESPACE@[31; 32) 39 WHITESPACE@[31; 32)
38 BLOCK@[32; 34) 40 BLOCK@[32; 34)
39 L_CURLY@[32; 33) 41 L_CURLY@[32; 33)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0045_block_inner_attrs.txt b/crates/ra_syntax/tests/data/parser/ok/0045_block_inner_attrs.txt
index a1ba645ef..eba587f18 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0045_block_inner_attrs.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0045_block_inner_attrs.txt
@@ -116,32 +116,34 @@ SOURCE_FILE@[0; 686)
116 IMPL_TRAIT_TYPE@[576; 600) 116 IMPL_TRAIT_TYPE@[576; 600)
117 IMPL_KW@[576; 580) 117 IMPL_KW@[576; 580)
118 WHITESPACE@[580; 581) 118 WHITESPACE@[580; 581)
119 PATH_TYPE@[581; 600) 119 TYPE_BOUND_LIST@[581; 600)
120 PATH@[581; 600) 120 TYPE_BOUND@[581; 600)
121 PATH_SEGMENT@[581; 600) 121 PATH_TYPE@[581; 600)
122 NAME_REF@[581; 583) 122 PATH@[581; 600)
123 IDENT@[581; 583) "Fn" 123 PATH_SEGMENT@[581; 600)
124 PARAM_LIST@[583; 585) 124 NAME_REF@[581; 583)
125 L_PAREN@[583; 584) 125 IDENT@[581; 583) "Fn"
126 R_PAREN@[584; 585) 126 PARAM_LIST@[583; 585)
127 WHITESPACE@[585; 586) 127 L_PAREN@[583; 584)
128 RET_TYPE@[586; 600) 128 R_PAREN@[584; 585)
129 THIN_ARROW@[586; 588) 129 WHITESPACE@[585; 586)
130 WHITESPACE@[588; 589) 130 RET_TYPE@[586; 600)
131 PATH_TYPE@[589; 600) 131 THIN_ARROW@[586; 588)
132 PATH@[589; 600) 132 WHITESPACE@[588; 589)
133 PATH_SEGMENT@[589; 600) 133 PATH_TYPE@[589; 600)
134 NAME_REF@[589; 594) 134 PATH@[589; 600)
135 IDENT@[589; 594) "Event" 135 PATH_SEGMENT@[589; 600)
136 TYPE_ARG_LIST@[594; 600) 136 NAME_REF@[589; 594)
137 L_ANGLE@[594; 595) 137 IDENT@[589; 594) "Event"
138 TYPE_ARG@[595; 599) 138 TYPE_ARG_LIST@[594; 600)
139 PATH_TYPE@[595; 599) 139 L_ANGLE@[594; 595)
140 PATH@[595; 599) 140 TYPE_ARG@[595; 599)
141 PATH_SEGMENT@[595; 599) 141 PATH_TYPE@[595; 599)
142 NAME_REF@[595; 599) 142 PATH@[595; 599)
143 IDENT@[595; 599) "Self" 143 PATH_SEGMENT@[595; 599)
144 R_ANGLE@[599; 600) 144 NAME_REF@[595; 599)
145 IDENT@[595; 599) "Self"
146 R_ANGLE@[599; 600)
145 R_PAREN@[600; 601) 147 R_PAREN@[600; 601)
146 WHITESPACE@[601; 602) 148 WHITESPACE@[601; 602)
147 BLOCK@[602; 683) 149 BLOCK@[602; 683)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0049_async_block.rs b/crates/ra_syntax/tests/data/parser/ok/0049_async_block.rs
new file mode 100644
index 000000000..4781b3225
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0049_async_block.rs
@@ -0,0 +1,5 @@
1fn foo() {
2 async {};
3 async move {};
4}
5
diff --git a/crates/ra_syntax/tests/data/parser/ok/0049_async_block.txt b/crates/ra_syntax/tests/data/parser/ok/0049_async_block.txt
new file mode 100644
index 000000000..6212e1130
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0049_async_block.txt
@@ -0,0 +1,35 @@
1SOURCE_FILE@[0; 47)
2 FN_DEF@[0; 45)
3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3)
5 NAME@[3; 6)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 8)
8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9)
11 BLOCK@[9; 45)
12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 15)
14 EXPR_STMT@[15; 24)
15 BLOCK_EXPR@[15; 23)
16 ASYNC_KW@[15; 20)
17 WHITESPACE@[20; 21)
18 BLOCK@[21; 23)
19 L_CURLY@[21; 22)
20 R_CURLY@[22; 23)
21 SEMI@[23; 24)
22 WHITESPACE@[24; 29)
23 EXPR_STMT@[29; 43)
24 BLOCK_EXPR@[29; 42)
25 ASYNC_KW@[29; 34)
26 WHITESPACE@[34; 35)
27 MOVE_KW@[35; 39)
28 WHITESPACE@[39; 40)
29 BLOCK@[40; 42)
30 L_CURLY@[40; 41)
31 R_CURLY@[41; 42)
32 SEMI@[42; 43)
33 WHITESPACE@[43; 44)
34 R_CURLY@[44; 45)
35 WHITESPACE@[45; 47)