rubocop 0.90.0 → 0.91.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 +2 -2
 - data/config/default.yml +35 -0
 - data/lib/rubocop.rb +10 -1
 - data/lib/rubocop/cli/command/execute_runner.rb +8 -0
 - data/lib/rubocop/config_loader.rb +3 -3
 - data/lib/rubocop/config_store.rb +3 -3
 - data/lib/rubocop/cop/bundler/duplicated_gem.rb +5 -1
 - data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
 - data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -0
 - data/lib/rubocop/cop/generator.rb +1 -1
 - data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
 - data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
 - data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +1 -0
 - data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -0
 - data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -0
 - data/lib/rubocop/cop/layout/begin_end_alignment.rb +77 -0
 - data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
 - data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +6 -5
 - data/lib/rubocop/cop/layout/end_alignment.rb +5 -10
 - data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +17 -4
 - data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -3
 - data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -6
 - data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -0
 - data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -2
 - data/lib/rubocop/cop/lint/constant_definition_in_block.rb +54 -0
 - data/lib/rubocop/cop/lint/debugger.rb +2 -3
 - data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -3
 - data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -4
 - data/lib/rubocop/cop/lint/duplicate_require.rb +7 -2
 - data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
 - data/lib/rubocop/cop/lint/empty_file.rb +1 -4
 - data/lib/rubocop/cop/lint/erb_new_arguments.rb +2 -0
 - data/lib/rubocop/cop/lint/float_comparison.rb +2 -2
 - data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
 - data/lib/rubocop/cop/lint/identity_comparison.rb +49 -0
 - data/lib/rubocop/cop/lint/inherit_exception.rb +2 -2
 - data/lib/rubocop/cop/lint/multiple_comparison.rb +3 -1
 - data/lib/rubocop/cop/lint/number_conversion.rb +1 -0
 - data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -2
 - data/lib/rubocop/cop/lint/raise_exception.rb +1 -0
 - data/lib/rubocop/cop/lint/rand_one.rb +2 -1
 - data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
 - data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +3 -1
 - data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
 - data/lib/rubocop/cop/lint/to_json.rb +16 -5
 - data/lib/rubocop/cop/lint/unreachable_loop.rb +2 -1
 - data/lib/rubocop/cop/lint/uri_escape_unescape.rb +3 -1
 - data/lib/rubocop/cop/lint/uri_regexp.rb +2 -1
 - data/lib/rubocop/cop/lint/useless_method_definition.rb +20 -27
 - data/lib/rubocop/cop/lint/useless_times.rb +97 -0
 - data/lib/rubocop/cop/mixin/comments_help.rb +3 -9
 - data/lib/rubocop/cop/mixin/configurable_naming.rb +2 -2
 - data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +9 -0
 - data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -1
 - data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
 - data/lib/rubocop/cop/naming/file_name.rb +1 -1
 - data/lib/rubocop/cop/security/eval.rb +1 -0
 - data/lib/rubocop/cop/security/json_load.rb +1 -0
 - data/lib/rubocop/cop/security/marshal_load.rb +1 -0
 - data/lib/rubocop/cop/security/open.rb +1 -0
 - data/lib/rubocop/cop/security/yaml_load.rb +1 -0
 - data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -11
 - data/lib/rubocop/cop/style/alias.rb +2 -0
 - data/lib/rubocop/cop/style/array_join.rb +1 -0
 - data/lib/rubocop/cop/style/attr.rb +1 -0
 - data/lib/rubocop/cop/style/auto_resource_cleanup.rb +2 -0
 - data/lib/rubocop/cop/style/case_equality.rb +3 -0
 - data/lib/rubocop/cop/style/class_and_module_children.rb +2 -0
 - data/lib/rubocop/cop/style/class_check.rb +6 -9
 - data/lib/rubocop/cop/style/class_methods_definitions.rb +42 -16
 - data/lib/rubocop/cop/style/class_vars.rb +1 -2
 - data/lib/rubocop/cop/style/conditional_assignment.rb +49 -60
 - data/lib/rubocop/cop/style/dir.rb +1 -0
 - data/lib/rubocop/cop/style/double_negation.rb +1 -0
 - data/lib/rubocop/cop/style/empty_literal.rb +3 -1
 - data/lib/rubocop/cop/style/eval_with_location.rb +1 -3
 - data/lib/rubocop/cop/style/even_odd.rb +1 -0
 - data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -2
 - data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
 - data/lib/rubocop/cop/style/float_division.rb +2 -0
 - data/lib/rubocop/cop/style/format_string.rb +1 -4
 - data/lib/rubocop/cop/style/hash_as_last_array_item.rb +12 -2
 - data/lib/rubocop/cop/style/hash_transform_keys.rb +5 -11
 - data/lib/rubocop/cop/style/hash_transform_values.rb +5 -11
 - data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
 - data/lib/rubocop/cop/style/lambda_call.rb +3 -1
 - data/lib/rubocop/cop/style/mixin_usage.rb +1 -0
 - data/lib/rubocop/cop/style/multiline_ternary_operator.rb +14 -1
 - data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
 - data/lib/rubocop/cop/style/non_nil_check.rb +2 -0
 - data/lib/rubocop/cop/style/not.rb +1 -0
 - data/lib/rubocop/cop/style/numeric_predicate.rb +1 -3
 - data/lib/rubocop/cop/style/preferred_hash_methods.rb +2 -0
 - data/lib/rubocop/cop/style/raise_args.rb +2 -0
 - data/lib/rubocop/cop/style/random_with_offset.rb +1 -0
 - data/lib/rubocop/cop/style/redundant_exception.rb +1 -3
 - data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
 - data/lib/rubocop/cop/style/redundant_freeze.rb +2 -1
 - data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -3
 - data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -2
 - data/lib/rubocop/cop/style/redundant_sort.rb +1 -7
 - data/lib/rubocop/cop/style/safe_navigation.rb +5 -0
 - data/lib/rubocop/cop/style/sample.rb +2 -1
 - data/lib/rubocop/cop/style/send.rb +2 -3
 - data/lib/rubocop/cop/style/signal_exception.rb +2 -0
 - data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
 - data/lib/rubocop/cop/style/slicing_with_range.rb +2 -1
 - data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
 - data/lib/rubocop/cop/style/string_concatenation.rb +16 -2
 - data/lib/rubocop/cop/style/strip.rb +1 -0
 - data/lib/rubocop/cop/style/unpack_first.rb +1 -0
 - data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -5
 - data/lib/rubocop/core_ext/string.rb +1 -1
 - data/lib/rubocop/ext/regexp_node.rb +4 -4
 - data/lib/rubocop/options.rb +19 -1
 - data/lib/rubocop/result_cache.rb +30 -13
 - data/lib/rubocop/runner.rb +29 -14
 - data/lib/rubocop/version.rb +1 -1
 - metadata +8 -4
 
