rubocop 1.72.2 → 1.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/config/default.yml +56 -15
- data/config/internal_affairs.yml +20 -0
- data/lib/rubocop/config_loader.rb +0 -1
- data/lib/rubocop/config_loader_resolver.rb +4 -3
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +26 -1
- data/lib/rubocop/cop/layout/line_length.rb +3 -3
- data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -14
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -6
- data/lib/rubocop/cop/lint/literal_as_condition.rb +103 -9
- data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +32 -5
- data/lib/rubocop/cop/lint/return_in_void_context.rb +4 -11
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +12 -1
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +2 -11
- data/lib/rubocop/cop/lint/void.rb +6 -0
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_subset.rb +19 -4
- data/lib/rubocop/cop/mixin/range_help.rb +12 -0
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +12 -0
- data/lib/rubocop/cop/naming/variable_name.rb +64 -6
- data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
- data/lib/rubocop/cop/style/class_and_module_children.rb +29 -7
- data/lib/rubocop/cop/style/commented_keyword.rb +10 -3
- data/lib/rubocop/cop/style/comparable_between.rb +75 -0
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +163 -18
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/exponential_notation.rb +2 -2
- data/lib/rubocop/cop/style/format_string_token.rb +38 -11
- data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -5
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +13 -7
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +3 -3
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
- data/lib/rubocop/cop/style/redundant_condition.rb +45 -0
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +14 -4
- data/lib/rubocop/cop/style/redundant_format.rb +23 -11
- data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -3
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +0 -6
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/utils/format_string.rb +5 -2
- data/lib/rubocop/cops_documentation_generator.rb +12 -1
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/ext/regexp_node.rb +0 -1
- data/lib/rubocop/plugin/load_error.rb +1 -1
- data/lib/rubocop/plugin.rb +9 -2
- data/lib/rubocop/rspec/shared_contexts.rb +15 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -1
- metadata +6 -5
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
| @@ -7,11 +7,6 @@ module RuboCop | |
| 7 7 | 
             
                  #
         | 
| 8 8 | 
             
                  # NOTE: empty `else` branches are handled by `Style/EmptyElse`.
         | 
| 9 9 | 
             
                  #
         | 
| 10 | 
            -
                  # @safety
         | 
| 11 | 
            -
                  #   Autocorrection for this cop is not safe. The conditions for empty branches that
         | 
| 12 | 
            -
                  #   the autocorrection removes may have side effects, or the logic in subsequent
         | 
| 13 | 
            -
                  #   branches may change due to the removal of a previous condition.
         | 
| 14 | 
            -
                  #
         | 
| 15 10 | 
             
                  # @example
         | 
| 16 11 | 
             
                  #   # bad
         | 
| 17 12 | 
             
                  #   if condition
         | 
| @@ -41,6 +36,13 @@ module RuboCop | |
| 41 36 | 
             
                  #   if condition
         | 
| 42 37 | 
             
                  #     do_something
         | 
| 43 38 | 
             
                  #   elsif other_condition
         | 
| 39 | 
            +
                  #     nil
         | 
| 40 | 
            +
                  #   end
         | 
| 41 | 
            +
                  #
         | 
| 42 | 
            +
                  #   # good
         | 
| 43 | 
            +
                  #   if condition
         | 
| 44 | 
            +
                  #     do_something
         | 
| 45 | 
            +
                  #   elsif other_condition
         | 
| 44 46 | 
             
                  #     do_something_else
         | 
| 45 47 | 
             
                  #   end
         | 
| 46 48 | 
             
                  #
         | 
| @@ -63,11 +65,9 @@ module RuboCop | |
| 63 65 | 
             
                  class EmptyConditionalBody < Base
         | 
| 64 66 | 
             
                    extend AutoCorrector
         | 
| 65 67 | 
             
                    include CommentsHelp
         | 
| 66 | 
            -
                    include RangeHelp
         | 
| 67 68 |  | 
| 68 69 | 
             
                    MSG = 'Avoid `%<keyword>s` branches without a body.'
         | 
| 69 70 |  | 
| 70 | 
            -
                    # rubocop:disable Metrics/AbcSize
         | 
| 71 71 | 
             
                    def on_if(node)
         | 
| 72 72 | 
             
                      return if node.body || same_line?(node.loc.begin, node.loc.end)
         | 
| 73 73 | 
             
                      return if cop_config['AllowComments'] && contains_comments?(node)
         | 
| @@ -75,12 +75,11 @@ module RuboCop | |
| 75 75 | 
             
                      range = offense_range(node)
         | 
| 76 76 |  | 
| 77 77 | 
             
                      add_offense(range, message: format(MSG, keyword: node.keyword)) do |corrector|
         | 
| 78 | 
            -
                        next  | 
| 78 | 
            +
                        next unless can_simplify_conditional?(node)
         | 
| 79 79 |  | 
| 80 | 
            -
                         | 
| 80 | 
            +
                        flip_orphaned_else(corrector, node)
         | 
| 81 81 | 
             
                      end
         | 
| 82 82 | 
             
                    end
         | 
| 83 | 
            -
                    # rubocop:enable Metrics/AbcSize
         | 
| 84 83 |  | 
| 85 84 | 
             
                    private
         | 
| 86 85 |  | 
| @@ -92,53 +91,23 @@ module RuboCop | |
| 92 91 | 
             
                      end
         | 
| 93 92 | 
             
                    end
         | 
