rubocop 1.72.1 → 1.73.1

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/config/default.yml +26 -11
  4. data/config/internal_affairs.yml +16 -0
  5. data/lib/rubocop/config_loader_resolver.rb +2 -2
  6. data/lib/rubocop/config_validator.rb +1 -1
  7. data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -2
  8. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  9. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +26 -1
  10. data/lib/rubocop/cop/layout/line_length.rb +3 -3
  11. data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -14
  12. data/lib/rubocop/cop/lint/empty_conditional_body.rb +10 -5
  13. data/lib/rubocop/cop/lint/float_comparison.rb +1 -6
  14. data/lib/rubocop/cop/lint/literal_as_condition.rb +99 -9
  15. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
  16. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  17. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +23 -2
  18. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +7 -1
  19. data/lib/rubocop/cop/lint/void.rb +6 -0
  20. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  21. data/lib/rubocop/cop/mixin/hash_subset.rb +19 -4
  22. data/lib/rubocop/cop/mixin/trailing_comma.rb +12 -0
  23. data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
  24. data/lib/rubocop/cop/naming/variable_name.rb +64 -6
  25. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  26. data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -3
  27. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  28. data/lib/rubocop/cop/style/endless_method.rb +163 -18
  29. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  30. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -1
  31. data/lib/rubocop/cop/style/redundant_condition.rb +46 -0
  32. data/lib/rubocop/cop/style/redundant_format.rb +39 -11
  33. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -3
  34. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
  35. data/lib/rubocop/cop/style/single_line_methods.rb +3 -3
  36. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  37. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  38. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  39. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  40. data/lib/rubocop/cops_documentation_generator.rb +12 -1
  41. data/lib/rubocop/plugin/configuration_integrator.rb +2 -0
  42. data/lib/rubocop/plugin/load_error.rb +1 -1
  43. data/lib/rubocop/plugin.rb +9 -2
  44. data/lib/rubocop/rspec/cop_helper.rb +2 -0
  45. data/lib/rubocop/rspec/shared_contexts.rb +15 -0
  46. data/lib/rubocop/rspec/support.rb +1 -0
  47. data/lib/rubocop/version.rb +1 -1
  48. data/lib/rubocop.rb +0 -1
  49. metadata +4 -5
  50. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9909c26bded9ccffc98132b899b68773a19b0e1259d834d2cd147abf2ca8534e
4
- data.tar.gz: d6e58861b573240488aebcdaab3ec984a8c6fe75fd0da8cb51bfa8be3c4469ba
3
+ metadata.gz: a4215b7d095dfd177a36af3bdf5d5aecd786877a6feca3480078d9cb1a5917ad
4
+ data.tar.gz: fc20be6f63f1a0e3c06cd2fc13f8619f872e9a81642dfa833f90f88f70997857
5
5
  SHA512:
6
- metadata.gz: 235ed1dea8218bf39fff25ebcb297391ced4a9aeb4c582979711c095958c0aaab44dcead59108f7463f0f0d7da046b4b9f88be0be4016bdc369259ef89c37162
7
- data.tar.gz: b80078b908cbf8b75b0b9b047e7806521a65ca83cce802b38172d946cc625ffdd9bc255f91b1eba6e22d42670fee6aaa7d1ef2a81653a39ee1b1e869a7d0797b
6
+ metadata.gz: aee7de1fa54b8b7108f5ad7f29c3fbc1818547f28507010dca91adc0f648b02ce519c96846d2ad98407d8f8847047cd8f88547e7d5c81028d0f54cfafb44500b
7
+ data.tar.gz: afc90ab7e887e183ddfac0bf49e9f644c04564e7fd605423d29f2848f6cc509f2394fd642eccd8870d105b21055a5cb4d0dea051b92ba47ef3befbf5b7d3dad5
data/README.md CHANGED
@@ -52,7 +52,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
52
52
  in your `Gemfile`:
53
53
 
54
54
  ```rb
55
- gem 'rubocop', '~> 1.72', require: false
55
+ gem 'rubocop', '~> 1.73', require: false
56
56
  ```
57
57
 
58
58
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
@@ -241,9 +241,9 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
241
241
  <a href="https://opencollective.com/rubocop/organization/28/website" target="_blank"><img src="https://opencollective.com/rubocop/organization/28/avatar.svg"></a>
