ruby-lsp 0.25.0 → 0.26.1
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-test-exec +3 -15
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +1 -0
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +11 -0
- data/lib/ruby_indexer/test/configuration_test.rb +0 -1
- data/lib/ruby_indexer/test/index_test.rb +15 -0
- data/lib/ruby_lsp/addon.rb +19 -4
- data/lib/ruby_lsp/base_server.rb +22 -16
- data/lib/ruby_lsp/document.rb +4 -6
- data/lib/ruby_lsp/listeners/completion.rb +5 -2
- data/lib/ruby_lsp/listeners/test_style.rb +7 -5
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +6 -2
- data/lib/ruby_lsp/server.rb +47 -63
- data/lib/ruby_lsp/setup_bundler.rb +8 -0
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +1 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c80f549675508ffbb28d649de04506adabec01eac9aa4c6eee057ec848adf858
|
4
|
+
data.tar.gz: 71ea1a4d628444b98bc1173748f5aecf0d71bdc8d3dc80f33b2779c9c78d9de0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7261bf15c095154ff36152492aa252cbd84b84f6e83eb458623c7bb9790a57957885a855c2ee10683b7035267177e323c013988befc02e96f3fdf0274d2312ca
|
7
|
+
data.tar.gz: 74bcea4844e876230713400776bf7def1db44492bcf913526195b5d01919efd24ac69b517594ce2499e332184bf7ef4881e17e7694574bf4d35afabeda25b8c4
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.26.1
|
data/exe/ruby-lsp-test-exec
CHANGED
@@ -1,18 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
7
|
-
*ENV["RUBYOPT"],
|
8
|
-
"-rbundler/setup",
|
9
|
-
"-r#{File.expand_path("../lib/ruby_lsp/test_reporters/minitest_reporter", __dir__)}",
|
10
|
-
"-r#{File.expand_path("../lib/ruby_lsp/test_reporters/test_unit_reporter", __dir__)}",
|
11
|
-
].join(" ")
|
12
|
-
|
13
|
-
# Replace this process with whatever command was passed. We only want to set RUBYOPT.
|
14
|
-
# The way you use this executable is by prefixing your test command with `ruby-lsp-test-exec`, like so:
|
15
|
-
# ruby-lsp-test-exec bundle exec ruby -Itest test/example_test.rb
|
16
|
-
# ruby-lsp-test-exec bundle exec ruby -Ispec spec/example_spec.rb
|
17
|
-
# ruby-lsp-test-exec bundle exec rspec spec/example_spec.rb
|
18
|
-
exec({ "RUBYOPT" => rubyopt }, *ARGV)
|
4
|
+
# This executable will be removed thanks to the changes in https://github.com/Shopify/ruby-lsp/pull/3661.
|
5
|
+
# Remove this a few months after extension updates have rolled out
|
6
|
+
exec(*ARGV)
|
@@ -291,6 +291,17 @@ module RubyIndexer
|
|
291
291
|
|
292
292
|
# Top level constants
|
293
293
|
entries.concat(@entries_tree.search(name))
|
294
|
+
|
295
|
+
# Filter only constants since methods may have names that look like constants
|
296
|
+
entries.select! do |definitions|
|
297
|
+
definitions.select! do |entry|
|
298
|
+
entry.is_a?(Entry::Constant) || entry.is_a?(Entry::ConstantAlias) ||
|
299
|
+
entry.is_a?(Entry::Namespace) || entry.is_a?(Entry::UnresolvedConstantAlias)
|
300
|
+
end
|
301
|
+
|
302
|
+
definitions.any?
|
303
|
+
end
|
304
|
+
|
294
305
|
entries.uniq!
|
295
306
|
entries #: as Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]]
|
296
307
|
end
|
@@ -59,7 +59,6 @@ module RubyIndexer
|
|
59
59
|
|
60
60
|
assert_includes(paths, "#{RbConfig::CONFIG["rubylibdir"]}/pathname.rb")
|
61
61
|
assert_includes(paths, "#{RbConfig::CONFIG["rubylibdir"]}/ipaddr.rb")
|
62
|
-
assert_includes(paths, "#{RbConfig::CONFIG["rubylibdir"]}/erb.rb")
|
63
62
|
end
|
64
63
|
|
65
64
|
def test_indexable_uris_includes_project_files
|
@@ -1983,6 +1983,21 @@ module RubyIndexer
|
|
1983
1983
|
assert_equal(["XQRK"], result.map { |entries| entries.first&.name })
|
1984
1984
|
end
|
1985
1985
|
|
1986
|
+
def test_constant_completion_does_not_confuse_uppercase_methods
|
1987
|
+
index(<<~RUBY)
|
1988
|
+
class Foo
|
1989
|
+
def Qux
|
1990
|
+
end
|
1991
|
+
end
|
1992
|
+
RUBY
|
1993
|
+
|
1994
|
+
candidates = @index.constant_completion_candidates("Q", [])
|
1995
|
+
refute_includes(candidates.flat_map { |entries| entries.map(&:name) }, "Qux")
|
1996
|
+
|
1997
|
+
candidates = @index.constant_completion_candidates("Qux", [])
|
1998
|
+
assert_equal(0, candidates.length)
|
1999
|
+
end
|
2000
|
+
|
1986
2001
|
def test_constant_completion_candidates_for_empty_name
|
1987
2002
|
index(<<~RUBY)
|
1988
2003
|
module Foo
|
data/lib/ruby_lsp/addon.rb
CHANGED
@@ -57,11 +57,26 @@ module RubyLsp
|
|
57
57
|
|
58
58
|
if include_project_addons
|
59
59
|
project_addons = Dir.glob("#{global_state.workspace_path}/**/ruby_lsp/**/addon.rb")
|
60
|
-
|
61
|
-
# Ignore add-ons from dependencies if the bundle is stored inside the project. We already found those with
|
62
|
-
# `Gem.find_files`
|
63
60
|
bundle_path = Bundler.bundle_path.to_s
|
64
|
-
|
61
|
+
gems_dir = Bundler.bundle_path.join("gems")
|
62
|
+
|
63
|
+
# Create an array of rejection glob patterns to ignore add-ons already discovered through Gem.find_files if
|
64
|
+
# they are also copied inside the workspace for whatever reason. We received reports of projects having gems
|
65
|
+
# installed in vendor/bundle despite BUNDLE_PATH pointing elsewhere. Without this mechanism, we will
|
66
|
+
# double-require the same add-on, potentially for different versions of the same gem, which leads to incorrect
|
67
|
+
# behavior
|
68
|
+
reject_glob_patterns = addon_files.map do |path|
|
69
|
+
relative_gem_path = Pathname.new(path).relative_path_from(gems_dir)
|
70
|
+
first_part, *parts = relative_gem_path.to_s.split(File::SEPARATOR)
|
71
|
+
first_part&.gsub!(/-([0-9.]+)$/, "*")
|
72
|
+
"**/#{first_part}/#{parts.join("/")}"
|
73
|
+
end
|
74
|
+
|
75
|
+
project_addons.reject! do |path|
|
76
|
+
path.start_with?(bundle_path) ||
|
77
|
+
reject_glob_patterns.any? { |pattern| File.fnmatch?(pattern, path, File::Constants::FNM_PATHNAME) }
|
78
|
+
end
|
79
|
+
|
65
80
|
addon_files.concat(project_addons)
|
66
81
|
end
|
67
82
|
|
data/lib/ruby_lsp/base_server.rb
CHANGED
@@ -83,8 +83,7 @@ module RubyLsp
|
|
83
83
|
# The following requests need to be executed in the main thread directly to avoid concurrency issues. Everything
|
84
84
|
# else is pushed into the incoming queue
|
85
85
|
case method
|
86
|
-
when "initialize", "initialized", "
|
87
|
-
"rubyLsp/diagnoseState"
|
86
|
+
when "initialize", "initialized", "rubyLsp/diagnoseState"
|
88
87
|
process_message(message)
|
89
88
|
when "shutdown"
|
90
89
|
@global_state.synchronize do
|
@@ -94,26 +93,13 @@ module RubyLsp
|
|
94
93
|
@writer.write(Result.new(id: message[:id], response: nil).to_hash)
|
95
94
|
end
|
96
95
|
when "exit"
|
97
|
-
|
96
|
+
exit(@incoming_queue.closed? ? 0 : 1)
|
98
97
|
else
|
99
98
|
@incoming_queue << message
|
100
99
|
end
|
101
100
|
end
|
102
101
|
end
|
103
102
|
|
104
|
-
#: -> void
|
105
|
-
def run_shutdown
|
106
|
-
@incoming_queue.clear
|
107
|
-
@outgoing_queue.clear
|
108
|
-
@incoming_queue.close
|
109
|
-
@outgoing_queue.close
|
110
|
-
@cancelled_requests.clear
|
111
|
-
|
112
|
-
@worker.terminate
|
113
|
-
@outgoing_dispatcher.terminate
|
114
|
-
@store.clear
|
115
|
-
end
|
116
|
-
|
117
103
|
# This method is only intended to be used in tests! Pops the latest response that would be sent to the client
|
118
104
|
#: -> untyped
|
119
105
|
def pop_response
|
@@ -132,6 +118,26 @@ module RubyLsp
|
|
132
118
|
raise AbstractMethodInvokedError
|
133
119
|
end
|
134
120
|
|
121
|
+
#: -> bool?
|
122
|
+
def test_mode?
|
123
|
+
@test_mode
|
124
|
+
end
|
125
|
+
|
126
|
+
#: -> void
|
127
|
+
def run_shutdown
|
128
|
+
@incoming_queue.clear
|
129
|
+
@outgoing_queue.clear
|
130
|
+
@incoming_queue.close
|
131
|
+
@outgoing_queue.close
|
132
|
+
@cancelled_requests.clear
|
133
|
+
|
134
|
+
@worker.terminate
|
135
|
+
@outgoing_dispatcher.terminate
|
136
|
+
@store.clear
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
135
141
|
# @abstract
|
136
142
|
#: -> void
|
137
143
|
def shutdown
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -139,12 +139,10 @@ module RubyLsp
|
|
139
139
|
|
140
140
|
#: (Hash[Symbol, untyped] start_pos, ?Hash[Symbol, untyped]? end_pos) -> [Integer, Integer?]
|
141
141
|
def find_index_by_position(start_pos, end_pos = nil)
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
[start_index, end_index]
|
147
|
-
end
|
142
|
+
scanner = create_scanner
|
143
|
+
start_index = scanner.find_char_position(start_pos)
|
144
|
+
end_index = scanner.find_char_position(end_pos) if end_pos
|
145
|
+
[start_index, end_index]
|
148
146
|
end
|
149
147
|
|
150
148
|
private
|
@@ -445,11 +445,14 @@ module RubyLsp
|
|
445
445
|
return unless arguments_node
|
446
446
|
|
447
447
|
path_node_to_complete = arguments_node.arguments.first
|
448
|
-
|
449
448
|
return unless path_node_to_complete.is_a?(Prism::StringNode)
|
450
449
|
|
451
|
-
|
450
|
+
# If the file is unsaved (e.g.: untitled:Untitled-1), we can't provide relative completion as we don't know
|
451
|
+
# where the user intends to save it
|
452
|
+
full_path = @uri.to_standardized_path
|
453
|
+
return unless full_path
|
452
454
|
|
455
|
+
origin_dir = Pathname.new(full_path).dirname
|
453
456
|
content = path_node_to_complete.content
|
454
457
|
# if the path is not a directory, glob all possible next characters
|
455
458
|
# for example ../somethi| (where | is the cursor position)
|
@@ -75,8 +75,9 @@ module RubyLsp
|
|
75
75
|
|
76
76
|
unless full_files.empty?
|
77
77
|
specs, tests = full_files.partition { |path| spec?(path) }
|
78
|
-
|
79
|
-
commands << "#{
|
78
|
+
|
79
|
+
commands << "#{COMMAND} -Itest -e \"ARGV.each { |f| require f }\" #{tests.join(" ")}" if tests.any?
|
80
|
+
commands << "#{COMMAND} -Ispec -e \"ARGV.each { |f| require f }\" #{specs.join(" ")}" if specs.any?
|
80
81
|
end
|
81
82
|
|
82
83
|
commands
|
@@ -113,7 +114,7 @@ module RubyLsp
|
|
113
114
|
end
|
114
115
|
|
115
116
|
load_path = spec?(file_path) ? "-Ispec" : "-Itest"
|
116
|
-
"#{
|
117
|
+
"#{COMMAND} #{load_path} #{file_path} --name \"/#{regex}/\""
|
117
118
|
end
|
118
119
|
|
119
120
|
#: (String, Hash[String, Hash[Symbol, untyped]]) -> Array[String]
|
@@ -124,7 +125,7 @@ module RubyLsp
|
|
124
125
|
Shellwords.escape(TestDiscovery::DYNAMIC_REFERENCE_MARKER),
|
125
126
|
".*",
|
126
127
|
)
|
127
|
-
command = +"#{
|
128
|
+
command = +"#{COMMAND} -Itest #{file_path} --testcase \"/^#{group_regex}\\$/\""
|
128
129
|
|
129
130
|
unless examples.empty?
|
130
131
|
command << if examples.length == 1
|
@@ -143,13 +144,14 @@ module RubyLsp
|
|
143
144
|
|
144
145
|
MINITEST_REPORTER_PATH = File.expand_path("../test_reporters/minitest_reporter.rb", __dir__) #: String
|
145
146
|
TEST_UNIT_REPORTER_PATH = File.expand_path("../test_reporters/test_unit_reporter.rb", __dir__) #: String
|
146
|
-
ACCESS_MODIFIERS = [:public, :private, :protected].freeze
|
147
147
|
BASE_COMMAND = begin
|
148
148
|
Bundler.with_original_env { Bundler.default_lockfile }
|
149
149
|
"bundle exec ruby"
|
150
150
|
rescue Bundler::GemfileNotFound
|
151
151
|
"ruby"
|
152
152
|
end #: String
|
153
|
+
COMMAND = "#{BASE_COMMAND} -r#{MINITEST_REPORTER_PATH} -r#{TEST_UNIT_REPORTER_PATH}" #: String
|
154
|
+
ACCESS_MODIFIERS = [:public, :private, :protected].freeze
|
153
155
|
|
154
156
|
#: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
|
155
157
|
def initialize(response_builder, global_state, dispatcher, uri)
|
@@ -81,7 +81,7 @@ module RubyLsp
|
|
81
81
|
@offenses = [] #: Array[::RuboCop::Cop::Offense]
|
82
82
|
@errors = [] #: Array[String]
|
83
83
|
@warnings = [] #: Array[String]
|
84
|
-
@prism_result = nil #: Prism::ParseLexResult?
|
84
|
+
# @prism_result = nil #: Prism::ParseLexResult?
|
85
85
|
|
86
86
|
args += DEFAULT_ARGS
|
87
87
|
rubocop_options = ::RuboCop::Options.new.parse(args).first
|
@@ -101,7 +101,11 @@ module RubyLsp
|
|
101
101
|
@warnings = []
|
102
102
|
@offenses = []
|
103
103
|
@options[:stdin] = contents
|
104
|
-
|
104
|
+
|
105
|
+
# Setting the Prism result before running the RuboCop runner makes it reuse the existing AST and avoids
|
106
|
+
# double-parsing. Unfortunately, this leads to a bunch of cops failing to execute properly under LSP mode.
|
107
|
+
# Uncomment this once reusing the Prism result is more stable
|
108
|
+
# @prism_result = prism_result
|
105
109
|
|
106
110
|
super([path])
|
107
111
|
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -126,8 +126,12 @@ module RubyLsp
|
|
126
126
|
if message[:id]
|
127
127
|
# If a document is deleted before we are able to process all of its enqueued requests, we will try to read it
|
128
128
|
# from disk and it raise this error. This is expected, so we don't include the `data` attribute to avoid
|
129
|
-
# reporting these to our telemetry
|
130
|
-
|
129
|
+
# reporting these to our telemetry.
|
130
|
+
#
|
131
|
+
# Similarly, if we receive a location for an invalid position in the
|
132
|
+
# document, we don't report it to telemetry
|
133
|
+
case e
|
134
|
+
when Store::NonExistingDocumentError, Document::InvalidLocationError
|
131
135
|
send_message(Error.new(
|
132
136
|
id: message[:id],
|
133
137
|
code: Constant::ErrorCodes::INVALID_PARAMS,
|
@@ -167,6 +171,7 @@ module RubyLsp
|
|
167
171
|
return if @setup_error
|
168
172
|
|
169
173
|
errors = Addon.load_addons(@global_state, @outgoing_queue, include_project_addons: include_project_addons)
|
174
|
+
return if test_mode?
|
170
175
|
|
171
176
|
if errors.any?
|
172
177
|
send_log_message(
|
@@ -179,21 +184,13 @@ module RubyLsp
|
|
179
184
|
|
180
185
|
if errored_addons.any?
|
181
186
|
send_message(
|
182
|
-
Notification.
|
183
|
-
|
184
|
-
|
185
|
-
type: Constant::MessageType::WARNING,
|
186
|
-
message: "Error loading add-ons:\n\n#{errored_addons.map(&:formatted_errors).join("\n\n")}",
|
187
|
-
),
|
187
|
+
Notification.window_show_message(
|
188
|
+
"Error loading add-ons:\n\n#{errored_addons.map(&:formatted_errors).join("\n\n")}",
|
189
|
+
type: Constant::MessageType::WARNING,
|
188
190
|
),
|
189
191
|
)
|
190
192
|
|
191
|
-
|
192
|
-
send_log_message(
|
193
|
-
errored_addons.map(&:errors_details).join("\n\n"),
|
194
|
-
type: Constant::MessageType::WARNING,
|
195
|
-
)
|
196
|
-
end
|
193
|
+
send_log_message(errored_addons.map(&:errors_details).join("\n\n"), type: Constant::MessageType::WARNING)
|
197
194
|
end
|
198
195
|
end
|
199
196
|
|
@@ -367,52 +364,48 @@ module RubyLsp
|
|
367
364
|
|
368
365
|
#: (Hash[Symbol, untyped] message) -> void
|
369
366
|
def text_document_did_open(message)
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
end
|
367
|
+
text_document = message.dig(:params, :textDocument)
|
368
|
+
language_id = case text_document[:languageId]
|
369
|
+
when "erb", "eruby"
|
370
|
+
:erb
|
371
|
+
when "rbs"
|
372
|
+
:rbs
|
373
|
+
else
|
374
|
+
:ruby
|
375
|
+
end
|
380
376
|
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
377
|
+
document = @store.set(
|
378
|
+
uri: text_document[:uri],
|
379
|
+
source: text_document[:text],
|
380
|
+
version: text_document[:version],
|
381
|
+
language_id: language_id,
|
382
|
+
)
|
387
383
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
384
|
+
if document.past_expensive_limit? && text_document[:uri].scheme == "file"
|
385
|
+
log_message = <<~MESSAGE
|
386
|
+
The file #{text_document[:uri].path} is too long. For performance reasons, semantic highlighting and
|
387
|
+
diagnostics will be disabled.
|
388
|
+
MESSAGE
|
393
389
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
),
|
390
|
+
send_message(
|
391
|
+
Notification.new(
|
392
|
+
method: "window/logMessage",
|
393
|
+
params: Interface::LogMessageParams.new(
|
394
|
+
type: Constant::MessageType::WARNING,
|
395
|
+
message: log_message,
|
401
396
|
),
|
402
|
-
)
|
403
|
-
|
397
|
+
),
|
398
|
+
)
|
404
399
|
end
|
405
400
|
end
|
406
401
|
|
407
402
|
#: (Hash[Symbol, untyped] message) -> void
|
408
403
|
def text_document_did_close(message)
|
409
|
-
|
410
|
-
|
411
|
-
@store.delete(uri)
|
404
|
+
uri = message.dig(:params, :textDocument, :uri)
|
405
|
+
@store.delete(uri)
|
412
406
|
|
413
|
-
|
414
|
-
|
415
|
-
end
|
407
|
+
# Clear diagnostics for the closed file, so that they no longer appear in the problems tab
|
408
|
+
send_message(Notification.publish_diagnostics(uri.to_s, []))
|
416
409
|
end
|
417
410
|
|
418
411
|
#: (Hash[Symbol, untyped] message) -> void
|
@@ -420,9 +413,7 @@ module RubyLsp
|
|
420
413
|
params = message[:params]
|
421
414
|
text_document = params[:textDocument]
|
422
415
|
|
423
|
-
@
|
424
|
-
@store.push_edits(uri: text_document[:uri], edits: params[:contentChanges], version: text_document[:version])
|
425
|
-
end
|
416
|
+
@store.push_edits(uri: text_document[:uri], edits: params[:contentChanges], version: text_document[:version])
|
426
417
|
end
|
427
418
|
|
428
419
|
#: (Hash[Symbol, untyped] message) -> void
|
@@ -1105,11 +1096,7 @@ module RubyLsp
|
|
1105
1096
|
@global_state.register_formatter("rubocop_internal", Requests::Support::RuboCopFormatter.new)
|
1106
1097
|
|
1107
1098
|
# Clear all document caches for pull diagnostics
|
1108
|
-
@
|
1109
|
-
@store.each do |_uri, document|
|
1110
|
-
document.clear_cache("textDocument/diagnostic")
|
1111
|
-
end
|
1112
|
-
end
|
1099
|
+
@store.each { |_uri, document| document.clear_cache("textDocument/diagnostic") }
|
1113
1100
|
|
1114
1101
|
# Request a pull diagnostic refresh from the editor
|
1115
1102
|
if @global_state.client_capabilities.supports_diagnostic_refresh
|
@@ -1224,7 +1211,7 @@ module RubyLsp
|
|
1224
1211
|
}
|
1225
1212
|
end
|
1226
1213
|
end
|
1227
|
-
rescue Bundler::GemNotFound
|
1214
|
+
rescue Bundler::GemNotFound, Bundler::GemfileNotFound
|
1228
1215
|
[]
|
1229
1216
|
end
|
1230
1217
|
|
@@ -1510,10 +1497,7 @@ module RubyLsp
|
|
1510
1497
|
|
1511
1498
|
send_message(Result.new(
|
1512
1499
|
id: message[:id],
|
1513
|
-
response: {
|
1514
|
-
commands: commands,
|
1515
|
-
reporterPaths: [Listeners::TestStyle::MINITEST_REPORTER_PATH, Listeners::TestStyle::TEST_UNIT_REPORTER_PATH],
|
1516
|
-
},
|
1500
|
+
response: { commands: commands },
|
1517
1501
|
))
|
1518
1502
|
end
|
1519
1503
|
|
@@ -234,6 +234,14 @@ module RubyLsp
|
|
234
234
|
# If no error occurred, then clear previous errors
|
235
235
|
@error_path.delete if @error_path.exist?
|
236
236
|
$stderr.puts("Ruby LSP> Composed bundle installation complete")
|
237
|
+
rescue Errno::EPIPE
|
238
|
+
# If the $stderr pipe was closed by the client, for example when closing the editor during running bundle
|
239
|
+
# install, we don't want to write the error to a file or else we will report to telemetry on the next launch and
|
240
|
+
# it does not represent an actual error.
|
241
|
+
#
|
242
|
+
# This situation may happen because while running bundle install, the server is not yet ready to receive
|
243
|
+
# shutdown requests and we may continue doing work until the process is killed.
|
244
|
+
@error_path.delete if @error_path.exist?
|
237
245
|
rescue => e
|
238
246
|
# Write the error object to a file so that we can read it from the parent process
|
239
247
|
@error_path.write(Marshal.dump(e))
|
@@ -24,9 +24,6 @@ module RubyLsp
|
|
24
24
|
# https://code.visualstudio.com/api/references/vscode-api#StatementCoverage
|
25
25
|
#: type statement_coverage = { executed: Integer, location: position, branches: Array[branch_coverage] }
|
26
26
|
|
27
|
-
#: bool
|
28
|
-
attr_reader :invoked_shutdown
|
29
|
-
|
30
27
|
#: -> void
|
31
28
|
def initialize
|
32
29
|
dir_path = File.join(Dir.tmpdir, "ruby-lsp")
|
@@ -195,7 +192,7 @@ module RubyLsp
|
|
195
192
|
|
196
193
|
#: -> void
|
197
194
|
def at_exit
|
198
|
-
internal_shutdown unless invoked_shutdown
|
195
|
+
internal_shutdown unless @invoked_shutdown
|
199
196
|
end
|
200
197
|
|
201
198
|
class << self
|