aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r--crates/ra_syntax/src/ast.rs70
-rw-r--r--crates/ra_syntax/src/ast/generated.rs166
-rw-r--r--crates/ra_syntax/src/grammar.ron28
-rw-r--r--crates/ra_syntax/src/grammar/items.rs4
-rw-r--r--crates/ra_syntax/src/grammar/items/traits.rs6
-rw-r--r--crates/ra_syntax/src/parser_api.rs21
-rw-r--r--crates/ra_syntax/src/parser_impl.rs71
-rw-r--r--crates/ra_syntax/src/parser_impl/event.rs53
-rw-r--r--crates/ra_syntax/src/parser_impl/input.rs27
-rw-r--r--crates/ra_syntax/src/reparsing.rs2
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs4
-rw-r--r--crates/ra_syntax/src/yellow/builder.rs4
-rw-r--r--crates/ra_syntax/src/yellow/syntax_text.rs24
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0018_incomplete_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0022_bad_exprs.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0026_imp_recovery.txt4
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_block_neg.rs (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_block_neg.txt (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.txt)2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_block.rs (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_block.txt (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.txt)2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0087_unsafe_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0097_default_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0037_mod.rs5
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0037_mod.txt16
31 files changed, 426 insertions, 115 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 3e948800e..c10169d90 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -30,6 +30,12 @@ pub trait NameOwner<'a>: AstNode<'a> {
30 } 30 }
31} 31}
32 32
33pub trait VisibilityOwner<'a>: AstNode<'a> {
34 fn visibility(self) -> Option<Visibility<'a>> {
35 child_opt(self)
36 }
37}
38
33pub trait LoopBodyOwner<'a>: AstNode<'a> { 39pub trait LoopBodyOwner<'a>: AstNode<'a> {
34 fn loop_body(self) -> Option<Block<'a>> { 40 fn loop_body(self) -> Option<Block<'a>> {
35 child_opt(self) 41 child_opt(self)
@@ -109,6 +115,7 @@ pub trait DocCommentsOwner<'a>: AstNode<'a> {
109 /// That is, strips leading `///` and joins lines 115 /// That is, strips leading `///` and joins lines
110 fn doc_comment_text(self) -> RustString { 116 fn doc_comment_text(self) -> RustString {
111 self.doc_comments() 117 self.doc_comments()
118 .filter(|comment| comment.is_doc_comment())
112 .map(|comment| { 119 .map(|comment| {
113 let prefix = comment.prefix(); 120 let prefix = comment.prefix();
114 let trimmed = comment 121 let trimmed = comment
@@ -200,6 +207,10 @@ impl<'a> Comment<'a> {
200 } 207 }
201 } 208 }
202 209
210 pub fn is_doc_comment(&self) -> bool {
211 self.flavor().is_doc_comment()
212 }
213
203 pub fn prefix(&self) -> &'static str { 214 pub fn prefix(&self) -> &'static str {
204 self.flavor().prefix() 215 self.flavor().prefix()
205 } 216 }
@@ -231,6 +242,13 @@ impl CommentFlavor {
231 Multiline => "/*", 242 Multiline => "/*",
232 } 243 }
233 } 244 }
245
246 pub fn is_doc_comment(&self) -> bool {
247 match self {
248 CommentFlavor::Doc | CommentFlavor::ModuleDoc => true,
249 _ => false,
250 }
251 }
234} 252}
235 253
236impl<'a> Whitespace<'a> { 254impl<'a> Whitespace<'a> {
@@ -261,7 +279,7 @@ impl<'a> NameRef<'a> {
261 } 279 }
262} 280}
263 281
264impl<'a> ImplItem<'a> { 282impl<'a> ImplBlock<'a> {
265 pub fn target_type(self) -> Option<TypeRef<'a>> { 283 pub fn target_type(self) -> Option<TypeRef<'a>> {
266 match self.target() { 284 match self.target() {
267 (Some(t), None) | (_, Some(t)) => Some(t), 285 (Some(t), None) | (_, Some(t)) => Some(t),
@@ -345,6 +363,12 @@ impl<'a> PathSegment<'a> {
345 } 363 }
346} 364}
347 365
366impl<'a> Path<'a> {
367 pub fn parent_path(self) -> Option<Path<'a>> {
368 self.syntax().parent().and_then(Path::cast)
369 }
370}
371
348impl<'a> UseTree<'a> { 372impl<'a> UseTree<'a> {
349 pub fn has_star(self) -> bool { 373 pub fn has_star(self) -> bool {
350 self.syntax().children().any(|it| it.kind() == STAR) 374 self.syntax().children().any(|it| it.kind() == STAR)
@@ -463,3 +487,47 @@ impl<'a> PrefixExpr<'a> {
463 } 487 }
464 } 488 }
465} 489}
490
491#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
492pub enum SelfParamFlavor {
493 /// self
494 Owned,
495 /// &self
496 Ref,
497 /// &mut self
498 MutRef,
499}
500
501impl<'a> SelfParam<'a> {
502 pub fn flavor(&self) -> SelfParamFlavor {
503 let borrowed = self.syntax().children().any(|n| n.kind() == AMP);
504 if borrowed {
505 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
506 if self
507 .syntax()
508 .children()
509 .skip_while(|n| n.kind() != AMP)
510 .any(|n| n.kind() == MUT_KW)
511 {
512 SelfParamFlavor::MutRef
513 } else {
514 SelfParamFlavor::Ref
515 }
516 } else {
517 SelfParamFlavor::Owned
518 }
519 }
520}
521
522#[test]
523fn test_doc_comment_of_items() {
524 let file = SourceFileNode::parse(
525 r#"
526 //! doc
527 // non-doc
528 mod foo {}
529 "#,
530 );
531 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
532 assert_eq!("doc", module.doc_comment_text());
533}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index c5ac90a62..7df6a9c46 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -695,6 +695,7 @@ impl<R: TreeRoot<RaTypes>> ConstDefNode<R> {
695} 695}
696 696
697 697
698impl<'a> ast::VisibilityOwner<'a> for ConstDef<'a> {}
698impl<'a> ast::NameOwner<'a> for ConstDef<'a> {} 699impl<'a> ast::NameOwner<'a> for ConstDef<'a> {}
699impl<'a> ast::TypeParamsOwner<'a> for ConstDef<'a> {} 700impl<'a> ast::TypeParamsOwner<'a> for ConstDef<'a> {}
700impl<'a> ast::AttrsOwner<'a> for ConstDef<'a> {} 701impl<'a> ast::AttrsOwner<'a> for ConstDef<'a> {}
@@ -810,6 +811,7 @@ impl<R: TreeRoot<RaTypes>> EnumDefNode<R> {
810} 811}
811 812
812 813
814impl<'a> ast::VisibilityOwner<'a> for EnumDef<'a> {}
813impl<'a> ast::NameOwner<'a> for EnumDef<'a> {} 815impl<'a> ast::NameOwner<'a> for EnumDef<'a> {}
814impl<'a> ast::TypeParamsOwner<'a> for EnumDef<'a> {} 816impl<'a> ast::TypeParamsOwner<'a> for EnumDef<'a> {}
815impl<'a> ast::AttrsOwner<'a> for EnumDef<'a> {} 817impl<'a> ast::AttrsOwner<'a> for EnumDef<'a> {}
@@ -1213,6 +1215,7 @@ impl<R: TreeRoot<RaTypes>> FnDefNode<R> {
1213} 1215}
1214 1216
1215 1217
1218impl<'a> ast::VisibilityOwner<'a> for FnDef<'a> {}
1216impl<'a> ast::NameOwner<'a> for FnDef<'a> {} 1219impl<'a> ast::NameOwner<'a> for FnDef<'a> {}
1217impl<'a> ast::TypeParamsOwner<'a> for FnDef<'a> {} 1220impl<'a> ast::TypeParamsOwner<'a> for FnDef<'a> {}
1218impl<'a> ast::AttrsOwner<'a> for FnDef<'a> {} 1221impl<'a> ast::AttrsOwner<'a> for FnDef<'a> {}
@@ -1404,40 +1407,72 @@ impl<'a> IfExpr<'a> {
1404 } 1407 }
1405} 1408}
1406 1409
1407// ImplItem 1410// ImplBlock
1408#[derive(Debug, Clone, Copy,)] 1411#[derive(Debug, Clone, Copy,)]
1409pub struct ImplItemNode<R: TreeRoot<RaTypes> = OwnedRoot> { 1412pub struct ImplBlockNode<R: TreeRoot<RaTypes> = OwnedRoot> {
1410 pub(crate) syntax: SyntaxNode<R>, 1413 pub(crate) syntax: SyntaxNode<R>,
1411} 1414}
1412pub type ImplItem<'a> = ImplItemNode<RefRoot<'a>>; 1415pub type ImplBlock<'a> = ImplBlockNode<RefRoot<'a>>;
1413 1416
1414impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<ImplItemNode<R1>> for ImplItemNode<R2> { 1417impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<ImplBlockNode<R1>> for ImplBlockNode<R2> {
1415 fn eq(&self, other: &ImplItemNode<R1>) -> bool { self.syntax == other.syntax } 1418 fn eq(&self, other: &ImplBlockNode<R1>) -> bool { self.syntax == other.syntax }
1416} 1419}
1417impl<R: TreeRoot<RaTypes>> Eq for ImplItemNode<R> {} 1420impl<R: TreeRoot<RaTypes>> Eq for ImplBlockNode<R> {}
1418impl<R: TreeRoot<RaTypes>> Hash for ImplItemNode<R> { 1421impl<R: TreeRoot<RaTypes>> Hash for ImplBlockNode<R> {
1419 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) } 1422 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
1420} 1423}
1421 1424
1422impl<'a> AstNode<'a> for ImplItem<'a> { 1425impl<'a> AstNode<'a> for ImplBlock<'a> {
1423 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> { 1426 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1424 match syntax.kind() { 1427 match syntax.kind() {
1425 IMPL_ITEM => Some(ImplItem { syntax }), 1428 IMPL_BLOCK => Some(ImplBlock { syntax }),
1426 _ => None, 1429 _ => None,
1427 } 1430 }
1428 } 1431 }
1429 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 1432 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1430} 1433}
1431 1434
1432impl<R: TreeRoot<RaTypes>> ImplItemNode<R> { 1435impl<R: TreeRoot<RaTypes>> ImplBlockNode<R> {
1433 pub fn borrowed(&self) -> ImplItem { 1436 pub fn borrowed(&self) -> ImplBlock {
1434 ImplItemNode { syntax: self.syntax.borrowed() } 1437 ImplBlockNode { syntax: self.syntax.borrowed() }
1438 }
1439 pub fn owned(&self) -> ImplBlockNode {
1440 ImplBlockNode { syntax: self.syntax.owned() }
1435 } 1441 }
1436 pub fn owned(&self) -> ImplItemNode { 1442}
1437 ImplItemNode { syntax: self.syntax.owned() } 1443
1444
1445impl<'a> ImplBlock<'a> {
1446 pub fn item_list(self) -> Option<ItemList<'a>> {
1447 super::child_opt(self)
1438 } 1448 }
1439} 1449}
1440 1450
1451// ImplItem
1452#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1453pub enum ImplItem<'a> {
1454 FnDef(FnDef<'a>),
1455 TypeDef(TypeDef<'a>),
1456 ConstDef(ConstDef<'a>),
1457}
1458
1459impl<'a> AstNode<'a> for ImplItem<'a> {
1460 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1461 match syntax.kind() {
1462 FN_DEF => Some(ImplItem::FnDef(FnDef { syntax })),
1463 TYPE_DEF => Some(ImplItem::TypeDef(TypeDef { syntax })),
1464 CONST_DEF => Some(ImplItem::ConstDef(ConstDef { syntax })),
1465 _ => None,
1466 }
1467 }
1468 fn syntax(self) -> SyntaxNodeRef<'a> {
1469 match self {
1470 ImplItem::FnDef(inner) => inner.syntax(),
1471 ImplItem::TypeDef(inner) => inner.syntax(),
1472 ImplItem::ConstDef(inner) => inner.syntax(),
1473 }
1474 }
1475}
1441 1476
1442impl<'a> ImplItem<'a> {} 1477impl<'a> ImplItem<'a> {}
1443 1478
@@ -1552,7 +1587,11 @@ impl<R: TreeRoot<RaTypes>> ItemListNode<R> {
1552 1587
1553impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {} 1588impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {}
1554impl<'a> ast::ModuleItemOwner<'a> for ItemList<'a> {} 1589impl<'a> ast::ModuleItemOwner<'a> for ItemList<'a> {}
1555impl<'a> ItemList<'a> {} 1590impl<'a> ItemList<'a> {
1591 pub fn impl_items(self) -> impl Iterator<Item = ImplItem<'a>> + 'a {
1592 super::children(self)
1593 }
1594}
1556 1595
1557// Label 1596// Label
1558#[derive(Debug, Clone, Copy,)] 1597#[derive(Debug, Clone, Copy,)]
@@ -2136,6 +2175,7 @@ impl<R: TreeRoot<RaTypes>> ModuleNode<R> {
2136} 2175}
2137 2176
2138 2177
2178impl<'a> ast::VisibilityOwner<'a> for Module<'a> {}
2139impl<'a> ast::NameOwner<'a> for Module<'a> {} 2179impl<'a> ast::NameOwner<'a> for Module<'a> {}
2140impl<'a> ast::AttrsOwner<'a> for Module<'a> {} 2180impl<'a> ast::AttrsOwner<'a> for Module<'a> {}
2141impl<'a> ast::DocCommentsOwner<'a> for Module<'a> {} 2181impl<'a> ast::DocCommentsOwner<'a> for Module<'a> {}
@@ -2153,7 +2193,7 @@ pub enum ModuleItem<'a> {
2153 FnDef(FnDef<'a>), 2193 FnDef(FnDef<'a>),
2154 TraitDef(TraitDef<'a>), 2194 TraitDef(TraitDef<'a>),
2155 TypeDef(TypeDef<'a>), 2195 TypeDef(TypeDef<'a>),
2156 ImplItem(ImplItem<'a>), 2196 ImplBlock(ImplBlock<'a>),
2157 UseItem(UseItem<'a>), 2197 UseItem(UseItem<'a>),
2158 ExternCrateItem(ExternCrateItem<'a>), 2198 ExternCrateItem(ExternCrateItem<'a>),
2159 ConstDef(ConstDef<'a>), 2199 ConstDef(ConstDef<'a>),
@@ -2169,7 +2209,7 @@ impl<'a> AstNode<'a> for ModuleItem<'a> {
2169 FN_DEF => Some(ModuleItem::FnDef(FnDef { syntax })), 2209 FN_DEF => Some(ModuleItem::FnDef(FnDef { syntax })),
2170 TRAIT_DEF => Some(ModuleItem::TraitDef(TraitDef { syntax })), 2210 TRAIT_DEF => Some(ModuleItem::TraitDef(TraitDef { syntax })),
2171 TYPE_DEF => Some(ModuleItem::TypeDef(TypeDef { syntax })), 2211 TYPE_DEF => Some(ModuleItem::TypeDef(TypeDef { syntax })),
2172 IMPL_ITEM => Some(ModuleItem::ImplItem(ImplItem { syntax })), 2212 IMPL_BLOCK => Some(ModuleItem::ImplBlock(ImplBlock { syntax })),
2173 USE_ITEM => Some(ModuleItem::UseItem(UseItem { syntax })), 2213 USE_ITEM => Some(ModuleItem::UseItem(UseItem { syntax })),
2174 EXTERN_CRATE_ITEM => Some(ModuleItem::ExternCrateItem(ExternCrateItem { syntax })), 2214 EXTERN_CRATE_ITEM => Some(ModuleItem::ExternCrateItem(ExternCrateItem { syntax })),
2175 CONST_DEF => Some(ModuleItem::ConstDef(ConstDef { syntax })), 2215 CONST_DEF => Some(ModuleItem::ConstDef(ConstDef { syntax })),
@@ -2185,7 +2225,7 @@ impl<'a> AstNode<'a> for ModuleItem<'a> {
2185 ModuleItem::FnDef(inner) => inner.syntax(), 2225 ModuleItem::FnDef(inner) => inner.syntax(),
2186 ModuleItem::TraitDef(inner) => inner.syntax(), 2226 ModuleItem::TraitDef(inner) => inner.syntax(),
2187 ModuleItem::TypeDef(inner) => inner.syntax(), 2227 ModuleItem::TypeDef(inner) => inner.syntax(),
2188 ModuleItem::ImplItem(inner) => inner.syntax(), 2228 ModuleItem::ImplBlock(inner) => inner.syntax(),
2189 ModuleItem::UseItem(inner) => inner.syntax(), 2229 ModuleItem::UseItem(inner) => inner.syntax(),
2190 ModuleItem::ExternCrateItem(inner) => inner.syntax(), 2230 ModuleItem::ExternCrateItem(inner) => inner.syntax(),
2191 ModuleItem::ConstDef(inner) => inner.syntax(), 2231 ModuleItem::ConstDef(inner) => inner.syntax(),
@@ -2351,6 +2391,7 @@ impl<R: TreeRoot<RaTypes>> NamedFieldDefNode<R> {
2351} 2391}
2352 2392
2353 2393
2394impl<'a> ast::VisibilityOwner<'a> for NamedFieldDef<'a> {}
2354impl<'a> ast::NameOwner<'a> for NamedFieldDef<'a> {} 2395impl<'a> ast::NameOwner<'a> for NamedFieldDef<'a> {}
2355impl<'a> ast::AttrsOwner<'a> for NamedFieldDef<'a> {} 2396impl<'a> ast::AttrsOwner<'a> for NamedFieldDef<'a> {}
2356impl<'a> NamedFieldDef<'a> { 2397impl<'a> NamedFieldDef<'a> {
@@ -3082,6 +3123,7 @@ impl<R: TreeRoot<RaTypes>> PosFieldNode<R> {
3082} 3123}
3083 3124
3084 3125
3126impl<'a> ast::VisibilityOwner<'a> for PosField<'a> {}
3085impl<'a> ast::AttrsOwner<'a> for PosField<'a> {} 3127impl<'a> ast::AttrsOwner<'a> for PosField<'a> {}
3086impl<'a> PosField<'a> { 3128impl<'a> PosField<'a> {
3087 pub fn type_ref(self) -> Option<TypeRef<'a>> { 3129 pub fn type_ref(self) -> Option<TypeRef<'a>> {
@@ -3446,6 +3488,43 @@ impl<'a> ReturnExpr<'a> {
3446 } 3488 }
3447} 3489}
3448 3490
3491// SelfKw
3492#[derive(Debug, Clone, Copy,)]
3493pub struct SelfKwNode<R: TreeRoot<RaTypes> = OwnedRoot> {
3494 pub(crate) syntax: SyntaxNode<R>,
3495}
3496pub type SelfKw<'a> = SelfKwNode<RefRoot<'a>>;
3497
3498impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<SelfKwNode<R1>> for SelfKwNode<R2> {
3499 fn eq(&self, other: &SelfKwNode<R1>) -> bool { self.syntax == other.syntax }
3500}
3501impl<R: TreeRoot<RaTypes>> Eq for SelfKwNode<R> {}
3502impl<R: TreeRoot<RaTypes>> Hash for SelfKwNode<R> {
3503 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
3504}
3505
3506impl<'a> AstNode<'a> for SelfKw<'a> {
3507 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
3508 match syntax.kind() {
3509 SELF_KW => Some(SelfKw { syntax }),
3510 _ => None,
3511 }
3512 }
3513 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
3514}
3515
3516impl<R: TreeRoot<RaTypes>> SelfKwNode<R> {
3517 pub fn borrowed(&self) -> SelfKw {
3518 SelfKwNode { syntax: self.syntax.borrowed() }
3519 }
3520 pub fn owned(&self) -> SelfKwNode {
3521 SelfKwNode { syntax: self.syntax.owned() }
3522 }
3523}
3524
3525
3526impl<'a> SelfKw<'a> {}
3527
3449// SelfParam 3528// SelfParam
3450#[derive(Debug, Clone, Copy,)] 3529#[derive(Debug, Clone, Copy,)]
3451pub struct SelfParamNode<R: TreeRoot<RaTypes> = OwnedRoot> { 3530pub struct SelfParamNode<R: TreeRoot<RaTypes> = OwnedRoot> {
@@ -3481,7 +3560,15 @@ impl<R: TreeRoot<RaTypes>> SelfParamNode<R> {
3481} 3560}
3482 3561
3483 3562
3484impl<'a> SelfParam<'a> {} 3563impl<'a> SelfParam<'a> {
3564 pub fn type_ref(self) -> Option<TypeRef<'a>> {
3565 super::child_opt(self)
3566 }
3567
3568 pub fn self_kw(self) -> Option<SelfKw<'a>> {
3569 super::child_opt(self)
3570 }
3571}
3485 3572
3486// SlicePat 3573// SlicePat
3487#[derive(Debug, Clone, Copy,)] 3574#[derive(Debug, Clone, Copy,)]
@@ -3639,6 +3726,7 @@ impl<R: TreeRoot<RaTypes>> StaticDefNode<R> {
3639} 3726}
3640 3727
3641 3728
3729impl<'a> ast::VisibilityOwner<'a> for StaticDef<'a> {}
3642impl<'a> ast::NameOwner<'a> for StaticDef<'a> {} 3730impl<'a> ast::NameOwner<'a> for StaticDef<'a> {}
3643impl<'a> ast::TypeParamsOwner<'a> for StaticDef<'a> {} 3731impl<'a> ast::TypeParamsOwner<'a> for StaticDef<'a> {}
3644impl<'a> ast::AttrsOwner<'a> for StaticDef<'a> {} 3732impl<'a> ast::AttrsOwner<'a> for StaticDef<'a> {}
@@ -3742,6 +3830,7 @@ impl<R: TreeRoot<RaTypes>> StructDefNode<R> {
3742} 3830}
3743 3831
3744 3832
3833impl<'a> ast::VisibilityOwner<'a> for StructDef<'a> {}
3745impl<'a> ast::NameOwner<'a> for StructDef<'a> {} 3834impl<'a> ast::NameOwner<'a> for StructDef<'a> {}
3746impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {} 3835impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {}
3747impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {} 3836impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {}
@@ -3902,6 +3991,7 @@ impl<R: TreeRoot<RaTypes>> TraitDefNode<R> {
3902} 3991}
3903 3992
3904 3993
3994impl<'a> ast::VisibilityOwner<'a> for TraitDef<'a> {}
3905impl<'a> ast::NameOwner<'a> for TraitDef<'a> {} 3995impl<'a> ast::NameOwner<'a> for TraitDef<'a> {}
3906impl<'a> ast::AttrsOwner<'a> for TraitDef<'a> {} 3996impl<'a> ast::AttrsOwner<'a> for TraitDef<'a> {}
3907impl<'a> ast::DocCommentsOwner<'a> for TraitDef<'a> {} 3997impl<'a> ast::DocCommentsOwner<'a> for TraitDef<'a> {}
@@ -4135,6 +4225,7 @@ impl<R: TreeRoot<RaTypes>> TypeDefNode<R> {
4135} 4225}
4136 4226
4137 4227
4228impl<'a> ast::VisibilityOwner<'a> for TypeDef<'a> {}
4138impl<'a> ast::NameOwner<'a> for TypeDef<'a> {} 4229impl<'a> ast::NameOwner<'a> for TypeDef<'a> {}
4139impl<'a> ast::TypeParamsOwner<'a> for TypeDef<'a> {} 4230impl<'a> ast::TypeParamsOwner<'a> for TypeDef<'a> {}
4140impl<'a> ast::AttrsOwner<'a> for TypeDef<'a> {} 4231impl<'a> ast::AttrsOwner<'a> for TypeDef<'a> {}
@@ -4409,6 +4500,43 @@ impl<'a> UseTreeList<'a> {
4409 } 4500 }
4410} 4501}
4411 4502
4503// Visibility
4504#[derive(Debug, Clone, Copy,)]
4505pub struct VisibilityNode<R: TreeRoot<RaTypes> = OwnedRoot> {
4506 pub(crate) syntax: SyntaxNode<R>,
4507}
4508pub type Visibility<'a> = VisibilityNode<RefRoot<'a>>;
4509
4510impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<VisibilityNode<R1>> for VisibilityNode<R2> {
4511 fn eq(&self, other: &VisibilityNode<R1>) -> bool { self.syntax == other.syntax }
4512}
4513impl<R: TreeRoot<RaTypes>> Eq for VisibilityNode<R> {}
4514impl<R: TreeRoot<RaTypes>> Hash for VisibilityNode<R> {
4515 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
4516}
4517
4518impl<'a> AstNode<'a> for Visibility<'a> {
4519 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
4520 match syntax.kind() {
4521 VISIBILITY => Some(Visibility { syntax }),
4522 _ => None,
4523 }
4524 }
4525 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
4526}
4527
4528impl<R: TreeRoot<RaTypes>> VisibilityNode<R> {
4529 pub fn borrowed(&self) -> Visibility {
4530 VisibilityNode { syntax: self.syntax.borrowed() }
4531 }
4532 pub fn owned(&self) -> VisibilityNode {
4533 VisibilityNode { syntax: self.syntax.owned() }
4534 }
4535}
4536
4537
4538impl<'a> Visibility<'a> {}
4539
4412// WhereClause 4540// WhereClause
4413#[derive(Debug, Clone, Copy,)] 4541#[derive(Debug, Clone, Copy,)]
4414pub struct WhereClauseNode<R: TreeRoot<RaTypes> = OwnedRoot> { 4542pub struct WhereClauseNode<R: TreeRoot<RaTypes> = OwnedRoot> {
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index aab4839a9..c55e9e07a 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -128,7 +128,7 @@ Grammar(
128 "STATIC_DEF", 128 "STATIC_DEF",
129 "CONST_DEF", 129 "CONST_DEF",
130 "TRAIT_DEF", 130 "TRAIT_DEF",
131 "IMPL_ITEM", 131 "IMPL_BLOCK",
132 "TYPE_DEF", 132 "TYPE_DEF",
133 "MACRO_CALL", 133 "MACRO_CALL",
134 "TOKEN_TREE", 134 "TOKEN_TREE",
@@ -247,6 +247,7 @@ Grammar(
247 ), 247 ),
248 "FnDef": ( 248 "FnDef": (
249 traits: [ 249 traits: [
250 "VisibilityOwner",
250 "NameOwner", 251 "NameOwner",
251 "TypeParamsOwner", 252 "TypeParamsOwner",
252 "AttrsOwner", 253 "AttrsOwner",
@@ -257,6 +258,7 @@ Grammar(
257 "RetType": (options: ["TypeRef"]), 258 "RetType": (options: ["TypeRef"]),
258 "StructDef": ( 259 "StructDef": (
259 traits: [ 260 traits: [
261 "VisibilityOwner",
260 "NameOwner", 262 "NameOwner",
261 "TypeParamsOwner", 263 "TypeParamsOwner",
262 "AttrsOwner", 264 "AttrsOwner",
@@ -264,10 +266,11 @@ Grammar(
264 ] 266 ]
265 ), 267 ),
266 "NamedFieldDefList": (collections: [["fields", "NamedFieldDef"]]), 268 "NamedFieldDefList": (collections: [["fields", "NamedFieldDef"]]),
267 "NamedFieldDef": ( traits: ["NameOwner", "AttrsOwner"], options: ["TypeRef"] ), 269 "NamedFieldDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner"], options: ["TypeRef"] ),
268 "PosFieldList": (collections: [["fields", "PosField"]]), 270 "PosFieldList": (collections: [["fields", "PosField"]]),
269 "PosField": ( traits: ["AttrsOwner"], options: ["TypeRef"]), 271 "PosField": ( traits: ["VisibilityOwner", "AttrsOwner"], options: ["TypeRef"]),
270 "EnumDef": ( traits: [ 272 "EnumDef": ( traits: [
273 "VisibilityOwner",
271 "NameOwner", 274 "NameOwner",
272 "TypeParamsOwner", 275 "TypeParamsOwner",
273 "AttrsOwner", 276 "AttrsOwner",
@@ -275,33 +278,37 @@ Grammar(
275 ], options: [["variant_list", "EnumVariantList"]] ), 278 ], options: [["variant_list", "EnumVariantList"]] ),
276 "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ), 279 "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ),
277 "EnumVariant": ( traits: ["NameOwner"], options: ["Expr"] ), 280 "EnumVariant": ( traits: ["NameOwner"], options: ["Expr"] ),
278 "TraitDef": ( traits: ["NameOwner", "AttrsOwner", "DocCommentsOwner"] ), 281 "TraitDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner"] ),
279 "Module": ( 282 "Module": (
280 traits: ["NameOwner", "AttrsOwner", "DocCommentsOwner" ], 283 traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ],
281 options: [ "ItemList" ] 284 options: [ "ItemList" ]
282 ), 285 ),
283 "ItemList": ( 286 "ItemList": (
287 collections: [["impl_items", "ImplItem"]],
284 traits: [ "FnDefOwner", "ModuleItemOwner" ], 288 traits: [ "FnDefOwner", "ModuleItemOwner" ],
285 ), 289 ),
286 "ConstDef": ( traits: [ 290 "ConstDef": ( traits: [
291 "VisibilityOwner",
287 "NameOwner", 292 "NameOwner",
288 "TypeParamsOwner", 293 "TypeParamsOwner",
289 "AttrsOwner", 294 "AttrsOwner",
290 "DocCommentsOwner" 295 "DocCommentsOwner"
291 ] ), 296 ] ),
292 "StaticDef": ( traits: [ 297 "StaticDef": ( traits: [
298 "VisibilityOwner",
293 "NameOwner", 299 "NameOwner",
294 "TypeParamsOwner", 300 "TypeParamsOwner",
295 "AttrsOwner", 301 "AttrsOwner",
296 "DocCommentsOwner" 302 "DocCommentsOwner"
297 ] ), 303 ] ),
298 "TypeDef": ( traits: [ 304 "TypeDef": ( traits: [
305 "VisibilityOwner",
299 "NameOwner", 306 "NameOwner",
300 "TypeParamsOwner", 307 "TypeParamsOwner",
301 "AttrsOwner", 308 "AttrsOwner",
302 "DocCommentsOwner" 309 "DocCommentsOwner"
303 ] ), 310 ] ),
304 "ImplItem": (), 311 "ImplBlock": (options: ["ItemList"]),
305 312
306 "ParenType": (options: ["TypeRef"]), 313 "ParenType": (options: ["TypeRef"]),
307 "TupleType": ( collections: [["fields", "TypeRef"]] ), 314 "TupleType": ( collections: [["fields", "TypeRef"]] ),
@@ -342,9 +349,12 @@ Grammar(
342 ], 349 ],
343 ), 350 ),
344 "ModuleItem": ( 351 "ModuleItem": (
345 enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeDef", "ImplItem", 352 enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeDef", "ImplBlock",
346 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ] 353 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ]
347 ), 354 ),
355 "ImplItem": (
356 enum: ["FnDef", "TypeDef", "ConstDef"]
357 ),
348 358
349 "TupleExpr": (), 359 "TupleExpr": (),
350 "ArrayExpr": (), 360 "ArrayExpr": (),
@@ -482,6 +492,7 @@ Grammar(
482 ], 492 ],
483 ), 493 ),
484 494
495 "Visibility": (),
485 "Name": (), 496 "Name": (),
486 "NameRef": (), 497 "NameRef": (),
487 "MacroCall": ( options: [ "TokenTree", "Path" ] ), 498 "MacroCall": ( options: [ "TokenTree", "Path" ] ),
@@ -523,7 +534,8 @@ Grammar(
523 ["params", "Param"] 534 ["params", "Param"]
524 ] 535 ]
525 ), 536 ),
526 "SelfParam": (), 537 "SelfParam": (options: ["TypeRef", "SelfKw"]),
538 "SelfKw": (),
527 "Param": ( 539 "Param": (
528 options: [ "Pat", "TypeRef" ], 540 options: [ "Pat", "TypeRef" ],
529 ), 541 ),
diff --git a/crates/ra_syntax/src/grammar/items.rs b/crates/ra_syntax/src/grammar/items.rs
index aa5fe0777..265e84570 100644
--- a/crates/ra_syntax/src/grammar/items.rs
+++ b/crates/ra_syntax/src/grammar/items.rs
@@ -151,8 +151,8 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
151 // test unsafe_default_impl 151 // test unsafe_default_impl
152 // unsafe default impl Foo {} 152 // unsafe default impl Foo {}
153 IMPL_KW => { 153 IMPL_KW => {
154 traits::impl_item(p); 154 traits::impl_block(p);
155 IMPL_ITEM 155 IMPL_BLOCK
156 } 156 }
157 _ => { 157 _ => {
158 return if has_mods { 158 return if has_mods {
diff --git a/crates/ra_syntax/src/grammar/items/traits.rs b/crates/ra_syntax/src/grammar/items/traits.rs
index d4da8b2f7..0a0621753 100644
--- a/crates/ra_syntax/src/grammar/items/traits.rs
+++ b/crates/ra_syntax/src/grammar/items/traits.rs
@@ -40,9 +40,9 @@ pub(crate) fn trait_item_list(p: &mut Parser) {
40 m.complete(p, ITEM_LIST); 40 m.complete(p, ITEM_LIST);
41} 41}
42 42
43// test impl_item 43// test impl_block
44// impl Foo {} 44// impl Foo {}
45pub(super) fn impl_item(p: &mut Parser) { 45pub(super) fn impl_block(p: &mut Parser) {
46 assert!(p.at(IMPL_KW)); 46 assert!(p.at(IMPL_KW));
47 p.bump(); 47 p.bump();
48 if choose_type_params_over_qpath(p) { 48 if choose_type_params_over_qpath(p) {
@@ -52,7 +52,7 @@ pub(super) fn impl_item(p: &mut Parser) {
52 // TODO: never type 52 // TODO: never type
53 // impl ! {} 53 // impl ! {}
54 54
55 // test impl_item_neg 55 // test impl_block_neg
56 // impl !Send for X {} 56 // impl !Send for X {}
57 p.eat(EXCL); 57 p.eat(EXCL);
58 impl_type(p); 58 impl_type(p);
diff --git a/crates/ra_syntax/src/parser_api.rs b/crates/ra_syntax/src/parser_api.rs
index 02421def1..3487aef85 100644
--- a/crates/ra_syntax/src/parser_api.rs
+++ b/crates/ra_syntax/src/parser_api.rs
@@ -61,7 +61,7 @@ impl<'t> Parser<'t> {
61 Marker::new(self.0.start()) 61 Marker::new(self.0.start())
62 } 62 }
63 63
64 /// Advances the parser by one token. 64 /// Advances the parser by one token unconditionally.
65 pub(crate) fn bump(&mut self) { 65 pub(crate) fn bump(&mut self) {
66 self.0.bump(); 66 self.0.bump();
67 } 67 }
@@ -91,7 +91,7 @@ impl<'t> Parser<'t> {
91 self.0.error(message.into()) 91 self.0.error(message.into())
92 } 92 }
93 93
94 /// Consume the next token if it is `kind`. 94 /// Consume the next token if `kind` matches.
95 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool { 95 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
96 if !self.at(kind) { 96 if !self.at(kind) {
97 return false; 97 return false;
@@ -142,11 +142,13 @@ impl Marker {
142 } 142 }
143 } 143 }
144 144
145 /// Finishes the syntax tree node and assigns `kind` to it. 145 /// Finishes the syntax tree node and assigns `kind` to it,
146 /// and mark the create a `CompletedMarker` for possible future
147 /// operation like `.precede()` to deal with forward_parent.
146 pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { 148 pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
147 self.bomb.defuse(); 149 self.bomb.defuse();
148 p.0.complete(self.pos, kind); 150 p.0.complete(self.pos, kind);
149 CompletedMarker(self.pos, kind) 151 CompletedMarker::new(self.pos, kind)
150 } 152 }
151 153
152 /// Abandons the syntax tree node. All its children 154 /// Abandons the syntax tree node. All its children
@@ -160,13 +162,22 @@ impl Marker {
160pub(crate) struct CompletedMarker(u32, SyntaxKind); 162pub(crate) struct CompletedMarker(u32, SyntaxKind);
161 163
162impl CompletedMarker { 164impl CompletedMarker {
163 /// This one is tricky :-) 165 fn new(pos: u32, kind: SyntaxKind) -> Self {
166 CompletedMarker(pos, kind)
167 }
168
164 /// This method allows to create a new node which starts 169 /// This method allows to create a new node which starts
165 /// *before* the current one. That is, parser could start 170 /// *before* the current one. That is, parser could start
166 /// node `A`, then complete it, and then after parsing the 171 /// node `A`, then complete it, and then after parsing the
167 /// whole `A`, decide that it should have started some node 172 /// whole `A`, decide that it should have started some node
168 /// `B` before starting `A`. `precede` allows to do exactly 173 /// `B` before starting `A`. `precede` allows to do exactly
169 /// that. See also docs about `forward_parent` in `Event::Start`. 174 /// that. See also docs about `forward_parent` in `Event::Start`.
175 ///
176 /// Given completed events `[START, FINISH]` and its corresponding
177 /// `CompletedMarker(pos: 0, _)`.
178 /// Append a new `START` events as `[START, FINISH, NEWSTART]`,
179 /// then mark `NEWSTART` as `START`'s parent with saving its relative
180 /// distance to `NEWSTART` into forward_parent(=2 in this case);
170 pub(crate) fn precede(self, p: &mut Parser) -> Marker { 181 pub(crate) fn precede(self, p: &mut Parser) -> Marker {
171 Marker::new(p.0.precede(self.0)) 182 Marker::new(p.0.precede(self.0))
172 } 183 }
diff --git a/crates/ra_syntax/src/parser_impl.rs b/crates/ra_syntax/src/parser_impl.rs
index cb6e370ac..01a51cd8d 100644
--- a/crates/ra_syntax/src/parser_impl.rs
+++ b/crates/ra_syntax/src/parser_impl.rs
@@ -22,10 +22,21 @@ use crate::SyntaxKind::{self, EOF, TOMBSTONE};
22pub(crate) trait Sink { 22pub(crate) trait Sink {
23 type Tree; 23 type Tree;
24 24
25 /// Adds new leaf to the current branch.
25 fn leaf(&mut self, kind: SyntaxKind, text: SmolStr); 26 fn leaf(&mut self, kind: SyntaxKind, text: SmolStr);
26 fn start_internal(&mut self, kind: SyntaxKind); 27
27 fn finish_internal(&mut self); 28 /// Start new branch and make it current.
29 fn start_branch(&mut self, kind: SyntaxKind);
30
31 /// Finish current branch and restore previous
32 /// branch as current.
33 fn finish_branch(&mut self);
34
28 fn error(&mut self, error: SyntaxError); 35 fn error(&mut self, error: SyntaxError);
36
37 /// Complete tree building. Make sure that
38 /// `start_branch` and `finish_branch` calls
39 /// are paired!
29 fn finish(self) -> Self::Tree; 40 fn finish(self) -> Self::Tree;
30} 41}
31 42
@@ -52,8 +63,7 @@ pub(crate) fn parse_with<S: Sink>(
52/// to a separate struct in order not to pollute 63/// to a separate struct in order not to pollute
53/// the public API of the `Parser`. 64/// the public API of the `Parser`.
54pub(crate) struct ParserImpl<'t> { 65pub(crate) struct ParserImpl<'t> {
55 inp: &'t ParserInput<'t>, 66 parser_input: &'t ParserInput<'t>,
56
57 pos: InputPosition, 67 pos: InputPosition,
58 events: Vec<Event>, 68 events: Vec<Event>,
59 steps: Cell<u32>, 69 steps: Cell<u32>,
@@ -62,8 +72,7 @@ pub(crate) struct ParserImpl<'t> {
62impl<'t> ParserImpl<'t> { 72impl<'t> ParserImpl<'t> {
63 pub(crate) fn new(inp: &'t ParserInput<'t>) -> ParserImpl<'t> { 73 pub(crate) fn new(inp: &'t ParserInput<'t>) -> ParserImpl<'t> {
64 ParserImpl { 74 ParserImpl {
65 inp, 75 parser_input: inp,
66
67 pos: InputPosition::new(), 76 pos: InputPosition::new(),
68 events: Vec::new(), 77 events: Vec::new(),
69 steps: Cell::new(0), 78 steps: Cell::new(0),
@@ -76,9 +85,11 @@ impl<'t> ParserImpl<'t> {
76 } 85 }
77 86
78 pub(super) fn next2(&self) -> Option<(SyntaxKind, SyntaxKind)> { 87 pub(super) fn next2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
79 let c1 = self.inp.kind(self.pos); 88 let c1 = self.parser_input.kind(self.pos);
80 let c2 = self.inp.kind(self.pos + 1); 89 let c2 = self.parser_input.kind(self.pos + 1);
81 if self.inp.start(self.pos + 1) == self.inp.start(self.pos) + self.inp.len(self.pos) { 90 if self.parser_input.token_start_at(self.pos + 1)
91 == self.parser_input.token_start_at(self.pos) + self.parser_input.token_len(self.pos)
92 {
82 Some((c1, c2)) 93 Some((c1, c2))
83 } else { 94 } else {
84 None 95 None
@@ -86,12 +97,14 @@ impl<'t> ParserImpl<'t> {
86 } 97 }
87 98
88 pub(super) fn next3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> { 99 pub(super) fn next3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
89 let c1 = self.inp.kind(self.pos); 100 let c1 = self.parser_input.kind(self.pos);
90 let c2 = self.inp.kind(self.pos + 1); 101 let c2 = self.parser_input.kind(self.pos + 1);
91 let c3 = self.inp.kind(self.pos + 2); 102 let c3 = self.parser_input.kind(self.pos + 2);
92 if self.inp.start(self.pos + 1) == self.inp.start(self.pos) + self.inp.len(self.pos) 103 if self.parser_input.token_start_at(self.pos + 1)
93 && self.inp.start(self.pos + 2) 104 == self.parser_input.token_start_at(self.pos) + self.parser_input.token_len(self.pos)
94 == self.inp.start(self.pos + 1) + self.inp.len(self.pos + 1) 105 && self.parser_input.token_start_at(self.pos + 2)
106 == self.parser_input.token_start_at(self.pos + 1)
107 + self.parser_input.token_len(self.pos + 1)
95 { 108 {
96 Some((c1, c2, c3)) 109 Some((c1, c2, c3))
97 } else { 110 } else {
@@ -99,29 +112,27 @@ impl<'t> ParserImpl<'t> {
99 } 112 }
100 } 113 }
101 114
115 /// Get the syntax kind of the nth token.
102 pub(super) fn nth(&self, n: u32) -> SyntaxKind { 116 pub(super) fn nth(&self, n: u32) -> SyntaxKind {
103 let steps = self.steps.get(); 117 let steps = self.steps.get();
104 if steps > 10_000_000 { 118 assert!(steps <= 10_000_000, "the parser seems stuck");
105 panic!("the parser seems stuck");
106 }
107 self.steps.set(steps + 1); 119 self.steps.set(steps + 1);
108 120
109 self.inp.kind(self.pos + n) 121 self.parser_input.kind(self.pos + n)
110 } 122 }
111 123
112 pub(super) fn at_kw(&self, t: &str) -> bool { 124 pub(super) fn at_kw(&self, t: &str) -> bool {
113 self.inp.text(self.pos) == t 125 self.parser_input.token_text(self.pos) == t
114 } 126 }
115 127
128 /// Start parsing right behind the last event.
116 pub(super) fn start(&mut self) -> u32 { 129 pub(super) fn start(&mut self) -> u32 {
117 let pos = self.events.len() as u32; 130 let pos = self.events.len() as u32;
118 self.event(Event::Start { 131 self.push_event(Event::tombstone());
119 kind: TOMBSTONE,
120 forward_parent: None,
121 });
122 pos 132 pos
123 } 133 }
124 134
135 /// Advances the parser by one token unconditionally.
125 pub(super) fn bump(&mut self) { 136 pub(super) fn bump(&mut self) {
126 let kind = self.nth(0); 137 let kind = self.nth(0);
127 if kind == EOF { 138 if kind == EOF {
@@ -144,15 +155,17 @@ impl<'t> ParserImpl<'t> {
144 155
145 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) { 156 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) {
146 self.pos += u32::from(n_raw_tokens); 157 self.pos += u32::from(n_raw_tokens);
147 self.event(Event::Token { kind, n_raw_tokens }); 158 self.push_event(Event::Token { kind, n_raw_tokens });
148 } 159 }
149 160
161 /// Append one Error event to the back of events.
150 pub(super) fn error(&mut self, msg: String) { 162 pub(super) fn error(&mut self, msg: String) {
151 self.event(Event::Error { 163 self.push_event(Event::Error {
152 msg: ParseError(msg), 164 msg: ParseError(msg),
153 }) 165 })
154 } 166 }
155 167
168 /// Complete an event with appending a `Finish` event.
156 pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) { 169 pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) {
157 match self.events[pos as usize] { 170 match self.events[pos as usize] {
158 Event::Start { 171 Event::Start {
@@ -162,9 +175,10 @@ impl<'t> ParserImpl<'t> {
162 } 175 }
163 _ => unreachable!(), 176 _ => unreachable!(),
164 } 177 }
165 self.event(Event::Finish); 178 self.push_event(Event::Finish);
166 } 179 }
167 180
181 /// Ignore the dummy `Start` event.
168 pub(super) fn abandon(&mut self, pos: u32) { 182 pub(super) fn abandon(&mut self, pos: u32) {
169 let idx = pos as usize; 183 let idx = pos as usize;
170 if idx == self.events.len() - 1 { 184 if idx == self.events.len() - 1 {
@@ -178,6 +192,7 @@ impl<'t> ParserImpl<'t> {
178 } 192 }
179 } 193 }
180 194
195 /// Save the relative distance of a completed event to its forward_parent.
181 pub(super) fn precede(&mut self, pos: u32) -> u32 { 196 pub(super) fn precede(&mut self, pos: u32) -> u32 {
182 let new_pos = self.start(); 197 let new_pos = self.start();
183 match self.events[pos as usize] { 198 match self.events[pos as usize] {
@@ -192,7 +207,7 @@ impl<'t> ParserImpl<'t> {
192 new_pos 207 new_pos
193 } 208 }
194 209
195 fn event(&mut self, event: Event) { 210 fn push_event(&mut self, event: Event) {
196 self.events.push(event) 211 self.events.push(event)
197 } 212 }
198} 213}
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs
index 3d8b062d5..73dd6e02b 100644
--- a/crates/ra_syntax/src/parser_impl/event.rs
+++ b/crates/ra_syntax/src/parser_impl/event.rs
@@ -36,7 +36,7 @@ pub(crate) enum Event {
36 /// 36 ///
37 /// For left-recursive syntactic constructs, the parser produces 37 /// For left-recursive syntactic constructs, the parser produces
38 /// a child node before it sees a parent. `forward_parent` 38 /// a child node before it sees a parent. `forward_parent`
39 /// exists to allow to tweak parent-child relationships. 39 /// saves the position of current event's parent.
40 /// 40 ///
41 /// Consider this path 41 /// Consider this path
42 /// 42 ///
@@ -84,6 +84,15 @@ pub(crate) enum Event {
84 }, 84 },
85} 85}
86 86
87impl Event {
88 pub(crate) fn tombstone() -> Self {
89 Event::Start {
90 kind: TOMBSTONE,
91 forward_parent: None,
92 }
93 }
94}
95
87pub(super) struct EventProcessor<'a, S: Sink> { 96pub(super) struct EventProcessor<'a, S: Sink> {
88 sink: S, 97 sink: S,
89 text_pos: TextUnit, 98 text_pos: TextUnit,
@@ -110,17 +119,12 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
110 } 119 }
111 } 120 }
112 121
122 /// Generate the syntax tree with the control of events.
113 pub(super) fn process(mut self) -> S { 123 pub(super) fn process(mut self) -> S {
114 fn tombstone() -> Event {
115 Event::Start {
116 kind: TOMBSTONE,
117 forward_parent: None,
118 }
119 }
120 let mut forward_parents = Vec::new(); 124 let mut forward_parents = Vec::new();
121 125
122 for i in 0..self.events.len() { 126 for i in 0..self.events.len() {
123 match mem::replace(&mut self.events[i], tombstone()) { 127 match mem::replace(&mut self.events[i], Event::tombstone()) {
124 Event::Start { 128 Event::Start {
125 kind: TOMBSTONE, .. 129 kind: TOMBSTONE, ..
126 } => (), 130 } => (),
@@ -129,12 +133,18 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
129 kind, 133 kind,
130 forward_parent, 134 forward_parent,
131 } => { 135 } => {
136 // For events[A, B, C], B is A's forward_parent, C is B's forward_parent,
137 // in the normal control flow, the parent-child relation: `A -> B -> C`,
138 // while with the magic forward_parent, it writes: `C <- B <- A`.
139
140 // append `A` into parents.
132 forward_parents.push(kind); 141 forward_parents.push(kind);
133 let mut idx = i; 142 let mut idx = i;
134 let mut fp = forward_parent; 143 let mut fp = forward_parent;
135 while let Some(fwd) = fp { 144 while let Some(fwd) = fp {
136 idx += fwd as usize; 145 idx += fwd as usize;
137 fp = match mem::replace(&mut self.events[idx], tombstone()) { 146 // append `A`'s forward_parent `B`
147 fp = match mem::replace(&mut self.events[idx], Event::tombstone()) {
138 Event::Start { 148 Event::Start {
139 kind, 149 kind,
140 forward_parent, 150 forward_parent,
@@ -144,17 +154,19 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
144 } 154 }
145 _ => unreachable!(), 155 _ => unreachable!(),
146 }; 156 };
157 // append `B`'s forward_parent `C` in the next stage.
147 } 158 }
159
148 for kind in forward_parents.drain(..).rev() { 160 for kind in forward_parents.drain(..).rev() {
149 self.start(kind); 161 self.start(kind);
150 } 162 }
151 } 163 }
152 Event::Finish => { 164 Event::Finish => {
153 let last = i == self.events.len() - 1; 165 let is_last = i == self.events.len() - 1;
154 self.finish(last); 166 self.finish(is_last);
155 } 167 }
156 Event::Token { kind, n_raw_tokens } => { 168 Event::Token { kind, n_raw_tokens } => {
157 self.eat_ws(); 169 self.eat_trivias();
158 let n_raw_tokens = n_raw_tokens as usize; 170 let n_raw_tokens = n_raw_tokens as usize;
159 let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens] 171 let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens]
160 .iter() 172 .iter()
@@ -171,9 +183,10 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
171 self.sink 183 self.sink
172 } 184 }
173 185
186 /// Add the node into syntax tree but discard the comments/whitespaces.
174 fn start(&mut self, kind: SyntaxKind) { 187 fn start(&mut self, kind: SyntaxKind) {
175 if kind == SOURCE_FILE { 188 if kind == SOURCE_FILE {
176 self.sink.start_internal(kind); 189 self.sink.start_branch(kind);
177 return; 190 return;
178 } 191 }
179 let n_trivias = self.tokens[self.token_pos..] 192 let n_trivias = self.tokens[self.token_pos..]
@@ -194,18 +207,18 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
194 n_attached_trivias(kind, leading_trivias) 207 n_attached_trivias(kind, leading_trivias)
195 }; 208 };
196 self.eat_n_trivias(n_trivias - n_attached_trivias); 209 self.eat_n_trivias(n_trivias - n_attached_trivias);
197 self.sink.start_internal(kind); 210 self.sink.start_branch(kind);
198 self.eat_n_trivias(n_attached_trivias); 211 self.eat_n_trivias(n_attached_trivias);
199 } 212 }
200 213
201 fn finish(&mut self, last: bool) { 214 fn finish(&mut self, is_last: bool) {
202 if last { 215 if is_last {
203 self.eat_ws() 216 self.eat_trivias()
204 } 217 }
205 self.sink.finish_internal(); 218 self.sink.finish_branch();
206 } 219 }
207 220
208 fn eat_ws(&mut self) { 221 fn eat_trivias(&mut self) {
209 while let Some(&token) = self.tokens.get(self.token_pos) { 222 while let Some(&token) = self.tokens.get(self.token_pos) {
210 if !token.kind.is_trivia() { 223 if !token.kind.is_trivia() {
211 break; 224 break;
@@ -236,7 +249,7 @@ fn n_attached_trivias<'a>(
236 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>, 249 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
237) -> usize { 250) -> usize {
238 match kind { 251 match kind {
239 STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => { 252 CONST_DEF | TYPE_DEF | STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => {
240 let mut res = 0; 253 let mut res = 0;
241 for (i, (kind, text)) in trivias.enumerate() { 254 for (i, (kind, text)) in trivias.enumerate() {
242 match kind { 255 match kind {
diff --git a/crates/ra_syntax/src/parser_impl/input.rs b/crates/ra_syntax/src/parser_impl/input.rs
index ac6d900d8..7fde5b3ab 100644
--- a/crates/ra_syntax/src/parser_impl/input.rs
+++ b/crates/ra_syntax/src/parser_impl/input.rs
@@ -4,11 +4,26 @@ use std::ops::{Add, AddAssign};
4 4
5pub(crate) struct ParserInput<'t> { 5pub(crate) struct ParserInput<'t> {
6 text: &'t str, 6 text: &'t str,
7 /// start position of each token(expect whitespace and comment)
8 /// ```non-rust
9 /// struct Foo;
10 /// ^------^---
11 /// | | ^-
12 /// 0 7 10
13 /// ```
14 /// (token, start_offset): `[(struct, 0), (Foo, 7), (;, 10)]`
7 start_offsets: Vec<TextUnit>, 15 start_offsets: Vec<TextUnit>,
8 tokens: Vec<Token>, // non-whitespace tokens 16 /// non-whitespace/comment tokens
17 /// ```non-rust
18 /// struct Foo {}
19 /// ^^^^^^ ^^^ ^^
20 /// ```
21 /// tokens: `[struct, Foo, {, }]`
22 tokens: Vec<Token>,
9} 23}
10 24
11impl<'t> ParserInput<'t> { 25impl<'t> ParserInput<'t> {
26 /// Generate input from tokens(expect comment and whitespace).
12 pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> ParserInput<'t> { 27 pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> ParserInput<'t> {
13 let mut tokens = Vec::new(); 28 let mut tokens = Vec::new();
14 let mut start_offsets = Vec::new(); 29 let mut start_offsets = Vec::new();
@@ -28,6 +43,7 @@ impl<'t> ParserInput<'t> {
28 } 43 }
29 } 44 }
30 45
46 /// Get the syntax kind of token at given input position.
31 pub fn kind(&self, pos: InputPosition) -> SyntaxKind { 47 pub fn kind(&self, pos: InputPosition) -> SyntaxKind {
32 let idx = pos.0 as usize; 48 let idx = pos.0 as usize;
33 if !(idx < self.tokens.len()) { 49 if !(idx < self.tokens.len()) {
@@ -36,7 +52,8 @@ impl<'t> ParserInput<'t> {
36 self.tokens[idx].kind 52 self.tokens[idx].kind
37 } 53 }
38 54
39 pub fn len(&self, pos: InputPosition) -> TextUnit { 55 /// Get the length of a token at given input position.
56 pub fn token_len(&self, pos: InputPosition) -> TextUnit {
40 let idx = pos.0 as usize; 57 let idx = pos.0 as usize;
41 if !(idx < self.tokens.len()) { 58 if !(idx < self.tokens.len()) {
42 return 0.into(); 59 return 0.into();
@@ -44,7 +61,8 @@ impl<'t> ParserInput<'t> {
44 self.tokens[idx].len 61 self.tokens[idx].len
45 } 62 }
46 63
47 pub fn start(&self, pos: InputPosition) -> TextUnit { 64 /// Get the start position of a taken at given input position.
65 pub fn token_start_at(&self, pos: InputPosition) -> TextUnit {
48 let idx = pos.0 as usize; 66 let idx = pos.0 as usize;
49 if !(idx < self.tokens.len()) { 67 if !(idx < self.tokens.len()) {
50 return 0.into(); 68 return 0.into();
@@ -52,7 +70,8 @@ impl<'t> ParserInput<'t> {
52 self.start_offsets[idx] 70 self.start_offsets[idx]
53 } 71 }
54 72
55 pub fn text(&self, pos: InputPosition) -> &'t str { 73 /// Get the raw text of a token at given input position.
74 pub fn token_text(&self, pos: InputPosition) -> &'t str {
56 let idx = pos.0 as usize; 75 let idx = pos.0 as usize;
57 if !(idx < self.tokens.len()) { 76 if !(idx < self.tokens.len()) {
58 return ""; 77 return "";
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs
index 208cae5c8..7ee71a1b6 100644
--- a/crates/ra_syntax/src/reparsing.rs
+++ b/crates/ra_syntax/src/reparsing.rs
@@ -100,7 +100,7 @@ fn find_reparsable_node(
100 ITEM_LIST => { 100 ITEM_LIST => {
101 let parent = node.parent().unwrap(); 101 let parent = node.parent().unwrap();
102 match parent.kind() { 102 match parent.kind() {
103 IMPL_ITEM => grammar::impl_item_list, 103 IMPL_BLOCK => grammar::impl_item_list,
104 TRAIT_DEF => grammar::trait_item_list, 104 TRAIT_DEF => grammar::trait_item_list,
105 MODULE => grammar::mod_item_list, 105 MODULE => grammar::mod_item_list,
106 _ => return None, 106 _ => return None,
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs b/crates/ra_syntax/src/syntax_kinds/generated.rs
index 3a869ad34..ef4588d93 100644
--- a/crates/ra_syntax/src/syntax_kinds/generated.rs
+++ b/crates/ra_syntax/src/syntax_kinds/generated.rs
@@ -128,7 +128,7 @@ pub enum SyntaxKind {
128 STATIC_DEF, 128 STATIC_DEF,
129 CONST_DEF, 129 CONST_DEF,
130 TRAIT_DEF, 130 TRAIT_DEF,
131 IMPL_ITEM, 131 IMPL_BLOCK,
132 TYPE_DEF, 132 TYPE_DEF,
133 MACRO_CALL, 133 MACRO_CALL,
134 TOKEN_TREE, 134 TOKEN_TREE,
@@ -389,7 +389,7 @@ impl SyntaxKind {
389 STATIC_DEF => &SyntaxInfo { name: "STATIC_DEF" }, 389 STATIC_DEF => &SyntaxInfo { name: "STATIC_DEF" },
390 CONST_DEF => &SyntaxInfo { name: "CONST_DEF" }, 390 CONST_DEF => &SyntaxInfo { name: "CONST_DEF" },
391 TRAIT_DEF => &SyntaxInfo { name: "TRAIT_DEF" }, 391 TRAIT_DEF => &SyntaxInfo { name: "TRAIT_DEF" },
392 IMPL_ITEM => &SyntaxInfo { name: "IMPL_ITEM" }, 392 IMPL_BLOCK => &SyntaxInfo { name: "IMPL_BLOCK" },
393 TYPE_DEF => &SyntaxInfo { name: "TYPE_DEF" }, 393 TYPE_DEF => &SyntaxInfo { name: "TYPE_DEF" },
394 MACRO_CALL => &SyntaxInfo { name: "MACRO_CALL" }, 394 MACRO_CALL => &SyntaxInfo { name: "MACRO_CALL" },
395 TOKEN_TREE => &SyntaxInfo { name: "TOKEN_TREE" }, 395 TOKEN_TREE => &SyntaxInfo { name: "TOKEN_TREE" },
diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs
index 9fcebfb93..37ae6329b 100644
--- a/crates/ra_syntax/src/yellow/builder.rs
+++ b/crates/ra_syntax/src/yellow/builder.rs
@@ -26,11 +26,11 @@ impl Sink for GreenBuilder {
26 self.inner.leaf(kind, text); 26 self.inner.leaf(kind, text);
27 } 27 }
28 28
29 fn start_internal(&mut self, kind: SyntaxKind) { 29 fn start_branch(&mut self, kind: SyntaxKind) {
30 self.inner.start_internal(kind) 30 self.inner.start_internal(kind)
31 } 31 }
32 32
33 fn finish_internal(&mut self) { 33 fn finish_branch(&mut self) {
34 self.inner.finish_internal(); 34 self.inner.finish_internal();
35 } 35 }
36 36
diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs
index 46bde9a08..279a83b61 100644
--- a/crates/ra_syntax/src/yellow/syntax_text.rs
+++ b/crates/ra_syntax/src/yellow/syntax_text.rs
@@ -119,3 +119,27 @@ impl SyntaxTextSlice for ops::Range<TextUnit> {
119 TextRange::from_to(self.start, self.end).restrict(range) 119 TextRange::from_to(self.start, self.end).restrict(range)
120 } 120 }
121} 121}
122
123impl From<SyntaxText<'_>> for String {
124 fn from(text: SyntaxText) -> String {
125 text.to_string()
126 }
127}
128
129impl PartialEq<str> for SyntaxText<'_> {
130 fn eq(&self, mut rhs: &str) -> bool {
131 for chunk in self.chunks() {
132 if !rhs.starts_with(chunk) {
133 return false;
134 }
135 rhs = &rhs[chunk.len()..];
136 }
137 rhs.is_empty()
138 }
139}
140
141impl PartialEq<&'_ str> for SyntaxText<'_> {
142 fn eq(&self, rhs: &&str) -> bool {
143 self == *rhs
144 }
145}
diff --git a/crates/ra_syntax/tests/data/parser/err/0018_incomplete_fn.txt b/crates/ra_syntax/tests/data/parser/err/0018_incomplete_fn.txt
index 3937be255..262cbba1e 100644
--- a/crates/ra_syntax/tests/data/parser/err/0018_incomplete_fn.txt
+++ b/crates/ra_syntax/tests/data/parser/err/0018_incomplete_fn.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 183) 1SOURCE_FILE@[0; 183)
2 IMPL_ITEM@[0; 182) 2 IMPL_BLOCK@[0; 182)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 PATH_TYPE@[5; 13) 5 PATH_TYPE@[5; 13)
diff --git a/crates/ra_syntax/tests/data/parser/err/0022_bad_exprs.txt b/crates/ra_syntax/tests/data/parser/err/0022_bad_exprs.txt
index 55999c160..da3894133 100644
--- a/crates/ra_syntax/tests/data/parser/err/0022_bad_exprs.txt
+++ b/crates/ra_syntax/tests/data/parser/err/0022_bad_exprs.txt
@@ -94,7 +94,7 @@ SOURCE_FILE@[0; 112)
94 COMMA@[54; 55) 94 COMMA@[54; 55)
95 err: `expected SEMI` 95 err: `expected SEMI`
96 WHITESPACE@[55; 56) 96 WHITESPACE@[55; 56)
97 IMPL_ITEM@[56; 60) 97 IMPL_BLOCK@[56; 60)
98 IMPL_KW@[56; 60) 98 IMPL_KW@[56; 60)
99 err: `expected type` 99 err: `expected type`
100 err: `expected `{`` 100 err: `expected `{``
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 82683f6ee..9b5fadcf7 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
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 38) 1SOURCE_FILE@[0; 38)
2 IMPL_ITEM@[0; 14) 2 IMPL_BLOCK@[0; 14)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 TYPE_PARAM_LIST@[4; 14) 4 TYPE_PARAM_LIST@[4; 14)
5 L_ANGLE@[4; 5) 5 L_ANGLE@[4; 5)
@@ -17,7 +17,7 @@ SOURCE_FILE@[0; 38)
17 err: `expected trait or type` 17 err: `expected trait or type`
18 err: `expected `{`` 18 err: `expected `{``
19 WHITESPACE@[14; 15) 19 WHITESPACE@[14; 15)
20 IMPL_ITEM@[15; 37) 20 IMPL_BLOCK@[15; 37)
21 IMPL_KW@[15; 19) 21 IMPL_KW@[15; 19)
22 TYPE_PARAM_LIST@[19; 22) 22 TYPE_PARAM_LIST@[19; 22)
23 L_ANGLE@[19; 20) 23 L_ANGLE@[19; 20)
diff --git a/crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt b/crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt
index 75533ecc1..8021aee00 100644
--- a/crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt
@@ -19,7 +19,7 @@ SOURCE_FILE@[0; 30)
19 err: `expected a loop` 19 err: `expected a loop`
20 err: `expected SEMI` 20 err: `expected SEMI`
21 WHITESPACE@[22; 23) 21 WHITESPACE@[22; 23)
22 IMPL_ITEM@[23; 27) 22 IMPL_BLOCK@[23; 27)
23 IMPL_KW@[23; 27) 23 IMPL_KW@[23; 27)
24 err: `expected type` 24 err: `expected type`
25 err: `expected `{`` 25 err: `expected `{``
diff --git a/crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt b/crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt
index 7279d5cae..6875ed016 100644
--- a/crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 87) 1SOURCE_FILE@[0; 87)
2 IMPL_ITEM@[0; 12) 2 IMPL_BLOCK@[0; 12)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 PATH_TYPE@[5; 9) 5 PATH_TYPE@[5; 9)
@@ -12,7 +12,7 @@ SOURCE_FILE@[0; 87)
12 L_CURLY@[10; 11) 12 L_CURLY@[10; 11)
13 R_CURLY@[11; 12) 13 R_CURLY@[11; 12)
14 WHITESPACE@[12; 13) 14 WHITESPACE@[12; 13)
15 IMPL_ITEM@[13; 33) 15 IMPL_BLOCK@[13; 33)
16 IMPL_KW@[13; 17) 16 IMPL_KW@[13; 17)
17 WHITESPACE@[17; 18) 17 WHITESPACE@[17; 18)
18 PATH_TYPE@[18; 24) 18 PATH_TYPE@[18; 24)
@@ -33,12 +33,12 @@ SOURCE_FILE@[0; 87)
33 L_CURLY@[31; 32) 33 L_CURLY@[31; 32)
34 R_CURLY@[32; 33) 34 R_CURLY@[32; 33)
35 WHITESPACE@[33; 34) 35 WHITESPACE@[33; 34)
36 IMPL_ITEM@[34; 38) 36 IMPL_BLOCK@[34; 38)
37 IMPL_KW@[34; 38) 37 IMPL_KW@[34; 38)
38 err: `expected trait or type` 38 err: `expected trait or type`
39 err: `expected `{`` 39 err: `expected `{``
40 WHITESPACE@[38; 39) 40 WHITESPACE@[38; 39)
41 IMPL_ITEM@[39; 54) 41 IMPL_BLOCK@[39; 54)
42 IMPL_KW@[39; 43) 42 IMPL_KW@[39; 43)
43 WHITESPACE@[43; 44) 43 WHITESPACE@[43; 44)
44 PATH_TYPE@[44; 51) 44 PATH_TYPE@[44; 51)
@@ -51,7 +51,7 @@ SOURCE_FILE@[0; 87)
51 L_CURLY@[52; 53) 51 L_CURLY@[52; 53)
52 R_CURLY@[53; 54) 52 R_CURLY@[53; 54)
53 WHITESPACE@[54; 55) 53 WHITESPACE@[54; 55)
54 IMPL_ITEM@[55; 70) 54 IMPL_BLOCK@[55; 70)
55 IMPL_KW@[55; 59) 55 IMPL_KW@[55; 59)
56 WHITESPACE@[59; 60) 56 WHITESPACE@[59; 60)
57 PATH_TYPE@[60; 66) 57 PATH_TYPE@[60; 66)
@@ -64,7 +64,7 @@ SOURCE_FILE@[0; 87)
64 err: `expected trait or type` 64 err: `expected trait or type`
65 err: `expected `{`` 65 err: `expected `{``
66 WHITESPACE@[70; 71) 66 WHITESPACE@[70; 71)
67 IMPL_ITEM@[71; 86) 67 IMPL_BLOCK@[71; 86)
68 IMPL_KW@[71; 75) 68 IMPL_KW@[71; 75)
69 WHITESPACE@[75; 76) 69 WHITESPACE@[75; 76)
70 PATH_TYPE@[76; 83) 70 PATH_TYPE@[76; 83)
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 998ac3da9..de7df7312 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
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 83) 1SOURCE_FILE@[0; 83)
2 IMPL_ITEM@[0; 82) 2 IMPL_BLOCK@[0; 82)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 PATH_TYPE@[5; 6) 5 PATH_TYPE@[5; 6)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt
index 53027c852..4df01c6e5 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 128) 1SOURCE_FILE@[0; 128)
2 IMPL_ITEM@[0; 127) 2 IMPL_BLOCK@[0; 127)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 PATH_TYPE@[5; 6) 5 PATH_TYPE@[5; 6)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt
index b2f04ea7b..03139f7a4 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 69) 1SOURCE_FILE@[0; 69)
2 IMPL_ITEM@[0; 68) 2 IMPL_BLOCK@[0; 68)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 PATH_TYPE@[5; 6) 5 PATH_TYPE@[5; 6)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt
index b15f93cd2..50426bdfe 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 89) 1SOURCE_FILE@[0; 89)
2 IMPL_ITEM@[0; 88) 2 IMPL_BLOCK@[0; 88)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 PATH_TYPE@[5; 6) 5 PATH_TYPE@[5; 6)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt
index 6003ba645..5d68e88d6 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 27) 1SOURCE_FILE@[0; 27)
2 IMPL_ITEM@[0; 26) 2 IMPL_BLOCK@[0; 26)
3 UNSAFE_KW@[0; 6) 3 UNSAFE_KW@[0; 6)
4 WHITESPACE@[6; 7) 4 WHITESPACE@[6; 7)
5 DEFAULT_KW@[7; 14) 5 DEFAULT_KW@[7; 14)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_block_neg.rs
index b7527c870..b7527c870 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_block_neg.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_block_neg.txt
index b83db380e..563e43508 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_block_neg.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 20) 1SOURCE_FILE@[0; 20)
2 IMPL_ITEM@[0; 19) 2 IMPL_BLOCK@[0; 19)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 EXCL@[5; 6) 5 EXCL@[5; 6)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_block.rs
index d6337f6b3..d6337f6b3 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_block.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_block.txt
index 1b9a8aa0e..a2c218aa9 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_block.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 12) 1SOURCE_FILE@[0; 12)
2 IMPL_ITEM@[0; 11) 2 IMPL_BLOCK@[0; 11)
3 IMPL_KW@[0; 4) 3 IMPL_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 PATH_TYPE@[5; 8) 5 PATH_TYPE@[5; 8)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0087_unsafe_impl.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0087_unsafe_impl.txt
index f9c96c242..d93c0df4d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0087_unsafe_impl.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0087_unsafe_impl.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 19) 1SOURCE_FILE@[0; 19)
2 IMPL_ITEM@[0; 18) 2 IMPL_BLOCK@[0; 18)
3 UNSAFE_KW@[0; 6) 3 UNSAFE_KW@[0; 6)
4 WHITESPACE@[6; 7) 4 WHITESPACE@[6; 7)
5 IMPL_KW@[7; 11) 5 IMPL_KW@[7; 11)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0097_default_impl.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0097_default_impl.txt
index f45b6251f..0b9af800b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0097_default_impl.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0097_default_impl.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 20) 1SOURCE_FILE@[0; 20)
2 IMPL_ITEM@[0; 19) 2 IMPL_BLOCK@[0; 19)
3 DEFAULT_KW@[0; 7) 3 DEFAULT_KW@[0; 7)
4 WHITESPACE@[7; 8) 4 WHITESPACE@[7; 8)
5 IMPL_KW@[8; 12) 5 IMPL_KW@[8; 12)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0037_mod.rs b/crates/ra_syntax/tests/data/parser/ok/0037_mod.rs
new file mode 100644
index 000000000..7e5a1b835
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0037_mod.rs
@@ -0,0 +1,5 @@
1// https://github.com/rust-analyzer/rust-analyzer/issues/357
2
3//! docs
4// non-docs
5mod foo {} \ No newline at end of file
diff --git a/crates/ra_syntax/tests/data/parser/ok/0037_mod.txt b/crates/ra_syntax/tests/data/parser/ok/0037_mod.txt
new file mode 100644
index 000000000..f8a20ac53
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0037_mod.txt
@@ -0,0 +1,16 @@
1SOURCE_FILE@[0; 93)
2 COMMENT@[0; 60)
3 WHITESPACE@[60; 62)
4 MODULE@[62; 93)
5 COMMENT@[62; 70)
6 WHITESPACE@[70; 71)
7 COMMENT@[71; 82)
8 WHITESPACE@[82; 83)
9 MOD_KW@[83; 86)
10 WHITESPACE@[86; 87)
11 NAME@[87; 90)
12 IDENT@[87; 90) "foo"
13 WHITESPACE@[90; 91)
14 ITEM_LIST@[91; 93)
15 L_CURLY@[91; 92)
16 R_CURLY@[92; 93)