rubocop 1.65.0 → 1.66.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +67 -67
  3. data/config/default.yml +18 -2
  4. data/exe/rubocop +4 -3
  5. data/lib/rubocop/comment_config.rb +1 -1
  6. data/lib/rubocop/config.rb +5 -1
  7. data/lib/rubocop/config_loader.rb +14 -8
  8. data/lib/rubocop/config_loader_resolver.rb +1 -2
  9. data/lib/rubocop/config_validator.rb +1 -1
  10. data/lib/rubocop/cop/base.rb +4 -0
  11. data/lib/rubocop/cop/cop.rb +2 -2
  12. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
  13. data/lib/rubocop/cop/documentation.rb +18 -1
  14. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
  15. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  16. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +11 -1
  17. data/lib/rubocop/cop/layout/assignment_indentation.rb +3 -2
  18. data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
  19. data/lib/rubocop/cop/layout/condition_position.rb +0 -4
  20. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
  21. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +8 -3
  22. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +0 -3
  23. data/lib/rubocop/cop/layout/line_length.rb +14 -14
  24. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +0 -2
  25. data/lib/rubocop/cop/lint/ambiguous_operator.rb +0 -2
  26. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +0 -2
  27. data/lib/rubocop/cop/lint/boolean_symbol.rb +0 -2
  28. data/lib/rubocop/cop/lint/circular_argument_reference.rb +0 -13
  29. data/lib/rubocop/cop/lint/debugger.rb +0 -4
  30. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +0 -10
  31. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +0 -4
  32. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +0 -4
  33. data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -10
  34. data/lib/rubocop/cop/lint/each_with_object_argument.rb +0 -4
  35. data/lib/rubocop/cop/lint/else_layout.rb +0 -2
  36. data/lib/rubocop/cop/lint/empty_conditional_body.rb +27 -6
  37. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -11
  38. data/lib/rubocop/cop/lint/empty_interpolation.rb +0 -4
  39. data/lib/rubocop/cop/lint/empty_when.rb +0 -2
  40. data/lib/rubocop/cop/lint/ensure_return.rb +1 -6
  41. data/lib/rubocop/cop/lint/float_out_of_range.rb +0 -4
  42. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +0 -10
  43. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +5 -7
  44. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +0 -7
  45. data/lib/rubocop/cop/lint/interpolation_check.rb +0 -4
  46. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  47. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +0 -4
  48. data/lib/rubocop/cop/lint/loop.rb +6 -12
  49. data/lib/rubocop/cop/lint/nested_method_definition.rb +0 -6
  50. data/lib/rubocop/cop/lint/next_without_accumulator.rb +0 -4
  51. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +0 -5
  52. data/lib/rubocop/cop/lint/percent_string_array.rb +0 -4
  53. data/lib/rubocop/cop/lint/percent_symbol_array.rb +0 -4
  54. data/lib/rubocop/cop/lint/rand_one.rb +0 -4
  55. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +3 -1
  56. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  57. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +0 -4
  58. data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
  59. data/lib/rubocop/cop/lint/rescue_exception.rb +0 -4
  60. data/lib/rubocop/cop/lint/return_in_void_context.rb +0 -2
  61. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +0 -4
  62. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
  63. data/lib/rubocop/cop/lint/unified_integer.rb +0 -4
  64. data/lib/rubocop/cop/lint/unreachable_code.rb +0 -5
  65. data/lib/rubocop/cop/lint/useless_assignment.rb +19 -16
  66. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
  67. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
  68. data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
  69. data/lib/rubocop/cop/lint/void.rb +30 -8
  70. data/lib/rubocop/cop/metrics/block_length.rb +6 -5
  71. data/lib/rubocop/cop/metrics/class_length.rb +6 -5
  72. data/lib/rubocop/cop/metrics/method_length.rb +6 -5
  73. data/lib/rubocop/cop/metrics/module_length.rb +6 -5
  74. data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
  75. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +19 -9
  76. data/lib/rubocop/cop/mixin/line_length_help.rb +7 -2
  77. data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
  78. data/lib/rubocop/cop/naming/accessor_method_name.rb +5 -0
  79. data/lib/rubocop/cop/naming/predicate_name.rb +52 -26
  80. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -1
  81. data/lib/rubocop/cop/style/alias.rb +1 -1
  82. data/lib/rubocop/cop/style/arguments_forwarding.rb +8 -3
  83. data/lib/rubocop/cop/style/def_with_parentheses.rb +0 -2
  84. data/lib/rubocop/cop/style/each_for_simple_loop.rb +0 -1
  85. data/lib/rubocop/cop/style/empty_else.rb +6 -5
  86. data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
  87. data/lib/rubocop/cop/style/empty_literal.rb +31 -22
  88. data/lib/rubocop/cop/style/eval_with_location.rb +12 -11
  89. data/lib/rubocop/cop/style/file_read.rb +2 -5
  90. data/lib/rubocop/cop/style/file_write.rb +2 -5
  91. data/lib/rubocop/cop/style/format_string_token.rb +2 -2
  92. data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
  93. data/lib/rubocop/cop/style/guard_clause.rb +2 -0
  94. data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
  95. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +0 -1
  96. data/lib/rubocop/cop/style/if_with_semicolon.rb +45 -6
  97. data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
  98. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  99. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  100. data/lib/rubocop/cop/style/map_into_array.rb +12 -5
  101. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  102. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
  103. data/lib/rubocop/cop/style/missing_else.rb +0 -4
  104. data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
  105. data/lib/rubocop/cop/style/multiple_comparison.rb +3 -11
  106. data/lib/rubocop/cop/style/numeric_predicate.rb +2 -2
  107. data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
  108. data/lib/rubocop/cop/style/parallel_assignment.rb +5 -4
  109. data/lib/rubocop/cop/style/quoted_symbols.rb +0 -2
  110. data/lib/rubocop/cop/style/redundant_condition.rb +3 -3
  111. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
  112. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
  113. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -24
  114. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  115. data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -2
  116. data/lib/rubocop/cop/style/while_until_do.rb +0 -2
  117. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  118. data/lib/rubocop/cop/style/zero_length_predicate.rb +5 -1
  119. data/lib/rubocop/cop/team.rb +6 -2
  120. data/lib/rubocop/cop/variable_force.rb +13 -1
  121. data/lib/rubocop/core_ext/string.rb +2 -6
  122. data/lib/rubocop/ext/regexp_node.rb +9 -31
  123. data/lib/rubocop/formatter/junit_formatter.rb +70 -23
  124. data/lib/rubocop/lockfile.rb +6 -4
  125. data/lib/rubocop/options.rb +3 -1
  126. data/lib/rubocop/remote_config.rb +5 -1
  127. data/lib/rubocop/result_cache.rb +2 -8
  128. data/lib/rubocop/rspec/shared_contexts.rb +2 -2
  129. data/lib/rubocop/server/cache.rb +1 -1
  130. data/lib/rubocop/target_ruby.rb +7 -3
  131. data/lib/rubocop/version.rb +1 -1
  132. data/lib/rubocop/yaml_duplication_checker.rb +1 -0
  133. data/lib/rubocop.rb +7 -1
  134. metadata +8 -26