| 94 93 |  | 
| 95 | 
            -
                    def  | 
| 96 | 
            -
                       | 
| 97 | 
            -
                      remove_empty_branch(corrector, node)
         | 
| 98 | 
            -
                      correct_other_branches(corrector, node)
         | 
| 99 | 
            -
                    end
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                    def remove_comments(corrector, node)
         | 
| 102 | 
            -
                      comments_in_range(node).each do |comment|
         | 
| 103 | 
            -
                        range = range_by_whole_lines(comment.source_range, include_final_newline: true)
         | 
| 104 | 
            -
                        corrector.remove(range)
         | 
| 105 | 
            -
                      end
         | 
| 94 | 
            +
                    def can_simplify_conditional?(node)
         | 
| 95 | 
            +
                      node.else_branch && node.loc.else.source == 'else'
         | 
| 106 96 | 
             
                    end
         | 
| 107 97 |  | 
| 108 | 
            -
                    # rubocop:disable Metrics/AbcSize
         | 
| 109 98 | 
             
                    def remove_empty_branch(corrector, node)
         | 
| 110 99 | 
             
                      range = if empty_if_branch?(node) && else_branch?(node)
         | 
| 111 100 | 
             
                                branch_range(node)
         | 
| 112 | 
            -
                              elsif same_line?(node, else_kw_loc = node.loc.else)
         | 
| 113 | 
            -
                                node.source_range.begin.join(else_kw_loc.begin)
         | 
| 114 | 
            -
                              elsif node.parent&.loc.respond_to?(:end) &&
         | 
| 115 | 
            -
                                    same_line?(node, end_loc = node.parent.loc.end)
         | 
| 116 | 
            -
                                node.source_range.begin.join(end_loc.begin)
         | 
| 117 101 | 
             
                              else
         | 
| 118 102 | 
             
                                deletion_range(branch_range(node))
         | 
| 119 103 | 
             
                              end
         | 
| 120 104 |  | 
| 121 105 | 
             
                      corrector.remove(range)
         | 
| 122 106 | 
             
                    end
         | 
| 123 | 
            -
                    # rubocop:enable Metrics/AbcSize
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                    def correct_other_branches(corrector, node)
         | 
| 126 | 
            -
                      return unless require_other_branches_correction?(node)
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                      if node.else_branch&.if_type? && !node.else_branch.modifier_form?
         | 
| 129 | 
            -
                        # Replace an orphaned `elsif` with `if`
         | 
| 130 | 
            -
                        corrector.replace(node.else_branch.loc.keyword, 'if')
         | 
| 131 | 
            -
                      else
         | 
| 132 | 
            -
                        # Flip orphaned `else`
         | 
| 133 | 
            -
                        corrector.replace(node.loc.else, "#{node.inverse_keyword} #{node.condition.source}")
         | 
| 134 | 
            -
                      end
         | 
| 135 | 
            -
                    end
         | 
| 136 | 
            -
             | 
| 137 | 
            -
                    def require_other_branches_correction?(node)
         | 
| 138 | 
            -
                      return false unless node.if_type? && node.else?
         | 
| 139 | 
            -
                      return false if !empty_if_branch?(node) && node.elsif?
         | 
| 140 107 |  | 
| 141 | 
            -
             | 
| 108 | 
            +
                    def flip_orphaned_else(corrector, node)
         | 
| 109 | 
            +
                      corrector.replace(node.loc.else, "#{node.inverse_keyword} #{node.condition.source}")
         | 
| 110 | 
            +
                      remove_empty_branch(corrector, node)
         | 
| 142 111 | 
             
                    end
         | 
| 143 112 |  | 
| 144 113 | 
             
                    def empty_if_branch?(node)
         | 
| @@ -149,36 +118,17 @@ module RuboCop | |
| 149 118 | 
             
                      if_branch.if_type? && !if_branch.body
         | 
| 150 119 | 
             
                    end
         | 
| 151 120 |  | 
| 152 | 
            -
                    def empty_elsif_branch?(node)
         | 
| 153 | 
            -
                      return false unless (else_branch = node.else_branch)
         | 
| 154 | 
            -
             | 
| 155 | 
            -
                      else_branch.if_type? && !else_branch.body
         | 
| 156 | 
            -
                    end
         | 
| 157 | 
            -
             | 
| 158 121 | 
             
                    def else_branch?(node)
         | 
| 159 122 | 
             
                      node.else_branch && !node.else_branch.if_type?
         | 
| 160 123 | 
             
                    end
         | 
| 161 124 |  | 
| 162 | 
            -
                    # rubocop:disable Metrics/AbcSize
         | 
| 163 125 | 
             
                    def branch_range(node)
         | 
| 164 126 | 
             
                      if empty_if_branch?(node) && else_branch?(node)
         | 
| 165 127 | 
             
                        node.source_range.with(end_pos: node.loc.else.begin_pos)
         | 
| 166 128 | 
             
                      elsif node.loc.else
         | 
| 167 129 | 
             
                        node.source_range.with(end_pos: node.condition.source_range.end_pos)
         | 
| 168 | 
            -
                      elsif all_branches_body_missing?(node)
         | 
| 169 | 
            -
                        if_node = node.ancestors.detect(&:if?)
         | 
| 170 | 
            -
                        node.source_range.join(if_node.loc.end.end)
         | 
| 171 | 
            -
                      else
         | 
| 172 | 
            -
                        node.source_range
         | 
| 173 130 | 
             
                      end
         | 
