diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c77522027a4b..5f169b781fcf 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -39,7 +39,7 @@ output by `rubocop -V`, include them as well. Here's an example: ``` $ [bundle exec] rubocop -V -1.75.4 (using Parser 3.3.5.0, rubocop-ast 1.32.3, analyzing as Ruby 3.3, running on ruby 3.3.5) [x86_64-linux] +1.75.5 (using Parser 3.3.5.0, rubocop-ast 1.32.3, analyzing as Ruby 3.3, running on ruby 3.3.5) [x86_64-linux] - rubocop-performance 1.22.1 - rubocop-rspec 3.1.0 ``` diff --git a/CHANGELOG.md b/CHANGELOG.md index ad512957ccd2..8e7c428363a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,26 @@ ## master (unreleased) +## 1.75.5 (2025-05-05) + +### Bug fixes + +* [#14148](https://github.com/rubocop/rubocop/pull/14148): Fix an infinite loop error for `Layout/SpaceAfterSemicolon` with `Layout/SpaceBeforeSemicolon` when a sequence of semicolons appears. ([@koic][]) +* [#14145](https://github.com/rubocop/rubocop/pull/14145): Fix `Lint/ArrayLiteralInRegexp` cop error on empty interpolation. ([@viralpraxis][]) +* [#14072](https://github.com/rubocop/rubocop/issues/14072): Fix autocorrect issue in `Layout/HashAlignment`. ([@jonas054][]) +* [#14131](https://github.com/rubocop/rubocop/issues/14131): Fix false positives for `Style/ArgumentsForwarding` when using anonymous block argument forwarding to a method with a block. ([@koic][]) +* [#14140](https://github.com/rubocop/rubocop/pull/14140): Fix `Layout/LeadingCommentSpace` to allow splitting long inline RBS comment signatures across multiple lines. ([@Morriar][]) +* [#14147](https://github.com/rubocop/rubocop/pull/14147): Fix `Lint/LiteralAsCondition` cop error on `if` without body. ([@viralpraxis][]) +* [#14151](https://github.com/rubocop/rubocop/pull/14151): Fix `Lint/Void` cop error on nested empty `begin`. ([@viralpraxis][]) +* [#13547](https://github.com/rubocop/rubocop/pull/13547): Fix `Style/IdenticalConditionalBranches` cop failure in case of `if` node with implicit `then`. ([@viralpraxis][]) +* [#14146](https://github.com/rubocop/rubocop/pull/14146): Fix `Style/MethodCallWithArgsParentheses` cop error on complex numbers when `EnforcedStyle` is set to `omit_parentheses`. ([@viralpraxis][]) +* [#14137](https://github.com/rubocop/rubocop/issues/14137): Fix `Style/TrailingCommaInArguments` cop error if `EnforcedStyleForMultiline` is set to `comma`. ([@viralpraxis][]) + +### Changes + +* [#14144](https://github.com/rubocop/rubocop/pull/14144): `Layout/SpaceInsideArrayLiteralBrackets` make aware of array pattern matching. ([@koic][]) +* [#14142](https://github.com/rubocop/rubocop/issues/14142): `Layout/SpaceInsideHashLiteralBraces` make aware of hash pattern matching. ([@koic][]) + ## 1.75.4 (2025-04-28) ### Bug fixes @@ -4038,3 +4058,4 @@ [@jtannas]: https://github.com/jtannas [@flavorjones]: https://github.com/flavorjones [@sferik]: https://github.com/sferik +[@Morriar]: https://github.com/Morriar diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7aacf0dd4b68..e17bb73b23bd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ do so. ```console $ rubocop -V -1.75.4 (using Parser 3.3.5.0, rubocop-ast 1.32.3, analyzing as Ruby 3.3, running on ruby 3.3.5) [x86_64-linux] +1.75.5 (using Parser 3.3.5.0, rubocop-ast 1.32.3, analyzing as Ruby 3.3, running on ruby 3.3.5) [x86_64-linux] - rubocop-performance 1.22.1 - rubocop-rspec 3.1.0 ``` diff --git a/docs/modules/ROOT/pages/cops_layout.adoc b/docs/modules/ROOT/pages/cops_layout.adoc index fe6306572731..1ca6cc4474a6 100644 --- a/docs/modules/ROOT/pages/cops_layout.adoc +++ b/docs/modules/ROOT/pages/cops_layout.adoc @@ -833,7 +833,7 @@ end | Name | Default value | Configurable values | Categories -| `{"module_inclusion" => ["include", "prepend", "extend"]}` +| `{"module_inclusion"=>["include", "prepend", "extend"]}` | | ExpectedOrder @@ -4425,6 +4425,12 @@ include Enumerable #[Integer] attr_reader :name #: String attr_reader :age #: Integer? + +#: ( +#| Integer, +#| String +#| ) -> void +def foo; end ---- [#allowrbsinlineannotation_-true-layoutleadingcommentspace] @@ -4438,6 +4444,12 @@ include Enumerable #[Integer] attr_reader :name #: String attr_reader :age #: Integer? + +#: ( +#| Integer, +#| String +#| ) -> void +def foo; end ---- [#allowsteepannotation_-false-_default_-layoutleadingcommentspace] @@ -7212,6 +7224,8 @@ a = -> (x, y) { x + y } Checks that brackets used for array literals have or don't have surrounding space depending on configuration. +Array pattern matching is handled in the same way. + [#examples-layoutspaceinsidearrayliteralbrackets] === Examples @@ -7504,6 +7518,8 @@ some_array.each { } Checks that braces used for hash literals have or don't have surrounding space depending on configuration. +Hash pattern matching is handled in the same way. + [#examples-layoutspaceinsidehashliteralbraces] === Examples diff --git a/docs/modules/ROOT/pages/cops_lint.adoc b/docs/modules/ROOT/pages/cops_lint.adoc index 80e7bc59dd78..f60bd420c1b3 100644 --- a/docs/modules/ROOT/pages/cops_lint.adoc +++ b/docs/modules/ROOT/pages/cops_lint.adoc @@ -1119,11 +1119,11 @@ require 'my_debugger/start' | Name | Default value | Configurable values | DebuggerMethods -| `{"Kernel" => ["binding.irb", "Kernel.binding.irb"], "Byebug" => ["byebug", "remote_byebug", "Kernel.byebug", "Kernel.remote_byebug"], "Capybara" => ["page.save_and_open_page", "page.save_and_open_screenshot", "page.save_page", "page.save_screenshot", "save_and_open_page", "save_and_open_screenshot", "save_page", "save_screenshot"], "debug.rb" => ["binding.b", "binding.break", "Kernel.binding.b", "Kernel.binding.break"], "Pry" => ["binding.pry", "binding.remote_pry", "binding.pry_remote", "Kernel.binding.pry", "Kernel.binding.remote_pry", "Kernel.binding.pry_remote", "Pry.rescue", "pry"], "Rails" => ["debugger", "Kernel.debugger"], "RubyJard" => ["jard"], "WebConsole" => ["binding.console"]}` +| `{"Kernel"=>["binding.irb", "Kernel.binding.irb"], "Byebug"=>["byebug", "remote_byebug", "Kernel.byebug", "Kernel.remote_byebug"], "Capybara"=>["page.save_and_open_page", "page.save_and_open_screenshot", "page.save_page", "page.save_screenshot", "save_and_open_page", "save_and_open_screenshot", "save_page", "save_screenshot"], "debug.rb"=>["binding.b", "binding.break", "Kernel.binding.b", "Kernel.binding.break"], "Pry"=>["binding.pry", "binding.remote_pry", "binding.pry_remote", "Kernel.binding.pry", "Kernel.binding.remote_pry", "Kernel.binding.pry_remote", "Pry.rescue", "pry"], "Rails"=>["debugger", "Kernel.debugger"], "RubyJard"=>["jard"], "WebConsole"=>["binding.console"]}` | | DebuggerRequires -| `{"debug.rb" => ["debug/open", "debug/start"]}` +| `{"debug.rb"=>["debug/open", "debug/start"]}` | |=== @@ -1230,7 +1230,7 @@ Etc::Passwd | Name | Default value | Configurable values | DeprecatedConstants -| `{"NIL" => {"Alternative" => "nil", "DeprecatedVersion" => "2.4"}, "TRUE" => {"Alternative" => "true", "DeprecatedVersion" => "2.4"}, "FALSE" => {"Alternative" => "false", "DeprecatedVersion" => "2.4"}, "Net::HTTPServerException" => {"Alternative" => "Net::HTTPClientException", "DeprecatedVersion" => "2.6"}, "Random::DEFAULT" => {"Alternative" => "Random.new", "DeprecatedVersion" => "3.0"}, "Struct::Group" => {"Alternative" => "Etc::Group", "DeprecatedVersion" => "3.0"}, "Struct::Passwd" => {"Alternative" => "Etc::Passwd", "DeprecatedVersion" => "3.0"}}` +| `{"NIL"=>{"Alternative"=>"nil", "DeprecatedVersion"=>"2.4"}, "TRUE"=>{"Alternative"=>"true", "DeprecatedVersion"=>"2.4"}, "FALSE"=>{"Alternative"=>"false", "DeprecatedVersion"=>"2.4"}, "Net::HTTPServerException"=>{"Alternative"=>"Net::HTTPClientException", "DeprecatedVersion"=>"2.6"}, "Random::DEFAULT"=>{"Alternative"=>"Random.new", "DeprecatedVersion"=>"3.0"}, "Struct::Group"=>{"Alternative"=>"Etc::Group", "DeprecatedVersion"=>"3.0"}, "Struct::Passwd"=>{"Alternative"=>"Etc::Passwd", "DeprecatedVersion"=>"3.0"}}` | |=== @@ -7285,7 +7285,7 @@ values.sort { |*x| x[0] <=> x[1] } | Name | Default value | Configurable values | Methods -| `{"chunk_while" => 2, "each_with_index" => 2, "each_with_object" => 2, "inject" => 2, "max" => 2, "min" => 2, "minmax" => 2, "reduce" => 2, "slice_when" => 2, "sort" => 2}` +| `{"chunk_while"=>2, "each_with_index"=>2, "each_with_object"=>2, "inject"=>2, "max"=>2, "min"=>2, "minmax"=>2, "reduce"=>2, "slice_when"=>2, "sort"=>2}` | |=== diff --git a/docs/modules/ROOT/pages/cops_naming.adoc b/docs/modules/ROOT/pages/cops_naming.adoc index cef09a31f43f..72ec61cc43af 100644 --- a/docs/modules/ROOT/pages/cops_naming.adoc +++ b/docs/modules/ROOT/pages/cops_naming.adoc @@ -806,7 +806,7 @@ TeslaVehicle | Boolean | FlaggedTerms -| `{"whitelist" => {"Regex" => /white[-_\s]?list/, "Suggestions" => ["allowlist", "permit"]}, "blacklist" => {"Regex" => /black[-_\s]?list/, "Suggestions" => ["denylist", "block"]}, "slave" => {"WholeWord" => true, "Suggestions" => ["replica", "secondary", "follower"]}}` +| `{"whitelist"=>{"Regex"=>/white[-_\s]?list/, "Suggestions"=>["allowlist", "permit"]}, "blacklist"=>{"Regex"=>/black[-_\s]?list/, "Suggestions"=>["denylist", "block"]}, "slave"=>{"WholeWord"=>true, "Suggestions"=>["replica", "secondary", "follower"]}}` | |=== diff --git a/docs/modules/ROOT/pages/cops_style.adoc b/docs/modules/ROOT/pages/cops_style.adoc index 494f7632a4be..ee8f58adde8a 100644 --- a/docs/modules/ROOT/pages/cops_style.adoc +++ b/docs/modules/ROOT/pages/cops_style.adoc @@ -2350,7 +2350,7 @@ items.include? | Name | Default value | Configurable values | PreferredMethods -| `{"collect" => "map", "collect!" => "map!", "collect_concat" => "flat_map", "inject" => "reduce", "detect" => "find", "find_all" => "select", "member?" => "include?"}` +| `{"collect"=>"map", "collect!"=>"map!", "collect_concat"=>"flat_map", "inject"=>"reduce", "detect"=>"find", "find_all"=>"select", "member?"=>"include?"}` | | MethodsAcceptingSymbol @@ -7917,11 +7917,11 @@ end | Name | Default value | Configurable values | InverseMethods -| `{any?: :none?, even?: :odd?, "==": :!=, "=~": :!~, "<": :>=, ">": :<=}` +| `{:any?=>:none?, :even?=>:odd?, :===>:!=, :=~=>:!~, :<=>:>=, :>=>:<=}` | | InverseBlocks -| `{select: :reject, select!: :reject!}` +| `{:select=>:reject, :select!=>:reject!}` | |=== @@ -7999,7 +7999,7 @@ foo if !condition | Name | Default value | Configurable values | InverseMethods -| `{"!=": :==, ">": :<=, "<=": :>, "<": :>=, ">=": :<, "!~": :=~, zero?: :nonzero?, nonzero?: :zero?, any?: :none?, none?: :any?, even?: :odd?, odd?: :even?}` +| `{:!==>:==, :>=>:<=, :<==>:>, :<=>:>=, :>==>:<, :!~=>:=~, :zero?=>:nonzero?, :nonzero?=>:zero?, :any?=>:none?, :none?=>:any?, :even?=>:odd?, :odd?=>:even?}` | |=== @@ -12427,7 +12427,7 @@ default. | Name | Default value | Configurable values | PreferredDelimiters -| `{"default" => "()", "%i" => "[]", "%I" => "[]", "%r" => "{}", "%w" => "[]", "%W" => "[]"}` +| `{"default"=>"()", "%i"=>"[]", "%I"=>"[]", "%r"=>"{}", "%w"=>"[]", "%W"=>"[]"}` | |=== @@ -12913,7 +12913,7 @@ A.foo | Name | Default value | Configurable values | Methods -| `{"join" => "", "sum" => 0, "exit" => true, "exit!" => false, "split" => " ", "chomp" => "\n", "chomp!" => "\n"}` +| `{"join"=>"", "sum"=>0, "exit"=>true, "exit!"=>false, "split"=>" ", "chomp"=>"\n", "chomp!"=>"\n"}` | |=== @@ -16072,7 +16072,7 @@ end | Name | Default value | Configurable values | Methods -| `{"reduce" => ["acc", "elem"]}`, `{"inject" => ["acc", "elem"]}` +| `{"reduce"=>["acc", "elem"]}`, `{"inject"=>["acc", "elem"]}` | Array |=== @@ -16988,7 +16988,7 @@ from the `String` class. | Name | Default value | Configurable values | PreferredMethods -| `{"intern" => "to_sym"}` +| `{"intern"=>"to_sym"}` | |=== diff --git a/docs/modules/ROOT/pages/integration_with_other_tools.adoc b/docs/modules/ROOT/pages/integration_with_other_tools.adoc index 6454843bbbce..edfe0e074f16 100644 --- a/docs/modules/ROOT/pages/integration_with_other_tools.adoc +++ b/docs/modules/ROOT/pages/integration_with_other_tools.adoc @@ -125,7 +125,7 @@ following to your `.pre-commit-config.yaml` file: [source,yaml] ---- - repo: https://github.com/rubocop/rubocop - rev: v1.75.4 + rev: v1.75.5 hooks: - id: rubocop ---- @@ -136,7 +136,7 @@ entries in `additional_dependencies`: [source,yaml] ---- - repo: https://github.com/rubocop/rubocop - rev: v1.75.4 + rev: v1.75.5 hooks: - id: rubocop additional_dependencies: diff --git a/lib/rubocop/cop/layout/hash_alignment.rb b/lib/rubocop/cop/layout/hash_alignment.rb index 0924493569da..9182893756ad 100644 --- a/lib/rubocop/cop/layout/hash_alignment.rb +++ b/lib/rubocop/cop/layout/hash_alignment.rb @@ -250,7 +250,7 @@ def check_pairs(node) reset! alignment_for(first_pair).each do |alignment| - delta = alignment.deltas_for_first_pair(first_pair, node) + delta = alignment.deltas_for_first_pair(first_pair) check_delta delta, node: first_pair, alignment: alignment end diff --git a/lib/rubocop/cop/layout/leading_comment_space.rb b/lib/rubocop/cop/layout/leading_comment_space.rb index 7bf7f6de939b..149a4c0904cc 100644 --- a/lib/rubocop/cop/layout/leading_comment_space.rb +++ b/lib/rubocop/cop/layout/leading_comment_space.rb @@ -58,6 +58,12 @@ module Layout # attr_reader :name #: String # attr_reader :age #: Integer? # + # #: ( + # #| Integer, + # #| String + # #| ) -> void + # def foo; end + # # @example AllowRBSInlineAnnotation: true # # # good @@ -67,6 +73,12 @@ module Layout # attr_reader :name #: String # attr_reader :age #: Integer? # + # #: ( + # #| Integer, + # #| String + # #| ) -> void + # def foo; end + # # @example AllowSteepAnnotation: false (default) # # # bad @@ -175,7 +187,7 @@ def allow_rbs_inline_annotation? end def rbs_inline_annotation?(comment) - allow_rbs_inline_annotation? && comment.text.start_with?(/#:|#\[.+\]/) + allow_rbs_inline_annotation? && comment.text.start_with?(/#:|#\[.+\]|#\|/) end def allow_steep_annotation? diff --git a/lib/rubocop/cop/layout/space_after_semicolon.rb b/lib/rubocop/cop/layout/space_after_semicolon.rb index 8483173315ec..fbc1d097265d 100644 --- a/lib/rubocop/cop/layout/space_after_semicolon.rb +++ b/lib/rubocop/cop/layout/space_after_semicolon.rb @@ -23,6 +23,16 @@ def space_style_before_rcurly def kind(token) 'semicolon' if token.semicolon? end + + def space_missing?(token1, token2) + super && !semicolon_sequence?(token1, token2) + end + + private + + def semicolon_sequence?(token, next_token) + token.semicolon? && next_token.semicolon? + end end end end diff --git a/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb b/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb index 29a9d5cc0de9..8b33dacadf76 100644 --- a/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +++ b/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb @@ -6,6 +6,8 @@ module Layout # Checks that brackets used for array literals have or don't have # surrounding space depending on configuration. # + # Array pattern matching is handled in the same way. + # # @example EnforcedStyle: no_space (default) # # The `no_space` style enforces that array literals have # # no surrounding space. @@ -82,7 +84,7 @@ class SpaceInsideArrayLiteralBrackets < Base EMPTY_MSG = '%s space inside empty array brackets.' def on_array(node) - return unless node.square_brackets? + return if node.array_type? && !node.square_brackets? tokens, left, right = array_brackets(node) @@ -95,6 +97,7 @@ def on_array(node) issue_offenses(node, left, right, start_ok, end_ok) end + alias on_array_pattern on_array private diff --git a/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb b/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb index 5ddbae2c0aa5..c9cddac7941d 100644 --- a/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +++ b/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb @@ -6,6 +6,8 @@ module Layout # Checks that braces used for hash literals have or don't have # surrounding space depending on configuration. # + # Hash pattern matching is handled in the same way. + # # @example EnforcedStyle: space (default) # # The `space` style enforces that hash literals have # # surrounding space. @@ -87,6 +89,7 @@ def on_hash(node) check(tokens[-2], tokens[-1]) if tokens.size > 2 check_whitespace_only_hash(node) if enforce_no_space_style_for_empty_braces? end + alias on_hash_pattern on_hash private diff --git a/lib/rubocop/cop/lint/array_literal_in_regexp.rb b/lib/rubocop/cop/lint/array_literal_in_regexp.rb index 3741389c0881..35495357164e 100644 --- a/lib/rubocop/cop/lint/array_literal_in_regexp.rb +++ b/lib/rubocop/cop/lint/array_literal_in_regexp.rb @@ -51,10 +51,9 @@ class ArrayLiteralInRegexp < Base 'in a regexp.' def on_interpolation(begin_node) - final_node = begin_node.children.last - - return unless begin_node.parent.regexp_type? + return unless (final_node = begin_node.children.last) return unless final_node.array_type? + return unless begin_node.parent.regexp_type? if array_of_literal_values?(final_node) register_array_of_literal_values(begin_node, final_node) diff --git a/lib/rubocop/cop/lint/literal_as_condition.rb b/lib/rubocop/cop/lint/literal_as_condition.rb index 85b8d14101ea..88b9de9652ce 100644 --- a/lib/rubocop/cop/lint/literal_as_condition.rb +++ b/lib/rubocop/cop/lint/literal_as_condition.rb @@ -248,7 +248,7 @@ def correct_if_node(node, cond) add_offense(cond) do |corrector| corrector.replace(node, "else\n #{node.else_branch.source}") end - elsif result + elsif node.if_branch && result add_offense(cond) do |corrector| corrector.replace(node, node.if_branch.source) end diff --git a/lib/rubocop/cop/lint/void.rb b/lib/rubocop/cop/lint/void.rb index 00e9f1c1fa5f..b73310766853 100644 --- a/lib/rubocop/cop/lint/void.rb +++ b/lib/rubocop/cop/lint/void.rb @@ -128,8 +128,8 @@ def check_expression(expr) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def check_void_op(node, &block) - node = node.children.first while node.begin_type? - return unless node.call_type? && OPERATORS.include?(node.method_name) + node = node.children.first while node&.begin_type? + return unless node&.call_type? && OPERATORS.include?(node.method_name) if !UNARY_OPERATORS.include?(node.method_name) && node.loc.dot && node.arguments.none? return end diff --git a/lib/rubocop/cop/mixin/hash_alignment_styles.rb b/lib/rubocop/cop/mixin/hash_alignment_styles.rb index 8f12191fb9c7..c335bf2f8434 100644 --- a/lib/rubocop/cop/mixin/hash_alignment_styles.rb +++ b/lib/rubocop/cop/mixin/hash_alignment_styles.rb @@ -10,7 +10,7 @@ def checkable_layout?(_node) true end - def deltas_for_first_pair(first_pair, _node) + def deltas_for_first_pair(first_pair) { separator: separator_delta(first_pair), value: value_delta(first_pair) @@ -81,13 +81,7 @@ def separator_delta(first_pair, current_pair, key_delta) class TableAlignment include ValueAlignment - def initialize - self.max_key_width = 0 - end - - def deltas_for_first_pair(first_pair, node) - self.max_key_width = node.keys.map { |key| key.source.length }.max - + def deltas_for_first_pair(first_pair) separator_delta = separator_delta(first_pair, first_pair, 0) { separator: separator_delta, @@ -97,30 +91,37 @@ def deltas_for_first_pair(first_pair, node) private - attr_accessor :max_key_width - def key_delta(first_pair, current_pair) first_pair.key_delta(current_pair) end def hash_rocket_delta(first_pair, current_pair) - first_pair.loc.column + max_key_width + 1 - current_pair.loc.operator.column + first_pair.loc.column + max_key_width(first_pair.parent) + 1 - + current_pair.loc.operator.column end def value_delta(first_pair, current_pair) correct_value_column = first_pair.key.loc.column + - current_pair.delimiter(true).length + - max_key_width + max_key_width(first_pair.parent) + + max_delimiter_width(first_pair.parent) current_pair.value_omission? ? 0 : correct_value_column - current_pair.value.loc.column end + + def max_key_width(hash_node) + hash_node.keys.map { |key| key.source.length }.max + end + + def max_delimiter_width(hash_node) + hash_node.pairs.map { |pair| pair.delimiter(true).length }.max + end end # Handles calculation of deltas when the enforced style is 'separator'. class SeparatorAlignment include ValueAlignment - def deltas_for_first_pair(*_nodes) + def deltas_for_first_pair(_first_pair) {} end diff --git a/lib/rubocop/cop/mixin/trailing_comma.rb b/lib/rubocop/cop/mixin/trailing_comma.rb index e8d4e958c183..f250dc9cbbf7 100644 --- a/lib/rubocop/cop/mixin/trailing_comma.rb +++ b/lib/rubocop/cop/mixin/trailing_comma.rb @@ -107,7 +107,7 @@ def method_name_and_arguments_on_same_line?(node) # of the argument is not considered multiline, even if the argument # itself might span multiple lines. def allowed_multiline_argument?(node) - elements(node).one? && (!node.loc.end || !Util.begins_its_line?(node.loc.end)) + elements(node).one? && !Util.begins_its_line?(node_end_location(node)) end def elements(node) @@ -127,10 +127,14 @@ def elements(node) def no_elements_on_same_line?(node) items = elements(node).map(&:source_range) - items << node.loc.end + items << node_end_location(node) items.each_cons(2).none? { |a, b| on_same_line?(a, b) } end + def node_end_location(node) + node.loc.end || node.source_range.end.adjust(begin_pos: -1) + end + def on_same_line?(range1, range2) range1.last_line == range2.line end diff --git a/lib/rubocop/cop/style/arguments_forwarding.rb b/lib/rubocop/cop/style/arguments_forwarding.rb index 30f560a02e25..44e0eb45faed 100644 --- a/lib/rubocop/cop/style/arguments_forwarding.rb +++ b/lib/rubocop/cop/style/arguments_forwarding.rb @@ -479,6 +479,9 @@ def ruby_30_or_lower_optarg? end def ruby_32_only_anonymous_forwarding? + # A block argument and an anonymous block argument are never passed together. + return false if @send_node.each_ancestor(:any_block).any? + def_all_anonymous_args?(@def_node) && send_all_anonymous_args?(@send_node) end diff --git a/lib/rubocop/cop/style/identical_conditional_branches.rb b/lib/rubocop/cop/style/identical_conditional_branches.rb index e8b1bf31a5cb..e45531913690 100644 --- a/lib/rubocop/cop/style/identical_conditional_branches.rb +++ b/lib/rubocop/cop/style/identical_conditional_branches.rb @@ -189,7 +189,7 @@ def assignable_condition_value(node) end end - # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity + # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity def check_expressions(node, expressions, insert_position) return if expressions.any?(&:nil?) @@ -197,7 +197,7 @@ def check_expressions(node, expressions, insert_position) expressions.each do |expression| add_offense(expression) do |corrector| - next if node.if_type? && node.ternary? + next if node.if_type? && (node.ternary? || node.then?) range = range_by_whole_lines(expression.source_range, include_final_newline: true) corrector.remove(range) @@ -213,7 +213,7 @@ def check_expressions(node, expressions, insert_position) end end end - # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity + # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity def correct_assignment(corrector, node, expression, insert_position) if insert_position == :after_condition diff --git a/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb b/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb index c520fc7cb623..40e2132c3d68 100644 --- a/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +++ b/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb @@ -222,6 +222,9 @@ def regexp_slash_literal?(node) end def unary_literal?(node) + # NOTE: should be removed after releasing https://github.com/rubocop/rubocop-ast/pull/379 + return node.source.match?(/\A[+-]/) if node.complex_type? + (node.numeric_type? && node.sign?) || (node.parent&.send_type? && node.parent.unary_operation?) end diff --git a/lib/rubocop/version.rb b/lib/rubocop/version.rb index 45d1196ab462..d033eee1f667 100644 --- a/lib/rubocop/version.rb +++ b/lib/rubocop/version.rb @@ -3,7 +3,7 @@ module RuboCop # This module holds the RuboCop version information. module Version - STRING = '1.75.4' + STRING = '1.75.5' MSG = '%s (using %s, ' \ 'rubocop-ast %s, ' \ diff --git a/relnotes/v1.75.5.md b/relnotes/v1.75.5.md new file mode 100644 index 000000000000..0f21745d4faa --- /dev/null +++ b/relnotes/v1.75.5.md @@ -0,0 +1,22 @@ +### Bug fixes + +* [#14148](https://github.com/rubocop/rubocop/pull/14148): Fix an infinite loop error for `Layout/SpaceAfterSemicolon` with `Layout/SpaceBeforeSemicolon` when a sequence of semicolons appears. ([@koic][]) +* [#14145](https://github.com/rubocop/rubocop/pull/14145): Fix `Lint/ArrayLiteralInRegexp` cop error on empty interpolation. ([@viralpraxis][]) +* [#14072](https://github.com/rubocop/rubocop/issues/14072): Fix autocorrect issue in `Layout/HashAlignment`. ([@jonas054][]) +* [#14131](https://github.com/rubocop/rubocop/issues/14131): Fix false positives for `Style/ArgumentsForwarding` when using anonymous block argument forwarding to a method with a block. ([@koic][]) +* [#14140](https://github.com/rubocop/rubocop/pull/14140): Fix `Layout/LeadingCommentSpace` to allow splitting long inline RBS comment signatures across multiple lines. ([@Morriar][]) +* [#14147](https://github.com/rubocop/rubocop/pull/14147): Fix `Lint/LiteralAsCondition` cop error on `if` without body. ([@viralpraxis][]) +* [#14151](https://github.com/rubocop/rubocop/pull/14151): Fix `Lint/Void` cop error on nested empty `begin`. ([@viralpraxis][]) +* [#13547](https://github.com/rubocop/rubocop/pull/13547): Fix `Style/IdenticalConditionalBranches` cop failure in case of `if` node with implicit `then`. ([@viralpraxis][]) +* [#14146](https://github.com/rubocop/rubocop/pull/14146): Fix `Style/MethodCallWithArgsParentheses` cop error on complex numbers when `EnforcedStyle` is set to `omit_parentheses`. ([@viralpraxis][]) +* [#14137](https://github.com/rubocop/rubocop/issues/14137): Fix `Style/TrailingCommaInArguments` cop error if `EnforcedStyleForMultiline` is set to `comma`. ([@viralpraxis][]) + +### Changes + +* [#14144](https://github.com/rubocop/rubocop/pull/14144): `Layout/SpaceInsideArrayLiteralBrackets` make aware of array pattern matching. ([@koic][]) +* [#14142](https://github.com/rubocop/rubocop/issues/14142): `Layout/SpaceInsideHashLiteralBraces` make aware of hash pattern matching. ([@koic][]) + +[@koic]: https://github.com/koic +[@viralpraxis]: https://github.com/viralpraxis +[@jonas054]: https://github.com/jonas054 +[@Morriar]: https://github.com/Morriar diff --git a/spec/rubocop/cli/autocorrect_spec.rb b/spec/rubocop/cli/autocorrect_spec.rb index a62dd80abab6..4aad2529944c 100644 --- a/spec/rubocop/cli/autocorrect_spec.rb +++ b/spec/rubocop/cli/autocorrect_spec.rb @@ -1804,6 +1804,16 @@ def primes limit RUBY end + it 'corrects `Layout/SpaceAfterSemicolon` with `Layout/SpaceBeforeSemicolon`' do + create_file('example.rb', <<~RUBY) + foo;;bar + RUBY + expect(cli.run(%w[-a --only Layout/SpaceAfterSemicolon,Layout/SpaceBeforeSemicolon])).to eq(0) + expect(File.read('example.rb')).to eq(<<~RUBY) + foo;; bar + RUBY + end + it 'can correct SpaceAfterComma and HashSyntax offenses' do create_file('example.rb', "I18n.t('description',:property_name => property.name)") expect(cli.run(%w[-D --autocorrect-all --format emacs diff --git a/spec/rubocop/cop/layout/hash_alignment_spec.rb b/spec/rubocop/cop/layout/hash_alignment_spec.rb index a4ae4891b748..68d53a030a9d 100644 --- a/spec/rubocop/cop/layout/hash_alignment_spec.rb +++ b/spec/rubocop/cop/layout/hash_alignment_spec.rb @@ -1375,6 +1375,23 @@ def self.scenarios_order } RUBY end + + it 'corrects a hash with mixed separators into table alignment' do + expect_offense(<<~RUBY) + other = { + foo: 1, + ^^^^^^^ Align the keys and values of a hash literal if they span more than one line. + 'bar' => 2, + } + RUBY + + expect_correction(<<~RUBY) + other = { + foo: 1, + 'bar' => 2, + } + RUBY + end end end diff --git a/spec/rubocop/cop/layout/leading_comment_space_spec.rb b/spec/rubocop/cop/layout/leading_comment_space_spec.rb index f37bb721a215..dba492ae57d7 100644 --- a/spec/rubocop/cop/layout/leading_comment_space_spec.rb +++ b/spec/rubocop/cop/layout/leading_comment_space_spec.rb @@ -263,6 +263,16 @@ ^^^^^^^^^ Missing space after `#`. attr_reader :age #: Integer? ^^^^^^^^^^^ Missing space after `#`. + + #: ( + ^^^^ Missing space after `#`. + #| Integer, + ^^^^^^^^^^^^^ Missing space after `#`. + #| String + ^^^^^^^^^^^ Missing space after `#`. + #| ) -> void + ^^^^^^^^^^^^ Missing space after `#`. + def foo; end RUBY expect_correction(<<~RUBY) @@ -270,6 +280,12 @@ attr_reader :name # : String attr_reader :age # : Integer? + + # : ( + # | Integer, + # | String + # | ) -> void + def foo; end RUBY end end @@ -283,6 +299,12 @@ attr_reader :name #: String attr_reader :age #: Integer? + + #: ( + #| Integer, + #| String + #| ) -> void + def foo; end RUBY end end diff --git a/spec/rubocop/cop/layout/space_after_semicolon_spec.rb b/spec/rubocop/cop/layout/space_after_semicolon_spec.rb index f00792de29bc..ee06ee1d9f50 100644 --- a/spec/rubocop/cop/layout/space_after_semicolon_spec.rb +++ b/spec/rubocop/cop/layout/space_after_semicolon_spec.rb @@ -19,6 +19,12 @@ expect_no_offenses('x = 1;') end + it 'does not register an offense when semicolons appear consecutively' do + expect_no_offenses(<<~RUBY) + foo;; bar + RUBY + end + context 'inside block braces' do shared_examples 'common behavior' do it 'accepts a space between a semicolon and a closing brace' do diff --git a/spec/rubocop/cop/layout/space_inside_array_literal_brackets_spec.rb b/spec/rubocop/cop/layout/space_inside_array_literal_brackets_spec.rb index 1a37b663d60d..4fa3d614af1f 100644 --- a/spec/rubocop/cop/layout/space_inside_array_literal_brackets_spec.rb +++ b/spec/rubocop/cop/layout/space_inside_array_literal_brackets_spec.rb @@ -293,6 +293,72 @@ def Vector.[](*array) ] RUBY end + + context 'when using array pattern matching', :ruby27 do + it 'registers an offense when array pattern with spaces' do + expect_offense(<<~RUBY) + case foo + in [ bar, baz ] + ^ Do not use space inside array brackets. + ^ Do not use space inside array brackets. + end + RUBY + + expect_correction(<<~RUBY) + case foo + in [bar, baz] + end + RUBY + end + + it 'does not register an offense when array pattern with no spaces' do + expect_no_offenses(<<~RUBY) + case foo + in [bar, baz] + end + RUBY + end + end + + context 'when using one-line array `in` pattern matching', :ruby27 do + it 'registers an offense when array pattern with spaces' do + expect_offense(<<~RUBY) + foo in [ bar, baz ] + ^ Do not use space inside array brackets. + ^ Do not use space inside array brackets. + RUBY + + expect_correction(<<~RUBY) + foo in [bar, baz] + RUBY + end + + it 'does not register an offense when array pattern with no spaces' do + expect_no_offenses(<<~RUBY) + foo in [bar, baz] + RUBY + end + end + + context 'when using one-line array `=>` pattern matching', :ruby30 do + it 'registers an offense when array pattern with spaces' do + expect_offense(<<~RUBY) + foo => [ bar, baz ] + ^ Do not use space inside array brackets. + ^ Do not use space inside array brackets. + RUBY + + expect_correction(<<~RUBY) + foo => [bar, baz] + RUBY + end + + it 'does not register an offense when array pattern with no spaces' do + expect_no_offenses(<<~RUBY) + foo => [bar, baz] + RUBY + end + end end shared_examples 'space inside arrays' do @@ -458,6 +524,72 @@ def Vector.[](*array) [ 1, [ 2,3,4 ], [ 5,6,7 ] ] RUBY end + + context 'when using array pattern matching', :ruby27 do + it 'registers an offense when array pattern with no spaces' do + expect_offense(<<~RUBY) + case foo + in [bar, baz] + ^ Use space inside array brackets. + ^ Use space inside array brackets. + end + RUBY + + expect_correction(<<~RUBY) + case foo + in [ bar, baz ] + end + RUBY + end + + it 'does not register an offense when array pattern with spaces' do + expect_no_offenses(<<~RUBY) + case foo + in [ bar, baz ] + end + RUBY + end + end + + context 'when using one-line array `in` pattern matching', :ruby27 do + it 'registers an offense when array pattern with no spaces' do + expect_offense(<<~RUBY) + foo in [bar, baz] + ^ Use space inside array brackets. + ^ Use space inside array brackets. + RUBY + + expect_correction(<<~RUBY) + foo in [ bar, baz ] + RUBY + end + + it 'does not register an offense when array pattern with spaces' do + expect_no_offenses(<<~RUBY) + foo in [ bar, baz ] + RUBY + end + end + + context 'when using one-line array `=>` pattern matching', :ruby30 do + it 'registers an offense when array pattern with no spaces' do + expect_offense(<<~RUBY) + foo => [bar, baz] + ^ Use space inside array brackets. + ^ Use space inside array brackets. + RUBY + + expect_correction(<<~RUBY) + foo => [ bar, baz ] + RUBY + end + + it 'does not register an offense when array pattern with spaces' do + expect_no_offenses(<<~RUBY) + foo => [ bar, baz ] + RUBY + end + end end context 'when EnforcedStyle is compact' do diff --git a/spec/rubocop/cop/layout/space_inside_hash_literal_braces_spec.rb b/spec/rubocop/cop/layout/space_inside_hash_literal_braces_spec.rb index 18842d109b47..648f36d07878 100644 --- a/spec/rubocop/cop/layout/space_inside_hash_literal_braces_spec.rb +++ b/spec/rubocop/cop/layout/space_inside_hash_literal_braces_spec.rb @@ -112,6 +112,72 @@ RUBY end + context 'when using hash pattern matching', :ruby27 do + it 'registers an offense when hash pattern with no spaces' do + expect_offense(<<~RUBY) + case foo + in {k1: 0, k2: 1} + ^ Space inside } missing. + ^ Space inside { missing. + end + RUBY + + expect_correction(<<~RUBY) + case foo + in { k1: 0, k2: 1 } + end + RUBY + end + + it 'does not register an offense when hash pattern with spaces' do + expect_no_offenses(<<~RUBY) + case foo + in { k1: 0, k2: 1 } + end + RUBY + end + end + + context 'when using one-line hash `in` pattern matching', :ruby27 do + it 'registers an offense when hash pattern with no spaces' do + expect_offense(<<~RUBY) + foo in {k1: 0, k2: 1} + ^ Space inside } missing. + ^ Space inside { missing. + RUBY + + expect_correction(<<~RUBY) + foo in { k1: 0, k2: 1 } + RUBY + end + + it 'does not register an offense when hash pattern with spaces' do + expect_no_offenses(<<~RUBY) + foo in { k1: 0, k2: 1 } + RUBY + end + end + + context 'when using one-line hash `=>` pattern matching', :ruby30 do + it 'registers an offense when hash pattern with no spaces' do + expect_offense(<<~RUBY) + foo => {k1: 0, k2: 1} + ^ Space inside } missing. + ^ Space inside { missing. + RUBY + + expect_correction(<<~RUBY) + foo => { k1: 0, k2: 1 } + RUBY + end + + it 'does not register an offense when hash pattern with spaces' do + expect_no_offenses(<<~RUBY) + foo => { k1: 0, k2: 1 } + RUBY + end + end + context 'when EnforcedStyle is no_space' do let(:cop_config) { { 'EnforcedStyle' => 'no_space' } } @@ -182,6 +248,72 @@ RUBY end end + + context 'when using hash pattern matching', :ruby27 do + it 'registers an offense when hash with spaces' do + expect_offense(<<~RUBY) + case foo + in { k1: 0, k2: 1 } + ^ Space inside } detected. + ^ Space inside { detected. + end + RUBY + + expect_correction(<<~RUBY) + case foo + in {k1: 0, k2: 1} + end + RUBY + end + + it 'does not register an offense when hash pattern with no spaces' do + expect_no_offenses(<<~RUBY) + case foo + in {k1: 0, k2: 1} + end + RUBY + end + end + + context 'when using one-line hash `in` pattern matching', :ruby27 do + it 'registers an offense when hash with spaces' do + expect_offense(<<~RUBY) + foo in { k1: 0, k2: 1 } + ^ Space inside } detected. + ^ Space inside { detected. + RUBY + + expect_correction(<<~RUBY) + foo in {k1: 0, k2: 1} + RUBY + end + + it 'does not register an offense when hash with no spaces' do + expect_no_offenses(<<~RUBY) + foo in {k1: 0, k2: 1} + RUBY + end + end + + context 'when using one-line hash `=>` pattern matching', :ruby30 do + it 'registers an offense when hash with spaces' do + expect_offense(<<~RUBY) + foo => { k1: 0, k2: 1 } + ^ Space inside } detected. + ^ Space inside { detected. + RUBY + + expect_correction(<<~RUBY) + foo => {k1: 0, k2: 1} + RUBY + end + + it 'does not register an offense when hash with no spaces' do + expect_no_offenses(<<~RUBY) + foo => {k1: 0, k2: 1} + RUBY + end + end end context 'when EnforcedStyle is compact' do diff --git a/spec/rubocop/cop/lint/array_literal_in_regexp_spec.rb b/spec/rubocop/cop/lint/array_literal_in_regexp_spec.rb index ff97055014c3..b3590c60a6ce 100644 --- a/spec/rubocop/cop/lint/array_literal_in_regexp_spec.rb +++ b/spec/rubocop/cop/lint/array_literal_in_regexp_spec.rb @@ -82,4 +82,10 @@ "#{%w[a b c]}" RUBY end + + it 'does not register an offense with empty interpolation' do + expect_no_offenses(<<~'RUBY') + /#{}/ + RUBY + end end diff --git a/spec/rubocop/cop/lint/literal_as_condition_spec.rb b/spec/rubocop/cop/lint/literal_as_condition_spec.rb index 7fd36b8968c0..aad880d28deb 100644 --- a/spec/rubocop/cop/lint/literal_as_condition_spec.rb +++ b/spec/rubocop/cop/lint/literal_as_condition_spec.rb @@ -674,5 +674,17 @@ def foo expect_no_corrections end + + it 'registers an offense when there is no body for `if` node' do + expect_offense(<<~RUBY) + if 42 + ^^ Literal `42` appeared as a condition. + end + RUBY + + expect_correction(<<~RUBY) + + RUBY + end end end diff --git a/spec/rubocop/cop/lint/void_spec.rb b/spec/rubocop/cop/lint/void_spec.rb index 6eeb9a8aa117..4bf4b9cf1b10 100644 --- a/spec/rubocop/cop/lint/void_spec.rb +++ b/spec/rubocop/cop/lint/void_spec.rb @@ -1151,4 +1151,10 @@ def foo puts :ok RUBY end + + it 'does not register an offense for nested empty `begin`' do + expect_no_offenses(<<~RUBY) + ((); 1) + RUBY + end end diff --git a/spec/rubocop/cop/style/arguments_forwarding_spec.rb b/spec/rubocop/cop/style/arguments_forwarding_spec.rb index 11338e2ad6d8..33e688553cfb 100644 --- a/spec/rubocop/cop/style/arguments_forwarding_spec.rb +++ b/spec/rubocop/cop/style/arguments_forwarding_spec.rb @@ -1165,6 +1165,36 @@ def baz(qux, quuz, &block) RUBY end + it 'does not register an offense when using anonymous block argument forwarding to a method with a block', :ruby32 do + expect_no_offenses(<<~RUBY) + def foo(*, **, &) + with_block(*, **) do + bar(baz(*, **, &)) + end + end + RUBY + end + + it 'does not register an offense when using anonymous block argument forwarding to a method with a numbered block', :ruby32 do + expect_no_offenses(<<~RUBY) + def foo(*, **, &) + with_block(*, **) do + bar(baz(*, **, &), _1) + end + end + RUBY + end + + it 'does not register an offense when using anonymous block argument forwarding to a method with an `it` block', :ruby34 do + expect_no_offenses(<<~RUBY) + def foo(*, **, &) + with_block(*, **) do + bar(baz(*, **, &), it) + end + end + RUBY + end + it 'registers an offense when using block arg forwarding with no forwarding arguments' do expect_offense(<<~RUBY) def before_transition(options = {}, &block) diff --git a/spec/rubocop/cop/style/identical_conditional_branches_spec.rb b/spec/rubocop/cop/style/identical_conditional_branches_spec.rb index e56fa6afdcf7..ca1b4dd13cd1 100644 --- a/spec/rubocop/cop/style/identical_conditional_branches_spec.rb +++ b/spec/rubocop/cop/style/identical_conditional_branches_spec.rb @@ -930,5 +930,55 @@ def bar end end end + + context 'with `if` in non-modifier form with `then`' do + context 'when expression is on the same line as `then`' do + it 'registers an offense' do + expect_offense(<<~RUBY) + def fixed_point(value) + if value then value + ^^^^^ Move `value` out of the conditional. + else value + ^^^^^ Move `value` out of the conditional. + end + end + RUBY + + expect_no_corrections + end + + it 'registers an offense when `else` branch is not inlined' do + expect_offense(<<~RUBY) + def fixed_point(value) + if value then value + ^^^^^ Move `value` out of the conditional. + else + value + ^^^^^ Move `value` out of the conditional. + end + end + RUBY + + expect_no_corrections + end + end + + context 'when expression is on the next line' do + it 'registers an offense' do + expect_offense(<<~RUBY) + def fixed_point(value) + if value then + value + ^^^^^ Move `value` out of the conditional. + else value + ^^^^^ Move `value` out of the conditional. + end + end + RUBY + + expect_no_corrections + end + end + end end end diff --git a/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb b/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb index bfd0fe0ee4e3..2359dd0e5291 100644 --- a/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb +++ b/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb @@ -878,6 +878,12 @@ def seatle_style arg: default(42) expect_no_offenses('foo(+1)') expect_no_offenses('foo(+"")') expect_no_offenses('foo(-"")') + expect_no_offenses('foo(-1 + 3i)') + expect_no_offenses('foo(+1 + 3i)') + expect_no_offenses('foo(-3i)') + expect_no_offenses('foo(+3i)') + expect_no_offenses('foo(-1.3i)') + expect_no_offenses('foo(+1.3i)') end it 'accepts parens in args splat' do diff --git a/spec/rubocop/cop/style/trailing_comma_in_arguments_spec.rb b/spec/rubocop/cop/style/trailing_comma_in_arguments_spec.rb index 7da19dddd363..6d7d7bdab133 100644 --- a/spec/rubocop/cop/style/trailing_comma_in_arguments_spec.rb +++ b/spec/rubocop/cop/style/trailing_comma_in_arguments_spec.rb @@ -3,89 +3,91 @@ RSpec.describe RuboCop::Cop::Style::TrailingCommaInArguments, :config do shared_examples 'single line lists' do |extra_info| [%w[( )], %w[[ ]]].each do |start_bracket, end_bracket| - it 'registers an offense for trailing comma in a method call' do - expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) - some_method#{start_bracket}a, b, c, #{end_bracket} - _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. - RUBY - - expect_correction(<<~RUBY) - some_method#{start_bracket}a, b, c #{end_bracket} - RUBY - end - - it 'registers an offense for trailing comma preceded by whitespace in a method call' do - expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) - some_method#{start_bracket}a, b, c , #{end_bracket} - _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. - RUBY - - expect_correction(<<~RUBY) - some_method#{start_bracket}a, b, c #{end_bracket} - RUBY - end - - it 'registers an offense for trailing comma in a method call with hash parameters at the end' do - expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) - some_method#{start_bracket}a, b, c: 0, d: 1, #{end_bracket} - _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. - RUBY - - expect_correction(<<~RUBY) - some_method#{start_bracket}a, b, c: 0, d: 1 #{end_bracket} - RUBY - end - - it 'accepts method call without trailing comma' do - expect_no_offenses("some_method#{start_bracket}a, b, c#{end_bracket}") - end - - it 'accepts method call without trailing comma when a line break before a method call' do - expect_no_offenses(<<~RUBY) - obj - .do_something#{start_bracket}:foo, :bar#{end_bracket} - RUBY - end - - it 'accepts method call without trailing comma with single element hash ' \ - 'parameters at the end' do - expect_no_offenses("some_method#{start_bracket}a: 1#{end_bracket}") - end - - it 'accepts method call without parameters' do - expect_no_offenses('some_method') - end + context "with `#{start_bracket}#{end_bracket}` brackets" do + it 'registers an offense for trailing comma in a method call' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + some_method#{start_bracket}a, b, c, #{end_bracket} + _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. + RUBY - it 'accepts chained single-line method calls' do - expect_no_offenses(<<~RUBY) - target - .some_method#{start_bracket}a#{end_bracket} - RUBY - end + expect_correction(<<~RUBY) + some_method#{start_bracket}a, b, c #{end_bracket} + RUBY + end - context 'when using safe navigation operator' do - it 'registers an offense for trailing comma in a method call' do + it 'registers an offense for trailing comma preceded by whitespace in a method call' do expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) - receiver&.some_method#{start_bracket}a, b, c, #{end_bracket} - _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. + some_method#{start_bracket}a, b, c , #{end_bracket} + _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. RUBY expect_correction(<<~RUBY) - receiver&.some_method#{start_bracket}a, b, c #{end_bracket} + some_method#{start_bracket}a, b, c #{end_bracket} RUBY end - it 'registers an offense for trailing comma in a method call with hash ' \ - 'parameters at the end' do + it 'registers an offense for trailing comma in a method call with hash parameters at the end' do expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) - receiver&.some_method#{start_bracket}a, b, c: 0, d: 1, #{end_bracket} - _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. + some_method#{start_bracket}a, b, c: 0, d: 1, #{end_bracket} + _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. RUBY expect_correction(<<~RUBY) - receiver&.some_method#{start_bracket}a, b, c: 0, d: 1 #{end_bracket} + some_method#{start_bracket}a, b, c: 0, d: 1 #{end_bracket} + RUBY + end + + it 'accepts method call without trailing comma' do + expect_no_offenses("some_method#{start_bracket}a, b, c#{end_bracket}") + end + + it 'accepts method call without trailing comma when a line break before a method call' do + expect_no_offenses(<<~RUBY) + obj + .do_something#{start_bracket}:foo, :bar#{end_bracket} RUBY end + + it 'accepts method call without trailing comma with single element hash ' \ + 'parameters at the end' do + expect_no_offenses("some_method#{start_bracket}a: 1#{end_bracket}") + end + + it 'accepts method call without parameters' do + expect_no_offenses('some_method') + end + + it 'accepts chained single-line method calls' do + expect_no_offenses(<<~RUBY) + target + .some_method#{start_bracket}a#{end_bracket} + RUBY + end + + context 'when using safe navigation operator' do + it 'registers an offense for trailing comma in a method call' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + receiver&.some_method#{start_bracket}a, b, c, #{end_bracket} + _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. + RUBY + + expect_correction(<<~RUBY) + receiver&.some_method#{start_bracket}a, b, c #{end_bracket} + RUBY + end + + it 'registers an offense for trailing comma in a method call with hash ' \ + 'parameters at the end' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + receiver&.some_method#{start_bracket}a, b, c: 0, d: 1, #{end_bracket} + _{start_bracket} ^ Avoid comma after the last parameter of a method call#{extra_info}. + RUBY + + expect_correction(<<~RUBY) + receiver&.some_method#{start_bracket}a, b, c: 0, d: 1 #{end_bracket} + RUBY + end + end end end @@ -161,175 +163,159 @@ context 'when EnforcedStyleForMultiline is no_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'no_comma' } } - it 'registers an offense for trailing comma in a method call with ' \ - 'hash parameters at the end' do - expect_offense(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1,) - ^ Avoid comma after the last parameter of a method call. - RUBY - - expect_correction(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1) - RUBY - end - - it 'registers an offense for trailing comma in a `[]` method call with ' \ - 'hash parameters at the end' do - expect_offense(<<~RUBY) - object[ - a, - b, - c: 0, - d: 1,] - ^ Avoid comma after the last parameter of a method call. - RUBY - - expect_correction(<<~RUBY) - object[ - a, - b, - c: 0, - d: 1] - RUBY - end - - it 'accepts a method call with hash parameters at the end and no trailing comma' do - expect_no_offenses(<<~RUBY) - some_method(a, - b, - c: 0, - d: 1 - ) - RUBY - end - - it 'accepts comma inside a heredoc parameter at the end' do - expect_no_offenses(<<~RUBY) - route(help: { - 'auth' => <<-HELP.chomp - , - HELP - }) - RUBY - end + [%w[( )], %w[[ ]]].each do |start_bracket, end_bracket| + context "with `#{start_bracket}#{end_bracket}` brackets" do + it 'registers an offense for trailing comma in a method call with ' \ + 'hash parameters at the end' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1,#{end_bracket} + ^ Avoid comma after the last parameter of a method call. + RUBY - it 'accepts comma inside a heredoc with comments inside' do - expect_no_offenses(<<~RUBY) - route( - <<-HELP - , - # some comment - HELP - ) - RUBY - end + expect_correction(<<~RUBY) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1#{end_bracket} + RUBY + end - it 'accepts comma inside a heredoc with method and comments inside' do - expect_no_offenses(<<~RUBY) - route( - <<-HELP.chomp - , - # some comment - HELP - ) - RUBY - end + it 'accepts a method call with hash parameters at the end and no trailing comma' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket}a, + b, + c: 0, + d: 1 + #{end_bracket} + RUBY + end - it 'accepts comma inside a heredoc in brackets' do - expect_no_offenses(<<~RUBY) - expect_no_offenses( - expect_no_offenses(<<~SOURCE) - run( - :foo, defaults.merge( - bar: 3)) - SOURCE - ) - RUBY - end + it 'accepts comma inside a heredoc parameter at the end' do + expect_no_offenses(<<~RUBY) + route#{start_bracket}help: { + 'auth' => <<-HELP.chomp + , + HELP + }#{end_bracket} + RUBY + end - it 'accepts comma inside a modified heredoc parameter' do - expect_no_offenses(<<~RUBY) - some_method( - <<-LOREM.delete("\\n") - Something with a , in it - LOREM - ) - RUBY - end + it 'accepts comma inside a heredoc with comments inside' do + expect_no_offenses(<<~RUBY) + route#{start_bracket} + <<-HELP + , + # some comment + HELP + #{end_bracket} + RUBY + end - it 'autocorrects unwanted comma after modified heredoc parameter' do - expect_offense(<<~'RUBY') - some_method( - <<-LOREM.delete("\n"), - ^ Avoid comma after the last parameter of a method call. - Something with a , in it - LOREM - ) - RUBY + it 'accepts comma inside a heredoc with method and comments inside' do + expect_no_offenses(<<~RUBY) + route#{start_bracket} + <<-HELP.chomp + , + # some comment + HELP + #{end_bracket} + RUBY + end - expect_correction(<<~'RUBY') - some_method( - <<-LOREM.delete("\n") - Something with a , in it - LOREM - ) - RUBY - end + it 'accepts comma inside a heredoc in brackets' do + expect_no_offenses(<<~RUBY) + expect_no_offenses( + expect_no_offenses(<<~SOURCE) + run#{start_bracket} + :foo, defaults.merge( + bar: 3)#{end_bracket} + SOURCE + ) + RUBY + end - context 'when there is string interpolation inside heredoc parameter' do - it 'accepts comma inside a heredoc parameter' do - expect_no_offenses(<<~RUBY) - some_method( - <<-SQL - \#{variable}.a ASC, - \#{variable}.b ASC - SQL - ) - RUBY - end + it 'accepts comma inside a modified heredoc parameter' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + <<-LOREM.delete("\\n") + Something with a , in it + LOREM + #{end_bracket} + RUBY + end - it 'accepts comma inside a heredoc parameter when on a single line' do - expect_no_offenses(<<~RUBY) - some_method( - bar: <<-BAR - \#{variable} foo, bar - BAR - ) - RUBY - end + it 'autocorrects unwanted comma after modified heredoc parameter' do + expect_offense(<<~'RUBY', start_bracket: start_bracket, end_bracket: end_bracket) + some_method%{start_bracket} + <<-LOREM.delete("\n"), + ^ Avoid comma after the last parameter of a method call. + Something with a , in it + LOREM + %{end_bracket} + RUBY - it 'autocorrects unwanted comma inside string interpolation' do - expect_offense(<<~'RUBY') - some_method( - bar: <<-BAR, - #{other_method(a, b,)} foo, bar - ^ Avoid comma after the last parameter of a method call. - BAR - baz: <<-BAZ - #{third_method(c, d,)} foo, bar - ^ Avoid comma after the last parameter of a method call. - BAZ - ) - RUBY + expect_correction(<<~RUBY) + some_method#{start_bracket} + <<-LOREM.delete("\\n") + Something with a , in it + LOREM + #{end_bracket} + RUBY + end - expect_correction(<<~RUBY) - some_method( - bar: <<-BAR, - \#{other_method(a, b)} foo, bar - BAR - baz: <<-BAZ - \#{third_method(c, d)} foo, bar - BAZ - ) - RUBY + context 'when there is string interpolation inside heredoc parameter' do + it 'accepts comma inside a heredoc parameter' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + <<-SQL + \#{variable}.a ASC, + \#{variable}.b ASC + SQL + #{end_bracket} + RUBY + end + + it 'accepts comma inside a heredoc parameter when on a single line' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + bar: <<-BAR + \#{variable} foo, bar + BAR + #{end_bracket} + RUBY + end + + it 'autocorrects unwanted comma inside string interpolation' do + expect_offense(<<~'RUBY') + some_method( + bar: <<-BAR, + #{other_method(a, b,)} foo, bar + ^ Avoid comma after the last parameter of a method call. + BAR + baz: <<-BAZ + #{third_method(c, d,)} foo, bar + ^ Avoid comma after the last parameter of a method call. + BAZ + ) + RUBY + + expect_correction(<<~RUBY) + some_method( + bar: <<-BAR, + \#{other_method(a, b)} foo, bar + BAR + baz: <<-BAZ + \#{third_method(c, d)} foo, bar + BAZ + ) + RUBY + end + end end end end @@ -337,270 +323,278 @@ context 'when EnforcedStyleForMultiline is comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'comma' } } - context 'when closing bracket is on same line as last value' do - it 'accepts a method call with Hash as last parameter split on multiple lines' do - expect_no_offenses(<<~RUBY) - some_method(a: "b", - c: "d") - RUBY - end - end + [%w[( )], %w[[ ]]].each do |start_bracket, end_bracket| + context "with `#{start_bracket}#{end_bracket}` brackets" do + context 'when closing bracket is on same line as last value' do + it 'accepts a method call with Hash as last parameter split on multiple lines' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket}a: "b", + c: "d"#{end_bracket} + RUBY + end + end - it 'registers an offense for no trailing comma in a method call with ' \ - 'hash parameters at the end' do - expect_offense(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1 - ^^^^ Put a comma after the last parameter of a multiline method call. - ) - RUBY + it 'registers an offense for no trailing comma in a method call with ' \ + 'hash parameters at the end' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1 + ^^^^ Put a comma after the last parameter of a multiline method call. + #{end_bracket} + RUBY - expect_correction(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1, - ) - RUBY - end + expect_correction(<<~RUBY) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1, + #{end_bracket} + RUBY + end - it 'accepts a method call with two parameters on the same line' do - expect_no_offenses(<<~RUBY) - some_method(a, b - ) - RUBY - end + it 'accepts a method call with two parameters on the same line' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket}a, b + #{end_bracket} + RUBY + end - it 'accepts trailing comma in a method call with hash parameters at the end' do - expect_no_offenses(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1, - ) - RUBY - end + it 'accepts trailing comma in a method call with hash parameters at the end' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1, + #{end_bracket} + RUBY + end - it 'accepts missing comma after heredoc with comments' do - expect_no_offenses(<<~RUBY) - route( - a, <<-HELP.chomp - , - # some comment - HELP - ) - RUBY - end + it 'accepts missing comma after heredoc with comments' do + expect_no_offenses(<<~RUBY) + route#{start_bracket} + a, <<-HELP.chomp + , + # some comment + HELP + #{end_bracket} + RUBY + end - it 'accepts no trailing comma in a method call with a multiline ' \ - 'braceless hash at the end with more than one parameter on a line' do - expect_no_offenses(<<~RUBY) - some_method( - a, - b: 0, - c: 0, d: 1 - ) - RUBY - end + it 'accepts no trailing comma in a method call with a multiline ' \ + 'braceless hash at the end with more than one parameter on a line' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + a, + b: 0, + c: 0, d: 1 + #{end_bracket} + RUBY + end - it 'accepts a trailing comma in a method call with single line hashes' do - expect_no_offenses(<<~RUBY) - some_method( - { a: 0, b: 1 }, - { a: 1, b: 0 }, - ) - RUBY - end + it 'accepts a trailing comma in a method call with single line hashes' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + { a: 0, b: 1 }, + { a: 1, b: 0 }, + #{end_bracket} + RUBY + end - it 'accepts an empty hash being passed as a method argument' do - expect_no_offenses(<<~RUBY) - Foo.new({ - }) - RUBY - end + it 'accepts an empty hash being passed as a method argument' do + expect_no_offenses(<<~RUBY) + Foo.new#{start_bracket}{ + }#{end_bracket} + RUBY + end - it 'accepts a multiline call with a single argument and trailing comma' do - expect_no_offenses(<<~RUBY) - method( - 1, - ) - RUBY - end + it 'accepts a multiline call with a single argument and trailing comma' do + expect_no_offenses(<<~RUBY) + method#{start_bracket} + 1, + #{end_bracket} + RUBY + end - it 'does not break when a method call is chained on the offending one' do - expect_no_offenses(<<~RUBY) - foo.bar( - baz: 1, - ).fetch(:qux) - RUBY - end + it 'does not break when a method call is chained on the offending one' do + expect_no_offenses(<<~RUBY) + foo.bar#{start_bracket} + baz: 1, + #{end_bracket}.fetch(:qux) + RUBY + end - it 'does not break when a safe method call is chained on the offending simple one' do - expect_no_offenses(<<~RUBY) - foo - &.do_something(:bar, :baz) - RUBY - end + it 'does not break when a safe method call is chained on the offending simple one' do + expect_no_offenses(<<~RUBY) + foo + &.do_something#{start_bracket}:bar, :baz#{end_bracket} + RUBY + end - it 'does not break when a safe method call is chained on the offending more complex one' do - expect_no_offenses(<<~RUBY) - foo.bar( - baz: 1, - )&.fetch(:qux) - RUBY + it 'does not break when a safe method call is chained on the offending more complex one' do + expect_no_offenses(<<~RUBY) + foo.bar#{start_bracket} + baz: 1, + #{end_bracket}&.fetch(:qux) + RUBY + end + end end end context 'when EnforcedStyleForMultiline is consistent_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'consistent_comma' } } - context 'when closing bracket is on same line as last value' do - it 'registers an offense for a method call, with a Hash as the ' \ - 'last parameter, split on multiple lines' do - expect_offense(<<~RUBY) - some_method(a: "b", - c: "d") - ^^^^^^ Put a comma after the last parameter of a multiline method call. - RUBY - - expect_correction(<<~RUBY) - some_method(a: "b", - c: "d",) - RUBY - end - end - - it 'registers an offense for no trailing comma in a method call with ' \ - 'hash parameters at the end' do - expect_offense(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1 - ^^^^ Put a comma after the last parameter of a multiline method call. - ) - RUBY + [%w[( )], %w[[ ]]].each do |start_bracket, end_bracket| + context "with `#{start_bracket}#{end_bracket}` brackets" do + context 'when closing bracket is on same line as last value' do + it 'registers an offense for a method call, with a Hash as the ' \ + 'last parameter, split on multiple lines' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + some_method#{start_bracket}a: "b", + c: "d"#{end_bracket} + ^^^^^^ Put a comma after the last parameter of a multiline method call. + RUBY + + expect_correction(<<~RUBY) + some_method#{start_bracket}a: "b", + c: "d",#{end_bracket} + RUBY + end + end - expect_correction(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1, - ) - RUBY - end + it 'registers an offense for no trailing comma in a method call with ' \ + 'hash parameters at the end' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1 + ^^^^ Put a comma after the last parameter of a multiline method call. + #{end_bracket} + RUBY - it 'registers an offense for no trailing comma in a method call with' \ - 'two parameters on the same line' do - expect_offense(<<~RUBY) - some_method(a, b - ^ Put a comma after the last parameter of a multiline method call. - ) - RUBY + expect_correction(<<~RUBY) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1, + #{end_bracket} + RUBY + end - expect_correction(<<~RUBY) - some_method(a, b, - ) - RUBY - end + it 'registers an offense for no trailing comma in a method call with' \ + 'two parameters on the same line' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + some_method#{start_bracket}a, b + ^ Put a comma after the last parameter of a multiline method call. + #{end_bracket} + RUBY - it 'accepts trailing comma in a method call with hash parameters at the end' do - expect_no_offenses(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1, - ) - RUBY - end + expect_correction(<<~RUBY) + some_method#{start_bracket}a, b, + #{end_bracket} + RUBY + end - it 'accepts a trailing comma in a method call with a single hash parameter' do - expect_no_offenses(<<~RUBY) - some_method( - a: 0, - b: 1, - ) - RUBY - end + it 'accepts trailing comma in a method call with hash parameters at the end' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1, + #{end_bracket} + RUBY + end - it 'accepts a trailing comma in a method call with ' \ - 'a single hash parameter to a receiver object' do - expect_no_offenses(<<~RUBY) - obj.some_method( + it 'accepts a trailing comma in a method call with a single hash parameter' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} a: 0, b: 1, - ) - RUBY - end + #{end_bracket} + RUBY + end - it 'accepts a trailing comma in a method call with single line hashes' do - expect_no_offenses(<<~RUBY) - some_method( - { a: 0, b: 1 }, - { a: 1, b: 0 }, - ) - RUBY - end + it 'accepts a trailing comma in a method call with ' \ + 'a single hash parameter to a receiver object' do + expect_no_offenses(<<~RUBY) + obj.some_method#{start_bracket} + a: 0, + b: 1, + #{end_bracket} + RUBY + end - # this is a sad parse error - it 'accepts no trailing comma in a method call with a block parameter at the end' do - expect_no_offenses(<<~RUBY) - some_method( - a, - b, - c: 0, - d: 1, - &block - ) - RUBY - end + it 'accepts a trailing comma in a method call with single line hashes' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + { a: 0, b: 1 }, + { a: 1, b: 0 }, + #{end_bracket} + RUBY + end - it 'autocorrects missing comma after a heredoc' do - expect_offense(<<~RUBY) - route(1, <<-HELP.chomp - ^^^^^^^^^^^^^ Put a comma after the last parameter of a multiline method call. - ... - HELP - ) - RUBY + # this is a sad parse error + it 'accepts no trailing comma in a method call with a block parameter at the end' do + expect_no_offenses(<<~RUBY) + some_method#{start_bracket} + a, + b, + c: 0, + d: 1, + &block + #{end_bracket} + RUBY + end - expect_correction(<<~RUBY) - route(1, <<-HELP.chomp, - ... - HELP - ) - RUBY - end + it 'autocorrects missing comma after a heredoc' do + expect_offense(<<~RUBY, start_bracket: start_bracket, end_bracket: end_bracket) + route#{start_bracket}1, <<-HELP.chomp + ^^^^^^^^^^^^^ Put a comma after the last parameter of a multiline method call. + ... + HELP + #{end_bracket} + RUBY - it 'accepts a multiline call with a single argument and trailing comma' do - expect_no_offenses(<<~RUBY) - method( - 1, - ) - RUBY - end + expect_correction(<<~RUBY) + route#{start_bracket}1, <<-HELP.chomp, + ... + HELP + #{end_bracket} + RUBY + end - it 'accepts a multiline call with arguments on a single line and trailing comma' do - expect_no_offenses(<<~RUBY) - method( - 1, 2, - ) - RUBY - end + it 'accepts a multiline call with a single argument and trailing comma' do + expect_no_offenses(<<~RUBY) + method#{start_bracket} + 1, + #{end_bracket} + RUBY + end - it 'accepts a multiline call with single argument on multiple lines' do - expect_no_offenses(<<~RUBY) - method(a: - "foo") - RUBY + it 'accepts a multiline call with arguments on a single line and trailing comma' do + expect_no_offenses(<<~RUBY) + method#{start_bracket} + 1, 2, + #{end_bracket} + RUBY + end + + it 'accepts a multiline call with single argument on multiple lines' do + expect_no_offenses(<<~RUBY) + method#{start_bracket}a: + "foo"#{end_bracket} + RUBY + end + end end end end