@@ -17,8 +17,6 @@ module RuboCop
17
17
  # end
18
18
  # end
19
19
  #
20
- # @example
21
- #
22
20
  # # good
23
21
  #
24
22
  # def foo
@@ -26,8 +24,6 @@ module RuboCop
26
24
  # bar.call
27
25
  # end
28
26
  #
29
- # @example
30
- #
31
27
  # # good
32
28
  #
33
29
  # # `class_eval`, `instance_eval`, `module_eval`, `class_exec`, `instance_exec`, and
@@ -47,8 +43,6 @@ module RuboCop
47
43
  # end
48
44
  # end
49
45
  #
50
- # @example
51
- #
52
46
  # # good
53
47
  #
54
48
  # def foo
@@ -8,16 +8,12 @@ module RuboCop
8
8
  # @example
9
9
  #
10
10
  # # bad
11
- #
12
11
  # result = (1..4).reduce(0) do |acc, i|
13
12
  # next if i.odd?
14
13
  # acc + i
15
14
  # end
16
15
  #
17
- # @example
18
- #
19
16
  # # good
20
- #
21
17
  # result = (1..4).reduce(0) do |acc, i|
22
18
  # next acc if i.odd?
23
19
  # acc + i
@@ -11,17 +11,13 @@ module RuboCop
11
11
  # @example
12
12
  #
13
13
  # # bad
14
- #
15
14
  # @some_variable ||= begin
16
15
  # return some_value if some_condition_is_met
17
16
  #
18
17
  # do_something
19
18
  # end
20
19
  #
21
- # @example
22
- #
23
20
  # # good
24
- #
25
21
  # @some_variable ||= begin
26
22
  # if some_condition_is_met
27
23
  # some_value
@@ -31,7 +27,6 @@ module RuboCop
31
27
  # end
32
28
  #
33
29
  # # good
34
- #
35
30
  # some_variable = if some_condition_is_met
36
31
  # return if another_condition_is_met
37
32
  #
@@ -22,13 +22,9 @@ module RuboCop
22
22
  # @example
23
23
  #
24
24
  # # bad
25
- #
26
25
  # %w('foo', "bar")
27
26
  #
28
- # @example
29
- #
30
27
  # # good
31
- #
32
28
  # %w(foo bar)
33
29
  class PercentStringArray < Base
34
30
  include PercentLiteral
@@ -12,13 +12,9 @@ module RuboCop
12
12
  # @example
13
13
  #
14
14
  # # bad
15
- #
16
15
  # %i(:foo, :bar)
17
16
  #
18
- # @example
19
- #
20
17
  # # good
21
- #
22
18
  # %i(foo bar)
23
19
  class PercentSymbolArray < Base
24
20
  include PercentLiteral
@@ -9,16 +9,12 @@ module RuboCop
9
9
  # @example
10
10
  #
11
11
  # # bad
12
- #
13
12
  # rand 1
14
13
  # Kernel.rand(-1)
15
14
  # rand 1.0
16
15
  # rand(-1.0)
17
16
  #
18
- # @example
19
- #
20
17
  # # good
21
- #
22
18
  # 0 # just use 0 instead
23
19
  class RandOne < Base
24
20
  MSG = '`%<method>s` always returns `0`. Perhaps you meant `rand(2)` or `rand`?'
@@ -14,14 +14,16 @@ module RuboCop
14
14
  #
15
15
  # When comment enables all cops at once `rubocop:enable all`
16
16
  # that cop checks whether any cop was actually enabled.
17
+ #
17
18
  # @example
19
+ #
18
20
  # # bad
19
21
  # foo = 1
20
22
  # # rubocop:enable Layout/LineLength
21
23
  #
22
24
  # # good
23
25
  # foo = 1
24
- # @example
26
+ #
25
27
  # # bad
26
28
  # # rubocop:disable Style/StringLiterals
27
29
  # foo = "1"
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for unneeded usages of splat expansion
6
+ # Checks for unneeded usages of splat expansion.
7
7
  #
8
8
  # @example
9
9
  #
@@ -9,16 +9,12 @@ module RuboCop
9
9
  # @example
10
10
  #
11
11
  # # bad
12
- #
13
12
  # "result is #{something.to_s}"
14
13
  # print something.to_s
15
14
  # puts something.to_s
16
15
  # warn something.to_s
17
16
  #
18
- # @example
19
- #
20
17
  # # good
21
- #
22
18
  # "result is #{something}"
23
19
  # print something
24
20
  # puts something
@@ -15,15 +15,11 @@ module RuboCop
15
15
  # @example
16
16
  #
17
17
  # # bad
18
- #
19
18
  # if day.is? :tuesday && month == :jan
20
19
  # # ...
21
20
  # end
22
21
  #
23
- # @example
24
- #
25
22
  # # good
26
- #
27
23
  # if day.is?(:tuesday) && month == :jan
28
24
  # # ...
29
25
  # end
@@ -8,17 +8,13 @@ module RuboCop
8
8
  # @example
9
9
  #
10
10
  # # bad
11
- #
12
11
  # begin
13
12
  # do_something
14
13
  # rescue Exception
