ruby-lsp 0.23.11 → 0.23.17
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 +2 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp-launcher +20 -11
- data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +82 -116
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +134 -183
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -10
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +97 -217
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +139 -281
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +18 -19
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +23 -55
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +47 -61
- data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
- data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
- data/lib/ruby_indexer/test/configuration_test.rb +48 -7
- data/lib/ruby_indexer/test/constant_test.rb +34 -34
- data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
- data/lib/ruby_indexer/test/index_test.rb +146 -135
- data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
- data/lib/ruby_indexer/test/method_test.rb +149 -123
- data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +68 -73
- data/lib/ruby_indexer/test/test_case.rb +9 -3
- data/lib/ruby_indexer/test/uri_test.rb +15 -2
- data/lib/ruby_lsp/addon.rb +44 -71
- data/lib/ruby_lsp/base_server.rb +29 -32
- data/lib/ruby_lsp/client_capabilities.rb +10 -12
- data/lib/ruby_lsp/document.rb +40 -54
- data/lib/ruby_lsp/erb_document.rb +37 -41
- data/lib/ruby_lsp/global_state.rb +52 -57
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
- data/lib/ruby_lsp/listeners/completion.rb +67 -73
- data/lib/ruby_lsp/listeners/definition.rb +44 -58
- data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
- data/lib/ruby_lsp/listeners/document_link.rb +50 -70
- data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
- data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
- data/lib/ruby_lsp/listeners/hover.rb +92 -110
- data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
- data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
- data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
- data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
- data/lib/ruby_lsp/listeners/test_style.rb +167 -90
- data/lib/ruby_lsp/node_context.rb +12 -39
- data/lib/ruby_lsp/rbs_document.rb +9 -7
- data/lib/ruby_lsp/requests/code_action_resolve.rb +63 -59
- data/lib/ruby_lsp/requests/code_actions.rb +14 -26
- data/lib/ruby_lsp/requests/code_lens.rb +20 -19
- data/lib/ruby_lsp/requests/completion.rb +7 -20
- data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
- data/lib/ruby_lsp/requests/definition.rb +7 -17
- data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
- data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
- data/lib/ruby_lsp/requests/document_link.rb +6 -17
- data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
- data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
- data/lib/ruby_lsp/requests/formatting.rb +6 -9
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +85 -0
- data/lib/ruby_lsp/requests/hover.rb +10 -20
- data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
- data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
- data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
- data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
- data/lib/ruby_lsp/requests/references.rb +9 -53
- data/lib/ruby_lsp/requests/rename.rb +20 -46
- data/lib/ruby_lsp/requests/request.rb +8 -19
- data/lib/ruby_lsp/requests/selection_ranges.rb +6 -6
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
- data/lib/ruby_lsp/requests/signature_help.rb +8 -26
- data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
- data/lib/ruby_lsp/requests/support/common.rb +15 -55
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +11 -14
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
- data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
- data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
- data/lib/ruby_lsp/requests/support/source_uri.rb +20 -32
- data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
- data/lib/ruby_lsp/requests/support/test_item.rb +16 -14
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
- data/lib/ruby_lsp/response_builders/document_symbol.rb +14 -19
- data/lib/ruby_lsp/response_builders/hover.rb +11 -14
- data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +60 -88
- data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
- data/lib/ruby_lsp/response_builders/test_collection.rb +43 -10
- data/lib/ruby_lsp/ruby_document.rb +24 -92
- data/lib/ruby_lsp/scope.rb +7 -11
- data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
- data/lib/ruby_lsp/server.rb +182 -99
- data/lib/ruby_lsp/setup_bundler.rb +65 -60
- data/lib/ruby_lsp/static_docs.rb +11 -7
- data/lib/ruby_lsp/store.rb +29 -47
- data/lib/ruby_lsp/test_helper.rb +2 -12
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +191 -0
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
- data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
- data/lib/ruby_lsp/type_inferrer.rb +13 -14
- data/lib/ruby_lsp/utils.rb +92 -83
- metadata +9 -3
data/lib/ruby_lsp/server.rb
CHANGED
@@ -3,13 +3,12 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
class Server < BaseServer
|
6
|
-
extend T::Sig
|
7
|
-
|
8
6
|
# Only for testing
|
9
|
-
|
7
|
+
#: GlobalState
|
10
8
|
attr_reader :global_state
|
11
9
|
|
12
|
-
|
10
|
+
# @override
|
11
|
+
#: (Hash[Symbol, untyped] message) -> void
|
13
12
|
def process_message(message)
|
14
13
|
case message[:method]
|
15
14
|
when "initialize"
|
@@ -112,6 +111,10 @@ module RubyLsp
|
|
112
111
|
diagnose_state(message)
|
113
112
|
when "rubyLsp/discoverTests"
|
114
113
|
discover_tests(message)
|
114
|
+
when "rubyLsp/resolveTestCommands"
|
115
|
+
resolve_test_commands(message)
|
116
|
+
when "experimental/goToRelevantFile"
|
117
|
+
experimental_go_to_relevant_file(message)
|
115
118
|
when "$/cancelRequest"
|
116
119
|
@global_state.synchronize { @cancelled_requests << message[:params][:id] }
|
117
120
|
when nil
|
@@ -161,7 +164,7 @@ module RubyLsp
|
|
161
164
|
end
|
162
165
|
|
163
166
|
# Process responses to requests that were sent to the client
|
164
|
-
|
167
|
+
#: (Hash[Symbol, untyped] message) -> void
|
165
168
|
def process_response(message)
|
166
169
|
case message.dig(:result, :method)
|
167
170
|
when "window/showMessageRequest"
|
@@ -169,7 +172,7 @@ module RubyLsp
|
|
169
172
|
end
|
170
173
|
end
|
171
174
|
|
172
|
-
|
175
|
+
#: (?include_project_addons: bool) -> void
|
173
176
|
def load_addons(include_project_addons: true)
|
174
177
|
# If invoking Bundler.setup failed, then the load path will not be configured properly and trying to load add-ons
|
175
178
|
# with Gem.find_files will find every single version installed of an add-on, leading to requiring several
|
@@ -209,7 +212,7 @@ module RubyLsp
|
|
209
212
|
|
210
213
|
private
|
211
214
|
|
212
|
-
|
215
|
+
#: (Hash[Symbol, untyped] message) -> void
|
213
216
|
def run_initialize(message)
|
214
217
|
options = message[:params]
|
215
218
|
global_state_notifications = @global_state.apply_options(options)
|
@@ -220,7 +223,8 @@ module RubyLsp
|
|
220
223
|
configured_features = options.dig(:initializationOptions, :enabledFeatures)
|
221
224
|
|
222
225
|
configured_hints = options.dig(:initializationOptions, :featuresConfiguration, :inlayHint)
|
223
|
-
|
226
|
+
@store.features_configuration.dig(:inlayHint) #: as !nil
|
227
|
+
.configuration.merge!(configured_hints) if configured_hints
|
224
228
|
|
225
229
|
enabled_features = case configured_features
|
226
230
|
when Array
|
@@ -238,7 +242,9 @@ module RubyLsp
|
|
238
242
|
|
239
243
|
bundle_env_path = File.join(".ruby-lsp", "bundle_env")
|
240
244
|
bundle_env = if File.exist?(bundle_env_path)
|
241
|
-
env = File.readlines(bundle_env_path).to_h
|
245
|
+
env = File.readlines(bundle_env_path).to_h do |line|
|
246
|
+
line.chomp.split("=", 2) #: as [String, String]
|
247
|
+
end
|
242
248
|
FileUtils.rm(bundle_env_path)
|
243
249
|
env
|
244
250
|
end
|
@@ -290,6 +296,8 @@ module RubyLsp
|
|
290
296
|
experimental: {
|
291
297
|
addon_detection: true,
|
292
298
|
compose_bundle: true,
|
299
|
+
go_to_relevant_file: true,
|
300
|
+
full_test_discovery: true,
|
293
301
|
},
|
294
302
|
),
|
295
303
|
serverInfo: {
|
@@ -346,7 +354,7 @@ module RubyLsp
|
|
346
354
|
end
|
347
355
|
end
|
348
356
|
|
349
|
-
|
357
|
+
#: -> void
|
350
358
|
def run_initialized
|
351
359
|
load_addons
|
352
360
|
RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
|
@@ -373,17 +381,17 @@ module RubyLsp
|
|
373
381
|
check_formatter_is_available
|
374
382
|
end
|
375
383
|
|
376
|
-
|
384
|
+
#: (Hash[Symbol, untyped] message) -> void
|
377
385
|
def text_document_did_open(message)
|
378
386
|
@global_state.synchronize do
|
379
387
|
text_document = message.dig(:params, :textDocument)
|
380
388
|
language_id = case text_document[:languageId]
|
381
389
|
when "erb", "eruby"
|
382
|
-
|
390
|
+
:erb
|
383
391
|
when "rbs"
|
384
|
-
|
392
|
+
:rbs
|
385
393
|
else
|
386
|
-
|
394
|
+
:ruby
|
387
395
|
end
|
388
396
|
|
389
397
|
document = @store.set(
|
@@ -412,7 +420,7 @@ module RubyLsp
|
|
412
420
|
end
|
413
421
|
end
|
414
422
|
|
415
|
-
|
423
|
+
#: (Hash[Symbol, untyped] message) -> void
|
416
424
|
def text_document_did_close(message)
|
417
425
|
@global_state.synchronize do
|
418
426
|
uri = message.dig(:params, :textDocument, :uri)
|
@@ -423,7 +431,7 @@ module RubyLsp
|
|
423
431
|
end
|
424
432
|
end
|
425
433
|
|
426
|
-
|
434
|
+
#: (Hash[Symbol, untyped] message) -> void
|
427
435
|
def text_document_did_change(message)
|
428
436
|
params = message[:params]
|
429
437
|
text_document = params[:textDocument]
|
@@ -433,7 +441,7 @@ module RubyLsp
|
|
433
441
|
end
|
434
442
|
end
|
435
443
|
|
436
|
-
|
444
|
+
#: (Hash[Symbol, untyped] message) -> void
|
437
445
|
def text_document_selection_range(message)
|
438
446
|
uri = message.dig(:params, :textDocument, :uri)
|
439
447
|
ranges = @store.cache_fetch(uri, "textDocument/selectionRange") do |document|
|
@@ -459,7 +467,7 @@ module RubyLsp
|
|
459
467
|
send_message(Result.new(id: message[:id], response: response))
|
460
468
|
end
|
461
469
|
|
462
|
-
|
470
|
+
#: (Hash[Symbol, untyped] message) -> void
|
463
471
|
def run_combined_requests(message)
|
464
472
|
uri = URI(message.dig(:params, :textDocument, :uri))
|
465
473
|
document = @store.get(uri)
|
@@ -483,8 +491,15 @@ module RubyLsp
|
|
483
491
|
folding_range = Requests::FoldingRanges.new(parse_result.comments, dispatcher)
|
484
492
|
document_symbol = Requests::DocumentSymbol.new(uri, dispatcher)
|
485
493
|
document_link = Requests::DocumentLink.new(uri, parse_result.comments, dispatcher)
|
486
|
-
|
487
|
-
|
494
|
+
inlay_hint = Requests::InlayHints.new(
|
495
|
+
document,
|
496
|
+
@store.features_configuration.dig(:inlayHint), #: as !nil
|
497
|
+
dispatcher,
|
498
|
+
)
|
499
|
+
|
500
|
+
# The code lens listener requires the index to be populated, so the DeclarationListener must be inserted first in
|
501
|
+
# the dispatcher's state
|
502
|
+
code_lens = nil #: Requests::CodeLens?
|
488
503
|
|
489
504
|
if document.is_a?(RubyDocument) && document.should_index?
|
490
505
|
# Re-index the file as it is modified. This mode of indexing updates entries only. Require path trees are only
|
@@ -495,10 +510,12 @@ module RubyLsp
|
|
495
510
|
@global_state.index.handle_change(uri) do |index|
|
496
511
|
index.delete(uri, skip_require_paths_tree: true)
|
497
512
|
RubyIndexer::DeclarationListener.new(index, dispatcher, parse_result, uri, collect_comments: true)
|
513
|
+
code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
|
498
514
|
dispatcher.dispatch(parse_result.value)
|
499
515
|
end
|
500
516
|
end
|
501
517
|
else
|
518
|
+
code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
|
502
519
|
dispatcher.dispatch(parse_result.value)
|
503
520
|
end
|
504
521
|
|
@@ -507,7 +524,11 @@ module RubyLsp
|
|
507
524
|
document.cache_set("textDocument/foldingRange", folding_range.perform)
|
508
525
|
document.cache_set("textDocument/documentSymbol", document_symbol.perform)
|
509
526
|
document.cache_set("textDocument/documentLink", document_link.perform)
|
510
|
-
document.cache_set(
|
527
|
+
document.cache_set(
|
528
|
+
"textDocument/codeLens",
|
529
|
+
code_lens #: as !nil
|
530
|
+
.perform,
|
531
|
+
)
|
511
532
|
document.cache_set("textDocument/inlayHint", inlay_hint.perform)
|
512
533
|
|
513
534
|
send_message(Result.new(id: message[:id], response: document.cache_get(message[:method])))
|
@@ -518,7 +539,7 @@ module RubyLsp
|
|
518
539
|
alias_method :text_document_code_lens, :run_combined_requests
|
519
540
|
alias_method :text_document_folding_range, :run_combined_requests
|
520
541
|
|
521
|
-
|
542
|
+
#: (Hash[Symbol, untyped] message) -> void
|
522
543
|
def text_document_semantic_tokens_full(message)
|
523
544
|
document = @store.get(message.dig(:params, :textDocument, :uri))
|
524
545
|
|
@@ -539,7 +560,7 @@ module RubyLsp
|
|
539
560
|
send_message(Result.new(id: message[:id], response: semantic_highlighting.perform))
|
540
561
|
end
|
541
562
|
|
542
|
-
|
563
|
+
#: (Hash[Symbol, untyped] message) -> void
|
543
564
|
def text_document_semantic_tokens_delta(message)
|
544
565
|
document = @store.get(message.dig(:params, :textDocument, :uri))
|
545
566
|
|
@@ -564,7 +585,7 @@ module RubyLsp
|
|
564
585
|
send_message(Result.new(id: message[:id], response: request.perform))
|
565
586
|
end
|
566
587
|
|
567
|
-
|
588
|
+
#: (Hash[Symbol, untyped] message) -> void
|
568
589
|
def text_document_semantic_tokens_range(message)
|
569
590
|
params = message[:params]
|
570
591
|
range = params[:range]
|
@@ -593,7 +614,7 @@ module RubyLsp
|
|
593
614
|
send_message(Result.new(id: message[:id], response: request.perform))
|
594
615
|
end
|
595
616
|
|
596
|
-
|
617
|
+
#: (Hash[Symbol, untyped] message) -> void
|
597
618
|
def text_document_range_formatting(message)
|
598
619
|
# If formatter is set to `auto` but no supported formatting gem is found, don't attempt to format
|
599
620
|
if @global_state.formatter == "none"
|
@@ -621,7 +642,7 @@ module RubyLsp
|
|
621
642
|
send_message(Result.new(id: message[:id], response: response))
|
622
643
|
end
|
623
644
|
|
624
|
-
|
645
|
+
#: (Hash[Symbol, untyped] message) -> void
|
625
646
|
def text_document_formatting(message)
|
626
647
|
# If formatter is set to `auto` but no supported formatting gem is found, don't attempt to format
|
627
648
|
if @global_state.formatter == "none"
|
@@ -662,10 +683,14 @@ module RubyLsp
|
|
662
683
|
"Formatting error: #{error.message}",
|
663
684
|
type: Constant::MessageType::ERROR,
|
664
685
|
))
|
686
|
+
send_message(Notification.window_log_message(
|
687
|
+
"Formatting failed with\r\n: #{error.full_message}",
|
688
|
+
type: Constant::MessageType::ERROR,
|
689
|
+
))
|
665
690
|
send_empty_response(message[:id])
|
666
691
|
end
|
667
692
|
|
668
|
-
|
693
|
+
#: (Hash[Symbol, untyped] message) -> void
|
669
694
|
def text_document_document_highlight(message)
|
670
695
|
params = message[:params]
|
671
696
|
dispatcher = Prism::Dispatcher.new
|
@@ -681,7 +706,7 @@ module RubyLsp
|
|
681
706
|
send_message(Result.new(id: message[:id], response: request.perform))
|
682
707
|
end
|
683
708
|
|
684
|
-
|
709
|
+
#: (Hash[Symbol, untyped] message) -> void
|
685
710
|
def text_document_on_type_formatting(message)
|
686
711
|
params = message[:params]
|
687
712
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -704,7 +729,7 @@ module RubyLsp
|
|
704
729
|
)
|
705
730
|
end
|
706
731
|
|
707
|
-
|
732
|
+
#: (Hash[Symbol, untyped] message) -> void
|
708
733
|
def text_document_hover(message)
|
709
734
|
params = message[:params]
|
710
735
|
dispatcher = Prism::Dispatcher.new
|
@@ -729,7 +754,7 @@ module RubyLsp
|
|
729
754
|
)
|
730
755
|
end
|
731
756
|
|
732
|
-
|
757
|
+
#: (Hash[Symbol, untyped] message) -> void
|
733
758
|
def text_document_rename(message)
|
734
759
|
params = message[:params]
|
735
760
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -749,7 +774,7 @@ module RubyLsp
|
|
749
774
|
send_message(Error.new(id: message[:id], code: Constant::ErrorCodes::REQUEST_FAILED, message: e.message))
|
750
775
|
end
|
751
776
|
|
752
|
-
|
777
|
+
#: (Hash[Symbol, untyped] message) -> void
|
753
778
|
def text_document_prepare_rename(message)
|
754
779
|
params = message[:params]
|
755
780
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -767,7 +792,7 @@ module RubyLsp
|
|
767
792
|
)
|
768
793
|
end
|
769
794
|
|
770
|
-
|
795
|
+
#: (Hash[Symbol, untyped] message) -> void
|
771
796
|
def text_document_references(message)
|
772
797
|
params = message[:params]
|
773
798
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -785,15 +810,19 @@ module RubyLsp
|
|
785
810
|
)
|
786
811
|
end
|
787
812
|
|
788
|
-
|
813
|
+
#: (Document[untyped] document) -> SorbetLevel
|
789
814
|
def sorbet_level(document)
|
790
|
-
return
|
791
|
-
return
|
815
|
+
return SorbetLevel.ignore unless document.is_a?(RubyDocument)
|
816
|
+
return SorbetLevel.ignore unless @global_state.has_type_checker
|
792
817
|
|
793
|
-
document.
|
818
|
+
sigil = document.parse_result.magic_comments.find do |comment|
|
819
|
+
comment.key == "typed"
|
820
|
+
end&.value
|
821
|
+
|
822
|
+
SorbetLevel.new(sigil)
|
794
823
|
end
|
795
824
|
|
796
|
-
|
825
|
+
#: (Hash[Symbol, untyped] message) -> void
|
797
826
|
def text_document_inlay_hint(message)
|
798
827
|
params = message[:params]
|
799
828
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -811,7 +840,7 @@ module RubyLsp
|
|
811
840
|
return
|
812
841
|
end
|
813
842
|
|
814
|
-
hints_configurations =
|
843
|
+
hints_configurations = @store.features_configuration.dig(:inlayHint) #: as !nil
|
815
844
|
dispatcher = Prism::Dispatcher.new
|
816
845
|
|
817
846
|
unless document.is_a?(RubyDocument) || document.is_a?(ERBDocument)
|
@@ -827,7 +856,7 @@ module RubyLsp
|
|
827
856
|
send_message(Result.new(id: message[:id], response: result.select { |hint| range.cover?(hint.position[:line]) }))
|
828
857
|
end
|
829
858
|
|
830
|
-
|
859
|
+
#: (Hash[Symbol, untyped] message) -> void
|
831
860
|
def text_document_code_action(message)
|
832
861
|
params = message[:params]
|
833
862
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -849,7 +878,7 @@ module RubyLsp
|
|
849
878
|
)
|
850
879
|
end
|
851
880
|
|
852
|
-
|
881
|
+
#: (Hash[Symbol, untyped] message) -> void
|
853
882
|
def code_action_resolve(message)
|
854
883
|
params = message[:params]
|
855
884
|
uri = URI(params.dig(:data, :uri))
|
@@ -861,20 +890,12 @@ module RubyLsp
|
|
861
890
|
end
|
862
891
|
|
863
892
|
result = Requests::CodeActionResolve.new(document, @global_state, params).perform
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
fail_request_and_notify(message[:id], "Invalid selection for extract variable refactor")
|
868
|
-
when Requests::CodeActionResolve::Error::InvalidTargetRange
|
869
|
-
fail_request_and_notify(message[:id], "Couldn't find an appropriate location to place extracted refactor")
|
870
|
-
when Requests::CodeActionResolve::Error::UnknownCodeAction
|
871
|
-
fail_request_and_notify(message[:id], "Unknown code action")
|
872
|
-
else
|
873
|
-
send_message(Result.new(id: message[:id], response: result))
|
874
|
-
end
|
893
|
+
send_message(Result.new(id: message[:id], response: result))
|
894
|
+
rescue Requests::CodeActionResolve::CodeActionError => e
|
895
|
+
fail_request_and_notify(message[:id], e.message)
|
875
896
|
end
|
876
897
|
|
877
|
-
|
898
|
+
#: (Hash[Symbol, untyped] message) -> void
|
878
899
|
def text_document_diagnostic(message)
|
879
900
|
# Do not compute diagnostics for files outside of the workspace. For example, if someone is looking at a gem's
|
880
901
|
# source code, we don't want to show diagnostics for it
|
@@ -911,10 +932,14 @@ module RubyLsp
|
|
911
932
|
"Error running diagnostics: #{error.message}",
|
912
933
|
type: Constant::MessageType::ERROR,
|
913
934
|
))
|
935
|
+
send_message(Notification.window_log_message(
|
936
|
+
"Diagnostics failed with\r\n: #{error.full_message}",
|
937
|
+
type: Constant::MessageType::ERROR,
|
938
|
+
))
|
914
939
|
send_empty_response(message[:id])
|
915
940
|
end
|
916
941
|
|
917
|
-
|
942
|
+
#: (Hash[Symbol, untyped] message) -> void
|
918
943
|
def text_document_completion(message)
|
919
944
|
params = message[:params]
|
920
945
|
dispatcher = Prism::Dispatcher.new
|
@@ -939,7 +964,7 @@ module RubyLsp
|
|
939
964
|
)
|
940
965
|
end
|
941
966
|
|
942
|
-
|
967
|
+
#: (Hash[Symbol, untyped] message) -> void
|
943
968
|
def text_document_completion_item_resolve(message)
|
944
969
|
# When responding to a delegated completion request, it means we're handling a completion item that isn't related
|
945
970
|
# to Ruby (probably related to an ERB host language like HTML). We need to return the original completion item
|
@@ -958,7 +983,7 @@ module RubyLsp
|
|
958
983
|
))
|
959
984
|
end
|
960
985
|
|
961
|
-
|
986
|
+
#: (Hash[Symbol, untyped] message) -> void
|
962
987
|
def text_document_signature_help(message)
|
963
988
|
params = message[:params]
|
964
989
|
dispatcher = Prism::Dispatcher.new
|
@@ -984,7 +1009,7 @@ module RubyLsp
|
|
984
1009
|
)
|
985
1010
|
end
|
986
1011
|
|
987
|
-
|
1012
|
+
#: (Hash[Symbol, untyped] message) -> void
|
988
1013
|
def text_document_definition(message)
|
989
1014
|
params = message[:params]
|
990
1015
|
dispatcher = Prism::Dispatcher.new
|
@@ -1009,8 +1034,23 @@ module RubyLsp
|
|
1009
1034
|
)
|
1010
1035
|
end
|
1011
1036
|
|
1012
|
-
|
1037
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1013
1038
|
def workspace_did_change_watched_files(message)
|
1039
|
+
# If indexing is not complete yet, delay processing did change watched file notifications. We need initial
|
1040
|
+
# indexing to be in place so that we can handle file changes appropriately without risking duplicates. We also
|
1041
|
+
# have to sleep before re-inserting the notification in the queue otherwise the worker can get stuck in its own
|
1042
|
+
# loop of pushing and popping the same notification
|
1043
|
+
unless @global_state.index.initial_indexing_completed
|
1044
|
+
Thread.new do
|
1045
|
+
sleep(2)
|
1046
|
+
# We have to ensure that the queue is not closed yet, since nothing stops the user from saving a file and then
|
1047
|
+
# immediately telling the LSP to shutdown
|
1048
|
+
@incoming_queue << message unless @incoming_queue.closed?
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
return
|
1052
|
+
end
|
1053
|
+
|
1014
1054
|
changes = message.dig(:params, :changes)
|
1015
1055
|
# We allow add-ons to register for watching files and we have no restrictions for what they register for. If the
|
1016
1056
|
# same pattern is registered more than once, the LSP will receive duplicate change notifications. Receiving them
|
@@ -1037,7 +1077,8 @@ module RubyLsp
|
|
1037
1077
|
end
|
1038
1078
|
|
1039
1079
|
Addon.file_watcher_addons.each do |addon|
|
1040
|
-
|
1080
|
+
addon #: as untyped
|
1081
|
+
.workspace_did_change_watched_files(changes)
|
1041
1082
|
rescue => e
|
1042
1083
|
send_log_message(
|
1043
1084
|
"Error in #{addon.name} add-on while processing watched file notifications: #{e.full_message}",
|
@@ -1046,32 +1087,34 @@ module RubyLsp
|
|
1046
1087
|
end
|
1047
1088
|
end
|
1048
1089
|
|
1049
|
-
|
1090
|
+
#: (RubyIndexer::Index index, String file_path, Integer change_type) -> void
|
1050
1091
|
def handle_ruby_file_change(index, file_path, change_type)
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1092
|
+
@global_state.synchronize do
|
1093
|
+
load_path_entry = $LOAD_PATH.find { |load_path| file_path.start_with?(load_path) }
|
1094
|
+
uri = URI::Generic.from_path(load_path_entry: load_path_entry, path: file_path)
|
1095
|
+
|
1096
|
+
case change_type
|
1097
|
+
when Constant::FileChangeType::CREATED
|
1098
|
+
content = File.read(file_path)
|
1099
|
+
# If we receive a late created notification for a file that has already been claimed by the client, we want to
|
1100
|
+
# handle change for that URI so that the require path tree is updated
|
1101
|
+
@store.key?(uri) ? index.handle_change(uri, content) : index.index_single(uri, content)
|
1102
|
+
when Constant::FileChangeType::CHANGED
|
1103
|
+
content = File.read(file_path)
|
1104
|
+
# We only handle changes on file watched notifications if the client is not the one managing this URI.
|
1105
|
+
# Otherwise, these changes are handled when running the combined requests
|
1106
|
+
index.handle_change(uri, content) unless @store.key?(uri)
|
1107
|
+
when Constant::FileChangeType::DELETED
|
1108
|
+
index.delete(uri)
|
1109
|
+
end
|
1110
|
+
rescue Errno::ENOENT
|
1111
|
+
# If a file is created and then delete immediately afterwards, we will process the created notification before
|
1112
|
+
# we receive the deleted one, but the file no longer exists. This may happen when running a test suite that
|
1113
|
+
# creates and deletes files automatically.
|
1114
|
+
end
|
1072
1115
|
end
|
1073
1116
|
|
1074
|
-
|
1117
|
+
#: (URI::Generic uri) -> void
|
1075
1118
|
def handle_rubocop_config_change(uri)
|
1076
1119
|
return unless defined?(Requests::Support::RuboCopFormatter)
|
1077
1120
|
|
@@ -1091,7 +1134,7 @@ module RubyLsp
|
|
1091
1134
|
end
|
1092
1135
|
end
|
1093
1136
|
|
1094
|
-
|
1137
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1095
1138
|
def workspace_symbol(message)
|
1096
1139
|
send_message(
|
1097
1140
|
Result.new(
|
@@ -1104,7 +1147,7 @@ module RubyLsp
|
|
1104
1147
|
)
|
1105
1148
|
end
|
1106
1149
|
|
1107
|
-
|
1150
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1108
1151
|
def text_document_show_syntax_tree(message)
|
1109
1152
|
params = message[:params]
|
1110
1153
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -1123,7 +1166,26 @@ module RubyLsp
|
|
1123
1166
|
send_message(Result.new(id: message[:id], response: response))
|
1124
1167
|
end
|
1125
1168
|
|
1126
|
-
|
1169
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1170
|
+
def experimental_go_to_relevant_file(message)
|
1171
|
+
path = message.dig(:params, :textDocument, :uri).to_standardized_path
|
1172
|
+
unless path.nil? || path.start_with?(@global_state.workspace_path)
|
1173
|
+
send_empty_response(message[:id])
|
1174
|
+
return
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
unless path
|
1178
|
+
send_empty_response(message[:id])
|
1179
|
+
return
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
response = {
|
1183
|
+
locations: Requests::GoToRelevantFile.new(path, @global_state.workspace_path).perform,
|
1184
|
+
}
|
1185
|
+
send_message(Result.new(id: message[:id], response: response))
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1127
1189
|
def text_document_prepare_type_hierarchy(message)
|
1128
1190
|
params = message[:params]
|
1129
1191
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -1142,7 +1204,7 @@ module RubyLsp
|
|
1142
1204
|
send_message(Result.new(id: message[:id], response: response))
|
1143
1205
|
end
|
1144
1206
|
|
1145
|
-
|
1207
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1146
1208
|
def type_hierarchy_supertypes(message)
|
1147
1209
|
response = Requests::TypeHierarchySupertypes.new(
|
1148
1210
|
@global_state.index,
|
@@ -1151,14 +1213,14 @@ module RubyLsp
|
|
1151
1213
|
send_message(Result.new(id: message[:id], response: response))
|
1152
1214
|
end
|
1153
1215
|
|
1154
|
-
|
1216
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1155
1217
|
def type_hierarchy_subtypes(message)
|
1156
1218
|
# TODO: implement subtypes
|
1157
1219
|
# The current index representation doesn't allow us to find the children of an entry.
|
1158
1220
|
send_message(Result.new(id: message[:id], response: nil))
|
1159
1221
|
end
|
1160
1222
|
|
1161
|
-
|
1223
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1162
1224
|
def workspace_dependencies(message)
|
1163
1225
|
unless @global_state.top_level_bundle
|
1164
1226
|
send_message(Result.new(id: message[:id], response: []))
|
@@ -1186,12 +1248,13 @@ module RubyLsp
|
|
1186
1248
|
send_message(Result.new(id: message[:id], response: response))
|
1187
1249
|
end
|
1188
1250
|
|
1189
|
-
|
1251
|
+
# @override
|
1252
|
+
#: -> void
|
1190
1253
|
def shutdown
|
1191
1254
|
Addon.unload_addons
|
1192
1255
|
end
|
1193
1256
|
|
1194
|
-
|
1257
|
+
#: -> void
|
1195
1258
|
def perform_initial_indexing
|
1196
1259
|
# The begin progress invocation happens during `initialize`, so that the notification is sent before we are
|
1197
1260
|
# stuck indexing files
|
@@ -1223,7 +1286,7 @@ module RubyLsp
|
|
1223
1286
|
end
|
1224
1287
|
end
|
1225
1288
|
|
1226
|
-
|
1289
|
+
#: (String id, String title, ?percentage: Integer) -> void
|
1227
1290
|
def begin_progress(id, title, percentage: 0)
|
1228
1291
|
return unless @global_state.client_capabilities.supports_progress
|
1229
1292
|
|
@@ -1236,14 +1299,14 @@ module RubyLsp
|
|
1236
1299
|
send_message(Notification.progress_begin(id, title, percentage: percentage, message: "#{percentage}% completed"))
|
1237
1300
|
end
|
1238
1301
|
|
1239
|
-
|
1302
|
+
#: (String id, Integer percentage) -> void
|
1240
1303
|
def progress(id, percentage)
|
1241
1304
|
return unless @global_state.client_capabilities.supports_progress
|
1242
1305
|
|
1243
1306
|
send_message(Notification.progress_report(id, percentage: percentage, message: "#{percentage}% completed"))
|
1244
1307
|
end
|
1245
1308
|
|
1246
|
-
|
1309
|
+
#: (String id) -> void
|
1247
1310
|
def end_progress(id)
|
1248
1311
|
return unless @global_state.client_capabilities.supports_progress
|
1249
1312
|
|
@@ -1253,7 +1316,7 @@ module RubyLsp
|
|
1253
1316
|
# notification
|
1254
1317
|
end
|
1255
1318
|
|
1256
|
-
|
1319
|
+
#: -> void
|
1257
1320
|
def check_formatter_is_available
|
1258
1321
|
return if @setup_error
|
1259
1322
|
# Warn of an unavailable `formatter` setting, e.g. `rubocop_internal` on a project which doesn't have RuboCop.
|
@@ -1271,7 +1334,7 @@ module RubyLsp
|
|
1271
1334
|
end
|
1272
1335
|
end
|
1273
1336
|
|
1274
|
-
|
1337
|
+
#: (Hash[Symbol, untyped]? indexing_options) -> void
|
1275
1338
|
def process_indexing_configuration(indexing_options)
|
1276
1339
|
# Need to use the workspace URI, otherwise, this will fail for people working on a project that is a symlink.
|
1277
1340
|
index_path = File.join(@global_state.workspace_path, ".index.yml")
|
@@ -1312,7 +1375,7 @@ module RubyLsp
|
|
1312
1375
|
configuration.apply_config(indexing_options.transform_keys { |key| key.to_s.gsub(/([A-Z])/, "_\\1").downcase })
|
1313
1376
|
end
|
1314
1377
|
|
1315
|
-
|
1378
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1316
1379
|
def window_show_message_request(message)
|
1317
1380
|
result = message[:result]
|
1318
1381
|
return unless result
|
@@ -1327,7 +1390,7 @@ module RubyLsp
|
|
1327
1390
|
# NOTE: all servers methods are void because they can produce several messages for the client. The only reason this
|
1328
1391
|
# method returns the created thread is to that we can join it in tests and avoid flakiness. The implementation is
|
1329
1392
|
# not supposed to rely on the return of this method
|
1330
|
-
|
1393
|
+
#: (Hash[Symbol, untyped] message) -> Thread?
|
1331
1394
|
def compose_bundle(message)
|
1332
1395
|
already_composed_path = File.join(@global_state.workspace_path, ".ruby-lsp", "bundle_is_composed")
|
1333
1396
|
id = message[:id]
|
@@ -1352,7 +1415,9 @@ module RubyLsp
|
|
1352
1415
|
Open3.capture3(
|
1353
1416
|
Gem.ruby,
|
1354
1417
|
"-I",
|
1355
|
-
File.dirname(
|
1418
|
+
File.dirname(
|
1419
|
+
__dir__, #: as !nil
|
1420
|
+
),
|
1356
1421
|
File.expand_path("../../exe/ruby-lsp-launcher", __dir__),
|
1357
1422
|
@global_state.workspace_uri.to_s,
|
1358
1423
|
chdir: @global_state.workspace_path,
|
@@ -1374,7 +1439,7 @@ module RubyLsp
|
|
1374
1439
|
end
|
1375
1440
|
|
1376
1441
|
# Returns internal state information for debugging purposes
|
1377
|
-
|
1442
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1378
1443
|
def diagnose_state(message)
|
1379
1444
|
documents = {}
|
1380
1445
|
@store.each { |uri, document| documents[uri] = document.source }
|
@@ -1394,7 +1459,7 @@ module RubyLsp
|
|
1394
1459
|
|
1395
1460
|
# Discovers all available test groups and examples in a given file taking into consideration the merged response of
|
1396
1461
|
# all add-ons
|
1397
|
-
|
1462
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1398
1463
|
def discover_tests(message)
|
1399
1464
|
document = @store.get(message.dig(:params, :textDocument, :uri))
|
1400
1465
|
|
@@ -1414,5 +1479,23 @@ module RubyLsp
|
|
1414
1479
|
|
1415
1480
|
send_message(Result.new(id: message[:id], response: items.map(&:to_hash)))
|
1416
1481
|
end
|
1482
|
+
|
1483
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1484
|
+
def resolve_test_commands(message)
|
1485
|
+
items = message.dig(:params, :items)
|
1486
|
+
commands = Listeners::TestStyle.resolve_test_commands(items)
|
1487
|
+
|
1488
|
+
Addon.addons.each do |addon|
|
1489
|
+
commands.concat(addon.resolve_test_commands(items))
|
1490
|
+
end
|
1491
|
+
|
1492
|
+
send_message(Result.new(
|
1493
|
+
id: message[:id],
|
1494
|
+
response: {
|
1495
|
+
commands: commands,
|
1496
|
+
reporterPaths: [Listeners::TestStyle::MINITEST_REPORTER_PATH, Listeners::TestStyle::TEST_UNIT_REPORTER_PATH],
|
1497
|
+
},
|
1498
|
+
))
|
1499
|
+
end
|
1417
1500
|
end
|
1418
1501
|
end
|