From 23fdc562bf06bd001ec728d63a8f5b945bd96700 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Sat, 30 Mar 2019 17:11:21 +0200 Subject: Add new TYPE_BOUND_LIST and TYPE_BOUND syntax kinds These are now used when parsing type bounds. In addition parsing paths inside a bound now does not recursively parse paths, rather they are treated as separate bounds, separated by +. --- crates/ra_parser/src/grammar/items/traits.rs | 1 + crates/ra_parser/src/grammar/type_params.rs | 11 ++++- crates/ra_parser/src/syntax_kind/generated.rs | 4 ++ crates/ra_syntax/src/ast/generated.rs | 68 +++++++++++++++++++++++++++ crates/ra_syntax/src/grammar.ron | 13 +++++ 5 files changed, 95 insertions(+), 2 deletions(-) (limited to 'crates') 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::*; // test trait_item // trait T: Hash + Clone where U: Copy {} +// trait X: Hash + Clone where U: Copy {} pub(super) fn trait_def(p: &mut Parser) { assert!(p.at(TRAIT_KW)); 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) { } pub(super) fn bounds_without_colon(p: &mut Parser) { + let outer = p.start(); loop { + let inner = p.start(); let has_paren = p.eat(L_PAREN); p.eat(QUESTION); match p.current() { LIFETIME => p.bump(), FOR_KW => types::for_type(p), - _ if paths::is_path_start(p) => types::path_type(p), - _ => break, + _ if paths::is_path_start(p) => types::path_type_(p, false), + _ => { + inner.abandon(p); + break; + } } if has_paren { p.expect(R_PAREN); } + inner.complete(p, TYPE_BOUND); if !p.eat(PLUS) { break; } } + outer.complete(p, TYPE_BOUND_LIST); } // 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 { PARAM, SELF_PARAM, ARG_LIST, + TYPE_BOUND, + TYPE_BOUND_LIST, } use self::SyntaxKind::*; @@ -567,6 +569,8 @@ impl SyntaxKind { PARAM => &SyntaxInfo { name: "PARAM" }, SELF_PARAM => &SyntaxInfo { name: "SELF_PARAM" }, ARG_LIST => &SyntaxInfo { name: "ARG_LIST" }, + TYPE_BOUND => &SyntaxInfo { name: "TYPE_BOUND" }, + TYPE_BOUND_LIST => &SyntaxInfo { name: "TYPE_BOUND_LIST" }, TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" }, EOF => &SyntaxInfo { name: "EOF" }, } 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 { } } +// TypeBound +#[derive(Debug, PartialEq, Eq, Hash)] +#[repr(transparent)] +pub struct TypeBound { + pub(crate) syntax: SyntaxNode, +} +unsafe impl TransparentNewType for TypeBound { + type Repr = rowan::SyntaxNode; +} + +impl AstNode for TypeBound { + fn cast(syntax: &SyntaxNode) -> Option<&Self> { + match syntax.kind() { + TYPE_BOUND => Some(TypeBound::from_repr(syntax.into_repr())), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} + +impl ToOwned for TypeBound { + type Owned = TreeArc; + fn to_owned(&self) -> TreeArc { TreeArc::cast(self.syntax.to_owned()) } +} + + +impl TypeBound { + pub fn type_ref(&self) -> Option<&TypeRef> { + super::child_opt(self) + } + + pub fn lifetime(&self) -> Option<&Lifetime> { + super::child_opt(self) + } +} + +// TypeBoundList +#[derive(Debug, PartialEq, Eq, Hash)] +#[repr(transparent)] +pub struct TypeBoundList { + pub(crate) syntax: SyntaxNode, +} +unsafe impl TransparentNewType for TypeBoundList { + type Repr = rowan::SyntaxNode; +} + +impl AstNode for TypeBoundList { + fn cast(syntax: &SyntaxNode) -> Option<&Self> { + match syntax.kind() { + TYPE_BOUND_LIST => Some(TypeBoundList::from_repr(syntax.into_repr())), + _ => None, + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} + +impl ToOwned for TypeBoundList { + type Owned = TreeArc; + fn to_owned(&self) -> TreeArc { TreeArc::cast(self.syntax.to_owned()) } +} + + +impl TypeBoundList { + pub fn bounds(&self) -> impl Iterator { + super::children(self) + } +} + // TypeParam #[derive(Debug, PartialEq, Eq, Hash)] #[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( "PARAM", "SELF_PARAM", "ARG_LIST", + "TYPE_BOUND", + "TYPE_BOUND_LIST", ], ast: { "SourceFile": ( @@ -577,6 +579,17 @@ Grammar( traits: ["AttrsOwner"], ), "Lifetime": ( traits: ["AstToken"] ), + "TypeBound": ( + options: [ + "TypeRef", + "Lifetime", + ] + ), + "TypeBoundList": ( + collections: [ + ["bounds", "TypeBound"], + ] + ), "WhereClause": (), "ExprStmt": ( options: [ ["expr", "Expr"] ] -- cgit v1.2.3