15
14
  # handle_exception
16
15
  # end
17
16
  #
18
- # @example
19
- #
20
17
  # # good
21
- #
22
18
  # begin
23
19
  # do_something
24
20
  # rescue ArgumentError
@@ -19,8 +19,6 @@ module RuboCop
19
19
  # return 42
20
20
  # end
21
21
  #
22
- # @example
23
- #
24
22
  # # good
25
23
  # def initialize
26
24
  # foo
@@ -12,15 +12,11 @@ module RuboCop
12
12
  # @example
13
13
  #
14
14
  # # bad
15
- #
16
15
  # x&.foo.bar
17
16
  # x&.foo + bar
18
17
  # x&.foo[bar]
19
18
  #
20
- # @example
21
- #
22
19
  # # good
23
- #
24
20
  # x&.foo&.bar
25
21
  # x&.foo || bar
26
22
  class SafeNavigationChain < Base
@@ -12,17 +12,16 @@ module RuboCop
12
12
  # because `Ractor` should not access outer variables.
13
13
  # eg. following style is encouraged:
14
14
  #
15
- # [source,ruby]
16
- # ----
17
- # worker_id, pipe = env
18
- # Ractor.new(worker_id, pipe) do |worker_id, pipe|
19
- # end
20
- # ----
15
+ # [source,ruby]
16
+ # ----
17
+ # worker_id, pipe = env
18
+ # Ractor.new(worker_id, pipe) do |worker_id, pipe|
19
+ # end
20
+ # ----
21
21
  #
22
22
  # @example
23
23
  #
24
24
  # # bad
25
- #
26
25
  # def some_method
27
26
  # foo = 1
28
27
  #
@@ -31,10 +30,7 @@ module RuboCop
31
30
  # end
32
31
  # end
33
32
  #
34
- # @example
35
- #
36
33
  # # good
37
- #
38
34
  # def some_method
39
35
  # foo = 1
40
36
  #
@@ -8,14 +8,10 @@ module RuboCop
8
8
  # @example
9
9
  #
10
10
  # # bad
11
- #
12
11
  # 1.is_a?(Fixnum)
13
12
  # 1.is_a?(Bignum)
14
13
  #
15
- # @example
16
- #
17
14
  # # good
18
- #
19
15
  # 1.is_a?(Integer)
20
16
  class UnifiedInteger < Base
21
17
  extend AutoCorrector
@@ -10,14 +10,12 @@ module RuboCop
10
10
  # @example
11
11
  #
12
12
  # # bad
13
- #
14
13
  # def some_method
15
14
  # return
16
15
  # do_something
17
16
  # end
18
17
  #
19
18
  # # bad
20
- #
21
19
  # def some_method
22
20
  # if cond
23
21
  # return
@@ -27,10 +25,7 @@ module RuboCop
27
25
  # do_something
28
26
  # end
29
27
  #
30
- # @example
31
- #
32
28
  # # good
33
- #
34
29
  # def some_method
35
30
  # do_something
36
31
  # end
@@ -16,28 +16,23 @@ module RuboCop
16
16
  # reassignments and properly handles varied cases such as branch, loop,
17
17
  # rescue, ensure, etc.
18
18
  #
19
+ # This cop's autocorrection avoids cases like `a ||= 1` because removing assignment from
20
+ # operator assignment can cause NameError if this assignment has been used to declare
21
+ # a local variable. For example, replacing `a ||= 1` with `a || 1` may cause
22
+ # "undefined local variable or method `a' for main:Object (NameError)".
23
+ #
19
24
  # NOTE: Given the assignment `foo = 1, bar = 2`, removing unused variables
20
25
  # can lead to a syntax error, so this case is not autocorrected.
21
26
  #
22
- # @safety
23
- # This cop's autocorrection is unsafe because removing assignment from
24
- # operator assignment can cause NameError if this assignment has been used to declare
25
- # local variable. For example, replacing `a ||= 1` to `a || 1` may cause
26
- # "undefined local variable or method `a' for main:Object (NameError)".
27
- #
28
27
  # @example
29
28
  #
30
29
  # # bad
31
- #
32
30
  # def some_method
