rubocop 0.91.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +100 -54
  4. data/lib/rubocop.rb +10 -6
  5. data/lib/rubocop/cached_data.rb +2 -1
  6. data/lib/rubocop/cli/command/version.rb +1 -1
  7. data/lib/rubocop/comment_config.rb +9 -5
  8. data/lib/rubocop/config.rb +4 -0
  9. data/lib/rubocop/config_loader.rb +19 -2
  10. data/lib/rubocop/config_loader_resolver.rb +7 -5
  11. data/lib/rubocop/config_regeneration.rb +33 -0
  12. data/lib/rubocop/config_validator.rb +7 -6
  13. data/lib/rubocop/cop/badge.rb +9 -24
  14. data/lib/rubocop/cop/base.rb +16 -1
  15. data/lib/rubocop/cop/commissioner.rb +34 -20
  16. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
  17. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
  18. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
  19. data/lib/rubocop/cop/layout/array_alignment.rb +1 -0
  20. data/lib/rubocop/cop/layout/case_indentation.rb +4 -7
  21. data/lib/rubocop/cop/layout/class_structure.rb +8 -1
  22. data/lib/rubocop/cop/layout/dot_position.rb +6 -9
  23. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
  24. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +4 -13
  25. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +13 -8
  26. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -2
  27. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -2
  28. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +10 -1
  29. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +4 -13
  30. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
  31. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -7
  32. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
  33. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -18
  34. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -2
  35. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +2 -2
  36. data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
  37. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
  38. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
  39. data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
  40. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +23 -3
  41. data/lib/rubocop/cop/lint/duplicate_rescue_exception.rb +2 -4
  42. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
  43. data/lib/rubocop/cop/lint/identity_comparison.rb +5 -3
  44. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +2 -5
  45. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  46. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  47. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +22 -12
  48. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +14 -4
  49. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
  50. data/lib/rubocop/cop/lint/rescue_type.rb +0 -1
  51. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -6
  52. data/lib/rubocop/cop/lint/to_json.rb +1 -1
  53. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -5
  54. data/lib/rubocop/cop/lint/useless_access_modifier.rb +3 -9
  55. data/lib/rubocop/cop/lint/useless_times.rb +11 -2
  56. data/lib/rubocop/cop/metrics/block_length.rb +3 -1
  57. data/lib/rubocop/cop/metrics/class_length.rb +14 -6
  58. data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -1
  59. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +25 -16
  60. data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
  61. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  62. data/lib/rubocop/cop/mixin/rescue_node.rb +1 -0
  63. data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -3
  64. data/lib/rubocop/cop/mixin/visibility_help.rb +4 -16
  65. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  66. data/lib/rubocop/cop/offense.rb +15 -2
  67. data/lib/rubocop/cop/security/open.rb +12 -10
  68. data/lib/rubocop/cop/style/access_modifier_declarations.rb +6 -2
  69. data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
  70. data/lib/rubocop/cop/style/array_coercion.rb +4 -0
  71. data/lib/rubocop/cop/style/case_like_if.rb +20 -4
  72. data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
  73. data/lib/rubocop/cop/style/combinable_loops.rb +13 -11
  74. data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
  75. data/lib/rubocop/cop/style/commented_keyword.rb +7 -8
  76. data/lib/rubocop/cop/style/date_time.rb +12 -1
  77. data/lib/rubocop/cop/style/explicit_block_argument.rb +6 -2
  78. data/lib/rubocop/cop/style/for.rb +0 -4
  79. data/lib/rubocop/cop/style/format_string_token.rb +48 -3
  80. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +15 -6
  81. data/lib/rubocop/cop/style/if_unless_modifier.rb +0 -4
  82. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -6
  83. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -13
  84. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -11
  85. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
  86. data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
  87. data/lib/rubocop/cop/style/mixin_usage.rb +7 -27
  88. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -2
  89. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -0
  90. data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
  91. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -1
  92. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +12 -1
  93. data/lib/rubocop/cop/style/raise_args.rb +0 -3
  94. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  95. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -9
  96. data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
  97. data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
  98. data/lib/rubocop/cop/style/redundant_conditional.rb +4 -5
  99. data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
  100. data/lib/rubocop/cop/style/redundant_parentheses.rb +6 -3
  101. data/lib/rubocop/cop/style/redundant_percent_q.rb +9 -11
  102. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +39 -24
  103. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
  104. data/lib/rubocop/cop/style/redundant_return.rb +17 -17
  105. data/lib/rubocop/cop/style/redundant_self.rb +10 -9
  106. data/lib/rubocop/cop/style/redundant_sort.rb +13 -24
  107. data/lib/rubocop/cop/style/redundant_sort_by.rb +5 -9
  108. data/lib/rubocop/cop/style/rescue_standard_error.rb +20 -16
  109. data/lib/rubocop/cop/style/safe_navigation.rb +16 -4
  110. data/lib/rubocop/cop/style/string_concatenation.rb +14 -2
  111. data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -3
  112. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +4 -3
  113. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
  114. data/lib/rubocop/cop/util.rb +0 -1
  115. data/lib/rubocop/cop/variable_force/branch.rb +0 -4
  116. data/lib/rubocop/directive_comment.rb +32 -0
  117. data/lib/rubocop/ext/regexp_node.rb +20 -4
  118. data/lib/rubocop/formatter/disabled_config_formatter.rb +12 -5
  119. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  120. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  121. data/lib/rubocop/options.rb +22 -17
  122. data/lib/rubocop/result_cache.rb +8 -2
  123. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  124. data/lib/rubocop/rspec/expect_offense.rb +5 -5
  125. data/lib/rubocop/runner.rb +9 -5
  126. data/lib/rubocop/target_finder.rb +27 -26
  127. data/lib/rubocop/target_ruby.rb +1 -1
  128. data/lib/rubocop/version.rb +61 -6
  129. metadata +14 -17
  130. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
  131. data/lib/rubocop/cop/tokens_util.rb +0 -84
@@ -28,7 +28,7 @@ module RuboCop
28
28
  MSG = 'Place optional keyword parameters at the end of the parameters list.'
29
29
 
30
30
  def on_kwoptarg(node)
31
- kwarg_nodes = right_siblings_of(node).select(&:kwarg_type?)
31
+ kwarg_nodes = node.right_siblings.select(&:kwarg_type?)
32
32
  return if kwarg_nodes.empty?
33
33
 
34
34
  add_offense(node) do |corrector|
@@ -41,11 +41,6 @@ module RuboCop
41
41
 
42
42
  private
43
43
 
44
- # TODO: Use API from `rubocop-ast` when released.
45
- def right_siblings_of(node)
46
- node.parent.children[node.sibling_index + 1..-1]
47
- end
48
-
49
44
  def remove_kwargs(kwarg_nodes, corrector)
50
45
  kwarg_nodes.each do |kwarg|
51
46
  with_space = range_with_surrounding_space(range: kwarg.source_range)
@@ -144,25 +144,22 @@ module RuboCop
144
144
  # # good
145
145
  # Array 1
146
146
  class MethodCallWithArgsParentheses < Base
147
+ require_relative 'method_call_with_args_parentheses/omit_parentheses'
148
+ require_relative 'method_call_with_args_parentheses/require_parentheses'
149
+
147
150
  include ConfigurableEnforcedStyle
148
151
  include IgnoredMethods
149
152
  include IgnoredPattern
153
+ include RequireParentheses
154
+ include OmitParentheses
150
155
  extend AutoCorrector
151
156
 
152
- def initialize(*)
153
- super
154
- return unless style_configured?
155
-
156
- case style
157
- when :require_parentheses
158
- extend RequireParentheses
159
- when :omit_parentheses
160
- extend OmitParentheses
161
- end
157
+ def on_send(node)
158
+ send(style, node) # call require_parentheses or omit_parentheses
162
159
  end