| 
         @@ -49,6 +49,10 @@ module RuboCop 
     | 
|
| 
       49 
49 
     | 
    
         
             
                  #   foo && foo < bar
         
     | 
| 
       50 
50 
     | 
    
         
             
                  #   foo < bar if foo
         
     | 
| 
       51 
51 
     | 
    
         
             
                  #
         
     | 
| 
      
 52 
     | 
    
         
            +
                  #   # When checking `foo&.empty?` in a conditional, `foo` being `nil` will actually
         
     | 
| 
      
 53 
     | 
    
         
            +
                  #   # do the opposite of what the author intends.
         
     | 
| 
      
 54 
     | 
    
         
            +
                  #   foo && foo.empty?
         
     | 
| 
      
 55 
     | 
    
         
            +
                  #
         
     | 
| 
       52 
56 
     | 
    
         
             
                  #   # This could start returning `nil` as well as the return of the method
         
     | 
| 
       53 
57 
     | 
    
         
             
                  #   foo.nil? || foo.bar
         
     | 
| 
       54 
58 
     | 
    
         
             
                  #   !foo || foo.bar
         
     | 
| 
         @@ -104,6 +108,7 @@ module RuboCop 
     | 
|
| 
       104 
108 
     | 
    
         
             
                      # chain greater than 2
         
     | 
| 
       105 
109 
     | 
    
         
             
                      return if chain_size(method_chain, method) > 1
         
     | 
| 
       106 
110 
     | 
    
         
             
                      return if unsafe_method_used?(method_chain, method)
         
     | 
| 
      
 111 
     | 
    
         
            +
                      return if method_chain.method?(:empty?)
         
     | 
| 
       107 
112 
     | 
    
         | 
| 
       108 
113 
     | 
    
         
             
                      add_offense(node) do |corrector|
         
     | 
| 
       109 
114 
     | 
    
         
             
                        autocorrect(corrector, node)
         
     | 
| 
         @@ -31,9 +31,10 @@ module RuboCop 
     | 
|
| 
       31 
31 
     | 
    
         
             
                    extend AutoCorrector
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
                    MSG = 'Use `%<correct>s` instead of `%<incorrect>s`.'
         
     | 
| 
      
 34 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[first last [] at slice].freeze
         
     | 
| 
       34 
35 
     | 
    
         | 
| 
       35 
36 
     | 
    
         
             
                    def_node_matcher :sample_candidate?, <<~PATTERN
         
     | 