33
31
  # some_var = 1
34
32
  # do_something
35
33
  # end
36
34
  #
37
- # @example
38
- #
39
35
  # # good
40
- #
41
36
  # def some_method
42
37
  # some_var = 1
43
38
  # do_something(some_var)
@@ -57,24 +52,32 @@ module RuboCop
57
52
  scope.variables.each_value { |variable| check_for_unused_assignments(variable) }
58
53
  end
59
54
 
60
- # rubocop:disable Metrics/AbcSize
55
+ # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
61
56
  def check_for_unused_assignments(variable)
62
57
  return if variable.should_be_unused?
63
58
 
64
- variable.assignments.each do |assignment|
65
- next if assignment.used? || part_of_ignored_node?(assignment.node)
59
+ variable.assignments.reverse_each do |assignment|
60
+ assignment_node = assignment.node
61
+ next if assignment.used? || part_of_ignored_node?(assignment_node)
66
62
 
67
63
  message = message_for_useless_assignment(assignment)
68
64
  range = offense_range(assignment)
69
65
 
70
66
  add_offense(range, message: message) do |corrector|
71
- autocorrect(corrector, assignment) unless sequential_assignment?(assignment.node)
67
+ # In cases like `x = 1, y = 2`, where removing a variable would cause a syntax error,
68
+ # and where changing `x ||= 1` to `x = 1` would cause `NameError`,
69
+ # the autocorrect will be skipped, even if the variable is unused.
70
+ if sequential_assignment?(assignment_node) || assignment_node.parent&.or_asgn_type?
71
+ next
72
+ end
73
+
74
+ autocorrect(corrector, assignment)
72
75
  end
73
76
 
74
- ignore_node(assignment.node) if chained_assignment?(assignment.node)
77
+ ignore_node(assignment_node) if chained_assignment?(assignment_node)
75
78
  end
76
79
  end
77
- # rubocop:enable Metrics/AbcSize
80
+ # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
78
81
 
79
82
  def message_for_useless_assignment(assignment)
80
83
  variable = assignment.variable
@@ -10,17 +10,13 @@ module RuboCop
10
10
  # @example
11
11
  #
12
12
  # # bad
13
- #
14
13
  # begin
15
14
  # do_something
16
15
  # else
17
16
  # do_something_else # This will never be run.
18
17
  # end
19
18
  #
20
- # @example
21
- #
22
19
  # # good
23
- #
24
20
  # begin
25
21
  # do_something
26
22
  # rescue
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Certain numeric operations have no impact, being:
7
+ # Adding or subtracting 0, multiplying or dividing by 1 or raising to the power of 1.
8
+ # These are probably leftover from debugging, or are mistakes.
9
+ #
10
+ # @example
11
+ #
12
+ # # bad
13
+ # x + 0
14
+ # x - 0
15
+ # x * 1
16
+ # x / 1
17
+ # x ** 1
18
+ #
19
+ # # good
20
+ # x
21
+ #
22
+ # # bad
23
+ # x += 0
24
+ # x -= 0
25
+ # x *= 1
26
+ # x /= 1
27
+ # x **= 1
28
+ #
29
+ # # good
30
+ # x = x
31
+ #
32
+ class UselessNumericOperation < Base
33
+ extend AutoCorrector
34
+ MSG = 'Do not apply inconsequential numeric operations to variables.'
35
+ RESTRICT_ON_SEND = %i[+ - * / **].freeze
36
+
37
+ # @!method useless_operation?(node)
38
+ def_node_matcher :useless_operation?, '(send (send nil? $_) $_ (int $_))'
39
+
40
+ # @!method useless_abbreviated_assignment?(node)
41
+ def_node_matcher :useless_abbreviated_assignment?, '(op-asgn (lvasgn $_) $_ (int $_))'
42
+
43
+ def on_send(node)
44
+ return unless useless_operation?(node)
45
+
46
+ variable, operation, number = useless_operation?(node)
47
+ return unless useless?(operation, number)
48
+
49
+ add_offense(node) do |corrector|
50
+ corrector.replace(node, variable)
51
+ end
52
+ end
53
+
54
+ def on_op_asgn(node)
55
+ return unless useless_abbreviated_assignment?(node)
56
+
57
+ variable, operation, number = useless_abbreviated_assignment?(node)
58
+ return unless useless?(operation, number)
59
+
60
+ add_offense(node) do |corrector|
61
+ corrector.replace(node, "#{variable} = #{variable}")
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def useless?(operation, number)
68
+ if number.zero?
69
+ true if %i[+ -].include?(operation)
70
+ elsif number == 1
71
+ true if %i[* / **].include?(operation)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -17,16 +17,12 @@ module RuboCop
17
17
  # @example
