rubocop 1.79.2 → 1.80.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/exe/rubocop +1 -8
- data/lib/rubocop/cli.rb +5 -0
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -0
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -2
- data/lib/rubocop/cop/lint/self_assignment.rb +5 -4
- data/lib/rubocop/cop/naming/method_name.rb +1 -1
- data/lib/rubocop/cop/style/array_intersect.rb +45 -11
- data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +32 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +12 -1
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +9 -7
- data/lib/rubocop/formatter/disabled_config_formatter.rb +18 -5
- data/lib/rubocop/lsp/routes.rb +31 -2
- data/lib/rubocop/target_finder.rb +9 -9
- data/lib/rubocop/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 496ab84015431ed6854f23f7a0e5ca4df59bc01056024b8895c59900c885530d
|
4
|
+
data.tar.gz: '09bc286e311ba0b4e2cb9cbc9b4c4ed33b7154311e27be5c9604f30cde4c54d7'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b647e72a501941d047a93c9d761840664ce140ae11a9d5326855d6a9755cab4d065dcbf37db926396ab078cf18a44378ab89ed4a40745dd35bf3cec9fbdb4ce
|
7
|
+
data.tar.gz: 5f26cbc1e08e4fb9fa03b2cef099543864dfa741fb73e5e7062186f810a7f0f816bbe3dae981e8dba2c3758318fcbf015f7dbf140e472fbc8b5dd2f9fde1c9bf
|
data/README.md
CHANGED
@@ -51,7 +51,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
51
51
|
in your `Gemfile`:
|
52
52
|
|
53
53
|
```rb
|
54
|
-
gem 'rubocop', '~> 1.
|
54
|
+
gem 'rubocop', '~> 1.80', require: false
|
55
55
|
```
|
56
56
|
|
57
57
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/exe/rubocop
CHANGED
@@ -12,13 +12,6 @@ if RuboCop::Server.running?
|
|
12
12
|
exit_status = RuboCop::Server::ClientCommand::Exec.new.run
|
13
13
|
else
|
14
14
|
require 'rubocop'
|
15
|
-
|
16
|
-
cli = RuboCop::CLI.new
|
17
|
-
|
18
|
-
time_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
19
|
-
exit_status = cli.run
|
20
|
-
elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - time_start
|
21
|
-
|
22
|
-
puts "Finished in #{elapsed_time} seconds" if cli.options[:debug] || cli.options[:display_time]
|
15
|
+
exit_status = RuboCop::CLI.new.run
|
23
16
|
end
|
24
17
|
exit exit_status
|
data/lib/rubocop/cli.rb
CHANGED
@@ -37,6 +37,8 @@ module RuboCop
|
|
37
37
|
#
|
38
38
|
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
39
39
|
def run(args = ARGV)
|
40
|
+
time_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
41
|
+
|
40
42
|
@options, paths = Options.new.parse(args)
|
41
43
|
@env = Environment.new(@options, @config_store, paths)
|
42
44
|
|
@@ -72,6 +74,9 @@ module RuboCop
|
|
72
74
|
warn e.message
|
73
75
|
warn e.backtrace
|
74
76
|
STATUS_ERROR
|
77
|
+
ensure
|
78
|
+
elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - time_start
|
79
|
+
puts "Finished in #{elapsed_time} seconds" if @options[:debug] || @options[:display_time]
|
75
80
|
end
|
76
81
|
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
77
82
|
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
class ForToEachCorrector
|
7
7
|
extend NodePattern::Macros
|
8
8
|
|
9
|
-
CORRECTION = '%<collection>s
|
9
|
+
CORRECTION = '%<collection>s%<dot>seach do |%<argument>s|'
|
10
10
|
|
11
11
|
def initialize(for_node)
|
12
12
|
@for_node = for_node
|
@@ -25,7 +25,12 @@ module RuboCop
|
|
25
25
|
attr_reader :for_node, :variable_node, :collection_node
|
26
26
|
|
27
27
|
def correction
|
28
|
-
format(
|
28
|
+
format(
|
29
|
+
CORRECTION,
|
30
|
+
collection: collection_source,
|
31
|
+
dot: collection_node.csend_type? ? '&.' : '.',
|
32
|
+
argument: variable_node.source
|
33
|
+
)
|
29
34
|
end
|
30
35
|
|
31
36
|
def collection_source
|
@@ -38,7 +38,7 @@ module RuboCop
|
|
38
38
|
RESTRICT_ON_SEND = MODULE_INCLUSION_METHODS
|
39
39
|
|
40
40
|
def on_send(node)
|
41
|
-
return if node.receiver
|
41
|
+
return if node.receiver || node.arguments.empty?
|
42
42
|
return if node.parent&.type?(:send, :any_block)
|
43
43
|
|
44
44
|
return if next_line_empty_or_enable_directive_comment?(node.last_line)
|
@@ -10,6 +10,8 @@ module RuboCop
|
|
10
10
|
# condition, an explicit `return` statement, etc. In other contexts, the second operand should
|
11
11
|
# be indented regardless of enforced style.
|
12
12
|
#
|
13
|
+
# In both styles, operators should be aligned when an assignment begins on the next line.
|
14
|
+
#
|
13
15
|
# @example EnforcedStyle: aligned (default)
|
14
16
|
# # bad
|
15
17
|
# if a +
|
@@ -24,8 +24,6 @@ module RuboCop
|
|
24
24
|
|
25
25
|
MSG_REPEATED_ELEMENT = 'Duplicate element inside regexp character class'
|
26
26
|
|
27
|
-
OCTAL_DIGITS_AFTER_ESCAPE = 2
|
28
|
-
|
29
27
|
def on_regexp(node)
|
30
28
|
each_repeated_character_class_element_loc(node) do |loc|
|
31
29
|
add_offense(loc, message: MSG_REPEATED_ELEMENT) do |corrector|
|
@@ -40,9 +38,9 @@ module RuboCop
|
|
40
38
|
|
41
39
|
seen = Set.new
|
42
40
|
group_expressions(node, expr.expressions) do |group|
|
43
|
-
group_source = group.
|
41
|
+
group_source = group.to_s
|
44
42
|
|
45
|
-
yield
|
43
|
+
yield group.expression if seen.include?(group_source)
|
46
44
|
|
47
45
|
seen << group_source
|
48
46
|
end
|
@@ -52,40 +50,13 @@ module RuboCop
|
|
52
50
|
private
|
53
51
|
|
54
52
|
def group_expressions(node, expressions)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
until expressions.empty?
|
59
|
-
# With we may need to compose a group of multiple expressions.
|
60
|
-
group = [expressions.shift]
|
61
|
-
next if within_interpolation?(node, group.first)
|
62
|
-
|
63
|
-
# With regexp_parser < 2.7 escaped octal sequences may be up to 3
|
64
|
-
# separate expressions ("\\0", "0", "1").
|
65
|
-
pop_octal_digits(group, expressions) if escaped_octal?(group.first.to_s)
|
66
|
-
|
67
|
-
yield(group)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def pop_octal_digits(current_child, expressions)
|
72
|
-
OCTAL_DIGITS_AFTER_ESCAPE.times do
|
73
|
-
next_child = expressions.first
|
74
|
-
break unless octal?(next_child.to_s)
|
53
|
+
expressions.each do |expression|
|
54
|
+
next if within_interpolation?(node, expression)
|
75
55
|
|
76
|
-
|
56
|
+
yield(expression)
|
77
57
|
end
|
78
58
|
end
|
79
59
|
|
80
|
-
def source_range(children)
|
81
|
-
return children.first.expression if children.size == 1
|
82
|
-
|
83
|
-
range_between(
|
84
|
-
children.first.expression.begin_pos,
|
85
|
-
children.last.expression.begin_pos + children.last.to_s.length
|
86
|
-
)
|
87
|
-
end
|
88
|
-
|
89
60
|
def skip_expression?(expr)
|
90
61
|
expr.type != :set || expr.token == :intersection
|
91
62
|
end
|
@@ -99,14 +70,6 @@ module RuboCop
|
|
99
70
|
interpolation_locs(node).any? { |il| il.overlaps?(parse_tree_child_loc) }
|
100
71
|
end
|
101
72
|
|
102
|
-
def escaped_octal?(string)
|
103
|
-
string.length == 2 && string[0] == '\\' && octal?(string[1])
|
104
|
-
end
|
105
|
-
|
106
|
-
def octal?(char)
|
107
|
-
('0'..'7').cover?(char)
|
108
|
-
end
|
109
|
-
|
110
73
|
def interpolation_locs(node)
|
111
74
|
@interpolation_locs ||= {}
|
112
75
|
|
@@ -52,10 +52,9 @@ module RuboCop
|
|
52
52
|
each_missing_enable do |cop, line_range|
|
53
53
|
next if acceptable_range?(cop, line_range)
|
54
54
|
|
55
|
-
range = source_range(processed_source.buffer, line_range.min, 0..0)
|
56
55
|
comment = processed_source.comment_at_line(line_range.begin)
|
57
56
|
|
58
|
-
add_offense(
|
57
|
+
add_offense(comment, message: message(cop, comment))
|
59
58
|
end
|
60
59
|
end
|
61
60
|
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.receiver)
|
46
46
|
|
47
47
|
if node.method?(:[]=)
|
48
|
-
handle_key_assignment(node)
|
48
|
+
handle_key_assignment(node)
|
49
49
|
elsif node.assignment_method?
|
50
50
|
handle_attribute_assignment(node) if node.arguments.size == 1
|
51
51
|
end
|
@@ -105,12 +105,13 @@ module RuboCop
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def handle_key_assignment(node)
|
108
|
-
value_node = node.
|
108
|
+
value_node = node.last_argument
|
109
|
+
node_arguments = node.arguments[0...-1]
|
109
110
|
|
110
111
|
if value_node.send_type? && value_node.method?(:[]) &&
|
111
112
|
node.receiver == value_node.receiver &&
|
112
|
-
|
113
|
-
|
113
|
+
node_arguments.none?(&:call_type?) &&
|
114
|
+
node_arguments == value_node.arguments
|
114
115
|
add_offense(node)
|
115
116
|
end
|
116
117
|
end
|
@@ -10,6 +10,8 @@ module RuboCop
|
|
10
10
|
# * `(array1 & array2).any?`
|
11
11
|
# * `(array1.intersection(array2)).any?`
|
12
12
|
# * `array1.any? { |elem| array2.member?(elem) }`
|
13
|
+
# * `(array1 & array2).count > 0`
|
14
|
+
# * `(array1 & array2).size > 0`
|
13
15
|
#
|
14
16
|
# can be replaced with `array1.intersect?(array2)`.
|
15
17
|
#
|
@@ -51,6 +53,19 @@ module RuboCop
|
|
51
53
|
# array1.intersect?(array2)
|
52
54
|
# !array1.intersect?(array2)
|
53
55
|
#
|
56
|
+
# # bad
|
57
|
+
# (array1 & array2).count > 0
|
58
|
+
# (array1 & array2).count.positive?
|
59
|
+
# (array1 & array2).count != 0
|
60
|
+
#
|
61
|
+
# (array1 & array2).count == 0
|
62
|
+
# (array1 & array2).count.zero?
|
63
|
+
#
|
64
|
+
# # good
|
65
|
+
# array1.intersect?(array2)
|
66
|
+
#
|
67
|
+
# !array1.intersect?(array2)
|
68
|
+
#
|
54
69
|
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
55
70
|
# # good
|
56
71
|
# (array1 & array2).present?
|
@@ -73,9 +88,11 @@ module RuboCop
|
|
73
88
|
PREDICATES = %i[any? empty? none?].to_set.freeze
|
74
89
|
ACTIVE_SUPPORT_PREDICATES = (PREDICATES + %i[present? blank?]).freeze
|
75
90
|
|
91
|
+
ARRAY_SIZE_METHODS = %i[count length size].to_set.freeze
|
92
|
+
|
76
93
|
# @!method bad_intersection_check?(node, predicates)
|
77
94
|
def_node_matcher :bad_intersection_check?, <<~PATTERN
|
78
|
-
(call
|
95
|
+
$(call
|
79
96
|
{
|
80
97
|
(begin (send $_ :& $_))
|
81
98
|
(call $_ :intersection $_)
|
@@ -84,6 +101,20 @@ module RuboCop
|
|
84
101
|
)
|
85
102
|
PATTERN
|
86
103
|
|
104
|
+
# @!method intersection_size_check?(node, predicates)
|
105
|
+
def_node_matcher :intersection_size_check?, <<~PATTERN
|
106
|
+
(call
|
107
|
+
$(call
|
108
|
+
{
|
109
|
+
(begin (send $_ :& $_))
|
110
|
+
(call $_ :intersection $_)
|
111
|
+
}
|
112
|
+
%ARRAY_SIZE_METHODS
|
113
|
+
)
|
114
|
+
{$:> (int 0) | $:positive? | $:!= (int 0) | $:== (int 0) | $:zero?}
|
115
|
+
)
|
116
|
+
PATTERN
|
117
|
+
|
87
118
|
# @!method any_none_block_intersection(node)
|
88
119
|
def_node_matcher :any_none_block_intersection, <<~PATTERN
|
89
120
|
{
|
@@ -104,15 +135,15 @@ module RuboCop
|
|
104
135
|
PATTERN
|
105
136
|
|
106
137
|
MSG = 'Use `%<replacement>s` instead of `%<existing>s`.'
|
107
|
-
STRAIGHT_METHODS = %i[present? any?].freeze
|
108
|
-
NEGATED_METHODS = %i[blank? empty? none?].freeze
|
138
|
+
STRAIGHT_METHODS = %i[present? any? > positive? !=].freeze
|
139
|
+
NEGATED_METHODS = %i[blank? empty? none? == zero?].freeze
|
109
140
|
RESTRICT_ON_SEND = (STRAIGHT_METHODS + NEGATED_METHODS).freeze
|
110
141
|
|
111
142
|
def on_send(node)
|
112
143
|
return if node.block_literal?
|
113
|
-
return unless (receiver, argument, method_name = bad_intersection?(node))
|
144
|
+
return unless (dot_node, receiver, argument, method_name = bad_intersection?(node))
|
114
145
|
|
115
|
-
dot =
|
146
|
+
dot = dot_node.loc.dot.source
|
116
147
|
bang = straight?(method_name) ? '' : '!'
|
117
148
|
replacement = "#{bang}#{receiver.source}#{dot}intersect?(#{argument.source})"
|
118
149
|
|
@@ -135,13 +166,16 @@ module RuboCop
|
|
135
166
|
private
|
136
167
|
|
137
168
|
def bad_intersection?(node)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
PREDICATES
|
142
|
-
end
|
169
|
+
bad_intersection_check?(node, bad_intersection_predicates) ||
|
170
|
+
intersection_size_check?(node)
|
171
|
+
end
|
143
172
|
|
144
|
-
|
173
|
+
def bad_intersection_predicates
|
174
|
+
if active_support_extensions_enabled?
|
175
|
+
ACTIVE_SUPPORT_PREDICATES
|
176
|
+
else
|
177
|
+
PREDICATES
|
178
|
+
end
|
145
179
|
end
|
146
180
|
|
147
181
|
def straight?(method_name)
|
@@ -70,18 +70,25 @@ module RuboCop
|
|
70
70
|
(send _ :& _))
|
71
71
|
PATTERN
|
72
72
|
|
73
|
+
# rubocop:disable Metrics/AbcSize
|
73
74
|
def on_send(node)
|
74
75
|
return unless node.receiver&.begin_type?
|
75
76
|
return unless (preferred_method = preferred_method(node))
|
76
77
|
|
77
78
|
bit_operation = node.receiver.children.first
|
78
79
|
lhs, _operator, rhs = *bit_operation
|
79
|
-
|
80
|
+
|
81
|
+
preferred = if preferred_method == 'allbits?' && lhs.source == node.first_argument.source
|
82
|
+
"#{rhs.source}.allbits?(#{lhs.source})"
|
83
|
+
else
|
84
|
+
"#{lhs.source}.#{preferred_method}(#{rhs.source})"
|
85
|
+
end
|
80
86
|
|
81
87
|
add_offense(node, message: format(MSG, preferred: preferred)) do |corrector|
|
82
88
|
corrector.replace(node, preferred)
|
83
89
|
end
|
84
90
|
end
|
91
|
+
# rubocop:enable Metrics/AbcSize
|
85
92
|
|
86
93
|
private
|
87
94
|
|
@@ -68,7 +68,7 @@ module RuboCop
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def autocorrect(corrector, node)
|
71
|
-
if node.
|
71
|
+
if node.post_condition_loop?
|
72
72
|
replace_begin_end_with_modifier(corrector, node)
|
73
73
|
elsif node.modifier_form?
|
74
74
|
replace_source(corrector, node.source_range, modifier_replacement(node))
|
@@ -85,6 +85,29 @@ module RuboCop
|
|
85
85
|
end
|
86
86
|
alias on_defs on_def
|
87
87
|
|
88
|
+
def on_if(node)
|
89
|
+
return if node.modifier_form?
|
90
|
+
|
91
|
+
inspect_branches(node)
|
92
|
+
end
|
93
|
+
|
94
|
+
def on_case(node)
|
95
|
+
inspect_branches(node)
|
96
|
+
end
|
97
|
+
alias on_case_match on_case
|
98
|
+
|
99
|
+
def on_while(node)
|
100
|
+
return if node.modifier_form?
|
101
|
+
|
102
|
+
body = node.body
|
103
|
+
|
104
|
+
return unless body&.kwbegin_type?
|
105
|
+
return if body.rescue_node || body.ensure_node
|
106
|
+
|
107
|
+
register_offense(body)
|
108
|
+
end
|
109
|
+
alias on_until on_while
|
110
|
+
|
88
111
|
def on_block(node)
|
89
112
|
return if target_ruby_version < 2.5
|
90
113
|
return if node.send_node.lambda_literal?
|
@@ -199,6 +222,15 @@ module RuboCop
|
|
199
222
|
def valid_begin_assignment?(node)
|
200
223
|
node.parent&.assignment? && !node.children.one?
|
201
224
|
end
|
225
|
+
|
226
|
+
def inspect_branches(node)
|
227
|
+
node.branches.each do |branch|
|
228
|
+
next unless branch&.kwbegin_type?
|
229
|
+
next if branch.rescue_node || branch.ensure_node
|
230
|
+
|
231
|
+
register_offense(branch)
|
232
|
+
end
|
233
|
+
end
|
202
234
|
end
|
203
235
|
end
|
204
236
|
end
|
@@ -247,7 +247,7 @@ module RuboCop
|
|
247
247
|
"#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
|
248
248
|
elsif if_branch.true_type?
|
249
249
|
condition = if_branch.parent.condition
|
250
|
-
return condition.source if condition.arguments.empty?
|
250
|
+
return condition.source if condition.arguments.empty? || condition.parenthesized?
|
251
251
|
|
252
252
|
wrap_arguments_with_parens(condition)
|
253
253
|
else
|
@@ -220,7 +220,7 @@ module RuboCop
|
|
220
220
|
end
|
221
221
|
|
222
222
|
def call_node?(node)
|
223
|
-
node.call_type? || (node.any_block_type? && !node.lambda_or_proc?)
|
223
|
+
node.call_type? || (node.any_block_type? && node.braces? && !node.lambda_or_proc?)
|
224
224
|
end
|
225
225
|
|
226
226
|
def check_send(begin_node, node)
|
@@ -142,6 +142,7 @@ module RuboCop
|
|
142
142
|
# @!method strip_begin(node)
|
143
143
|
def_node_matcher :strip_begin, '{ (begin $!begin) $!(begin) }'
|
144
144
|
|
145
|
+
# rubocop:disable Metrics/AbcSize
|
145
146
|
def on_if(node)
|
146
147
|
return if allowed_if_condition?(node)
|
147
148
|
|
@@ -155,9 +156,11 @@ module RuboCop
|
|
155
156
|
removal_ranges = [begin_range(node, body), end_range(node, body)]
|
156
157
|
|
157
158
|
report_offense(node, method_chain, method_call, *removal_ranges) do |corrector|
|
159
|
+
corrector.replace(receiver, checked_variable.source) if checked_variable.csend_type?
|
158
160
|
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
159
161
|
end
|
160
162
|
end
|
163
|
+
# rubocop:enable Metrics/AbcSize
|
161
164
|
|
162
165
|
def on_and(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
163
166
|
collect_and_clauses(node).each do |(lhs, lhs_operator_range), (rhs, _rhs_operator_range)|
|
@@ -335,8 +338,16 @@ module RuboCop
|
|
335
338
|
|
336
339
|
def matching_call_nodes?(left, right)
|
337
340
|
return false unless left && right.respond_to?(:call_type?)
|
341
|
+
return false unless left.call_type? && right.call_type?
|
338
342
|
|
339
|
-
|
343
|
+
# Compare receiver and method name, but ignore the difference between
|
344
|
+
# safe navigation method call (`&.`) and dot method call (`.`).
|
345
|
+
left_receiver, left_method, *left_args = left.children
|
346
|
+
right_receiver, right_method, *right_args = right.children
|
347
|
+
|
348
|
+
left_method == right_method &&
|
349
|
+
matching_nodes?(left_receiver, right_receiver) &&
|
350
|
+
left_args == right_args
|
340
351
|
end
|
341
352
|
|
342
353
|
def chain_length(method_chain, method)
|
@@ -81,7 +81,7 @@ module RuboCop
|
|
81
81
|
|
82
82
|
content = *sym
|
83
83
|
content = content.map { |c| c.is_a?(AST::Node) ? c.source : c }.join
|
84
|
-
content_without_delimiter_pairs = content.gsub(/(\[[^\s\[\]]*\])|(\([^\s
|
84
|
+
content_without_delimiter_pairs = content.gsub(/(\[[^\s\[\]]*\])|(\([^\s()]*\))/, '')
|
85
85
|
|
86
86
|
content.include?(' ') || DELIMITERS.any? do |delimiter|
|
87
87
|
content_without_delimiter_pairs.include?(delimiter)
|
@@ -238,11 +238,16 @@ module RuboCop
|
|
238
238
|
end
|
239
239
|
|
240
240
|
def process_loop(node)
|
241
|
-
if
|
241
|
+
if node.post_condition_loop?
|
242
242
|
# See the comment at the end of file for this behavior.
|
243
243
|
condition_node, body_node = *node
|
244
244
|
process_node(body_node)
|
245
245
|
process_node(condition_node)
|
246
|
+
elsif node.for_type?
|
247
|
+
# In `for item in items` the rightmost expression is evaluated first.
|
248
|
+
process_node(node.collection)
|
249
|
+
process_node(node.variable)
|
250
|
+
process_node(node.body) if node.body
|
246
251
|
else
|
247
252
|
process_children(node)
|
248
253
|
end
|
@@ -356,17 +361,14 @@ module RuboCop
|
|
356
361
|
end
|
357
362
|
|
358
363
|
def reference_assignments(loop_assignments, loop_node)
|
359
|
-
node = loop_assignments.first.node
|
360
|
-
|
361
364
|
# If inside a branching statement, mark all as referenced.
|
362
365
|
# Otherwise, mark only the last assignment as referenced.
|
363
366
|
# Note that `rescue` must be considered as branching because of
|
364
367
|
# the `retry` keyword.
|
365
|
-
|
366
|
-
|
367
|
-
else
|
368
|
-
loop_assignments.last&.reference!(loop_node)
|
368
|
+
loop_assignments.each do |assignment|
|
369
|
+
assignment.reference!(loop_node) if assignment.node.each_ancestor(*BRANCH_NODES).any?
|
369
370
|
end
|
371
|
+
loop_assignments.last&.reference!(loop_node)
|
370
372
|
end
|
371
373
|
|
372
374
|
def scanned_node?(node)
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
module Formatter
|
5
5
|
# This formatter displays a YAML configuration file where all cops that
|
6
6
|
# detected any offenses are configured to not detect the offense.
|
7
|
-
class DisabledConfigFormatter < BaseFormatter
|
7
|
+
class DisabledConfigFormatter < BaseFormatter # rubocop:disable Metrics/ClassLength
|
8
8
|
include PathUtil
|
9
9
|
|
10
10
|
HEADING = <<~COMMENTS
|
@@ -17,6 +17,22 @@ module RuboCop
|
|
17
17
|
# versions of RuboCop, may require this file to be generated again.
|
18
18
|
COMMENTS
|
19
19
|
|
20
|
+
EXCLUDED_CONFIG_KEYS = %w[
|
21
|
+
AutoCorrect
|
22
|
+
Description
|
23
|
+
Enabled
|
24
|
+
Exclude
|
25
|
+
Include
|
26
|
+
Reference
|
27
|
+
References
|
28
|
+
Safe
|
29
|
+
SafeAutoCorrect
|
30
|
+
StyleGuide
|
31
|
+
VersionAdded
|
32
|
+
VersionChanged
|
33
|
+
VersionRemoved
|
34
|
+
].freeze
|
35
|
+
|
20
36
|
@config_to_allow_offenses = {}
|
21
37
|
@detected_styles = {}
|
22
38
|
|
@@ -163,10 +179,7 @@ module RuboCop
|
|
163
179
|
end
|
164
180
|
|
165
181
|
def cop_config_params(default_cfg, cfg)
|
166
|
-
default_cfg.keys -
|
167
|
-
%w[Description StyleGuide Reference References Enabled Exclude Safe
|
168
|
-
SafeAutoCorrect VersionAdded VersionChanged VersionRemoved] -
|
169
|
-
cfg.keys
|
182
|
+
default_cfg.keys - EXCLUDED_CONFIG_KEYS - cfg.keys
|
170
183
|
end
|
171
184
|
|
172
185
|
def output_cop_param_comments(output_buffer, params, default_cfg)
|
data/lib/rubocop/lsp/routes.rb
CHANGED
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
|
52
52
|
document_formatting_provider: true,
|
53
53
|
text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
|
54
|
-
change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::
|
54
|
+
change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::INCREMENTAL,
|
55
55
|
open_close: true
|
56
56
|
)
|
57
57
|
)
|
@@ -76,7 +76,12 @@ module RuboCop
|
|
76
76
|
|
77
77
|
handle 'textDocument/didChange' do |request|
|
78
78
|
params = request[:params]
|
79
|
-
|
79
|
+
file_uri = params[:textDocument][:uri]
|
80
|
+
text = @text_cache[file_uri]
|
81
|
+
params[:contentChanges].each do |content|
|
82
|
+
text = change_text(text, content[:text], content[:range])
|
83
|
+
end
|
84
|
+
result = diagnostic(file_uri, text)
|
80
85
|
@server.write(result)
|
81
86
|
end
|
82
87
|
|
@@ -219,6 +224,30 @@ module RuboCop
|
|
219
224
|
}
|
220
225
|
end
|
221
226
|
|
227
|
+
def change_text(orig_text, text, range)
|
228
|
+
return text unless range
|
229
|
+
|
230
|
+
start_pos = text_pos(orig_text, range[:start])
|
231
|
+
end_pos = text_pos(orig_text, range[:end])
|
232
|
+
text_bin = orig_text.b
|
233
|
+
text_bin[start_pos...end_pos] = text.b
|
234
|
+
text_bin.force_encoding(orig_text.encoding)
|
235
|
+
end
|
236
|
+
|
237
|
+
def text_pos(text, range)
|
238
|
+
line = range[:line]
|
239
|
+
char = range[:character]
|
240
|
+
pos = 0
|
241
|
+
text.each_line.with_index do |l, i|
|
242
|
+
if i == line
|
243
|
+
pos += l.encode('utf-16be').b[0, char * 2].encode('utf-8', 'utf-16be').bytesize
|
244
|
+
return pos
|
245
|
+
end
|
246
|
+
pos += l.bytesize
|
247
|
+
end
|
248
|
+
pos
|
249
|
+
end
|
250
|
+
|
222
251
|
def convert_file_uri_to_path(uri)
|
223
252
|
URI.decode_www_form_component(uri.delete_prefix('file://'))
|
224
253
|
end
|
@@ -42,14 +42,12 @@ module RuboCop
|
|
42
42
|
# Support Windows: Backslashes from command-line -> forward slashes
|
43
43
|
base_dir = base_dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
44
44
|
all_files = find_files(base_dir, File::FNM_DOTMATCH)
|
45
|
-
# use file.include? for performance optimization
|
46
|
-
hidden_files = all_files.select { |file| file.include?(HIDDEN_PATH_SUBSTRING) }.sort
|
47
45
|
base_dir_config = @config_store.for(base_dir)
|
48
46
|
|
49
|
-
target_files = if
|
47
|
+
target_files = if hidden_path?(base_dir)
|
50
48
|
all_files.select { |file| ruby_file?(file) }
|
51
49
|
else
|
52
|
-
all_files.select { |file| to_inspect?(file,
|
50
|
+
all_files.select { |file| to_inspect?(file, base_dir_config) }
|
53
51
|
end
|
54
52
|
|
55
53
|
target_files.sort_by!(&order)
|
@@ -74,18 +72,20 @@ module RuboCop
|
|
74
72
|
|
75
73
|
private
|
76
74
|
|
77
|
-
def to_inspect?(file,
|
75
|
+
def to_inspect?(file, base_dir_config)
|
78
76
|
return false if base_dir_config.file_to_exclude?(file)
|
79
|
-
return true if !
|
80
|
-
file <=> hidden_file
|
81
|
-
end && ruby_file?(file)
|
77
|
+
return true if !hidden_path?(file) && ruby_file?(file)
|
82
78
|
|
83
79
|
base_dir_config.file_to_include?(file)
|
84
80
|
end
|
85
81
|
|
82
|
+
def hidden_path?(path)
|
83
|
+
path.include?(HIDDEN_PATH_SUBSTRING)
|
84
|
+
end
|
85
|
+
|
86
86
|
def wanted_dir_patterns(base_dir, exclude_pattern, flags)
|
87
87
|
# Escape glob characters in base_dir to avoid unwanted behavior.
|
88
|
-
base_dir = base_dir.gsub(/[
|
88
|
+
base_dir = base_dir.gsub(/[\\{}\[\]*?]/) do |reserved_glob_character|
|
89
89
|
"\\#{reserved_glob_character}"
|
90
90
|
end
|
91
91
|
|
data/lib/rubocop/version.rb
CHANGED
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.
|
4
|
+
version: 1.80.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
- Yuji Nakayama
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-08-
|
12
|
+
date: 2025-08-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
@@ -1090,9 +1090,9 @@ licenses:
|
|
1090
1090
|
- MIT
|
1091
1091
|
metadata:
|
1092
1092
|
homepage_uri: https://rubocop.org/
|
1093
|
-
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.
|
1093
|
+
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.80.0
|
1094
1094
|
source_code_uri: https://github.com/rubocop/rubocop/
|
1095
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
1095
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.80/
|
1096
1096
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
1097
1097
|
rubygems_mfa_required: 'true'
|
1098
1098
|
rdoc_options: []
|