Skip to content

Commit ac16838

Browse files
committed
Respond to LSP Shutdown command to prevent VS Code deadlocks
1 parent 1447294 commit ac16838

File tree

2 files changed

+28
-11
lines changed

2 files changed

+28
-11
lines changed

lib/syntax_tree/language_server.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ def run
3636
write(id: id, result: { capabilities: capabilities })
3737
in method: "initialized"
3838
# ignored
39-
in method: "shutdown"
39+
in method: "shutdown" # tolerate missing ID to be a good citizen
4040
store.clear
41+
write(id: request[:id], result: {})
4142
return
4243
in {
4344
method: "textDocument/didChange",

test/language_server_test.rb

+26-10
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ def to_hash
1111
end
1212
end
1313

14-
class Shutdown
14+
class Shutdown < Struct.new(:id)
1515
def to_hash
16-
{ method: "shutdown" }
16+
{ method: "shutdown", id: id }
1717
end
1818
end
1919

@@ -107,13 +107,14 @@ def test_formatting
107107
TextDocumentDidChange.new("file:///path/to/file.rb", "class Bar; end"),
108108
TextDocumentFormatting.new(2, "file:///path/to/file.rb"),
109109
TextDocumentDidClose.new("file:///path/to/file.rb"),
110-
Shutdown.new
110+
Shutdown.new(3)
111111
]
112112

113113
case run_server(messages)
114114
in [
115115
{ id: 1, result: { capabilities: Hash } },
116-
{ id: 2, result: [{ newText: new_text }] }
116+
{ id: 2, result: [{ newText: new_text }] },
117+
{ id: 3, result: {} }
117118
]
118119
assert_equal("class Bar\nend\n", new_text)
119120
end
@@ -129,13 +130,14 @@ def test_inlay_hints
129130
end
130131
RUBY
131132
TextDocumentInlayHints.new(2, "file:///path/to/file.rb"),
132-
Shutdown.new
133+
Shutdown.new(3)
133134
]
134135

135136
case run_server(messages)
136137
in [
137138
{ id: 1, result: { capabilities: Hash } },
138-
{ id: 2, result: { before:, after: } }
139+
{ id: 2, result: { before:, after: } },
140+
{ id: 3, result: {} }
139141
]
140142
assert_equal(1, before.length)
141143
assert_equal(2, after.length)
@@ -147,11 +149,15 @@ def test_visualizing
147149
Initialize.new(1),
148150
TextDocumentDidOpen.new("file:///path/to/file.rb", "1 + 2"),
149151
SyntaxTreeVisualizing.new(2, "file:///path/to/file.rb"),
150-
Shutdown.new
152+
Shutdown.new(3)
151153
]
152154

153155
case run_server(messages)
154-
in [{ id: 1, result: { capabilities: Hash } }, { id: 2, result: }]
156+
in [
157+
{ id: 1, result: { capabilities: Hash } },
158+
{ id: 2, result: },
159+
{ id: 3, result: {} }
160+
]
155161
assert_equal(
156162
"(program (statements ((binary (int \"1\") + (int \"2\")))))\n",
157163
result
@@ -167,13 +173,14 @@ def test_reading_file
167173
messages = [
168174
Initialize.new(1),
169175
TextDocumentFormatting.new(2, "file://#{file.path}"),
170-
Shutdown.new
176+
Shutdown.new(3)
171177
]
172178

173179
case run_server(messages)
174180
in [
175181
{ id: 1, result: { capabilities: Hash } },
176-
{ id: 2, result: [{ newText: new_text }] }
182+
{ id: 2, result: [{ newText: new_text }] },
183+
{ id: 3, result: {} }
177184
]
178185
assert_equal("class Foo\nend\n", new_text)
179186
end
@@ -186,6 +193,15 @@ def test_bogus_request
186193
end
187194
end
188195

196+
def test_clean_shutdown
197+
messages = [Initialize.new(1), Shutdown.new(2)]
198+
199+
case run_server(messages)
200+
in [{ id: 1, result: { capabilities: Hash } }, { id: 2, result: {} }]
201+
assert_equal(true, true)
202+
end
203+
end
204+
189205
private
190206

191207
def write(content)

0 commit comments

Comments
 (0)