| 174 131 | 
             
                    end
         | 
| 175 | 
            -
                    # rubocop:enable Metrics/AbcSize
         | 
| 176 | 
            -
             | 
| 177 | 
            -
                    def all_branches_body_missing?(node)
         | 
| 178 | 
            -
                      return false unless node.parent&.if_type?
         | 
| 179 | 
            -
             | 
| 180 | 
            -
                      node.parent.branches.compact.empty?
         | 
| 181 | 
            -
                    end
         | 
| 182 132 |  | 
| 183 133 | 
             
                    def deletion_range(range)
         | 
| 184 134 | 
             
                      # Collect a range between the start of the `if` node and the next relevant node,
         | 
| @@ -156,12 +156,6 @@ module RuboCop | |
| 156 156 |  | 
| 157 157 | 
             
                      overridden_kwargs
         | 
| 158 158 | 
             
                    end
         | 
| 159 | 
            -
             | 
| 160 | 
            -
                    def arguments_range(node)
         | 
| 161 | 
            -
                      arguments = node.arguments
         | 
| 162 | 
            -
             | 
| 163 | 
            -
                      range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
         | 
| 164 | 
            -
                    end
         | 
| 165 159 | 
             
                  end
         | 
| 166 160 | 
             
                end
         | 
| 167 161 | 
             
              end
         | 
| @@ -81,21 +81,16 @@ module RuboCop | |
| 81 81 | 
             
                      (node.numeric_type? && node.value.zero?) || node.nil_type?
         | 
| 82 82 | 
             
                    end
         | 
| 83 83 |  | 
| 84 | 
            -
                    # rubocop:disable Metrics/PerceivedComplexity
         | 
| 85 84 | 
             
                    def check_send(node)
         | 
| 86 85 | 
             
                      if node.arithmetic_operation?
         | 
| 87 86 | 
             
                        float?(node.receiver) || float?(node.first_argument)
         | 
| 88 87 | 
             
                      elsif FLOAT_RETURNING_METHODS.include?(node.method_name)
         | 
| 89 88 | 
             
                        true
         | 
| 90 89 | 
             
                      elsif node.receiver&.float_type?
         | 
| 91 | 
            -
                         | 
| 92 | 
            -
                          true
         | 
| 93 | 
            -
                        else
         | 
| 90 | 
            +
                        FLOAT_INSTANCE_METHODS.include?(node.method_name) ||
         | 
| 94 91 | 
             
                          check_numeric_returning_method(node)
         | 
| 95 | 
            -
                        end
         | 
| 96 92 | 
             
                      end
         | 
| 97 93 | 
             
                    end
         | 
| 98 | 
            -
                    # rubocop:enable Metrics/PerceivedComplexity
         | 
| 99 94 |  | 
| 100 95 | 
             
                    def check_numeric_returning_method(node)
         | 
| 101 96 | 
             
                      return false unless node.receiver
         | 
| @@ -18,12 +18,15 @@ module RuboCop | |
| 18 18 | 
             
                  #   end
         | 
| 19 19 | 
             
                  #
         | 
| 20 20 | 
             
                  #   # bad
         | 
| 21 | 
            -
                  #    | 
| 21 | 
            +
                  #   # We're only interested in the left hand side being a truthy literal,
         | 
| 22 | 
            +
                  #   # because it affects the evaluation of the &&, whereas the right hand
         | 
| 23 | 
            +
                  #   # side will be conditionally executed/called and can be a literal.
         | 
| 24 | 
            +
                  #   if true && some_var
         | 
| 22 25 | 
             
                  #     do_something
         | 
| 23 26 | 
             
                  #   end
         | 
| 24 27 | 
             
                  #
         | 
| 25 28 | 
             
                  #   # good
         | 
| 26 | 
            -
                  #   if some_var | 
| 29 | 
            +
                  #   if some_var
         | 
| 27 30 | 
             
                  #     do_something
         | 
| 28 31 | 
             
                  #   end
         | 
| 29 32 | 
             
                  #
         | 
| @@ -34,27 +37,94 @@ module RuboCop | |
| 34 37 | 
             
                  #   end
         | 
| 35 38 | 
             
                  class LiteralAsCondition < Base
         | 
| 36 39 | 
             
                    include RangeHelp
         | 
| 40 | 
            +
                    extend AutoCorrector
         | 
| 37 41 |  | 
| 38 42 | 
             
                    MSG = 'Literal `%<literal>s` appeared as a condition.'
         | 
| 39 43 | 
             
                    RESTRICT_ON_SEND = [:!].freeze
         | 
| 40 44 |  | 
| 45 | 
            +
                    def on_and(node)
         | 
| 46 | 
            +
                      return unless node.lhs.truthy_literal?
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                      add_offense(node.lhs) do |corrector|
         | 
| 49 | 
            +
                        # Don't autocorrect `'foo' && return` because having `return` as
         | 
| 50 | 
            +
                        # the leftmost node can lead to a void value expression syntax error.
         | 
| 51 | 
            +
                        next if node.rhs.type?(:return, :break, :next)
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                        corrector.replace(node, node.rhs.source)
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
             | 
| 41 57 | 
             
                    def on_if(node)
         | 
| 42 | 
            -
                       | 
| 58 | 
            +
                      cond = condition(node)
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                      if node.unless?
         | 
| 61 | 
            +
                        correct_if_node(node, cond, true) if cond.falsey_literal?
         | 
