diff options
-rw-r--r-- | crates/ra_parser/src/grammar/items/traits.rs | 1 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/type_params.rs | 11 | ||||
-rw-r--r-- | crates/ra_parser/src/syntax_kind/generated.rs | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 68 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 13 |
5 files changed, 95 insertions, 2 deletions
diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs index f49615f6b..d03a6be0d 100644 --- a/crates/ra_parser/src/grammar/items/traits.rs +++ b/crates/ra_parser/src/grammar/items/traits.rs | |||
@@ -2,6 +2,7 @@ use super::*; | |||
2 | 2 | ||
3 | // test trait_item | 3 | // test trait_item |
4 | // trait T<U>: Hash + Clone where U: Copy {} | 4 | // trait T<U>: Hash + Clone where U: Copy {} |
5 | // trait X<U: Debug + Display>: Hash + Clone where U: Copy {} | ||
5 | pub(super) fn trait_def(p: &mut Parser) { | 6 | pub(super) fn trait_def(p: &mut Parser) { |
6 | assert!(p.at(TRAIT_KW)); | 7 | assert!(p.at(TRAIT_KW)); |
7 | p.bump(); | 8 | p.bump(); |
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs index 40f998682..e28c124cd 100644 --- a/crates/ra_parser/src/grammar/type_params.rs +++ b/crates/ra_parser/src/grammar/type_params.rs | |||
@@ -80,22 +80,29 @@ fn lifetime_bounds(p: &mut Parser) { | |||
80 | } | 80 | } |
81 | 81 | ||
82 | pub(super) fn bounds_without_colon(p: &mut Parser) { | 82 | pub(super) fn bounds_without_colon(p: &mut Parser) { |
83 | let outer = p.start(); | ||
83 | loop { | 84 | loop { |
85 | let inner = p.start(); | ||
84 | let has_paren = p.eat(L_PAREN); | 86 | let has_paren = p.eat(L_PAREN); |
85 | p.eat(QUESTION); | 87 | p.eat(QUESTION); |
86 | match p.current() { | 88 | match p.current() { |
87 | LIFETIME => p.bump(), | 89 | LIFETIME => p.bump(), |
88 | FOR_KW => types::for_type(p), | 90 | FOR_KW => types::for_type(p), |
89 | _ if paths::is_path_start(p) => types::path_type(p), | 91 | _ if paths::is_path_start(p) => types::path_type_(p, false), |
90 | _ => break, | 92 | _ => { |
93 | inner.abandon(p); | ||
94 | break; | ||
95 | } | ||
91 | } | 96 | } |
92 | if has_paren { | 97 | if has_paren { |
93 | p.expect(R_PAREN); | 98 | p.expect(R_PAREN); |
94 | } | 99 | } |
100 | inner.complete(p, TYPE_BOUND); | ||
95 | if !p.eat(PLUS) { | 101 | if !p.eat(PLUS) { |
96 | break; | 102 | break; |
97 | } | 103 | } |
98 | } | 104 | } |
105 | outer.complete(p, TYPE_BOUND_LIST); | ||
99 | } | 106 | } |
100 | 107 | ||
101 | // test where_clause | 108 | // test where_clause |
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index 03247ae38..547af1b27 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs | |||
@@ -228,6 +228,8 @@ pub enum SyntaxKind { | |||
228 | PARAM, | 228 | PARAM, |
229 | SELF_PARAM, | 229 | SELF_PARAM, |
230 | ARG_LIST, | 230 | ARG_LIST, |
231 | TYPE_BOUND, | ||
232 | TYPE_BOUND_LIST, | ||
231 | } | 233 | } |
232 | use self::SyntaxKind::*; | 234 | use self::SyntaxKind::*; |
233 | 235 | ||
@@ -567,6 +569,8 @@ impl SyntaxKind { | |||
567 | PARAM => &SyntaxInfo { name: "PARAM" }, | 569 | PARAM => &SyntaxInfo { name: "PARAM" }, |
568 | SELF_PARAM => &SyntaxInfo { name: "SELF_PARAM" }, | 570 | SELF_PARAM => &SyntaxInfo { name: "SELF_PARAM" }, |
569 | ARG_LIST => &SyntaxInfo { name: "ARG_LIST" }, | 571 | ARG_LIST => &SyntaxInfo { name: "ARG_LIST" }, |
572 | TYPE_BOUND => &SyntaxInfo { name: "TYPE_BOUND" }, | ||
573 | TYPE_BOUND_LIST => &SyntaxInfo { name: "TYPE_BOUND_LIST" }, | ||
570 | TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" }, | 574 | TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" }, |
571 | EOF => &SyntaxInfo { name: "EOF" }, | 575 | EOF => &SyntaxInfo { name: "EOF" }, |
572 | } | 576 | } |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 47a37e4d1..faf80bc32 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -4369,6 +4369,74 @@ impl TypeArgList { | |||
4369 | } | 4369 | } |
4370 | } | 4370 | } |
4371 | 4371 | ||
4372 | // TypeBound | ||
4373 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
4374 | #[repr(transparent)] | ||
4375 | pub struct TypeBound { | ||
4376 | pub(crate) syntax: SyntaxNode, | ||
4377 | } | ||
4378 | unsafe impl TransparentNewType for TypeBound { | ||
4379 | type Repr = rowan::SyntaxNode<RaTypes>; | ||
4380 | } | ||
4381 | |||
4382 | impl AstNode for TypeBound { | ||
4383 | fn cast(syntax: &SyntaxNode) -> Option<&Self> { | ||
4384 | match syntax.kind() { | ||
4385 | TYPE_BOUND => Some(TypeBound::from_repr(syntax.into_repr())), | ||
4386 | _ => None, | ||
4387 | } | ||
4388 | } | ||
4389 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
4390 | } | ||
4391 | |||
4392 | impl ToOwned for TypeBound { | ||
4393 | type Owned = TreeArc<TypeBound>; | ||
4394 | fn to_owned(&self) -> TreeArc<TypeBound> { TreeArc::cast(self.syntax.to_owned()) } | ||
4395 | } | ||
4396 | |||
4397 | |||
4398 | impl TypeBound { | ||
4399 | pub fn type_ref(&self) -> Option<&TypeRef> { | ||
4400 | super::child_opt(self) | ||
4401 | } | ||
4402 | |||
4403 | pub fn lifetime(&self) -> Option<&Lifetime> { | ||
4404 | super::child_opt(self) | ||
4405 | } | ||
4406 | } | ||
4407 | |||
4408 | // TypeBoundList | ||
4409 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
4410 | #[repr(transparent)] | ||
4411 | pub struct TypeBoundList { | ||
4412 | pub(crate) syntax: SyntaxNode, | ||
4413 | } | ||
4414 | unsafe impl TransparentNewType for TypeBoundList { | ||
4415 | type Repr = rowan::SyntaxNode<RaTypes>; | ||
4416 | } | ||
4417 | |||
4418 | impl AstNode for TypeBoundList { | ||
4419 | fn cast(syntax: &SyntaxNode) -> Option<&Self> { | ||
4420 | match syntax.kind() { | ||
4421 | TYPE_BOUND_LIST => Some(TypeBoundList::from_repr(syntax.into_repr())), | ||
4422 | _ => None, | ||
4423 | } | ||
4424 | } | ||
4425 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
4426 | } | ||
4427 | |||
4428 | impl ToOwned for TypeBoundList { | ||
4429 | type Owned = TreeArc<TypeBoundList>; | ||
4430 | fn to_owned(&self) -> TreeArc<TypeBoundList> { TreeArc::cast(self.syntax.to_owned()) } | ||
4431 | } | ||
4432 | |||
4433 | |||
4434 | impl TypeBoundList { | ||
4435 | pub fn bounds(&self) -> impl Iterator<Item = &TypeBound> { | ||
4436 | super::children(self) | ||
4437 | } | ||
4438 | } | ||
4439 | |||
4372 | // TypeParam | 4440 | // TypeParam |
4373 | #[derive(Debug, PartialEq, Eq, Hash)] | 4441 | #[derive(Debug, PartialEq, Eq, Hash)] |
4374 | #[repr(transparent)] | 4442 | #[repr(transparent)] |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index ad6d74162..660a2b207 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -243,6 +243,8 @@ Grammar( | |||
243 | "PARAM", | 243 | "PARAM", |
244 | "SELF_PARAM", | 244 | "SELF_PARAM", |
245 | "ARG_LIST", | 245 | "ARG_LIST", |
246 | "TYPE_BOUND", | ||
247 | "TYPE_BOUND_LIST", | ||
246 | ], | 248 | ], |
247 | ast: { | 249 | ast: { |
248 | "SourceFile": ( | 250 | "SourceFile": ( |
@@ -577,6 +579,17 @@ Grammar( | |||
577 | traits: ["AttrsOwner"], | 579 | traits: ["AttrsOwner"], |
578 | ), | 580 | ), |
579 | "Lifetime": ( traits: ["AstToken"] ), | 581 | "Lifetime": ( traits: ["AstToken"] ), |
582 | "TypeBound": ( | ||
583 | options: [ | ||
584 | "TypeRef", | ||
585 | "Lifetime", | ||
586 | ] | ||
587 | ), | ||
588 | "TypeBoundList": ( | ||
589 | collections: [ | ||
590 | ["bounds", "TypeBound"], | ||
591 | ] | ||
592 | ), | ||
580 | "WhereClause": (), | 593 | "WhereClause": (), |
581 | "ExprStmt": ( | 594 | "ExprStmt": ( |
582 | options: [ ["expr", "Expr"] ] | 595 | options: [ ["expr", "Expr"] ] |