From b56c7d9db282e054401211e38b832cb3e2f79963 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Thu, 11 Jan 2024 06:25:48 +0800 Subject: [PATCH] Allow multiple parameters and blocks for operators ending in `=` (#14159) --- spec/compiler/parser/parser_spec.cr | 8 +++++++- src/compiler/crystal/syntax/parser.cr | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 41fad5cc3a89..2fa1a5b4c4a7 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -290,10 +290,16 @@ module Crystal assert_syntax_error "def foo=(*args); end", "setter method 'foo=' cannot have more than one parameter" assert_syntax_error "def foo=(**kwargs); end", "setter method 'foo=' cannot have more than one parameter" assert_syntax_error "def foo=(&block); end", "setter method 'foo=' cannot have a block" - assert_syntax_error "def []=(&block); end", "setter method '[]=' cannot have a block" assert_syntax_error "f.[]= do |a| end", "setter method '[]=' cannot be called with a block" assert_syntax_error "f.[]= { |bar| }", "setter method '[]=' cannot be called with a block" + # #10397 + %w(<= >= == != []= ===).each do |operator| + it_parses "def #{operator}(other, file = 1); end", Def.new(operator, ["other".arg, Arg.new("file", 1.int32)]) + it_parses "def #{operator}(*args, **opts); end", Def.new(operator, ["args".arg], splat_index: 0, double_splat: "opts".arg) + it_parses "def #{operator}(*args, **opts, &); end", Def.new(operator, ["args".arg], splat_index: 0, double_splat: "opts".arg, block_arg: Arg.new(""), block_arity: 0) + end + # #5895, #6042, #5997 %w( begin nil true false yield with abstract diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 751608468cd5..f14399212e65 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -3658,8 +3658,8 @@ module Crystal end_location = token_end_location - if name.ends_with?('=') - if name != "[]=" && (params.size > 1 || found_splat || found_double_splat) + if Lexer.setter?(name) + if params.size > 1 || found_splat || found_double_splat raise "setter method '#{name}' cannot have more than one parameter" elsif found_block raise "setter method '#{name}' cannot have a block"