| 62 | 
            +
                        correct_if_node(node, cond, false) if cond.truthy_literal?
         | 
| 63 | 
            +
                      else
         | 
| 64 | 
            +
                        correct_if_node(node, cond, true) if cond.truthy_literal?
         | 
| 65 | 
            +
                        correct_if_node(node, cond, false) if cond.falsey_literal?
         | 
| 66 | 
            +
                      end
         | 
| 43 67 | 
             
                    end
         | 
| 44 68 |  | 
| 45 69 | 
             
                    def on_while(node)
         | 
| 46 | 
            -
                      return if  | 
| 70 | 
            +
                      return if node.condition.source == 'true'
         | 
| 47 71 |  | 
| 48 | 
            -
                       | 
| 72 | 
            +
                      if node.condition.truthy_literal?
         | 
| 73 | 
            +
                        add_offense(node.condition) do |corrector|
         | 
| 74 | 
            +
                          corrector.replace(node.condition, 'true')
         | 
| 75 | 
            +
                        end
         | 
| 76 | 
            +
                      elsif node.condition.falsey_literal?
         | 
| 77 | 
            +
                        add_offense(node.condition) do |corrector|
         | 
| 78 | 
            +
                          corrector.remove(node)
         | 
| 79 | 
            +
                        end
         | 
| 80 | 
            +
                      end
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    # rubocop:disable Metrics/AbcSize
         | 
| 84 | 
            +
                    def on_while_post(node)
         | 
| 85 | 
            +
                      return if node.condition.source == 'true'
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                      if node.condition.truthy_literal?
         | 
| 88 | 
            +
                        add_offense(node.condition) do |corrector|
         | 
| 89 | 
            +
                          corrector.replace(node, node.source.sub(node.condition.source, 'true'))
         | 
| 90 | 
            +
                        end
         | 
| 91 | 
            +
                      elsif node.condition.falsey_literal?
         | 
| 92 | 
            +
                        add_offense(node.condition) do |corrector|
         | 
| 93 | 
            +
                          corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
         | 
| 94 | 
            +
                        end
         | 
| 95 | 
            +
                      end
         | 
| 49 96 | 
             
                    end
         | 
| 50 | 
            -
                     | 
| 97 | 
            +
                    # rubocop:enable Metrics/AbcSize
         | 
| 51 98 |  | 
| 52 99 | 
             
                    def on_until(node)
         | 
| 53 | 
            -
                      return if  | 
| 100 | 
            +
                      return if node.condition.source == 'false'
         | 
| 54 101 |  | 
| 55 | 
            -
                       | 
| 102 | 
            +
                      if node.condition.falsey_literal?
         | 
| 103 | 
            +
                        add_offense(node.condition) do |corrector|
         | 
| 104 | 
            +
                          corrector.replace(node.condition, 'false')
         | 
| 105 | 
            +
                        end
         | 
| 106 | 
            +
                      elsif node.condition.truthy_literal?
         | 
| 107 | 
            +
                        add_offense(node.condition) do |corrector|
         | 
| 108 | 
            +
                          corrector.remove(node)
         | 
| 109 | 
            +
                        end
         | 
| 110 | 
            +
                      end
         | 
| 111 | 
            +
                    end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                    # rubocop:disable Metrics/AbcSize
         | 
| 114 | 
            +
                    def on_until_post(node)
         | 
| 115 | 
            +
                      return if node.condition.source == 'false'
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                      if node.condition.falsey_literal?
         | 
| 118 | 
            +
                        add_offense(node.condition) do |corrector|
         | 
| 119 | 
            +
                          corrector.replace(node, node.source.sub(node.condition.source, 'false'))
         | 
| 120 | 
            +
                        end
         | 
| 121 | 
            +
                      elsif node.condition.truthy_literal?
         | 
| 122 | 
            +
                        add_offense(node.condition) do |corrector|
         | 
| 123 | 
            +
                          corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
         | 
| 124 | 
            +
                        end
         | 
| 125 | 
            +
                      end
         | 
| 56 126 | 
             
                    end
         | 
| 57 | 
            -
                     | 
| 127 | 
            +
                    # rubocop:enable Metrics/AbcSize
         | 
| 58 128 |  | 
| 59 129 | 
             
                    def on_case(case_node)
         | 
| 60 130 | 
             
                      if case_node.condition
         | 
| @@ -130,6 +200,8 @@ module RuboCop | |
| 130 200 |  | 
| 131 201 | 
             
                    def handle_node(node)
         | 
| 132 202 | 
             
                      if node.literal?
         | 
| 203 | 
            +
                        return if node.parent.and_type?
         | 
| 204 | 
            +
             | 
| 133 205 | 
             
                        add_offense(node)
         | 
| 134 206 | 
             
                      elsif %i[send and or begin].include?(node.type)
         | 
| 135 207 | 
             
                        check_node(node)
         | 
| @@ -159,6 +231,28 @@ module RuboCop | |
| 159 231 | 
             
                        when_node.conditions.last.source_range.end_pos
         | 
| 160 232 | 
             
                      )
         | 
| 161 233 | 
             
                    end
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                    # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
         | 
| 236 | 
            +
                    def correct_if_node(node, cond, result)
         | 
| 237 | 
            +
                      if result
         | 
| 238 | 
            +
                        add_offense(cond) do |corrector|
         | 
| 239 | 
            +
                          corrector.replace(node, node.if_branch.source)
         | 
| 240 | 
            +
                        end
         | 
