rubocop 1.45.1 → 1.46.0

Sign up to get free protection for your applications and to get access to all the features.
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: