rubocop 1.45.1 → 1.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +3 -9
  4. data/lib/rubocop/comment_config.rb +17 -0
  5. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  6. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  7. data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
  8. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +8 -2
  9. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +11 -7
  10. data/lib/rubocop/cop/lint/debugger.rb +3 -0
  11. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -9
  12. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +6 -10
  13. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +7 -1
  14. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  15. data/lib/rubocop/cop/lint/to_enum_arguments.rb +6 -2
  16. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -9
  17. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -1
  18. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +10 -7
  19. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +0 -3
  20. data/lib/rubocop/cop/style/accessor_grouping.rb +12 -11
  21. data/lib/rubocop/cop/style/array_intersect.rb +1 -1
  22. data/lib/rubocop/cop/style/documentation_method.rb +4 -4
  23. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  24. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -6
  25. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  26. data/lib/rubocop/cop/style/word_array.rb +17 -5
  27. data/lib/rubocop/cop/team.rb +11 -8
  28. data/lib/rubocop/cop/util.rb +12 -3
  29. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  30. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  31. data/lib/rubocop/target_ruby.rb +1 -1
  32. data/lib/rubocop/version.rb +1 -1
  33. metadata +6 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 648a8aa3156aebf0c078bc0b600f301d3aa0abaf92d6b3643c343718575f7302
4
- data.tar.gz: 21b185886d70b70a163c6e7f3ea47e04ee0a0afcf11217e0d7bcb31e25440880
3
+ metadata.gz: a2c58d5ebb1a39e8a8f66fe34861ea52ae7c7d601c4f64e5f39c9b3f335a04b4
4
+ data.tar.gz: b0eab2e29b9875b27aa3eb069147ec82b3fc108fe15c81dcb43c68265b6757d9
5
5
  SHA512:
6
- metadata.gz: ff5a5e947001ba9507f3e806896559baaf0e4bccc6b2cc56316dffc3ae334f62046040be389518139d2979c4d09900600f9b233bc1f4dbd2d1d37a2f8fe99037
7
- data.tar.gz: 8f89f55198c9d206c5b8d0c32cbeb5033491046c0ea0f4311f6c1a23595bcce852ec732606ca1fd2bc499b31ecb2265dcf6d85edd352f6400d01bd9385993a44
6
+ metadata.gz: 63da1401d75b3245df06193f264339cf62b180102c584b5b708ed1ba7191787bd71ae33636eb703406ab6ea87127854ba38c8348336f521113fee265d74da9cc
7
+ data.tar.gz: 7155f94dd7b68d2e103003bbfa95b74e2e4a9d9a8efd78c210adc227bc0a2b6cd399a7e7e285acd6934b070036ca0362d3b9560b9e92693bd9a9bc0497b71af6
data/README.md CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.45', require: false
56
+ gem 'rubocop', '~> 1.46', require: false
57
57
  ```
58
58
 
59
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -1630,13 +1630,12 @@ Lint/Debugger:
1630
1630
  Description: 'Check for debugger calls.'
1631
1631
  Enabled: true
1632
1632
  VersionAdded: '0.14'
1633
- VersionChanged: '1.10'
1633
+ VersionChanged: '1.46'
1634
1634
  DebuggerMethods:
1635
1635
  # Groups are available so that a specific group can be disabled in
1636
1636
  # a user's configuration, but are otherwise not significant.
1637
1637
  Kernel:
1638
1638
  - binding.irb
1639
- - p
1640
1639
  - Kernel.binding.irb
1641
1640
  Byebug:
1642
1641
  - byebug
@@ -1646,9 +1645,6 @@ Lint/Debugger:
1646
1645
  Capybara:
1647
1646
  - save_and_open_page
1648
1647
  - save_and_open_screenshot
1649
- PP:
1650
- - PP.pp
1651
- - pp
1652
1648
  debug.rb:
1653
1649
  - binding.b
1654
1650
  - binding.break
@@ -2927,6 +2923,7 @@ Naming/VariableNumber:
2927
2923
  - rfc822 # Time#rfc822
2928
2924
  - rfc2822 # Time#rfc2822
2929
2925
  - rfc3339 # DateTime.rfc3339
2926
+ - x86_64 # Allowed by default as an underscore separated CPU architecture name
2930
2927
  AllowedPatterns: []
2931
2928
 
2932
2929
  #################### Security ##############################
@@ -3054,6 +3051,7 @@ Style/ArrayCoercion:
3054
3051
  Style/ArrayIntersect:
3055
3052
  Description: 'Use `array1.intersect?(array2)` instead of `(array1 & array2).any?`.'
3056
3053
  Enabled: 'pending'
3054
+ Safe: false
3057
3055
  VersionAdded: '1.40'
3058
3056
 
3059
3057
  Style/ArrayJoin:
@@ -4027,10 +4025,6 @@ Style/InverseMethods:
4027
4025
  :=~: :!~
4028
4026
  :<: :>=
4029
4027
  :>: :<=
4030
- # `ActiveSupport` defines some common inverse methods. They are listed below,
4031
- # and not enabled by default.
4032
- # :present?: :blank?,
4033
- # :include?: :exclude?
4034
4028
  # `InverseBlocks` are methods that are inverted by inverting the return
4035
4029
  # of the block that is passed to the method
4036
4030
  InverseBlocks:
@@ -42,6 +42,10 @@ module RuboCop
42
42
  disabled_line_ranges.none? { |range| range.include?(line_number) }
43
43
  end
44
44
 
45
+ def cop_opted_in?(cop)
46
+ opt_in_cops.include?(cop.cop_name)
47
+ end
48
+
45
49
  def cop_disabled_line_ranges
46
50
  @cop_disabled_line_ranges ||= analyze
47
51
  end
@@ -74,6 +78,19 @@ module RuboCop
74
78
  extras
75
79
  end
76
80
 
81
+ def opt_in_cops
82
+ @opt_in_cops ||= begin
83
+ cops = Set.new
84
+ each_directive do |directive|
85
+ next unless directive.enabled?
86
+ next if directive.all_cops?
87
+
88
+ cops.merge(directive.cop_names)
89
+ end
90
+ cops
91
+ end
92
+ end
93
+
77
94
  def analyze # rubocop:todo Metrics/AbcSize
78
95
  return {} if @no_directives
79
96
 
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Enforces the use of `processed_source.file_path` instead of `processed_source.buffer.name`.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # processed_source.buffer.name
12
+ #
13
+ # # good
14
+ # processed_source.file_path
15
+ #
16
+ class ProcessedSourceBufferName < Base
17
+ extend AutoCorrector
18
+
19
+ MSG = 'Use `file_path` instead.'
20
+
21
+ RESTRICT_ON_SEND = %i[name].freeze
22
+
23
+ # @!method processed_source_buffer_name?(node)
24
+ def_node_matcher :processed_source_buffer_name?, <<~PATTERN
25
+ (send
26
+ (send
27
+ {(lvar :processed_source) (send nil? :processed_source)} :buffer) :name)
28
+ PATTERN
29
+
30
+ def on_send(node)
31
+ return unless processed_source_buffer_name?(node)
32
+
33
+ offense_range = node.children.first.loc.selector.begin.join(node.loc.expression.end)
34
+
35
+ add_offense(offense_range) do |corrector|
36
+ corrector.replace(offense_range, 'file_path')
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -15,6 +15,7 @@ require_relative 'internal_affairs/node_matcher_directive'
15
15
  require_relative 'internal_affairs/node_type_predicate'
16
16
  require_relative 'internal_affairs/numblock_handler'
17
17
  require_relative 'internal_affairs/offense_location_keyword'
18
+ require_relative 'internal_affairs/processed_source_buffer_name'
18
19
  require_relative 'internal_affairs/redundant_context_config_parameter'
19
20
  require_relative 'internal_affairs/redundant_described_class_as_subject'
20
21
  require_relative 'internal_affairs/redundant_let_rubocop_config_new'
@@ -82,6 +82,10 @@ module RuboCop
82
82
  check_other_alignment(node)
83
83
  end
84
84
 
85
+ def on_sclass(node)
86
+ check_other_alignment(node)
87
+ end
88
+
85
89
  def on_module(node)
86
90
  check_other_alignment(node)
87
91
  end
@@ -67,8 +67,7 @@ module RuboCop
67
67
 
68
68
  outermost_send = outermost_send_on_same_line(heredoc_arg)
69
69
  return unless outermost_send
70
- return unless outermost_send.loc.end
71
- return unless heredoc_arg.first_line != outermost_send.loc.end.line
70
+ return if end_keyword_before_closing_parentesis?(node)
72
71
  return if subsequent_closing_parentheses_in_same_line?(outermost_send)
73
72
  return if exist_argument_between_heredoc_end_and_closing_parentheses?(node)
74
73
 
@@ -160,6 +159,12 @@ module RuboCop
160
159
 
161
160
  # Closing parenthesis helpers.
162
161
 
162
+ def end_keyword_before_closing_parentesis?(parenthesized_send_node)
163
+ parenthesized_send_node.ancestors.any? do |ancestor|
164
+ ancestor.loc.respond_to?(:end) && ancestor.loc.end&.source == 'end'
165
+ end
166
+ end
167
+
163
168
  def subsequent_closing_parentheses_in_same_line?(outermost_send)
164
169
  last_arg_of_outer_send = outermost_send.last_argument
165
170
  return false unless last_arg_of_outer_send&.loc.respond_to?(:end) &&
@@ -215,6 +220,7 @@ module RuboCop
215
220
  end
216
221
 
217
222
  def exist_argument_between_heredoc_end_and_closing_parentheses?(node)
223
+ return true unless node.loc.end
218
224
  return false unless (heredoc_end = find_most_bottom_of_heredoc_end(node.arguments))
219
225
 
220
226
  heredoc_end < node.loc.end.begin_pos &&
@@ -87,22 +87,26 @@ module RuboCop
87
87
  corrector.replace(range, correction)
88
88
  end
89
89
 
90
- def string_literal_ranges(ast)
90
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
91
+ def ignored_literal_ranges(ast)
91
92
  # which lines start inside a string literal?
92
93
  return [] if ast.nil?
93
94
 
94
- ranges = Set.new
95
- ast.each_node(:str, :dstr) do |str|
96
- loc = str.location
95
+ ast.each_node(:str, :dstr, :array).with_object(Set.new) do |literal, ranges|
96
+ loc = literal.location
97
97
 
98
- if str.heredoc?
98
+ if literal.array_type?
99
+ next unless literal.percent_literal?
100
+
101
+ ranges << loc.expression
102
+ elsif literal.heredoc?
99
103
  ranges << loc.heredoc_body
100
104
  elsif loc.respond_to?(:begin) && loc.begin
101
105
  ranges << loc.expression
102
106
  end
103
107
  end
104
- ranges
105
108
  end
109
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
106
110
 
107
111
  def comment_ranges(comments)
108
112
  comments.map(&:loc).map(&:expression)
@@ -119,7 +123,7 @@ module RuboCop
119
123
  end
120
124
 
121
125
  def ignored_ranges
122
- @ignored_ranges ||= string_literal_ranges(processed_source.ast) +
126
+ @ignored_ranges ||= ignored_literal_ranges(processed_source.ast) +
123
127
  comment_ranges(processed_source.comments)
124
128
  end
125
129
 
@@ -70,6 +70,9 @@ module RuboCop
70
70
  def on_send(node)
71
71
  return unless debugger_method?(node)
72
72
 
73
+ # Basically, debugger methods are not used as a method argument without arguments.
74
+ return if node.arguments.empty? && node.each_ancestor(:send, :csend).any?
75
+
73
76
  add_offense(node)
74
77
  end
75
78
 
@@ -120,7 +120,7 @@ module RuboCop
120
120
 
121
121
  def scoping_method_call?(child)
122
122
  child.sclass_type? || eval_call?(child) || exec_call?(child) ||
123
- class_constructor?(child) || allowed_method_name?(child)
123
+ child.class_constructor? || allowed_method_name?(child)
124
124
  end
125
125
 
126
126
  def allowed_method_name?(node)
@@ -138,14 +138,6 @@ module RuboCop
138
138
  def_node_matcher :exec_call?, <<~PATTERN
139
139
  (block (send _ {:instance_exec :class_exec :module_exec} ...) ...)
140
140
  PATTERN
141
-
142
- # @!method class_constructor?(node)
143
- def_node_matcher :class_constructor?, <<~PATTERN
144
- ({block numblock} {
145
- (send (const {nil? cbase} {:Class :Module :Struct}) :new ...)
146
- (send (const {nil? cbase} :Data) :define ...)
147
- } ...)
148
- PATTERN
149
141
  end
150
142
  end
151
143
  end
@@ -69,7 +69,7 @@ module RuboCop
69
69
  end
70
70
 
71
71
  def on_in_pattern(node)
72
- regexp_patterns = patterns(node).select(&:regexp_type?)
72
+ regexp_patterns = regexp_patterns(node)
73
73
 
74
74
  @valid_ref = regexp_patterns.map { |pattern| check_regexp(pattern) }.compact.max
75
75
  end
@@ -90,16 +90,12 @@ module RuboCop
90
90
 
91
91
  private
92
92
 
93
- def patterns(pattern_node)
94
- pattern = pattern_node.node_parts[0]
95
-
96
- case pattern.type
97
- when :array_pattern, :match_alt
98
- pattern.children
99
- when :match_as
100
- patterns(pattern)
101
- else
93
+ def regexp_patterns(in_node)
94
+ pattern = in_node.pattern
95
+ if pattern.regexp_type?
102
96
  [pattern]
97
+ else
98
+ pattern.each_descendant(:regexp).to_a
103
99
  end
104
100
  end
105
101
 
@@ -284,12 +284,18 @@ module RuboCop
284
284
  .all? { |intervening| /\A\s*,\s*\Z/.match?(intervening) }
285
285
  end
286
286
 
287
+ SIMILAR_COP_NAMES_CACHE = Hash.new do |hash, cop_name|
288
+ hash[:all_cop_names] = Registry.global.names unless hash.key?(:all_cop_names)
289
+ hash[cop_name] = NameSimilarity.find_similar_name(cop_name, hash[:all_cop_names])
290
+ end
291
+ private_constant :SIMILAR_COP_NAMES_CACHE
292
+
287
293
  def describe(cop)
288
294
  return 'all cops' if cop == 'all'
289
295
  return "`#{remove_department_marker(cop)}` department" if department_marker?(cop)
290
296
  return "`#{cop}`" if all_cop_names.include?(cop)
291
297
 
292
- similar = NameSimilarity.find_similar_name(cop, all_cop_names)
298
+ similar = SIMILAR_COP_NAMES_CACHE[cop]
293
299
  similar ? "`#{cop}` (did you mean `#{similar}`?)" : "`#{cop}` (unknown cop)"
294
300
  end
295
301
 
@@ -41,7 +41,8 @@ module RuboCop
41
41
 
42
42
  def on_send(node)
43
43
  return if node.receiver
44
- return unless node.parent.block_type? && node.parent.method?(:refine)
44
+ return unless (parent = node.parent)
45
+ return unless parent.block_type? && parent.method?(:refine)
45
46
 
46
47
  add_offense(node.loc.selector, message: format(MSG, current: node.method_name))
47
48
  end
@@ -43,8 +43,12 @@ module RuboCop
43
43
  return unless def_node
44
44
 
45
45
  enum_conversion_call?(node) do |method_node, arguments|
46
- add_offense(node) unless method_name?(method_node, def_node.method_name) &&
47
- arguments_match?(arguments, def_node)
46
+ next if method_node.call_type? &&
47
+ !method_node.method?(:__method__) && !method_node.method?(:__callee__)
48
+ next if method_name?(method_node, def_node.method_name) &&
49
+ arguments_match?(arguments, def_node)
50
+
51
+ add_offense(node)
48
52
  end
49
53
  end
50
54
 
@@ -167,14 +167,6 @@ module RuboCop
167
167
  ({block numblock} (send _ {:class_eval :instance_eval}) ...)
168
168
  PATTERN
169
169
 
170
- # @!method class_constructor?(node)
171
- def_node_matcher :class_constructor?, <<~PATTERN
172
- ({block numblock} {
173
- (send (const {nil? cbase} {:Class :Module :Struct}) :new ...)
174
- (send (const {nil? cbase} :Data) :define ...)
175
- } ...)
176
- PATTERN
177
-
178
170
  def check_node(node)
179
171
  return if node.nil?
180
172
 
@@ -273,7 +265,7 @@ module RuboCop
273
265
 
274
266
  def eval_call?(child)
275
267
  class_or_instance_eval?(child) ||
276
- class_constructor?(child) ||
268
+ child.class_constructor? ||
277
269
  any_context_creating_methods?(child)
278
270
  end
279
271
 
@@ -72,8 +72,9 @@ module RuboCop
72
72
  def use_exception_variable_in_ensure?(resbody_node)
73
73
  return false unless (exception_variable = resbody_node.exception_variable)
74
74
  return false unless (ensure_node = resbody_node.each_ancestor(:ensure).first)
75
+ return false unless (ensure_body = ensure_node.body)
75
76
 
76
- ensure_node.body.each_descendant(:lvar).map(&:source).include?(exception_variable.source)
77
+ ensure_body.each_descendant(:lvar).map(&:source).include?(exception_variable.source)
77
78
  end
78
79
 
79
80
  def exception_objects(resbody_node)
@@ -95,19 +95,19 @@ module RuboCop
95
95
  use_modifier_form_without_parenthesized_method_call?(method_dispatch_node)
96
96
  end
97
97
 
98
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
98
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
99
99
  def def_node_that_require_parentheses(node)
100
100
  last_pair = node.parent.pairs.last
101
101
  return unless last_pair.key.source == last_pair.value.source
102
102
  return unless (dispatch_node = find_ancestor_method_dispatch_node(node))
103
- return if node.respond_to?(:parenthesized?) && !node.parenthesized?
104
- return unless last_expression?(dispatch_node) || method_dispatch_as_argument?(dispatch_node)
103
+ return if dispatch_node.parenthesized?
104
+ return if last_expression?(dispatch_node) && !method_dispatch_as_argument?(dispatch_node)
105
105
 
106
106
  def_node = node.each_ancestor(:send, :csend, :super, :yield).first
107
107
 
108
108
  DefNode.new(def_node) unless def_node && def_node.arguments.empty?
109
109
  end
110
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
110
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
111
111
 
112
112
  def find_ancestor_method_dispatch_node(node)
113
113
  return unless (ancestor = node.parent.parent)
@@ -132,9 +132,12 @@ module RuboCop
132
132
  ancestor.ancestors.any? { |node| node.respond_to?(:modifier_form?) && node.modifier_form? }
133
133
  end
134
134
 
135
- def last_expression?(ancestor)
136
- ancestor.right_sibling ||
137
- ancestor.each_ancestor.find { |node| node.assignment? || node.send_type? }&.right_sibling
135
+ def last_expression?(node)
136
+ return false if node.right_sibling
137
+ return true unless (assignment_node = node.each_ancestor.find(&:assignment?))
138
+ return last_expression?(assignment_node.parent) if assignment_node.parent&.assignment?
139
+
140
+ !assignment_node.right_sibling
138
141
  end
139
142
 
140
143
  def method_dispatch_as_argument?(method_dispatch_node)
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # TEAM: backend_infra
4
- # WATCHERS: maxh
5
-
6
3
  module RuboCop
7
4
  module Cop
8
5
  # Common functionality for checking for a line break before each
@@ -7,8 +7,8 @@ module RuboCop
7
7
  # By default it enforces accessors to be placed in grouped declarations,
8
8
  # but it can be configured to enforce separating them in multiple declarations.
9
9
  #
10
- # NOTE: `Sorbet` is not compatible with "grouped" style. Consider "separated" style
11
- # or disabling this cop.
10
+ # NOTE: If there is a method call before the accessor method it is always allowed
11
+ # as it might be intended like Sorbet.
12
12
  #
13
13
  # @example EnforcedStyle: grouped (default)
14
14
  # # bad
@@ -43,11 +43,9 @@ module RuboCop
43
43
  GROUPED_MSG = 'Group together all `%<accessor>s` attributes.'
44
44
  SEPARATED_MSG = 'Use one attribute per `%<accessor>s`.'
45
45
 
46
- ACCESSOR_METHODS = %i[attr_reader attr_writer attr_accessor attr].freeze
47
-
48
46
  def on_class(node)
49
47
  class_send_elements(node).each do |macro|
50
- next unless accessor?(macro)
48
+ next unless macro.attribute_accessor?
51
49
 
52
50
  check(macro)
53
51
  end
@@ -58,7 +56,7 @@ module RuboCop
58
56
  private
59
57
 
60
58
  def check(send_node)
61
- return if previous_line_comment?(send_node)
59
+ return if previous_line_comment?(send_node) || !groupable_accessor?(send_node)
62
60
  return unless (grouped_style? && sibling_accessors(send_node).size > 1) ||
63
61
  (separated_style? && send_node.arguments.size > 1)
64
62
 
@@ -81,6 +79,13 @@ module RuboCop
81
79
  comment_line?(processed_source[node.first_line - 2])
82
80
  end
83
81
 
82
+ def groupable_accessor?(node)
83
+ return true unless (previous_expression = node.left_siblings.last)
84
+ return true unless previous_expression.send_type?
85
+
86
+ previous_expression.attribute_accessor? || previous_expression.access_modifier?
87
+ end
88
+
84
89
  def class_send_elements(class_node)
85
90
  class_def = class_node.body
86
91
 
@@ -93,10 +98,6 @@ module RuboCop
93
98
  end
94
99
  end
95
100
 
96
- def accessor?(send_node)
97
- send_node.macro? && ACCESSOR_METHODS.include?(send_node.method_name)
98
- end
99
-
100
101
  def grouped_style?
101
102
  style == :grouped
102
103
  end
@@ -107,7 +108,7 @@ module RuboCop
107
108
 
108
109
  def sibling_accessors(send_node)
109
110
  send_node.parent.each_child_node(:send).select do |sibling|
110
- accessor?(sibling) &&
111
+ sibling.attribute_accessor? &&
111
112
  sibling.method?(send_node.method_name) &&
112
113
  node_visibility(sibling) == node_visibility(send_node) &&
113
114
  !previous_line_comment?(sibling)
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # `(array1 & array2).any?` and is more readable.
13
13
  #
14
14
  # @safety
15
- # This cop cannot guarantee that array1 and array2 are
15
+ # This cop cannot guarantee that `array1` and `array2` are
16
16
  # actually arrays while method `intersect?` is for arrays only.
17
17
  #
18
18
  # @example
@@ -101,16 +101,16 @@ module RuboCop
101
101
 
102
102
  MSG = 'Missing method documentation comment.'
103
103
 
104
- # @!method module_function_node?(node)
105
- def_node_matcher :module_function_node?, <<~PATTERN
106
- (send nil? :module_function ...)
104
+ # @!method modifier_node?(node)
105
+ def_node_matcher :modifier_node?, <<~PATTERN
106
+ (send nil? {:module_function :ruby2_keywords} ...)
107
107
  PATTERN
108
108
 
109
109
  def on_def(node)
110
110
  return if node.method?(:initialize)
111
111
 
112
112
  parent = node.parent
113
- module_function_node?(parent) ? check(parent) : check(node)
113
+ modifier_node?(parent) ? check(parent) : check(node)
114
114
  end
115
115
  alias on_defs on_def
116
116
 
@@ -153,7 +153,7 @@ module RuboCop
153
153
 
154
154
  return if node.send_type? && !method_call_with_redundant_parentheses?(node)
155
155
 
156
- offense(begin_node, 'an unary operation')
156
+ offense(begin_node, 'a unary operation')
157
157
  end
158
158
 
159
159
  def offense(node, msg)
@@ -74,7 +74,7 @@ module RuboCop
74
74
 
75
75
  non_redundant =
76
76
  whitespace_in_free_space_mode?(node, class_elem) ||
77
- backslash_b?(class_elem) || backslash_zero?(class_elem) ||
77
+ backslash_b?(class_elem) || octal_requiring_char_class?(class_elem) ||
78
78
  requires_escape_outside_char_class?(class_elem)
79
79
 
80
80
  !non_redundant
@@ -104,11 +104,10 @@ module RuboCop
104
104
  elem == '\b'
105
105
  end
106
106
 
107
- def backslash_zero?(elem)
108
- # See https://github.com/rubocop/rubocop/issues/11067 for details - in short "\0" != "0" -
109
- # the former means an Unicode code point `"\u0000"`, the latter a number character `"0"`.
110
- # Similarly "\032" means "\u001A". Other numbers starting with "\0" can also be mentioned.
111
- elem == '\0'
107
+ def octal_requiring_char_class?(elem)
108
+ # The octal escapes \1 to \7 only work inside a character class
109
+ # because they would be a backreference outside it.
110
+ elem.match?(/\A\\[1-7]\z/)
112
111
  end
113
112
 
114
113
  def requires_escape_outside_char_class?(elem)
@@ -8,7 +8,7 @@ module RuboCop
8
8
  #
9
9
  # @safety
10
10
  # This cop is unsafe because `x..-1` and `x..` are only guaranteed to
11
- # be equivalent for `Array#[]`, and the cop cannot determine what class
11
+ # be equivalent for `Array#[]`, `String#[]`, and the cop cannot determine what class
12
12
  # the receiver is.
13
13
  #
14
14
  # For example:
@@ -82,10 +82,19 @@ module RuboCop
82
82
  attr_accessor :largest_brackets
83
83
  end
84
84
 
85
+ def on_new_investigation
86
+ super
87
+
88
+ # Prevent O(n2) checks (checking the entire matrix once for each child array) by caching
89
+ @matrix_of_complex_content_cache = Hash.new do |cache, node|
90
+ cache[node] = matrix_of_complex_content?(node)
91
+ end
92
+ end
93
+
85
94
  def on_array(node)
86
95
  if bracketed_array_of?(:str, node)
87
96
  return if complex_content?(node.values)
88
- return if within_2d_array_of_complex_content?(node)
97
+ return if within_matrix_of_complex_content?(node)
89
98
 
90
99
  check_bracketed_array(node, 'w')
91
100
  elsif node.percent_literal?(:string)
@@ -95,12 +104,15 @@ module RuboCop
95
104
 
96
105
  private
97
106
 
98
- def within_2d_array_of_complex_content?(node)
107
+ def within_matrix_of_complex_content?(node)
99
108
  return false unless (parent = node.parent)
100
109
 
101
- parent.array_type? &&
102
- parent.values.all?(&:array_type?) &&
103
- parent.values.any? { |subarray| complex_content?(subarray.values) }
110
+ parent.array_type? && @matrix_of_complex_content_cache[parent]
111
+ end
112
+
113
+ def matrix_of_complex_content?(array)
114
+ array.values.all?(&:array_type?) &&
115
+ array.values.any? { |subarray| complex_content?(subarray.values) }
104
116
  end
105
117
 
106
118
  def complex_content?(strings, complex_regex: word_regex)
@@ -28,7 +28,7 @@ module RuboCop
28
28
  def self.mobilize_cops(cop_classes, config, options = {})
29
29
  cop_classes = Registry.new(cop_classes.to_a, options) unless cop_classes.is_a?(Registry)
30
30
 
31
- cop_classes.enabled(config).map do |cop_class|
31
+ cop_classes.map do |cop_class|
32
32
  cop_class.new(config, options)
33
33
  end
34
34
  end
@@ -58,6 +58,7 @@ module RuboCop
58
58
  @options = options
59
59
  reset
60
60
  @ready = true
61
+ @registry = Registry.new(cops, options.dup)
61
62
 
62
63
  validate_config
63
64
  end
@@ -84,7 +85,7 @@ module RuboCop
84
85
  # until there are no corrections left to perform
85
86
  # To speed things up, run autocorrecting cops by themselves, and only
86
87
  # run the other cops when no corrections are left
87
- on_duty = roundup_relevant_cops(processed_source.file_path)
88
+ on_duty = roundup_relevant_cops(processed_source)
88
89
 
89
90
  autocorrect_cops, other_cops = on_duty.partition(&:autocorrect?)
90
91
  report = investigate_partial(autocorrect_cops, processed_source,
@@ -130,7 +131,7 @@ module RuboCop
130
131
  # holds source read in from stdin, when --stdin option is used
131
132
  @options[:stdin] = new_source
132
133
  else
133
- filename = processed_source.buffer.name
134
+ filename = processed_source.file_path
134
135
  File.write(filename, new_source)
135
136
  end
136
137
  @updated_source_file = true
@@ -156,11 +157,13 @@ module RuboCop
156
157
  end
157
158
 
158
159
  # @return [Array<cop>]
159
- def roundup_relevant_cops(filename)
160
- cops.reject do |cop|
161
- cop.excluded_file?(filename) ||
162
- !support_target_ruby_version?(cop) ||
163
- !support_target_rails_version?(cop)
160
+ def roundup_relevant_cops(processed_source)
161
+ cops.select do |cop|
162
+ next true if processed_source.comment_config.cop_opted_in?(cop)
163
+ next false unless @registry.enabled?(cop, @config)
164
+ next false if cop.excluded_file?(processed_source.file_path)
165
+
166
+ support_target_ruby_version?(cop) && support_target_rails_version?(cop)
164
167
  end
165
168
  end
166
169
 
@@ -3,6 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  # This module contains a collection of useful utility methods.
6
+ # rubocop:disable Metrics/ModuleLength
6
7
  module Util
7
8
  include PathUtil
8
9
 
@@ -92,13 +93,20 @@ module RuboCop
92
93
  sexp.each_child_node { |elem| on_node(syms, elem, excludes, &block) }
93
94
  end
94
95
 
96
+ # Arbitrarily chosen value, should be enough to cover
97
+ # the most nested source code in real world projects.
98
+ MAX_LINE_BEGINS_REGEX_INDEX = 50
95
99
  LINE_BEGINS_REGEX_CACHE = Hash.new do |hash, index|
96
- hash[index] = /^\s{#{index}}\S/
100
+ hash[index] = /^\s{#{index}}\S/ if index <= MAX_LINE_BEGINS_REGEX_INDEX
97
101
  end
98
- private_constant :LINE_BEGINS_REGEX_CACHE
102
+ private_constant :MAX_LINE_BEGINS_REGEX_INDEX, :LINE_BEGINS_REGEX_CACHE
99
103
 
100
104
  def begins_its_line?(range)
101
- range.source_line.match?(LINE_BEGINS_REGEX_CACHE[range.column])
105
+ if (regex = LINE_BEGINS_REGEX_CACHE[range.column])
106
+ range.source_line.match?(regex)
107
+ else
108
+ range.source_line.index(/\S/) == range.column
109
+ end
102
110
  end
103
111
 
104
112
  # Returns, for example, a bare `if` node if the given node is an `if`
@@ -190,5 +198,6 @@ module RuboCop
190
198
  source == target || (source.is_a?(Array) && source.include?(target))
191
199
  end
192
200
  end
201
+ # rubocop:enable Metrics/ModuleLength
193
202
  end
194
203
  end
@@ -69,7 +69,7 @@ module CopHelper
69
69
  end
70
70
 
71
71
  def _investigate(cop, processed_source)
72
- team = RuboCop::Cop::Team.new([cop], nil, raise_error: true)
72
+ team = RuboCop::Cop::Team.new([cop], configuration, raise_error: true)
73
73
  report = team.investigate(processed_source)
74
74
  @last_corrector = report.correctors.first || RuboCop::Cop::Corrector.new(processed_source)
75
75
  report.offenses.reject(&:disabled?)
@@ -172,3 +172,7 @@ end
172
172
  RSpec.shared_context 'ruby 3.2' do
173
173
  let(:ruby_version) { 3.2 }
174
174
  end
175
+
176
+ RSpec.shared_context 'ruby 3.3' do
177
+ let(:ruby_version) { 3.3 }
178
+ end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  # The kind of Ruby that code inspected by RuboCop is written in.
5
5
  # @api private
6
6
  class TargetRuby
7
- KNOWN_RUBIES = [2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2].freeze
7
+ KNOWN_RUBIES = [2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3].freeze
8
8
  DEFAULT_VERSION = 2.6
9
9
 
10
10
  OBSOLETE_RUBIES = {
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.45.1'
6
+ STRING = '1.46.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.45.1
4
+ version: 1.46.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2023-02-08 00:00:00.000000000 Z
13
+ date: 2023-02-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -120,7 +120,7 @@ dependencies:
120
120
  requirements:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
- version: 1.24.1
123
+ version: 1.26.0
124
124
  - - "<"
125
125
  - !ruby/object:Gem::Version
126
126
  version: '2.0'
@@ -130,7 +130,7 @@ dependencies:
130
130
  requirements:
131
131
  - - ">="
132
132
  - !ruby/object:Gem::Version
133
- version: 1.24.1
133
+ version: 1.26.0
134
134
  - - "<"
135
135
  - !ruby/object:Gem::Version
136
136
  version: '2.0'
@@ -281,6 +281,7 @@ files:
281
281
  - lib/rubocop/cop/internal_affairs/node_type_predicate.rb
282
282
  - lib/rubocop/cop/internal_affairs/numblock_handler.rb
283
283
  - lib/rubocop/cop/internal_affairs/offense_location_keyword.rb
284
+ - lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb
284
285
  - lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb
285
286
  - lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb
286
287
  - lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb
@@ -980,7 +981,7 @@ metadata:
980
981
  homepage_uri: https://rubocop.org/
981
982
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
982
983
  source_code_uri: https://github.com/rubocop/rubocop/
983
- documentation_uri: https://docs.rubocop.org/rubocop/1.45/
984
+ documentation_uri: https://docs.rubocop.org/rubocop/1.46/
984
985
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
985
986
  rubygems_mfa_required: 'true'
986
987
  post_install_message: