rubocop 0.86.0 → 0.87.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +46 -4
  4. data/lib/rubocop.rb +7 -1
  5. data/lib/rubocop/cli.rb +0 -2
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +40 -5
  7. data/lib/rubocop/cli/command/show_cops.rb +1 -1
  8. data/lib/rubocop/config_loader.rb +22 -62
  9. data/lib/rubocop/config_obsoletion.rb +0 -1
  10. data/lib/rubocop/cop/autocorrect_logic.rb +13 -23
  11. data/lib/rubocop/cop/base.rb +399 -0
  12. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +10 -20
  13. data/lib/rubocop/cop/commissioner.rb +48 -50
  14. data/lib/rubocop/cop/cop.rb +85 -236
  15. data/lib/rubocop/cop/corrector.rb +38 -115
  16. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
  17. data/lib/rubocop/cop/generator.rb +1 -1
  18. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +11 -14
  19. data/lib/rubocop/cop/layout/case_indentation.rb +18 -19
  20. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -8
  21. data/lib/rubocop/cop/layout/first_argument_indentation.rb +4 -0
  22. data/lib/rubocop/cop/layout/hash_alignment.rb +1 -2
  23. data/lib/rubocop/cop/layout/multiline_block_layout.rb +0 -1
  24. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +19 -25
  25. data/lib/rubocop/cop/legacy/corrections_proxy.rb +49 -0
  26. data/lib/rubocop/cop/legacy/corrector.rb +29 -0
  27. data/lib/rubocop/cop/lint/interpolation_check.rb +13 -0
  28. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  29. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +2 -2
  30. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -3
  31. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  32. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +27 -23
  33. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +2 -2
  34. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +8 -0
  35. data/lib/rubocop/cop/lint/syntax.rb +11 -26
  36. data/lib/rubocop/cop/lint/unused_method_argument.rb +1 -1
  37. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -1
  38. data/lib/rubocop/cop/metrics/block_length.rb +22 -0
  39. data/lib/rubocop/cop/metrics/class_length.rb +25 -2
  40. data/lib/rubocop/cop/metrics/method_length.rb +23 -0
  41. data/lib/rubocop/cop/metrics/module_length.rb +25 -2
  42. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +129 -0
  43. data/lib/rubocop/cop/mixin/allowed_methods.rb +19 -0
  44. data/lib/rubocop/cop/mixin/auto_corrector.rb +12 -0
  45. data/lib/rubocop/cop/mixin/code_length.rb +4 -0
  46. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -1
  47. data/lib/rubocop/cop/mixin/enforce_superclass.rb +3 -1
  48. data/lib/rubocop/cop/mixin/nil_methods.rb +3 -5
  49. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +6 -1
  50. data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -2
  51. data/lib/rubocop/cop/mixin/too_many_lines.rb +3 -13
  52. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +4 -2
  53. data/lib/rubocop/cop/naming/ascii_identifiers.rb +27 -4
  54. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +2 -2
  55. data/lib/rubocop/cop/naming/method_name.rb +1 -1
  56. data/lib/rubocop/cop/naming/method_parameter_name.rb +1 -1
  57. data/lib/rubocop/cop/naming/predicate_name.rb +3 -5
  58. data/lib/rubocop/cop/naming/variable_name.rb +1 -1
  59. data/lib/rubocop/cop/naming/variable_number.rb +1 -1
  60. data/lib/rubocop/cop/offense.rb +16 -2
  61. data/lib/rubocop/cop/style/accessor_grouping.rb +136 -0
  62. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +121 -0
  63. data/lib/rubocop/cop/style/class_vars.rb +21 -0
  64. data/lib/rubocop/cop/style/date_time.rb +1 -1
  65. data/lib/rubocop/cop/style/dir.rb +2 -2
  66. data/lib/rubocop/cop/style/empty_literal.rb +5 -5
  67. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -2
  68. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -0
  69. data/lib/rubocop/cop/style/multiline_block_chain.rb +10 -1
  70. data/lib/rubocop/cop/style/mutable_constant.rb +4 -4
  71. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -5
  72. data/lib/rubocop/cop/style/proc.rb +1 -1
  73. data/lib/rubocop/cop/style/random_with_offset.rb +4 -10
  74. data/lib/rubocop/cop/style/redundant_assignment.rb +117 -0
  75. data/lib/rubocop/cop/style/redundant_exception.rb +14 -10
  76. data/lib/rubocop/cop/style/redundant_fetch_block.rb +26 -7
  77. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  78. data/lib/rubocop/cop/style/redundant_parentheses.rb +7 -1
  79. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +2 -1
  80. data/lib/rubocop/cop/style/rescue_standard_error.rb +1 -1
  81. data/lib/rubocop/cop/style/signal_exception.rb +1 -1
  82. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  83. data/lib/rubocop/cop/style/struct_inheritance.rb +2 -2
  84. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  85. data/lib/rubocop/cop/style/trivial_accessors.rb +8 -7
  86. data/lib/rubocop/cop/style/zero_length_predicate.rb +2 -2
  87. data/lib/rubocop/cop/team.rb +97 -81
  88. data/lib/rubocop/cop/utils/format_string.rb +1 -2
  89. data/lib/rubocop/name_similarity.rb +1 -3
  90. data/lib/rubocop/options.rb +15 -8
  91. data/lib/rubocop/rake_task.rb +6 -9
  92. data/lib/rubocop/rspec/cop_helper.rb +4 -4
  93. data/lib/rubocop/rspec/expect_offense.rb +10 -16
  94. data/lib/rubocop/rspec/shared_contexts.rb +7 -7
  95. data/lib/rubocop/runner.rb +31 -29
  96. data/lib/rubocop/target_ruby.rb +1 -1
  97. data/lib/rubocop/version.rb +1 -1
  98. metadata +15 -7
  99. data/lib/rubocop/cop/mixin/classish_length.rb +0 -37
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Legacy
6
+ # Legacy support for Corrector#corrections
7
+ # See https://docs.rubocop.org/rubocop/cop_api_v1_changelog.html
8
+ class CorrectionsProxy
9
+ def initialize(corrector)
10
+ @corrector = corrector
11
+ end
12
+
13
+ def <<(callable)
14
+ suppress_clobbering do
15
+ @corrector.transaction do
16
+ callable.call(@corrector)
17
+ end
18
+ end
19
+ end
20
+
21
+ def empty?
22
+ @corrector.empty?
23
+ end
24
+
25
+ def concat(corrections)
26
+ if corrections.is_a?(CorrectionsProxy)
27
+ suppress_clobbering do
28
+ corrector.merge!(corrections.corrector)
29
+ end
30
+ else
31
+ corrections.each { |correction| self << correction }
32
+ end
33
+ end
34
+
35
+ protected
36
+
37
+ attr_reader :corrector
38
+
39
+ private
40
+
41
+ def suppress_clobbering
42
+ yield
43
+ rescue ::Parser::ClobberingError
44
+ # ignore Clobbering errors
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Legacy
6
+ # Legacy Corrector for v0 API support.
7
+ # See https://docs.rubocop.org/rubocop/cop_api_v1_changelog.html
8
+ class Corrector < RuboCop::Cop::Corrector
9
+ # Support legacy second argument
10
+ def initialize(source, corr = [])
11
+ super(source)
12
+ if corr.is_a?(CorrectionsProxy)
13
+ merge!(corr.send(:corrector))
14
+ else
15
+ # warn "Corrector.new with corrections is deprecated." unless corr.empty? TODO
16
+ corr.each do |c|
17
+ corrections << c
18
+ end
19
+ end
20
+ end
21
+
22
+ def corrections
23
+ # warn "#corrections is deprecated. Open an issue if you have a valid usecase." TODO
24
+ CorrectionsProxy.new(self)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -30,6 +30,19 @@ module RuboCop
30
30
  add_offense(node)
