From bbaabb21784134e874d8f5eb55dc4858e0c295bb Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 19 Mar 2021 22:44:34 +0800 Subject: [PATCH] Support splats inside tuple literals in type names (#10430) --- spec/compiler/formatter/formatter_spec.cr | 1 + spec/compiler/parser/parser_spec.cr | 1 + src/compiler/crystal/syntax/parser.cr | 12 ++++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/spec/compiler/formatter/formatter_spec.cr b/spec/compiler/formatter/formatter_spec.cr index 76cd16bb7a03..4541df4d0c99 100644 --- a/spec/compiler/formatter/formatter_spec.cr +++ b/spec/compiler/formatter/formatter_spec.cr @@ -107,6 +107,7 @@ describe Crystal::Formatter do assert_format "Foo( A , 1 )", "Foo(A, 1)" assert_format "Foo( x: Int32 )", "Foo(x: Int32)" assert_format "Foo( x: Int32 , y: Float64 )", "Foo(x: Int32, y: Float64)" + assert_format "Foo( * T, { * A ,*\n B } )", "Foo(*T, {*A, *B})" assert_format "NamedTuple(a: Int32,)", "NamedTuple(a: Int32)" assert_format "NamedTuple(\n a: Int32,\n)" diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 5bdbf690b6f2..e0b21d4a3b2a 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -569,6 +569,7 @@ module Crystal it_parses "Foo(typeof(1), typeof(2))", Generic.new("Foo".path, [TypeOf.new([1.int32] of ASTNode), TypeOf.new([2.int32] of ASTNode)] of ASTNode) it_parses "Foo({X, Y})", Generic.new("Foo".path, [Generic.new(Path.global("Tuple"), ["X".path, "Y".path] of ASTNode)] of ASTNode) it_parses "Foo({X, Y,})", Generic.new("Foo".path, [Generic.new(Path.global("Tuple"), ["X".path, "Y".path] of ASTNode)] of ASTNode) + it_parses "Foo({*X, *{Y}})", Generic.new("Foo".path, [Generic.new(Path.global("Tuple"), ["X".path.splat, Generic.new(Path.global("Tuple"), ["Y".path] of ASTNode).splat] of ASTNode)] of ASTNode) it_parses "Foo({->})", Generic.new("Foo".path, [Generic.new(Path.global("Tuple"), [ProcNotation.new] of ASTNode)] of ASTNode) it_parses "Foo({String, ->})", Generic.new("Foo".path, [Generic.new(Path.global("Tuple"), ["String".path, ProcNotation.new] of ASTNode)] of ASTNode) it_parses "Foo({String, ->, ->})", Generic.new("Foo".path, [Generic.new(Path.global("Tuple"), ["String".path, ProcNotation.new, ProcNotation.new] of ASTNode)] of ASTNode) diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 0f9e58e83632..075ff20303f1 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -4788,7 +4788,7 @@ module Crystal if named_tuple_start? || @token.type == :DELIMITER_START type = make_named_tuple_type parse_named_type_args(:"}") else - type = make_tuple_type parse_union_types(:"}") + type = make_tuple_type parse_union_types(:"}", allow_splats: true) end check :"}" next_token_skip_space @@ -4828,13 +4828,17 @@ module Crystal end end - def parse_union_types(end_token) - types = [parse_union_type] + def parse_union_types(end_token, *, allow_splats = false) + type = allow_splats ? parse_type_splat { parse_union_type } : parse_union_type + types = [type] + while @token.type == :"," next_token_skip_space_or_newline break if @token.type == end_token # allow trailing comma - types << parse_union_type + type = allow_splats ? parse_type_splat { parse_union_type } : parse_union_type + types << type end + types end