| 241 | 
            +
                      elsif node.elsif_conditional?
         | 
| 242 | 
            +
                        add_offense(cond) do |corrector|
         | 
| 243 | 
            +
                          corrector.replace(node, "#{node.else_branch.source.sub('elsif', 'if')}\nend")
         | 
| 244 | 
            +
                        end
         | 
| 245 | 
            +
                      elsif node.else? || node.ternary?
         | 
| 246 | 
            +
                        add_offense(cond) do |corrector|
         | 
| 247 | 
            +
                          corrector.replace(node, node.else_branch.source)
         | 
| 248 | 
            +
                        end
         | 
| 249 | 
            +
                      else
         | 
| 250 | 
            +
                        add_offense(cond) do |corrector|
         | 
| 251 | 
            +
                          corrector.remove(node)
         | 
| 252 | 
            +
                        end
         | 
| 253 | 
            +
                      end
         | 
| 254 | 
            +
                    end
         | 
| 255 | 
            +
                    # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
         | 
| 162 256 | 
             
                  end
         | 
| 163 257 | 
             
                end
         | 
| 164 258 | 
             
              end
         | 
| @@ -79,7 +79,7 @@ module RuboCop | |
| 79 79 | 
             
                    end
         | 
| 80 80 |  | 
| 81 81 | 
             
                    def range_pairs(expr)
         | 
| 82 | 
            -
                       | 
| 82 | 
            +
                      expr.expressions.filter_map { |e| [e.expressions[0], e.expressions[1]] if e.type == :set }
         | 
| 83 83 | 
             
                    end
         | 
| 84 84 |  | 
| 85 85 | 
             
                    def unsafe_range?(range_start, range_end)
         | 
| @@ -94,7 +94,7 @@ module RuboCop | |
| 94 94 |  | 
| 95 95 | 
             
                    def skip_range?(range_start, range_end)
         | 
| 96 96 | 
             
                      [range_start, range_end].any? do |bound|
         | 
| 97 | 
            -
                        bound | 
| 97 | 
            +
                        bound&.type != :literal
         | 
| 98 98 | 
             
                      end
         | 
| 99 99 | 
             
                    end
         | 
| 100 100 |  | 
| @@ -46,7 +46,7 @@ module RuboCop | |
| 46 46 | 
             
                    def on_return(return_node)
         | 
| 47 47 | 
             
                      return if return_value?(return_node)
         | 
