From ce1b34fd59a6145a4bb5682d672c846e101725d4 Mon Sep 17 00:00:00 2001 From: Michael Chesser Date: Tue, 7 Jan 2020 09:29:03 +1030 Subject: Improve const generics parsing - Handle const generics type args - Fix issue with const generic as first parameter in trait impl --- crates/ra_parser/src/grammar/items/traits.rs | 5 ++- crates/ra_parser/src/grammar/type_args.rs | 10 ++++- crates/ra_parser/src/syntax_kind/generated.rs | 1 + crates/ra_syntax/src/ast/generated.rs | 33 ++++++++++++++ .../test_data/parser/inline/ok/0039_type_arg.rs | 2 +- .../test_data/parser/inline/ok/0039_type_arg.txt | 51 ++++++++++++++-------- .../parser/inline/ok/0150_impl_type_params.rs | 1 + .../parser/inline/ok/0150_impl_type_params.txt | 38 ++++++++++++++++ xtask/src/ast_src.rs | 3 ++ 9 files changed, 123 insertions(+), 21 deletions(-) create mode 100644 crates/ra_syntax/test_data/parser/inline/ok/0150_impl_type_params.rs create mode 100644 crates/ra_syntax/test_data/parser/inline/ok/0150_impl_type_params.txt diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs index 2c560e824..964fd3041 100644 --- a/crates/ra_parser/src/grammar/items/traits.rs +++ b/crates/ra_parser/src/grammar/items/traits.rs @@ -100,6 +100,8 @@ pub(crate) fn impl_item_list(p: &mut Parser) { m.complete(p, ITEM_LIST); } +// test impl_type_params +// impl Bar {} fn choose_type_params_over_qpath(p: &Parser) -> bool { // There's an ambiguity between generic parameters and qualified paths in impls. // If we see `<` it may start both, so we have to inspect some following tokens. @@ -107,6 +109,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool { // but not qualified paths (with one exception): // `<` `>` - empty generic parameters // `<` `#` - generic parameters with attributes + // `<` `const` - const generic parameters // `<` (LIFETIME|IDENT) `>` - single generic parameter // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds @@ -119,7 +122,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool { if !p.at(T![<]) { return false; } - if p.nth(1) == T![#] || p.nth(1) == T![>] { + if p.nth(1) == T![#] || p.nth(1) == T![>] || p.nth(1) == CONST_KW { return true; } (p.nth(1) == LIFETIME || p.nth(1) == IDENT) diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs index 7256c2697..33d9973e9 100644 --- a/crates/ra_parser/src/grammar/type_args.rs +++ b/crates/ra_parser/src/grammar/type_args.rs @@ -26,7 +26,7 @@ pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) { } // test type_arg -// type A = B<'static, i32, Item=u64>; +// type A = B<'static, i32, 1, { 2 }, Item=u64>; fn type_arg(p: &mut Parser) { let m = p.start(); match p.current() { @@ -47,6 +47,14 @@ fn type_arg(p: &mut Parser) { types::type_(p); m.complete(p, ASSOC_TYPE_ARG); } + T!['{'] => { + expressions::block(p); + m.complete(p, CONST_ARG); + } + k if k.is_literal() => { + p.bump(k); + m.complete(p, CONST_ARG); + } _ => { types::type_(p); m.complete(p, TYPE_ARG); diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index 262c545e4..4b301d67a 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -234,6 +234,7 @@ pub enum SyntaxKind { LIFETIME_ARG, TYPE_ARG, ASSOC_TYPE_ARG, + CONST_ARG, PARAM_LIST, PARAM, SELF_PARAM, diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 2eb4b14d2..33d5578e7 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -3114,6 +3114,9 @@ impl TypeArgList { pub fn assoc_type_args(&self) -> AstChildren { AstChildren::new(&self.syntax) } + pub fn const_arg(&self) -> AstChildren { + AstChildren::new(&self.syntax) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeArg { @@ -3196,6 +3199,36 @@ impl AstNode for LifetimeArg { } impl LifetimeArg {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ConstArg { + pub(crate) syntax: SyntaxNode, +} +impl AstNode for ConstArg { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + CONST_ARG => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} +impl ConstArg { + pub fn literal(&self) -> Option { + AstChildren::new(&self.syntax).next() + } + pub fn block_expr(&self) -> Option { + AstChildren::new(&self.syntax).next() + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroItems { pub(crate) syntax: SyntaxNode, } diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rs b/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rs index 385c43131..0d07d7651 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rs @@ -1 +1 @@ -type A = B<'static, i32, Item=u64>; +type A = B<'static, i32, 1, { 2 }, Item=u64>; diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.txt b/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.txt index 4786bf77a..025faf5ca 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.txt @@ -1,5 +1,5 @@ -SOURCE_FILE@[0; 36) - TYPE_ALIAS_DEF@[0; 35) +SOURCE_FILE@[0; 46) + TYPE_ALIAS_DEF@[0; 45) TYPE_KW@[0; 4) "type" WHITESPACE@[4; 5) " " NAME@[5; 6) @@ -7,12 +7,12 @@ SOURCE_FILE@[0; 36) WHITESPACE@[6; 7) " " EQ@[7; 8) "=" WHITESPACE@[8; 9) " " - PATH_TYPE@[9; 34) - PATH@[9; 34) - PATH_SEGMENT@[9; 34) + PATH_TYPE@[9; 44) + PATH@[9; 44) + PATH_SEGMENT@[9; 44) NAME_REF@[9; 10) IDENT@[9; 10) "B" - TYPE_ARG_LIST@[10; 34) + TYPE_ARG_LIST@[10; 44) L_ANGLE@[10; 11) "<" LIFETIME_ARG@[11; 18) LIFETIME@[11; 18) "\'static" @@ -26,15 +26,30 @@ SOURCE_FILE@[0; 36) IDENT@[20; 23) "i32" COMMA@[23; 24) "," WHITESPACE@[24; 25) " " - ASSOC_TYPE_ARG@[25; 33) - NAME_REF@[25; 29) - IDENT@[25; 29) "Item" - EQ@[29; 30) "=" - PATH_TYPE@[30; 33) - PATH@[30; 33) - PATH_SEGMENT@[30; 33) - NAME_REF@[30; 33) - IDENT@[30; 33) "u64" - R_ANGLE@[33; 34) ">" - SEMI@[34; 35) ";" - WHITESPACE@[35; 36) "\n" + CONST_ARG@[25; 26) + INT_NUMBER@[25; 26) "1" + COMMA@[26; 27) "," + WHITESPACE@[27; 28) " " + CONST_ARG@[28; 33) + BLOCK_EXPR@[28; 33) + BLOCK@[28; 33) + L_CURLY@[28; 29) "{" + WHITESPACE@[29; 30) " " + LITERAL@[30; 31) + INT_NUMBER@[30; 31) "2" + WHITESPACE@[31; 32) " " + R_CURLY@[32; 33) "}" + COMMA@[33; 34) "," + WHITESPACE@[34; 35) " " + ASSOC_TYPE_ARG@[35; 43) + NAME_REF@[35; 39) + IDENT@[35; 39) "Item" + EQ@[39; 40) "=" + PATH_TYPE@[40; 43) + PATH@[40; 43) + PATH_SEGMENT@[40; 43) + NAME_REF@[40; 43) + IDENT@[40; 43) "u64" + R_ANGLE@[43; 44) ">" + SEMI@[44; 45) ";" + WHITESPACE@[45; 46) "\n" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0150_impl_type_params.rs b/crates/ra_syntax/test_data/parser/inline/ok/0150_impl_type_params.rs new file mode 100644 index 000000000..cb0a105c2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0150_impl_type_params.rs @@ -0,0 +1 @@ +impl Bar {} diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0150_impl_type_params.txt b/crates/ra_syntax/test_data/parser/inline/ok/0150_impl_type_params.txt new file mode 100644 index 000000000..47fadef85 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0150_impl_type_params.txt @@ -0,0 +1,38 @@ +SOURCE_FILE@[0; 29) + IMPL_BLOCK@[0; 28) + IMPL_KW@[0; 4) "impl" + TYPE_PARAM_LIST@[4; 18) + L_ANGLE@[4; 5) "<" + CONST_PARAM@[5; 17) + CONST_KW@[5; 10) "const" + WHITESPACE@[10; 11) " " + NAME@[11; 12) + IDENT@[11; 12) "N" + COLON@[12; 13) ":" + WHITESPACE@[13; 14) " " + PATH_TYPE@[14; 17) + PATH@[14; 17) + PATH_SEGMENT@[14; 17) + NAME_REF@[14; 17) + IDENT@[14; 17) "u32" + R_ANGLE@[17; 18) ">" + WHITESPACE@[18; 19) " " + PATH_TYPE@[19; 25) + PATH@[19; 25) + PATH_SEGMENT@[19; 25) + NAME_REF@[19; 22) + IDENT@[19; 22) "Bar" + TYPE_ARG_LIST@[22; 25) + L_ANGLE@[22; 23) "<" + TYPE_ARG@[23; 24) + PATH_TYPE@[23; 24) + PATH@[23; 24) + PATH_SEGMENT@[23; 24) + NAME_REF@[23; 24) + IDENT@[23; 24) "N" + R_ANGLE@[24; 25) ">" + WHITESPACE@[25; 26) " " + ITEM_LIST@[26; 28) + L_CURLY@[26; 27) "{" + R_CURLY@[27; 28) "}" + WHITESPACE@[28; 29) "\n" diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index d494a4a38..67d1f41bc 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -206,6 +206,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { "LIFETIME_ARG", "TYPE_ARG", "ASSOC_TYPE_ARG", + "CONST_ARG", "PARAM_LIST", "PARAM", "SELF_PARAM", @@ -511,10 +512,12 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { type_args: [TypeArg], lifetime_args: [LifetimeArg], assoc_type_args: [AssocTypeArg], + const_arg: [ConstArg], } struct TypeArg { TypeRef } struct AssocTypeArg { NameRef, TypeRef } struct LifetimeArg {} + struct ConstArg { Literal, BlockExpr } struct MacroItems: ModuleItemOwner, FnDefOwner { } -- cgit v1.2.3