31
31
  end
32
32
 
33
+ def autocorrect(node)
34
+ lambda do |corrector|
35
+ starting_token, ending_token = if node.source.include?('"')
36
+ ['%{', '}']
37
+ else
38
+ ['"', '"']
39
+ end
40
+
41
+ corrector.replace(node.loc.begin, starting_token)
42
+ corrector.replace(node.loc.end, ending_token)
43
+ end
44
+ end
45
+
33
46
  def heredoc?(node)
34
47
  node.loc.is_a?(Parser::Source::Map::Heredoc) ||
35
48
  (node.parent && heredoc?(node.parent))
@@ -96,7 +96,7 @@ module RuboCop
96
96
  PATTERN
97
97
 
98
98
  def_node_matcher :class_or_module_or_struct_new_call?, <<~PATTERN
99
- (block (send (const nil? {:Class :Module :Struct}) :new ...) ...)
99
+ (block (send (const {nil? cbase} {:Class :Module :Struct}) :new ...) ...)
100
100
  PATTERN
101
101
  end
102
102
  end
@@ -69,11 +69,11 @@ module RuboCop
69
69
  end
70
70
 
71
71
  def_node_matcher :unsorted_dir_block?, <<~PATTERN
72
- (send (const nil? :Dir) :glob ...)
72
+ (send (const {nil? cbase} :Dir) :glob ...)
73
73
  PATTERN
74
74
 
75
75
  def_node_matcher :unsorted_dir_each?, <<~PATTERN
76
- (send (send (const nil? :Dir) {:[] :glob} ...) :each)
76
+ (send (send (const {nil? cbase} :Dir) {:[] :glob} ...) :each)
77
77
  PATTERN
78
78
 
79
79
  def_node_matcher :loop_variable, <<~PATTERN
@@ -48,17 +48,22 @@ module RuboCop
48
48
  return true
49
49
  end
50
50
 
51
- node.operator_method? || node.setter_method? || grouped_parentheses?(node)
51
+ node.operator_method? || node.setter_method? || chained_calls?(node) ||
52
+ operator_keyword?(node)
52
53
  end
53
54
 
54
55
  def first_argument_starts_with_left_parenthesis?(node)
55
56
  node.first_argument.source.start_with?('(')
56
57
  end
57
58
 
58
- def grouped_parentheses?(node)
59
+ def chained_calls?(node)
59
60
  first_argument = node.first_argument
61
+ first_argument.send_type? && (node.children.last&.children&.count || 0) > 1
62
+ end
60
63
 
61
- first_argument.send_type? && first_argument.receiver&.begin_type?
64
+ def operator_keyword?(node)
65
+ first_argument = node.first_argument
66
+ first_argument.operator_keyword?
62
67
  end
63
68
 
64
69
  def spaces_before_left_parenthesis(node)
@@ -25,7 +25,7 @@ module RuboCop
25
25
  'Perhaps you meant `rand(2)` or `rand`?'
26
26
 
27
27
  def_node_matcher :rand_one?, <<~PATTERN
28
- (send {(const nil? :Kernel) nil?} :rand {(int {-1 1}) (float {-1.0 1.0})})
28
+ (send {(const {nil? cbase} :Kernel) nil?} :rand {(int {-1 1}) (float {-1.0 1.0})})
29
29
  PATTERN
30
30
 
31
31
  def on_send(node)
@@ -25,34 +25,34 @@ module RuboCop
25
25
  #
26
26
  # # good
27
27
  # x += 1
28
- class RedundantCopDisableDirective < Cop
28
+ class RedundantCopDisableDirective < Base
29
29
  include RangeHelp
30
+ extend AutoCorrector
30
31
 
31
32
  COP_NAME = 'Lint/RedundantCopDisableDirective'
32
33
 
33
- def check(offenses, cop_disabled_line_ranges, comments)
34
+ attr_accessor :offenses_to_check
35
+
36
+ def initialize(config = nil, options = nil, offenses = nil)
37
+ @offenses_to_check = offenses
38
+ super(config, options)
39
+ end
40
+
41
+ def on_new_investigation
42
+ return unless offenses_to_check
43
+
44
+ comments = processed_source.comments
45
+ cop_disabled_line_ranges = processed_source.disabled_line_ranges
46
+
34
47
  redundant_cops = Hash.new { |h, k| h[k] = Set.new }
35
48
 
36
49
  each_redundant_disable(cop_disabled_line_ranges,
37
- offenses, comments) do |comment, redundant_cop|
50
+ offenses_to_check, comments) do |comment, redundant_cop|
38
51
  redundant_cops[comment].add(redundant_cop)
39
52
  end
40
53
 
41
54
  add_offenses(redundant_cops)
42
- end
43
-
44
- def autocorrect(args)
45
- lambda do |corrector|
46
- ranges, range = *args # Ranges are sorted by position.
47
-
48
- range = if range.source.start_with?('#')
49
- comment_range_with_surrounding_space(range)
50
- else
51
- directive_range_in_list(range, ranges)
52
- end
53
-
54
- corrector.remove(range)
55
- end
55
+ super
56
56
  end
57
57
 
58
58
  private
