ruby-lsp 0.23.11 → 0.25.0
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 +10 -4
- data/exe/ruby-lsp-check +0 -4
- data/exe/ruby-lsp-launcher +45 -22
- data/exe/ruby-lsp-test-exec +18 -0
- data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -2
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -6
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +82 -116
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +140 -183
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +10 -14
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +106 -236
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +155 -281
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +23 -27
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +25 -57
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +58 -68
- data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
- 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 +49 -8
- 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 +170 -135
- data/lib/ruby_indexer/test/instance_variables_test.rb +61 -37
- data/lib/ruby_indexer/test/method_test.rb +166 -123
- data/lib/ruby_indexer/test/prefix_tree_test.rb +21 -21
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +70 -75
- data/lib/ruby_indexer/test/reference_finder_test.rb +79 -14
- data/lib/ruby_indexer/test/test_case.rb +9 -3
- data/lib/ruby_indexer/test/uri_test.rb +15 -2
- data/lib/ruby_lsp/addon.rb +73 -86
- data/lib/ruby_lsp/base_server.rb +41 -42
- data/lib/ruby_lsp/client_capabilities.rb +16 -13
- data/lib/ruby_lsp/document.rb +201 -98
- data/lib/ruby_lsp/erb_document.rb +45 -47
- data/lib/ruby_lsp/global_state.rb +73 -57
- data/lib/ruby_lsp/internal.rb +8 -3
- data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
- data/lib/ruby_lsp/listeners/completion.rb +76 -74
- data/lib/ruby_lsp/listeners/definition.rb +44 -58
- data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
- data/lib/ruby_lsp/listeners/document_link.rb +50 -70
- 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 +107 -115
- data/lib/ruby_lsp/listeners/inlay_hints.rb +8 -13
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
- data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
- data/lib/ruby_lsp/listeners/spec_style.rb +214 -0
- data/lib/ruby_lsp/listeners/test_discovery.rb +92 -0
- data/lib/ruby_lsp/listeners/test_style.rb +203 -95
- data/lib/ruby_lsp/node_context.rb +12 -39
- data/lib/ruby_lsp/rbs_document.rb +10 -11
- data/lib/ruby_lsp/requests/code_action_resolve.rb +65 -61
- data/lib/ruby_lsp/requests/code_actions.rb +14 -26
- data/lib/ruby_lsp/requests/code_lens.rb +31 -21
- data/lib/ruby_lsp/requests/completion.rb +8 -21
- data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
- data/lib/ruby_lsp/requests/definition.rb +8 -20
- data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
- data/lib/ruby_lsp/requests/discover_tests.rb +20 -7
- data/lib/ruby_lsp/requests/document_highlight.rb +6 -16
- 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 +85 -0
- data/lib/ruby_lsp/requests/hover.rb +12 -25
- data/lib/ruby_lsp/requests/inlay_hints.rb +8 -19
- data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
- data/lib/ruby_lsp/requests/prepare_rename.rb +5 -10
- 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 +17 -57
- data/lib/ruby_lsp/requests/rename.rb +27 -51
- data/lib/ruby_lsp/requests/request.rb +13 -25
- data/lib/ruby_lsp/requests/selection_ranges.rb +7 -7
- 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 +9 -27
- data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
- data/lib/ruby_lsp/requests/support/common.rb +16 -58
- data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +13 -16
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +30 -36
- 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 +16 -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 +6 -9
- data/lib/ruby_lsp/response_builders/document_symbol.rb +15 -21
- data/lib/ruby_lsp/response_builders/hover.rb +12 -18
- data/lib/ruby_lsp/response_builders/response_builder.rb +6 -7
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +62 -91
- data/lib/ruby_lsp/response_builders/signature_help.rb +6 -8
- data/lib/ruby_lsp/response_builders/test_collection.rb +35 -13
- data/lib/ruby_lsp/ruby_document.rb +32 -98
- data/lib/ruby_lsp/scope.rb +7 -11
- data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
- data/lib/ruby_lsp/server.rb +266 -143
- data/lib/ruby_lsp/setup_bundler.rb +113 -82
- data/lib/ruby_lsp/static_docs.rb +12 -7
- data/lib/ruby_lsp/store.rb +21 -49
- data/lib/ruby_lsp/test_helper.rb +3 -16
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +236 -0
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +145 -0
- data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +92 -0
- data/lib/ruby_lsp/type_inferrer.rb +13 -14
- data/lib/ruby_lsp/utils.rb +138 -93
- data/static_docs/break.md +103 -0
- metadata +14 -20
- data/lib/ruby_lsp/load_sorbet.rb +0 -62
|
@@ -12,12 +12,12 @@ module RubyIndexer
|
|
|
12
12
|
|
|
13
13
|
def test_from_path_on_windows
|
|
14
14
|
uri = URI::Generic.from_path(path: "C:/some/windows/path/to/file.rb")
|
|
15
|
-
assert_equal("/C
|
|
15
|
+
assert_equal("/C%3A/some/windows/path/to/file.rb", uri.path)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def test_from_path_on_windows_with_lowercase_drive
|
|
19
19
|
uri = URI::Generic.from_path(path: "c:/some/windows/path/to/file.rb")
|
|
20
|
-
assert_equal("/c
|
|
20
|
+
assert_equal("/c%3A/some/windows/path/to/file.rb", uri.path)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def test_to_standardized_path_on_unix
|
|
@@ -68,5 +68,18 @@ module RubyIndexer
|
|
|
68
68
|
uri.add_require_path_from_load_entry("/some/unix/path")
|
|
69
69
|
assert_equal("to/file", uri.require_path)
|
|
70
70
|
end
|
|
71
|
+
|
|
72
|
+
def test_from_path_escapes_colon_characters
|
|
73
|
+
uri = URI::Generic.from_path(path: "c:/some/windows/path with/spaces/file.rb")
|
|
74
|
+
assert_equal("c:/some/windows/path with/spaces/file.rb", uri.to_standardized_path)
|
|
75
|
+
assert_equal("file:///c%3A/some/windows/path%20with/spaces/file.rb", uri.to_s)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_from_path_with_unicode_characters
|
|
79
|
+
path = "/path/with/unicode/文件.rb"
|
|
80
|
+
uri = URI::Generic.from_path(path: path)
|
|
81
|
+
assert_equal(path, uri.to_standardized_path)
|
|
82
|
+
assert_equal("file:///path/with/unicode/%E6%96%87%E4%BB%B6.rb", uri.to_s)
|
|
83
|
+
end
|
|
71
84
|
end
|
|
72
85
|
end
|
data/lib/ruby_lsp/addon.rb
CHANGED
|
@@ -19,48 +19,36 @@ module RubyLsp
|
|
|
19
19
|
# end
|
|
20
20
|
# end
|
|
21
21
|
# ```
|
|
22
|
+
# @abstract
|
|
22
23
|
class Addon
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
abstract!
|
|
27
|
-
|
|
28
|
-
@addons = T.let([], T::Array[Addon])
|
|
29
|
-
@addon_classes = T.let([], T::Array[T.class_of(Addon)])
|
|
24
|
+
@addons = [] #: Array[Addon]
|
|
25
|
+
@addon_classes = [] #: Array[singleton(Addon)]
|
|
30
26
|
# Add-on instances that have declared a handler to accept file watcher events
|
|
31
|
-
@file_watcher_addons =
|
|
27
|
+
@file_watcher_addons = [] #: Array[Addon]
|
|
32
28
|
|
|
33
29
|
AddonNotFoundError = Class.new(StandardError)
|
|
34
30
|
|
|
35
31
|
class IncompatibleApiError < StandardError; end
|
|
36
32
|
|
|
37
33
|
class << self
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
sig { returns(T::Array[Addon]) }
|
|
34
|
+
#: Array[Addon]
|
|
41
35
|
attr_accessor :addons
|
|
42
36
|
|
|
43
|
-
|
|
37
|
+
#: Array[Addon]
|
|
44
38
|
attr_accessor :file_watcher_addons
|
|
45
39
|
|
|
46
|
-
|
|
40
|
+
#: Array[singleton(Addon)]
|
|
47
41
|
attr_reader :addon_classes
|
|
48
42
|
|
|
49
43
|
# Automatically track and instantiate add-on classes
|
|
50
|
-
|
|
44
|
+
#: (singleton(Addon) child_class) -> void
|
|
51
45
|
def inherited(child_class)
|
|
52
46
|
addon_classes << child_class
|
|
53
47
|
super
|
|
54
48
|
end
|
|
55
49
|
|
|
56
50
|
# Discovers and loads all add-ons. Returns a list of errors when trying to require add-ons
|
|
57
|
-
|
|
58
|
-
params(
|
|
59
|
-
global_state: GlobalState,
|
|
60
|
-
outgoing_queue: Thread::Queue,
|
|
61
|
-
include_project_addons: T::Boolean,
|
|
62
|
-
).returns(T::Array[StandardError])
|
|
63
|
-
end
|
|
51
|
+
#: (GlobalState global_state, Thread::Queue outgoing_queue, ?include_project_addons: bool) -> Array[StandardError]
|
|
64
52
|
def load_addons(global_state, outgoing_queue, include_project_addons: true)
|
|
65
53
|
# Require all add-ons entry points, which should be placed under
|
|
66
54
|
# `some_gem/lib/ruby_lsp/your_gem_name/addon.rb` or in the workspace under
|
|
@@ -68,7 +56,13 @@ module RubyLsp
|
|
|
68
56
|
addon_files = Gem.find_files("ruby_lsp/**/addon.rb")
|
|
69
57
|
|
|
70
58
|
if include_project_addons
|
|
71
|
-
|
|
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
|
+
bundle_path = Bundler.bundle_path.to_s
|
|
64
|
+
project_addons.reject! { |path| path.start_with?(bundle_path) }
|
|
65
|
+
addon_files.concat(project_addons)
|
|
72
66
|
end
|
|
73
67
|
|
|
74
68
|
errors = addon_files.filter_map do |addon_path|
|
|
@@ -98,7 +92,7 @@ module RubyLsp
|
|
|
98
92
|
end
|
|
99
93
|
|
|
100
94
|
# Unloads all add-ons. Only intended to be invoked once when shutting down the Ruby LSP server
|
|
101
|
-
|
|
95
|
+
#: -> void
|
|
102
96
|
def unload_addons
|
|
103
97
|
@addons.each(&:deactivate)
|
|
104
98
|
@addons.clear
|
|
@@ -112,7 +106,7 @@ module RubyLsp
|
|
|
112
106
|
# Important: if the add-on is not found, AddonNotFoundError will be raised. If the add-on is found, but its
|
|
113
107
|
# current version does not satisfy the given version constraint, then IncompatibleApiError will be raised. It is
|
|
114
108
|
# the responsibility of the add-ons using this API to handle these errors appropriately.
|
|
115
|
-
|
|
109
|
+
#: (String addon_name, *String version_constraints) -> Addon
|
|
116
110
|
def get(addon_name, *version_constraints)
|
|
117
111
|
if version_constraints.empty?
|
|
118
112
|
raise IncompatibleApiError, "Must specify version constraints when accessing other add-ons"
|
|
@@ -144,7 +138,7 @@ module RubyLsp
|
|
|
144
138
|
# end
|
|
145
139
|
# end
|
|
146
140
|
# ```
|
|
147
|
-
|
|
141
|
+
#: (*String version_constraints) -> void
|
|
148
142
|
def depend_on_ruby_lsp!(*version_constraints)
|
|
149
143
|
version_object = Gem::Version.new(RubyLsp::VERSION)
|
|
150
144
|
|
|
@@ -155,23 +149,23 @@ module RubyLsp
|
|
|
155
149
|
end
|
|
156
150
|
end
|
|
157
151
|
|
|
158
|
-
|
|
152
|
+
#: -> void
|
|
159
153
|
def initialize
|
|
160
|
-
@errors =
|
|
154
|
+
@errors = [] #: Array[StandardError]
|
|
161
155
|
end
|
|
162
156
|
|
|
163
|
-
|
|
157
|
+
#: (StandardError error) -> self
|
|
164
158
|
def add_error(error)
|
|
165
159
|
@errors << error
|
|
166
160
|
self
|
|
167
161
|
end
|
|
168
162
|
|
|
169
|
-
|
|
163
|
+
#: -> bool
|
|
170
164
|
def error?
|
|
171
165
|
@errors.any?
|
|
172
166
|
end
|
|
173
167
|
|
|
174
|
-
|
|
168
|
+
#: -> String
|
|
175
169
|
def formatted_errors
|
|
176
170
|
<<~ERRORS
|
|
177
171
|
#{name}:
|
|
@@ -179,97 +173,90 @@ module RubyLsp
|
|
|
179
173
|
ERRORS
|
|
180
174
|
end
|
|
181
175
|
|
|
182
|
-
|
|
176
|
+
#: -> String
|
|
183
177
|
def errors_details
|
|
184
178
|
@errors.map(&:full_message).join("\n\n")
|
|
185
179
|
end
|
|
186
180
|
|
|
187
181
|
# Each add-on should implement `MyAddon#activate` and use to perform any sort of initialization, such as
|
|
188
182
|
# reading information into memory or even spawning a separate process
|
|
189
|
-
|
|
190
|
-
|
|
183
|
+
# @abstract
|
|
184
|
+
#: (GlobalState, Thread::Queue) -> void
|
|
185
|
+
def activate(global_state, outgoing_queue)
|
|
186
|
+
raise AbstractMethodInvokedError
|
|
187
|
+
end
|
|
191
188
|
|
|
192
|
-
# Each add-on
|
|
189
|
+
# Each add-on must implement `MyAddon#deactivate` and use to perform any clean up, like shutting down a
|
|
193
190
|
# child process
|
|
194
|
-
|
|
195
|
-
|
|
191
|
+
# @abstract
|
|
192
|
+
#: -> void
|
|
193
|
+
def deactivate
|
|
194
|
+
raise AbstractMethodInvokedError
|
|
195
|
+
end
|
|
196
196
|
|
|
197
197
|
# Add-ons should override the `name` method to return the add-on name
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
# @abstract
|
|
199
|
+
#: -> String
|
|
200
|
+
def name
|
|
201
|
+
raise AbstractMethodInvokedError
|
|
202
|
+
end
|
|
200
203
|
|
|
201
204
|
# Add-ons should override the `version` method to return a semantic version string representing the add-on's
|
|
202
205
|
# version. This is used for compatibility checks
|
|
203
|
-
|
|
204
|
-
|
|
206
|
+
# @abstract
|
|
207
|
+
#: -> String
|
|
208
|
+
def version
|
|
209
|
+
raise AbstractMethodInvokedError
|
|
210
|
+
end
|
|
205
211
|
|
|
206
212
|
# Handle a response from a window/showMessageRequest request. Add-ons must include the addon_name as part of the
|
|
207
213
|
# original request so that the response is delegated to the correct add-on and must override this method to handle
|
|
208
214
|
# the response
|
|
209
215
|
# https://microsoft.github.io/language-server-protocol/specification#window_showMessageRequest
|
|
210
|
-
|
|
216
|
+
# @overridable
|
|
217
|
+
#: (String title) -> void
|
|
211
218
|
def handle_window_show_message_response(title); end
|
|
212
219
|
|
|
213
220
|
# Creates a new CodeLens listener. This method is invoked on every CodeLens request
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
|
|
217
|
-
uri: URI::Generic,
|
|
218
|
-
dispatcher: Prism::Dispatcher,
|
|
219
|
-
).void
|
|
220
|
-
end
|
|
221
|
+
# @overridable
|
|
222
|
+
#: (ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens] response_builder, URI::Generic uri, Prism::Dispatcher dispatcher) -> void
|
|
221
223
|
def create_code_lens_listener(response_builder, uri, dispatcher); end
|
|
222
224
|
|
|
223
225
|
# Creates a new Hover listener. This method is invoked on every Hover request
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
response_builder: ResponseBuilders::Hover,
|
|
227
|
-
node_context: NodeContext,
|
|
228
|
-
dispatcher: Prism::Dispatcher,
|
|
229
|
-
).void
|
|
230
|
-
end
|
|
226
|
+
# @overridable
|
|
227
|
+
#: (ResponseBuilders::Hover response_builder, NodeContext node_context, Prism::Dispatcher dispatcher) -> void
|
|
231
228
|
def create_hover_listener(response_builder, node_context, dispatcher); end
|
|
232
229
|
|
|
233
230
|
# Creates a new DocumentSymbol listener. This method is invoked on every DocumentSymbol request
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
response_builder: ResponseBuilders::DocumentSymbol,
|
|
237
|
-
dispatcher: Prism::Dispatcher,
|
|
238
|
-
).void
|
|
239
|
-
end
|
|
231
|
+
# @overridable
|
|
232
|
+
#: (ResponseBuilders::DocumentSymbol response_builder, Prism::Dispatcher dispatcher) -> void
|
|
240
233
|
def create_document_symbol_listener(response_builder, dispatcher); end
|
|
241
234
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
response_builder: ResponseBuilders::SemanticHighlighting,
|
|
245
|
-
dispatcher: Prism::Dispatcher,
|
|
246
|
-
).void
|
|
247
|
-
end
|
|
235
|
+
# @overridable
|
|
236
|
+
#: (ResponseBuilders::SemanticHighlighting response_builder, Prism::Dispatcher dispatcher) -> void
|
|
248
237
|
def create_semantic_highlighting_listener(response_builder, dispatcher); end
|
|
249
238
|
|
|
250
239
|
# Creates a new Definition listener. This method is invoked on every Definition request
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
response_builder: ResponseBuilders::CollectionResponseBuilder[T.any(
|
|
254
|
-
Interface::Location,
|
|
255
|
-
Interface::LocationLink,
|
|
256
|
-
)],
|
|
257
|
-
uri: URI::Generic,
|
|
258
|
-
node_context: NodeContext,
|
|
259
|
-
dispatcher: Prism::Dispatcher,
|
|
260
|
-
).void
|
|
261
|
-
end
|
|
240
|
+
# @overridable
|
|
241
|
+
#: (ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)] response_builder, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher) -> void
|
|
262
242
|
def create_definition_listener(response_builder, uri, node_context, dispatcher); end
|
|
263
243
|
|
|
264
244
|
# Creates a new Completion listener. This method is invoked on every Completion request
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem],
|
|
268
|
-
node_context: NodeContext,
|
|
269
|
-
dispatcher: Prism::Dispatcher,
|
|
270
|
-
uri: URI::Generic,
|
|
271
|
-
).void
|
|
272
|
-
end
|
|
245
|
+
# @overridable
|
|
246
|
+
#: (ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem] response_builder, NodeContext node_context, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
|
|
273
247
|
def create_completion_listener(response_builder, node_context, dispatcher, uri); end
|
|
248
|
+
|
|
249
|
+
# Creates a new Discover Tests listener. This method is invoked on every DiscoverTests request
|
|
250
|
+
# @overridable
|
|
251
|
+
#: (ResponseBuilders::TestCollection response_builder, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
|
|
252
|
+
def create_discover_tests_listener(response_builder, dispatcher, uri); end
|
|
253
|
+
|
|
254
|
+
# Resolves the minimal set of commands required to execute the requested tests. Add-ons are responsible for only
|
|
255
|
+
# handling items related to the framework they add support for and have discovered themselves
|
|
256
|
+
# @overridable
|
|
257
|
+
#: (Array[Hash[Symbol, untyped]]) -> Array[String]
|
|
258
|
+
def resolve_test_commands(items)
|
|
259
|
+
[]
|
|
260
|
+
end
|
|
274
261
|
end
|
|
275
262
|
end
|
data/lib/ruby_lsp/base_server.rb
CHANGED
|
@@ -2,36 +2,29 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module RubyLsp
|
|
5
|
+
# @abstract
|
|
5
6
|
class BaseServer
|
|
6
|
-
|
|
7
|
-
extend T::Helpers
|
|
8
|
-
|
|
9
|
-
abstract!
|
|
10
|
-
|
|
11
|
-
sig { params(options: T.untyped).void }
|
|
7
|
+
#: (**untyped options) -> void
|
|
12
8
|
def initialize(**options)
|
|
13
|
-
@
|
|
14
|
-
@
|
|
15
|
-
@
|
|
16
|
-
@
|
|
17
|
-
@
|
|
18
|
-
@incoming_queue =
|
|
19
|
-
@outgoing_queue =
|
|
20
|
-
@cancelled_requests =
|
|
21
|
-
@worker =
|
|
22
|
-
@current_request_id =
|
|
23
|
-
@global_state =
|
|
24
|
-
@store =
|
|
25
|
-
@outgoing_dispatcher =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@global_state.synchronize { @writer.write(message.to_hash) }
|
|
30
|
-
end
|
|
9
|
+
@reader = MessageReader.new(options[:reader] || $stdin) #: MessageReader
|
|
10
|
+
@writer = MessageWriter.new(options[:writer] || $stdout) #: MessageWriter
|
|
11
|
+
@test_mode = options[:test_mode] #: bool?
|
|
12
|
+
@setup_error = options[:setup_error] #: StandardError?
|
|
13
|
+
@install_error = options[:install_error] #: StandardError?
|
|
14
|
+
@incoming_queue = Thread::Queue.new #: Thread::Queue
|
|
15
|
+
@outgoing_queue = Thread::Queue.new #: Thread::Queue
|
|
16
|
+
@cancelled_requests = [] #: Array[Integer]
|
|
17
|
+
@worker = new_worker #: Thread
|
|
18
|
+
@current_request_id = 1 #: Integer
|
|
19
|
+
@global_state = GlobalState.new #: GlobalState
|
|
20
|
+
@store = Store.new(@global_state) #: Store
|
|
21
|
+
@outgoing_dispatcher = Thread.new do
|
|
22
|
+
unless @test_mode
|
|
23
|
+
while (message = @outgoing_queue.pop)
|
|
24
|
+
@global_state.synchronize { @writer.write(message.to_hash) }
|
|
31
25
|
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
)
|
|
26
|
+
end
|
|
27
|
+
end #: Thread
|
|
35
28
|
|
|
36
29
|
Thread.main.priority = 1
|
|
37
30
|
|
|
@@ -41,9 +34,9 @@ module RubyLsp
|
|
|
41
34
|
process_message(initialize_request) if initialize_request
|
|
42
35
|
end
|
|
43
36
|
|
|
44
|
-
|
|
37
|
+
#: -> void
|
|
45
38
|
def start
|
|
46
|
-
@reader.
|
|
39
|
+
@reader.each_message do |message|
|
|
47
40
|
method = message[:method]
|
|
48
41
|
|
|
49
42
|
# We must parse the document under a mutex lock or else we might switch threads and accept text edits in the
|
|
@@ -108,7 +101,7 @@ module RubyLsp
|
|
|
108
101
|
end
|
|
109
102
|
end
|
|
110
103
|
|
|
111
|
-
|
|
104
|
+
#: -> void
|
|
112
105
|
def run_shutdown
|
|
113
106
|
@incoming_queue.clear
|
|
114
107
|
@outgoing_queue.clear
|
|
@@ -122,33 +115,39 @@ module RubyLsp
|
|
|
122
115
|
end
|
|
123
116
|
|
|
124
117
|
# This method is only intended to be used in tests! Pops the latest response that would be sent to the client
|
|
125
|
-
|
|
118
|
+
#: -> untyped
|
|
126
119
|
def pop_response
|
|
127
120
|
@outgoing_queue.pop
|
|
128
121
|
end
|
|
129
122
|
|
|
130
123
|
# This method is only intended to be used in tests! Pushes a message to the incoming queue directly
|
|
131
|
-
|
|
124
|
+
#: (Hash[Symbol, untyped] message) -> void
|
|
132
125
|
def push_message(message)
|
|
133
126
|
@incoming_queue << message
|
|
134
127
|
end
|
|
135
128
|
|
|
136
|
-
|
|
137
|
-
|
|
129
|
+
# @abstract
|
|
130
|
+
#: (Hash[Symbol, untyped] message) -> void
|
|
131
|
+
def process_message(message)
|
|
132
|
+
raise AbstractMethodInvokedError
|
|
133
|
+
end
|
|
138
134
|
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
# @abstract
|
|
136
|
+
#: -> void
|
|
137
|
+
def shutdown
|
|
138
|
+
raise AbstractMethodInvokedError
|
|
139
|
+
end
|
|
141
140
|
|
|
142
|
-
|
|
141
|
+
#: (Integer id, String message, ?type: Integer) -> void
|
|
143
142
|
def fail_request_and_notify(id, message, type: Constant::MessageType::INFO)
|
|
144
143
|
send_message(Error.new(id: id, code: Constant::ErrorCodes::REQUEST_FAILED, message: message))
|
|
145
144
|
send_message(Notification.window_show_message(message, type: type))
|
|
146
145
|
end
|
|
147
146
|
|
|
148
|
-
|
|
147
|
+
#: -> Thread
|
|
149
148
|
def new_worker
|
|
150
149
|
Thread.new do
|
|
151
|
-
while (message =
|
|
150
|
+
while (message = @incoming_queue.pop)
|
|
152
151
|
id = message[:id]
|
|
153
152
|
|
|
154
153
|
# Check if the request was cancelled before trying to process it
|
|
@@ -165,7 +164,7 @@ module RubyLsp
|
|
|
165
164
|
end
|
|
166
165
|
end
|
|
167
166
|
|
|
168
|
-
|
|
167
|
+
#: ((Result | Error | Notification | Request) message) -> void
|
|
169
168
|
def send_message(message)
|
|
170
169
|
# When we're shutting down the server, there's a small race condition between closing the thread queues and
|
|
171
170
|
# finishing remaining requests. We may close the queue in the middle of processing a request, which will then fail
|
|
@@ -176,12 +175,12 @@ module RubyLsp
|
|
|
176
175
|
@current_request_id += 1 if message.is_a?(Request)
|
|
177
176
|
end
|
|
178
177
|
|
|
179
|
-
|
|
178
|
+
#: (Integer id) -> void
|
|
180
179
|
def send_empty_response(id)
|
|
181
180
|
send_message(Result.new(id: id, response: nil))
|
|
182
181
|
end
|
|
183
182
|
|
|
184
|
-
|
|
183
|
+
#: (String message, ?type: Integer) -> void
|
|
185
184
|
def send_log_message(message, type: Constant::MessageType::LOG)
|
|
186
185
|
send_message(Notification.window_log_message(message, type: Constant::MessageType::LOG))
|
|
187
186
|
end
|
|
@@ -5,40 +5,42 @@ module RubyLsp
|
|
|
5
5
|
# This class stores all client capabilities that the Ruby LSP and its add-ons depend on to ensure that we're
|
|
6
6
|
# not enabling functionality unsupported by the editor connecting to the server
|
|
7
7
|
class ClientCapabilities
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
sig { returns(T::Boolean) }
|
|
8
|
+
#: bool
|
|
11
9
|
attr_reader :supports_watching_files,
|
|
12
10
|
:supports_request_delegation,
|
|
13
11
|
:window_show_message_supports_extra_properties,
|
|
14
12
|
:supports_progress,
|
|
15
|
-
:supports_diagnostic_refresh
|
|
13
|
+
:supports_diagnostic_refresh,
|
|
14
|
+
:supports_code_lens_refresh
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
#: -> void
|
|
18
17
|
def initialize
|
|
19
18
|
# The editor supports watching files. This requires two capabilities: dynamic registration and relative pattern
|
|
20
19
|
# support
|
|
21
|
-
@supports_watching_files =
|
|
20
|
+
@supports_watching_files = false #: bool
|
|
22
21
|
|
|
23
22
|
# The editor supports request delegation. This is an experimental capability since request delegation has not been
|
|
24
23
|
# standardized into the LSP spec yet
|
|
25
|
-
@supports_request_delegation =
|
|
24
|
+
@supports_request_delegation = false #: bool
|
|
26
25
|
|
|
27
26
|
# The editor supports extra arbitrary properties for `window/showMessageRequest`. Necessary for add-ons to show
|
|
28
27
|
# dialogs with user interactions
|
|
29
|
-
@window_show_message_supports_extra_properties =
|
|
28
|
+
@window_show_message_supports_extra_properties = false #: bool
|
|
30
29
|
|
|
31
30
|
# Which resource operations the editor supports, like renaming files
|
|
32
|
-
@supported_resource_operations =
|
|
31
|
+
@supported_resource_operations = [] #: Array[String]
|
|
33
32
|
|
|
34
33
|
# The editor supports displaying progress requests
|
|
35
|
-
@supports_progress =
|
|
34
|
+
@supports_progress = false #: bool
|
|
36
35
|
|
|
37
36
|
# The editor supports server initiated refresh for diagnostics
|
|
38
|
-
@supports_diagnostic_refresh =
|
|
37
|
+
@supports_diagnostic_refresh = false #: bool
|
|
38
|
+
|
|
39
|
+
# The editor supports server initiated refresh for code lenses
|
|
40
|
+
@supports_code_lens_refresh = false #: bool
|
|
39
41
|
end
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
#: (Hash[Symbol, untyped] capabilities) -> void
|
|
42
44
|
def apply_client_capabilities(capabilities)
|
|
43
45
|
workspace_capabilities = capabilities[:workspace] || {}
|
|
44
46
|
|
|
@@ -63,9 +65,10 @@ module RubyLsp
|
|
|
63
65
|
@supports_progress = progress if progress
|
|
64
66
|
|
|
65
67
|
@supports_diagnostic_refresh = workspace_capabilities.dig(:diagnostics, :refreshSupport) || false
|
|
68
|
+
@supports_code_lens_refresh = workspace_capabilities.dig(:codeLens, :refreshSupport) || false
|
|
66
69
|
end
|
|
67
70
|
|
|
68
|
-
|
|
71
|
+
#: -> bool
|
|
69
72
|
def supports_rename?
|
|
70
73
|
@supported_resource_operations.include?("rename")
|
|
71
74
|
end
|