ruby-lsp 0.23.11 → 0.23.16
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 +123 -169
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -7
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +92 -202
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +116 -222
- 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 +22 -45
- 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 +5 -9
- 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 +139 -135
- data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
- data/lib/ruby_indexer/test/method_test.rb +143 -117
- data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +65 -71
- data/lib/ruby_indexer/test/test_case.rb +2 -2
- 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 +39 -45
- data/lib/ruby_lsp/erb_document.rb +36 -40
- 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 +60 -66
- data/lib/ruby_lsp/listeners/definition.rb +38 -52
- data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
- data/lib/ruby_lsp/listeners/document_link.rb +46 -63
- 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 +83 -102
- 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 +11 -26
- 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 +160 -88
- data/lib/ruby_lsp/node_context.rb +12 -39
- data/lib/ruby_lsp/rbs_document.rb +8 -6
- data/lib/ruby_lsp/requests/code_action_resolve.rb +24 -25
- data/lib/ruby_lsp/requests/code_actions.rb +14 -26
- data/lib/ruby_lsp/requests/code_lens.rb +6 -17
- 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 +8 -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 +87 -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 +8 -37
- data/lib/ruby_lsp/requests/rename.rb +19 -42
- data/lib/ruby_lsp/requests/request.rb +7 -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 +16 -51
- 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 +10 -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 +13 -18
- 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 +6 -10
- data/lib/ruby_lsp/ruby_document.rb +24 -62
- data/lib/ruby_lsp/scope.rb +7 -11
- data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
- data/lib/ruby_lsp/server.rb +147 -79
- data/lib/ruby_lsp/setup_bundler.rb +65 -60
- data/lib/ruby_lsp/static_docs.rb +11 -7
- data/lib/ruby_lsp/store.rb +24 -42
- data/lib/ruby_lsp/test_helper.rb +2 -12
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +164 -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 +49 -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
|
@@ -290,6 +294,8 @@ module RubyLsp
|
|
290
294
|
experimental: {
|
291
295
|
addon_detection: true,
|
292
296
|
compose_bundle: true,
|
297
|
+
go_to_relevant_file: true,
|
298
|
+
full_test_discovery: true,
|
293
299
|
},
|
294
300
|
),
|
295
301
|
serverInfo: {
|
@@ -346,7 +352,7 @@ module RubyLsp
|
|
346
352
|
end
|
347
353
|
end
|
348
354
|
|
349
|
-
|
355
|
+
#: -> void
|
350
356
|
def run_initialized
|
351
357
|
load_addons
|
352
358
|
RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
|
@@ -373,7 +379,7 @@ module RubyLsp
|
|
373
379
|
check_formatter_is_available
|
374
380
|
end
|
375
381
|
|
376
|
-
|
382
|
+
#: (Hash[Symbol, untyped] message) -> void
|
377
383
|
def text_document_did_open(message)
|
378
384
|
@global_state.synchronize do
|
379
385
|
text_document = message.dig(:params, :textDocument)
|
@@ -412,7 +418,7 @@ module RubyLsp
|
|
412
418
|
end
|
413
419
|
end
|
414
420
|
|
415
|
-
|
421
|
+
#: (Hash[Symbol, untyped] message) -> void
|
416
422
|
def text_document_did_close(message)
|
417
423
|
@global_state.synchronize do
|
418
424
|
uri = message.dig(:params, :textDocument, :uri)
|
@@ -423,7 +429,7 @@ module RubyLsp
|
|
423
429
|
end
|
424
430
|
end
|
425
431
|
|
426
|
-
|
432
|
+
#: (Hash[Symbol, untyped] message) -> void
|
427
433
|
def text_document_did_change(message)
|
428
434
|
params = message[:params]
|
429
435
|
text_document = params[:textDocument]
|
@@ -433,7 +439,7 @@ module RubyLsp
|
|
433
439
|
end
|
434
440
|
end
|
435
441
|
|
436
|
-
|
442
|
+
#: (Hash[Symbol, untyped] message) -> void
|
437
443
|
def text_document_selection_range(message)
|
438
444
|
uri = message.dig(:params, :textDocument, :uri)
|
439
445
|
ranges = @store.cache_fetch(uri, "textDocument/selectionRange") do |document|
|
@@ -459,7 +465,7 @@ module RubyLsp
|
|
459
465
|
send_message(Result.new(id: message[:id], response: response))
|
460
466
|
end
|
461
467
|
|
462
|
-
|
468
|
+
#: (Hash[Symbol, untyped] message) -> void
|
463
469
|
def run_combined_requests(message)
|
464
470
|
uri = URI(message.dig(:params, :textDocument, :uri))
|
465
471
|
document = @store.get(uri)
|
@@ -484,7 +490,11 @@ module RubyLsp
|
|
484
490
|
document_symbol = Requests::DocumentSymbol.new(uri, dispatcher)
|
485
491
|
document_link = Requests::DocumentLink.new(uri, parse_result.comments, dispatcher)
|
486
492
|
code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
|
487
|
-
inlay_hint = Requests::InlayHints.new(
|
493
|
+
inlay_hint = Requests::InlayHints.new(
|
494
|
+
document,
|
495
|
+
@store.features_configuration.dig(:inlayHint), #: as !nil
|
496
|
+
dispatcher,
|
497
|
+
)
|
488
498
|
|
489
499
|
if document.is_a?(RubyDocument) && document.should_index?
|
490
500
|
# Re-index the file as it is modified. This mode of indexing updates entries only. Require path trees are only
|
@@ -518,7 +528,7 @@ module RubyLsp
|
|
518
528
|
alias_method :text_document_code_lens, :run_combined_requests
|
519
529
|
alias_method :text_document_folding_range, :run_combined_requests
|
520
530
|
|
521
|
-
|
531
|
+
#: (Hash[Symbol, untyped] message) -> void
|
522
532
|
def text_document_semantic_tokens_full(message)
|
523
533
|
document = @store.get(message.dig(:params, :textDocument, :uri))
|
524
534
|
|
@@ -539,7 +549,7 @@ module RubyLsp
|
|
539
549
|
send_message(Result.new(id: message[:id], response: semantic_highlighting.perform))
|
540
550
|
end
|
541
551
|
|
542
|
-
|
552
|
+
#: (Hash[Symbol, untyped] message) -> void
|
543
553
|
def text_document_semantic_tokens_delta(message)
|
544
554
|
document = @store.get(message.dig(:params, :textDocument, :uri))
|
545
555
|
|
@@ -564,7 +574,7 @@ module RubyLsp
|
|
564
574
|
send_message(Result.new(id: message[:id], response: request.perform))
|
565
575
|
end
|
566
576
|
|
567
|
-
|
577
|
+
#: (Hash[Symbol, untyped] message) -> void
|
568
578
|
def text_document_semantic_tokens_range(message)
|
569
579
|
params = message[:params]
|
570
580
|
range = params[:range]
|
@@ -593,7 +603,7 @@ module RubyLsp
|
|
593
603
|
send_message(Result.new(id: message[:id], response: request.perform))
|
594
604
|
end
|
595
605
|
|
596
|
-
|
606
|
+
#: (Hash[Symbol, untyped] message) -> void
|
597
607
|
def text_document_range_formatting(message)
|
598
608
|
# If formatter is set to `auto` but no supported formatting gem is found, don't attempt to format
|
599
609
|
if @global_state.formatter == "none"
|
@@ -621,7 +631,7 @@ module RubyLsp
|
|
621
631
|
send_message(Result.new(id: message[:id], response: response))
|
622
632
|
end
|
623
633
|
|
624
|
-
|
634
|
+
#: (Hash[Symbol, untyped] message) -> void
|
625
635
|
def text_document_formatting(message)
|
626
636
|
# If formatter is set to `auto` but no supported formatting gem is found, don't attempt to format
|
627
637
|
if @global_state.formatter == "none"
|
@@ -665,7 +675,7 @@ module RubyLsp
|
|
665
675
|
send_empty_response(message[:id])
|
666
676
|
end
|
667
677
|
|
668
|
-
|
678
|
+
#: (Hash[Symbol, untyped] message) -> void
|
669
679
|
def text_document_document_highlight(message)
|
670
680
|
params = message[:params]
|
671
681
|
dispatcher = Prism::Dispatcher.new
|
@@ -681,7 +691,7 @@ module RubyLsp
|
|
681
691
|
send_message(Result.new(id: message[:id], response: request.perform))
|
682
692
|
end
|
683
693
|
|
684
|
-
|
694
|
+
#: (Hash[Symbol, untyped] message) -> void
|
685
695
|
def text_document_on_type_formatting(message)
|
686
696
|
params = message[:params]
|
687
697
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -704,7 +714,7 @@ module RubyLsp
|
|
704
714
|
)
|
705
715
|
end
|
706
716
|
|
707
|
-
|
717
|
+
#: (Hash[Symbol, untyped] message) -> void
|
708
718
|
def text_document_hover(message)
|
709
719
|
params = message[:params]
|
710
720
|
dispatcher = Prism::Dispatcher.new
|
@@ -729,7 +739,7 @@ module RubyLsp
|
|
729
739
|
)
|
730
740
|
end
|
731
741
|
|
732
|
-
|
742
|
+
#: (Hash[Symbol, untyped] message) -> void
|
733
743
|
def text_document_rename(message)
|
734
744
|
params = message[:params]
|
735
745
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -749,7 +759,7 @@ module RubyLsp
|
|
749
759
|
send_message(Error.new(id: message[:id], code: Constant::ErrorCodes::REQUEST_FAILED, message: e.message))
|
750
760
|
end
|
751
761
|
|
752
|
-
|
762
|
+
#: (Hash[Symbol, untyped] message) -> void
|
753
763
|
def text_document_prepare_rename(message)
|
754
764
|
params = message[:params]
|
755
765
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -767,7 +777,7 @@ module RubyLsp
|
|
767
777
|
)
|
768
778
|
end
|
769
779
|
|
770
|
-
|
780
|
+
#: (Hash[Symbol, untyped] message) -> void
|
771
781
|
def text_document_references(message)
|
772
782
|
params = message[:params]
|
773
783
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -785,7 +795,7 @@ module RubyLsp
|
|
785
795
|
)
|
786
796
|
end
|
787
797
|
|
788
|
-
|
798
|
+
#: (Document[untyped] document) -> RubyDocument::SorbetLevel
|
789
799
|
def sorbet_level(document)
|
790
800
|
return RubyDocument::SorbetLevel::Ignore unless @global_state.has_type_checker
|
791
801
|
return RubyDocument::SorbetLevel::Ignore unless document.is_a?(RubyDocument)
|
@@ -793,7 +803,7 @@ module RubyLsp
|
|
793
803
|
document.sorbet_level
|
794
804
|
end
|
795
805
|
|
796
|
-
|
806
|
+
#: (Hash[Symbol, untyped] message) -> void
|
797
807
|
def text_document_inlay_hint(message)
|
798
808
|
params = message[:params]
|
799
809
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -811,7 +821,7 @@ module RubyLsp
|
|
811
821
|
return
|
812
822
|
end
|
813
823
|
|
814
|
-
hints_configurations =
|
824
|
+
hints_configurations = @store.features_configuration.dig(:inlayHint) #: as !nil
|
815
825
|
dispatcher = Prism::Dispatcher.new
|
816
826
|
|
817
827
|
unless document.is_a?(RubyDocument) || document.is_a?(ERBDocument)
|
@@ -827,7 +837,7 @@ module RubyLsp
|
|
827
837
|
send_message(Result.new(id: message[:id], response: result.select { |hint| range.cover?(hint.position[:line]) }))
|
828
838
|
end
|
829
839
|
|
830
|
-
|
840
|
+
#: (Hash[Symbol, untyped] message) -> void
|
831
841
|
def text_document_code_action(message)
|
832
842
|
params = message[:params]
|
833
843
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -849,7 +859,7 @@ module RubyLsp
|
|
849
859
|
)
|
850
860
|
end
|
851
861
|
|
852
|
-
|
862
|
+
#: (Hash[Symbol, untyped] message) -> void
|
853
863
|
def code_action_resolve(message)
|
854
864
|
params = message[:params]
|
855
865
|
uri = URI(params.dig(:data, :uri))
|
@@ -874,7 +884,7 @@ module RubyLsp
|
|
874
884
|
end
|
875
885
|
end
|
876
886
|
|
877
|
-
|
887
|
+
#: (Hash[Symbol, untyped] message) -> void
|
878
888
|
def text_document_diagnostic(message)
|
879
889
|
# Do not compute diagnostics for files outside of the workspace. For example, if someone is looking at a gem's
|
880
890
|
# source code, we don't want to show diagnostics for it
|
@@ -914,7 +924,7 @@ module RubyLsp
|
|
914
924
|
send_empty_response(message[:id])
|
915
925
|
end
|
916
926
|
|
917
|
-
|
927
|
+
#: (Hash[Symbol, untyped] message) -> void
|
918
928
|
def text_document_completion(message)
|
919
929
|
params = message[:params]
|
920
930
|
dispatcher = Prism::Dispatcher.new
|
@@ -939,7 +949,7 @@ module RubyLsp
|
|
939
949
|
)
|
940
950
|
end
|
941
951
|
|
942
|
-
|
952
|
+
#: (Hash[Symbol, untyped] message) -> void
|
943
953
|
def text_document_completion_item_resolve(message)
|
944
954
|
# When responding to a delegated completion request, it means we're handling a completion item that isn't related
|
945
955
|
# to Ruby (probably related to an ERB host language like HTML). We need to return the original completion item
|
@@ -958,7 +968,7 @@ module RubyLsp
|
|
958
968
|
))
|
959
969
|
end
|
960
970
|
|
961
|
-
|
971
|
+
#: (Hash[Symbol, untyped] message) -> void
|
962
972
|
def text_document_signature_help(message)
|
963
973
|
params = message[:params]
|
964
974
|
dispatcher = Prism::Dispatcher.new
|
@@ -984,7 +994,7 @@ module RubyLsp
|
|
984
994
|
)
|
985
995
|
end
|
986
996
|
|
987
|
-
|
997
|
+
#: (Hash[Symbol, untyped] message) -> void
|
988
998
|
def text_document_definition(message)
|
989
999
|
params = message[:params]
|
990
1000
|
dispatcher = Prism::Dispatcher.new
|
@@ -1009,8 +1019,23 @@ module RubyLsp
|
|
1009
1019
|
)
|
1010
1020
|
end
|
1011
1021
|
|
1012
|
-
|
1022
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1013
1023
|
def workspace_did_change_watched_files(message)
|
1024
|
+
# If indexing is not complete yet, delay processing did change watched file notifications. We need initial
|
1025
|
+
# indexing to be in place so that we can handle file changes appropriately without risking duplicates. We also
|
1026
|
+
# have to sleep before re-inserting the notification in the queue otherwise the worker can get stuck in its own
|
1027
|
+
# loop of pushing and popping the same notification
|
1028
|
+
unless @global_state.index.initial_indexing_completed
|
1029
|
+
Thread.new do
|
1030
|
+
sleep(2)
|
1031
|
+
# We have to ensure that the queue is not closed yet, since nothing stops the user from saving a file and then
|
1032
|
+
# immediately telling the LSP to shutdown
|
1033
|
+
@incoming_queue << message unless @incoming_queue.closed?
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
return
|
1037
|
+
end
|
1038
|
+
|
1014
1039
|
changes = message.dig(:params, :changes)
|
1015
1040
|
# We allow add-ons to register for watching files and we have no restrictions for what they register for. If the
|
1016
1041
|
# same pattern is registered more than once, the LSP will receive duplicate change notifications. Receiving them
|
@@ -1037,7 +1062,8 @@ module RubyLsp
|
|
1037
1062
|
end
|
1038
1063
|
|
1039
1064
|
Addon.file_watcher_addons.each do |addon|
|
1040
|
-
|
1065
|
+
addon #: as untyped
|
1066
|
+
.workspace_did_change_watched_files(changes)
|
1041
1067
|
rescue => e
|
1042
1068
|
send_log_message(
|
1043
1069
|
"Error in #{addon.name} add-on while processing watched file notifications: #{e.full_message}",
|
@@ -1046,32 +1072,34 @@ module RubyLsp
|
|
1046
1072
|
end
|
1047
1073
|
end
|
1048
1074
|
|
1049
|
-
|
1075
|
+
#: (RubyIndexer::Index index, String file_path, Integer change_type) -> void
|
1050
1076
|
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
|
-
|
1077
|
+
@global_state.synchronize do
|
1078
|
+
load_path_entry = $LOAD_PATH.find { |load_path| file_path.start_with?(load_path) }
|
1079
|
+
uri = URI::Generic.from_path(load_path_entry: load_path_entry, path: file_path)
|
1080
|
+
|
1081
|
+
case change_type
|
1082
|
+
when Constant::FileChangeType::CREATED
|
1083
|
+
content = File.read(file_path)
|
1084
|
+
# If we receive a late created notification for a file that has already been claimed by the client, we want to
|
1085
|
+
# handle change for that URI so that the require path tree is updated
|
1086
|
+
@store.key?(uri) ? index.handle_change(uri, content) : index.index_single(uri, content)
|
1087
|
+
when Constant::FileChangeType::CHANGED
|
1088
|
+
content = File.read(file_path)
|
1089
|
+
# We only handle changes on file watched notifications if the client is not the one managing this URI.
|
1090
|
+
# Otherwise, these changes are handled when running the combined requests
|
1091
|
+
index.handle_change(uri, content) unless @store.key?(uri)
|
1092
|
+
when Constant::FileChangeType::DELETED
|
1093
|
+
index.delete(uri)
|
1094
|
+
end
|
1095
|
+
rescue Errno::ENOENT
|
1096
|
+
# If a file is created and then delete immediately afterwards, we will process the created notification before
|
1097
|
+
# we receive the deleted one, but the file no longer exists. This may happen when running a test suite that
|
1098
|
+
# creates and deletes files automatically.
|
1099
|
+
end
|
1072
1100
|
end
|
1073
1101
|
|
1074
|
-
|
1102
|
+
#: (URI::Generic uri) -> void
|
1075
1103
|
def handle_rubocop_config_change(uri)
|
1076
1104
|
return unless defined?(Requests::Support::RuboCopFormatter)
|
1077
1105
|
|
@@ -1091,7 +1119,7 @@ module RubyLsp
|
|
1091
1119
|
end
|
1092
1120
|
end
|
1093
1121
|
|
1094
|
-
|
1122
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1095
1123
|
def workspace_symbol(message)
|
1096
1124
|
send_message(
|
1097
1125
|
Result.new(
|
@@ -1104,7 +1132,7 @@ module RubyLsp
|
|
1104
1132
|
)
|
1105
1133
|
end
|
1106
1134
|
|
1107
|
-
|
1135
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1108
1136
|
def text_document_show_syntax_tree(message)
|
1109
1137
|
params = message[:params]
|
1110
1138
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -1123,7 +1151,26 @@ module RubyLsp
|
|
1123
1151
|
send_message(Result.new(id: message[:id], response: response))
|
1124
1152
|
end
|
1125
1153
|
|
1126
|
-
|
1154
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1155
|
+
def experimental_go_to_relevant_file(message)
|
1156
|
+
path = message.dig(:params, :textDocument, :uri).to_standardized_path
|
1157
|
+
unless path.nil? || path.start_with?(@global_state.workspace_path)
|
1158
|
+
send_empty_response(message[:id])
|
1159
|
+
return
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
unless path
|
1163
|
+
send_empty_response(message[:id])
|
1164
|
+
return
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
response = {
|
1168
|
+
locations: Requests::GoToRelevantFile.new(path, @global_state.workspace_path).perform,
|
1169
|
+
}
|
1170
|
+
send_message(Result.new(id: message[:id], response: response))
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1127
1174
|
def text_document_prepare_type_hierarchy(message)
|
1128
1175
|
params = message[:params]
|
1129
1176
|
document = @store.get(params.dig(:textDocument, :uri))
|
@@ -1142,7 +1189,7 @@ module RubyLsp
|
|
1142
1189
|
send_message(Result.new(id: message[:id], response: response))
|
1143
1190
|
end
|
1144
1191
|
|
1145
|
-
|
1192
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1146
1193
|
def type_hierarchy_supertypes(message)
|
1147
1194
|
response = Requests::TypeHierarchySupertypes.new(
|
1148
1195
|
@global_state.index,
|
@@ -1151,14 +1198,14 @@ module RubyLsp
|
|
1151
1198
|
send_message(Result.new(id: message[:id], response: response))
|
1152
1199
|
end
|
1153
1200
|
|
1154
|
-
|
1201
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1155
1202
|
def type_hierarchy_subtypes(message)
|
1156
1203
|
# TODO: implement subtypes
|
1157
1204
|
# The current index representation doesn't allow us to find the children of an entry.
|
1158
1205
|
send_message(Result.new(id: message[:id], response: nil))
|
1159
1206
|
end
|
1160
1207
|
|
1161
|
-
|
1208
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1162
1209
|
def workspace_dependencies(message)
|
1163
1210
|
unless @global_state.top_level_bundle
|
1164
1211
|
send_message(Result.new(id: message[:id], response: []))
|
@@ -1186,12 +1233,13 @@ module RubyLsp
|
|
1186
1233
|
send_message(Result.new(id: message[:id], response: response))
|
1187
1234
|
end
|
1188
1235
|
|
1189
|
-
|
1236
|
+
# @override
|
1237
|
+
#: -> void
|
1190
1238
|
def shutdown
|
1191
1239
|
Addon.unload_addons
|
1192
1240
|
end
|
1193
1241
|
|
1194
|
-
|
1242
|
+
#: -> void
|
1195
1243
|
def perform_initial_indexing
|
1196
1244
|
# The begin progress invocation happens during `initialize`, so that the notification is sent before we are
|
1197
1245
|
# stuck indexing files
|
@@ -1223,7 +1271,7 @@ module RubyLsp
|
|
1223
1271
|
end
|
1224
1272
|
end
|
1225
1273
|
|
1226
|
-
|
1274
|
+
#: (String id, String title, ?percentage: Integer) -> void
|
1227
1275
|
def begin_progress(id, title, percentage: 0)
|
1228
1276
|
return unless @global_state.client_capabilities.supports_progress
|
1229
1277
|
|
@@ -1236,14 +1284,14 @@ module RubyLsp
|
|
1236
1284
|
send_message(Notification.progress_begin(id, title, percentage: percentage, message: "#{percentage}% completed"))
|
1237
1285
|
end
|
1238
1286
|
|
1239
|
-
|
1287
|
+
#: (String id, Integer percentage) -> void
|
1240
1288
|
def progress(id, percentage)
|
1241
1289
|
return unless @global_state.client_capabilities.supports_progress
|
1242
1290
|
|
1243
1291
|
send_message(Notification.progress_report(id, percentage: percentage, message: "#{percentage}% completed"))
|
1244
1292
|
end
|
1245
1293
|
|
1246
|
-
|
1294
|
+
#: (String id) -> void
|
1247
1295
|
def end_progress(id)
|
1248
1296
|
return unless @global_state.client_capabilities.supports_progress
|
1249
1297
|
|
@@ -1253,7 +1301,7 @@ module RubyLsp
|
|
1253
1301
|
# notification
|
1254
1302
|
end
|
1255
1303
|
|
1256
|
-
|
1304
|
+
#: -> void
|
1257
1305
|
def check_formatter_is_available
|
1258
1306
|
return if @setup_error
|
1259
1307
|
# Warn of an unavailable `formatter` setting, e.g. `rubocop_internal` on a project which doesn't have RuboCop.
|
@@ -1271,7 +1319,7 @@ module RubyLsp
|
|
1271
1319
|
end
|
1272
1320
|
end
|
1273
1321
|
|
1274
|
-
|
1322
|
+
#: (Hash[Symbol, untyped]? indexing_options) -> void
|
1275
1323
|
def process_indexing_configuration(indexing_options)
|
1276
1324
|
# Need to use the workspace URI, otherwise, this will fail for people working on a project that is a symlink.
|
1277
1325
|
index_path = File.join(@global_state.workspace_path, ".index.yml")
|
@@ -1312,7 +1360,7 @@ module RubyLsp
|
|
1312
1360
|
configuration.apply_config(indexing_options.transform_keys { |key| key.to_s.gsub(/([A-Z])/, "_\\1").downcase })
|
1313
1361
|
end
|
1314
1362
|
|
1315
|
-
|
1363
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1316
1364
|
def window_show_message_request(message)
|
1317
1365
|
result = message[:result]
|
1318
1366
|
return unless result
|
@@ -1327,7 +1375,7 @@ module RubyLsp
|
|
1327
1375
|
# NOTE: all servers methods are void because they can produce several messages for the client. The only reason this
|
1328
1376
|
# method returns the created thread is to that we can join it in tests and avoid flakiness. The implementation is
|
1329
1377
|
# not supposed to rely on the return of this method
|
1330
|
-
|
1378
|
+
#: (Hash[Symbol, untyped] message) -> Thread?
|
1331
1379
|
def compose_bundle(message)
|
1332
1380
|
already_composed_path = File.join(@global_state.workspace_path, ".ruby-lsp", "bundle_is_composed")
|
1333
1381
|
id = message[:id]
|
@@ -1352,7 +1400,9 @@ module RubyLsp
|
|
1352
1400
|
Open3.capture3(
|
1353
1401
|
Gem.ruby,
|
1354
1402
|
"-I",
|
1355
|
-
File.dirname(
|
1403
|
+
File.dirname(
|
1404
|
+
__dir__, #: as !nil
|
1405
|
+
),
|
1356
1406
|
File.expand_path("../../exe/ruby-lsp-launcher", __dir__),
|
1357
1407
|
@global_state.workspace_uri.to_s,
|
1358
1408
|
chdir: @global_state.workspace_path,
|
@@ -1374,7 +1424,7 @@ module RubyLsp
|
|
1374
1424
|
end
|
1375
1425
|
|
1376
1426
|
# Returns internal state information for debugging purposes
|
1377
|
-
|
1427
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1378
1428
|
def diagnose_state(message)
|
1379
1429
|
documents = {}
|
1380
1430
|
@store.each { |uri, document| documents[uri] = document.source }
|
@@ -1394,7 +1444,7 @@ module RubyLsp
|
|
1394
1444
|
|
1395
1445
|
# Discovers all available test groups and examples in a given file taking into consideration the merged response of
|
1396
1446
|
# all add-ons
|
1397
|
-
|
1447
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1398
1448
|
def discover_tests(message)
|
1399
1449
|
document = @store.get(message.dig(:params, :textDocument, :uri))
|
1400
1450
|
|
@@ -1414,5 +1464,23 @@ module RubyLsp
|
|
1414
1464
|
|
1415
1465
|
send_message(Result.new(id: message[:id], response: items.map(&:to_hash)))
|
1416
1466
|
end
|
1467
|
+
|
1468
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1469
|
+
def resolve_test_commands(message)
|
1470
|
+
items = message.dig(:params, :items)
|
1471
|
+
commands = Listeners::TestStyle.resolve_test_commands(items)
|
1472
|
+
|
1473
|
+
Addon.addons.each do |addon|
|
1474
|
+
commands.concat(addon.resolve_test_commands(items))
|
1475
|
+
end
|
1476
|
+
|
1477
|
+
send_message(Result.new(
|
1478
|
+
id: message[:id],
|
1479
|
+
response: {
|
1480
|
+
commands: commands,
|
1481
|
+
reporterPaths: [Listeners::TestStyle::MINITEST_REPORTER_PATH, Listeners::TestStyle::TEST_UNIT_REPORTER_PATH],
|
1482
|
+
},
|
1483
|
+
))
|
1484
|
+
end
|
1417
1485
|
end
|
1418
1486
|
end
|