18
18
  #
19
19
  # # bad
20
- #
21
20
  # def something
22
21
  # x = Something.new
23
22
  # x.attr = 5
24
23
  # end
25
24
  #
26
- # @example
27
- #
28
25
  # # good
29
- #
30
26
  # def something
31
27
  # x = Something.new
32
28
  # x.attr = 5
@@ -66,7 +66,6 @@ module RuboCop
66
66
  BINARY_OPERATORS = %i[* / % + - == === != < > <= >= <=>].freeze
67
67
  UNARY_OPERATORS = %i[+@ -@ ~ !].freeze
68
68
  OPERATORS = (BINARY_OPERATORS + UNARY_OPERATORS).freeze
69
- VOID_CONTEXT_TYPES = %i[def for block].freeze
70
69
  NONMUTATING_METHODS_WITH_BANG_VERSION = %i[capitalize chomp chop compact
71
70
  delete_prefix delete_suffix downcase
72
71
  encode flatten gsub lstrip merge next
@@ -86,7 +85,6 @@ module RuboCop
86
85
  check_void_op(node.body) { node.method?(:each) }
87
86
  check_expression(node.body)
88
87
  end
89
-
90
88
  alias on_numblock on_block
91
89
 
92
90
  def on_begin(node)
@@ -94,6 +92,10 @@ module RuboCop
94
92
  end
95
93
  alias on_kwbegin on_begin
96
94
 
95
+ def on_ensure(node)
96
+ check_ensure(node)
97
+ end
98
+
97
99
  private
98
100
 
99
101
  def check_begin(node)
@@ -193,12 +195,24 @@ module RuboCop
193
195
  end
194
196
  end
195
197
 
198
+ def check_ensure(node)
199
+ return unless (body = node.body)
200
+ # NOTE: the `begin` node case is already handled via `on_begin`
201
+ return if body.begin_type?
202
+
203
+ check_void_op(body) do
204
+ block_node = node.each_ancestor(:block).first
205
+ block_node&.method?(:each)
206
+ end
207
+
208
+ check_expression(body)
209
+ end
210
+
196
211
  def in_void_context?(node)
197
212
  parent = node.parent
198
-
199
213
  return false unless parent && parent.children.last == node
200
214
 
201
- VOID_CONTEXT_TYPES.include?(parent.type) && parent.void_context?
215
+ parent.respond_to?(:void_context?) && parent.void_context?
202
216
  end
203
217
 
204
218
  def autocorrect_void_op(corrector, node)
@@ -231,15 +245,23 @@ module RuboCop
231
245
  def entirely_literal?(node)
232
246
  case node.type
233
247
  when :array
234
- node.each_value.all? { |value| entirely_literal?(value) }
248
+ all_values_entirely_literal?(node)
235
249
  when :hash
236
- return false unless node.each_key.all? { |key| entirely_literal?(key) }
237
-
238
- node.each_value.all? { |value| entirely_literal?(value) }
250
+ all_keys_entirely_literal?(node) && all_values_entirely_literal?(node)
251
+ when :send, :csend
252
+ node.method?(:freeze) && node.receiver && entirely_literal?(node.receiver)
239
253
  else
240
254
  node.literal?
241
255
  end
242
256
  end
257
+
258
+ def all_keys_entirely_literal?(node)
259
+ node.each_key.all? { |key| entirely_literal?(key) }
260
+ end
261
+
262
+ def all_values_entirely_literal?(node)
263
+ node.each_value.all? { |value| entirely_literal?(value) }
264
+ end
243
265
  end
244
266
  end
245
267
  end
@@ -9,8 +9,9 @@ module RuboCop
9
9
  # The cop can be configured to ignore blocks passed to certain methods.
10
10
  #
11
11
  # You can set constructs you want to fold with `CountAsOne`.
12
- # Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
13
- # will be counted as one line regardless of its actual size.
12
+ #
13
+ # Available are: 'array', 'hash', 'heredoc', and 'method_call'.
14
+ # Each construct will be counted as one line regardless of its actual size.
14
15
  #
15
16
  # NOTE: This cop does not apply for `Struct` definitions.
16
17
  #
@@ -18,7 +19,7 @@ module RuboCop
18
19
  # for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
19
20
  # instead. By default, there are no methods to allowed.
20
21
  #
21
- # @example CountAsOne: ['array', 'heredoc', 'method_call']
22
+ # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
22
23
  #
23
24
  # something do
24
25
  # array = [ # +1
@@ -26,7 +27,7 @@ module RuboCop
26
27
  # 2
27
28
  # ]
28
29
  #
29
- # hash = { # +3
30
+ # hash = { # +1
30
31
  # key: 'value'
31
32
  # }
32
33
  #
@@ -39,7 +40,7 @@ module RuboCop
39
40
  # 1,
40
41
  # 2
41
42
  # )
42
- # end # 6 points
43
+ # end # 4 points
43
44
  #
44
45
  class BlockLength < Base
45
46
  include CodeLength
@@ -8,12 +8,13 @@ module RuboCop
8
8
  # The maximum allowed length is configurable.
9
9
  #
10
10
  # You can set constructs you want to fold with `CountAsOne`.
11
- # Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
12
- # will be counted as one line regardless of its actual size.
11
+ #
12
+ # Available are: 'array', 'hash', 'heredoc', and 'method_call'.
13
+ # Each construct will be counted as one line regardless of its actual size.
13
14
  #
14
15
  # NOTE: This cop also applies for `Struct` definitions.
15
16
  #
16
- # @example CountAsOne: ['array', 'heredoc', 'method_call']
17
+ # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
17
18
  #
18
19
  # class Foo
19
20
  # ARRAY = [ # +1
@@ -21,7 +22,7 @@ module RuboCop
21
22
  # 2
22
23
  # ]
23
24
  #
24
- # HASH = { # +3
25
+ # HASH = { # +1
25
26
  # key: 'value'
26
27
  # }
27
28
  #
@@ -34,7 +35,7 @@ module RuboCop
34
35
  # 1,
35
36
  # 2
36
37
  # )
37
- # end # 6 points
38
+ # end # 4 points
38
39
  #
39
40
  class ClassLength < Base
40
41
  include CodeLength
@@ -8,15 +8,16 @@ module RuboCop
8
8
  # The maximum allowed length is configurable.
9
9
  #
10
10
  # You can set constructs you want to fold with `CountAsOne`.
11
- # Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
12
- # will be counted as one line regardless of its actual size.
11
+ #
12
+ # Available are: 'array', 'hash', 'heredoc', and 'method_call'.
13
+ # Each construct will be counted as one line regardless of its actual size.
13
14
  #
14
15
  # NOTE: The `ExcludedMethods` and `IgnoredMethods` configuration is
15
16
  # deprecated and only kept for backwards compatibility.
16
17
  # Please use `AllowedMethods` and `AllowedPatterns` instead.
17
18
  # By default, there are no methods to allowed.
18
19
  #
19
- # @example CountAsOne: ['array', 'heredoc', 'method_call']
20
+ # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
20
21
  #
21
22
  # def m
22
23
  # array = [ # +1
@@ -24,7 +25,7 @@ module RuboCop
24
25
  # 2
25
26
  # ]
26
27
  #
27
- # hash = { # +3
28
+ # hash = { # +1
28
29
  # key: 'value'
29
30
  # }
30
31
  #
@@ -37,7 +38,7 @@ module RuboCop
37
38
  # 1,
38
39
  # 2
39
40
  # )
40
- # end # 6 points
41
+ # end # 4 points
41
42
  #
42
43
  class MethodLength < Base
43
44
  include CodeLength