rubocop 1.79.2 → 1.81.6
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/config/default.yml +14 -2
- data/exe/rubocop +1 -8
- data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
- data/lib/rubocop/cli.rb +6 -2
- data/lib/rubocop/config_loader.rb +3 -1
- data/lib/rubocop/config_store.rb +5 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +4 -4
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +7 -4
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +0 -5
- data/lib/rubocop/cop/layout/line_length.rb +9 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +8 -0
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +13 -7
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -2
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +6 -5
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/void.rb +7 -0
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +15 -2
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/array_intersect.rb +46 -12
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +7 -3
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +15 -2
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
- data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
- data/lib/rubocop/cop/style/redundant_begin.rb +34 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +26 -5
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -11
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +18 -1
- data/lib/rubocop/cop/style/semicolon.rb +20 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +9 -7
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/formatter/disabled_config_formatter.rb +18 -5
- data/lib/rubocop/lsp/diagnostic.rb +21 -20
- data/lib/rubocop/lsp/routes.rb +62 -6
- data/lib/rubocop/lsp/runtime.rb +2 -2
- data/lib/rubocop/lsp/server.rb +2 -2
- data/lib/rubocop/lsp/stdin_runner.rb +0 -16
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/runner.rb +6 -4
- data/lib/rubocop/target_finder.rb +9 -9
- data/lib/rubocop/target_ruby.rb +10 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +7 -6
|
@@ -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)
|
|
@@ -194,10 +194,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
194
194
|
|
|
195
195
|
def configurations(department, cop, cop_config)
|
|
196
196
|
header = ['Name', 'Default value', 'Configurable values']
|
|
197
|
-
configs = cop_config
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
configs = cop_config.each_key.reject do |key|
|
|
198
|
+
key == 'AllowMultipleStyles' ||
|
|
199
|
+
(key != 'SupportedTypes' && key.start_with?('Supported'))
|
|
200
|
+
end
|
|
201
201
|
return '' if configs.empty?
|
|
202
202
|
|
|
203
203
|
content = configs.map do |name|
|
|
@@ -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)
|
|
@@ -16,8 +16,8 @@ module RuboCop
|
|
|
16
16
|
# Diagnostic for Language Server Protocol of RuboCop.
|
|
17
17
|
# @api private
|
|
18
18
|
class Diagnostic
|
|
19
|
-
def initialize(
|
|
20
|
-
@
|
|
19
|
+
def initialize(position_encoding, offense, uri, cop_class)
|
|
20
|
+
@position_encoding = position_encoding
|
|
21
21
|
@offense = offense
|
|
22
22
|
@uri = uri
|
|
23
23
|
@cop_class = cop_class
|
|
@@ -45,11 +45,11 @@ module RuboCop
|
|
|
45
45
|
range: LanguageServer::Protocol::Interface::Range.new(
|
|
46
46
|
start: LanguageServer::Protocol::Interface::Position.new(
|
|
47
47
|
line: @offense.line - 1,
|
|
48
|
-
character: highlighted.begin_pos
|
|
48
|
+
character: to_position_character(highlighted.begin_pos)
|
|
49
49
|
),
|
|
50
50
|
end: LanguageServer::Protocol::Interface::Position.new(
|
|
51
51
|
line: @offense.line - 1,
|
|
52
|
-
character: highlighted.end_pos
|
|
52
|
+
character: to_position_character(highlighted.end_pos)
|
|
53
53
|
)
|
|
54
54
|
),
|
|
55
55
|
data: {
|
|
@@ -107,11 +107,11 @@ module RuboCop
|
|
|
107
107
|
range: LanguageServer::Protocol::Interface::Range.new(
|
|
108
108
|
start: LanguageServer::Protocol::Interface::Position.new(
|
|
109
109
|
line: range.line - 1,
|
|
110
|
-
character: range.column
|
|
110
|
+
character: to_position_character(range.column)
|
|
111
111
|
),
|
|
112
112
|
end: LanguageServer::Protocol::Interface::Position.new(
|
|
113
113
|
line: range.last_line - 1,
|
|
114
|
-
character: range.last_column
|
|
114
|
+
character: to_position_character(range.last_column)
|
|
115
115
|
)
|
|
116
116
|
),
|
|
117
117
|
new_text: replacement
|
|
@@ -149,7 +149,7 @@ module RuboCop
|
|
|
149
149
|
|
|
150
150
|
eol = LanguageServer::Protocol::Interface::Position.new(
|
|
151
151
|
line: @offense.line - 1,
|
|
152
|
-
character:
|
|
152
|
+
character: to_position_character
|
|
153
153
|
)
|
|
154
154
|
|
|
155
155
|
# TODO: fails for multiline strings - may be preferable to use block
|
|
@@ -162,19 +162,6 @@ module RuboCop
|
|
|
162
162
|
[inline_comment]
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
-
def length_of_line(line)
|
|
166
|
-
if @document_encoding == Encoding::UTF_16LE
|
|
167
|
-
line_length = 0
|
|
168
|
-
line.codepoints.each do |codepoint|
|
|
169
|
-
line_length += 1
|
|
170
|
-
line_length += 1 if codepoint > RubyLsp::Document::Scanner::SURROGATE_PAIR_START
|
|
171
|
-
end
|
|
172
|
-
line_length
|
|
173
|
-
else
|
|
174
|
-
line.length
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
165
|
def correctable?
|
|
179
166
|
!@offense.corrector.nil?
|
|
180
167
|
end
|
|
@@ -184,6 +171,20 @@ module RuboCop
|
|
|
184
171
|
uri.scheme = 'file' if uri.scheme.nil?
|
|
185
172
|
uri
|
|
186
173
|
end
|
|
174
|
+
|
|
175
|
+
def to_position_character(utf8_index = nil)
|
|
176
|
+
str = utf8_index ? @offense.source_line[0, utf8_index] : @offense.source_line
|
|
177
|
+
case @position_encoding
|
|
178
|
+
when 'utf-8', Encoding::UTF_8
|
|
179
|
+
str.bytesize
|
|
180
|
+
when 'utf-32', Encoding::UTF_32
|
|
181
|
+
str.size
|
|
182
|
+
else # 'utf-16'
|
|
183
|
+
# utf-16 is default position encoding on LSP
|
|
184
|
+
# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
|
|
185
|
+
str.size + str.count("\u{10000}-\u{10FFFF}")
|
|
186
|
+
end
|
|
187
|
+
end
|
|
187
188
|
end
|
|
188
189
|
end
|
|
189
190
|
end
|
data/lib/rubocop/lsp/routes.rb
CHANGED
|
@@ -15,7 +15,7 @@ module RuboCop
|
|
|
15
15
|
module LSP
|
|
16
16
|
# Routes for Language Server Protocol of RuboCop.
|
|
17
17
|
# @api private
|
|
18
|
-
class Routes
|
|
18
|
+
class Routes # rubocop:disable Metrics/ClassLength
|
|
19
19
|
CONFIGURATION_FILE_PATTERNS = [
|
|
20
20
|
RuboCop::ConfigFinder::DOTFILE,
|
|
21
21
|
RuboCop::CLI::Command::AutoGenerateConfig::AUTO_GENERATED_FILE
|
|
@@ -42,6 +42,7 @@ module RuboCop
|
|
|
42
42
|
|
|
43
43
|
handle 'initialize' do |request|
|
|
44
44
|
initialization_options = extract_initialization_options_from(request)
|
|
45
|
+
@position_encoding = initialization_options[:position_encoding]
|
|
45
46
|
|
|
46
47
|
@server.configure(initialization_options)
|
|
47
48
|
|
|
@@ -51,9 +52,10 @@ module RuboCop
|
|
|
51
52
|
capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
|
|
52
53
|
document_formatting_provider: true,
|
|
53
54
|
text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
|
|
54
|
-
change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::
|
|
55
|
+
change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::INCREMENTAL,
|
|
55
56
|
open_close: true
|
|
56
|
-
)
|
|
57
|
+
),
|
|
58
|
+
position_encoding: @position_encoding
|
|
57
59
|
)
|
|
58
60
|
)
|
|
59
61
|
)
|
|
@@ -76,7 +78,12 @@ module RuboCop
|
|
|
76
78
|
|
|
77
79
|
handle 'textDocument/didChange' do |request|
|
|
78
80
|
params = request[:params]
|
|
79
|
-
|
|
81
|
+
file_uri = params[:textDocument][:uri]
|
|
82
|
+
text = @text_cache[file_uri]
|
|
83
|
+
params[:contentChanges].each do |content|
|
|
84
|
+
text = change_text(text, content[:text], content[:range])
|
|
85
|
+
end
|
|
86
|
+
result = diagnostic(file_uri, text)
|
|
80
87
|
@server.write(result)
|
|
81
88
|
end
|
|
82
89
|
|
|
@@ -179,14 +186,26 @@ module RuboCop
|
|
|
179
186
|
|
|
180
187
|
def extract_initialization_options_from(request)
|
|
181
188
|
safe_autocorrect = request.dig(:params, :initializationOptions, :safeAutocorrect)
|
|
189
|
+
position_encodings = request.dig(:params, :capabilities, :general, :positionEncodings)
|
|
182
190
|
|
|
183
191
|
{
|
|
184
192
|
safe_autocorrect: safe_autocorrect.nil? || safe_autocorrect == true,
|
|
185
193
|
lint_mode: request.dig(:params, :initializationOptions, :lintMode) == true,
|
|
186
|
-
layout_mode: request.dig(:params, :initializationOptions, :layoutMode) == true
|
|
194
|
+
layout_mode: request.dig(:params, :initializationOptions, :layoutMode) == true,
|
|
195
|
+
position_encoding: position_encoding(position_encodings)
|
|
187
196
|
}
|
|
188
197
|
end
|
|
189
198
|
|
|
199
|
+
def position_encoding(position_encodings)
|
|
200
|
+
if position_encodings&.include?('utf-8')
|
|
201
|
+
'utf-8'
|
|
202
|
+
elsif position_encodings&.include?('utf-32')
|
|
203
|
+
'utf-32'
|
|
204
|
+
else
|
|
205
|
+
'utf-16'
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
190
209
|
def format_file(file_uri, command: nil)
|
|
191
210
|
unless (text = @text_cache[file_uri])
|
|
192
211
|
Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
|
|
@@ -214,11 +233,48 @@ module RuboCop
|
|
|
214
233
|
method: 'textDocument/publishDiagnostics',
|
|
215
234
|
params: {
|
|
216
235
|
uri: file_uri,
|
|
217
|
-
diagnostics: @server.offenses(convert_file_uri_to_path(file_uri),
|
|
236
|
+
diagnostics: @server.offenses(convert_file_uri_to_path(file_uri),
|
|
237
|
+
text, @position_encoding)
|
|
218
238
|
}
|
|
219
239
|
}
|
|
220
240
|
end
|
|
221
241
|
|
|
242
|
+
def change_text(orig_text, text, range)
|
|
243
|
+
return text unless range
|
|
244
|
+
|
|
245
|
+
start_pos = text_pos(orig_text, range[:start])
|
|
246
|
+
end_pos = text_pos(orig_text, range[:end])
|
|
247
|
+
orig_text[start_pos...end_pos] = text
|
|
248
|
+
orig_text
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def text_pos(text, range)
|
|
252
|
+
line = range[:line]
|
|
253
|
+
char = range[:character]
|
|
254
|
+
pos = 0
|
|
255
|
+
text.each_line.with_index do |l, i|
|
|
256
|
+
if i == line
|
|
257
|
+
pos += line_pos(l, char)
|
|
258
|
+
return pos
|
|
259
|
+
end
|
|
260
|
+
pos += l.size
|
|
261
|
+
end
|
|
262
|
+
pos
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def line_pos(line, char)
|
|
266
|
+
case @position_encoding
|
|
267
|
+
when 'utf-8'
|
|
268
|
+
line.byteslice(0, char).size
|
|
269
|
+
when 'utf-32'
|
|
270
|
+
char
|
|
271
|
+
else # 'utf-16'
|
|
272
|
+
# utf-16 is default position encoding on LSP
|
|
273
|
+
# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
|
|
274
|
+
line.encode('utf-16be').byteslice(0, char * 2).size
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
222
278
|
def convert_file_uri_to_path(uri)
|
|
223
279
|
URI.decode_www_form_component(uri.delete_prefix('file://'))
|
|
224
280
|
end
|
data/lib/rubocop/lsp/runtime.rb
CHANGED
|
@@ -44,14 +44,14 @@ module RuboCop
|
|
|
44
44
|
@runner.formatted_source
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
def offenses(path, text,
|
|
47
|
+
def offenses(path, text, position_encoding, prism_result: nil)
|
|
48
48
|
diagnostic_options = {}
|
|
49
49
|
diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
|
|
50
50
|
|
|
51
51
|
@runner.run(path, text, diagnostic_options, prism_result: prism_result)
|
|
52
52
|
@runner.offenses.map do |offense|
|
|
53
53
|
Diagnostic.new(
|
|
54
|
-
|
|
54
|
+
position_encoding, offense, path, @cop_registry[offense.cop_name]&.first
|
|
55
55
|
).to_lsp_diagnostic(@runner.config_for_working_directory)
|
|
56
56
|
end
|
|
57
57
|
end
|
data/lib/rubocop/lsp/server.rb
CHANGED
|
@@ -51,8 +51,8 @@ module RuboCop
|
|
|
51
51
|
@runtime.format(path, text, command: command)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
def offenses(path, text)
|
|
55
|
-
@runtime.offenses(path, text)
|
|
54
|
+
def offenses(path, text, position_encoding)
|
|
55
|
+
@runtime.offenses(path, text, position_encoding)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def configure(options)
|
|
@@ -40,7 +40,6 @@ module RuboCop
|
|
|
40
40
|
super(@options, config_store)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
# rubocop:disable Metrics/MethodLength
|
|
44
43
|
def run(path, contents, options, prism_result: nil)
|
|
45
44
|
@options = options.merge(DEFAULT_RUBOCOP_OPTIONS)
|
|
46
45
|
@options[:stdin] = contents
|
|
@@ -54,22 +53,7 @@ module RuboCop
|
|
|
54
53
|
super([path])
|
|
55
54
|
|
|
56
55
|
raise Interrupt if aborting?
|
|
57
|
-
rescue RuboCop::Runner::InfiniteCorrectionLoop => e
|
|
58
|
-
if defined?(::RubyLsp::Requests::Formatting::Error)
|
|
59
|
-
raise ::RubyLsp::Requests::Formatting::Error, e.message
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
raise e
|
|
63
|
-
rescue RuboCop::ValidationError => e
|
|
64
|
-
raise ConfigurationError, e.message
|
|
65
|
-
rescue StandardError => e
|
|
66
|
-
if defined?(::RubyLsp::Requests::Formatting::Error)
|
|
67
|
-
raise ::RubyLsp::Requests::Support::InternalRuboCopError, e
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
raise e
|
|
71
56
|
end
|
|
72
|
-
# rubocop:enable Metrics/MethodLength
|
|
73
57
|
|
|
74
58
|
def formatted_source
|
|
75
59
|
@options[:stdin]
|
data/lib/rubocop/result_cache.rb
CHANGED
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
|
9
9
|
# Provides functionality for caching RuboCop runs.
|
|
10
10
|
# @api private
|
|
11
11
|
class ResultCache
|
|
12
|
-
NON_CHANGING = %i[color format formatters out debug fail_level
|
|
12
|
+
NON_CHANGING = %i[color format formatters out debug display_time fail_level
|
|
13
13
|
fix_layout autocorrect safe_autocorrect autocorrect_all
|
|
14
14
|
cache fail_fast stdin parallel].freeze
|
|
15
15
|
|
data/lib/rubocop/runner.rb
CHANGED
|
@@ -273,7 +273,8 @@ module RuboCop
|
|
|
273
273
|
end
|
|
274
274
|
|
|
275
275
|
def do_inspection_loop(file)
|
|
276
|
-
|
|
276
|
+
# We can reuse the prism result since the source did not change yet.
|
|
277
|
+
processed_source = get_processed_source(file, @prism_result)
|
|
277
278
|
# This variable is 2d array used to track corrected offenses after each
|
|
278
279
|
# inspection iteration. This is used to output meaningful infinite loop
|
|
279
280
|
# error message.
|
|
@@ -295,7 +296,8 @@ module RuboCop
|
|
|
295
296
|
# loop if we find any.
|
|
296
297
|
break unless updated_source_file
|
|
297
298
|
|
|
298
|
-
|
|
299
|
+
# Autocorrect has happened, don't use the prism result since it is stale.
|
|
300
|
+
processed_source = get_processed_source(file, nil)
|
|
299
301
|
end
|
|
300
302
|
|
|
301
303
|
# Return summary of corrected offenses after all iterations
|
|
@@ -482,7 +484,7 @@ module RuboCop
|
|
|
482
484
|
end
|
|
483
485
|
|
|
484
486
|
# rubocop:disable Metrics/MethodLength
|
|
485
|
-
def get_processed_source(file)
|
|
487
|
+
def get_processed_source(file, prism_result)
|
|
486
488
|
config = @config_store.for_file(file)
|
|
487
489
|
ruby_version = config.target_ruby_version
|
|
488
490
|
parser_engine = config.parser_engine
|
|
@@ -493,7 +495,7 @@ module RuboCop
|
|
|
493
495
|
ruby_version,
|
|
494
496
|
file,
|
|
495
497
|
parser_engine: parser_engine,
|
|
496
|
-
prism_result:
|
|
498
|
+
prism_result: prism_result
|
|
497
499
|
)
|
|
498
500
|
else
|
|
499
501
|
begin
|
|
@@ -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/target_ruby.rb
CHANGED
|
@@ -110,8 +110,17 @@ module RuboCop
|
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
def version_from_gemspec_file(file)
|
|
113
|
+
# When using parser_prism, we need to use a Ruby version that Prism supports (3.3+)
|
|
114
|
+
# for parsing the gemspec file. This doesn't affect the detected Ruby version,
|
|
115
|
+
# it's just for the parsing step.
|
|
116
|
+
ruby_version_for_parsing = if @config.parser_engine == :parser_prism
|
|
117
|
+
3.3
|
|
118
|
+
else
|
|
119
|
+
DEFAULT_VERSION
|
|
120
|
+
end
|
|
121
|
+
|
|
113
122
|
processed_source = ProcessedSource.from_file(
|
|
114
|
-
file,
|
|
123
|
+
file, ruby_version_for_parsing, parser_engine: @config.parser_engine
|
|
115
124
|
)
|
|
116
125
|
return unless processed_source.valid_syntax?
|
|
117
126
|
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
|
@@ -489,6 +489,7 @@ require_relative 'rubocop/cop/style/arguments_forwarding'
|
|
|
489
489
|
require_relative 'rubocop/cop/style/array_coercion'
|
|
490
490
|
require_relative 'rubocop/cop/style/array_first_last'
|
|
491
491
|
require_relative 'rubocop/cop/style/array_intersect'
|
|
492
|
+
require_relative 'rubocop/cop/style/array_intersect_with_single_element'
|
|
492
493
|
require_relative 'rubocop/cop/style/array_join'
|
|
493
494
|
require_relative 'rubocop/cop/style/ascii_comments'
|
|
494
495
|
require_relative 'rubocop/cop/style/attr'
|
|
@@ -8,7 +8,10 @@ module RubyLsp
|
|
|
8
8
|
module RuboCop
|
|
9
9
|
# A Ruby LSP add-on for RuboCop.
|
|
10
10
|
class Addon < RubyLsp::Addon
|
|
11
|
-
|
|
11
|
+
RESTART_WATCHERS = %w[.rubocop.yml .rubocop_todo.yml .rubocop].freeze
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
super
|
|
12
15
|
@runtime_adapter = nil
|
|
13
16
|
end
|
|
14
17
|
|
|
@@ -16,12 +19,16 @@ module RubyLsp
|
|
|
16
19
|
'RuboCop'
|
|
17
20
|
end
|
|
18
21
|
|
|
22
|
+
def version
|
|
23
|
+
::RuboCop::Version::STRING
|
|
24
|
+
end
|
|
25
|
+
|
|
19
26
|
def activate(global_state, message_queue)
|
|
20
27
|
::RuboCop::LSP::Logger.log(
|
|
21
28
|
"Activating RuboCop LSP addon #{::RuboCop::Version::STRING}.", prefix: '[RuboCop]'
|
|
22
29
|
)
|
|
23
30
|
|
|
24
|
-
@runtime_adapter = RuntimeAdapter.new
|
|
31
|
+
@runtime_adapter = RuntimeAdapter.new(message_queue)
|
|
25
32
|
global_state.register_formatter('rubocop', @runtime_adapter)
|
|
26
33
|
register_additional_file_watchers(global_state, message_queue)
|
|
27
34
|
|
|
@@ -49,7 +56,7 @@ module RubyLsp
|
|
|
49
56
|
register_options: Interface::DidChangeWatchedFilesRegistrationOptions.new(
|
|
50
57
|
watchers: [
|
|
51
58
|
Interface::FileSystemWatcher.new(
|
|
52
|
-
glob_pattern:
|
|
59
|
+
glob_pattern: "**/{#{RESTART_WATCHERS.join(',')}}",
|
|
53
60
|
kind: Constant::WatchKind::CREATE | Constant::WatchKind::CHANGE | Constant::WatchKind::DELETE
|
|
54
61
|
)
|
|
55
62
|
]
|
|
@@ -62,13 +69,21 @@ module RubyLsp
|
|
|
62
69
|
# rubocop:enable Metrics/MethodLength
|
|
63
70
|
|
|
64
71
|
def workspace_did_change_watched_files(changes)
|
|
65
|
-
|
|
72
|
+
if (changed_config_file = changed_config_file(changes))
|
|
73
|
+
@runtime_adapter.reload_config
|
|
74
|
+
|
|
75
|
+
::RuboCop::LSP::Logger.log(<<~MESSAGE, prefix: '[RuboCop]')
|
|
76
|
+
Re-initialized RuboCop LSP addon #{::RuboCop::Version::STRING} due to #{changed_config_file} change.
|
|
77
|
+
MESSAGE
|
|
78
|
+
end
|
|
79
|
+
end
|
|
66
80
|
|
|
67
|
-
|
|
81
|
+
private
|
|
68
82
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
83
|
+
def changed_config_file(changes)
|
|
84
|
+
RESTART_WATCHERS.find do |file_name|
|
|
85
|
+
changes.any? { |change| change[:uri].end_with?(file_name) }
|
|
86
|
+
end
|
|
72
87
|
end
|
|
73
88
|
end
|
|
74
89
|
end
|
|
@@ -7,30 +7,45 @@ module RubyLsp
|
|
|
7
7
|
# Provides an adapter to bridge RuboCop's built-in LSP runtime with Ruby LSP's add-on.
|
|
8
8
|
# @api private
|
|
9
9
|
class RuntimeAdapter
|
|
10
|
-
|
|
10
|
+
def initialize(message_queue)
|
|
11
|
+
@message_queue = message_queue
|
|
12
|
+
reload_config
|
|
13
|
+
end
|
|
11
14
|
|
|
12
|
-
def
|
|
13
|
-
|
|
15
|
+
def reload_config
|
|
16
|
+
@runtime = nil
|
|
17
|
+
options, _paths = ::RuboCop::Options.new.parse([])
|
|
14
18
|
|
|
19
|
+
config_store = ::RuboCop::ConfigStore.new
|
|
20
|
+
config_store.apply_options!(options)
|
|
15
21
|
@runtime = ::RuboCop::LSP::Runtime.new(config_store)
|
|
22
|
+
rescue ::RuboCop::Error => e
|
|
23
|
+
@message_queue << Notification.window_show_message(
|
|
24
|
+
"RuboCop configuration error: #{e.message}. Formatting will not be available.",
|
|
25
|
+
type: Constant::MessageType::ERROR
|
|
26
|
+
)
|
|
16
27
|
end
|
|
17
28
|
|
|
18
29
|
def run_diagnostic(uri, document)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
with_error_handling do
|
|
31
|
+
@runtime.offenses(
|
|
32
|
+
uri_to_path(uri),
|
|
33
|
+
document.source,
|
|
34
|
+
document.encoding,
|
|
35
|
+
prism_result: prism_result(document)
|
|
36
|
+
)
|
|
37
|
+
end
|
|
25
38
|
end
|
|
26
39
|
|
|
27
40
|
def run_formatting(uri, document)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
41
|
+
with_error_handling do
|
|
42
|
+
@runtime.format(
|
|
43
|
+
uri_to_path(uri),
|
|
44
|
+
document.source,
|
|
45
|
+
command: 'rubocop.formatAutocorrects',
|
|
46
|
+
prism_result: prism_result(document)
|
|
47
|
+
)
|
|
48
|
+
end
|
|
34
49
|
end
|
|
35
50
|
|
|
36
51
|
def run_range_formatting(_uri, _partial_source, _base_indentation)
|
|
@@ -43,6 +58,25 @@ module RubyLsp
|
|
|
43
58
|
|
|
44
59
|
private
|
|
45
60
|
|
|
61
|
+
def with_error_handling
|
|
62
|
+
return unless @runtime
|
|
63
|
+
|
|
64
|
+
yield
|
|
65
|
+
rescue StandardError => e
|
|
66
|
+
::RuboCop::LSP::Logger.log(e.full_message, prefix: '[RuboCop]')
|
|
67
|
+
|
|
68
|
+
message = if e.is_a?(::RuboCop::ErrorWithAnalyzedFileLocation)
|
|
69
|
+
"for the #{e.cop.name} cop"
|
|
70
|
+
else
|
|
71
|
+
"- #{e.message}"
|
|
72
|
+
end
|
|
73
|
+
raise Requests::Formatting::Error, <<~MSG
|
|
74
|
+
An internal error occurred #{message}.
|
|
75
|
+
Updating to a newer version of RuboCop may solve this.
|
|
76
|
+
For more details, run RuboCop on the command line.
|
|
77
|
+
MSG
|
|
78
|
+
end
|
|
79
|
+
|
|
46
80
|
# duplicated from: lib/standard/lsp/routes.rb
|
|
47
81
|
# modified to incorporate Ruby LSP's to_standardized_path method
|
|
48
82
|
def uri_to_path(uri)
|