242
242
  <a href="https://opencollective.com/rubocop/organization/29/website" target="_blank"><img src="https://opencollective.com/rubocop/organization/29/avatar.svg"></a>
243
243
 
244
- ## Changelog
244
+ ## Release Notes
245
245
 
246
- RuboCop's changelog is available [here](CHANGELOG.md).
246
+ RuboCop's release notes are available [here](https://github.com/rubocop/rubocop/releases).
247
247
 
248
248
  ## Copyright
249
249
 
data/config/default.yml CHANGED
@@ -2046,6 +2046,7 @@ Lint/LambdaWithoutLiteralBlock:
2046
2046
  Lint/LiteralAsCondition:
2047
2047
  Description: 'Checks of literals used in conditions.'
2048
2048
  Enabled: true
2049
+ AutoCorrect: contextual
2049
2050
  VersionAdded: '0.51'
2050
2051
 
2051
2052
  Lint/LiteralAssignmentInCondition:
@@ -2259,9 +2260,8 @@ Lint/RedundantRegexpQuantifiers:
2259
2260
  Lint/RedundantRequireStatement:
2260
2261
  Description: 'Checks for unnecessary `require` statement.'
2261
2262
  Enabled: true
2262
- SafeAutoCorrect: false
2263
2263
  VersionAdded: '0.76'
2264
- VersionChanged: '1.57'
2264
+ VersionChanged: '1.73'
2265
2265
 
2266
2266
  Lint/RedundantSafeNavigation:
2267
2267
  Description: 'Checks for redundant safe navigation calls.'
@@ -3081,13 +3081,15 @@ Naming/VariableName:
3081
3081
  StyleGuide: '#snake-case-symbols-methods-vars'
3082
3082
  Enabled: true
3083
3083
  VersionAdded: '0.50'
3084
- VersionChanged: '1.8'
3084
+ VersionChanged: '1.73'
3085
3085
  EnforcedStyle: snake_case
3086
3086
  SupportedStyles:
3087
3087
  - snake_case
3088
3088
  - camelCase
3089
3089
  AllowedIdentifiers: []
3090
3090
  AllowedPatterns: []
3091
+ ForbiddenIdentifiers: []
3092
+ ForbiddenPatterns: []
3091
3093
 
3092
3094
  Naming/VariableNumber:
3093
3095
  Description: 'Use the configured style when numbering symbols, methods and variables.'
@@ -3922,6 +3924,8 @@ Style/EndlessMethod:
3922
3924
  - allow_single_line
3923
3925
  - allow_always
3924
3926
  - disallow
3927
+ - require_single_line
3928
+ - require_always
3925
3929
 
3926
3930
  Style/EnvHome:
3927
3931
  Description: "Checks for consistent usage of `ENV['HOME']`."
@@ -5104,6 +5108,9 @@ Style/RedundantCondition:
5104
5108
  Description: 'Checks for unnecessary conditional expressions.'
5105
5109
  Enabled: true
5106
5110
  VersionAdded: '0.76'
5111
+ VersionChanged: '1.73'
5112
+ AllowedMethods:
5113
+ - nonzero?
5107
5114
 
5108
5115
  Style/RedundantConditional:
5109
5116
  Description: "Don't return true/false from a conditional."
@@ -5171,7 +5178,9 @@ Style/RedundantFilterChain:
5171
5178
  Style/RedundantFormat:
5172
5179
  Description: 'Checks for usages of `Kernel#format` or `Kernel#sprintf` with only a single argument.'
5173
5180
  Enabled: pending
5181
+ SafeAutoCorrect: false
5174
5182
  VersionAdded: '1.72'
5183
+ VersionChanged: '1.72'
5175
5184
 
5176
5185
  Style/RedundantFreeze:
5177
5186
  Description: "Checks usages of Object#freeze on immutable objects."
@@ -5699,14 +5708,17 @@ Style/TrailingCommaInArrayLiteral:
5699
5708
  StyleGuide: '#no-trailing-array-commas'
5700
5709
  Enabled: true
5701
5710
  VersionAdded: '0.53'
5702
- # If `comma`, the cop requires a comma after the last item in an array,
5703
- # but only when each item is on its own line.
5704
- # If `consistent_comma`, the cop requires a comma after the last item of all
5705
- # non-empty, multiline array literals.
5711
+ # If `comma`, the cop requires a comma after the last item in an array, but only when each item is
5712
+ # on its own line.
5713
+ # If `consistent_comma`, the cop requires a comma after the last item of all non-empty, multiline
5714
+ # array literals.
5715
+ # If `diff_comma`, the cop requires a comma after the last item of all non-empty, multiline array
5716
+ # literals, but only when that last item immediately precedes a newline.
5706
5717
  EnforcedStyleForMultiline: no_comma
5707
5718
  SupportedStylesForMultiline:
5708
5719
  - comma
5709
5720
  - consistent_comma
5721
+ - diff_comma
5710
5722
  - no_comma
5711
5723
 
5712
5724
  Style/TrailingCommaInBlockArgs:
@@ -5718,14 +5730,17 @@ Style/TrailingCommaInBlockArgs:
5718
5730
  Style/TrailingCommaInHashLiteral:
5719
5731
  Description: 'Checks for trailing comma in hash literals.'
5720
5732
  Enabled: true
5721
- # If `comma`, the cop requires a comma after the last item in a hash,
5722
- # but only when each item is on its own line.
5723
- # If `consistent_comma`, the cop requires a comma after the last item of all
5724
- # non-empty, multiline hash literals.
5733
+ # If `comma`, the cop requires a comma after the last item in a hash, but only when each item is
5734
+ # on its own line.
5735
+ # If `consistent_comma`, the cop requires a comma after the last item of all non-empty, multiline
5736
+ # hash literals.
5737
+ # If `diff_comma`, the cop requires a comma after the last item of all non-empty, multiline hash
5738
+ # literals, but only when that last item immediately precedes a newline.
5725
5739
  EnforcedStyleForMultiline: no_comma
5726
5740
  SupportedStylesForMultiline:
5727
5741
  - comma
5728
5742
  - consistent_comma
5743
+ - diff_comma
5729
5744
  - no_comma
5730
5745
  VersionAdded: '0.53'
5731
5746
 
@@ -6,6 +6,22 @@ InternalAffairs/CopDescription:
6
6
  Include:
7
7
  - 'lib/rubocop/cop/**/*.rb'
8
8
 
9
+ InternalAffairs/ExampleHeredocDelimiter:
10
+ Include:
11
+ - 'spec/rubocop/cop/**/*.rb'
12
+
13
+ InternalAffairs/ExampleDescription:
14
+ Include:
15
+ - 'spec/rubocop/cop/**/*.rb'
16
+
17
+ InternalAffairs/OnSendWithoutOnCSend:
18
+ Include:
19
+ - 'lib/rubocop/cop/**/*.rb'
20
+
21
+ InternalAffairs/UndefinedConfig:
22
+ Include:
23
+ - 'lib/rubocop/cop/**/*.rb'
24
+
9
25
  InternalAffairs/UselessMessageAssertion:
10
26
  Include:
11
27
  - '**/*_spec.rb'
@@ -123,7 +123,7 @@ module RuboCop
123
123
  elsif merge_hashes?(base_hash, derived_hash, key)
124
124
  result[key] = merge(base_hash[key], derived_hash[key], **opts)
125
125
  elsif should_union?(derived_hash, base_hash, opts[:inherit_mode], key)
126
- result[key] = base_hash[key] | derived_hash[key]
126
+ result[key] = Array(base_hash[key]) | Array(derived_hash[key])
127
127
  elsif opts[:debug]
128
128
  warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
129
129
  end
@@ -205,7 +205,7 @@ module RuboCop
205
205
  end
206
206
 
207
207
  def should_union?(derived_hash, base_hash, root_mode, key)
208
- return false unless base_hash[key].is_a?(Array)
208
+ return false unless base_hash[key].is_a?(Array) || derived_hash[key].is_a?(Array)
209
209
 
210
210
  derived_mode = derived_hash['inherit_mode']
211
211
  return false if should_override?(derived_mode, key)
@@ -9,7 +9,7 @@ module RuboCop
9
9
 
10
10
  # @api private
11
11
  COMMON_PARAMS = %w[Exclude Include Severity inherit_mode AutoCorrect StyleGuide Details
12
- Enabled].freeze
12
+ Enabled Reference].freeze
13
13
  # @api private
14
14
  INTERNAL_PARAMS = %w[Description StyleGuide
15
15
  VersionAdded VersionChanged VersionRemoved
@@ -90,8 +90,10 @@ module RuboCop
90
90
  description_text = string_contents(current_description)
91
91
  return unless (new_description = correct_description(description_text, description_map))
92
92
 
93
+ quote = current_description.dstr_type? ? '"' : "'"
94
+
93
95
  add_offense(current_description, message: message) do |corrector|
94
- corrector.replace(current_description, "'#{new_description}'")
96
+ corrector.replace(current_description, "#{quote}#{new_description}#{quote}")
95
97
  end
96
98
  end
97
99
 
@@ -106,7 +108,7 @@ module RuboCop
106
108
  end
107
109
 
108
110
  def string_contents(node)
109
- node.str_type? ? node.value : node.source
111
+ node.type?(:str, :dstr) ? node.value : node.source
110
112
  end
111
113
  end
112
114
  end
@@ -155,10 +155,10 @@ module RuboCop
155
155
  end
156
156
 
157
157
  def all_elements_aligned?(elements)
158
- elements.flat_map do |e|
159
- if e.hash_type?
160
- e.each_child_node.map { |child| child.loc.column }
161
- else
158
+ if elements.first.hash_type?
159
+ elements.first.each_child_node.map { |child| child.loc.column }
160
+ else
161
+ elements.flat_map do |e|
162
162
  e.loc.column
163
163
  end
164
164
  end.uniq.count == 1
@@ -93,7 +93,7 @@ module RuboCop
93
93
  add_offense(node, message: message) do |corrector|
94
94
  line = range_by_whole_lines(node.source_range)
95
95
 
96
- corrector.insert_before(line, "\n") unless previous_line_empty?(node.first_line)
96
+ corrector.insert_before(line, "\n") if should_insert_line_before?(node)
97
97
 
98
98
  correct_next_line_if_denied_style(corrector, node, line)
99
99
  end
@@ -122,6 +122,8 @@ module RuboCop
122
122
  end
123
123
 
124
124
  def correct_next_line_if_denied_style(corrector, node, line)
125
+ return unless should_insert_line_after?(node)
126
+
125
127
  case style
126
128
  when :around
127
129
  corrector.insert_after(line, "\n") unless next_line_empty?(node.last_line)
@@ -205,6 +207,29 @@ module RuboCop
205
207
  format(MSG_BEFORE_FOR_ONLY_BEFORE, modifier: modifier)
206
208
  end
207
209
  end
210
+
211
+ def should_insert_line_before?(node)
212
+ return false if previous_line_empty?(node.first_line)
213
+ return true unless inside_block?(node) && no_empty_lines_around_block_body?
214
+ return true unless node.parent.begin_type?
215
+
216
+ node.parent.children.first != node
217
+ end
218
+
219
+ def should_insert_line_after?(node)
220
+ return true unless inside_block?(node) && no_empty_lines_around_block_body?
221
+
222
+ node.parent.children.last != node
223
+ end
224
+
225
+ def inside_block?(node)
226
+ node.parent.block_type? || (node.parent.begin_type? && node.parent.parent&.block_type?)
227
+ end
228
+
229
+ def no_empty_lines_around_block_body?
230
+ config.for_enabled_cop('Layout/EmptyLinesAroundBlockBody')['EnforcedStyle'] ==
231
+ 'no_empty_lines'
232
+ end
208
233
  end
209
234
  end
210
235
  end
@@ -209,7 +209,7 @@ module RuboCop
209
209
  # are not bisected.
210
210
  # If the string contains spaces, use them to determine a place for a clean break;
211
211
  # otherwise, the string will be broken at the line length limit.
212
- def breakable_string_range(node) # rubocop:disable Metrics/AbcSize
212
+ def breakable_string_range(node)
213
213
  source_range = node.source_range
214
214
  relevant_substr = largest_possible_string(node)
215
215
 
@@ -221,13 +221,13 @@ module RuboCop
221
221
  adjustment = max - source_range.last_column - 3
222
222
  return if adjustment.abs > source_range.size
223
223
 
224
- source_range.adjust(end_pos: max - source_range.last_column - 3)
224
+ source_range.adjust(end_pos: adjustment)
225
225
  end
226
226
  end
227
227
 
228
228
  def breakable_dstr_begin_position(node)
229
229
  source_range = node.source_range
230
- source_range.begin_pos if source_range.begin_pos < max && source_range.end_pos >= max
230
+ source_range.begin_pos if source_range.column < max && source_range.last_column >= max
231
231
  end
232
232
 
233
233
  def breakable_range_by_line_index
@@ -54,14 +54,12 @@ module RuboCop
54
54
  # if a method definition is inside an if, it is very likely
55
55
  # that a different definition is used depending on platform, etc.
56
56
  return if node.each_ancestor.any?(&:if_type?)
57
- return if possible_dsl?(node)
58
57
 
59
58
  found_instance_method(node, node.method_name)
60
59
  end
61
60
 
62
61
  def on_defs(node)
63
62
  return if node.each_ancestor.any?(&:if_type?)
64
- return if possible_dsl?(node)
65
63
 
66
64
  if node.receiver.const_type?
67
65
  _, const_name = *node.receiver
@@ -79,7 +77,6 @@ module RuboCop
79
77
  def on_alias(node)
80
78
  return unless (name = method_alias?(node))
81
79
  return if node.ancestors.any?(&:if_type?)
82
- return if possible_dsl?(node)
83
80
 
84
81
  found_instance_method(node, name)
85
82
  end
@@ -94,7 +91,6 @@ module RuboCop
94
91
  def on_send(node)
95
92
  if (name = alias_method?(node))
96
93
  return if node.ancestors.any?(&:if_type?)
97
- return if possible_dsl?(node)
98
94
 
99
95
  found_instance_method(node, name)
100
96
  elsif (attr = node.attribute_accessor?)
@@ -237,16 +233,6 @@ module RuboCop
237
233
  end
238
234
  end
239
235
 
240
- def possible_dsl?(node)
241
- # DSL methods may evaluate a block in the context of a newly created
242
- # class or module
243
- # Assume that if a method definition is inside any block call which
244
- # we can't identify, it could be a DSL
245
- node.each_ancestor(:block).any? do |ancestor|
246
- !ancestor.method?(:class_eval) && !ancestor.class_constructor?
247
- end
248
- end
249
-
250
236
  def source_location(node)
251
237
  range = node.source_range
252
238
  path = smart_path(range.source_buffer.name)
@@ -67,7 +67,6 @@ module RuboCop
67
67
 
68
68
  MSG = 'Avoid `%<keyword>s` branches without a body.'
69
69
 
70
- # rubocop:disable Metrics/AbcSize
71
70
  def on_if(node)
72
71
  return if node.body || same_line?(node.loc.begin, node.loc.end)
73
72
  return if cop_config['AllowComments'] && contains_comments?(node)
@@ -75,15 +74,21 @@ module RuboCop
75
74
  range = offense_range(node)
76
75
 
77
76
  add_offense(range, message: format(MSG, keyword: node.keyword)) do |corrector|
78
- next if node.parent&.call_type?
79
-
80
- autocorrect(corrector, node)
77
+ autocorrect(corrector, node) if do_autocorrect?(node)
81
78
  end
82
79
  end
83
- # rubocop:enable Metrics/AbcSize
84
80
 
85
81
  private
86
82
 
83
+ def do_autocorrect?(node)
84
+ # if condition; end.do_something
85
+ return false if (parent = node.parent)&.call_type?
86
+ # x = if condition; end
87
+ return false if (parent&.assignment? || parent&.operator_keyword?) && node.children.one?
88
+
89
+ true
90
+ end
91
+
87
92
  def offense_range(node)
88
93
  if node.loc.else
89
94
  node.source_range.begin.join(node.loc.else.begin)
@@ -81,21 +81,16 @@ module RuboCop
81
81
  (node.numeric_type? && node.value.zero?) || node.nil_type?
82
82
  end
83
83
 
84
- # rubocop:disable Metrics/PerceivedComplexity
85
84
  def check_send(node)
86
85
  if node.arithmetic_operation?
87
86
  float?(node.receiver) || float?(node.first_argument)
88
87
  elsif FLOAT_RETURNING_METHODS.include?(node.method_name)
89
88
  true
90
89
  elsif node.receiver&.float_type?
91
- if FLOAT_INSTANCE_METHODS.include?(node.method_name)
92
- true
93
- else
90
+ FLOAT_INSTANCE_METHODS.include?(node.method_name) ||
94
91
  check_numeric_returning_method(node)
95
- end
96
92
  end
97
93
  end
98
- # rubocop:enable Metrics/PerceivedComplexity
99
94
 
100
95
  def check_numeric_returning_method(node)
101
96
  return false unless node.receiver
@@ -18,12 +18,15 @@ module RuboCop
18
18
  # end
19
19
  #
20
20
  # # bad
21
- # if some_var && true
21
+ # # We're only interested in the left hand side being a truthy literal,
22
+ # # because it affects the evaluation of the &&, whereas the right hand
23
+ # # side will be conditionally executed/called and can be a literal.
24
+ # if true && some_var
22
25
  # do_something
23
26
  # end
24
27
  #
25
28
  # # good
26
- # if some_var && some_condition
29
+ # if some_var
27
30
  # do_something
28
31
  # end
29
32
  #
@@ -34,27 +37,90 @@ module RuboCop
34
37
  # end
35
38
  class LiteralAsCondition < Base
36
39
  include RangeHelp
40
+ extend AutoCorrector
37
41
 
38
42
  MSG = 'Literal `%<literal>s` appeared as a condition.'
39
43
  RESTRICT_ON_SEND = [:!].freeze
40
44
 
45
+ def on_and(node)
46
+ return unless node.lhs.truthy_literal?
47
+
48
+ add_offense(node.lhs) do |corrector|
49
+ corrector.replace(node, node.rhs.source)
50
+ end
51
+ end
52
+
41
53
  def on_if(node)
42
- check_for_literal(node)
54
+ cond = condition(node)
55
+
56
+ if node.unless?
57
+ correct_if_node(node, cond, true) if cond.falsey_literal?
58
+ correct_if_node(node, cond, false) if cond.truthy_literal?
59
+ else
60
+ correct_if_node(node, cond, true) if cond.truthy_literal?
61
+ correct_if_node(node, cond, false) if cond.falsey_literal?
62
+ end
43
63
  end
44
64
 
45
65
  def on_while(node)
46
- return if condition(node).true_type?
66
+ return if node.condition.source == 'true'
47
67
 
48
- check_for_literal(node)
68
+ if node.condition.truthy_literal?
69
+ add_offense(node.condition) do |corrector|
70
+ corrector.replace(node.condition, 'true')
71
+ end
72
+ elsif node.condition.falsey_literal?
73
+ add_offense(node.condition) do |corrector|
74
+ corrector.remove(node)
75
+ end
76
+ end
77
+ end
78
+
79
+ # rubocop:disable Metrics/AbcSize
80
+ def on_while_post(node)
81
+ return if node.condition.source == 'true'
82
+
83
+ if node.condition.truthy_literal?
84
+ add_offense(node.condition) do |corrector|
85
+ corrector.replace(node, node.source.sub(node.condition.source, 'true'))
86
+ end
87
+ elsif node.condition.falsey_literal?
88
+ add_offense(node.condition) do |corrector|
89
+ corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
90
+ end
91
+ end
49
92
  end
50
- alias on_while_post on_while
93
+ # rubocop:enable Metrics/AbcSize
51
94
 
52
95
  def on_until(node)
53
- return if condition(node).false_type?
96
+ return if node.condition.source == 'false'
54
97
 
55
- check_for_literal(node)
98
+ if node.condition.falsey_literal?
99
+ add_offense(node.condition) do |corrector|
100
+ corrector.replace(node.condition, 'false')
101
+ end
102
+ elsif node.condition.truthy_literal?
103
+ add_offense(node.condition) do |corrector|
104
+ corrector.remove(node)
105
+ end
106
+ end
107
+ end
108
+
109
+ # rubocop:disable Metrics/AbcSize
110
+ def on_until_post(node)
111
+ return if node.condition.source == 'false'
112
+
113
+ if node.condition.falsey_literal?
114
+ add_offense(node.condition) do |corrector|
115
+ corrector.replace(node, node.source.sub(node.condition.source, 'false'))
116
+ end
117
+ elsif node.condition.truthy_literal?
118
+ add_offense(node.condition) do |corrector|
119
+ corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
120
+ end
121
+ end
56
122
  end
57
- alias on_until_post on_until
123
+ # rubocop:enable Metrics/AbcSize
58
124
 
59
125
  def on_case(case_node)
60
126
  if case_node.condition
@@ -130,6 +196,8 @@ module RuboCop
130
196
 
131
197
  def handle_node(node)
132
198
  if node.literal?
199
+ return if node.parent.and_type?
200
+
133
201
  add_offense(node)
134
202
  elsif %i[send and or begin].include?(node.type)
135
203
  check_node(node)
@@ -159,6 +227,28 @@ module RuboCop
159
227
  when_node.conditions.last.source_range.end_pos
160
228
  )
161
229
  end
230
+
231
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
232
+ def correct_if_node(node, cond, result)
233
+ if result
234
+ add_offense(cond) do |corrector|
235
+ corrector.replace(node, node.if_branch.source)
236
+ end
237
+ elsif node.elsif_conditional?
238
+ add_offense(cond) do |corrector|
239
+ corrector.replace(node, "#{node.else_branch.source.sub('elsif', 'if')}\nend")
240
+ end
241
+ elsif node.else? || node.ternary?
242
+ add_offense(cond) do |corrector|
243
+ corrector.replace(node, node.else_branch.source)
244
+ end
245
+ else
246
+ add_offense(cond) do |corrector|
247
+ corrector.remove(node)
248
+ end
249
+ end
250
+ end
251
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
162
252
  end
163
253
  end
164
254
  end
@@ -79,7 +79,7 @@ module RuboCop
79
79
  end
80
80
 
81
81
  def range_pairs(expr)
82
- RuboCop::Cop::Utils::RegexpRanges.new(expr).pairs
82
+ expr.expressions.filter_map { |e| [e.expressions[0], e.expressions[1]] if e.type == :set }
83
83
  end
84
84
 
85
85
  def unsafe_range?(range_start, range_end)
@@ -94,7 +94,7 @@ module RuboCop
94
94
 
95
95
  def skip_range?(range_start, range_end)
96
96
  [range_start, range_end].any? do |bound|
97
- bound.type != :literal
97
+ bound&.type != :literal
98
98
  end
99
99
  end
100
100
 
@@ -17,17 +17,12 @@ module RuboCop
17
17
  # * 2.0+ ... `enumerator`
18
18
  # * 2.1+ ... `thread`
19
19
  # * 2.2+ ... Add `rational` and `complex` above
20
- # * 2.5+ ... Add `pp` above
21
20
  # * 2.7+ ... Add `ruby2_keywords` above
22
21
  # * 3.1+ ... Add `fiber` above
23
22
  # * 3.2+ ... `set`
24
23
  #
25
24
  # This cop target those features.
26
25
  #
27
- # @safety
28
- # This cop's autocorrection is unsafe because if `require 'pp'` is removed from one file,
29
- # `NameError` can be encountered when another file uses `PP.pp`.
30
- #
31
26
  # @example
32
27
  # # bad
33
28
  # require 'unloaded_feature'
@@ -42,10 +37,6 @@ module RuboCop
42
37
  MSG = 'Remove unnecessary `require` statement.'
43
38
  RESTRICT_ON_SEND = %i[require].freeze
44
39
  RUBY_22_LOADED_FEATURES = %w[rational complex].freeze
