diff options
Diffstat (limited to 'crates/ra_syntax')
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 | ||
33 | pub trait VisibilityOwner<'a>: AstNode<'a> { | ||
34 | fn visibility(self) -> Option<Visibility<'a>> { | ||
35 | child_opt(self) | ||
36 | } | ||
37 | } | ||
38 | |||
33 | pub trait LoopBodyOwner<'a>: AstNode<'a> { | 39 | pub 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 | ||
236 | impl<'a> Whitespace<'a> { | 254 | impl<'a> Whitespace<'a> { |
@@ -261,7 +279,7 @@ impl<'a> NameRef<'a> { | |||
261 | } | 279 | } |
262 | } | 280 | } |
263 | 281 | ||
264 | impl<'a> ImplItem<'a> { | 282 | impl<'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 | ||
366 | impl<'a> Path<'a> { | ||
367 | pub fn parent_path(self) -> Option<Path<'a>> { | ||
368 | self.syntax().parent().and_then(Path::cast) | ||
369 | } | ||
370 | } | ||
371 | |||
348 | impl<'a> UseTree<'a> { | 372 | impl<'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)] | ||
492 | pub enum SelfParamFlavor { | ||
493 | /// self | ||
494 | Owned, | ||
495 | /// &self | ||
496 | Ref, | ||
497 | /// &mut self | ||
498 | MutRef, | ||
499 | } | ||
500 | |||
501 | impl<'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] | ||
523 | fn 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 | ||
698 | impl<'a> ast::VisibilityOwner<'a> for ConstDef<'a> {} | ||
698 | impl<'a> ast::NameOwner<'a> for ConstDef<'a> {} | 699 | impl<'a> ast::NameOwner<'a> for ConstDef<'a> {} |
699 | impl<'a> ast::TypeParamsOwner<'a> for ConstDef<'a> {} | 700 | impl<'a> ast::TypeParamsOwner<'a> for ConstDef<'a> {} |
700 | impl<'a> ast::AttrsOwner<'a> for ConstDef<'a> {} | 701 | impl<'a> ast::AttrsOwner<'a> for ConstDef<'a> {} |
@@ -810,6 +811,7 @@ impl<R: TreeRoot<RaTypes>> EnumDefNode<R> { | |||
810 | } | 811 | } |
811 | 812 | ||
812 | 813 | ||
814 | impl<'a> ast::VisibilityOwner<'a> for EnumDef<'a> {} | ||
813 | impl<'a> ast::NameOwner<'a> for EnumDef<'a> {} | 815 | impl<'a> ast::NameOwner<'a> for EnumDef<'a> {} |
814 | impl<'a> ast::TypeParamsOwner<'a> for EnumDef<'a> {} | 816 | impl<'a> ast::TypeParamsOwner<'a> for EnumDef<'a> {} |
815 | impl<'a> ast::AttrsOwner<'a> for EnumDef<'a> {} | 817 | impl<'a> ast::AttrsOwner<'a> for EnumDef<'a> {} |
@@ -1213,6 +1215,7 @@ impl<R: TreeRoot<RaTypes>> FnDefNode<R> { | |||
1213 | } | 1215 | } |
1214 | 1216 | ||
1215 | 1217 | ||
1218 | impl<'a> ast::VisibilityOwner<'a> for FnDef<'a> {} | ||
1216 | impl<'a> ast::NameOwner<'a> for FnDef<'a> {} | 1219 | impl<'a> ast::NameOwner<'a> for FnDef<'a> {} |
1217 | impl<'a> ast::TypeParamsOwner<'a> for FnDef<'a> {} | 1220 | impl<'a> ast::TypeParamsOwner<'a> for FnDef<'a> {} |
1218 | impl<'a> ast::AttrsOwner<'a> for FnDef<'a> {} | 1221 | impl<'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,)] |
1409 | pub struct ImplItemNode<R: TreeRoot<RaTypes> = OwnedRoot> { | 1412 | pub struct ImplBlockNode<R: TreeRoot<RaTypes> = OwnedRoot> { |
1410 | pub(crate) syntax: SyntaxNode<R>, | 1413 | pub(crate) syntax: SyntaxNode<R>, |
1411 | } | 1414 | } |
1412 | pub type ImplItem<'a> = ImplItemNode<RefRoot<'a>>; | 1415 | pub type ImplBlock<'a> = ImplBlockNode<RefRoot<'a>>; |
1413 | 1416 | ||
1414 | impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<ImplItemNode<R1>> for ImplItemNode<R2> { | 1417 | impl<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 | } |
1417 | impl<R: TreeRoot<RaTypes>> Eq for ImplItemNode<R> {} | 1420 | impl<R: TreeRoot<RaTypes>> Eq for ImplBlockNode<R> {} |
1418 | impl<R: TreeRoot<RaTypes>> Hash for ImplItemNode<R> { | 1421 | impl<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 | ||
1422 | impl<'a> AstNode<'a> for ImplItem<'a> { | 1425 | impl<'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 | ||
1432 | impl<R: TreeRoot<RaTypes>> ImplItemNode<R> { | 1435 | impl<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 | |||
1445 | impl<'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)] | ||
1453 | pub enum ImplItem<'a> { | ||
1454 | FnDef(FnDef<'a>), | ||
1455 | TypeDef(TypeDef<'a>), | ||
1456 | ConstDef(ConstDef<'a>), | ||
1457 | } | ||
1458 | |||
1459 | impl<'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 | ||
1442 | impl<'a> ImplItem<'a> {} | 1477 | impl<'a> ImplItem<'a> {} |
1443 | 1478 | ||
@@ -1552,7 +1587,11 @@ impl<R: TreeRoot<RaTypes>> ItemListNode<R> { | |||
1552 | 1587 | ||
1553 | impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {} | 1588 | impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {} |
1554 | impl<'a> ast::ModuleItemOwner<'a> for ItemList<'a> {} | 1589 | impl<'a> ast::ModuleItemOwner<'a> for ItemList<'a> {} |
1555 | impl<'a> ItemList<'a> {} | 1590 | impl<'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 | ||
2178 | impl<'a> ast::VisibilityOwner<'a> for Module<'a> {} | ||
2139 | impl<'a> ast::NameOwner<'a> for Module<'a> {} | 2179 | impl<'a> ast::NameOwner<'a> for Module<'a> {} |
2140 | impl<'a> ast::AttrsOwner<'a> for Module<'a> {} | 2180 | impl<'a> ast::AttrsOwner<'a> for Module<'a> {} |
2141 | impl<'a> ast::DocCommentsOwner<'a> for Module<'a> {} | 2181 | impl<'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 | ||
2394 | impl<'a> ast::VisibilityOwner<'a> for NamedFieldDef<'a> {} | ||
2354 | impl<'a> ast::NameOwner<'a> for NamedFieldDef<'a> {} | 2395 | impl<'a> ast::NameOwner<'a> for NamedFieldDef<'a> {} |
2355 | impl<'a> ast::AttrsOwner<'a> for NamedFieldDef<'a> {} | 2396 | impl<'a> ast::AttrsOwner<'a> for NamedFieldDef<'a> {} |
2356 | impl<'a> NamedFieldDef<'a> { | 2397 | impl<'a> NamedFieldDef<'a> { |
@@ -3082,6 +3123,7 @@ impl<R: TreeRoot<RaTypes>> PosFieldNode<R> { | |||
3082 | } | 3123 | } |
3083 | 3124 | ||
3084 | 3125 | ||
3126 | impl<'a> ast::VisibilityOwner<'a> for PosField<'a> {} | ||
3085 | impl<'a> ast::AttrsOwner<'a> for PosField<'a> {} | 3127 | impl<'a> ast::AttrsOwner<'a> for PosField<'a> {} |
3086 | impl<'a> PosField<'a> { | 3128 | impl<'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,)] | ||
3493 | pub struct SelfKwNode<R: TreeRoot<RaTypes> = OwnedRoot> { | ||
3494 | pub(crate) syntax: SyntaxNode<R>, | ||
3495 | } | ||
3496 | pub type SelfKw<'a> = SelfKwNode<RefRoot<'a>>; | ||
3497 | |||
3498 | impl<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 | } | ||
3501 | impl<R: TreeRoot<RaTypes>> Eq for SelfKwNode<R> {} | ||
3502 | impl<R: TreeRoot<RaTypes>> Hash for SelfKwNode<R> { | ||
3503 | fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) } | ||
3504 | } | ||
3505 | |||
3506 | impl<'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 | |||
3516 | impl<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 | |||
3526 | impl<'a> SelfKw<'a> {} | ||
3527 | |||
3449 | // SelfParam | 3528 | // SelfParam |
3450 | #[derive(Debug, Clone, Copy,)] | 3529 | #[derive(Debug, Clone, Copy,)] |
3451 | pub struct SelfParamNode<R: TreeRoot<RaTypes> = OwnedRoot> { | 3530 | pub struct SelfParamNode<R: TreeRoot<RaTypes> = OwnedRoot> { |
@@ -3481,7 +3560,15 @@ impl<R: TreeRoot<RaTypes>> SelfParamNode<R> { | |||
3481 | } | 3560 | } |
3482 | 3561 | ||
3483 | 3562 | ||
3484 | impl<'a> SelfParam<'a> {} | 3563 | impl<'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 | ||
3729 | impl<'a> ast::VisibilityOwner<'a> for StaticDef<'a> {} | ||
3642 | impl<'a> ast::NameOwner<'a> for StaticDef<'a> {} | 3730 | impl<'a> ast::NameOwner<'a> for StaticDef<'a> {} |
3643 | impl<'a> ast::TypeParamsOwner<'a> for StaticDef<'a> {} | 3731 | impl<'a> ast::TypeParamsOwner<'a> for StaticDef<'a> {} |
3644 | impl<'a> ast::AttrsOwner<'a> for StaticDef<'a> {} | 3732 | impl<'a> ast::AttrsOwner<'a> for StaticDef<'a> {} |
@@ -3742,6 +3830,7 @@ impl<R: TreeRoot<RaTypes>> StructDefNode<R> { | |||
3742 | } | 3830 | } |
3743 | 3831 | ||
3744 | 3832 | ||
3833 | impl<'a> ast::VisibilityOwner<'a> for StructDef<'a> {} | ||
3745 | impl<'a> ast::NameOwner<'a> for StructDef<'a> {} | 3834 | impl<'a> ast::NameOwner<'a> for StructDef<'a> {} |
3746 | impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {} | 3835 | impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {} |
3747 | impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {} | 3836 | impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {} |
@@ -3902,6 +3991,7 @@ impl<R: TreeRoot<RaTypes>> TraitDefNode<R> { | |||
3902 | } | 3991 | } |
3903 | 3992 | ||
3904 | 3993 | ||
3994 | impl<'a> ast::VisibilityOwner<'a> for TraitDef<'a> {} | ||
3905 | impl<'a> ast::NameOwner<'a> for TraitDef<'a> {} | 3995 | impl<'a> ast::NameOwner<'a> for TraitDef<'a> {} |
3906 | impl<'a> ast::AttrsOwner<'a> for TraitDef<'a> {} | 3996 | impl<'a> ast::AttrsOwner<'a> for TraitDef<'a> {} |
3907 | impl<'a> ast::DocCommentsOwner<'a> for TraitDef<'a> {} | 3997 | impl<'a> ast::DocCommentsOwner<'a> for TraitDef<'a> {} |
@@ -4135,6 +4225,7 @@ impl<R: TreeRoot<RaTypes>> TypeDefNode<R> { | |||
4135 | } | 4225 | } |
4136 | 4226 | ||
4137 | 4227 | ||
4228 | impl<'a> ast::VisibilityOwner<'a> for TypeDef<'a> {} | ||
4138 | impl<'a> ast::NameOwner<'a> for TypeDef<'a> {} | 4229 | impl<'a> ast::NameOwner<'a> for TypeDef<'a> {} |
4139 | impl<'a> ast::TypeParamsOwner<'a> for TypeDef<'a> {} | 4230 | impl<'a> ast::TypeParamsOwner<'a> for TypeDef<'a> {} |
4140 | impl<'a> ast::AttrsOwner<'a> for TypeDef<'a> {} | 4231 | impl<'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,)] | ||
4505 | pub struct VisibilityNode<R: TreeRoot<RaTypes> = OwnedRoot> { | ||
4506 | pub(crate) syntax: SyntaxNode<R>, | ||
4507 | } | ||
4508 | pub type Visibility<'a> = VisibilityNode<RefRoot<'a>>; | ||
4509 | |||
4510 | impl<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 | } | ||
4513 | impl<R: TreeRoot<RaTypes>> Eq for VisibilityNode<R> {} | ||
4514 | impl<R: TreeRoot<RaTypes>> Hash for VisibilityNode<R> { | ||
4515 | fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) } | ||
4516 | } | ||
4517 | |||
4518 | impl<'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 | |||
4528 | impl<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 | |||
4538 | impl<'a> Visibility<'a> {} | ||
4539 | |||
4412 | // WhereClause | 4540 | // WhereClause |
4413 | #[derive(Debug, Clone, Copy,)] | 4541 | #[derive(Debug, Clone, Copy,)] |
4414 | pub struct WhereClauseNode<R: TreeRoot<RaTypes> = OwnedRoot> { | 4542 | pub 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 {} |
45 | pub(super) fn impl_item(p: &mut Parser) { | 45 | pub(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 { | |||
160 | pub(crate) struct CompletedMarker(u32, SyntaxKind); | 162 | pub(crate) struct CompletedMarker(u32, SyntaxKind); |
161 | 163 | ||
162 | impl CompletedMarker { | 164 | impl 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}; | |||
22 | pub(crate) trait Sink { | 22 | pub(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`. |
54 | pub(crate) struct ParserImpl<'t> { | 65 | pub(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> { | |||
62 | impl<'t> ParserImpl<'t> { | 72 | impl<'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 | ||
87 | impl Event { | ||
88 | pub(crate) fn tombstone() -> Self { | ||
89 | Event::Start { | ||
90 | kind: TOMBSTONE, | ||
91 | forward_parent: None, | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | |||
87 | pub(super) struct EventProcessor<'a, S: Sink> { | 96 | pub(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 | ||
5 | pub(crate) struct ParserInput<'t> { | 5 | pub(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 | ||
11 | impl<'t> ParserInput<'t> { | 25 | impl<'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 | |||
123 | impl From<SyntaxText<'_>> for String { | ||
124 | fn from(text: SyntaxText) -> String { | ||
125 | text.to_string() | ||
126 | } | ||
127 | } | ||
128 | |||
129 | impl 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 | |||
141 | impl 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 @@ | |||
1 | SOURCE_FILE@[0; 183) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 38) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 87) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 83) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 128) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 69) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 89) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 27) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 20) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 12) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 19) | 1 | SOURCE_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 @@ | |||
1 | SOURCE_FILE@[0; 20) | 1 | SOURCE_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 | ||
5 | mod 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 @@ | |||
1 | SOURCE_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) | ||