| 48 48 |  | 
| 49 | 
            -
                      return_node.each_ancestor(: | 
| 49 | 
            +
                      return_node.each_ancestor(:any_block, :def, :defs) do |node|
         | 
| 50 50 | 
             
                        break if scoped_node?(node)
         | 
| 51 51 |  | 
| 52 52 | 
             
                        # if a proc is passed to `Module#define_method` or
         | 
| @@ -54,7 +54,7 @@ module RuboCop | |
| 54 54 | 
             
                        # non-local exit error
         | 
| 55 55 | 
             
                        break if define_method?(node.send_node)
         | 
| 56 56 |  | 
| 57 | 
            -
                        next  | 
| 57 | 
            +
                        next if node.argument_list.empty?
         | 
| 58 58 |  | 
| 59 59 | 
             
                        if chained_send?(node.send_node)
         | 
| 60 60 | 
             
                          add_offense(return_node.loc.keyword)
         | 
| @@ -17,17 +17,12 @@ module RuboCop | |
| 17 17 | 
             
                  #   * 2.0+ ... `enumerator`
         | 
| 18 18 | 
             
                  #   * 2.1+ ... `thread`
         | 
| 19 19 | 
             
                  #   * 2.2+ ... Add `rational` and `complex` above
         | 
| 20 | 
            -
                  #   * 2.5+ ... Add `pp` above
         | 
| 21 20 | 
             
                  #   * 2.7+ ... Add `ruby2_keywords` above
         | 
| 22 21 | 
             
                  #   * 3.1+ ... Add `fiber` above
         | 
| 23 22 | 
             
                  #   * 3.2+ ... `set`
         | 
| 24 23 | 
             
                  #
         | 
| 25 24 | 
             
                  # This cop target those features.
         | 
| 26 25 | 
             
                  #
         | 
| 27 | 
            -
                  # @safety
         | 
| 28 | 
            -
                  #   This cop's autocorrection is unsafe because if `require 'pp'` is removed from one file,
         | 
| 29 | 
            -
                  #   `NameError` can be encountered when another file uses `PP.pp`.
         | 
| 30 | 
            -
                  #
         | 
| 31 26 | 
             
                  # @example
         | 
| 32 27 | 
             
                  #   # bad
         | 
| 33 28 | 
             
                  #   require 'unloaded_feature'
         | 
| @@ -42,10 +37,6 @@ module RuboCop | |
| 42 37 | 
             
                    MSG = 'Remove unnecessary `require` statement.'
         | 
| 43 38 | 
             
                    RESTRICT_ON_SEND = %i[require].freeze
         | 
| 44 39 | 
             
                    RUBY_22_LOADED_FEATURES = %w[rational complex].freeze
         | 
| 45 | 
            -
                    PRETTY_PRINT_METHODS = %i[
         | 
| 46 | 
            -
                      pretty_inspect pretty_print pretty_print_cycle
         | 
| 47 | 
            -
                      pretty_print_inspect pretty_print_instance_variables
         | 
| 48 | 
            -
                    ].freeze
         | 
| 49 40 |  | 
| 50 41 | 
             
                    # @!method redundant_require_statement?(node)
         | 
| 51 42 | 
             
                    def_node_matcher :redundant_require_statement?, <<~PATTERN
         | 
| @@ -53,11 +44,6 @@ module RuboCop | |
| 53 44 | 
             
                        (str #redundant_feature?))
         | 
| 54 45 | 
             
                    PATTERN
         | 
| 55 46 |  | 
| 56 | 
            -
                    # @!method pp_const?(node)
         | 
| 57 | 
            -
                    def_node_matcher :pp_const?, <<~PATTERN
         | 
| 58 | 
            -
                      (const {nil? cbase} :PP)
         | 
| 59 | 
            -
                    PATTERN
         | 
| 60 | 
            -
             | 
| 61 47 | 
             
                    def on_send(node)
         | 
| 62 48 | 
             
                      return unless redundant_require_statement?(node)
         | 
| 63 49 |  | 
| @@ -81,18 +67,11 @@ module RuboCop | |
| 81 67 | 
             
                      feature_name == 'enumerator' ||
         | 
| 82 68 | 
             
                        (target_ruby_version >= 2.1 && feature_name == 'thread') ||
         | 
| 83 69 | 
             
                        (target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
         | 
| 84 | 
            -
                        (target_ruby_version >= 2.5 && feature_name == 'pp' && !need_to_require_pp?) ||
         | 
| 85 70 | 
             
                        (target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
         | 
| 86 71 | 
             
                        (target_ruby_version >= 3.1 && feature_name == 'fiber') ||
         | 
| 87 72 | 
             
                        (target_ruby_version >= 3.2 && feature_name == 'set')
         | 
| 88 73 | 
             
                    end
         | 
| 89 74 | 
             
                    # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                    def need_to_require_pp?
         | 
| 92 | 
            -
                      processed_source.ast.each_descendant(:send).any? do |node|
         | 
| 93 | 
            -
                        pp_const?(node.receiver) || PRETTY_PRINT_METHODS.include?(node.method_name)
         | 
| 94 | 
            -
                      end
         | 
| 95 | 
            -
                    end
         | 
| 96 75 | 
             
                  end
         | 
| 97 76 | 
             
                end
         | 
| 98 77 | 
             
              end
         | 
| @@ -3,13 +3,13 @@ | |
| 3 3 | 
             
            module RuboCop
         | 
| 4 4 | 
             
              module Cop
         | 
| 5 5 | 
             
                module Lint
         | 
| 6 | 
            -
                  # Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_r`, `to_c`,
         | 
| 6 | 
            +
                  # Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_d`, `to_r`, `to_c`,
         | 
| 7 7 | 
             
                  # `to_a`, `to_h`, and `to_set`.
         | 
| 8 8 | 
             
                  #
         | 
| 9 9 | 
             
                  # When one of these methods is called on an object of the same type, that object
         | 
| 10 10 | 
             
                  # is returned, making the call unnecessary. The cop detects conversion methods called
         | 
| 11 11 | 
             
                  # on object literals, class constructors, class `[]` methods, and the `Kernel` methods
         | 
| 12 | 
            -
                  # `String()`, `Integer()`, `Float()`, `Rational()`, `Complex() | 
| 12 | 
            +
                  # `String()`, `Integer()`, `Float()`, BigDecimal(), `Rational()`, `Complex()`, and `Array()`.
         | 
| 13 13 | 
             
                  #
         | 
| 14 14 | 
             
                  # Specifically, these cases are detected for each conversion method:
         | 
| 15 15 | 
             
                  #
         | 
| @@ -39,7 +39,7 @@ module RuboCop | |
| 39 39 | 
             
                  #   1i.to_c
         | 
| 40 40 | 
             
                  #   [].to_a
         | 
| 41 41 | 
             
                  #   {}.to_h
         | 
| 42 | 
            -
                  #   Set.new. | 
| 42 | 
            +
                  #   Set.new.to_set
         | 
| 43 43 | 
             
                  #
         | 
| 44 44 | 
             
                  #   # good
         | 
| 45 45 | 
             
                  #   "text"
         | 
| @@ -52,6 +52,16 @@ module RuboCop | |
| 52 52 | 
             
                  #   {}
         | 
| 53 53 | 
             
                  #   Set.new
         | 
| 54 54 | 
             
                  #
         | 
| 55 | 
            +
                  #   # bad
         | 
| 56 | 
            +
                  #   Integer(var).to_i
         | 
| 57 | 
            +
                  #
         | 
| 58 | 
            +
                  #   # good
         | 
| 59 | 
            +
                  #   Integer(var)
         | 
| 60 | 
            +
                  #
         | 
| 61 | 
            +
                  #   # good - chaining to a type constructor with exceptions suppressed
         | 
| 62 | 
            +
                  #   # in this case, `Integer()` could return `nil`
         | 
| 63 | 
            +
                  #   Integer(var, exception: false).to_i
         | 
| 64 | 
            +
                  #
         | 
| 55 65 | 
             
                  #   # bad - chaining the same conversion
         | 
| 56 66 | 
             
                  #   foo.to_s.to_s
         | 
| 57 67 | 
             
                  #
         | 
| @@ -88,6 +98,7 @@ module RuboCop | |
| 88 98 | 
             
                      to_s: 'string_constructor?',
         | 
| 89 99 | 
             
                      to_i: 'integer_constructor?',
         | 
| 90 100 | 
             
                      to_f: 'float_constructor?',
         | 
| 101 | 
            +
                      to_d: 'bigdecimal_constructor?',
         | 
| 91 102 | 
             
                      to_r: 'rational_constructor?',
         | 
| 92 103 | 
             
                      to_c: 'complex_constructor?',
         | 
| 93 104 | 
             
                      to_a: 'array_constructor?',
         | 
| @@ -100,7 +111,7 @@ module RuboCop | |
| 100 111 | 
             
                    TYPED_METHODS = { to_s: %i[inspect] }.freeze
         | 
| 101 112 |  | 
| 102 113 | 
             
                    CONVERSION_METHODS = Set[*LITERAL_NODE_TYPES.keys].freeze
         | 
| 103 | 
            -
                    RESTRICT_ON_SEND = CONVERSION_METHODS
         | 
| 114 | 
            +
                    RESTRICT_ON_SEND = CONVERSION_METHODS + [:to_d]
         | 
| 104 115 |  | 
| 105 116 | 
             
                    private_constant :LITERAL_NODE_TYPES, :CONSTRUCTOR_MAPPING
         | 
| 106 117 |  | 
| @@ -127,6 +138,11 @@ module RuboCop | |
| 127 138 | 
             
                      #type_constructor?(:Float)
         | 
| 128 139 | 
             
                    PATTERN
         | 
| 129 140 |  | 
| 141 | 
            +
                    # @!method bigdecimal_constructor?(node)
         | 
| 142 | 
            +
                    def_node_matcher :bigdecimal_constructor?, <<~PATTERN
         | 
| 143 | 
            +
                      #type_constructor?(:BigDecimal)
         | 
| 144 | 
            +
                    PATTERN
         | 
| 145 | 
            +
             | 
| 130 146 | 
             
                    # @!method rational_constructor?(node)
         | 
| 131 147 | 
             
                    def_node_matcher :rational_constructor?, <<~PATTERN
         | 
| 132 148 | 
             
                      #type_constructor?(:Rational)
         | 
| @@ -161,6 +177,11 @@ module RuboCop | |
| 161 177 | 
             
                      }
         | 
| 162 178 | 
             
                    PATTERN
         | 
| 163 179 |  | 
| 180 | 
            +
                    # @!method exception_false_keyword_argument?(node)
         | 
| 181 | 
            +
                    def_node_matcher :exception_false_keyword_argument?, <<~PATTERN
         | 
| 182 | 
            +
                      (hash (pair (sym :exception) false))
         | 
| 183 | 
            +
                    PATTERN
         | 
| 184 | 
            +
             | 
| 164 185 | 
             
                    # rubocop:disable Metrics/AbcSize
         | 
| 165 186 | 
             
                    def on_send(node)
         | 
| 166 187 | 
             
                      return if hash_or_set_with_block?(node)
         | 
| @@ -211,7 +232,13 @@ module RuboCop | |
| 211 232 | 
             
                      matcher = CONSTRUCTOR_MAPPING[node.method_name]
         | 
| 212 233 | 
             
                      return false unless matcher
         | 
| 213 234 |  | 
| 214 | 
            -
                      public_send(matcher, receiver)
         | 
| 235 | 
            +
                      public_send(matcher, receiver) && !constructor_suppresses_exceptions?(receiver)
         | 
| 236 | 
            +
                    end
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                    def constructor_suppresses_exceptions?(receiver)
         | 
| 239 | 
            +
                      # If the constructor suppresses exceptions with `exception: false`, it is possible
         | 
| 240 | 
            +
                      # it could return `nil`, and therefore a chained conversion is not redundant.
         | 
| 241 | 
            +
                      receiver.arguments.any? { |arg| exception_false_keyword_argument?(arg) }
         | 
| 215 242 | 
             
                    end
         | 
| 216 243 |  | 
| 217 244 | 
             
                    def chained_conversion?(node, receiver)
         | 
| @@ -35,22 +35,15 @@ module RuboCop | |
| 35 35 | 
             
                    def on_return(return_node)
         | 
| 36 36 | 
             
                      return unless return_node.descendants.any?
         | 
| 37 37 |  | 
| 38 | 
            -
                       | 
| 39 | 
            -
             | 
| 40 | 
            -
                      return  | 
| 41 | 
            -
                      return unless context_node&.void_context?
         | 
| 38 | 
            +
                      def_node = return_node.each_ancestor(:def).first
         | 
| 39 | 
            +
                      return unless def_node&.void_context?
         | 
| 40 | 
            +
                      return if return_node.each_ancestor(:any_block).any?(&:lambda?)
         | 
| 42 41 |  | 
| 43 42 | 
             
                      add_offense(
         | 
| 44 43 | 
             
                        return_node.loc.keyword,
         | 
| 45 | 
            -
                        message: format(message, method:  | 
| 44 | 
            +
                        message: format(message, method: def_node.method_name)
         | 
| 46 45 | 
             
                      )
         | 
| 47 46 | 
             
                    end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                    private
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                    def non_void_context(return_node)
         | 
| 52 | 
            -
                      return_node.each_ancestor(:block, :def, :defs).first
         | 
| 53 | 
            -
                    end
         | 
| 54 47 | 
             
                  end
         | 
| 55 48 | 
             
                end
         | 
| 56 49 | 
             
              end
         | 
| @@ -51,7 +51,18 @@ module RuboCop | |
| 51 51 |  | 
| 52 52 | 
             
                    # @!method hash_initialized_with_mutable_shared_object?(node)
         | 
| 53 53 | 
             
                    def_node_matcher :hash_initialized_with_mutable_shared_object?, <<~PATTERN
         | 
| 54 | 
            -
                       | 
| 54 | 
            +
                      {
         | 
| 55 | 
            +
                        (send (const {nil? cbase} :Hash) :new [
         | 
| 56 | 
            +
                          {array hash (send (const {nil? cbase} {:Array :Hash}) :new)}
         | 
| 57 | 
            +
                          !#capacity_keyword_argument?
         | 
| 58 | 
            +
                        ])
         | 
| 59 | 
            +
                        (send (const {nil? cbase} :Hash) :new hash #capacity_keyword_argument?)
         | 
| 60 | 
            +
                      }
         | 
| 61 | 
            +
                    PATTERN
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    # @!method capacity_keyword_argument?(node)
         | 
| 64 | 
            +
                    def_node_matcher :capacity_keyword_argument?, <<~PATTERN
         | 
| 65 | 
            +
                      (hash (pair (sym :capacity) _))
         | 
| 55 66 | 
             
                    PATTERN
         | 
| 56 67 |  | 
| 57 68 | 
             
                    def on_send(node)
         | 
| @@ -4,8 +4,8 @@ module RuboCop | |
| 4 4 | 
             
              module Cop
         | 
| 5 5 | 
             
                module Lint
         | 
| 6 6 | 
             
                  # Checks for useless constant scoping. Private constants must be defined using
         | 
| 7 | 
            -
                  # `private_constant | 
| 8 | 
            -
                  #  | 
| 7 | 
            +
                  # `private_constant`. Even if `private` access modifier is used, it is public scope despite
         | 
| 8 | 
            +
                  # its appearance.
         | 
| 9 9 | 
             
                  #
         | 
| 10 10 | 
             
                  # It does not support autocorrection due to behavior change and multiple ways to fix it.
         | 
| 11 11 | 
             
                  # Or a public constant may be intended.
         | 
| @@ -26,14 +26,6 @@ module RuboCop | |
| 26 26 | 
             
                  #
         | 
| 27 27 | 
             
                  #   # good
         | 
| 28 28 | 
             
                  #   class Foo
         | 
| 29 | 
            -
                  #     class << self
         | 
| 30 | 
            -
                  #       private
         | 
| 31 | 
            -
                  #       PRIVATE_CONST = 42
         | 
| 32 | 
            -
                  #     end
         | 
| 33 | 
            -
                  #   end
         | 
| 34 | 
            -
                  #
         | 
| 35 | 
            -
                  #   # good
         | 
| 36 | 
            -
                  #   class Foo
         | 
| 37 29 | 
             
                  #     PUBLIC_CONST = 42 # If private scope is not intended.
         | 
| 38 30 | 
             
                  #   end
         | 
| 39 31 | 
             
                  #
         | 
| @@ -46,7 +38,6 @@ module RuboCop | |
| 46 38 | 
             
                    PATTERN
         | 
| 47 39 |  | 
| 48 40 | 
             
                    def on_casgn(node)
         | 
| 49 | 
            -
                      return if node.each_ancestor(:sclass).any?
         | 
| 50 41 | 
             
                      return unless after_private_modifier?(node.left_siblings)
         | 
| 51 42 | 
             
                      return if private_constantize?(node.right_siblings, node.name)
         | 
| 52 43 |  | 
| @@ -125,9 +125,14 @@ module RuboCop | |
| 125 125 | 
             
                      check_nonmutating(expr)
         | 
| 126 126 | 
             
                    end
         | 
| 127 127 |  | 
| 128 | 
            +
                    # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         | 
| 128 129 | 
             
                    def check_void_op(node, &block)
         | 
| 129 130 | 
             
                      node = node.children.first while node.begin_type?
         | 
| 130 131 | 
             
                      return unless node.call_type? && OPERATORS.include?(node.method_name)
         | 
| 132 | 
            +
                      if !UNARY_OPERATORS.include?(node.method_name) && node.loc.dot && node.arguments.none?
         | 
| 133 | 
            +
                        return
         | 
| 134 | 
            +
                      end
         | 
| 135 | 
            +
             | 
| 131 136 | 
             
                      return if block && yield(node)
         | 
| 132 137 |  | 
| 133 138 | 
             
                      add_offense(node.loc.selector,
         | 
| @@ -135,6 +140,7 @@ module RuboCop | |
| 135 140 | 
             
                        autocorrect_void_op(corrector, node)
         | 
| 136 141 | 
             
                      end
         | 
| 137 142 | 
             
                    end
         | 
| 143 | 
            +
                    # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         | 
| 138 144 |  | 
| 139 145 | 
             
                    def check_var(node)
         | 
| 140 146 | 
             
                      return unless node.variable? || node.const_type?
         | 
| @@ -35,7 +35,7 @@ module RuboCop | |
| 35 35 | 
             
                    comment_line_numbers = processed_source.comments.map { |comment| comment.loc.line }
         | 
| 36 36 |  | 
| 37 37 | 
             
                    comment_line_numbers.any? do |comment_line_number|
         | 
| 38 | 
            -
                      comment_line_number | 
| 38 | 
            +
                      comment_line_number.between?(node.first_line, node.last_line)
         | 
| 39 39 | 
             
                    end
         | 
| 40 40 | 
             
                  end
         | 
| 41 41 |  |