45
- PRETTY_PRINT_METHODS = %i[
46
- pretty_inspect pretty_print pretty_print_cycle
47
- pretty_print_inspect pretty_print_instance_variables
48
- ].freeze
49
40
 
50
41
  # @!method redundant_require_statement?(node)
51
42
  def_node_matcher :redundant_require_statement?, <<~PATTERN
@@ -53,11 +44,6 @@ module RuboCop
53
44
  (str #redundant_feature?))
54
45
  PATTERN
55
46
 
56
- # @!method pp_const?(node)
57
- def_node_matcher :pp_const?, <<~PATTERN
58
- (const {nil? cbase} :PP)
59
- PATTERN
60
-
61
47
  def on_send(node)
62
48
  return unless redundant_require_statement?(node)
63
49
 
@@ -81,18 +67,11 @@ module RuboCop
81
67
  feature_name == 'enumerator' ||
82
68
  (target_ruby_version >= 2.1 && feature_name == 'thread') ||
83
69
  (target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
84
- (target_ruby_version >= 2.5 && feature_name == 'pp' && !need_to_require_pp?) ||
85
70
  (target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
86
71
  (target_ruby_version >= 3.1 && feature_name == 'fiber') ||
87
72
  (target_ruby_version >= 3.2 && feature_name == 'set')
88
73
  end
89
74
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
90
-
91
- def need_to_require_pp?
92
- processed_source.ast.each_descendant(:send).any? do |node|
93
- pp_const?(node.receiver) || PRETTY_PRINT_METHODS.include?(node.method_name)
94
- end
95
- end
96
75
  end
97
76
  end
98
77
  end