ruby-lsp 0.23.15 → 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/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +16 -19
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +0 -3
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +9 -19
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +33 -69
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +1 -10
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
- data/lib/ruby_indexer/test/index_test.rb +7 -0
- data/lib/ruby_indexer/test/method_test.rb +7 -7
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +4 -3
- data/lib/ruby_indexer/test/test_case.rb +7 -1
- data/lib/ruby_lsp/document.rb +7 -10
- data/lib/ruby_lsp/erb_document.rb +2 -2
- data/lib/ruby_lsp/listeners/completion.rb +8 -8
- data/lib/ruby_lsp/listeners/definition.rb +7 -7
- data/lib/ruby_lsp/listeners/document_link.rb +7 -10
- data/lib/ruby_lsp/listeners/hover.rb +10 -9
- data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
- data/lib/ruby_lsp/listeners/spec_style.rb +11 -11
- data/lib/ruby_lsp/listeners/test_style.rb +15 -10
- data/lib/ruby_lsp/rbs_document.rb +2 -2
- data/lib/ruby_lsp/requests/code_action_resolve.rb +54 -51
- data/lib/ruby_lsp/requests/code_lens.rb +15 -3
- data/lib/ruby_lsp/requests/completion.rb +2 -2
- data/lib/ruby_lsp/requests/definition.rb +3 -4
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
- 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 +0 -2
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/inlay_hints.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +1 -16
- data/lib/ruby_lsp/requests/rename.rb +1 -4
- data/lib/ruby_lsp/requests/request.rb +2 -1
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -1
- data/lib/ruby_lsp/requests/signature_help.rb +1 -1
- data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +0 -5
- data/lib/ruby_lsp/requests/support/source_uri.rb +4 -2
- data/lib/ruby_lsp/requests/support/test_item.rb +6 -0
- data/lib/ruby_lsp/response_builders/document_symbol.rb +1 -1
- data/lib/ruby_lsp/response_builders/test_collection.rb +37 -0
- data/lib/ruby_lsp/ruby_document.rb +4 -34
- data/lib/ruby_lsp/server.rb +38 -22
- data/lib/ruby_lsp/setup_bundler.rb +2 -1
- data/lib/ruby_lsp/store.rb +6 -6
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +43 -4
- data/lib/ruby_lsp/utils.rb +55 -2
- metadata +1 -1
data/lib/ruby_lsp/server.rb
CHANGED
@@ -242,7 +242,9 @@ module RubyLsp
|
|
242
242
|
|
243
243
|
bundle_env_path = File.join(".ruby-lsp", "bundle_env")
|
244
244
|
bundle_env = if File.exist?(bundle_env_path)
|
245
|
-
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
|
246
248
|
FileUtils.rm(bundle_env_path)
|
247
249
|
env
|
248
250
|
end
|
@@ -385,11 +387,11 @@ module RubyLsp
|
|
385
387
|
text_document = message.dig(:params, :textDocument)
|
386
388
|
language_id = case text_document[:languageId]
|
387
389
|
when "erb", "eruby"
|
388
|
-
|
390
|
+
:erb
|
389
391
|
when "rbs"
|
390
|
-
|
392
|
+
:rbs
|
391
393
|
else
|
392
|
-
|
394
|
+
:ruby
|
393
395
|
end
|
394
396
|
|
395
397
|
document = @store.set(
|
@@ -489,13 +491,16 @@ module RubyLsp
|
|
489
491
|
folding_range = Requests::FoldingRanges.new(parse_result.comments, dispatcher)
|
490
492
|
document_symbol = Requests::DocumentSymbol.new(uri, dispatcher)
|
491
493
|
document_link = Requests::DocumentLink.new(uri, parse_result.comments, dispatcher)
|
492
|
-
code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
|
493
494
|
inlay_hint = Requests::InlayHints.new(
|
494
495
|
document,
|
495
496
|
@store.features_configuration.dig(:inlayHint), #: as !nil
|
496
497
|
dispatcher,
|
497
498
|
)
|
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?
|
503
|
+
|
499
504
|
if document.is_a?(RubyDocument) && document.should_index?
|
500
505
|
# Re-index the file as it is modified. This mode of indexing updates entries only. Require path trees are only
|
501
506
|
# updated on save
|
@@ -505,10 +510,12 @@ module RubyLsp
|
|
505
510
|
@global_state.index.handle_change(uri) do |index|
|
506
511
|
index.delete(uri, skip_require_paths_tree: true)
|
507
512
|
RubyIndexer::DeclarationListener.new(index, dispatcher, parse_result, uri, collect_comments: true)
|
513
|
+
code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
|
508
514
|
dispatcher.dispatch(parse_result.value)
|
509
515
|
end
|
510
516
|
end
|
511
517
|
else
|
518
|
+
code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
|
512
519
|
dispatcher.dispatch(parse_result.value)
|
513
520
|
end
|
514
521
|
|
@@ -517,7 +524,11 @@ module RubyLsp
|
|
517
524
|
document.cache_set("textDocument/foldingRange", folding_range.perform)
|
518
525
|
document.cache_set("textDocument/documentSymbol", document_symbol.perform)
|
519
526
|
document.cache_set("textDocument/documentLink", document_link.perform)
|
520
|
-
document.cache_set(
|
527
|
+
document.cache_set(
|
528
|
+
"textDocument/codeLens",
|
529
|
+
code_lens #: as !nil
|
530
|
+
.perform,
|
531
|
+
)
|
521
532
|
document.cache_set("textDocument/inlayHint", inlay_hint.perform)
|
522
533
|
|
523
534
|
send_message(Result.new(id: message[:id], response: document.cache_get(message[:method])))
|
@@ -672,6 +683,10 @@ module RubyLsp
|
|
672
683
|
"Formatting error: #{error.message}",
|
673
684
|
type: Constant::MessageType::ERROR,
|
674
685
|
))
|
686
|
+
send_message(Notification.window_log_message(
|
687
|
+
"Formatting failed with\r\n: #{error.full_message}",
|
688
|
+
type: Constant::MessageType::ERROR,
|
689
|
+
))
|
675
690
|
send_empty_response(message[:id])
|
676
691
|
end
|
677
692
|
|
@@ -795,12 +810,16 @@ module RubyLsp
|
|
795
810
|
)
|
796
811
|
end
|
797
812
|
|
798
|
-
#: (Document[untyped] document) ->
|
813
|
+
#: (Document[untyped] document) -> SorbetLevel
|
799
814
|
def sorbet_level(document)
|
800
|
-
return
|
801
|
-
return
|
815
|
+
return SorbetLevel.ignore unless document.is_a?(RubyDocument)
|
816
|
+
return SorbetLevel.ignore unless @global_state.has_type_checker
|
817
|
+
|
818
|
+
sigil = document.parse_result.magic_comments.find do |comment|
|
819
|
+
comment.key == "typed"
|
820
|
+
end&.value
|
802
821
|
|
803
|
-
|
822
|
+
SorbetLevel.new(sigil)
|
804
823
|
end
|
805
824
|
|
806
825
|
#: (Hash[Symbol, untyped] message) -> void
|
@@ -871,17 +890,9 @@ module RubyLsp
|
|
871
890
|
end
|
872
891
|
|
873
892
|
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
|
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)
|
885
896
|
end
|
886
897
|
|
887
898
|
#: (Hash[Symbol, untyped] message) -> void
|
@@ -921,6 +932,10 @@ module RubyLsp
|
|
921
932
|
"Error running diagnostics: #{error.message}",
|
922
933
|
type: Constant::MessageType::ERROR,
|
923
934
|
))
|
935
|
+
send_message(Notification.window_log_message(
|
936
|
+
"Diagnostics failed with\r\n: #{error.full_message}",
|
937
|
+
type: Constant::MessageType::ERROR,
|
938
|
+
))
|
924
939
|
send_empty_response(message[:id])
|
925
940
|
end
|
926
941
|
|
@@ -1062,7 +1077,8 @@ module RubyLsp
|
|
1062
1077
|
end
|
1063
1078
|
|
1064
1079
|
Addon.file_watcher_addons.each do |addon|
|
1065
|
-
|
1080
|
+
addon #: as untyped
|
1081
|
+
.workspace_did_change_watched_files(changes)
|
1066
1082
|
rescue => e
|
1067
1083
|
send_log_message(
|
1068
1084
|
"Error in #{addon.name} add-on while processing watched file notifications: #{e.full_message}",
|
@@ -260,7 +260,8 @@ module RubyLsp
|
|
260
260
|
# The ENV can only be merged after checking if an update is required because we depend on the original value of
|
261
261
|
# ENV["BUNDLE_GEMFILE"], which gets overridden after the merge
|
262
262
|
should_update = should_bundle_update?
|
263
|
-
|
263
|
+
ENV #: as untyped
|
264
|
+
.merge!(env)
|
264
265
|
|
265
266
|
unless should_update && !force_install
|
266
267
|
Bundler::CLI::Install.new({ "no-cache" => true }).run
|
data/lib/ruby_lsp/store.rb
CHANGED
@@ -38,11 +38,11 @@ module RubyLsp
|
|
38
38
|
ext = File.extname(path)
|
39
39
|
language_id = case ext
|
40
40
|
when ".erb", ".rhtml"
|
41
|
-
|
41
|
+
:erb
|
42
42
|
when ".rbs"
|
43
|
-
|
43
|
+
:rbs
|
44
44
|
else
|
45
|
-
|
45
|
+
:ruby
|
46
46
|
end
|
47
47
|
|
48
48
|
set(uri: uri, source: File.binread(path), version: 0, language_id: language_id)
|
@@ -51,12 +51,12 @@ module RubyLsp
|
|
51
51
|
raise NonExistingDocumentError, uri.to_s
|
52
52
|
end
|
53
53
|
|
54
|
-
#: (uri: URI::Generic, source: String, version: Integer, language_id:
|
54
|
+
#: (uri: URI::Generic, source: String, version: Integer, language_id: Symbol) -> Document[untyped]
|
55
55
|
def set(uri:, source:, version:, language_id:)
|
56
56
|
@state[uri.to_s] = case language_id
|
57
|
-
when
|
57
|
+
when :erb
|
58
58
|
ERBDocument.new(source: source, version: version, uri: uri, global_state: @global_state)
|
59
|
-
when
|
59
|
+
when :rbs
|
60
60
|
RBSDocument.new(source: source, version: version, uri: uri, global_state: @global_state)
|
61
61
|
else
|
62
62
|
RubyDocument.new(source: source, version: version, uri: uri, global_state: @global_state)
|
@@ -4,25 +4,57 @@
|
|
4
4
|
require "json"
|
5
5
|
require "socket"
|
6
6
|
require "singleton"
|
7
|
+
require "tmpdir"
|
7
8
|
|
8
9
|
module RubyLsp
|
9
10
|
class LspReporter
|
10
11
|
include Singleton
|
11
12
|
|
13
|
+
#: bool
|
14
|
+
attr_reader :invoked_shutdown
|
15
|
+
|
12
16
|
#: -> void
|
13
17
|
def initialize
|
18
|
+
dir_path = File.join(Dir.tmpdir, "ruby-lsp")
|
19
|
+
FileUtils.mkdir_p(dir_path)
|
20
|
+
|
21
|
+
port_path = File.join(dir_path, "test_reporter_port")
|
14
22
|
port = ENV["RUBY_LSP_REPORTER_PORT"]
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
23
|
+
|
24
|
+
@io = begin
|
25
|
+
# The environment variable is only used for tests. The extension always writes to the temporary file
|
26
|
+
if port
|
27
|
+
TCPSocket.new("localhost", port)
|
28
|
+
elsif File.exist?(port_path)
|
29
|
+
TCPSocket.new("localhost", File.read(port_path))
|
30
|
+
else
|
31
|
+
# For tests that don't spawn the TCP server
|
32
|
+
require "stringio"
|
33
|
+
StringIO.new
|
34
|
+
end
|
35
|
+
rescue
|
19
36
|
require "stringio"
|
20
37
|
StringIO.new
|
21
38
|
end #: IO | StringIO
|
39
|
+
|
40
|
+
@invoked_shutdown = false #: bool
|
22
41
|
end
|
23
42
|
|
24
43
|
#: -> void
|
25
44
|
def shutdown
|
45
|
+
# When running in coverage mode, we don't want to inform the extension that we finished immediately after running
|
46
|
+
# tests. We only do it after we finish processing coverage results, by invoking `internal_shutdown`
|
47
|
+
return if ENV["RUBY_LSP_TEST_RUNNER"] == "coverage"
|
48
|
+
|
49
|
+
internal_shutdown
|
50
|
+
end
|
51
|
+
|
52
|
+
# This method is intended to be used by the RubyLsp::LspReporter class itself only. If you're writing a custom test
|
53
|
+
# reporter, use `shutdown` instead
|
54
|
+
#: -> void
|
55
|
+
def internal_shutdown
|
56
|
+
@invoked_shutdown = true
|
57
|
+
|
26
58
|
send_message("finish")
|
27
59
|
@io.close
|
28
60
|
end
|
@@ -148,5 +180,12 @@ if ENV["RUBY_LSP_TEST_RUNNER"] == "coverage"
|
|
148
180
|
at_exit do
|
149
181
|
coverage_results = RubyLsp::LspReporter.instance.gather_coverage_results
|
150
182
|
File.write(File.join(".ruby-lsp", "coverage_result.json"), coverage_results.to_json)
|
183
|
+
RubyLsp::LspReporter.instance.internal_shutdown
|
184
|
+
end
|
185
|
+
elsif ENV["RUBY_LSP_TEST_RUNNER"] && ENV["RUBY_LSP_ENV"] != "test"
|
186
|
+
at_exit do
|
187
|
+
# If the test process crashed immediately without finishing the tests, we still need to tell the extension that the
|
188
|
+
# execution ended so that it can clean up
|
189
|
+
RubyLsp::LspReporter.instance.internal_shutdown unless RubyLsp::LspReporter.instance.invoked_shutdown
|
151
190
|
end
|
152
191
|
end
|
data/lib/ruby_lsp/utils.rb
CHANGED
@@ -137,7 +137,12 @@ module RubyLsp
|
|
137
137
|
#: -> Hash[Symbol, untyped]
|
138
138
|
def to_hash
|
139
139
|
hash = { method: @method }
|
140
|
-
|
140
|
+
|
141
|
+
if @params
|
142
|
+
hash[:params] = @params #: as untyped
|
143
|
+
.to_hash
|
144
|
+
end
|
145
|
+
|
141
146
|
hash
|
142
147
|
end
|
143
148
|
end
|
@@ -181,7 +186,12 @@ module RubyLsp
|
|
181
186
|
#: -> Hash[Symbol, untyped]
|
182
187
|
def to_hash
|
183
188
|
hash = { id: @id, method: @method }
|
184
|
-
|
189
|
+
|
190
|
+
if @params
|
191
|
+
hash[:params] = @params #: as untyped
|
192
|
+
.to_hash
|
193
|
+
end
|
194
|
+
|
185
195
|
hash
|
186
196
|
end
|
187
197
|
end
|
@@ -249,4 +259,47 @@ module RubyLsp
|
|
249
259
|
@configuration[:enableAll] || @configuration[feature]
|
250
260
|
end
|
251
261
|
end
|
262
|
+
|
263
|
+
class SorbetLevel
|
264
|
+
class << self
|
265
|
+
#: -> SorbetLevel
|
266
|
+
def ignore
|
267
|
+
new("ignore")
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
#: (String?) -> void
|
272
|
+
def initialize(sigil)
|
273
|
+
@level = case sigil
|
274
|
+
when "ignore"
|
275
|
+
:ignore
|
276
|
+
when "false"
|
277
|
+
:false
|
278
|
+
when "true"
|
279
|
+
:true
|
280
|
+
when "strict", "strong"
|
281
|
+
:strict
|
282
|
+
else
|
283
|
+
:none
|
284
|
+
end #: Symbol
|
285
|
+
end
|
286
|
+
|
287
|
+
#: -> bool
|
288
|
+
def ignore? = @level == :ignore
|
289
|
+
|
290
|
+
#: -> bool
|
291
|
+
def false? = @level == :false
|
292
|
+
|
293
|
+
#: -> bool
|
294
|
+
def true? = @level == :true
|
295
|
+
|
296
|
+
#: -> bool
|
297
|
+
def strict? = @level == :strict
|
298
|
+
|
299
|
+
#: -> bool
|
300
|
+
def none? = @level == :none
|
301
|
+
|
302
|
+
#: -> bool
|
303
|
+
def true_or_higher? = @level == :true || @level == :strict
|
304
|
+
end
|
252
305
|
end
|