| 
       36 
     | 
    
         
            -
                      (send $(send _ :shuffle $...) ${ 
     | 
| 
      
 37 
     | 
    
         
            +
                      (send $(send _ :shuffle $...) ${:#{RESTRICT_ON_SEND.join(' :')}} $...)
         
     | 
| 
       37 
38 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       38 
39 
     | 
    
         | 
| 
       39 
40 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
         @@ -16,11 +16,10 @@ module RuboCop 
     | 
|
| 
       16 
16 
     | 
    
         
             
                  class Send < Base
         
     | 
| 
       17 
17 
     | 
    
         
             
                    MSG = 'Prefer `Object#__send__` or `Object#public_send` to ' \
         
     | 
| 
       18 
18 
     | 
    
         
             
                          '`send`.'
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                    def_node_matcher :sending?, '({send csend} _ :send ...)'
         
     | 
| 
      
 19 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[send].freeze
         
     | 
| 
       21 
20 
     | 
    
         | 
| 
       22 
21 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       23 
     | 
    
         
            -
                      return unless  
     | 
| 
      
 22 
     | 
    
         
            +
                      return unless node.arguments?
         
     | 
| 
       24 
23 
     | 
    
         | 
| 
       25 
24 
     | 
    
         
             
                      add_offense(node.loc.selector)
         
     | 
| 
       26 
25 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -112,6 +112,8 @@ module RuboCop 
     | 
|
| 
       112 
112 
     | 
    
         
             
                    RAISE_MSG = 'Use `raise` instead of `fail` to ' \
         
     | 
| 
       113 
113 
     | 
    
         
             
                                'rethrow exceptions.'
         
     | 
| 
       114 
114 
     | 
    
         | 
| 
      
 115 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[raise fail].freeze
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
       115 
117 
     | 
    
         
             
                    def_node_matcher :kernel_call?, '(send (const {nil? cbase} :Kernel) %1 ...)'
         
     | 
| 
       116 
118 
     | 
    
         
             
                    def_node_search :custom_fail_methods,
         
     | 
| 
       117 
119 
     | 
    
         
             
                                    '{(def :fail ...) (defs _ :fail ...)}'
         
     | 
| 
         @@ -19,11 +19,12 @@ module RuboCop 
     | 
|
| 
       19 
19 
     | 
    
         
             
                    minimum_target_ruby_version 2.6
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
                    MSG = 'Prefer ary[n..] over ary[n..-1].'
         
     | 
| 
      
 22 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[[]].freeze
         
     | 
| 
       22 
23 
     | 
    
         | 
| 
       23 
24 
     | 
    
         
             
                    def_node_matcher :range_till_minus_one?, '(irange !nil? (int -1))'
         
     | 
| 
       24 
25 
     | 
    
         | 
| 
       25 
26 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       26 
     | 
    
         
            -
                      return unless node. 
     | 
| 
      
 27 
     | 
    
         
            +
                      return unless node.arguments.count == 1
         
     | 
| 
       27 
28 
     | 
    
         
             
                      return unless range_till_minus_one?(node.arguments.first)
         
     | 
| 
       28 
29 
     | 
    
         | 
| 
       29 
30 
     | 
    
         
             
                      add_offense(node.first_argument) do |corrector|
         
     | 
| 
         @@ -6,6 +6,11 @@ module RuboCop 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  # This cop checks for places where string concatenation
         
     | 
| 
       7 
7 
     | 
    
         
             
                  # can be replaced with string interpolation.
         
     | 
| 
       8 
8 
     | 
    
         
             
                  #
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # The cop can autocorrect simple cases but will skip autocorrecting
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # more complex cases where the resulting code would be harder to read.
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # In those cases, it might be useful to extract statements to local
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # variables or methods which you can then interpolate in a string.
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
       9 
14 
     | 
    
         
             
                  # @example
         
     | 
| 
       10 
15 
     | 
    
         
             
                  #   # bad
         
     | 
| 
       11 
16 
     | 
    
         
             
                  #   email_with_name = user.name + ' <' + user.email + '>'
         
     | 
| 
         @@ -19,6 +24,7 @@ module RuboCop 
     | 
|
| 
       19 
24 
     | 
    
         
             
                    extend AutoCorrector
         
     | 
| 
       20 
25 
     | 
    
         | 
| 
       21 
26 
     | 
    
         
             
                    MSG = 'Prefer string interpolation to string concatenation.'
         
     | 
| 
      
 27 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[+].freeze
         
     | 
| 
       22 
28 
     | 
    
         | 
| 
       23 
29 
     | 
    
         
             
                    def_node_matcher :string_concatenation?, <<~PATTERN
         
     | 
| 
       24 
30 
     | 
    
         
             
                      {
         
     | 
| 
         @@ -28,7 +34,6 @@ module RuboCop 
     | 
|
| 
       28 
34 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       29 
35 
     | 
    
         | 
| 
       30 
36 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       31 
     | 
    
         
            -
                      return unless node.method?(:+)
         
     | 
| 
       32 
37 
     | 
    
         
             
                      return unless string_concatenation?(node)
         
     | 
| 
       33 
38 
     | 
    
         | 
| 
       34 
39 
     | 
    
         
             
                      topmost_plus_node = find_topmost_plus_node(node)
         
     | 
| 
         @@ -37,7 +42,9 @@ module RuboCop 
     | 
|
| 
       37 
42 
     | 
    
         
             
                      collect_parts(topmost_plus_node, parts)
         
     | 
| 
       38 
43 
     | 
    
         | 
| 
       39 
44 
     | 
    
         
             
                      add_offense(topmost_plus_node) do |corrector|
         
     | 
| 
       40 
     | 
    
         
            -
                         
     | 
| 
      
 45 
     | 
    
         
            +
                        if parts.none? { |part| uncorrectable?(part) }
         
     | 
| 
      
 46 
     | 
    
         
            +
                          corrector.replace(topmost_plus_node, replacement(parts))
         
     | 
| 
      
 47 
     | 
    
         
            +
                        end
         
     | 
| 
       41 
48 
     | 
    
         
             
                      end
         
     | 
| 
       42 
49 
     | 
    
         
             
                    end
         
     | 
| 
       43 
50 
     | 
    
         | 
| 
         @@ -66,6 +73,13 @@ module RuboCop 
     | 
|
| 
       66 
73 
     | 
    
         
             
                      node.send_type? && node.method?(:+)
         
     | 
| 
       67 
74 
     | 
    
         
             
                    end
         
     | 
| 
       68 
75 
     | 
    
         | 
| 
      
 76 
     | 
    
         
            +
                    def uncorrectable?(part)
         
     | 
| 
      
 77 
     | 
    
         
            +
                      part.multiline? ||
         
     | 
| 
      
 78 
     | 
    
         
            +
                        part.dstr_type? ||
         
     | 
| 
      
 79 
     | 
    
         
            +
                        (part.str_type? && part.heredoc?) ||
         
     | 
| 
      
 80 
     | 
    
         
            +
                        part.each_descendant(:block).any?
         
     | 
| 
      
 81 
     | 
    
         
            +
                    end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
       69 
83 
     | 
    
         
             
                    def replacement(parts)
         
     | 
| 
       70 
84 
     | 
    
         
             
                      interpolated_parts =
         
     | 
| 
       71 
85 
     | 
    
         
             
                        parts.map do |part|
         
     | 
| 
         @@ -32,7 +32,7 @@ module RuboCop 
     | 
|
| 
       32 
32 
     | 
    
         
             
                    NONZERO_MSG = 'Use `!empty?` instead of ' \
         
     | 
| 
       33 
33 
     | 
    
         
             
                                  '`%<lhs>s %<opr>s %<rhs>s`.'
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                     
     | 
| 
      
 35 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[size length].freeze
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
       37 
37 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       38 
38 
     | 
    
         
             
                      check_zero_length_predicate(node)
         
     | 
| 
         @@ -42,8 +42,6 @@ module RuboCop 
     | 
|
| 
       42 
42 
     | 
    
         
             
                    private
         
     | 
| 
       43 
43 
     | 
    
         | 
| 
       44 
44 
     | 
    
         
             
                    def check_zero_length_predicate(node)
         
     | 
| 
       45 
     | 
    
         
            -
                      return unless LENGTH_METHODS.include?(node.method_name)
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
45 
     | 
    
         
             
                      zero_length_predicate = zero_length_predicate(node.parent)
         
     | 
| 
       48 
46 
     | 
    
         
             
                      return unless zero_length_predicate
         
     | 
| 
       49 
47 
     | 
    
         | 
| 
         @@ -59,8 +57,6 @@ module RuboCop 
     | 
|
| 
       59 
57 
     | 
    
         
             
                    end
         
     | 
| 
       60 
58 
     | 
    
         | 
| 
       61 
59 
     | 
    
         
             
                    def check_nonzero_length_predicate(node)
         
     | 
| 
       62 
     | 
    
         
            -
                      return unless LENGTH_METHODS.include?(node.method_name)
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
60 
     | 
    
         
             
                      nonzero_length_predicate = nonzero_length_predicate(node.parent)
         
     | 
| 
       65 
61 
     | 
    
         
             
                      return unless nonzero_length_predicate
         
     | 
| 
       66 
62 
     | 
    
         | 
| 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            # Extensions to the core String class
         
     | 
| 
       4 
4 
     | 
    
         
             
            class String
         
     | 
| 
       5 
     | 
    
         
            -
              unless method_defined? 
     | 
| 
      
 5 
     | 
    
         
            +
              unless method_defined?(:blank?) && ' '.blank?
         
     | 
| 
       6 
6 
     | 
    
         
             
                # Checks whether a string is blank. A string is considered blank if it
         
     | 
| 
       7 
7 
     | 
    
         
             
                # is either empty or contains only whitespace characters.
         
     | 
| 
       8 
8 
     | 
    
         
             
                #
         
     | 
| 
         @@ -21,10 +21,10 @@ module RuboCop 
     | 
|
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                    str = content
         
     | 
| 
       23 
23 
     | 
    
         
             
                    Ext::RegexpNode.parsed_cache[str] ||= begin
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 24 
     | 
    
         
            +
                      Regexp::Parser.parse(str)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    rescue StandardError
         
     | 
| 
      
 26 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
       28 
28 
     | 
    
         
             
                  end
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
                  def each_capture(named: ANY)
         
     | 
    
        data/lib/rubocop/options.rb
    CHANGED
    
    | 
         @@ -69,6 +69,7 @@ module RuboCop 
     | 
|
| 
       69 
69 
     | 
    
         | 
| 
       70 
70 
     | 
    
         
             
                    add_severity_option(opts)
         
     | 
| 
       71 
71 
     | 
    
         
             
                    add_flags_with_optional_args(opts)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    add_cache_options(opts)
         
     | 
| 
       72 
73 
     | 
    
         
             
                    add_boolean_flags(opts)
         
     | 
| 
       73 
74 
     | 
    
         
             
                    add_aliases(opts)
         
     | 
| 
       74 
75 
     | 
    
         | 
| 
         @@ -164,10 +165,16 @@ module RuboCop 
     | 
|
| 
       164 
165 
     | 
    
         
             
                  end
         
     | 
| 
       165 
166 
     | 
    
         
             
                end
         
     | 
| 
       166 
167 
     | 
    
         | 
| 
      
 168 
     | 
    
         
            +
                def add_cache_options(opts)
         
     | 
| 
      
 169 
     | 
    
         
            +
                  option(opts, '-C', '--cache FLAG')
         
     | 
| 
      
 170 
     | 
    
         
            +
                  option(opts, '--cache-root DIR') do
         
     | 
| 
      
 171 
     | 
    
         
            +
                    @validator.validate_cache_enabled_for_cache_root
         
     | 
| 
      
 172 
     | 
    
         
            +
                  end
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
       167 
175 
     | 
    
         
             
                # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
         
     | 
| 
       168 
176 
     | 
    
         
             
                def add_boolean_flags(opts)
         
     | 
| 
       169 
177 
     | 
    
         
             
                  option(opts, '-F', '--fail-fast')
         
     | 
| 
       170 
     | 
    
         
            -
                  option(opts, '-C', '--cache FLAG')
         
     | 
| 
       171 
178 
     | 
    
         
             
                  option(opts, '-d', '--debug')
         
     | 
| 
       172 
179 
     | 
    
         
             
                  option(opts, '-D', '--[no-]display-cop-names')
         
     | 
| 
       173 
180 
     | 
    
         
             
                  option(opts, '-E', '--extra-details')
         
     | 
| 
         @@ -392,6 +399,13 @@ module RuboCop 
     | 
|
| 
       392 
399 
     | 
    
         
             
                  # of option order.
         
     | 
| 
       393 
400 
     | 
    
         
             
                  raise OptionParser::MissingArgument
         
     | 
| 
       394 
401 
     | 
    
         
             
                end
         
     | 
| 
      
 402 
     | 
    
         
            +
             
     | 
| 
      
 403 
     | 
    
         
            +
                def validate_cache_enabled_for_cache_root
         
     | 
| 
      
 404 
     | 
    
         
            +
                  return unless @options[:cache] == 'false'
         
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
      
 406 
     | 
    
         
            +
                  raise OptionArgumentError, '--cache-root can not be used with ' \
         
     | 
| 
      
 407 
     | 
    
         
            +
                                              '--cache false'
         
     | 
| 
      
 408 
     | 
    
         
            +
                end
         
     | 
| 
       395 
409 
     | 
    
         
             
              end
         
     | 
| 
       396 
410 
     | 
    
         | 
| 
       397 
411 
     | 
    
         
             
              # This module contains help texts for command line options.
         
     | 
| 
         @@ -464,6 +478,10 @@ module RuboCop 
     | 
|
| 
       464 
478 
     | 
    
         
             
                  cache:                            ["Use result caching (FLAG=true) or don't",
         
     | 
| 
       465 
479 
     | 
    
         
             
                                                     '(FLAG=false), default determined by',
         
     | 
| 
       466 
480 
     | 
    
         
             
                                                     'configuration parameter AllCops: UseCache.'],
         
     | 
| 
      
 481 
     | 
    
         
            +
                  cache_root:                       ['Set the cache root directory.',
         
     | 
| 
      
 482 
     | 
    
         
            +
                                                     'Takes precedence over the configuration',
         
     | 
| 
      
 483 
     | 
    
         
            +
                                                     'parameter AllCops: CacheRootDirectory and',
         
     | 
| 
      
 484 
     | 
    
         
            +
                                                     'the $RUBOCOP_CACHE_ROOT environment variable.'],
         
     | 
| 
       467 
485 
     | 
    
         
             
                  debug:                            'Display debug info.',
         
     | 
| 
       468 
486 
     | 
    
         
             
                  display_cop_names:                ['Display cop names in offense messages.',
         
     | 
| 
       469 
487 
     | 
    
         
             
                                                     'Default is true.'],
         
     | 
    
        data/lib/rubocop/result_cache.rb
    CHANGED
    
    | 
         @@ -3,6 +3,7 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require 'digest/sha1'
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'find'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'etc'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'zlib'
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
            module RuboCop
         
     | 
| 
       8 
9 
     | 
    
         
             
              # Provides functionality for caching rubocop runs.
         
     | 
| 
         @@ -30,6 +31,11 @@ module RuboCop 
     | 
|
| 
       30 
31 
     | 
    
         
             
                end
         
     | 
| 
       31 
32 
     | 
    
         | 
| 
       32 
33 
     | 
    
         
             
                class << self
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 35 
     | 
    
         
            +
                  attr_accessor :rubocop_required_features
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  ResultCache.rubocop_required_features = []
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
       33 
39 
     | 
    
         
             
                  private
         
     | 
| 
       34 
40 
     | 
    
         | 
| 
       35 
41 
     | 
    
         
             
                  def requires_file_removal?(file_count, config_store)
         
     | 
| 
         @@ -61,7 +67,8 @@ module RuboCop 
     | 
|
| 
       61 
67 
     | 
    
         
             
                end
         
     | 
| 
       62 
68 
     | 
    
         | 
| 
       63 
69 
     | 
    
         
             
                def self.cache_root(config_store)
         
     | 
| 
       64 
     | 
    
         
            -
                  root =  
     | 
| 
      
 70 
     | 
    
         
            +
                  root = ENV['RUBOCOP_CACHE_ROOT']
         
     | 
| 
      
 71 
     | 
    
         
            +
                  root ||= config_store.for_pwd.for_all_cops['CacheRootDirectory']
         
     | 
| 
       65 
72 
     | 
    
         
             
                  root ||= if ENV.key?('XDG_CACHE_HOME')
         
     | 
| 
       66 
73 
     | 
    
         
             
                             # Include user ID in the path to make sure the user has write
         
     | 
| 
       67 
74 
     | 
    
         
             
                             # access.
         
     | 
| 
         @@ -76,7 +83,10 @@ module RuboCop 
     | 
|
| 
       76 
83 
     | 
    
         
             
                  config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
         
     | 
| 
       77 
84 
     | 
    
         
             
                end
         
     | 
| 
       78 
85 
     | 
    
         | 
| 
      
 86 
     | 
    
         
            +
                attr :path
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
       79 
88 
     | 
    
         
             
                def initialize(file, team, options, config_store, cache_root = nil)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  cache_root ||= options[:cache_root]
         
     | 
| 
       80 
90 
     | 
    
         
             
                  cache_root ||= ResultCache.cache_root(config_store)
         
     | 
| 
       81 
91 
     | 
    
         
             
                  @allow_symlinks_in_cache_location =
         
     | 
| 
       82 
92 
     | 
    
         
             
                    ResultCache.allow_symlinks_in_cache_location?(config_store)
         
     | 
| 
         @@ -159,27 +169,34 @@ module RuboCop 
     | 
|
| 
       159 
169 
     | 
    
         
             
                end
         
     | 
| 
       160 
170 
     | 
    
         | 
| 
       161 
171 
     | 
    
         
             
                # The checksum of the rubocop program running the inspection.
         
     | 
| 
       162 
     | 
    
         
            -
                # rubocop:disable Metrics/AbcSize
         
     | 
| 
       163 
172 
     | 
    
         
             
                def rubocop_checksum
         
     | 
| 
       164 
173 
     | 
    
         
             
                  ResultCache.source_checksum ||=
         
     | 
| 
       165 
174 
     | 
    
         
             
                    begin
         
     | 
| 
       166 
     | 
    
         
            -
                      lib_root = File.join(File.dirname(__FILE__), '..')
         
     | 
| 
       167 
     | 
    
         
            -
                      exe_root = File.join(lib_root, '..', 'exe')
         
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
       169 
     | 
    
         
            -
                      # These are all the files we have `require`d plus everything in the
         
     | 
| 
       170 
     | 
    
         
            -
                      # exe directory. A change to any of them could affect the cop output
         
     | 
| 
       171 
     | 
    
         
            -
                      # so we include them in the cache hash.
         
     | 
| 
       172 
     | 
    
         
            -
                      source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
         
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
175 
     | 
    
         
             
                      digest = Digest::SHA1.new
         
     | 
| 
       175 
     | 
    
         
            -
                       
     | 
| 
      
 176 
     | 
    
         
            +
                      rubocop_extra_features
         
     | 
| 
       176 
177 
     | 
    
         
             
                        .select { |path| File.file?(path) }
         
     | 
| 
       177 
178 
     | 
    
         
             
                        .sort!
         
     | 
| 
       178 
     | 
    
         
            -
                        .each  
     | 
| 
      
 179 
     | 
    
         
            +
                        .each do |path|
         
     | 
| 
      
 180 
     | 
    
         
            +
                          content = File.open(path, 'rb', &:read)
         
     | 
| 
      
 181 
     | 
    
         
            +
                          digest << Zlib.crc32(content).to_s # mtime not reliable
         
     | 
| 
      
 182 
     | 
    
         
            +
                        end
         
     | 
| 
      
 183 
     | 
    
         
            +
                      digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING
         
     | 
| 
       179 
184 
     | 
    
         
             
                      digest.hexdigest
         
     | 
| 
       180 
185 
     | 
    
         
             
                    end
         
     | 
| 
       181 
186 
     | 
    
         
             
                end
         
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                def rubocop_extra_features
         
     | 
| 
      
 189 
     | 
    
         
            +
                  lib_root = File.join(File.dirname(__FILE__), '..')
         
     | 
| 
      
 190 
     | 
    
         
            +
                  exe_root = File.join(lib_root, '..', 'exe')
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                  # These are all the files we have `require`d plus everything in the
         
     | 
| 
      
 193 
     | 
    
         
            +
                  # exe directory. A change to any of them could affect the cop output
         
     | 
| 
      
 194 
     | 
    
         
            +
                  # so we include them in the cache hash.
         
     | 
| 
      
 195 
     | 
    
         
            +
                  source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
         
     | 
| 
      
 196 
     | 
    
         
            +
                  source_files -= ResultCache.rubocop_required_features # Rely on gem versions
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                  source_files
         
     | 
| 
      
 199 
     | 
    
         
            +
                end
         
     | 
| 
       183 
200 
     | 
    
         | 
| 
       184 
201 
     | 
    
         
             
                # Return a hash of the options given at invocation, minus the ones that have
         
     | 
| 
       185 
202 
     | 
    
         
             
                # no effect on which offenses and disabled line ranges are found, and thus
         
     | 
    
        data/lib/rubocop/runner.rb
    CHANGED
    
    | 
         @@ -11,9 +11,12 @@ module RuboCop 
     | 
|
| 
       11 
11 
     | 
    
         
             
                class InfiniteCorrectionLoop < RuntimeError
         
     | 
| 
       12 
12 
     | 
    
         
             
                  attr_reader :offenses
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                  def initialize(path,  
     | 
| 
       15 
     | 
    
         
            -
                     
     | 
| 
       16 
     | 
    
         
            -
                     
     | 
| 
      
 14 
     | 
    
         
            +
                  def initialize(path, offenses_by_iteration, loop_start: -1)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @offenses = offenses_by_iteration.flatten.uniq
         
     | 
| 
      
 16 
     | 
    
         
            +
                    root_cause = offenses_by_iteration[loop_start..-1]
         
     | 
| 
      
 17 
     | 
    
         
            +
                                 .map { |x| x.map(&:cop_name).uniq.join(', ') }
         
     | 
| 
      
 18 
     | 
    
         
            +
                                 .join(' -> ')
         
     | 
| 
      
 19 
     | 
    
         
            +
                    super "Infinite loop detected in #{path} and caused by #{root_cause}"
         
     | 
| 
       17 
20 
     | 
    
         
             
                  end
         
     | 
| 
       18 
21 
     | 
    
         
             
                end
         
     | 
| 
       19 
22 
     | 
    
         | 
| 
         @@ -81,7 +84,10 @@ module RuboCop 
     | 
|
| 
       81 
84 
     | 
    
         
             
                  # OPTIMIZE: Calling `ResultCache.cleanup` takes time. This optimization
         
     | 
| 
       82 
85 
     | 
    
         
             
                  # mainly targets editors that integrates RuboCop. When RuboCop is run
         
     | 
| 
       83 
86 
     | 
    
         
             
                  # by an editor, it should be inspecting only one file.
         
     | 
| 
       84 
     | 
    
         
            -
                   
     | 
| 
      
 87 
     | 
    
         
            +
                  if files.size > 1 && cached_run?
         
     | 
| 
      
 88 
     | 
    
         
            +
                    ResultCache.cleanup(@config_store, @options[:debug], @options[:cache_root])
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
       85 
91 
     | 
    
         
             
                  formatter_set.finished(inspected_files.freeze)
         
     | 
| 
       86 
92 
     | 
    
         
             
                  formatter_set.close_output_files
         
     | 
| 
       87 
93 
     | 
    
         
             
                end
         
     | 
| 
         @@ -233,18 +239,21 @@ module RuboCop 
     | 
|
| 
       233 
239 
     | 
    
         | 
| 
       234 
240 
     | 
    
         
             
                def do_inspection_loop(file)
         
     | 
| 
       235 
241 
     | 
    
         
             
                  processed_source = get_processed_source(file)
         
     | 
| 
       236 
     | 
    
         
            -
                  offenses  
     | 
| 
      
 242 
     | 
    
         
            +
                  # This variable is 2d array used to track corrected offenses after each
         
     | 
| 
      
 243 
     | 
    
         
            +
                  # inspection iteration. This is used to output meaningful infinite loop
         
     | 
| 
      
 244 
     | 
    
         
            +
                  # error message.
         
     | 
| 
      
 245 
     | 
    
         
            +
                  offenses_by_iteration = []
         
     | 
| 
       237 
246 
     | 
    
         | 
| 
       238 
247 
     | 
    
         
             
                  # When running with --auto-correct, we need to inspect the file (which
         
     | 
| 
       239 
248 
     | 
    
         
             
                  # includes writing a corrected version of it) until no more corrections
         
     | 
| 
       240 
249 
     | 
    
         
             
                  # are made. This is because automatic corrections can introduce new
         
     | 
| 
       241 
250 
     | 
    
         
             
                  # offenses. In the normal case the loop is only executed once.
         
     | 
| 
       242 
     | 
    
         
            -
                  iterate_until_no_changes(processed_source,  
     | 
| 
      
 251 
     | 
    
         
            +
                  iterate_until_no_changes(processed_source, offenses_by_iteration) do
         
     | 
| 
       243 
252 
     | 
    
         
             
                    # The offenses that couldn't be corrected will be found again so we
         
     | 
| 
       244 
253 
     | 
    
         
             
                    # only keep the corrected ones in order to avoid duplicate reporting.
         
     | 
| 
       245 
     | 
    
         
            -
                     
     | 
| 
      
 254 
     | 
    
         
            +
                    !offenses_by_iteration.empty? && offenses_by_iteration.last.select!(&:corrected?)
         
     | 
| 
       246 
255 
     | 
    
         
             
                    new_offenses, updated_source_file = inspect_file(processed_source)
         
     | 
| 
       247 
     | 
    
         
            -
                     
     | 
| 
      
 256 
     | 
    
         
            +
                    offenses_by_iteration.push(new_offenses)
         
     | 
| 
       248 
257 
     | 
    
         | 
| 
       249 
258 
     | 
    
         
             
                    # We have to reprocess the source to pickup the changes. Since the
         
     | 
| 
       250 
259 
     | 
    
         
             
                    # change could (theoretically) introduce parsing errors, we break the
         
     | 
| 
         @@ -254,10 +263,12 @@ module RuboCop 
     | 
|
| 
       254 
263 
     | 
    
         
             
                    processed_source = get_processed_source(file)
         
     | 
| 
       255 
264 
     | 
    
         
             
                  end
         
     | 
| 
       256 
265 
     | 
    
         | 
| 
      
 266 
     | 
    
         
            +
                  # Return summary of corrected offenses after all iterations
         
     | 
| 
      
 267 
     | 
    
         
            +
                  offenses = offenses_by_iteration.flatten.uniq
         
     | 
| 
       257 
268 
     | 
    
         
             
                  [processed_source, offenses]
         
     | 
| 
       258 
269 
     | 
    
         
             
                end
         
     | 
| 
       259 
270 
     | 
    
         | 
| 
       260 
     | 
    
         
            -
                def iterate_until_no_changes(source,  
     | 
| 
      
 271 
     | 
    
         
            +
                def iterate_until_no_changes(source, offenses_by_iteration)
         
     | 
| 
       261 
272 
     | 
    
         
             
                  # Keep track of the state of the source. If a cop modifies the source
         
     | 
| 
       262 
273 
     | 
    
         
             
                  # and another cop undoes it producing identical source we have an
         
     | 
| 
       263 
274 
     | 
    
         
             
                  # infinite loop.
         
     | 
| 
         @@ -269,10 +280,10 @@ module RuboCop 
     | 
|
| 
       269 
280 
     | 
    
         
             
                  iterations = 0
         
     | 
| 
       270 
281 
     | 
    
         | 
| 
       271 
282 
     | 
    
         
             
                  loop do
         
     | 
| 
       272 
     | 
    
         
            -
                    check_for_infinite_loop(source,  
     | 
| 
      
 283 
     | 
    
         
            +
                    check_for_infinite_loop(source, offenses_by_iteration)
         
     | 
| 
       273 
284 
     | 
    
         | 
| 
       274 
285 
     | 
    
         
             
                    if (iterations += 1) > MAX_ITERATIONS
         
     | 
| 
       275 
     | 
    
         
            -
                      raise InfiniteCorrectionLoop.new(source.path,  
     | 
| 
      
 286 
     | 
    
         
            +
                      raise InfiniteCorrectionLoop.new(source.path, offenses_by_iteration)
         
     | 
| 
       276 
287 
     | 
    
         
             
                    end
         
     | 
| 
       277 
288 
     | 
    
         | 
| 
       278 
289 
     | 
    
         
             
                    source = yield
         
     | 
| 
         @@ -282,11 +293,15 @@ module RuboCop 
     | 
|
| 
       282 
293 
     | 
    
         | 
| 
       283 
294 
     | 
    
         
             
                # Check whether a run created source identical to a previous run, which
         
     | 
| 
       284 
295 
     | 
    
         
             
                # means that we definitely have an infinite loop.
         
     | 
| 
       285 
     | 
    
         
            -
                def check_for_infinite_loop(processed_source,  
     | 
| 
      
 296 
     | 
    
         
            +
                def check_for_infinite_loop(processed_source, offenses_by_iteration)
         
     | 
| 
       286 
297 
     | 
    
         
             
                  checksum = processed_source.checksum
         
     | 
| 
       287 
298 
     | 
    
         | 
| 
       288 
     | 
    
         
            -
                  if @processed_sources. 
     | 
| 
       289 
     | 
    
         
            -
                    raise InfiniteCorrectionLoop.new( 
     | 
| 
      
 299 
     | 
    
         
            +
                  if (loop_start_index = @processed_sources.index(checksum))
         
     | 
| 
      
 300 
     | 
    
         
            +
                    raise InfiniteCorrectionLoop.new(
         
     | 
| 
      
 301 
     | 
    
         
            +
                      processed_source.path,
         
     | 
| 
      
 302 
     | 
    
         
            +
                      offenses_by_iteration,
         
     | 
| 
      
 303 
     | 
    
         
            +
                      loop_start: loop_start_index
         
     | 
| 
      
 304 
     | 
    
         
            +
                    )
         
     | 
| 
       290 
305 
     | 
    
         
             
                  end
         
     | 
| 
       291 
306 
     | 
    
         | 
| 
       292 
307 
     | 
    
         
             
                  @processed_sources << checksum
         
     | 
    
        data/lib/rubocop/version.rb
    CHANGED