Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package rubygem-rubocop for openSUSE:Factory checked in at 2022-02-02 22:41:36 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-rubocop (Old) and /work/SRC/openSUSE:Factory/.rubygem-rubocop.new.1898 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-rubocop" Wed Feb 2 22:41:36 2022 rev:33 rq:950651 version:1.25.0 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-rubocop/rubygem-rubocop.changes 2021-12-26 13:30:28.706958221 +0100 +++ /work/SRC/openSUSE:Factory/.rubygem-rubocop.new.1898/rubygem-rubocop.changes 2022-02-02 22:42:34.347060609 +0100 @@ -1,0 +2,6 @@ +Tue Jan 25 07:30:58 UTC 2022 - Stephan Kulow <co...@suse.com> + +updated to version 1.25.0 + no changelog found + +------------------------------------------------------------------- Old: ---- rubocop-1.24.0.gem New: ---- rubocop-1.25.0.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-rubocop.spec ++++++ --- /var/tmp/diff_new_pack.thXcmh/_old 2022-02-02 22:42:34.935056623 +0100 +++ /var/tmp/diff_new_pack.thXcmh/_new 2022-02-02 22:42:34.943056569 +0100 @@ -1,7 +1,7 @@ # # spec file for package rubygem-rubocop # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -24,7 +24,7 @@ # Name: rubygem-rubocop -Version: 1.24.0 +Version: 1.25.0 Release: 0 %define mod_name rubocop %define mod_full_name %{mod_name}-%{version} ++++++ rubocop-1.24.0.gem -> rubocop-1.25.0.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/LICENSE.txt new/LICENSE.txt --- old/LICENSE.txt 2021-12-23 12:06:24.000000000 +0100 +++ new/LICENSE.txt 2022-01-18 08:45:16.000000000 +0100 @@ -1,4 +1,4 @@ -Copyright (c) 2012-21 Bozhidar Batsov +Copyright (c) 2012-22 Bozhidar Batsov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.md new/README.md --- old/README.md 2021-12-23 12:06:24.000000000 +0100 +++ new/README.md 2022-01-18 08:45:16.000000000 +0100 @@ -9,7 +9,6 @@ [](https://github.com/rubocop/rubocop/actions?query=workflow%3ACI) [](https://codeclimate.com/github/rubocop/rubocop/test_coverage) [](https://codeclimate.com/github/rubocop/rubocop/maintainability) -[](https://dependabot.com/compatibility-score.html?dependency-name=rubocop&package-manager=bundler&version-scheme=semver) [](https://discord.gg/wJjWvGRDmm) > Role models are important. <br/> @@ -54,7 +53,7 @@ in your `Gemfile`: ```rb -gem 'rubocop', '~> 1.24', require: false +gem 'rubocop', '~> 1.25', require: false ``` See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details. @@ -245,5 +244,5 @@ ## Copyright -Copyright (c) 2012-2021 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for +Copyright (c) 2012-2022 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for further details. Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/config/default.yml new/config/default.yml --- old/config/default.yml 2021-12-23 12:06:24.000000000 +0100 +++ new/config/default.yml 2022-01-18 08:45:16.000000000 +0100 @@ -2489,12 +2489,14 @@ Naming/BlockForwarding: Description: 'Use anonymous block forwarding.' + StyleGuide: '#block-forwarding' Enabled: pending VersionAdded: '1.24' EnforcedStyle: anonymous SupportedStyles: - anonymous - explicit + BlockForwardingName: block Naming/BlockParameterName: Description: >- @@ -3697,6 +3699,8 @@ - always # forces use of explicit hash literal value. - never + # accepts both shorthand and explicit use of hash literal value. + - either # Force hashes that have a symbol value to use hash rockets UseHashRocketsWithSymbolValues: false # Do not suggest { a?: 1 } over { :a? => 1 } in ruby19 style diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/gemspec/require_mfa.rb new/lib/rubocop/cop/gemspec/require_mfa.rb --- old/lib/rubocop/cop/gemspec/require_mfa.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/gemspec/require_mfa.rb 2022-01-18 08:45:16.000000000 +0100 @@ -117,7 +117,7 @@ correct_metadata(corrector, metadata) else - correct_missing_metadata(corrector, node, block_var) + insert_mfa_required(corrector, node, block_var) end end @@ -129,11 +129,9 @@ end end - def correct_missing_metadata(corrector, node, block_var) + def insert_mfa_required(corrector, node, block_var) corrector.insert_before(node.loc.end, <<~RUBY) - #{block_var}.metadata = { - 'rubygems_mfa_required' => 'true' - } + #{block_var}.metadata['rubygems_mfa_required'] = 'true' RUBY end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/gemspec/required_ruby_version.rb new/lib/rubocop/cop/gemspec/required_ruby_version.rb --- old/lib/rubocop/cop/gemspec/required_ruby_version.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/gemspec/required_ruby_version.rb 2022-01-18 08:45:16.000000000 +0100 @@ -68,8 +68,11 @@ # @!method defined_ruby_version(node) def_node_matcher :defined_ruby_version, <<~PATTERN - {$(str _) $(array (str _) (str _)) - (send (const (const nil? :Gem) :Requirement) :new $(str _))} + { + $(str _) + $(array (str _) (str _)) + (send (const (const nil? :Gem) :Requirement) :new $str+) + } PATTERN def on_new_investigation @@ -97,7 +100,11 @@ def extract_ruby_version(required_ruby_version) return unless required_ruby_version - if required_ruby_version.array_type? + if required_ruby_version.is_a?(Array) + required_ruby_version = required_ruby_version.detect do |v| + /[>=]/.match?(v.str_content) + end + elsif required_ruby_version.array_type? required_ruby_version = required_ruby_version.children.detect do |v| /[>=]/.match?(v.str_content) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/generator.rb new/lib/rubocop/cop/generator.rb --- old/lib/rubocop/cop/generator.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/generator.rb 2022-01-18 08:45:16.000000000 +0100 @@ -182,7 +182,8 @@ end def generate(template) - format(template, department: badge.department, cop_name: badge.cop_name) + format(template, department: badge.department.to_s.gsub('/', '::'), + cop_name: badge.cop_name) end def spec_path @@ -209,8 +210,8 @@ return 'rspec' if camel_case_string == 'RSpec' camel_case_string - .gsub(/([^A-Z])([A-Z]+)/, '\1_\2') - .gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2') + .gsub(%r{([^A-Z/])([A-Z]+)}, '\1_\2') + .gsub(%r{([A-Z])([A-Z][^A-Z\d/]+)}, '\1_\2') .downcase end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb new/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb --- old/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb 2022-01-18 08:45:16.000000000 +0100 @@ -33,8 +33,9 @@ def on_send(node) return unless (dispatch_node = dispatch_method(node)) + return unless (dot = dispatch_node.loc.dot) - range = range_between(dispatch_node.loc.dot.begin_pos, dispatch_node.loc.selector.end_pos) + range = range_between(dot.begin_pos, dispatch_node.loc.selector.end_pos) add_offense(range) do |corrector| corrector.remove(range) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/layout/argument_alignment.rb new/lib/rubocop/cop/layout/argument_alignment.rb --- old/lib/rubocop/cop/layout/argument_alignment.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/layout/argument_alignment.rb 2022-01-18 08:45:16.000000000 +0100 @@ -53,23 +53,50 @@ 'following the first line of a multi-line method call.' def on_send(node) - first_arg = node.first_argument - return if !multiple_arguments?(node, first_arg) || (node.send_type? && node.method?(:[]=)) + return if !multiple_arguments?(node) || (node.send_type? && node.method?(:[]=)) - if first_arg.hash_type? && !first_arg.braces? - pairs = first_arg.pairs - check_alignment(pairs, base_column(node, pairs.first)) - else - check_alignment(node.arguments, base_column(node, first_arg)) - end + items = flattened_arguments(node) + + check_alignment(items, base_column(node, items.first)) end + alias on_csend on_send private - def multiple_arguments?(node, first_argument) + def flattened_arguments(node) + if fixed_indentation? + arguments_with_last_arg_pairs(node) + else + arguments_or_first_arg_pairs(node) + end + end + + def arguments_with_last_arg_pairs(node) + items = node.arguments[0..-2] + last_arg = node.arguments.last + + if last_arg.hash_type? && !last_arg.braces? + items += last_arg.pairs + else + items << last_arg + end + items + end + + def arguments_or_first_arg_pairs(node) + first_arg = node.first_argument + if first_arg.hash_type? && !first_arg.braces? + first_arg.pairs + else + node.arguments + end + end + + def multiple_arguments?(node) return true if node.arguments.size >= 2 + first_argument = node.first_argument first_argument&.hash_type? && first_argument.pairs.count >= 2 end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb new/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb --- old/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb 2022-01-18 08:45:16.000000000 +0100 @@ -30,7 +30,11 @@ def on_new_investigation processed_source.diagnostics.each do |diagnostic| - next unless diagnostic.reason == :ambiguous_literal + if target_ruby_version >= 3.0 + next unless diagnostic.reason == :ambiguous_regexp + else + next unless diagnostic.reason == :ambiguous_literal + end offense_node = find_offense_node_by(diagnostic) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/lint/each_with_object_argument.rb new/lib/rubocop/cop/lint/each_with_object_argument.rb --- old/lib/rubocop/cop/lint/each_with_object_argument.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/lint/each_with_object_argument.rb 2022-01-18 08:45:16.000000000 +0100 @@ -27,7 +27,7 @@ # @!method each_with_object?(node) def_node_matcher :each_with_object?, <<~PATTERN - ({send csend} _ :each_with_object $_) + (call _ :each_with_object $_) PATTERN def on_send(node) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb new/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb --- old/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb 2022-01-18 08:45:16.000000000 +0100 @@ -33,11 +33,12 @@ # @!method io_select(node) def_node_matcher :io_select, <<~PATTERN (send - (const {nil? cbase} :IO) :select $_ $_ {(array) nil} $...) + (const {nil? cbase} :IO) :select $...) PATTERN def on_send(node) - return unless (read, write, timeout = io_select(node)) + read, write, _excepts, timeout = *io_select(node) + return unless read return unless scheduler_compatible?(read, write) || scheduler_compatible?(write, read) preferred = preferred_method(read, write, timeout) @@ -51,13 +52,13 @@ private def scheduler_compatible?(io1, io2) - return false unless io1.array_type? && io1.values.size == 1 + return false unless io1&.array_type? && io1.values.size == 1 - io2.array_type? ? io2.values.empty? : io2.nil_type? + io2&.array_type? ? io2.values.empty? : (io2.nil? || io2.nil_type?) end def preferred_method(read, write, timeout) - timeout_argument = timeout.empty? ? '' : "(#{timeout[0].source})" + timeout_argument = timeout.nil? ? '' : "(#{timeout.source})" if read.array_type? && read.values[0] "#{read.values[0].source}.wait_readable#{timeout_argument}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb new/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb --- old/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb 2022-01-18 08:45:16.000000000 +0100 @@ -41,7 +41,11 @@ end node.operator_method? || node.setter_method? || chained_calls?(node) || - operator_keyword?(node) || node.first_argument.hash_type? + valid_first_argument?(node.first_argument) + end + + def valid_first_argument?(first_arg) + first_arg.operator_keyword? || first_arg.hash_type? || ternary_expression?(first_arg) end def first_argument_starts_with_left_parenthesis?(node) @@ -53,9 +57,8 @@ first_argument.send_type? && (node.children.last&.children&.count || 0) > 1 end - def operator_keyword?(node) - first_argument = node.first_argument - first_argument.operator_keyword? + def ternary_expression?(node) + node.if_type? && node.ternary? end def spaces_before_left_parenthesis(node) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb new/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb --- old/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb 2022-01-18 08:45:16.000000000 +0100 @@ -59,7 +59,7 @@ # @!method attribute_call?(node) def_node_matcher :attribute_call?, <<~PATTERN - ( {csend send} _receiver _method # and no parameters + (call _receiver _method # and no parameters ) PATTERN diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb new/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb --- old/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb 2022-01-18 08:45:16.000000000 +0100 @@ -8,7 +8,7 @@ EXPLICIT_HASH_VALUE_MSG = 'Explicit the hash value.' def on_pair(node) - return if target_ruby_version <= 3.0 + return if target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' hash_key_source = node.key.source @@ -46,10 +46,22 @@ def without_parentheses_call_expr_follows?(node) return false unless (ancestor = node.parent.parent) - return false unless (right_sibling = ancestor.right_sibling) - ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? && - right_sibling.respond_to?(:parenthesized?) && !right_sibling.parenthesized? + right_sibling = ancestor.right_sibling + + return true if right_sibling.nil? && without_parentheses?(ancestor) + return false unless right_sibling + return true if node_with_block_and_arguments?(right_sibling) + + without_parentheses?(ancestor) && without_parentheses?(right_sibling) + end + + def without_parentheses?(node) + node.respond_to?(:parenthesized?) && !node.parenthesized? + end + + def node_with_block_and_arguments?(node) + node.respond_to?(:block_type?) && node.block_type? && node.children&.first&.arguments? end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/naming/block_forwarding.rb new/lib/rubocop/cop/naming/block_forwarding.rb --- old/lib/rubocop/cop/naming/block_forwarding.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/naming/block_forwarding.rb 2022-01-18 08:45:16.000000000 +0100 @@ -9,6 +9,9 @@ # by `do_something(&)`. # # It also supports the opposite style by alternative `explicit` option. + # You can specify the block variable name for auto-correction with `BlockForwardingName`. + # The default variable name is `block`. If the name is already in use, it will not be + # auto-corrected. # # @example EnforcedStyle: anonymous (default) # @@ -36,6 +39,7 @@ # class BlockForwarding < Base include ConfigurableEnforcedStyle + include RangeHelp extend AutoCorrector extend TargetRubyVersion @@ -49,12 +53,13 @@ last_argument = node.arguments.last return if expected_block_forwarding_style?(node, last_argument) - register_offense(last_argument) + register_offense(last_argument, node) node.each_descendant(:block_pass) do |block_pass_node| - next if block_pass_node.children.first&.sym_type? + next if block_pass_node.children.first&.sym_type? || + last_argument.source != block_pass_node.source - register_offense(block_pass_node) + register_offense(block_pass_node, node) end end alias on_defs on_def @@ -65,7 +70,7 @@ if style == :anonymous !explicit_block_argument?(last_argument) || use_kwarg_in_method_definition?(node) || - use_block_argument_as_local_variable?(node, last_argument) + use_block_argument_as_local_variable?(node, last_argument.source[1..-1]) else !anonymous_block_argument?(last_argument) end @@ -83,18 +88,32 @@ node.blockarg_type? && !node.name.nil? end + def register_offense(block_argument, node) + add_offense(block_argument, message: format(MSG, style: style)) do |corrector| + if style == :anonymous + corrector.replace(block_argument, '&') + + arguments = block_argument.parent + + add_parentheses(arguments, corrector) unless arguments.parenthesized_call? + else + unless use_block_argument_as_local_variable?(node, block_forwarding_name) + corrector.replace(block_argument, "&#{block_forwarding_name}") + end + end + end + end + def use_block_argument_as_local_variable?(node, last_argument) return if node.body.nil? node.body.each_descendant(:lvar).any? do |lvar| - !lvar.parent.block_pass_type? && lvar.source == last_argument.source[1..-1] + !lvar.parent.block_pass_type? && lvar.source == last_argument end end - def register_offense(block_argument) - add_offense(block_argument, message: format(MSG, style: style)) do |corrector| - corrector.replace(block_argument, '&') - end + def block_forwarding_name + cop_config.fetch('BlockForwardingName', 'block') end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/collection_compact.rb new/lib/rubocop/cop/style/collection_compact.rb --- old/lib/rubocop/cop/style/collection_compact.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/collection_compact.rb 2022-01-18 08:45:16.000000000 +0100 @@ -41,7 +41,7 @@ # @!method reject_method_with_block_pass?(node) def_node_matcher :reject_method_with_block_pass?, <<~PATTERN - (send _ {:reject :reject!} + (send !nil? {:reject :reject!} (block_pass (sym :nil?))) PATTERN @@ -50,7 +50,7 @@ def_node_matcher :reject_method?, <<~PATTERN (block (send - _ {:reject :reject!}) + !nil? {:reject :reject!}) $(args ...) (send $(lvar _) :nil?)) @@ -60,7 +60,7 @@ def_node_matcher :select_method?, <<~PATTERN (block (send - _ {:select :select!}) + !nil? {:select :select!}) $(args ...) (send (send diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/file_write.rb new/lib/rubocop/cop/style/file_write.rb --- old/lib/rubocop/cop/style/file_write.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/file_write.rb 2022-01-18 08:45:16.000000000 +0100 @@ -64,7 +64,7 @@ add_offense(write_node, message: message) do |corrector| range = range_between(node.loc.selector.begin_pos, write_node.loc.expression.end_pos) - replacement = "#{write_method(mode)}(#{filename.source}, #{content.source})" + replacement = replacement(mode, filename, content, write_node) corrector.replace(range, replacement) end @@ -92,6 +92,32 @@ def write_method(mode) mode.end_with?('b') ? :binwrite : :write end + + def replacement(mode, filename, content, write_node) + replacement = "#{write_method(mode)}(#{filename.source}, #{content.source})" + + if heredoc?(write_node) + first_argument = write_node.body.first_argument + + <<~REPLACEMENT.chomp + #{replacement} + #{heredoc_range(first_argument).source} + REPLACEMENT + else + replacement + end + end + + def heredoc?(write_node) + write_node.block_type? && (first_argument = write_node.body.first_argument) && + first_argument.respond_to?(:heredoc?) && first_argument.heredoc? + end + + def heredoc_range(first_argument) + range_between( + first_argument.loc.heredoc_body.begin_pos, first_argument.loc.heredoc_end.end_pos + ) + end end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/hash_syntax.rb new/lib/rubocop/cop/style/hash_syntax.rb --- old/lib/rubocop/cop/style/hash_syntax.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/hash_syntax.rb 2022-01-18 08:45:16.000000000 +0100 @@ -23,6 +23,12 @@ # It can enforce either the use of the explicit hash value syntax or # the use of Ruby 3.1's hash value shorthand syntax. # + # The supported styles are: + # + # * always - forces use of the 3.1 syntax (e.g. {foo:}) + # * never - forces use of explicit hash literal value + # * either - accepts both shorthand and explicit use of hash literal value + # # @example EnforcedStyle: ruby19 (default) # # bad # {:a => 2} @@ -75,6 +81,14 @@ # # good # {foo: foo, bar: bar} # + # @example EnforcedShorthandSyntax: either + # + # # good + # {foo: foo, bar: bar} + # + # # good + # {foo:, bar:} + # class HashSyntax < Base include ConfigurableEnforcedStyle include HashShorthandSyntax diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/hash_transform_keys.rb new/lib/rubocop/cop/style/hash_transform_keys.rb --- old/lib/rubocop/cop/style/hash_transform_keys.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/hash_transform_keys.rb 2022-01-18 08:45:16.000000000 +0100 @@ -30,13 +30,13 @@ # @!method on_bad_each_with_object(node) def_node_matcher :on_bad_each_with_object, <<~PATTERN (block - ({send csend} !#array_receiver? :each_with_object (hash)) + (call !#array_receiver? :each_with_object (hash)) (args (mlhs (arg $_) (arg _val)) (arg _memo)) - ({send csend} (lvar _memo) :[]= $!`_memo $(lvar _val))) + (call (lvar _memo) :[]= $!`_memo $(lvar _val))) PATTERN # @!method on_bad_hash_brackets_map(node) @@ -45,7 +45,7 @@ (const _ :Hash) :[] (block - ({send csend} !#array_receiver? {:map :collect}) + (call !#array_receiver? {:map :collect}) (args (arg $_) (arg _val)) @@ -54,9 +54,9 @@ # @!method on_bad_map_to_h(node) def_node_matcher :on_bad_map_to_h, <<~PATTERN - ({send csend} + (call (block - ({send csend} !#array_receiver? {:map :collect}) + (call !#array_receiver? {:map :collect}) (args (arg $_) (arg _val)) @@ -67,7 +67,7 @@ # @!method on_bad_to_h(node) def_node_matcher :on_bad_to_h, <<~PATTERN (block - ({send csend} !#array_receiver? :to_h) + (call !#array_receiver? :to_h) (args (arg $_) (arg _val)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/hash_transform_values.rb new/lib/rubocop/cop/style/hash_transform_values.rb --- old/lib/rubocop/cop/style/hash_transform_values.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/hash_transform_values.rb 2022-01-18 08:45:16.000000000 +0100 @@ -30,13 +30,13 @@ # @!method on_bad_each_with_object(node) def_node_matcher :on_bad_each_with_object, <<~PATTERN (block - ({send csend} !#array_receiver? :each_with_object (hash)) + (call !#array_receiver? :each_with_object (hash)) (args (mlhs (arg _key) (arg $_)) (arg _memo)) - ({send csend} (lvar _memo) :[]= $(lvar _key) $!`_memo)) + (call (lvar _memo) :[]= $(lvar _key) $!`_memo)) PATTERN # @!method on_bad_hash_brackets_map(node) @@ -45,7 +45,7 @@ (const _ :Hash) :[] (block - ({send csend} !#array_receiver? {:map :collect}) + (call !#array_receiver? {:map :collect}) (args (arg _key) (arg $_)) @@ -54,9 +54,9 @@ # @!method on_bad_map_to_h(node) def_node_matcher :on_bad_map_to_h, <<~PATTERN - ({send csend} + (call (block - ({send csend} !#array_receiver? {:map :collect}) + (call !#array_receiver? {:map :collect}) (args (arg _key) (arg $_)) @@ -67,7 +67,7 @@ # @!method on_bad_to_h(node) def_node_matcher :on_bad_to_h, <<~PATTERN (block - ({send csend} !#array_receiver? :to_h) + (call !#array_receiver? :to_h) (args (arg _key) (arg $_)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb new/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb --- old/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb 2022-01-18 08:45:16.000000000 +0100 @@ -36,7 +36,7 @@ # # good (but potentially an unsafe correction) # foo.do_something? # - # @example AllowedMethods: ['nonzero?'] + # @example AllowedMethods: ['nonzero?'] (default) # # good # num.nonzero? ? true : false # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/map_to_hash.rb new/lib/rubocop/cop/style/map_to_hash.rb --- old/lib/rubocop/cop/style/map_to_hash.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/map_to_hash.rb 2022-01-18 08:45:16.000000000 +0100 @@ -59,7 +59,7 @@ def autocorrect(corrector, to_h, map) removal_range = range_between(to_h.loc.dot.begin_pos, to_h.loc.selector.end_pos) - corrector.remove(removal_range) + corrector.remove(range_with_surrounding_space(range: removal_range, side: :left)) corrector.replace(map.loc.selector, 'to_h') end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb new/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb --- old/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb 2022-01-18 08:45:16.000000000 +0100 @@ -13,9 +13,11 @@ private + # rubocop:disable Metrics/PerceivedComplexity def omit_parentheses(node) return unless node.parenthesized? return if inside_endless_method_def?(node) + return if require_parentheses_for_hash_value_omission?(node) return if syntax_like_method_call?(node) return if super_call_without_arguments?(node) return if allowed_camel_case_method_call?(node) @@ -26,6 +28,7 @@ auto_correct(corrector, node) end end + # rubocop:enable Metrics/PerceivedComplexity def auto_correct(corrector, node) if parentheses_at_the_end_of_multiline_call?(node) @@ -45,6 +48,17 @@ node.each_ancestor(:def, :defs).any?(&:endless?) && node.arguments.any? end + # Require hash value omission be enclosed in parentheses to prevent the following issue: + # https://bugs.ruby-lang.org/issues/18396. + def require_parentheses_for_hash_value_omission?(node) + return false unless (last_argument = node.last_argument) + + next_line = node.parent&.assignment? ? node.parent.right_sibling : node.right_sibling + return false unless next_line + + last_argument.hash_type? && last_argument.pairs.last&.value_omission? && next_line + end + def syntax_like_method_call?(node) node.implicit_call? || node.operator_method? end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/method_call_with_args_parentheses.rb new/lib/rubocop/cop/style/method_call_with_args_parentheses.rb --- old/lib/rubocop/cop/style/method_call_with_args_parentheses.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/method_call_with_args_parentheses.rb 2022-01-18 08:45:16.000000000 +0100 @@ -43,9 +43,11 @@ # NOTE: Parentheses are still allowed in cases where omitting them # results in ambiguous or syntactically incorrect code. For example, # parentheses are required around a method with arguments when inside an - # endless method definition introduced in Ruby 3.0. Parentheses are also + # endless method definition introduced in Ruby 3.0. Parentheses are also # allowed when forwarding arguments with the triple-dot syntax introduced # in Ruby 2.7 as omitting them starts an endless range. + # And Ruby 3.1's hash omission syntax has a case that requires parentheses + # because of the following issue: https://bugs.ruby-lang.org/issues/18396. # # @example EnforcedStyle: require_parentheses (default) # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/method_def_parentheses.rb new/lib/rubocop/cop/style/method_def_parentheses.rb --- old/lib/rubocop/cop/style/method_def_parentheses.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/method_def_parentheses.rb 2022-01-18 08:45:16.000000000 +0100 @@ -6,8 +6,13 @@ # This cop checks for parentheses around the arguments in method # definitions. Both instance and class/singleton methods are checked. # - # This cop does not consider endless methods, since parentheses are - # always required for them. + # Regardless of style, parentheses are necessary for: + # + # 1. Endless methods + # 2. Argument lists containing a `forward-arg` (`...`) + # 3. Argument lists containing an anonymous block forwarding (`&`) + # + # Removing the parens would be a syntax error here. # # @example EnforcedStyle: require_parentheses (default) # # The `require_parentheses` style requires method definitions @@ -121,21 +126,13 @@ corrector.remove(arg_node.loc.end) end - def correct_definition(def_node, corrector) - arguments_range = def_node.arguments.source_range - args_with_space = range_with_surrounding_space(range: arguments_range, side: :left) - leading_space = range_between(args_with_space.begin_pos, arguments_range.begin_pos) - corrector.replace(leading_space, '(') - corrector.insert_after(arguments_range, ')') - end - def forced_parentheses?(node) # Regardless of style, parentheses are necessary for: # 1. Endless methods # 2. Argument lists containing a `forward-arg` (`...`) + # 3. Argument lists containing an anonymous block forwarding (`&`) # Removing the parens would be a syntax error here. - - node.endless? || node.arguments.any?(&:forward_arg_type?) + node.endless? || node.arguments.any?(&:forward_arg_type?) || anonymous_block_arg?(node) end def require_parentheses?(args) @@ -151,7 +148,8 @@ location = node.arguments.source_range add_offense(location, message: MSG_MISSING) do |corrector| - correct_definition(node, corrector) + add_parentheses(node.arguments, corrector) + unexpected_style_detected 'require_no_parentheses' end end @@ -163,6 +161,12 @@ unexpected_style_detected 'require_parentheses' end end + + def anonymous_block_arg?(node) + return false unless (last_argument = node.arguments.last) + + last_argument.blockarg_type? && last_argument.name.nil? + end end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/sample.rb new/lib/rubocop/cop/style/sample.rb --- old/lib/rubocop/cop/style/sample.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/sample.rb 2022-01-18 08:45:16.000000000 +0100 @@ -91,11 +91,12 @@ second.int_type? ? second.to_a.first : :unknown end - def range_size(range_node) # rubocop:todo Metrics/CyclomaticComplexity + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def range_size(range_node) vals = range_node.to_a - return :unknown unless vals.all?(&:int_type?) + return :unknown unless vals.all? { |val| val.nil? || val.int_type? } - low, high = vals.map { |val| val.children[0] } + low, high = vals.map { |val| val.nil? ? 0 : val.children[0] } return :unknown unless low.zero? && high >= 0 case range_node.type @@ -105,6 +106,7 @@ (low..high).size end end + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def source_range(shuffle_node, node) Parser::Source::Range.new(shuffle_node.source_range.source_buffer, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/style/ternary_parentheses.rb new/lib/rubocop/cop/style/ternary_parentheses.rb --- old/lib/rubocop/cop/style/ternary_parentheses.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/style/ternary_parentheses.rb 2022-01-18 08:45:16.000000000 +0100 @@ -67,7 +67,10 @@ MSG_COMPLEX = '%<command>s parentheses for ternary expressions with complex conditions.' def on_if(node) - return if only_closing_parenthesis_is_last_line?(node.condition) + condition = node.condition + + return if only_closing_parenthesis_is_last_line?(condition) + return if condition_as_parenthesized_one_line_pattern_matching?(condition) return unless node.ternary? && !infinite_loop? && offense?(node) message = message(node) @@ -77,11 +80,22 @@ end end + private + def only_closing_parenthesis_is_last_line?(condition) condition.source.split("\n").last == ')' end - private + def condition_as_parenthesized_one_line_pattern_matching?(condition) + return false unless condition.parenthesized_call? + return false unless (first_child = condition.children.first) + + if target_ruby_version >= 3.0 + first_child.match_pattern_p_type? + else + first_child.match_pattern_type? # For Ruby 2.7's one line pattern matching AST. + end + end def autocorrect(corrector, node) condition = node.condition diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/cop/util.rb new/lib/rubocop/cop/util.rb --- old/lib/rubocop/cop/util.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/cop/util.rb 2022-01-18 08:45:16.000000000 +0100 @@ -30,8 +30,15 @@ node.loc.respond_to?(:end) && node.loc.end && node.loc.end.is?(')') end + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def add_parentheses(node, corrector) - if !node.respond_to?(:arguments) + if node.args_type? + arguments_range = node.source_range + args_with_space = range_with_surrounding_space(range: arguments_range, side: :left) + leading_space = range_between(args_with_space.begin_pos, arguments_range.begin_pos) + corrector.replace(leading_space, '(') + corrector.insert_after(arguments_range, ')') + elsif !node.respond_to?(:arguments) corrector.wrap(node, '(', ')') elsif node.arguments.empty? corrector.insert_after(node, '()') @@ -43,6 +50,7 @@ corrector.insert_after(args_end(node), ')') end end + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength def args_begin(node) loc = node.loc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/rubocop/version.rb new/lib/rubocop/version.rb --- old/lib/rubocop/version.rb 2021-12-23 12:06:24.000000000 +0100 +++ new/lib/rubocop/version.rb 2022-01-18 08:45:16.000000000 +0100 @@ -3,7 +3,7 @@ module RuboCop # This module holds the RuboCop version information. module Version - STRING = '1.24.0' + STRING = '1.25.0' MSG = '%<version>s (using Parser %<parser_version>s, '\ 'rubocop-ast %<rubocop_ast_version>s, ' \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2021-12-23 12:06:24.000000000 +0100 +++ new/metadata 2022-01-18 08:45:16.000000000 +0100 @@ -1,7 +1,7 @@ --- !ruby/object:Gem::Specification name: rubocop version: !ruby/object:Gem::Version - version: 1.24.0 + version: 1.25.0 platform: ruby authors: - Bozhidar Batsov @@ -10,7 +10,7 @@ autorequire: bindir: exe cert_chain: [] -date: 2021-12-23 00:00:00.000000000 Z +date: 2022-01-18 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: parallel @@ -32,14 +32,14 @@ requirements: - - ">=" - !ruby/object:Gem::Version - version: 3.0.0.0 + version: 3.1.0.0 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version - version: 3.0.0.0 + version: 3.1.0.0 - !ruby/object:Gem::Dependency name: rainbow requirement: !ruby/object:Gem::Requirement @@ -100,7 +100,7 @@ requirements: - - ">=" - !ruby/object:Gem::Version - version: 1.15.0 + version: 1.15.1 - - "<" - !ruby/object:Gem::Version version: '2.0' @@ -110,7 +110,7 @@ requirements: - - ">=" - !ruby/object:Gem::Version - version: 1.15.0 + version: 1.15.1 - - "<" - !ruby/object:Gem::Version version: '2.0' @@ -911,7 +911,7 @@ homepage_uri: https://rubocop.org/ changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md source_code_uri: https://github.com/rubocop/rubocop/ - documentation_uri: https://docs.rubocop.org/rubocop/1.24/ + documentation_uri: https://docs.rubocop.org/rubocop/1.25/ bug_tracker_uri: https://github.com/rubocop/rubocop/issues rubygems_mfa_required: 'true' post_install_message: