rubocop 1.50.2 → 1.53.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 +3 -3
- data/config/default.yml +76 -6
- data/lib/rubocop/cli/command/lsp.rb +19 -0
- data/lib/rubocop/cli.rb +3 -0
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader_resolver.rb +4 -3
- data/lib/rubocop/config_obsoletion.rb +2 -2
- data/lib/rubocop/cop/base.rb +5 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +5 -5
- data/lib/rubocop/cop/layout/class_structure.rb +7 -0
- data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
- data/lib/rubocop/cop/lint/debugger.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -4
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
- data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
- data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +34 -5
- data/lib/rubocop/cop/lint/mixed_case_range.rb +109 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +5 -0
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +120 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +8 -3
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
- data/lib/rubocop/cop/lint/useless_assignment.rb +59 -1
- data/lib/rubocop/cop/lint/void.rb +63 -7
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
- data/lib/rubocop/cop/migration/department_name.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +7 -3
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +25 -10
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
- data/lib/rubocop/cop/naming/variable_name.rb +6 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +5 -1
- data/lib/rubocop/cop/style/attr.rb +11 -1
- data/lib/rubocop/cop/style/begin_block.rb +1 -2
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +3 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +17 -39
- data/lib/rubocop/cop/style/collection_compact.rb +16 -6
- data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +26 -6
- data/lib/rubocop/cop/style/conditional_assignment.rb +5 -3
- data/lib/rubocop/cop/style/copyright.rb +5 -2
- data/lib/rubocop/cop/style/dir.rb +1 -1
- data/lib/rubocop/cop/style/dir_empty.rb +8 -14
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +5 -5
- data/lib/rubocop/cop/style/exact_regexp_match.rb +68 -0
- data/lib/rubocop/cop/style/file_read.rb +2 -2
- data/lib/rubocop/cop/style/guard_clause.rb +2 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -22
- data/lib/rubocop/cop/style/hash_except.rb +19 -8
- data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +6 -2
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -6
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +3 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -1
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +101 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +7 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +86 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +3 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
- data/lib/rubocop/cop/style/require_order.rb +11 -5
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +81 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +15 -5
- data/lib/rubocop/cop/style/semicolon.rb +12 -1
- data/lib/rubocop/cop/style/signal_exception.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
- data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/regexp_ranges.rb +100 -0
- data/lib/rubocop/cop/variable_force/assignment.rb +33 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
- data/lib/rubocop/cop/variable_force.rb +1 -0
- data/lib/rubocop/cops_documentation_generator.rb +1 -1
- data/lib/rubocop/ext/regexp_parser.rb +4 -1
- data/lib/rubocop/lsp/logger.rb +22 -0
- data/lib/rubocop/lsp/routes.rb +223 -0
- data/lib/rubocop/lsp/runtime.rb +79 -0
- data/lib/rubocop/lsp/server.rb +62 -0
- data/lib/rubocop/lsp/severity.rb +27 -0
- data/lib/rubocop/options.rb +11 -1
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/server/client_command/exec.rb +2 -1
- data/lib/rubocop/target_ruby.rb +3 -2
- data/lib/rubocop/version.rb +10 -6
- data/lib/rubocop.rb +13 -0
- metadata +38 -6
@@ -0,0 +1,223 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'severity'
|
4
|
+
|
5
|
+
#
|
6
|
+
# This code is based on https://github.com/standardrb/standard.
|
7
|
+
#
|
8
|
+
# Copyright (c) 2023 Test Double, Inc.
|
9
|
+
#
|
10
|
+
# The MIT License (MIT)
|
11
|
+
#
|
12
|
+
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
13
|
+
#
|
14
|
+
module RuboCop
|
15
|
+
module Lsp
|
16
|
+
# Routes for Language Server Protocol of RuboCop.
|
17
|
+
# @api private
|
18
|
+
class Routes
|
19
|
+
def self.handle(name, &block)
|
20
|
+
define_method("handle_#{name}", &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
private_class_method :handle
|
24
|
+
|
25
|
+
def initialize(server)
|
26
|
+
@server = server
|
27
|
+
|
28
|
+
@text_cache = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def for(name)
|
32
|
+
name = "handle_#{name}"
|
33
|
+
return unless respond_to?(name)
|
34
|
+
|
35
|
+
method(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
handle 'initialize' do |request|
|
39
|
+
@server.write(
|
40
|
+
id: request[:id],
|
41
|
+
result: LanguageServer::Protocol::Interface::InitializeResult.new(
|
42
|
+
capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
|
43
|
+
document_formatting_provider: true,
|
44
|
+
diagnostic_provider: true,
|
45
|
+
text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
|
46
|
+
change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
|
47
|
+
open_close: true
|
48
|
+
)
|
49
|
+
)
|
50
|
+
)
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
handle 'initialized' do |_request|
|
55
|
+
version = RuboCop::Version::STRING
|
56
|
+
|
57
|
+
Logger.log("RuboCop #{version} language server initialized, PID #{Process.pid}")
|
58
|
+
end
|
59
|
+
|
60
|
+
handle 'shutdown' do |request|
|
61
|
+
Logger.log('Client asked to shutdown RuboCop language server.')
|
62
|
+
@server.stop do
|
63
|
+
@server.write(id: request[:id], result: nil)
|
64
|
+
Logger.log('Exiting...')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
handle 'textDocument/diagnostic' do |request|
|
69
|
+
doc = request[:params][:textDocument]
|
70
|
+
result = diagnostic(doc[:uri], doc[:text])
|
71
|
+
@server.write(result)
|
72
|
+
end
|
73
|
+
|
74
|
+
handle 'textDocument/didChange' do |request|
|
75
|
+
params = request[:params]
|
76
|
+
result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
|
77
|
+
@server.write(result)
|
78
|
+
end
|
79
|
+
|
80
|
+
handle 'textDocument/didOpen' do |request|
|
81
|
+
doc = request[:params][:textDocument]
|
82
|
+
result = diagnostic(doc[:uri], doc[:text])
|
83
|
+
@server.write(result)
|
84
|
+
end
|
85
|
+
|
86
|
+
handle 'textDocument/didClose' do |request|
|
87
|
+
@text_cache.delete(request.dig(:params, :textDocument, :uri))
|
88
|
+
end
|
89
|
+
|
90
|
+
handle 'textDocument/formatting' do |request|
|
91
|
+
uri = request[:params][:textDocument][:uri]
|
92
|
+
@server.write(id: request[:id], result: format_file(uri))
|
93
|
+
end
|
94
|
+
|
95
|
+
handle 'workspace/didChangeConfiguration' do |_request|
|
96
|
+
Logger.log('Ignoring workspace/didChangeConfiguration')
|
97
|
+
end
|
98
|
+
|
99
|
+
handle 'workspace/didChangeWatchedFiles' do |request|
|
100
|
+
changed = request[:params][:changes].any? do |change|
|
101
|
+
change[:uri].end_with?(RuboCop::ConfigFinder::DOTFILE)
|
102
|
+
end
|
103
|
+
|
104
|
+
if changed
|
105
|
+
Logger.log('Configuration file changed; restart required')
|
106
|
+
@server.stop
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
handle 'workspace/executeCommand' do |request|
|
111
|
+
if request[:params][:command] == 'rubocop.formatAutocorrects'
|
112
|
+
uri = request[:params][:arguments][0][:uri]
|
113
|
+
@server.write(
|
114
|
+
id: request[:id],
|
115
|
+
method: 'workspace/applyEdit',
|
116
|
+
params: {
|
117
|
+
label: 'Format with RuboCop autocorrects',
|
118
|
+
edit: {
|
119
|
+
changes: {
|
120
|
+
uri => format_file(uri)
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
)
|
125
|
+
else
|
126
|
+
handle_unsupported_method(request, request[:params][:command])
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
handle 'textDocument/willSave' do |_request|
|
131
|
+
# Nothing to do
|
132
|
+
end
|
133
|
+
|
134
|
+
handle 'textDocument/didSave' do |_request|
|
135
|
+
# Nothing to do
|
136
|
+
end
|
137
|
+
|
138
|
+
handle '$/cancelRequest' do |_request|
|
139
|
+
# Can't cancel anything because single-threaded
|
140
|
+
end
|
141
|
+
|
142
|
+
handle '$/setTrace' do |_request|
|
143
|
+
# No-op, we log everything
|
144
|
+
end
|
145
|
+
|
146
|
+
def handle_unsupported_method(request, method = request[:method])
|
147
|
+
@server.write(
|
148
|
+
id: request[:id],
|
149
|
+
error: LanguageServer::Protocol::Interface::ResponseError.new(
|
150
|
+
code: LanguageServer::Protocol::Constant::ErrorCodes::METHOD_NOT_FOUND,
|
151
|
+
message: "Unsupported Method: #{method}"
|
152
|
+
)
|
153
|
+
)
|
154
|
+
Logger.log("Unsupported Method: #{method}")
|
155
|
+
end
|
156
|
+
|
157
|
+
def handle_method_missing(request)
|
158
|
+
return unless request.key?(:id)
|
159
|
+
|
160
|
+
@server.write(id: request[:id], result: nil)
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def format_file(file_uri)
|
166
|
+
unless (text = @text_cache[file_uri])
|
167
|
+
Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
|
168
|
+
|
169
|
+
return []
|
170
|
+
end
|
171
|
+
|
172
|
+
new_text = @server.format(remove_file_protocol_from(file_uri), text)
|
173
|
+
|
174
|
+
return [] if new_text == text
|
175
|
+
|
176
|
+
[
|
177
|
+
newText: new_text,
|
178
|
+
range: {
|
179
|
+
start: { line: 0, character: 0 },
|
180
|
+
end: { line: text.count("\n") + 1, character: 0 }
|
181
|
+
}
|
182
|
+
]
|
183
|
+
end
|
184
|
+
|
185
|
+
def diagnostic(file_uri, text)
|
186
|
+
@text_cache[file_uri] = text
|
187
|
+
offenses = @server.offenses(remove_file_protocol_from(file_uri), text)
|
188
|
+
diagnostics = offenses.map { |offense| to_diagnostic(offense) }
|
189
|
+
|
190
|
+
{
|
191
|
+
method: 'textDocument/publishDiagnostics',
|
192
|
+
params: {
|
193
|
+
uri: file_uri,
|
194
|
+
diagnostics: diagnostics
|
195
|
+
}
|
196
|
+
}
|
197
|
+
end
|
198
|
+
|
199
|
+
def remove_file_protocol_from(uri)
|
200
|
+
uri.delete_prefix('file://')
|
201
|
+
end
|
202
|
+
|
203
|
+
def to_diagnostic(offense)
|
204
|
+
code = offense[:cop_name]
|
205
|
+
message = offense[:message]
|
206
|
+
loc = offense[:location]
|
207
|
+
rubocop_severity = offense[:severity]
|
208
|
+
severity = Severity.find_by(rubocop_severity)
|
209
|
+
|
210
|
+
{
|
211
|
+
code: code, message: message, range: to_range(loc), severity: severity, source: 'rubocop'
|
212
|
+
}
|
213
|
+
end
|
214
|
+
|
215
|
+
def to_range(location)
|
216
|
+
{
|
217
|
+
start: { character: location[:start_column] - 1, line: location[:start_line] - 1 },
|
218
|
+
end: { character: location[:last_column] - 1, line: location[:last_line] - 1 }
|
219
|
+
}
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This code is based on https://github.com/standardrb/standard.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2023 Test Double, Inc.
|
7
|
+
#
|
8
|
+
# The MIT License (MIT)
|
9
|
+
#
|
10
|
+
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
11
|
+
#
|
12
|
+
module RuboCop
|
13
|
+
module Lsp
|
14
|
+
# Runtime for Language Server Protocol of RuboCop.
|
15
|
+
# @api private
|
16
|
+
class Runtime
|
17
|
+
def initialize(config_store)
|
18
|
+
@config_store = config_store
|
19
|
+
@logged_paths = []
|
20
|
+
end
|
21
|
+
|
22
|
+
# This abuses the `--stdin` option of rubocop and reads the formatted text
|
23
|
+
# from the `options[:stdin]` that rubocop mutates. This depends on
|
24
|
+
# `parallel: false` as well as the fact that RuboCop doesn't otherwise dup
|
25
|
+
# or reassign that options object. Risky business!
|
26
|
+
#
|
27
|
+
# Reassigning `options[:stdin]` is done here:
|
28
|
+
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cop/team.rb#L131
|
29
|
+
# Printing `options[:stdin]`
|
30
|
+
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
|
31
|
+
# Setting `parallel: true` would break this here:
|
32
|
+
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
|
33
|
+
def format(path, text)
|
34
|
+
formatting_options = {
|
35
|
+
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: true
|
36
|
+
}
|
37
|
+
|
38
|
+
redirect_stdout { run_rubocop(formatting_options, path) }
|
39
|
+
|
40
|
+
formatting_options[:stdin]
|
41
|
+
end
|
42
|
+
|
43
|
+
def offenses(path, text)
|
44
|
+
diagnostic_options = {
|
45
|
+
stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'
|
46
|
+
}
|
47
|
+
|
48
|
+
json = redirect_stdout { run_rubocop(diagnostic_options, path) }
|
49
|
+
results = JSON.parse(json, symbolize_names: true)
|
50
|
+
|
51
|
+
if results[:files].empty?
|
52
|
+
unless @logged_paths.include?(path)
|
53
|
+
Logger.log "Ignoring file, per configuration: #{path}"
|
54
|
+
@logged_paths << path
|
55
|
+
end
|
56
|
+
return []
|
57
|
+
end
|
58
|
+
|
59
|
+
results.dig(:files, 0, :offenses)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def redirect_stdout(&block)
|
65
|
+
stdout = StringIO.new
|
66
|
+
|
67
|
+
RuboCop::Server::Helper.redirect(stdout: stdout, &block)
|
68
|
+
|
69
|
+
stdout.string
|
70
|
+
end
|
71
|
+
|
72
|
+
def run_rubocop(options, path)
|
73
|
+
runner = RuboCop::Runner.new(options, @config_store)
|
74
|
+
|
75
|
+
runner.run([path])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'language_server-protocol'
|
4
|
+
require_relative 'logger'
|
5
|
+
require_relative 'routes'
|
6
|
+
require_relative 'runtime'
|
7
|
+
|
8
|
+
#
|
9
|
+
# This code is based on https://github.com/standardrb/standard.
|
10
|
+
#
|
11
|
+
# Copyright (c) 2023 Test Double, Inc.
|
12
|
+
#
|
13
|
+
# The MIT License (MIT)
|
14
|
+
#
|
15
|
+
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
16
|
+
#
|
17
|
+
module RuboCop
|
18
|
+
module Lsp
|
19
|
+
# Language Server Protocol of RuboCop.
|
20
|
+
# @api private
|
21
|
+
class Server
|
22
|
+
def initialize(config_store)
|
23
|
+
@reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
|
24
|
+
@writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
|
25
|
+
@runtime = RuboCop::Lsp::Runtime.new(config_store)
|
26
|
+
@routes = Routes.new(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def start
|
30
|
+
@reader.read do |request|
|
31
|
+
if !request.key?(:method)
|
32
|
+
@routes.handle_method_missing(request)
|
33
|
+
elsif (route = @routes.for(request[:method]))
|
34
|
+
route.call(request)
|
35
|
+
else
|
36
|
+
@routes.handle_unsupported_method(request)
|
37
|
+
end
|
38
|
+
rescue StandardError => e
|
39
|
+
log("Error #{e.class} #{e.message[0..100]}")
|
40
|
+
log(e.backtrace.inspect)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def write(response)
|
45
|
+
@writer.write(response)
|
46
|
+
end
|
47
|
+
|
48
|
+
def format(path, text)
|
49
|
+
@runtime.format(path, text)
|
50
|
+
end
|
51
|
+
|
52
|
+
def offenses(path, text)
|
53
|
+
@runtime.offenses(path, text)
|
54
|
+
end
|
55
|
+
|
56
|
+
def stop(&block)
|
57
|
+
at_exit(&block) if block
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Lsp
|
5
|
+
# Severity for Language Server Protocol of RuboCop.
|
6
|
+
# @api private
|
7
|
+
class Severity
|
8
|
+
SEVERITIES = {
|
9
|
+
fatal: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
|
10
|
+
error: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
|
11
|
+
warning: LanguageServer::Protocol::Constant::DiagnosticSeverity::WARNING,
|
12
|
+
convention: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
|
13
|
+
refactor: LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT,
|
14
|
+
info: LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def self.find_by(rubocop_severity)
|
18
|
+
if (severity = SEVERITIES[rubocop_severity.to_sym])
|
19
|
+
return severity
|
20
|
+
end
|
21
|
+
|
22
|
+
Logger.log("Unknown severity: #{rubocop_severity}")
|
23
|
+
LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/rubocop/options.rb
CHANGED
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
'root of the project. RuboCop will use this path to determine which ' \
|
17
17
|
'cops are enabled (via eg. Include/Exclude), and so that certain cops ' \
|
18
18
|
'like Naming/FileName can be checked.'
|
19
|
-
EXITING_OPTIONS = %i[version verbose_version show_cops show_docs_url].freeze
|
19
|
+
EXITING_OPTIONS = %i[version verbose_version show_cops show_docs_url lsp].freeze
|
20
20
|
DEFAULT_MAXIMUM_EXCLUSION_ITEMS = 15
|
21
21
|
|
22
22
|
def initialize
|
@@ -49,12 +49,14 @@ module RuboCop
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
+
# rubocop:disable Metrics/AbcSize
|
52
53
|
def define_options
|
53
54
|
OptionParser.new do |opts|
|
54
55
|
opts.banner = rainbow.wrap('Usage: rubocop [options] [file1, file2, ...]').bright
|
55
56
|
|
56
57
|
add_check_options(opts)
|
57
58
|
add_cache_options(opts)
|
59
|
+
add_lsp_option(opts)
|
58
60
|
add_server_options(opts)
|
59
61
|
add_output_options(opts)
|
60
62
|
add_autocorrection_options(opts)
|
@@ -66,6 +68,7 @@ module RuboCop
|
|
66
68
|
add_profile_options(opts) if RUBY_ENGINE == 'ruby' && !Platform.windows?
|
67
69
|
end
|
68
70
|
end
|
71
|
+
# rubocop:enable Metrics/AbcSize
|
69
72
|
|
70
73
|
def add_check_options(opts) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
71
74
|
section(opts, 'Basic Options') do # rubocop:disable Metrics/BlockLength
|
@@ -205,6 +208,12 @@ module RuboCop
|
|
205
208
|
end
|
206
209
|
end
|
207
210
|
|
211
|
+
def add_lsp_option(opts)
|
212
|
+
section(opts, 'LSP Option') do
|
213
|
+
option(opts, '--lsp')
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
208
217
|
def add_server_options(opts)
|
209
218
|
section(opts, 'Server Options') do
|
210
219
|
option(opts, '--[no-]server')
|
@@ -620,6 +629,7 @@ module RuboCop
|
|
620
629
|
stop_server: 'Stop server process.',
|
621
630
|
server_status: 'Show server status.',
|
622
631
|
no_detach: 'Run the server process in the foreground.',
|
632
|
+
lsp: 'Start a language server listening on STDIN.',
|
623
633
|
raise_cop_error: ['Raise cop-related errors with cause and location.',
|
624
634
|
'This is used to prevent cops from failing silently.',
|
625
635
|
'Default is false.'],
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -83,7 +83,7 @@ module RuboCop
|
|
83
83
|
config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
|
84
84
|
end
|
85
85
|
|
86
|
-
|
86
|
+
attr_reader :path
|
87
87
|
|
88
88
|
def initialize(file, team, options, config_store, cache_root = nil)
|
89
89
|
cache_root ||= File.join(options[:cache_root], 'rubocop_cache') if options[:cache_root]
|
@@ -18,10 +18,11 @@ module RuboCop
|
|
18
18
|
def run
|
19
19
|
ensure_server!
|
20
20
|
Cache.status_path.delete if Cache.status_path.file?
|
21
|
+
read_stdin = ARGV.include?('-s') || ARGV.include?('--stdin')
|
21
22
|
send_request(
|
22
23
|
command: 'exec',
|
23
24
|
args: ARGV.dup,
|
24
|
-
body: $stdin.
|
25
|
+
body: read_stdin ? $stdin.read : ''
|
25
26
|
)
|
26
27
|
warn stderr unless stderr.empty?
|
27
28
|
status
|
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
# @api private
|
6
6
|
class TargetRuby
|
7
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
|
-
DEFAULT_VERSION = 2.
|
8
|
+
DEFAULT_VERSION = 2.7
|
9
9
|
|
10
10
|
OBSOLETE_RUBIES = {
|
11
11
|
1.9 => '0.41',
|
@@ -14,7 +14,8 @@ module RuboCop
|
|
14
14
|
2.2 => '0.68',
|
15
15
|
2.3 => '0.81',
|
16
16
|
2.4 => '1.12',
|
17
|
-
2.5 => '1.28'
|
17
|
+
2.5 => '1.28',
|
18
|
+
2.6 => '1.50'
|
18
19
|
}.freeze
|
19
20
|
private_constant :KNOWN_RUBIES, :OBSOLETE_RUBIES
|
20
21
|
|
data/lib/rubocop/version.rb
CHANGED
@@ -3,15 +3,19 @@
|
|
3
3
|
module RuboCop
|
4
4
|
# This module holds the RuboCop version information.
|
5
5
|
module Version
|
6
|
-
STRING = '1.
|
6
|
+
STRING = '1.53.0'
|
7
7
|
|
8
8
|
MSG = '%<version>s (using Parser %<parser_version>s, ' \
|
9
9
|
'rubocop-ast %<rubocop_ast_version>s, ' \
|
10
10
|
'running on %<ruby_engine>s %<ruby_version>s)%<server_mode>s [%<ruby_platform>s]'
|
11
11
|
|
12
|
-
CANONICAL_FEATURE_NAMES = {
|
13
|
-
|
14
|
-
|
12
|
+
CANONICAL_FEATURE_NAMES = {
|
13
|
+
'Rspec' => 'RSpec', 'Graphql' => 'GraphQL', 'Md' => 'Markdown', 'Factory_bot' => 'FactoryBot',
|
14
|
+
'Thread_safety' => 'ThreadSafety'
|
15
|
+
}.freeze
|
16
|
+
EXTENSION_PATH_NAMES = {
|
17
|
+
'rubocop-md' => 'markdown', 'rubocop-factory_bot' => 'factory_bot'
|
18
|
+
}.freeze
|
15
19
|
|
16
20
|
# @api private
|
17
21
|
def self.version(debug: false, env: nil)
|
@@ -43,7 +47,7 @@ module RuboCop
|
|
43
47
|
env.config_store.unvalidated.for_pwd.loaded_features.sort
|
44
48
|
end
|
45
49
|
|
46
|
-
features.
|
50
|
+
features.filter_map do |loaded_feature|
|
47
51
|
next unless (match = loaded_feature.match(/rubocop-(?<feature>.*)/))
|
48
52
|
|
49
53
|
# Get the expected name of the folder containing the extension code.
|
@@ -61,7 +65,7 @@ module RuboCop
|
|
61
65
|
next unless (feature_version = feature_version(feature))
|
62
66
|
|
63
67
|
" - #{loaded_feature} #{feature_version}"
|
64
|
-
end
|
68
|
+
end
|
65
69
|
end
|
66
70
|
|
67
71
|
# Returns feature version in one of two ways:
|
data/lib/rubocop.rb
CHANGED
@@ -69,6 +69,7 @@ require_relative 'rubocop/cop/mixin/alignment'
|
|
69
69
|
require_relative 'rubocop/cop/mixin/allowed_identifiers'
|
70
70
|
require_relative 'rubocop/cop/mixin/allowed_methods'
|
71
71
|
require_relative 'rubocop/cop/mixin/allowed_pattern'
|
72
|
+
require_relative 'rubocop/cop/mixin/allowed_receivers'
|
72
73
|
require_relative 'rubocop/cop/mixin/auto_corrector' # rubocop:todo Naming/InclusiveLanguage
|
73
74
|
require_relative 'rubocop/cop/mixin/check_assignment'
|
74
75
|
require_relative 'rubocop/cop/mixin/check_line_breakable'
|
@@ -138,6 +139,7 @@ require_relative 'rubocop/cop/mixin/comments_help' # relies on visibility_help
|
|
138
139
|
require_relative 'rubocop/cop/mixin/def_node' # relies on visibility_help
|
139
140
|
|
140
141
|
require_relative 'rubocop/cop/utils/format_string'
|
142
|
+
require_relative 'rubocop/cop/utils/regexp_ranges'
|
141
143
|
|
142
144
|
require_relative 'rubocop/cop/migration/department_name'
|
143
145
|
|
@@ -335,6 +337,7 @@ require_relative 'rubocop/cop/lint/literal_in_interpolation'
|
|
335
337
|
require_relative 'rubocop/cop/lint/loop'
|
336
338
|
require_relative 'rubocop/cop/lint/missing_cop_enable_directive'
|
337
339
|
require_relative 'rubocop/cop/lint/missing_super'
|
340
|
+
require_relative 'rubocop/cop/lint/mixed_case_range'
|
338
341
|
require_relative 'rubocop/cop/lint/mixed_regexp_capture_types'
|
339
342
|
require_relative 'rubocop/cop/lint/multiple_comparison'
|
340
343
|
require_relative 'rubocop/cop/lint/nested_method_definition'
|
@@ -357,6 +360,7 @@ require_relative 'rubocop/cop/lint/rand_one'
|
|
357
360
|
require_relative 'rubocop/cop/lint/redundant_cop_disable_directive'
|
358
361
|
require_relative 'rubocop/cop/lint/redundant_cop_enable_directive'
|
359
362
|
require_relative 'rubocop/cop/lint/redundant_dir_glob_sort'
|
363
|
+
require_relative 'rubocop/cop/lint/redundant_regexp_quantifiers'
|
360
364
|
require_relative 'rubocop/cop/lint/redundant_require_statement'
|
361
365
|
require_relative 'rubocop/cop/lint/redundant_safe_navigation'
|
362
366
|
require_relative 'rubocop/cop/lint/redundant_splat_expansion'
|
@@ -507,6 +511,7 @@ require_relative 'rubocop/cop/style/end_block'
|
|
507
511
|
require_relative 'rubocop/cop/style/env_home'
|
508
512
|
require_relative 'rubocop/cop/style/eval_with_location'
|
509
513
|
require_relative 'rubocop/cop/style/even_odd'
|
514
|
+
require_relative 'rubocop/cop/style/exact_regexp_match'
|
510
515
|
require_relative 'rubocop/cop/style/expand_path_arguments'
|
511
516
|
require_relative 'rubocop/cop/style/explicit_block_argument'
|
512
517
|
require_relative 'rubocop/cop/style/exponential_notation'
|
@@ -557,15 +562,20 @@ require_relative 'rubocop/cop/style/multiline_in_pattern_then'
|
|
557
562
|
require_relative 'rubocop/cop/style/numbered_parameters'
|
558
563
|
require_relative 'rubocop/cop/style/open_struct_use'
|
559
564
|
require_relative 'rubocop/cop/style/operator_method_call'
|
565
|
+
require_relative 'rubocop/cop/style/redundant_array_constructor'
|
560
566
|
require_relative 'rubocop/cop/style/redundant_assignment'
|
561
567
|
require_relative 'rubocop/cop/style/redundant_constant_base'
|
568
|
+
require_relative 'rubocop/cop/style/redundant_current_directory_in_path'
|
562
569
|
require_relative 'rubocop/cop/style/redundant_double_splat_hash_braces'
|
563
570
|
require_relative 'rubocop/cop/style/redundant_each'
|
564
571
|
require_relative 'rubocop/cop/style/redundant_fetch_block'
|
565
572
|
require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
|
573
|
+
require_relative 'rubocop/cop/style/redundant_filter_chain'
|
566
574
|
require_relative 'rubocop/cop/style/redundant_heredoc_delimiter_quotes'
|
567
575
|
require_relative 'rubocop/cop/style/redundant_initialize'
|
568
576
|
require_relative 'rubocop/cop/style/redundant_line_continuation'
|
577
|
+
require_relative 'rubocop/cop/style/redundant_regexp_argument'
|
578
|
+
require_relative 'rubocop/cop/style/redundant_regexp_constructor'
|
569
579
|
require_relative 'rubocop/cop/style/redundant_self_assignment'
|
570
580
|
require_relative 'rubocop/cop/style/redundant_self_assignment_branch'
|
571
581
|
require_relative 'rubocop/cop/style/require_order'
|
@@ -643,6 +653,7 @@ require_relative 'rubocop/cop/style/regexp_literal'
|
|
643
653
|
require_relative 'rubocop/cop/style/rescue_modifier'
|
644
654
|
require_relative 'rubocop/cop/style/rescue_standard_error'
|
645
655
|
require_relative 'rubocop/cop/style/return_nil'
|
656
|
+
require_relative 'rubocop/cop/style/return_nil_in_predicate_method_definition'
|
646
657
|
require_relative 'rubocop/cop/style/safe_navigation'
|
647
658
|
require_relative 'rubocop/cop/style/sample'
|
648
659
|
require_relative 'rubocop/cop/style/select_by_regexp'
|
@@ -689,6 +700,7 @@ require_relative 'rubocop/cop/style/when_then'
|
|
689
700
|
require_relative 'rubocop/cop/style/while_until_do'
|
690
701
|
require_relative 'rubocop/cop/style/while_until_modifier'
|
691
702
|
require_relative 'rubocop/cop/style/word_array'
|
703
|
+
require_relative 'rubocop/cop/style/yaml_file_read'
|
692
704
|
require_relative 'rubocop/cop/style/yoda_condition'
|
693
705
|
require_relative 'rubocop/cop/style/yoda_expression'
|
694
706
|
require_relative 'rubocop/cop/style/zero_length_predicate'
|
@@ -734,6 +746,7 @@ require_relative 'rubocop/cli/command/base'
|
|
734
746
|
require_relative 'rubocop/cli/command/auto_generate_config'
|
735
747
|
require_relative 'rubocop/cli/command/execute_runner'
|
736
748
|
require_relative 'rubocop/cli/command/init_dotfile'
|
749
|
+
require_relative 'rubocop/cli/command/lsp'
|
737
750
|
require_relative 'rubocop/cli/command/show_cops'
|
738
751
|
require_relative 'rubocop/cli/command/show_docs_url'
|
739
752
|
require_relative 'rubocop/cli/command/suggest_extensions'
|