rubocop 1.7.0 → 1.10.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/LICENSE.txt +1 -1
- data/README.md +4 -3
- data/config/default.yml +137 -31
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop.rb +14 -1
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +5 -4
- data/lib/rubocop/comment_config.rb +6 -6
- data/lib/rubocop/config.rb +5 -2
- data/lib/rubocop/config_loader.rb +7 -14
- data/lib/rubocop/config_store.rb +12 -1
- data/lib/rubocop/cop/base.rb +2 -1
- data/lib/rubocop/cop/exclude_limit.rb +26 -0
- data/lib/rubocop/cop/gemspec/date_assignment.rb +56 -0
- data/lib/rubocop/cop/generator.rb +1 -3
- data/lib/rubocop/cop/internal_affairs.rb +5 -1
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +68 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +89 -0
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +61 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +64 -0
- data/lib/rubocop/cop/layout/class_structure.rb +7 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +38 -18
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +16 -2
- data/lib/rubocop/cop/layout/line_length.rb +2 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +26 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/space_before_brackets.rb +19 -16
- data/lib/rubocop/cop/lint/debugger.rb +58 -14
- data/lib/rubocop/cop/lint/deprecated_constants.rb +80 -0
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +13 -4
- data/lib/rubocop/cop/lint/duplicate_require.rb +2 -2
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +44 -0
- data/lib/rubocop/cop/lint/multiple_comparison.rb +4 -4
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +10 -6
- data/lib/rubocop/cop/lint/number_conversion.rb +41 -6
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +47 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +39 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +2 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +50 -0
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +5 -3
- data/lib/rubocop/cop/lint/symbol_conversion.rb +103 -0
- data/lib/rubocop/cop/lint/triple_quotes.rb +71 -0
- data/lib/rubocop/cop/message_annotator.rb +4 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
- data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +18 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -0
- data/lib/rubocop/cop/mixin/code_length.rb +3 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -11
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +3 -1
- data/lib/rubocop/cop/mixin/preferred_delimiters.rb +2 -2
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +5 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +38 -5
- data/lib/rubocop/cop/naming/variable_name.rb +2 -0
- data/lib/rubocop/cop/naming/variable_number.rb +2 -9
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/severity.rb +3 -3
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
- data/lib/rubocop/cop/style/constant_visibility.rb +27 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -9
- data/lib/rubocop/cop/style/double_negation.rb +2 -2
- data/lib/rubocop/cop/style/empty_literal.rb +6 -2
- data/lib/rubocop/cop/style/endless_method.rb +102 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +138 -49
- data/lib/rubocop/cop/style/explicit_block_argument.rb +11 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +6 -7
- data/lib/rubocop/cop/style/float_division.rb +3 -0
- data/lib/rubocop/cop/style/format_string_token.rb +18 -2
- data/lib/rubocop/cop/style/hash_conversion.rb +81 -0
- data/lib/rubocop/cop/style/hash_like_case.rb +2 -1
- data/lib/rubocop/cop/style/if_inside_else.rb +22 -10
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +120 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +4 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +3 -0
- data/lib/rubocop/cop/style/non_nil_check.rb +23 -13
- data/lib/rubocop/cop/style/numeric_literals.rb +6 -9
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +3 -2
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +32 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +29 -5
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +2 -4
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +2 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +30 -1
- data/lib/rubocop/options.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +5 -2
- data/lib/rubocop/runner.rb +1 -0
- data/lib/rubocop/target_ruby.rb +47 -11
- data/lib/rubocop/version.rb +2 -2
- metadata +24 -7
| @@ -28,10 +28,6 @@ module RuboCop | |
| 28 28 | 
             
                  #   10_000_00 # typical representation of $10,000 in cents
         | 
| 29 29 | 
             
                  #
         | 
| 30 30 | 
             
                  class NumericLiterals < Base
         | 
| 31 | 
            -
                    # The parameter is called MinDigits (meaning the minimum number of
         | 
| 32 | 
            -
                    # digits for which an offense can be registered), but essentially it's
         | 
| 33 | 
            -
                    # a Max parameter (the maximum number of something that's allowed).
         | 
| 34 | 
            -
                    include ConfigurableMax
         | 
| 35 31 | 
             
                    include IntegerNode
         | 
| 36 32 | 
             
                    extend AutoCorrector
         | 
| 37 33 |  | 
| @@ -39,6 +35,11 @@ module RuboCop | |
| 39 35 | 
             
                          'separate every 3 digits with them.'
         | 
| 40 36 | 
             
                    DELIMITER_REGEXP = /[eE.]/.freeze
         | 
| 41 37 |  | 
| 38 | 
            +
                    # The parameter is called MinDigits (meaning the minimum number of
         | 
| 39 | 
            +
                    # digits for which an offense can be registered), but essentially it's
         | 
| 40 | 
            +
                    # a Max parameter (the maximum number of something that's allowed).
         | 
| 41 | 
            +
                    exclude_limit 'MinDigits'
         | 
| 42 | 
            +
             | 
| 42 43 | 
             
                    def on_int(node)
         | 
| 43 44 | 
             
                      check(node)
         | 
| 44 45 | 
             
                    end
         | 
| @@ -49,10 +50,6 @@ module RuboCop | |
| 49 50 |  | 
| 50 51 | 
             
                    private
         | 
| 51 52 |  | 
| 52 | 
            -
                    def max_parameter_name
         | 
| 53 | 
            -
                      'MinDigits'
         | 
| 54 | 
            -
                    end
         | 
| 55 | 
            -
             | 
| 56 53 | 
             
                    def check(node)
         | 
| 57 54 | 
             
                      int = integer_part(node)
         | 
| 58 55 |  | 
| @@ -62,7 +59,7 @@ module RuboCop | |
| 62 59 |  | 
| 63 60 | 
             
                      case int
         | 
| 64 61 | 
             
                      when /^\d+$/
         | 
