ruby-lsp 0.23.2 → 0.23.3
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-launcher +15 -9
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +31 -29
- data/lib/ruby_indexer/test/method_test.rb +15 -0
- data/lib/ruby_lsp/base_server.rb +1 -2
- data/lib/ruby_lsp/document.rb +19 -21
- data/lib/ruby_lsp/listeners/definition.rb +7 -2
- data/lib/ruby_lsp/requests/rename.rb +2 -2
- data/lib/ruby_lsp/requests/workspace_symbol.rb +2 -2
- data/lib/ruby_lsp/server.rb +41 -35
- data/lib/ruby_lsp/store.rb +8 -12
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95642b8034d20684e2596755f391591d6dfffc9021e23a6e2efd0b9a0e500eb0
|
4
|
+
data.tar.gz: 6db469fda24144ce71eb0c2d8434251b3bf01a800035d85bea5e8e6801cf5120
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69365797e36c6597b43b5067da2e10b6c634cdb9121081db0e7c16c657fe12e2aa72042ba7beb07480b1cbb4a24c9a37a7a71f5a49a1be42923adb7a85a80715
|
7
|
+
data.tar.gz: 22695e4a4fd4e72738b43c32e9a693ed9895033e82240317700cde5583537b0ad6e7d8ce530a110624c57278d5a08c4eeb207ae010a4db99b3885bc241c5caa4
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.23.
|
1
|
+
0.23.3
|
data/exe/ruby-lsp-launcher
CHANGED
@@ -45,6 +45,12 @@ rescue Errno::ECHILD
|
|
45
45
|
# In theory, the child process can finish before we even get to the wait call, but that is not an error
|
46
46
|
end
|
47
47
|
|
48
|
+
error_path = File.join(".ruby-lsp", "install_error")
|
49
|
+
|
50
|
+
install_error = if File.exist?(error_path)
|
51
|
+
Marshal.load(File.read(error_path))
|
52
|
+
end
|
53
|
+
|
48
54
|
begin
|
49
55
|
bundle_env_path = File.join(".ruby-lsp", "bundle_env")
|
50
56
|
# We can't require `bundler/setup` because that file prematurely exits the process if setup fails. However, we can't
|
@@ -67,21 +73,21 @@ begin
|
|
67
73
|
rescue StandardError => e
|
68
74
|
# If installing gems failed for any reason, we don't want to exit the process prematurely. We can still provide most
|
69
75
|
# features in a degraded mode. We simply save the error so that we can report to the user that certain gems might be
|
70
|
-
# missing, but we respect the LSP life cycle
|
71
|
-
|
72
|
-
|
76
|
+
# missing, but we respect the LSP life cycle.
|
77
|
+
#
|
78
|
+
# If an install error occurred and one of the gems is not installed, Bundler.setup is guaranteed to fail with
|
79
|
+
# `Bundler::GemNotFound`. We don't set `setup_error` here because that would essentially report the same problem twice
|
80
|
+
# to telemetry, which is not useful
|
81
|
+
unless install_error && e.is_a?(Bundler::GemNotFound)
|
82
|
+
setup_error = e
|
83
|
+
$stderr.puts("Failed to set up composed Bundle\n#{e.full_message}")
|
84
|
+
end
|
73
85
|
|
74
86
|
# If Bundler.setup fails, we need to restore the original $LOAD_PATH so that we can still require the Ruby LSP server
|
75
87
|
# in degraded mode
|
76
88
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
77
89
|
end
|
78
90
|
|
79
|
-
error_path = File.join(".ruby-lsp", "install_error")
|
80
|
-
|
81
|
-
install_error = if File.exist?(error_path)
|
82
|
-
Marshal.load(File.read(error_path))
|
83
|
-
end
|
84
|
-
|
85
91
|
# Now that the bundle is set up, we can begin actually launching the server. Note that `Bundler.setup` will have already
|
86
92
|
# configured the load path using the version of the Ruby LSP present in the composed bundle. Do not push any Ruby LSP
|
87
93
|
# paths into the load path manually or we may end up requiring the wrong version of the gem
|
@@ -287,7 +287,6 @@ module RubyIndexer
|
|
287
287
|
when :module_function
|
288
288
|
handle_module_function(node)
|
289
289
|
when :private_class_method
|
290
|
-
@visibility_stack.push(VisibilityScope.new(visibility: Entry::Visibility::PRIVATE))
|
291
290
|
handle_private_class_method(node)
|
292
291
|
end
|
293
292
|
|
@@ -975,39 +974,42 @@ module RubyIndexer
|
|
975
974
|
|
976
975
|
sig { params(node: Prism::CallNode).void }
|
977
976
|
def handle_private_class_method(node)
|
978
|
-
node.arguments&.arguments
|
979
|
-
|
980
|
-
when Prism::StringNode, Prism::SymbolNode
|
981
|
-
[argument]
|
982
|
-
when Prism::ArrayNode
|
983
|
-
argument.elements
|
984
|
-
else
|
985
|
-
[]
|
986
|
-
end
|
977
|
+
arguments = node.arguments&.arguments
|
978
|
+
return unless arguments
|
987
979
|
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
980
|
+
# If we're passing a method definition directly to `private_class_method`, push a new private scope. That will be
|
981
|
+
# applied when the indexer finds the method definition and then popped on `call_node_leave`
|
982
|
+
if arguments.first.is_a?(Prism::DefNode)
|
983
|
+
@visibility_stack.push(VisibilityScope.new(visibility: Entry::Visibility::PRIVATE))
|
984
|
+
return
|
985
|
+
end
|
992
986
|
|
993
|
-
|
994
|
-
|
995
|
-
when Prism::StringNode
|
996
|
-
string_or_symbol_node.content
|
997
|
-
when Prism::SymbolNode
|
998
|
-
string_or_symbol_node.value
|
999
|
-
end
|
1000
|
-
next unless method_name
|
987
|
+
owner_name = @owner_stack.last&.name
|
988
|
+
return unless owner_name
|
1001
989
|
|
1002
|
-
|
1003
|
-
|
990
|
+
# private_class_method accepts strings, symbols or arrays of strings and symbols as arguments. Here we build a
|
991
|
+
# single list of all of the method names that have to be made private
|
992
|
+
arrays, others = T.cast(
|
993
|
+
arguments.partition { |argument| argument.is_a?(Prism::ArrayNode) },
|
994
|
+
[T::Array[Prism::ArrayNode], T::Array[Prism::Node]],
|
995
|
+
)
|
996
|
+
arrays.each { |array| others.concat(array.elements) }
|
1004
997
|
|
1005
|
-
|
1006
|
-
|
998
|
+
names = others.filter_map do |argument|
|
999
|
+
case argument
|
1000
|
+
when Prism::StringNode
|
1001
|
+
argument.unescaped
|
1002
|
+
when Prism::SymbolNode
|
1003
|
+
argument.value
|
1004
|
+
end
|
1005
|
+
end
|
1007
1006
|
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1007
|
+
names.each do |name|
|
1008
|
+
entries = @index.resolve_method(name, @index.existing_or_new_singleton_class(owner_name).name)
|
1009
|
+
next unless entries
|
1010
|
+
|
1011
|
+
entries.each do |entry|
|
1012
|
+
entry.visibility = Entry::Visibility::PRIVATE
|
1011
1013
|
end
|
1012
1014
|
end
|
1013
1015
|
end
|
@@ -909,6 +909,21 @@ module RubyIndexer
|
|
909
909
|
assert_equal("Foo", T.must(entry.owner).name)
|
910
910
|
end
|
911
911
|
|
912
|
+
def test_making_several_class_methods_private
|
913
|
+
index(<<~RUBY)
|
914
|
+
class Foo
|
915
|
+
def self.bar; end
|
916
|
+
def self.baz; end
|
917
|
+
def self.qux; end
|
918
|
+
|
919
|
+
private_class_method :bar, :baz, :qux
|
920
|
+
|
921
|
+
def initialize
|
922
|
+
end
|
923
|
+
end
|
924
|
+
RUBY
|
925
|
+
end
|
926
|
+
|
912
927
|
private
|
913
928
|
|
914
929
|
sig { params(entry: Entry::Method, call_string: String).void }
|
data/lib/ruby_lsp/base_server.rb
CHANGED
@@ -90,8 +90,7 @@ module RubyLsp
|
|
90
90
|
# The following requests need to be executed in the main thread directly to avoid concurrency issues. Everything
|
91
91
|
# else is pushed into the incoming queue
|
92
92
|
case method
|
93
|
-
when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange"
|
94
|
-
"$/cancelRequest"
|
93
|
+
when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange"
|
95
94
|
process_message(message)
|
96
95
|
when "shutdown"
|
97
96
|
@global_state.synchronize do
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -97,33 +97,31 @@ module RubyLsp
|
|
97
97
|
|
98
98
|
sig { params(edits: T::Array[T::Hash[Symbol, T.untyped]], version: Integer).void }
|
99
99
|
def push_edits(edits, version:)
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
scanner = create_scanner
|
100
|
+
edits.each do |edit|
|
101
|
+
range = edit[:range]
|
102
|
+
scanner = create_scanner
|
104
103
|
|
105
|
-
|
106
|
-
|
104
|
+
start_position = scanner.find_char_position(range[:start])
|
105
|
+
end_position = scanner.find_char_position(range[:end])
|
107
106
|
|
108
|
-
|
109
|
-
|
107
|
+
@source[start_position...end_position] = edit[:text]
|
108
|
+
end
|
110
109
|
|
111
|
-
|
112
|
-
|
113
|
-
|
110
|
+
@version = version
|
111
|
+
@needs_parsing = true
|
112
|
+
@cache.clear
|
114
113
|
|
115
|
-
|
116
|
-
|
114
|
+
last_edit = edits.last
|
115
|
+
return unless last_edit
|
117
116
|
|
118
|
-
|
117
|
+
last_edit_range = last_edit[:range]
|
119
118
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
119
|
+
@last_edit = if last_edit_range[:start] == last_edit_range[:end]
|
120
|
+
Insert.new(last_edit_range)
|
121
|
+
elsif last_edit[:text].empty?
|
122
|
+
Delete.new(last_edit_range)
|
123
|
+
else
|
124
|
+
Replace.new(last_edit_range)
|
127
125
|
end
|
128
126
|
end
|
129
127
|
|
@@ -330,7 +330,8 @@ module RubyLsp
|
|
330
330
|
|
331
331
|
methods.each do |target_method|
|
332
332
|
uri = target_method.uri
|
333
|
-
|
333
|
+
full_path = uri.full_path
|
334
|
+
next if sorbet_level_true_or_higher?(@sorbet_level) && (!full_path || not_in_dependencies?(full_path))
|
334
335
|
|
335
336
|
@response_builder << Interface::LocationLink.new(
|
336
337
|
target_uri: uri.to_s,
|
@@ -403,7 +404,11 @@ module RubyLsp
|
|
403
404
|
# additional behavior on top of jumping to RBIs. The only sigil where Sorbet cannot handle constants is typed
|
404
405
|
# ignore
|
405
406
|
uri = entry.uri
|
406
|
-
|
407
|
+
full_path = uri.full_path
|
408
|
+
|
409
|
+
if @sorbet_level != RubyDocument::SorbetLevel::Ignore && (!full_path || not_in_dependencies?(full_path))
|
410
|
+
next
|
411
|
+
end
|
407
412
|
|
408
413
|
@response_builder << Interface::LocationLink.new(
|
409
414
|
target_uri: uri.to_s,
|
@@ -116,8 +116,8 @@ module RubyLsp
|
|
116
116
|
T.must(@global_state.index[fully_qualified_name]).each do |entry|
|
117
117
|
# Do not rename files that are not part of the workspace
|
118
118
|
uri = entry.uri
|
119
|
-
file_path =
|
120
|
-
next unless file_path
|
119
|
+
file_path = uri.full_path
|
120
|
+
next unless file_path&.start_with?(@global_state.workspace_path)
|
121
121
|
|
122
122
|
case entry
|
123
123
|
when RubyIndexer::Entry::Class, RubyIndexer::Entry::Module, RubyIndexer::Entry::Constant,
|
@@ -22,10 +22,10 @@ module RubyLsp
|
|
22
22
|
def perform
|
23
23
|
@index.fuzzy_search(@query).filter_map do |entry|
|
24
24
|
uri = entry.uri
|
25
|
-
file_path =
|
25
|
+
file_path = uri.full_path
|
26
26
|
|
27
27
|
# We only show symbols declared in the workspace
|
28
|
-
in_dependencies = !not_in_dependencies?(file_path)
|
28
|
+
in_dependencies = file_path && !not_in_dependencies?(file_path)
|
29
29
|
next if in_dependencies
|
30
30
|
|
31
31
|
# We should never show private symbols when searching the entire workspace
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -359,48 +359,52 @@ module RubyLsp
|
|
359
359
|
|
360
360
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
361
361
|
def text_document_did_open(message)
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
362
|
+
@global_state.synchronize do
|
363
|
+
text_document = message.dig(:params, :textDocument)
|
364
|
+
language_id = case text_document[:languageId]
|
365
|
+
when "erb", "eruby"
|
366
|
+
Document::LanguageId::ERB
|
367
|
+
when "rbs"
|
368
|
+
Document::LanguageId::RBS
|
369
|
+
else
|
370
|
+
Document::LanguageId::Ruby
|
371
|
+
end
|
371
372
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
373
|
+
document = @store.set(
|
374
|
+
uri: text_document[:uri],
|
375
|
+
source: text_document[:text],
|
376
|
+
version: text_document[:version],
|
377
|
+
language_id: language_id,
|
378
|
+
)
|
378
379
|
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
380
|
+
if document.past_expensive_limit? && text_document[:uri].scheme == "file"
|
381
|
+
log_message = <<~MESSAGE
|
382
|
+
The file #{text_document[:uri].path} is too long. For performance reasons, semantic highlighting and
|
383
|
+
diagnostics will be disabled.
|
384
|
+
MESSAGE
|
384
385
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
386
|
+
send_message(
|
387
|
+
Notification.new(
|
388
|
+
method: "window/logMessage",
|
389
|
+
params: Interface::LogMessageParams.new(
|
390
|
+
type: Constant::MessageType::WARNING,
|
391
|
+
message: log_message,
|
392
|
+
),
|
391
393
|
),
|
392
|
-
)
|
393
|
-
|
394
|
+
)
|
395
|
+
end
|
394
396
|
end
|
395
397
|
end
|
396
398
|
|
397
399
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
398
400
|
def text_document_did_close(message)
|
399
|
-
|
400
|
-
|
401
|
+
@global_state.synchronize do
|
402
|
+
uri = message.dig(:params, :textDocument, :uri)
|
403
|
+
@store.delete(uri)
|
401
404
|
|
402
|
-
|
403
|
-
|
405
|
+
# Clear diagnostics for the closed file, so that they no longer appear in the problems tab
|
406
|
+
send_message(Notification.publish_diagnostics(uri.to_s, []))
|
407
|
+
end
|
404
408
|
end
|
405
409
|
|
406
410
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
@@ -408,7 +412,9 @@ module RubyLsp
|
|
408
412
|
params = message[:params]
|
409
413
|
text_document = params[:textDocument]
|
410
414
|
|
411
|
-
@
|
415
|
+
@global_state.synchronize do
|
416
|
+
@store.push_edits(uri: text_document[:uri], edits: params[:contentChanges], version: text_document[:version])
|
417
|
+
end
|
412
418
|
end
|
413
419
|
|
414
420
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
@@ -1254,10 +1260,10 @@ module RubyLsp
|
|
1254
1260
|
return
|
1255
1261
|
end
|
1256
1262
|
|
1257
|
-
return unless indexing_options
|
1258
|
-
|
1259
1263
|
configuration = @global_state.index.configuration
|
1260
1264
|
configuration.workspace_path = @global_state.workspace_path
|
1265
|
+
return unless indexing_options
|
1266
|
+
|
1261
1267
|
# The index expects snake case configurations, but VS Code standardizes on camel case settings
|
1262
1268
|
configuration.apply_config(indexing_options.transform_keys { |key| key.to_s.gsub(/([A-Z])/, "_\\1").downcase })
|
1263
1269
|
end
|
data/lib/ruby_lsp/store.rb
CHANGED
@@ -65,15 +65,13 @@ module RubyLsp
|
|
65
65
|
).returns(Document[T.untyped])
|
66
66
|
end
|
67
67
|
def set(uri:, source:, version:, language_id:)
|
68
|
-
@
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
RubyDocument.new(source: source, version: version, uri: uri, global_state: @global_state)
|
76
|
-
end
|
68
|
+
@state[uri.to_s] = case language_id
|
69
|
+
when Document::LanguageId::ERB
|
70
|
+
ERBDocument.new(source: source, version: version, uri: uri, global_state: @global_state)
|
71
|
+
when Document::LanguageId::RBS
|
72
|
+
RBSDocument.new(source: source, version: version, uri: uri, global_state: @global_state)
|
73
|
+
else
|
74
|
+
RubyDocument.new(source: source, version: version, uri: uri, global_state: @global_state)
|
77
75
|
end
|
78
76
|
end
|
79
77
|
|
@@ -94,9 +92,7 @@ module RubyLsp
|
|
94
92
|
|
95
93
|
sig { params(uri: URI::Generic).void }
|
96
94
|
def delete(uri)
|
97
|
-
@
|
98
|
-
@state.delete(uri.to_s)
|
99
|
-
end
|
95
|
+
@state.delete(uri.to_s)
|
100
96
|
end
|
101
97
|
|
102
98
|
sig { params(uri: URI::Generic).returns(T::Boolean) }
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.23.
|
4
|
+
version: 0.23.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-01-
|
10
|
+
date: 2025-01-09 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: language_server-protocol
|