@@ -187,10 +187,12 @@ module RuboCop
187
187
  cop_list = cops.sort.map { |c| describe(c) }
188
188
 
189
189
  add_offense(
190
- [[location], location],
191
- location: location,
190
+ location,
192
191
  message: "Unnecessary disabling of #{cop_list.join(', ')}."
193
- )
192
+ ) do |corrector|
193
+ range = comment_range_with_surrounding_space(location)
194
+ corrector.remove(range)
195
+ end
194
196
  end
195
197
 
196
198
  def add_offense_for_some_cops(comment, cops)
@@ -200,10 +202,12 @@ module RuboCop
200
202
 
201
203
  cop_ranges.each do |cop, range|
202
204
  add_offense(
203
- [ranges, range],
204
- location: range,
205
+ range,
205
206
  message: "Unnecessary disabling of #{describe(cop)}."
206
- )
207
+ ) do |corrector|
208
+ range = directive_range_in_list(range, ranges)
209
+ corrector.remove(range)
210
+ end
207
211
  end
208
212
  end
209
213
 
@@ -60,8 +60,8 @@ module RuboCop
60
60
 
61
61
  def_node_matcher :array_new?, <<~PATTERN
62
62
  {
63
- $(send (const nil? :Array) :new ...)
64
- $(block (send (const nil? :Array) :new ...) ...)
63
+ $(send (const {nil? cbase} :Array) :new ...)
64
+ $(block (send (const {nil? cbase} :Array) :new ...) ...)
65
65
  }
66
66
  PATTERN
67
67
 
@@ -32,6 +32,14 @@ module RuboCop
32
32
 
33
33
  add_offense(node.condition)
34
34
  end
35
+
36
+ def autocorrect(node)
37
+ lambda do |corrector|
38
+ receiver = node.receiver.source
39
+
40
+ corrector.replace(node, "#{receiver} && #{receiver}.#{node.method_name}")
41
+ end
42
+ end
35
43
  end
36
44
  end
37
45
  end
@@ -3,49 +3,34 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This is not actually a cop. It does not inspect anything. It just
7
- # provides methods to repack Parser's diagnostics/errors
6
+ # This cop repacks Parser's diagnostics/errors
8
7
  # into RuboCop's offenses.
9
- class Syntax < Cop
10
- PseudoSourceRange = Struct.new(:line, :column, :source_line, :begin_pos,
11
- :end_pos)
12
-
13
- ERROR_SOURCE_RANGE = PseudoSourceRange.new(1, 0, '', 0, 1).freeze
14
-
15
- def self.offenses_from_processed_source(processed_source,
16
- config, options)
17
- cop = new(config, options)
18
-
19
- cop.add_offense_from_error(processed_source.parser_error) if processed_source.parser_error
20
-
8
+ class Syntax < Base
9
+ def on_other_file
10
+ add_offense_from_error(processed_source.parser_error) if processed_source.parser_error
21
11
  processed_source.diagnostics.each do |diagnostic|
22
- cop.add_offense_from_diagnostic(diagnostic,
23
- processed_source.ruby_version)
12
+ add_offense_from_diagnostic(diagnostic,
13
+ processed_source.ruby_version)
24
14
  end
25
-
26
- cop.offenses
15
+ super
27
16
  end
28
17
 
18
+ private
19
+
29
20
  def add_offense_from_diagnostic(diagnostic, ruby_version)
30
21
  message =
31
22
  "#{diagnostic.message}\n(Using Ruby #{ruby_version} parser; " \
32
23
  'configure using `TargetRubyVersion` parameter, under `AllCops`)'