163
-
164
- # @abstract Overridden in style modules
165
- def autocorrect(_node); end
160
+ alias on_csend on_send
161
+ alias on_super on_send
162
+ alias on_yield on_send
166
163
 
167
164
  private
168
165
 
@@ -7,15 +7,19 @@ module RuboCop
7
7
  # Style omit_parentheses
8
8
  module OmitParentheses
9
9
  TRAILING_WHITESPACE_REGEX = /\s+\Z/.freeze
10
+ OMIT_MSG = 'Omit parentheses for method calls with arguments.'
11
+ private_constant :OMIT_MSG
10
12
 
11
- def on_send(node)
13
+ private
14
+
15
+ def omit_parentheses(node)
12
16
  return unless node.parenthesized?
13
17
  return if node.implicit_call?
14
18
  return if super_call_without_arguments?(node)
15
19
  return if allowed_camel_case_method_call?(node)
16
20
  return if legitimate_call_with_parentheses?(node)
17
21
 
18
- add_offense(offense_range(node)) do |corrector|
22
+ add_offense(offense_range(node), message: OMIT_MSG) do |corrector|
19
23
  if parentheses_at_the_end_of_multiline_call?(node)
20
24
  corrector.replace(args_begin(node), ' \\')
21
25
  else
@@ -24,20 +28,11 @@ module RuboCop
24
28
  corrector.remove(node.loc.end)
25
29
  end
26
30
  end
27
- alias on_csend on_send
28
- alias on_super on_send
29
- alias on_yield on_send
30
-
31
- private
32
31
 
33
32
  def offense_range(node)
34
33
  node.loc.begin.join(node.loc.end)
35
34
  end
36
35
 
37
- def message(_range = nil)
38
- 'Omit parentheses for method calls with arguments.'
39
- end
40
-
41
36
  def super_call_without_arguments?(node)
42
37
  node.super_type? && node.arguments.none?
43
38
  end
@@ -6,27 +6,23 @@ module RuboCop
6
6
  class MethodCallWithArgsParentheses
7
7
  # Style require_parentheses
8
8
  module RequireParentheses
9
- def on_send(node)
9
+ REQUIRE_MSG = 'Use parentheses for method calls with arguments.'
10
+ private_constant :REQUIRE_MSG
11
+
12
+ private
13
+
14
+ def require_parentheses(node)
10
15
  return if ignored_method?(node.method_name)
11
16
  return if matches_ignored_pattern?(node.method_name)
12
17
  return if eligible_for_parentheses_omission?(node)
13
18
  return unless node.arguments? && !node.parenthesized?
14
19
 
15
- add_offense(node) do |corrector|
20
+ add_offense(node, message: REQUIRE_MSG) do |corrector|
16
21
  corrector.replace(args_begin(node), '(')
17
22
 
18
23
  corrector.insert_after(args_end(node), ')') unless args_parenthesized?(node)
19
24
  end
20
25
  end
21
- alias on_csend on_send
22
- alias on_super on_send
23
- alias on_yield on_send
24
-
25
- def message(_node = nil)
26
- 'Use parentheses for method calls with arguments.'
27
- end
28
-
29
- private
30
26
 
31
27
  def eligible_for_parentheses_omission?(node)
32
28
  node.operator_method? || node.setter_method? || ignored_macro?(node)
@@ -140,16 +140,12 @@ module RuboCop
140
140
  def missing_parentheses(node)
141
141
  location = node.arguments.source_range
142
142
 
143
- return unless unexpected_style_detected(:require_no_parentheses)
144
-
145
143
  add_offense(location, message: MSG_MISSING) do |corrector|
146
144
  correct_definition(node, corrector)
147
145
  end
148
146
  end
149
147
 
150
148
  def unwanted_parentheses(args)
151
- return unless unexpected_style_detected(:require_parentheses)
152
-
153
149
  add_offense(args, message: MSG_PRESENT) do |corrector|
154
150
  # offense is registered on args node when parentheses are unwanted
155
151
  correct_arguments(args, corrector)
@@ -50,41 +50,21 @@ module RuboCop
50
50
  const)
51
51
  PATTERN
52
52
 
53
- def_node_matcher :wrapped_macro_scope?, <<~PATTERN
54
- {({sclass class module block} ... ({begin if} ...))}
53
+ def_node_matcher :in_top_level_scope?, <<~PATTERN
54
+ {
55
+ root? # either at the top level
56
+ ^[ {kwbegin begin if def} # or wrapped within one of these
57
+ #in_top_level_scope? ] # that is in top level scope
58
+ }
55
59
  PATTERN
56
60
 
57
61
  def on_send(node)
58
62
  include_statement(node) do |statement|
59
- return if node.argument? ||
60
- accepted_include?(node) ||
61
- belongs_to_class_or_module?(node)
63
+ return unless in_top_level_scope?(node)
62
64
 
63
65
  add_offense(node, message: format(MSG, statement: statement))
64
66
  end
65
67
  end
66
-
67
- private
68
-
69
- def accepted_include?(node)
70
- node.parent && (node.macro? || ascend_macro_scope?(node.parent))
71
- end
72
-
73
- def ascend_macro_scope?(ancestor)
74
- return true if wrapped_macro_scope?(ancestor)
75
-
76
- ancestor.parent && ascend_macro_scope?(ancestor.parent)
77
- end
78
-
79
- def belongs_to_class_or_module?(node)
80
- if !node.parent
81
- false
82
- else
83
- return true if node.parent.class_type? || node.parent.module_type?
84
-
85
- belongs_to_class_or_module?(node.parent)
86
- end
87
- end
88
68
  end
89
69
  end
90
70
  end
@@ -22,7 +22,7 @@ module RuboCop
22
22
  # alive_threads.map do |t|
23
23
  # t.object_id
24
24
  # end
25
- class MultilineBlockChain < Cop
25
+ class MultilineBlockChain < Base
26
26
  include RangeHelp
27
27
 
28
28
  MSG = 'Avoid multi-line chains of blocks.'
@@ -36,7 +36,7 @@ module RuboCop
36
36
  range = range_between(receiver.loc.end.begin_pos,
37
37
  node.send_node.source_range.end_pos)
38
38
 
39
- add_offense(nil, location: range)
39
+ add_offense(range)
40
40
 
41
41
  # Done. If there are more blocks in the chain, they will be
42
42
  # found by subsequent calls to on_block.
@@ -58,6 +58,7 @@ module RuboCop
58
58
  private
59
59
 
60
60
  def require_then?(when_node)
61
+ return true if when_node.conditions.count >= 2
61
62
  return false unless when_node.body
62
63
 
63
64
  when_node.loc.line == when_node.body.loc.line
@@ -49,6 +49,8 @@ module RuboCop
49
49
  end
50
50
 
51
51
  def remove_parentheses(source)
52
+ return source unless source.start_with?('(')
53
+
52
54
  source.gsub(/\A\(/, '').gsub(/\)\z/, '')
53
55
  end
54
56
  end
@@ -89,7 +89,9 @@ module RuboCop
89
89
  end
90
90
 
91
91
  def else_branch_to_multiline(else_branch, indentation)
92
- if else_branch.if_type? && else_branch.elsif?
92
+ if else_branch.nil?
93
+ 'end'
94
+ elsif else_branch.if_type? && else_branch.elsif?
93
95
  multiline_replacement(else_branch, indentation)
94
96
  else
95
97
  <<~RUBY.chomp
@@ -4,7 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # This cop checks for places where keyword arguments can be used instead of
7
- # boolean arguments when defining methods.
7
+ # boolean arguments when defining methods. `respond_to_missing?` method is allowed by default.
8
+ # These are customizable with `AllowedMethods` option.
8
9
  #
9
10
  # @example
10
11
  # # bad
@@ -23,11 +24,21 @@ module RuboCop
23
24
  # puts bar
24
25
  # end
25
26
  #
27
+ # @example AllowedMethods: ['some_method']
28
+ # # good
29
+ # def some_method(bar = false)
30
+ # puts bar
31
+ # end
32
+ #
26
33
  class OptionalBooleanParameter < Base
34
+ include AllowedMethods
35
+
27
36
  MSG = 'Use keyword arguments when defining method with boolean argument.'
28
37
  BOOLEAN_TYPES = %i[true false].freeze
29
38
 
30
39
  def on_def(node)
40
+ return if allowed_method?(node.method_name)
41
+
31
42
  node.arguments.each do |arg|
32
43
  next unless arg.optarg_type?
33
44
 
@@ -84,8 +84,6 @@ module RuboCop
84
84
 
85
85
  def check_compact(node)
86
86
  if node.arguments.size > 1
87
- return unless opposite_style_detected
88
-
89
87
  add_offense(node, message: format(COMPACT_MSG, method: node.method_name)) do |corrector|
90
88
  replacement = correction_exploded_to_compact(node)
91
89
 
@@ -103,7 +101,6 @@ module RuboCop
103
101
 
104
102
  return unless first_arg.send_type? && first_arg.method?(:new)
105
103
  return if acceptable_exploded_args?(first_arg.arguments)
106
- return unless opposite_style_detected
107
104
 
108
105
  add_offense(node, message: format(EXPLODED_MSG, method: node.method_name)) do |corrector|
109
106
  replacement = correction_compact_to_exploded(node)
@@ -36,7 +36,7 @@ module RuboCop
36
36
  (send
37
37
  {nil? (const {nil? cbase} :Random) (const {nil? cbase} :Kernel)}
38
38
  :rand
39
- {int irange erange}))
39
+ {int (irange int int) (erange int int)}))
40
40
  PATTERN
41
41
 
42
42
  def_node_matcher :rand_op_integer?, <<~PATTERN
@@ -44,7 +44,7 @@ module RuboCop
44
44
  (send
45
45
  {nil? (const {nil? cbase} :Random) (const {nil? cbase} :Kernel)}
46
46
  :rand
47
- {int irange erange})
47
+ {int (irange int int) (erange int int)})
48
48
  {:+ :-}
49
49
  int)
50
50
  PATTERN
@@ -54,7 +54,7 @@ module RuboCop
54
54
  (send
55
55
  {nil? (const {nil? cbase} :Random) (const {nil? cbase} :Kernel)}
56
56
  :rand
57
- {int irange erange})
57
+ {int (irange int int) (erange int int)})
58
58
  {:succ :pred :next})
59
59
  PATTERN
60
60
 
@@ -94,21 +94,13 @@ module RuboCop
94
94
  add_offense(assignment) do |corrector|
95
95
  expression = assignment.children[1]
96
96
  corrector.replace(assignment, expression.source)
97
- corrector.remove(right_sibling_of(assignment))
97
+ corrector.remove(assignment.right_sibling)
98
98
  end
99
99
  else
100
100
  last_expr = node.children.last
101
101
  check_branch(last_expr)
102
102
  end
103
103
  end
104
-
105
- def right_sibling_of(node)
106
- siblings_of(node)[node.sibling_index + 1]
107
- end
108
-
109
- def siblings_of(node)
110
- node.parent.children
111
- end
112
104
  end
113
105
  end
114
106
  end
@@ -28,6 +28,14 @@ module RuboCop
28
28
  # end
29
29
  #
30
30
  # # bad
31
+ # begin
32
+ # do_something
33
+ # end
34
+ #
35
+ # # good
36
+ # do_something
37
+ #
38
+ # # bad
31
39
  # # When using Ruby 2.5 or later.
32
40
  # do_something do
33
41
  # begin
@@ -60,7 +68,9 @@ module RuboCop
60
68
  MSG = 'Redundant `begin` block detected.'
61
69
 
62
70
  def on_def(node)
63
- check(node)
71
+ return unless node.body&.kwbegin_type?
72
+
73
+ register_offense(node.body)
64
74
  end
65
75
  alias on_defs on_def
66
76
 
@@ -69,20 +79,38 @@ module RuboCop
69
79
 
70
80
  return if node.send_node.lambda_literal?
71
81
  return if node.braces?
82
+ return unless node.body&.kwbegin_type?
72
83
 
73
- check(node)
84
+ register_offense(node.body)
74
85
  end
75
86
 
76
- private
87
+ def on_kwbegin(node)
88
+ return if contain_rescue_or_ensure?(node) || valid_context_using_only_begin?(node)
77
89
 
78
- def check(node)
79
- return unless node.body&.kwbegin_type?
90
+ register_offense(node)
91
+ end
92
+
93
+ private
80
94
 
81
- add_offense(node.body.loc.begin) do |corrector|
82
- corrector.remove(node.body.loc.begin)
83
- corrector.remove(node.body.loc.end)
95
+ def register_offense(node)
96
+ add_offense(node.loc.begin) do |corrector|
97
+ corrector.remove(node.loc.begin)
98
+ corrector.remove(node.loc.end)
84
99
  end
85
100
  end
101
+
102
+ def contain_rescue_or_ensure?(node)
103
+ first_child = node.children.first
104
+
105
+ first_child.rescue_type? || first_child.ensure_type?
106
+ end
107
+
108
+ def valid_context_using_only_begin?(node)
109
+ parent = node.parent
110
+
111
+ node.each_ancestor.any?(&:assignment?) || parent&.post_condition_loop? ||
112
+ parent&.send_type? || parent&.operator_keyword?
113
+ end
86
114
  end
87
115
  end
88
116
  end
@@ -75,7 +75,7 @@ module RuboCop
75
75
  def offense?(node)
76
76
  condition, if_branch, else_branch = *node
77
77
 
78
- return false if use_if_branch?(else_branch)
78
+ return false if use_if_branch?(else_branch) || use_hash_key_assignment?(else_branch)
79
79
 
80
80
  condition == if_branch && !node.elsif? && (
81
81
  node.ternary? ||
@@ -88,6 +88,10 @@ module RuboCop
88
88
  else_branch&.if_type?
89
89
  end
90
90
 
91
+ def use_hash_key_assignment?(else_branch)
92
+ else_branch&.send_type? && else_branch&.method?(:[]=)
93
+ end
94
+
91
95
  def else_source(else_branch)
92
96
  if require_parentheses?(else_branch)
93
97
  "(#{else_branch.source})"
@@ -24,8 +24,9 @@ module RuboCop
24
24
  #
25
25
  # # good
26
26
  # x != y
27
- class RedundantConditional < Cop
27
+ class RedundantConditional < Base
28
28
  include Alignment
29
+ extend AutoCorrector
29
30
 
30
31
  operators = RuboCop::AST::Node::COMPARISON_OPERATORS.to_a
31
32
  COMPARISON_OPERATOR_MATCHER = "{:#{operators.join(' :')}}"
@@ -36,11 +37,9 @@ module RuboCop
36
37
  def on_if(node)
37
38
  return unless offense?(node)
38
39
 
39
- add_offense(node)
40
- end
40
+ message = message(node)
41
41
 
42
- def autocorrect(node)
43
- lambda do |corrector|
42
+ add_offense(node, message: message) do |corrector|
44
43
  corrector.replace(node, replacement_condition(node))
45
44
  end
46
45
  end