| 65 | 
            -
                        return unless (self. | 
| 62 | 
            +
                        return unless (self.min_digits = int.size + 1)
         | 
| 66 63 |  | 
| 67 64 | 
             
                        register_offense(node)
         | 
| 68 65 | 
             
                      when /\d{4}/, short_group_regex
         | 
| @@ -8,7 +8,7 @@ module RuboCop | |
| 8 8 | 
             
                  # These can be replaced by their respective predicate methods.
         | 
| 9 9 | 
             
                  # The cop can also be configured to do the reverse.
         | 
| 10 10 | 
             
                  #
         | 
| 11 | 
            -
                  # The cop disregards `#nonzero?` as  | 
| 11 | 
            +
                  # The cop disregards `#nonzero?` as its value is truthy or falsey,
         | 
| 12 12 | 
             
                  # but not `true` and `false`, and thus not always interchangeable with
         | 
| 13 13 | 
             
                  # `!= 0`.
         | 
| 14 14 | 
             
                  #
         | 
| @@ -81,11 +81,12 @@ module RuboCop | |
| 81 81 | 
             
                      return node.source if message_nodes.size > 1
         | 
| 82 82 |  | 
| 83 83 | 
             
                      argument = message_nodes.first.source
         | 
| 84 | 
            +
                      exception_class = exception_node.const_name || exception_node.receiver.source
         | 
| 84 85 |  | 
| 85 86 | 
             
                      if node.parent && requires_parens?(node.parent)
         | 
| 86 | 
            -
                        "#{node.method_name}(#{ | 
| 87 | 
            +
                        "#{node.method_name}(#{exception_class}.new(#{argument}))"
         | 
| 87 88 | 
             
                      else
         | 
| 88 | 
            -
                        "#{node.method_name} #{ | 
| 89 | 
            +
                        "#{node.method_name} #{exception_class}.new(#{argument})"
         | 
| 89 90 | 
             
                      end
         | 
| 90 91 | 
             
                    end
         | 
| 91 92 |  | 
| @@ -66,7 +66,7 @@ module RuboCop | |
| 66 66 | 
             
                    end
         | 
| 67 67 |  | 
| 68 68 | 
             
                    def correct_with_arguments(return_node, corrector)
         | 
| 69 | 
            -
                      if return_node. | 
| 69 | 
            +
                      if return_node.children.size > 1
         | 
| 70 70 | 
             
                        add_brackets(corrector, return_node)
         | 
| 71 71 | 
             
                      elsif hash_without_braces?(return_node.first_argument)
         | 
| 72 72 | 
             
                        add_braces(corrector, return_node.first_argument)
         | 
| @@ -8,6 +8,10 @@ module RuboCop | |
| 8 8 | 
             
                  #
         | 
| 9 9 | 
             
                  # Endless methods added in Ruby 3.0 are also accepted by this cop.
         | 
| 10 10 | 
             
                  #
         | 
| 11 | 
            +
                  # If `Style/EndlessMethod` is enabled with `EnforcedStyle: allow_single_line` or
         | 
| 12 | 
            +
                  # `allow_always`, single-line methods will be auto-corrected to endless
         | 
| 13 | 
            +
                  # methods if there is only one statement in the body.
         | 
| 14 | 
            +
                  #
         | 
| 11 15 | 
             
                  # @example
         | 
| 12 16 | 
             
                  #   # bad
         | 
| 13 17 | 
             
                  #   def some_method; body end
         | 
| @@ -47,6 +51,30 @@ module RuboCop | |
| 47 51 | 
             
                    private
         | 
| 48 52 |  | 
| 49 53 | 
             
                    def autocorrect(corrector, node)
         | 
| 54 | 
            +
                      if correct_to_endless?(node.body)
         | 
| 55 | 
            +
                        correct_to_endless(corrector, node)
         | 
| 56 | 
            +
                      else
         | 
| 57 | 
            +
                        correct_to_multiline(corrector, node)
         | 
| 58 | 
            +
                      end
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    def allow_empty?
         | 
| 62 | 
            +
                      cop_config['AllowIfMethodIsEmpty']
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    def correct_to_endless?(body_node)
         | 
| 66 | 
            +
                      return false if target_ruby_version < 3.0
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                      endless_method_config = config.for_cop('Style/EndlessMethod')
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                      return false unless endless_method_config['Enabled']
         | 
| 71 | 
            +
                      return false if endless_method_config['EnforcedStyle'] == 'disallow'
         | 
| 72 | 
            +
                      return false unless body_node
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                      !(body_node.begin_type? || body_node.kwbegin_type?)
         | 
| 75 | 
            +
                    end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    def correct_to_multiline(corrector, node)
         | 
| 50 78 | 
             
                      each_part(node.body) do |part|
         | 
| 51 79 | 
             
                        LineBreakCorrector.break_line_before(
         | 
| 52 80 | 
             
                          range: part, node: node, corrector: corrector,
         | 
| @@ -62,8 +90,10 @@ module RuboCop | |
| 62 90 | 
             
                      move_comment(node, corrector)
         | 
| 63 91 | 
             
                    end
         | 
| 64 92 |  | 
| 65 | 
            -
                    def  | 
| 66 | 
            -
                       | 
| 93 | 
            +
                    def correct_to_endless(corrector, node)
         | 
| 94 | 
            +
                      arguments = node.arguments.any? ? node.arguments.source : '()'
         | 
| 95 | 
            +
                      replacement = "def #{node.method_name}#{arguments} = #{node.body.source}"
         | 
| 96 | 
            +
                      corrector.replace(node, replacement)
         | 
| 67 97 | 
             
                    end
         | 
| 68 98 |  | 
| 69 99 | 
             
                    def each_part(body)
         | 
| @@ -63,13 +63,13 @@ module RuboCop | |
| 63 63 | 
             
                    end
         | 
| 64 64 |  | 
| 65 65 | 
             
                    def autocorrect(corrector, node, if_branch)
         | 
| 66 | 
            +
                      corrector.wrap(node.condition, '(', ')') if node.condition.or_type?
         | 
| 67 | 
            +
             | 
| 66 68 | 
             
                      if node.unless?
         | 
| 67 69 | 
             
                        corrector.replace(node.loc.keyword, 'if')
         | 
| 68 70 | 
             
                        corrector.insert_before(node.condition, '!')
         | 
| 69 71 | 
             
                      end
         | 
| 70 72 |  | 
| 71 | 
            -
                      corrector.wrap(node.condition, '(', ')') if node.condition.or_type?
         | 
| 72 | 
            -
             | 
| 73 73 | 
             
                      and_operator = if_branch.unless? ? ' && !' : ' && '
         | 
| 74 74 | 
             
                      if if_branch.modifier_form?
         | 
| 75 75 | 
             
                        correct_for_guard_condition_style(corrector, node, if_branch, and_operator)
         | 
| @@ -80,8 +80,11 @@ module RuboCop | |
| 80 80 | 
             
                    end
         | 
| 81 81 |  | 
| 82 82 | 
             
                    def correct_for_guard_condition_style(corrector, node, if_branch, and_operator)
         | 
| 83 | 
            +
                      outer_condition = node.condition
         | 
| 84 | 
            +
                      correct_outer_condition(corrector, outer_condition)
         | 
| 85 | 
            +
             | 
| 83 86 | 
             
                      condition = if_branch.condition
         | 
| 84 | 
            -
                      corrector.insert_after( | 
| 87 | 
            +
                      corrector.insert_after(outer_condition, replacement_condition(and_operator, condition))
         | 
| 85 88 |  | 
| 86 89 | 
             
                      range = range_between(if_branch.loc.keyword.begin_pos, condition.source_range.end_pos)
         | 
| 87 90 | 
             
                      corrector.remove(range_with_surrounding_space(range: range, newlines: false))
         | 
| @@ -100,14 +103,35 @@ module RuboCop | |
| 100 103 | 
             
                    def correct_for_comment(corrector, node, if_branch)
         | 
| 101 104 | 
             
                      return if config.for_cop('Style/IfUnlessModifier')['Enabled']
         | 
| 102 105 |  | 
| 103 | 
            -
                      comments = processed_source. | 
| 106 | 
            +
                      comments = processed_source.ast_with_comments[if_branch]
         | 
| 104 107 | 
             
                      comment_text = comments.map(&:text).join("\n") << "\n"
         | 
| 105 108 |  | 
| 106 109 | 
             
                      corrector.insert_before(node.loc.keyword, comment_text) unless comments.empty?
         | 
| 107 110 | 
             
                    end
         | 
| 108 111 |  | 
| 112 | 
            +
                    def correct_outer_condition(corrector, condition)
         | 
| 113 | 
            +
                      return unless requrie_parentheses?(condition)
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                      end_pos = condition.loc.selector.end_pos
         | 
| 116 | 
            +
                      begin_pos = condition.first_argument.source_range.begin_pos
         | 
| 117 | 
            +
                      return if end_pos > begin_pos
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                      corrector.replace(range_between(end_pos, begin_pos), '(')
         | 
| 120 | 
            +
                      corrector.insert_after(condition.last_argument.source_range, ')')
         | 
| 121 | 
            +
                    end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                    def requrie_parentheses?(condition)
         | 
| 124 | 
            +
                      condition.send_type? && !condition.arguments.empty? && !condition.parenthesized?
         | 
| 125 | 
            +
                    end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                    def arguments_range(node)
         | 
| 128 | 
            +
                      range_between(
         | 
| 129 | 
            +
                        node.first_argument.source_range.begin_pos, node.last_argument.source_range.end_pos
         | 
| 130 | 
            +
                      )
         | 
| 131 | 
            +
                    end
         | 
| 132 | 
            +
             | 
| 109 133 | 
             
                    def wrap_condition?(node)
         | 
| 110 | 
            -
                      node.or_type? ||
         | 
| 134 | 
            +
                      node.and_type? || node.or_type? ||
         | 
| 111 135 | 
             
                        (node.send_type? && node.arguments.any? && !node.parenthesized?)
         | 
| 112 136 | 
             
                    end
         | 
| 113 137 |  | 
| @@ -81,13 +81,13 @@ module RuboCop | |
| 81 81 | 
             
                    }
         | 
| 82 82 |  | 
| 83 83 | 
             
                    PERL_VARS =
         | 
| 84 | 
            -
                       | 
| 84 | 
            +
                      ENGLISH_VARS.flat_map { |k, vs| vs.map { |v| [v, [k]] } }.to_h
         | 
| 85 85 |  | 
| 86 86 | 
             
                    ENGLISH_VARS.merge!(
         | 
| 87 | 
            -
                       | 
| 87 | 
            +
                      ENGLISH_VARS.flat_map { |_, vs| vs.map { |v| [v, [v]] } }.to_h
         | 
| 88 88 | 
             
                    )
         | 
| 89 89 | 
             
                    PERL_VARS.merge!(
         | 
| 90 | 
            -
                       | 
| 90 | 
            +
                      PERL_VARS.flat_map { |_, vs| vs.map { |v| [v, [v]] } }.to_h
         | 
| 91 91 | 
             
                    )
         | 
| 92 92 | 
             
                    ENGLISH_VARS.each_value(&:freeze).freeze
         | 
| 93 93 | 
             
                    PERL_VARS.each_value(&:freeze).freeze
         | 
| @@ -41,12 +41,10 @@ module RuboCop | |
| 41 41 | 
             
                          'having a single-line body.'
         | 
| 42 42 |  | 
| 43 43 | 
             
                    def on_while(node)
         | 
| 44 | 
            -
                      return unless  | 
| 44 | 
            +
                      return unless single_line_as_modifier?(node)
         | 
| 45 45 |  | 
| 46 46 | 
             
                      add_offense(node.loc.keyword, message: format(MSG, keyword: node.keyword)) do |corrector|
         | 
| 47 | 
            -
                         | 
| 48 | 
            -
             | 
| 49 | 
            -
                        corrector.replace(node, oneline)
         | 
| 47 | 
            +
                        corrector.replace(node, to_modifier_form(node))
         | 
| 50 48 | 
             
                      end
         | 
| 51 49 | 
             
                    end
         | 
| 52 50 | 
             
                    alias on_until on_while
         | 
| @@ -23,6 +23,7 @@ module RuboCop | |
| 23 23 |  | 
| 24 24 | 
             
                  def minimum_severity_to_fail
         | 
| 25 25 | 
             
                    @minimum_severity_to_fail ||= begin
         | 
| 26 | 
            +
                      # Unless given explicitly as `fail_level`, `:info` severity offenses do not fail
         | 
| 26 27 | 
             
                      name = options.fetch(:fail_level, :refactor)
         | 
| 27 28 | 
             
                      RuboCop::Cop::Severity.new(name)
         | 
| 28 29 | 
             
                    end
         | 
| @@ -13,6 +13,7 @@ module RuboCop | |
| 13 13 | 
             
                  include PathUtil
         | 
| 14 14 |  | 
| 15 15 | 
             
                  COLOR_FOR_SEVERITY = {
         | 
| 16 | 
            +
                    info:       :gray,
         | 
| 16 17 | 
             
                    refactor:   :yellow,
         | 
| 17 18 | 
             
                    convention: :yellow,
         | 
| 18 19 | 
             
                    warning:    :magenta,
         | 
| @@ -76,7 +77,7 @@ module RuboCop | |
| 76 77 | 
             
                  end
         | 
| 77 78 |  | 
| 78 79 | 
             
                  def colored_severity_code(offense)
         | 
| 79 | 
            -
                    color = COLOR_FOR_SEVERITY | 
| 80 | 
            +
                    color = COLOR_FOR_SEVERITY.fetch(offense.severity.name)
         | 
| 80 81 | 
             
                    colorize(offense.severity.code, color)
         | 
| 81 82 | 
             
                  end
         | 
| 82 83 |  | 
| @@ -27,7 +27,7 @@ module RuboCop | |
| 27 27 | 
             
                end
         | 
| 28 28 |  | 
| 29 29 | 
             
                def any?
         | 
| 30 | 
            -
                  frozen_string_literal_specified? || encoding_specified?
         | 
| 30 | 
            +
                  frozen_string_literal_specified? || encoding_specified? || shareable_constant_value_specified?
         | 
| 31 31 | 
             
                end
         | 
| 32 32 |  | 
| 33 33 | 
             
                # Does the magic comment enable the frozen string literal feature.
         | 
| @@ -46,6 +46,10 @@ module RuboCop | |
| 46 46 | 
             
                  [true, false].include?(frozen_string_literal)
         | 
| 47 47 | 
             
                end
         | 
| 48 48 |  | 
| 49 | 
            +
                def valid_shareable_constant_value?
         | 
| 50 | 
            +
                  %w[none literal experimental_everything experimental_copy].include?(shareable_constant_values)
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 49 53 | 
             
                # Was a magic comment for the frozen string literal found?
         | 
| 50 54 | 
             
                #
         | 
| 51 55 | 
             
                # @return [Boolean]
         | 
| @@ -53,6 +57,13 @@ module RuboCop | |
| 53 57 | 
             
                  specified?(frozen_string_literal)
         | 
| 54 58 | 
             
                end
         | 
| 55 59 |  | 
| 60 | 
            +
                # Was a shareable_constant_value specified?
         | 
| 61 | 
            +
                #
         | 
| 62 | 
            +
                # @return [Boolean]
         | 
| 63 | 
            +
                def shareable_constant_value_specified?
         | 
| 64 | 
            +
                  specified?(shareable_constant_value)
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 56 67 | 
             
                # Expose the `frozen_string_literal` value coerced to a boolean if possible.
         | 
| 57 68 | 
             
                #
         | 
| 58 69 | 
             
                # @return [Boolean] if value is `true` or `false`
         | 
| @@ -69,6 +80,13 @@ module RuboCop | |
| 69 80 | 
             
                  end
         | 
| 70 81 | 
             
                end
         | 
| 71 82 |  | 
| 83 | 
            +
                # Expose the `shareable_constant_value` value coerced to a boolean if possible.
         | 
| 84 | 
            +
                #
         | 
| 85 | 
            +
                # @return [String] for shareable_constant_value config
         | 
| 86 | 
            +
                def shareable_constant_value
         | 
| 87 | 
            +
                  extract_shareable_constant_value
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 72 90 | 
             
                def encoding_specified?
         | 
| 73 91 | 
             
                  specified?(encoding)
         | 
| 74 92 | 
             
                end
         | 
| @@ -146,6 +164,10 @@ module RuboCop | |
| 146 164 | 
             
                  def extract_frozen_string_literal
         | 
| 147 165 | 
             
                    match('frozen[_-]string[_-]literal')
         | 
| 148 166 | 
             
                  end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                  def extract_shareable_constant_value
         | 
| 169 | 
            +
                    match('shareable[_-]constant[_-]values')
         | 
| 170 | 
            +
                  end
         | 
| 149 171 | 
             
                end
         | 
| 150 172 |  | 
| 151 173 | 
             
                # Wrapper for Vim style magic comments.
         | 
| @@ -176,6 +198,9 @@ module RuboCop | |
| 176 198 |  | 
| 177 199 | 
             
                  # Vim comments cannot specify frozen string literal behavior.
         | 
| 178 200 | 
             
                  def frozen_string_literal; end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                  # Vim comments cannot specify shareable constant values behavior.
         | 
| 203 | 
            +
                  def shareable_constant_value; end
         | 
| 179 204 | 
             
                end
         | 
| 180 205 |  | 
| 181 206 | 
             
                # Wrapper for regular magic comments not bound to an editor.
         | 
| @@ -209,6 +234,10 @@ module RuboCop | |
| 209 234 | 
             
                  def extract_frozen_string_literal
         | 
| 210 235 | 
             
                    extract(/\A\s*#\s*frozen[_-]string[_-]literal:\s*(#{TOKEN})\s*\z/io)
         | 
| 211 236 | 
             
                  end
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                  def extract_shareable_constant_value
         | 
| 239 | 
            +
                    extract(/\A\s*#\s*shareable[_-]constant[_-]value:\s*(#{TOKEN})\s*\z/io)
         | 
| 240 | 
            +
                  end
         | 
| 212 241 | 
             
                end
         | 
| 213 242 | 
             
              end
         | 
| 214 243 | 
             
            end
         | 
    
        data/lib/rubocop/options.rb
    CHANGED
    
    | @@ -470,7 +470,7 @@ module RuboCop | |
| 470 470 | 
             
                                                     'This option applies to the previously',
         | 
| 471 471 | 
             
                                                     'specified --format, or the default format',
         | 
| 472 472 | 
             
                                                     'if no format is specified.'],
         | 
| 473 | 
            -
                  fail_level:                       ['Minimum severity (A/R/C/W/E/F) for exit',
         | 
| 473 | 
            +
                  fail_level:                       ['Minimum severity (A/I/R/C/W/E/F) for exit',
         | 
| 474 474 | 
             
                                                     'with error code.'],
         | 
| 475 475 | 
             
                  display_time:                     'Display elapsed time in seconds.',
         | 
| 476 476 | 
             
                  display_only_failed:              ['Only output offense messages. Omit passing',
         | 
| @@ -111,9 +111,12 @@ module RuboCop | |
| 111 111 | 
             
                    source
         | 
| 112 112 | 
             
                  end
         | 
| 113 113 |  | 
| 114 | 
            -
                  def expect_offense(source, file = nil, severity: nil, **replacements)
         | 
| 114 | 
            +
                  def expect_offense(source, file = nil, severity: nil, chomp: false, **replacements)
         | 
| 115 115 | 
             
                    expected_annotations = parse_annotations(source, **replacements)
         | 
| 116 | 
            -
                     | 
| 116 | 
            +
                    source = expected_annotations.plain_source
         | 
| 117 | 
            +
                    source = source.chomp if chomp
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                    @processed_source = parse_processed_source(source, file)
         | 
| 117 120 | 
             
                    @offenses = _investigate(cop, @processed_source)
         | 
| 118 121 | 
             
                    actual_annotations =
         | 
| 119 122 | 
             
                      expected_annotations.with_offense_annotations(@offenses)
         | 
    
        data/lib/rubocop/runner.rb
    CHANGED
    
    | @@ -390,6 +390,7 @@ module RuboCop | |
| 390 390 |  | 
| 391 391 | 
             
                def minimum_severity_to_fail
         | 
| 392 392 | 
             
                  @minimum_severity_to_fail ||= begin
         | 
| 393 | 
            +
                    # Unless given explicitly as `fail_level`, `:info` severity offenses do not fail
         | 
| 393 394 | 
             
                    name = @options[:fail_level] || :refactor
         | 
| 394 395 | 
             
                    RuboCop::Cop::Severity.new(name)
         | 
| 395 396 | 
             
                  end
         | 
    
        data/lib/rubocop/target_ruby.rb
    CHANGED
    
    | @@ -44,33 +44,61 @@ module RuboCop | |
| 44 44 | 
             
                # The target ruby version may be found in a .ruby-version file.
         | 
| 45 45 | 
             
                # @api private
         | 
| 46 46 | 
             
                class RubyVersionFile < Source
         | 
| 47 | 
            -
                   | 
| 47 | 
            +
                  RUBY_VERSION_FILENAME = '.ruby-version'
         | 
| 48 | 
            +
                  RUBY_VERSION_PATTERN = /\A(?:ruby-)?(?<version>\d+\.\d+)/.freeze
         | 
| 48 49 |  | 
| 49 50 | 
             
                  def name
         | 
| 50 | 
            -
                    "`#{ | 
| 51 | 
            +
                    "`#{RUBY_VERSION_FILENAME}`"
         | 
| 51 52 | 
             
                  end
         | 
| 52 53 |  | 
| 53 54 | 
             
                  private
         | 
| 54 55 |  | 
| 56 | 
            +
                  def filename
         | 
| 57 | 
            +
                    RUBY_VERSION_FILENAME
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  def pattern
         | 
| 61 | 
            +
                    RUBY_VERSION_PATTERN
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
             | 
| 55 64 | 
             
                  def find_version
         | 
| 56 | 
            -
                    file =  | 
| 65 | 
            +
                    file = version_file
         | 
| 57 66 | 
             
                    return unless file && File.file?(file)
         | 
| 58 67 |  | 
| 59 | 
            -
                     | 
| 60 | 
            -
                    # `(ruby-)` is not a capture type.
         | 
| 61 | 
            -
                    File.read(file).match(/\A(ruby-)?(?<version>\d+\.\d+)/) do |md|
         | 
| 62 | 
            -
                      # rubocop:enable Lint/MixedRegexpCaptureTypes
         | 
| 68 | 
            +
                    File.read(file).match(pattern) do |md|
         | 
| 63 69 | 
             
                      md[:version].to_f
         | 
| 64 70 | 
             
                    end
         | 
| 65 71 | 
             
                  end
         | 
| 66 72 |  | 
| 67 | 
            -
                  def  | 
| 68 | 
            -
                    @ | 
| 69 | 
            -
                      @config.find_file_upwards( | 
| 73 | 
            +
                  def version_file
         | 
| 74 | 
            +
                    @version_file ||=
         | 
| 75 | 
            +
                      @config.find_file_upwards(filename,
         | 
| 70 76 | 
             
                                                @config.base_dir_for_path_parameters)
         | 
| 71 77 | 
             
                  end
         | 
| 72 78 | 
             
                end
         | 
| 73 79 |  | 
| 80 | 
            +
                # The target ruby version may be found in a .tool-versions file, in a line
         | 
| 81 | 
            +
                # starting with `ruby`.
         | 
| 82 | 
            +
                # @api private
         | 
| 83 | 
            +
                class ToolVersionsFile < RubyVersionFile
         | 
| 84 | 
            +
                  TOOL_VERSIONS_FILENAME = '.tool-versions'
         | 
| 85 | 
            +
                  TOOL_VERSIONS_PATTERN = /\Aruby (?:ruby-)?(?<version>\d+\.\d+)/.freeze
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  def name
         | 
| 88 | 
            +
                    "`#{TOOL_VERSIONS_FILENAME}`"
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  private
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  def filename
         | 
| 94 | 
            +
                    TOOL_VERSIONS_FILENAME
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  def pattern
         | 
| 98 | 
            +
                    TOOL_VERSIONS_PATTERN
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
             | 
| 74 102 | 
             
                # The lock file of Bundler may identify the target ruby version.
         | 
| 75 103 | 
             
                # @api private
         | 
| 76 104 | 
             
                class BundlerLockFile < Source
         | 
| @@ -194,7 +222,15 @@ module RuboCop | |
| 194 222 | 
             
                  KNOWN_RUBIES
         | 
| 195 223 | 
             
                end
         | 
| 196 224 |  | 
| 197 | 
            -
                SOURCES = [ | 
| 225 | 
            +
                SOURCES = [
         | 
| 226 | 
            +
                  RuboCopConfig,
         | 
| 227 | 
            +
                  RubyVersionFile,
         | 
| 228 | 
            +
                  ToolVersionsFile,
         | 
| 229 | 
            +
                  BundlerLockFile,
         | 
| 230 | 
            +
                  GemspecFile,
         | 
| 231 | 
            +
                  Default
         | 
| 232 | 
            +
                ].freeze
         | 
| 233 | 
            +
             | 
| 198 234 | 
             
                private_constant :SOURCES
         | 
| 199 235 |  | 
| 200 236 | 
             
                def initialize(config)
         |