33
- add_offense(nil,
34
- location: diagnostic.location,
24
+ add_offense(diagnostic.location,
35
25
  message: message,
36
26
  severity: diagnostic.level)
37
27
  end
38
28
 
39
29
  def add_offense_from_error(error)
40
30
  message = beautify_message(error.message)
41
- add_offense(nil,
42
- location: ERROR_SOURCE_RANGE,
43
- message: message,
44
- severity: :fatal)
31
+ add_global_offense(message, severity: :fatal)
45
32
  end
46
33
 
47
- private
48
-
49
34
  def beautify_message(message)
50
35
  message = message.capitalize
51
36
  message << '.' unless message.end_with?('.')
@@ -62,7 +62,7 @@ module RuboCop
62
62
  include UnusedArgument
63
63
 
64
64
  def_node_matcher :not_implemented?, <<~PATTERN
65
- {(send nil? :raise (const nil? :NotImplementedError))
65
+ {(send nil? :raise (const {nil? cbase} :NotImplementedError))
66
66
  (send nil? :fail ...)}
67
67
  PATTERN
68
68
 
@@ -172,7 +172,7 @@ module RuboCop
172
172
  PATTERN
173
173
 
174
174
  def_node_matcher :class_or_module_or_struct_new_call?, <<~PATTERN
175
- (block (send (const nil? {:Class :Module :Struct}) :new ...) ...)
175
+ (block (send (const {nil? cbase} {:Class :Module :Struct}) :new ...) ...)
176
176
  PATTERN
177
177
 
178
178
  def check_node(node)
@@ -7,6 +7,28 @@ module RuboCop
7
7
  # Comment lines can optionally be ignored.
8
8
  # The maximum allowed length is configurable.
9
9
  # The cop can be configured to ignore blocks passed to certain methods.
10
+ #
11
+ # You can set literals you want to fold with `CountAsOne`.
12
+ # Available are: 'array', 'hash', and 'heredoc'. Each literal
13
+ # will be counted as one line regardless of its actual size.
14
+ #
15
+ # @example CountAsOne: ['array', 'heredoc']
16
+ #
17
+ # something do
18
+ # array = [ # +1
19
+ # 1,
20
+ # 2
21
+ # ]
22
+ #
23
+ # hash = { # +3
24
+ # key: 'value'
25
+ # }
26
+ #
27
+ # msg = <<~HEREDOC # +1
28
+ # Heredoc
29
+ # content.
30
+ # HEREDOC
31
+ # end # 5 points
10
32
  class BlockLength < Cop
11
33
  include TooManyLines
12
34
 
@@ -6,8 +6,31 @@ module RuboCop
6
6
  # This cop checks if the length a class exceeds some maximum value.
7
7
  # Comment lines can optionally be ignored.
8
8
  # The maximum allowed length is configurable.
9
+ #
10
+ # You can set literals you want to fold with `CountAsOne`.
11
+ # Available are: 'array', 'hash', and 'heredoc'. Each literal
12
+ # will be counted as one line regardless of its actual size.
13
+ #
14
+ # @example CountAsOne: ['array', 'heredoc']
15
+ #
16
+ # class Foo
17
+ # ARRAY = [ # +1
18
+ # 1,
19
+ # 2
20
+ # ]
21
+ #
22
+ # HASH = { # +3
23
+ # key: 'value'
24
+ # }
25
+ #
26
+ # MSG = <<~HEREDOC # +1
27
+ # Heredoc
28
+ # content.
29
+ # HEREDOC
30
+ # end # 5 points
31
+ #
9
32
  class ClassLength < Cop
10
- include ClassishLength
33
+ include TooManyLines
11
34
 
12
35
  def on_class(node)
13
36
  check_code_length(node)
@@ -22,7 +45,7 @@ module RuboCop
22
45
  private
23
46
 
24
47
  def_node_matcher :class_definition?, <<~PATTERN
25
- (casgn nil? _ (block (send (const nil? :Class) :new) ...))
48
+ (casgn nil? _ (block (send (const {nil? cbase} :Class) :new) ...))
26
49
  PATTERN
27
50
 
28
51
  def message(length, max_length)
@@ -6,6 +6,29 @@ module RuboCop
6
6
  # This cop checks if the length of a method exceeds some maximum value.
7
7
  # Comment lines can optionally be ignored.
8
8
  # The maximum allowed length is configurable.
9
+ #
10
+ # You can set literals you want to fold with `CountAsOne`.
11
+ # Available are: 'array', 'hash', and 'heredoc'. Each literal
12
+ # will be counted as one line regardless of its actual size.
13
+ #
14
+ # @example CountAsOne: ['array', 'heredoc']
15
+ #
16
+ # def m
17
+ # array = [ # +1
18
+ # 1,
19
+ # 2
20
+ # ]
21
+ #
22
+ # hash = { # +3
23
+ # key: 'value'
24
+ # }
25
+ #
26
+ # <<~HEREDOC # +1
27
+ # Heredoc
28
+ # content.
29
+ # HEREDOC
30
+ # end # 5 points
31
+ #
9
32
  class MethodLength < Cop
10
33
  include TooManyLines
11
34