ruby-lsp 0.23.15 → 0.26.9
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/VERSION +1 -1
- data/exe/ruby-lsp +17 -14
- data/exe/ruby-lsp-check +0 -4
- data/exe/ruby-lsp-launcher +41 -14
- data/exe/ruby-lsp-test-exec +6 -0
- data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -3
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +42 -20
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -7
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +49 -62
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +84 -74
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -9
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +9 -14
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
- data/lib/ruby_lsp/addon.rb +44 -15
- data/lib/ruby_lsp/base_server.rb +56 -37
- data/lib/ruby_lsp/client_capabilities.rb +6 -1
- data/lib/ruby_lsp/document.rb +174 -62
- data/lib/ruby_lsp/erb_document.rb +10 -8
- data/lib/ruby_lsp/global_state.rb +86 -33
- data/lib/ruby_lsp/internal.rb +6 -3
- data/lib/ruby_lsp/listeners/completion.rb +22 -11
- data/lib/ruby_lsp/listeners/definition.rb +41 -21
- data/lib/ruby_lsp/listeners/document_highlight.rb +26 -1
- data/lib/ruby_lsp/listeners/document_link.rb +64 -28
- data/lib/ruby_lsp/listeners/hover.rb +27 -16
- data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +2 -2
- data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
- data/lib/ruby_lsp/listeners/spec_style.rb +155 -79
- data/lib/ruby_lsp/listeners/test_discovery.rb +39 -21
- data/lib/ruby_lsp/listeners/test_style.rb +75 -35
- data/lib/ruby_lsp/rbs_document.rb +3 -6
- data/lib/ruby_lsp/requests/code_action_resolve.rb +83 -58
- data/lib/ruby_lsp/requests/code_actions.rb +20 -5
- data/lib/ruby_lsp/requests/code_lens.rb +27 -6
- data/lib/ruby_lsp/requests/completion.rb +3 -3
- data/lib/ruby_lsp/requests/completion_resolve.rb +8 -6
- data/lib/ruby_lsp/requests/definition.rb +4 -7
- data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
- data/lib/ruby_lsp/requests/document_highlight.rb +2 -2
- data/lib/ruby_lsp/requests/document_link.rb +1 -1
- data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +64 -12
- data/lib/ruby_lsp/requests/hover.rb +3 -6
- data/lib/ruby_lsp/requests/inlay_hints.rb +4 -4
- data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
- data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +10 -21
- data/lib/ruby_lsp/requests/rename.rb +9 -10
- data/lib/ruby_lsp/requests/request.rb +8 -8
- data/lib/ruby_lsp/requests/selection_ranges.rb +2 -2
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +2 -2
- data/lib/ruby_lsp/requests/signature_help.rb +2 -2
- data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +9 -12
- data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
- data/lib/ruby_lsp/requests/support/package_url.rb +414 -0
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +7 -1
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +13 -3
- data/lib/ruby_lsp/requests/support/source_uri.rb +7 -4
- data/lib/ruby_lsp/requests/support/test_item.rb +7 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +20 -12
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +1 -4
- data/lib/ruby_lsp/response_builders/document_symbol.rb +2 -3
- data/lib/ruby_lsp/response_builders/hover.rb +1 -4
- data/lib/ruby_lsp/response_builders/response_builder.rb +6 -7
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +4 -5
- data/lib/ruby_lsp/response_builders/signature_help.rb +1 -2
- data/lib/ruby_lsp/response_builders/test_collection.rb +29 -3
- data/lib/ruby_lsp/ruby_document.rb +14 -42
- data/lib/ruby_lsp/scripts/compose_bundle.rb +3 -3
- data/lib/ruby_lsp/scripts/compose_bundle_windows.rb +3 -1
- data/lib/ruby_lsp/server.rb +173 -130
- data/lib/ruby_lsp/setup_bundler.rb +114 -47
- data/lib/ruby_lsp/static_docs.rb +1 -0
- data/lib/ruby_lsp/store.rb +6 -16
- data/lib/ruby_lsp/test_helper.rb +1 -4
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +121 -17
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +65 -25
- data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +16 -18
- data/lib/ruby_lsp/utils.rb +102 -13
- data/static_docs/break.md +103 -0
- metadata +8 -33
- data/lib/ruby_indexer/test/class_variables_test.rb +0 -140
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +0 -770
- data/lib/ruby_indexer/test/configuration_test.rb +0 -280
- data/lib/ruby_indexer/test/constant_test.rb +0 -402
- data/lib/ruby_indexer/test/enhancements_test.rb +0 -325
- data/lib/ruby_indexer/test/global_variable_test.rb +0 -49
- data/lib/ruby_indexer/test/index_test.rb +0 -2190
- data/lib/ruby_indexer/test/instance_variables_test.rb +0 -240
- data/lib/ruby_indexer/test/method_test.rb +0 -973
- data/lib/ruby_indexer/test/prefix_tree_test.rb +0 -150
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +0 -380
- data/lib/ruby_indexer/test/reference_finder_test.rb +0 -330
- data/lib/ruby_indexer/test/test_case.rb +0 -51
- data/lib/ruby_indexer/test/uri_test.rb +0 -85
- data/lib/ruby_lsp/load_sorbet.rb +0 -62
data/lib/ruby_lsp/server.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
module RubyLsp
|
|
5
5
|
class Server < BaseServer
|
|
6
|
+
NON_REPORTABLE_SETUP_ERRORS = [Bundler::GemNotFound, Bundler::GitError].freeze #: Array[singleton(StandardError)]
|
|
7
|
+
|
|
6
8
|
# Only for testing
|
|
7
9
|
#: GlobalState
|
|
8
10
|
attr_reader :global_state
|
|
@@ -32,6 +34,8 @@ module RubyLsp
|
|
|
32
34
|
text_document_document_link(message)
|
|
33
35
|
when "textDocument/codeLens"
|
|
34
36
|
text_document_code_lens(message)
|
|
37
|
+
when "codeLens/resolve"
|
|
38
|
+
code_lens_resolve(message)
|
|
35
39
|
when "textDocument/semanticTokens/full"
|
|
36
40
|
text_document_semantic_tokens_full(message)
|
|
37
41
|
when "textDocument/semanticTokens/full/delta"
|
|
@@ -92,13 +96,10 @@ module RubyLsp
|
|
|
92
96
|
id: message[:id],
|
|
93
97
|
response:
|
|
94
98
|
Addon.addons.map do |addon|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# Therefore, we only call the method if it's defined by the add-on itself
|
|
100
|
-
if version_method.owner != Addon
|
|
101
|
-
version = addon.version
|
|
99
|
+
version = begin
|
|
100
|
+
addon.version
|
|
101
|
+
rescue AbstractMethodInvokedError
|
|
102
|
+
nil
|
|
102
103
|
end
|
|
103
104
|
|
|
104
105
|
{ name: addon.name, version: version, errored: addon.error? }
|
|
@@ -122,30 +123,22 @@ module RubyLsp
|
|
|
122
123
|
end
|
|
123
124
|
rescue DelegateRequestError
|
|
124
125
|
send_message(Error.new(id: message[:id], code: DelegateRequestError::CODE, message: "DELEGATE_REQUEST"))
|
|
125
|
-
rescue StandardError, LoadError => e
|
|
126
|
+
rescue StandardError, LoadError, SystemExit => e
|
|
126
127
|
# If an error occurred in a request, we have to return an error response or else the editor will hang
|
|
127
128
|
if message[:id]
|
|
128
129
|
# If a document is deleted before we are able to process all of its enqueued requests, we will try to read it
|
|
129
130
|
# from disk and it raise this error. This is expected, so we don't include the `data` attribute to avoid
|
|
130
|
-
# reporting these to our telemetry
|
|
131
|
+
# reporting these to our telemetry.
|
|
132
|
+
#
|
|
133
|
+
# Similarly, if we receive a location for an invalid position in the
|
|
134
|
+
# document, we don't report it to telemetry
|
|
131
135
|
case e
|
|
132
|
-
when Store::NonExistingDocumentError
|
|
136
|
+
when Store::NonExistingDocumentError, Document::InvalidLocationError
|
|
133
137
|
send_message(Error.new(
|
|
134
138
|
id: message[:id],
|
|
135
139
|
code: Constant::ErrorCodes::INVALID_PARAMS,
|
|
136
140
|
message: e.full_message,
|
|
137
141
|
))
|
|
138
|
-
when Document::LocationNotFoundError
|
|
139
|
-
send_message(Error.new(
|
|
140
|
-
id: message[:id],
|
|
141
|
-
code: Constant::ErrorCodes::REQUEST_FAILED,
|
|
142
|
-
message: <<~MESSAGE,
|
|
143
|
-
Request #{message[:method]} failed to find the target position.
|
|
144
|
-
The file might have been modified while the server was in the middle of searching for the target.
|
|
145
|
-
If you experience this regularly, please report any findings and extra information on
|
|
146
|
-
https://github.com/Shopify/ruby-lsp/issues/2446
|
|
147
|
-
MESSAGE
|
|
148
|
-
))
|
|
149
142
|
else
|
|
150
143
|
send_message(Error.new(
|
|
151
144
|
id: message[:id],
|
|
@@ -180,6 +173,7 @@ module RubyLsp
|
|
|
180
173
|
return if @setup_error
|
|
181
174
|
|
|
182
175
|
errors = Addon.load_addons(@global_state, @outgoing_queue, include_project_addons: include_project_addons)
|
|
176
|
+
return if test_mode?
|
|
183
177
|
|
|
184
178
|
if errors.any?
|
|
185
179
|
send_log_message(
|
|
@@ -192,21 +186,13 @@ module RubyLsp
|
|
|
192
186
|
|
|
193
187
|
if errored_addons.any?
|
|
194
188
|
send_message(
|
|
195
|
-
Notification.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
type: Constant::MessageType::WARNING,
|
|
199
|
-
message: "Error loading add-ons:\n\n#{errored_addons.map(&:formatted_errors).join("\n\n")}",
|
|
200
|
-
),
|
|
189
|
+
Notification.window_show_message(
|
|
190
|
+
"Error loading add-ons:\n\n#{errored_addons.map(&:formatted_errors).join("\n\n")}",
|
|
191
|
+
type: Constant::MessageType::WARNING,
|
|
201
192
|
),
|
|
202
193
|
)
|
|
203
194
|
|
|
204
|
-
|
|
205
|
-
send_log_message(
|
|
206
|
-
errored_addons.map(&:errors_details).join("\n\n"),
|
|
207
|
-
type: Constant::MessageType::WARNING,
|
|
208
|
-
)
|
|
209
|
-
end
|
|
195
|
+
send_log_message(errored_addons.map(&:errors_details).join("\n\n"), type: Constant::MessageType::WARNING)
|
|
210
196
|
end
|
|
211
197
|
end
|
|
212
198
|
|
|
@@ -222,10 +208,6 @@ module RubyLsp
|
|
|
222
208
|
|
|
223
209
|
configured_features = options.dig(:initializationOptions, :enabledFeatures)
|
|
224
210
|
|
|
225
|
-
configured_hints = options.dig(:initializationOptions, :featuresConfiguration, :inlayHint)
|
|
226
|
-
@store.features_configuration.dig(:inlayHint) #: as !nil
|
|
227
|
-
.configuration.merge!(configured_hints) if configured_hints
|
|
228
|
-
|
|
229
211
|
enabled_features = case configured_features
|
|
230
212
|
when Array
|
|
231
213
|
# If the configuration is using an array, then absent features are disabled and present ones are enabled. That's
|
|
@@ -242,7 +224,9 @@ module RubyLsp
|
|
|
242
224
|
|
|
243
225
|
bundle_env_path = File.join(".ruby-lsp", "bundle_env")
|
|
244
226
|
bundle_env = if File.exist?(bundle_env_path)
|
|
245
|
-
env = File.readlines(bundle_env_path).to_h
|
|
227
|
+
env = File.readlines(bundle_env_path).to_h do |line|
|
|
228
|
+
line.chomp.split("=", 2) #: as [String, String]
|
|
229
|
+
end
|
|
246
230
|
FileUtils.rm(bundle_env_path)
|
|
247
231
|
env
|
|
248
232
|
end
|
|
@@ -321,7 +305,7 @@ module RubyLsp
|
|
|
321
305
|
@current_request_id,
|
|
322
306
|
Interface::RelativePattern.new(
|
|
323
307
|
base_uri: @global_state.workspace_uri.to_s,
|
|
324
|
-
pattern: "{.rubocop.yml,.rubocop}",
|
|
308
|
+
pattern: "{.rubocop.yml,.rubocop,.rubocop_todo.yml}",
|
|
325
309
|
),
|
|
326
310
|
registration_id: "rubocop-watcher",
|
|
327
311
|
))
|
|
@@ -333,7 +317,7 @@ module RubyLsp
|
|
|
333
317
|
|
|
334
318
|
global_state_notifications.each { |notification| send_message(notification) }
|
|
335
319
|
|
|
336
|
-
if @setup_error
|
|
320
|
+
if @setup_error && NON_REPORTABLE_SETUP_ERRORS.none? { |error_class| @setup_error.is_a?(error_class) }
|
|
337
321
|
send_message(Notification.telemetry(
|
|
338
322
|
type: "error",
|
|
339
323
|
errorMessage: @setup_error.message,
|
|
@@ -377,56 +361,53 @@ module RubyLsp
|
|
|
377
361
|
|
|
378
362
|
perform_initial_indexing
|
|
379
363
|
check_formatter_is_available
|
|
364
|
+
update_server if @global_state.enabled_feature?(:launcher)
|
|
380
365
|
end
|
|
381
366
|
|
|
382
367
|
#: (Hash[Symbol, untyped] message) -> void
|
|
383
368
|
def text_document_did_open(message)
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
end
|
|
369
|
+
text_document = message.dig(:params, :textDocument)
|
|
370
|
+
language_id = case text_document[:languageId]
|
|
371
|
+
when "erb", "eruby"
|
|
372
|
+
:erb
|
|
373
|
+
when "rbs"
|
|
374
|
+
:rbs
|
|
375
|
+
else
|
|
376
|
+
:ruby
|
|
377
|
+
end
|
|
394
378
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
379
|
+
document = @store.set(
|
|
380
|
+
uri: text_document[:uri],
|
|
381
|
+
source: text_document[:text],
|
|
382
|
+
version: text_document[:version],
|
|
383
|
+
language_id: language_id,
|
|
384
|
+
)
|
|
401
385
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
386
|
+
if document.past_expensive_limit? && text_document[:uri].scheme == "file"
|
|
387
|
+
log_message = <<~MESSAGE
|
|
388
|
+
The file #{text_document[:uri].path} is too long. For performance reasons, semantic highlighting and
|
|
389
|
+
diagnostics will be disabled.
|
|
390
|
+
MESSAGE
|
|
407
391
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
),
|
|
392
|
+
send_message(
|
|
393
|
+
Notification.new(
|
|
394
|
+
method: "window/logMessage",
|
|
395
|
+
params: Interface::LogMessageParams.new(
|
|
396
|
+
type: Constant::MessageType::WARNING,
|
|
397
|
+
message: log_message,
|
|
415
398
|
),
|
|
416
|
-
)
|
|
417
|
-
|
|
399
|
+
),
|
|
400
|
+
)
|
|
418
401
|
end
|
|
419
402
|
end
|
|
420
403
|
|
|
421
404
|
#: (Hash[Symbol, untyped] message) -> void
|
|
422
405
|
def text_document_did_close(message)
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
@store.delete(uri)
|
|
406
|
+
uri = message.dig(:params, :textDocument, :uri)
|
|
407
|
+
@store.delete(uri)
|
|
426
408
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
end
|
|
409
|
+
# Clear diagnostics for the closed file, so that they no longer appear in the problems tab
|
|
410
|
+
send_message(Notification.publish_diagnostics(uri.to_s, []))
|
|
430
411
|
end
|
|
431
412
|
|
|
432
413
|
#: (Hash[Symbol, untyped] message) -> void
|
|
@@ -434,9 +415,7 @@ module RubyLsp
|
|
|
434
415
|
params = message[:params]
|
|
435
416
|
text_document = params[:textDocument]
|
|
436
417
|
|
|
437
|
-
@
|
|
438
|
-
@store.push_edits(uri: text_document[:uri], edits: params[:contentChanges], version: text_document[:version])
|
|
439
|
-
end
|
|
418
|
+
@store.push_edits(uri: text_document[:uri], edits: params[:contentChanges], version: text_document[:version])
|
|
440
419
|
end
|
|
441
420
|
|
|
442
421
|
#: (Hash[Symbol, untyped] message) -> void
|
|
@@ -489,13 +468,16 @@ module RubyLsp
|
|
|
489
468
|
folding_range = Requests::FoldingRanges.new(parse_result.comments, dispatcher)
|
|
490
469
|
document_symbol = Requests::DocumentSymbol.new(uri, dispatcher)
|
|
491
470
|
document_link = Requests::DocumentLink.new(uri, parse_result.comments, dispatcher)
|
|
492
|
-
code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
|
|
493
471
|
inlay_hint = Requests::InlayHints.new(
|
|
472
|
+
@global_state,
|
|
494
473
|
document,
|
|
495
|
-
@store.features_configuration.dig(:inlayHint), #: as !nil
|
|
496
474
|
dispatcher,
|
|
497
475
|
)
|
|
498
476
|
|
|
477
|
+
# The code lens listener requires the index to be populated, so the DeclarationListener must be inserted first in
|
|
478
|
+
# the dispatcher's state
|
|
479
|
+
code_lens = nil #: Requests::CodeLens?
|
|
480
|
+
|
|
499
481
|
if document.is_a?(RubyDocument) && document.should_index?
|
|
500
482
|
# Re-index the file as it is modified. This mode of indexing updates entries only. Require path trees are only
|
|
501
483
|
# updated on save
|
|
@@ -505,11 +487,13 @@ module RubyLsp
|
|
|
505
487
|
@global_state.index.handle_change(uri) do |index|
|
|
506
488
|
index.delete(uri, skip_require_paths_tree: true)
|
|
507
489
|
RubyIndexer::DeclarationListener.new(index, dispatcher, parse_result, uri, collect_comments: true)
|
|
508
|
-
|
|
490
|
+
code_lens = Requests::CodeLens.new(@global_state, document, dispatcher)
|
|
491
|
+
dispatcher.dispatch(document.ast)
|
|
509
492
|
end
|
|
510
493
|
end
|
|
511
494
|
else
|
|
512
|
-
|
|
495
|
+
code_lens = Requests::CodeLens.new(@global_state, document, dispatcher)
|
|
496
|
+
dispatcher.dispatch(document.ast)
|
|
513
497
|
end
|
|
514
498
|
|
|
515
499
|
# Store all responses retrieve in this round of visits in the cache and then return the response for the request
|
|
@@ -517,7 +501,11 @@ module RubyLsp
|
|
|
517
501
|
document.cache_set("textDocument/foldingRange", folding_range.perform)
|
|
518
502
|
document.cache_set("textDocument/documentSymbol", document_symbol.perform)
|
|
519
503
|
document.cache_set("textDocument/documentLink", document_link.perform)
|
|
520
|
-
document.cache_set(
|
|
504
|
+
document.cache_set(
|
|
505
|
+
"textDocument/codeLens",
|
|
506
|
+
code_lens #: as !nil
|
|
507
|
+
.perform,
|
|
508
|
+
)
|
|
521
509
|
document.cache_set("textDocument/inlayHint", inlay_hint.perform)
|
|
522
510
|
|
|
523
511
|
send_message(Result.new(id: message[:id], response: document.cache_get(message[:method])))
|
|
@@ -544,7 +532,7 @@ module RubyLsp
|
|
|
544
532
|
|
|
545
533
|
dispatcher = Prism::Dispatcher.new
|
|
546
534
|
semantic_highlighting = Requests::SemanticHighlighting.new(@global_state, dispatcher, document, nil)
|
|
547
|
-
dispatcher.visit(document.
|
|
535
|
+
dispatcher.visit(document.ast)
|
|
548
536
|
|
|
549
537
|
send_message(Result.new(id: message[:id], response: semantic_highlighting.perform))
|
|
550
538
|
end
|
|
@@ -570,7 +558,7 @@ module RubyLsp
|
|
|
570
558
|
document,
|
|
571
559
|
message.dig(:params, :previousResultId),
|
|
572
560
|
)
|
|
573
|
-
dispatcher.visit(document.
|
|
561
|
+
dispatcher.visit(document.ast)
|
|
574
562
|
send_message(Result.new(id: message[:id], response: request.perform))
|
|
575
563
|
end
|
|
576
564
|
|
|
@@ -599,7 +587,7 @@ module RubyLsp
|
|
|
599
587
|
nil,
|
|
600
588
|
range: range.dig(:start, :line)..range.dig(:end, :line),
|
|
601
589
|
)
|
|
602
|
-
dispatcher.visit(document.
|
|
590
|
+
dispatcher.visit(document.ast)
|
|
603
591
|
send_message(Result.new(id: message[:id], response: request.perform))
|
|
604
592
|
end
|
|
605
593
|
|
|
@@ -672,6 +660,10 @@ module RubyLsp
|
|
|
672
660
|
"Formatting error: #{error.message}",
|
|
673
661
|
type: Constant::MessageType::ERROR,
|
|
674
662
|
))
|
|
663
|
+
send_message(Notification.window_log_message(
|
|
664
|
+
"Formatting failed with\r\n: #{error.full_message}",
|
|
665
|
+
type: Constant::MessageType::ERROR,
|
|
666
|
+
))
|
|
675
667
|
send_empty_response(message[:id])
|
|
676
668
|
end
|
|
677
669
|
|
|
@@ -687,7 +679,7 @@ module RubyLsp
|
|
|
687
679
|
end
|
|
688
680
|
|
|
689
681
|
request = Requests::DocumentHighlight.new(@global_state, document, params[:position], dispatcher)
|
|
690
|
-
dispatcher.dispatch(document.
|
|
682
|
+
dispatcher.dispatch(document.ast)
|
|
691
683
|
send_message(Result.new(id: message[:id], response: request.perform))
|
|
692
684
|
end
|
|
693
685
|
|
|
@@ -795,12 +787,16 @@ module RubyLsp
|
|
|
795
787
|
)
|
|
796
788
|
end
|
|
797
789
|
|
|
798
|
-
#: (Document[untyped] document) ->
|
|
790
|
+
#: (Document[untyped] document) -> SorbetLevel
|
|
799
791
|
def sorbet_level(document)
|
|
800
|
-
return
|
|
801
|
-
return
|
|
792
|
+
return SorbetLevel.ignore unless document.is_a?(RubyDocument)
|
|
793
|
+
return SorbetLevel.ignore unless @global_state.has_type_checker
|
|
794
|
+
|
|
795
|
+
sigil = document.parse_result.magic_comments.find do |comment|
|
|
796
|
+
comment.key == "typed"
|
|
797
|
+
end&.value
|
|
802
798
|
|
|
803
|
-
|
|
799
|
+
SorbetLevel.new(sigil)
|
|
804
800
|
end
|
|
805
801
|
|
|
806
802
|
#: (Hash[Symbol, untyped] message) -> void
|
|
@@ -821,7 +817,6 @@ module RubyLsp
|
|
|
821
817
|
return
|
|
822
818
|
end
|
|
823
819
|
|
|
824
|
-
hints_configurations = @store.features_configuration.dig(:inlayHint) #: as !nil
|
|
825
820
|
dispatcher = Prism::Dispatcher.new
|
|
826
821
|
|
|
827
822
|
unless document.is_a?(RubyDocument) || document.is_a?(ERBDocument)
|
|
@@ -829,8 +824,8 @@ module RubyLsp
|
|
|
829
824
|
return
|
|
830
825
|
end
|
|
831
826
|
|
|
832
|
-
request = Requests::InlayHints.new(
|
|
833
|
-
dispatcher.visit(document.
|
|
827
|
+
request = Requests::InlayHints.new(@global_state, document, dispatcher)
|
|
828
|
+
dispatcher.visit(document.ast)
|
|
834
829
|
result = request.perform
|
|
835
830
|
document.cache_set("textDocument/inlayHint", result)
|
|
836
831
|
|
|
@@ -871,17 +866,9 @@ module RubyLsp
|
|
|
871
866
|
end
|
|
872
867
|
|
|
873
868
|
result = Requests::CodeActionResolve.new(document, @global_state, params).perform
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
fail_request_and_notify(message[:id], "Invalid selection for extract variable refactor")
|
|
878
|
-
when Requests::CodeActionResolve::Error::InvalidTargetRange
|
|
879
|
-
fail_request_and_notify(message[:id], "Couldn't find an appropriate location to place extracted refactor")
|
|
880
|
-
when Requests::CodeActionResolve::Error::UnknownCodeAction
|
|
881
|
-
fail_request_and_notify(message[:id], "Unknown code action")
|
|
882
|
-
else
|
|
883
|
-
send_message(Result.new(id: message[:id], response: result))
|
|
884
|
-
end
|
|
869
|
+
send_message(Result.new(id: message[:id], response: result))
|
|
870
|
+
rescue Requests::CodeActionResolve::CodeActionError => e
|
|
871
|
+
fail_request_and_notify(message[:id], e.message)
|
|
885
872
|
end
|
|
886
873
|
|
|
887
874
|
#: (Hash[Symbol, untyped] message) -> void
|
|
@@ -921,6 +908,10 @@ module RubyLsp
|
|
|
921
908
|
"Error running diagnostics: #{error.message}",
|
|
922
909
|
type: Constant::MessageType::ERROR,
|
|
923
910
|
))
|
|
911
|
+
send_message(Notification.window_log_message(
|
|
912
|
+
"Diagnostics failed with\r\n: #{error.full_message}",
|
|
913
|
+
type: Constant::MessageType::ERROR,
|
|
914
|
+
))
|
|
924
915
|
send_empty_response(message[:id])
|
|
925
916
|
end
|
|
926
917
|
|
|
@@ -1056,13 +1047,14 @@ module RubyLsp
|
|
|
1056
1047
|
|
|
1057
1048
|
file_name = File.basename(file_path)
|
|
1058
1049
|
|
|
1059
|
-
if file_name == ".rubocop.yml" || file_name == ".rubocop"
|
|
1050
|
+
if file_name == ".rubocop.yml" || file_name == ".rubocop" || file_name == ".rubocop_todo.yml"
|
|
1060
1051
|
handle_rubocop_config_change(uri)
|
|
1061
1052
|
end
|
|
1062
1053
|
end
|
|
1063
1054
|
|
|
1064
1055
|
Addon.file_watcher_addons.each do |addon|
|
|
1065
|
-
|
|
1056
|
+
addon #: as untyped
|
|
1057
|
+
.workspace_did_change_watched_files(changes)
|
|
1066
1058
|
rescue => e
|
|
1067
1059
|
send_log_message(
|
|
1068
1060
|
"Error in #{addon.name} add-on while processing watched file notifications: #{e.full_message}",
|
|
@@ -1106,11 +1098,7 @@ module RubyLsp
|
|
|
1106
1098
|
@global_state.register_formatter("rubocop_internal", Requests::Support::RuboCopFormatter.new)
|
|
1107
1099
|
|
|
1108
1100
|
# Clear all document caches for pull diagnostics
|
|
1109
|
-
@
|
|
1110
|
-
@store.each do |_uri, document|
|
|
1111
|
-
document.cache_set("textDocument/diagnostic", Document::EMPTY_CACHE)
|
|
1112
|
-
end
|
|
1113
|
-
end
|
|
1101
|
+
@store.each { |_uri, document| document.clear_cache("textDocument/diagnostic") }
|
|
1114
1102
|
|
|
1115
1103
|
# Request a pull diagnostic refresh from the editor
|
|
1116
1104
|
if @global_state.client_capabilities.supports_diagnostic_refresh
|
|
@@ -1225,7 +1213,7 @@ module RubyLsp
|
|
|
1225
1213
|
}
|
|
1226
1214
|
end
|
|
1227
1215
|
end
|
|
1228
|
-
rescue Bundler::GemNotFound
|
|
1216
|
+
rescue Bundler::GemNotFound, Bundler::GemfileNotFound, Errno::ENOENT
|
|
1229
1217
|
[]
|
|
1230
1218
|
end
|
|
1231
1219
|
|
|
@@ -1264,9 +1252,25 @@ module RubyLsp
|
|
|
1264
1252
|
# allocations and garbage collections are faster
|
|
1265
1253
|
GC.compact unless @test_mode
|
|
1266
1254
|
|
|
1255
|
+
@global_state.synchronize do
|
|
1256
|
+
# If we linearize ancestors while the index is not fully populated, we may end up caching incorrect results
|
|
1257
|
+
# that were missing namespaces. After indexing is complete, we need to clear the ancestors cache and start
|
|
1258
|
+
# again
|
|
1259
|
+
@global_state.index.clear_ancestors
|
|
1260
|
+
|
|
1261
|
+
# The results for code lens depend on ancestor linearization, so we need to clear any previously computed
|
|
1262
|
+
# responses
|
|
1263
|
+
@store.each { |_uri, document| document.clear_cache("textDocument/codeLens") }
|
|
1264
|
+
end
|
|
1265
|
+
|
|
1267
1266
|
# Always end the progress notification even if indexing failed or else it never goes away and the user has no
|
|
1268
1267
|
# way of dismissing it
|
|
1269
1268
|
end_progress("indexing-progress")
|
|
1269
|
+
|
|
1270
|
+
# Request a code lens refresh if we populated them before all test parent classes were indexed
|
|
1271
|
+
if @global_state.client_capabilities.supports_code_lens_refresh
|
|
1272
|
+
send_message(Request.new(id: @current_request_id, method: "workspace/codeLens/refresh", params: nil))
|
|
1273
|
+
end
|
|
1270
1274
|
end
|
|
1271
1275
|
end
|
|
1272
1276
|
|
|
@@ -1392,8 +1396,38 @@ module RubyLsp
|
|
|
1392
1396
|
|
|
1393
1397
|
# We compose the bundle in a thread so that the LSP continues to work while we're checking for its validity. Once
|
|
1394
1398
|
# we return the response back to the editor, then the restart is triggered
|
|
1399
|
+
launch_bundle_compose("Recomposing the bundle ahead of restart") do |stderr, status|
|
|
1400
|
+
if status&.exitstatus == 0
|
|
1401
|
+
# Create a signal for the restart that it can skip composing the bundle and launch directly
|
|
1402
|
+
FileUtils.touch(already_composed_path)
|
|
1403
|
+
send_message(Result.new(id: id, response: { success: true }))
|
|
1404
|
+
else
|
|
1405
|
+
# This special error code makes the extension avoid restarting in case we already know that the composed
|
|
1406
|
+
# bundle is not valid
|
|
1407
|
+
send_message(
|
|
1408
|
+
Error.new(id: id, code: BUNDLE_COMPOSE_FAILED_CODE, message: "Failed to compose bundle\n#{stderr}"),
|
|
1409
|
+
)
|
|
1410
|
+
end
|
|
1411
|
+
end
|
|
1412
|
+
end
|
|
1413
|
+
|
|
1414
|
+
#: -> void
|
|
1415
|
+
def update_server
|
|
1416
|
+
return unless File.exist?(File.join(@global_state.workspace_path, ".ruby-lsp", "needs_update"))
|
|
1417
|
+
|
|
1418
|
+
launch_bundle_compose("Trying to update server") do |stderr, status|
|
|
1419
|
+
if status&.exitstatus == 0
|
|
1420
|
+
send_log_message("Successfully updated the server")
|
|
1421
|
+
else
|
|
1422
|
+
send_log_message("Failed to update server\n#{stderr}", type: Constant::MessageType::ERROR)
|
|
1423
|
+
end
|
|
1424
|
+
end
|
|
1425
|
+
end
|
|
1426
|
+
|
|
1427
|
+
#: (String) { (IO, Process::Status?) -> void } -> Thread
|
|
1428
|
+
def launch_bundle_compose(log, &block)
|
|
1395
1429
|
Thread.new do
|
|
1396
|
-
send_log_message(
|
|
1430
|
+
send_log_message(log)
|
|
1397
1431
|
|
|
1398
1432
|
_stdout, stderr, status = Bundler.with_unbundled_env do
|
|
1399
1433
|
Open3.capture3(
|
|
@@ -1404,21 +1438,12 @@ module RubyLsp
|
|
|
1404
1438
|
),
|
|
1405
1439
|
File.expand_path("../../exe/ruby-lsp-launcher", __dir__),
|
|
1406
1440
|
@global_state.workspace_uri.to_s,
|
|
1441
|
+
*ARGV,
|
|
1407
1442
|
chdir: @global_state.workspace_path,
|
|
1408
1443
|
)
|
|
1409
1444
|
end
|
|
1410
1445
|
|
|
1411
|
-
|
|
1412
|
-
# Create a signal for the restart that it can skip composing the bundle and launch directly
|
|
1413
|
-
FileUtils.touch(already_composed_path)
|
|
1414
|
-
send_message(Result.new(id: id, response: { success: true }))
|
|
1415
|
-
else
|
|
1416
|
-
# This special error code makes the extension avoid restarting in case we already know that the composed
|
|
1417
|
-
# bundle is not valid
|
|
1418
|
-
send_message(
|
|
1419
|
-
Error.new(id: id, code: BUNDLE_COMPOSE_FAILED_CODE, message: "Failed to compose bundle\n#{stderr}"),
|
|
1420
|
-
)
|
|
1421
|
-
end
|
|
1446
|
+
block.call(stderr, status)
|
|
1422
1447
|
end
|
|
1423
1448
|
end
|
|
1424
1449
|
|
|
@@ -1475,10 +1500,28 @@ module RubyLsp
|
|
|
1475
1500
|
|
|
1476
1501
|
send_message(Result.new(
|
|
1477
1502
|
id: message[:id],
|
|
1478
|
-
response: {
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1503
|
+
response: { commands: commands },
|
|
1504
|
+
))
|
|
1505
|
+
end
|
|
1506
|
+
|
|
1507
|
+
#: (Hash[Symbol, untyped] message) -> void
|
|
1508
|
+
def code_lens_resolve(message)
|
|
1509
|
+
code_lens = message[:params]
|
|
1510
|
+
args = code_lens.dig(:data, :arguments)
|
|
1511
|
+
|
|
1512
|
+
case code_lens.dig(:data, :kind)
|
|
1513
|
+
when "run_test"
|
|
1514
|
+
code_lens[:command] = Interface::Command.new(title: "▶ Run", command: "rubyLsp.runTest", arguments: args)
|
|
1515
|
+
when "run_test_in_terminal"
|
|
1516
|
+
code_lens[:command] =
|
|
1517
|
+
Interface::Command.new(title: "▶ Run in terminal", command: "rubyLsp.runTestInTerminal", arguments: args)
|
|
1518
|
+
when "debug_test"
|
|
1519
|
+
code_lens[:command] = Interface::Command.new(title: "⚙ Debug", command: "rubyLsp.debugTest", arguments: args)
|
|
1520
|
+
end
|
|
1521
|
+
|
|
1522
|
+
send_message(Result.new(
|
|
1523
|
+
id: message[:id],
|
|
1524
|
+
response: code_lens,
|
|
1482
1525
|
))
|
|
1483
1526
|
end
|
|
1484
1527
|
end
|