ruby-lsp 0.13.2 → 0.13.4
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 +30 -0
- data/VERSION +1 -1
- data/lib/ruby_lsp/check_docs.rb +3 -3
- data/lib/ruby_lsp/document.rb +12 -0
- data/lib/ruby_lsp/executor.rb +77 -266
- data/lib/ruby_lsp/listener.rb +1 -50
- data/lib/ruby_lsp/listeners/code_lens.rb +233 -0
- data/lib/ruby_lsp/listeners/completion.rb +275 -0
- data/lib/ruby_lsp/listeners/definition.rb +158 -0
- data/lib/ruby_lsp/listeners/document_highlight.rb +556 -0
- data/lib/ruby_lsp/listeners/document_link.rb +162 -0
- data/lib/ruby_lsp/listeners/document_symbol.rb +223 -0
- data/lib/ruby_lsp/listeners/folding_ranges.rb +271 -0
- data/lib/ruby_lsp/listeners/hover.rb +152 -0
- data/lib/ruby_lsp/listeners/inlay_hints.rb +80 -0
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +430 -0
- data/lib/ruby_lsp/listeners/signature_help.rb +74 -0
- data/lib/ruby_lsp/requests/code_action_resolve.rb +4 -4
- data/lib/ruby_lsp/requests/code_actions.rb +13 -4
- data/lib/ruby_lsp/requests/code_lens.rb +21 -221
- data/lib/ruby_lsp/requests/completion.rb +64 -244
- data/lib/ruby_lsp/requests/definition.rb +34 -147
- data/lib/ruby_lsp/requests/diagnostics.rb +17 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +12 -536
- data/lib/ruby_lsp/requests/document_link.rb +11 -132
- data/lib/ruby_lsp/requests/document_symbol.rb +23 -210
- data/lib/ruby_lsp/requests/folding_ranges.rb +16 -252
- data/lib/ruby_lsp/requests/formatting.rb +4 -4
- data/lib/ruby_lsp/requests/hover.rb +48 -92
- data/lib/ruby_lsp/requests/inlay_hints.rb +23 -56
- data/lib/ruby_lsp/requests/on_type_formatting.rb +16 -4
- data/lib/ruby_lsp/requests/request.rb +17 -0
- data/lib/ruby_lsp/requests/selection_ranges.rb +4 -3
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +21 -408
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +4 -4
- data/lib/ruby_lsp/requests/signature_help.rb +43 -51
- data/lib/ruby_lsp/requests/support/common.rb +3 -2
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +2 -0
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +2 -2
- data/lib/ruby_lsp/requests/workspace_symbol.rb +5 -4
- data/lib/ruby_lsp/requests.rb +1 -1
- data/lib/ruby_lsp/utils.rb +8 -0
- metadata +17 -6
- data/lib/ruby_lsp/requests/base_request.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 675bc1c9ddbcb8c05d591e184e2cf77914a6fcfa4af5db6178864063a910e0bd
|
4
|
+
data.tar.gz: 3f14554ce578fe5457ad90f2500b5267fded390e17b58142a2a174928630c53c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55fabbd6b161a499b378eead24ba073a7729d7772d702585b995efc3667c761a39544bb09c289c0ef16fa3300b907a7573173bbe7966b6656cddf912c60b7fd7
|
7
|
+
data.tar.gz: 85c9e57ae099be6fc957cf6a0ad63e07b6eb5e207770b3ea5cbd0cd328383ca9f76314c16f03f1a2707ce78991a6ce20dc382fb17ce4ed8ce1e7e4fdd6c5d5bb
|
data/README.md
CHANGED
@@ -46,6 +46,36 @@ See the [documentation](https://shopify.github.io/ruby-lsp) for more in-depth de
|
|
46
46
|
For creating rich themes for Ruby using the semantic highlighting information, see the [semantic highlighting
|
47
47
|
documentation](SEMANTIC_HIGHLIGHTING.md).
|
48
48
|
|
49
|
+
### Configuring code indexing
|
50
|
+
|
51
|
+
By default, the Ruby LSP indexes all Ruby files defined in the current project and all of its dependencies, including
|
52
|
+
default gems, except for
|
53
|
+
|
54
|
+
- Gems that only appear under the `:development` group
|
55
|
+
- All Ruby files under `test/**/*.rb`
|
56
|
+
|
57
|
+
By creating a `.index.yml` file, these configurations can be overridden and tuned.
|
58
|
+
|
59
|
+
```yaml
|
60
|
+
# Exclude files based on a given pattern. Often used to exclude test files or fixtures
|
61
|
+
excluded_patterns:
|
62
|
+
- "**/spec/**/*.rb"
|
63
|
+
|
64
|
+
# Include files based on a given pattern. Can be used to index Ruby files that use different extensions
|
65
|
+
included_patterns:
|
66
|
+
- "**/bin/*"
|
67
|
+
|
68
|
+
# Exclude gems by name. If a gem is never referenced in the project's code and is only used as a tool, excluding it will
|
69
|
+
# speed up indexing and reduce the amount of results in features like definition or completion
|
70
|
+
excluded_gems:
|
71
|
+
- rubocop
|
72
|
+
- pathname
|
73
|
+
|
74
|
+
# Include gems by name. Normally used to include development gems that are excluded by default
|
75
|
+
included_gems:
|
76
|
+
- prism
|
77
|
+
```
|
78
|
+
|
49
79
|
### Addons
|
50
80
|
|
51
81
|
The Ruby LSP provides an addon system that allows other gems to enhance the base functionality with more editor
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.13.
|
1
|
+
0.13.4
|
data/lib/ruby_lsp/check_docs.rb
CHANGED
@@ -51,15 +51,15 @@ module RubyLsp
|
|
51
51
|
|
52
52
|
# Find all classes that inherit from BaseRequest or Listener, which are the ones we want to make sure are
|
53
53
|
# documented
|
54
|
-
features = ObjectSpace.each_object(Class).
|
54
|
+
features = ObjectSpace.each_object(Class).select do |k|
|
55
55
|
klass = T.unsafe(k)
|
56
|
-
klass
|
56
|
+
klass < Requests::Request
|
57
57
|
end
|
58
58
|
|
59
59
|
missing_docs = T.let(Hash.new { |h, k| h[k] = [] }, T::Hash[String, T::Array[String]])
|
60
60
|
|
61
61
|
features.each do |klass|
|
62
|
-
class_name = T.
|
62
|
+
class_name = T.unsafe(klass).name
|
63
63
|
file_path, line_number = Module.const_source_location(class_name)
|
64
64
|
next unless file_path && line_number
|
65
65
|
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -173,6 +173,18 @@ module RubyLsp
|
|
173
173
|
[closest, parent, nesting.map { |n| n.constant_path.location.slice }]
|
174
174
|
end
|
175
175
|
|
176
|
+
sig { returns(T::Boolean) }
|
177
|
+
def sorbet_sigil_is_true_or_higher
|
178
|
+
parse_result.magic_comments.any? do |comment|
|
179
|
+
comment.key == "typed" && ["true", "strict", "strong"].include?(comment.value)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
sig { returns(T::Boolean) }
|
184
|
+
def typechecker_enabled?
|
185
|
+
DependencyDetector.instance.typechecker && sorbet_sigil_is_true_or_higher
|
186
|
+
end
|
187
|
+
|
176
188
|
class Scanner
|
177
189
|
extend T::Sig
|
178
190
|
|
data/lib/ruby_lsp/executor.rb
CHANGED
@@ -94,7 +94,7 @@ module RubyLsp
|
|
94
94
|
cached_response = document.cache_get(request[:method])
|
95
95
|
return cached_response if cached_response
|
96
96
|
|
97
|
-
# Run
|
97
|
+
# Run requests for the document
|
98
98
|
dispatcher = Prism::Dispatcher.new
|
99
99
|
folding_range = Requests::FoldingRanges.new(document.parse_result.comments, dispatcher)
|
100
100
|
document_symbol = Requests::DocumentSymbol.new(dispatcher)
|
@@ -107,13 +107,13 @@ module RubyLsp
|
|
107
107
|
|
108
108
|
# Store all responses retrieve in this round of visits in the cache and then return the response for the request
|
109
109
|
# we actually received
|
110
|
-
document.cache_set("textDocument/foldingRange", folding_range.
|
111
|
-
document.cache_set("textDocument/documentSymbol", document_symbol.
|
112
|
-
document.cache_set("textDocument/documentLink", document_link.
|
113
|
-
document.cache_set("textDocument/codeLens", code_lens.
|
110
|
+
document.cache_set("textDocument/foldingRange", folding_range.perform)
|
111
|
+
document.cache_set("textDocument/documentSymbol", document_symbol.perform)
|
112
|
+
document.cache_set("textDocument/documentLink", document_link.perform)
|
113
|
+
document.cache_set("textDocument/codeLens", code_lens.perform)
|
114
114
|
document.cache_set(
|
115
115
|
"textDocument/semanticTokens/full",
|
116
|
-
Requests::Support::SemanticTokenEncoder.new.encode(semantic_highlighting.
|
116
|
+
Requests::Support::SemanticTokenEncoder.new.encode(semantic_highlighting.perform),
|
117
117
|
)
|
118
118
|
document.cache_get(request[:method])
|
119
119
|
when "textDocument/semanticTokens/range"
|
@@ -143,13 +143,30 @@ module RubyLsp
|
|
143
143
|
nil
|
144
144
|
end
|
145
145
|
when "textDocument/documentHighlight"
|
146
|
-
|
146
|
+
dispatcher = Prism::Dispatcher.new
|
147
|
+
document = @store.get(uri)
|
148
|
+
request = Requests::DocumentHighlight.new(document, request.dig(:params, :position), dispatcher)
|
149
|
+
dispatcher.dispatch(document.tree)
|
150
|
+
request.perform
|
147
151
|
when "textDocument/onTypeFormatting"
|
148
152
|
on_type_formatting(uri, request.dig(:params, :position), request.dig(:params, :ch))
|
149
153
|
when "textDocument/hover"
|
150
|
-
|
154
|
+
dispatcher = Prism::Dispatcher.new
|
155
|
+
document = @store.get(uri)
|
156
|
+
Requests::Hover.new(
|
157
|
+
document,
|
158
|
+
@index,
|
159
|
+
request.dig(:params, :position),
|
160
|
+
dispatcher,
|
161
|
+
document.typechecker_enabled?,
|
162
|
+
).perform
|
151
163
|
when "textDocument/inlayHint"
|
152
|
-
|
164
|
+
hints_configurations = T.must(@store.features_configuration.dig(:inlayHint))
|
165
|
+
dispatcher = Prism::Dispatcher.new
|
166
|
+
document = @store.get(uri)
|
167
|
+
request = Requests::InlayHints.new(document, request.dig(:params, :range), hints_configurations, dispatcher)
|
168
|
+
dispatcher.visit(document.tree)
|
169
|
+
request.perform
|
153
170
|
when "textDocument/codeAction"
|
154
171
|
code_action(uri, request.dig(:params, :range), request.dig(:params, :context))
|
155
172
|
when "codeAction/resolve"
|
@@ -169,11 +186,36 @@ module RubyLsp
|
|
169
186
|
nil
|
170
187
|
end
|
171
188
|
when "textDocument/completion"
|
172
|
-
|
173
|
-
|
174
|
-
|
189
|
+
dispatcher = Prism::Dispatcher.new
|
190
|
+
document = @store.get(uri)
|
191
|
+
Requests::Completion.new(
|
192
|
+
document,
|
193
|
+
@index,
|
194
|
+
request.dig(:params, :position),
|
195
|
+
document.typechecker_enabled?,
|
196
|
+
dispatcher,
|
197
|
+
).perform
|
175
198
|
when "textDocument/signatureHelp"
|
176
|
-
|
199
|
+
dispatcher = Prism::Dispatcher.new
|
200
|
+
document = @store.get(uri)
|
201
|
+
|
202
|
+
Requests::SignatureHelp.new(
|
203
|
+
document,
|
204
|
+
@index,
|
205
|
+
request.dig(:params, :position),
|
206
|
+
request.dig(:params, :context),
|
207
|
+
dispatcher,
|
208
|
+
).perform
|
209
|
+
when "textDocument/definition"
|
210
|
+
dispatcher = Prism::Dispatcher.new
|
211
|
+
document = @store.get(uri)
|
212
|
+
Requests::Definition.new(
|
213
|
+
document,
|
214
|
+
@index,
|
215
|
+
request.dig(:params, :position),
|
216
|
+
dispatcher,
|
217
|
+
document.typechecker_enabled?,
|
218
|
+
).perform
|
177
219
|
when "workspace/didChangeWatchedFiles"
|
178
220
|
did_change_watched_files(request.dig(:params, :changes))
|
179
221
|
when "workspace/symbol"
|
@@ -243,96 +285,14 @@ module RubyLsp
|
|
243
285
|
end
|
244
286
|
end
|
245
287
|
|
246
|
-
sig do
|
247
|
-
params(
|
248
|
-
uri: URI::Generic,
|
249
|
-
position: T::Hash[Symbol, T.untyped],
|
250
|
-
context: T::Hash[Symbol, T.untyped],
|
251
|
-
).returns(T.any(T.nilable(Interface::SignatureHelp), T::Hash[Symbol, T.untyped]))
|
252
|
-
end
|
253
|
-
def signature_help(uri, position, context)
|
254
|
-
current_signature = context[:activeSignatureHelp]
|
255
|
-
document = @store.get(uri)
|
256
|
-
target, parent, nesting = document.locate_node(
|
257
|
-
{ line: position[:line], character: position[:character] - 2 },
|
258
|
-
node_types: [Prism::CallNode],
|
259
|
-
)
|
260
|
-
|
261
|
-
# If we're typing a nested method call (e.g.: `foo(bar)`), then we may end up locating `bar` as the target method
|
262
|
-
# call incorrectly. To correct that, we check if there's an active signature with the same name as the parent node
|
263
|
-
# and then replace the target
|
264
|
-
if current_signature && parent.is_a?(Prism::CallNode)
|
265
|
-
active_signature = current_signature[:activeSignature] || 0
|
266
|
-
|
267
|
-
if current_signature.dig(:signatures, active_signature, :label)&.start_with?(parent.message)
|
268
|
-
target = parent
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
dispatcher = Prism::Dispatcher.new
|
273
|
-
listener = Requests::SignatureHelp.new(context, nesting, @index, dispatcher)
|
274
|
-
dispatcher.dispatch_once(target)
|
275
|
-
listener.response
|
276
|
-
end
|
277
|
-
|
278
288
|
sig { params(query: T.nilable(String)).returns(T::Array[Interface::WorkspaceSymbol]) }
|
279
289
|
def workspace_symbol(query)
|
280
|
-
Requests::WorkspaceSymbol.new(query, @index).
|
290
|
+
Requests::WorkspaceSymbol.new(query, @index).perform
|
281
291
|
end
|
282
292
|
|
283
293
|
sig { params(uri: URI::Generic, range: T.nilable(T::Hash[Symbol, T.untyped])).returns({ ast: String }) }
|
284
294
|
def show_syntax_tree(uri, range)
|
285
|
-
{ ast: Requests::ShowSyntaxTree.new(@store.get(uri), range).
|
286
|
-
end
|
287
|
-
|
288
|
-
sig do
|
289
|
-
params(
|
290
|
-
uri: URI::Generic,
|
291
|
-
position: T::Hash[Symbol, T.untyped],
|
292
|
-
).returns(T.nilable(T.any(T::Array[Interface::Location], Interface::Location)))
|
293
|
-
end
|
294
|
-
def definition(uri, position)
|
295
|
-
document = @store.get(uri)
|
296
|
-
target, parent, nesting = document.locate_node(
|
297
|
-
position,
|
298
|
-
node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode],
|
299
|
-
)
|
300
|
-
|
301
|
-
target = parent if target.is_a?(Prism::ConstantReadNode) && parent.is_a?(Prism::ConstantPathNode)
|
302
|
-
|
303
|
-
dispatcher = Prism::Dispatcher.new
|
304
|
-
base_listener = Requests::Definition.new(uri, nesting, @index, dispatcher)
|
305
|
-
dispatcher.dispatch_once(target)
|
306
|
-
base_listener.response
|
307
|
-
end
|
308
|
-
|
309
|
-
sig do
|
310
|
-
params(
|
311
|
-
uri: URI::Generic,
|
312
|
-
position: T::Hash[Symbol, T.untyped],
|
313
|
-
).returns(T.nilable(Interface::Hover))
|
314
|
-
end
|
315
|
-
def hover(uri, position)
|
316
|
-
document = @store.get(uri)
|
317
|
-
target, parent, nesting = document.locate_node(
|
318
|
-
position,
|
319
|
-
node_types: Requests::Hover::ALLOWED_TARGETS,
|
320
|
-
)
|
321
|
-
|
322
|
-
if (Requests::Hover::ALLOWED_TARGETS.include?(parent.class) &&
|
323
|
-
!Requests::Hover::ALLOWED_TARGETS.include?(target.class)) ||
|
324
|
-
(parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
|
325
|
-
target = parent
|
326
|
-
end
|
327
|
-
|
328
|
-
# Instantiate all listeners
|
329
|
-
dispatcher = Prism::Dispatcher.new
|
330
|
-
hover = Requests::Hover.new(@index, nesting, dispatcher)
|
331
|
-
|
332
|
-
# Emit events for all listeners
|
333
|
-
dispatcher.dispatch_once(target)
|
334
|
-
|
335
|
-
hover.response
|
295
|
+
{ ast: Requests::ShowSyntaxTree.new(@store.get(uri), range).perform }
|
336
296
|
end
|
337
297
|
|
338
298
|
sig do
|
@@ -363,7 +323,7 @@ module RubyLsp
|
|
363
323
|
end
|
364
324
|
def selection_range(uri, positions)
|
365
325
|
ranges = @store.cache_fetch(uri, "textDocument/selectionRange") do |document|
|
366
|
-
Requests::SelectionRanges.new(document).
|
326
|
+
Requests::SelectionRanges.new(document).perform
|
367
327
|
end
|
368
328
|
|
369
329
|
# Per the selection range request spec (https://microsoft.github.io/language-server-protocol/specification#textDocument_selectionRange),
|
@@ -390,7 +350,7 @@ module RubyLsp
|
|
390
350
|
path = uri.to_standardized_path
|
391
351
|
return unless path.nil? || path.start_with?(T.must(@store.workspace_uri.to_standardized_path))
|
392
352
|
|
393
|
-
Requests::Formatting.new(@store.get(uri), formatter: @store.formatter).
|
353
|
+
Requests::Formatting.new(@store.get(uri), formatter: @store.formatter).perform
|
394
354
|
end
|
395
355
|
|
396
356
|
sig do
|
@@ -401,42 +361,7 @@ module RubyLsp
|
|
401
361
|
).returns(T::Array[Interface::TextEdit])
|
402
362
|
end
|
403
363
|
def on_type_formatting(uri, position, character)
|
404
|
-
Requests::OnTypeFormatting.new(@store.get(uri), position, character).
|
405
|
-
end
|
406
|
-
|
407
|
-
sig do
|
408
|
-
params(
|
409
|
-
uri: URI::Generic,
|
410
|
-
position: T::Hash[Symbol, T.untyped],
|
411
|
-
).returns(T.nilable(T::Array[Interface::DocumentHighlight]))
|
412
|
-
end
|
413
|
-
def document_highlight(uri, position)
|
414
|
-
document = @store.get(uri)
|
415
|
-
|
416
|
-
target, parent = document.locate_node(position)
|
417
|
-
dispatcher = Prism::Dispatcher.new
|
418
|
-
listener = Requests::DocumentHighlight.new(target, parent, dispatcher)
|
419
|
-
dispatcher.visit(document.tree)
|
420
|
-
listener.response
|
421
|
-
end
|
422
|
-
|
423
|
-
sig do
|
424
|
-
params(
|
425
|
-
uri: URI::Generic,
|
426
|
-
range: T::Hash[Symbol, T.untyped],
|
427
|
-
).returns(T.nilable(T::Array[Interface::InlayHint]))
|
428
|
-
end
|
429
|
-
def inlay_hint(uri, range)
|
430
|
-
document = @store.get(uri)
|
431
|
-
|
432
|
-
start_line = range.dig(:start, :line)
|
433
|
-
end_line = range.dig(:end, :line)
|
434
|
-
|
435
|
-
dispatcher = Prism::Dispatcher.new
|
436
|
-
hints_configurations = T.must(@store.features_configuration.dig(:inlayHint))
|
437
|
-
listener = Requests::InlayHints.new(start_line..end_line, hints_configurations, dispatcher)
|
438
|
-
dispatcher.visit(document.tree)
|
439
|
-
listener.response
|
364
|
+
Requests::OnTypeFormatting.new(@store.get(uri), position, character).perform
|
440
365
|
end
|
441
366
|
|
442
367
|
sig do
|
@@ -449,14 +374,14 @@ module RubyLsp
|
|
449
374
|
def code_action(uri, range, context)
|
450
375
|
document = @store.get(uri)
|
451
376
|
|
452
|
-
Requests::CodeActions.new(document, range, context).
|
377
|
+
Requests::CodeActions.new(document, range, context).perform
|
453
378
|
end
|
454
379
|
|
455
380
|
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Interface::CodeAction) }
|
456
381
|
def code_action_resolve(params)
|
457
382
|
uri = URI(params.dig(:data, :uri))
|
458
383
|
document = @store.get(uri)
|
459
|
-
result = Requests::CodeActionResolve.new(document, params).
|
384
|
+
result = Requests::CodeActionResolve.new(document, params).perform
|
460
385
|
|
461
386
|
case result
|
462
387
|
when Requests::CodeActionResolve::Error::EmptySelection
|
@@ -490,7 +415,7 @@ module RubyLsp
|
|
490
415
|
return unless path.nil? || path.start_with?(T.must(@store.workspace_uri.to_standardized_path))
|
491
416
|
|
492
417
|
response = @store.cache_fetch(uri, "textDocument/diagnostic") do |document|
|
493
|
-
Requests::Diagnostics.new(document).
|
418
|
+
Requests::Diagnostics.new(document).perform
|
494
419
|
end
|
495
420
|
|
496
421
|
Interface::FullDocumentDiagnosticReport.new(kind: "full", items: response) if response
|
@@ -503,61 +428,10 @@ module RubyLsp
|
|
503
428
|
end_line = range.dig(:end, :line)
|
504
429
|
|
505
430
|
dispatcher = Prism::Dispatcher.new
|
506
|
-
|
431
|
+
request = Requests::SemanticHighlighting.new(dispatcher, range: start_line..end_line)
|
507
432
|
dispatcher.visit(document.tree)
|
508
433
|
|
509
|
-
Requests::Support::SemanticTokenEncoder.new.encode(
|
510
|
-
end
|
511
|
-
|
512
|
-
sig do
|
513
|
-
params(
|
514
|
-
uri: URI::Generic,
|
515
|
-
position: T::Hash[Symbol, T.untyped],
|
516
|
-
).returns(T.nilable(T::Array[Interface::CompletionItem]))
|
517
|
-
end
|
518
|
-
def completion(uri, position)
|
519
|
-
document = @store.get(uri)
|
520
|
-
|
521
|
-
# Completion always receives the position immediately after the character that was just typed. Here we adjust it
|
522
|
-
# back by 1, so that we find the right node
|
523
|
-
char_position = document.create_scanner.find_char_position(position) - 1
|
524
|
-
matched, parent, nesting = document.locate(
|
525
|
-
document.tree,
|
526
|
-
char_position,
|
527
|
-
node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode],
|
528
|
-
)
|
529
|
-
return unless matched && parent
|
530
|
-
|
531
|
-
target = case matched
|
532
|
-
when Prism::CallNode
|
533
|
-
message = matched.message
|
534
|
-
|
535
|
-
if message == "require"
|
536
|
-
args = matched.arguments&.arguments
|
537
|
-
return if args.nil? || args.is_a?(Prism::ForwardingArgumentsNode)
|
538
|
-
|
539
|
-
argument = args.first
|
540
|
-
return unless argument.is_a?(Prism::StringNode)
|
541
|
-
return unless (argument.location.start_offset..argument.location.end_offset).cover?(char_position)
|
542
|
-
|
543
|
-
argument
|
544
|
-
else
|
545
|
-
matched
|
546
|
-
end
|
547
|
-
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
548
|
-
if parent.is_a?(Prism::ConstantPathNode) && matched.is_a?(Prism::ConstantReadNode)
|
549
|
-
parent
|
550
|
-
else
|
551
|
-
matched
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
|
-
return unless target
|
556
|
-
|
557
|
-
dispatcher = Prism::Dispatcher.new
|
558
|
-
listener = Requests::Completion.new(@index, nesting, dispatcher)
|
559
|
-
dispatcher.dispatch_once(target)
|
560
|
-
listener.response
|
434
|
+
Requests::Support::SemanticTokenEncoder.new.encode(request.perform)
|
561
435
|
end
|
562
436
|
|
563
437
|
sig { params(id: String, title: String, percentage: Integer).void }
|
@@ -663,81 +537,18 @@ module RubyLsp
|
|
663
537
|
Hash.new(true)
|
664
538
|
end
|
665
539
|
|
666
|
-
document_symbol_provider = if enabled_features["documentSymbols"]
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
code_lens_provider = if enabled_features["codeLens"]
|
680
|
-
Interface::CodeLensOptions.new(resolve_provider: false)
|
681
|
-
end
|
682
|
-
|
683
|
-
hover_provider = if enabled_features["hover"]
|
684
|
-
Interface::HoverClientCapabilities.new(dynamic_registration: false)
|
685
|
-
end
|
686
|
-
|
687
|
-
folding_ranges_provider = if enabled_features["foldingRanges"]
|
688
|
-
Interface::FoldingRangeClientCapabilities.new(line_folding_only: true)
|
689
|
-
end
|
690
|
-
|
691
|
-
semantic_tokens_provider = if enabled_features["semanticHighlighting"]
|
692
|
-
Interface::SemanticTokensRegistrationOptions.new(
|
693
|
-
document_selector: { scheme: "file", language: "ruby" },
|
694
|
-
legend: Interface::SemanticTokensLegend.new(
|
695
|
-
token_types: Requests::SemanticHighlighting::TOKEN_TYPES.keys,
|
696
|
-
token_modifiers: Requests::SemanticHighlighting::TOKEN_MODIFIERS.keys,
|
697
|
-
),
|
698
|
-
range: true,
|
699
|
-
full: { delta: false },
|
700
|
-
)
|
701
|
-
end
|
702
|
-
|
703
|
-
diagnostics_provider = if enabled_features["diagnostics"]
|
704
|
-
{
|
705
|
-
interFileDependencies: false,
|
706
|
-
workspaceDiagnostics: false,
|
707
|
-
}
|
708
|
-
end
|
709
|
-
|
710
|
-
on_type_formatting_provider = if enabled_features["onTypeFormatting"]
|
711
|
-
Interface::DocumentOnTypeFormattingOptions.new(
|
712
|
-
first_trigger_character: "{",
|
713
|
-
more_trigger_character: ["\n", "|", "d"],
|
714
|
-
)
|
715
|
-
end
|
716
|
-
|
717
|
-
code_action_provider = if enabled_features["codeActions"]
|
718
|
-
Interface::CodeActionOptions.new(resolve_provider: true)
|
719
|
-
end
|
720
|
-
|
721
|
-
inlay_hint_provider = if enabled_features["inlayHint"]
|
722
|
-
Interface::InlayHintOptions.new(resolve_provider: false)
|
723
|
-
end
|
724
|
-
|
725
|
-
completion_provider = if enabled_features["completion"]
|
726
|
-
Interface::CompletionOptions.new(
|
727
|
-
resolve_provider: false,
|
728
|
-
trigger_characters: ["/"],
|
729
|
-
completion_item: {
|
730
|
-
labelDetailsSupport: true,
|
731
|
-
},
|
732
|
-
)
|
733
|
-
end
|
734
|
-
|
735
|
-
signature_help_provider = if enabled_features["signatureHelp"]
|
736
|
-
# Identifier characters are automatically included, such as A-Z, a-z, 0-9, _, * or :
|
737
|
-
Interface::SignatureHelpOptions.new(
|
738
|
-
trigger_characters: ["(", " ", ","],
|
739
|
-
)
|
740
|
-
end
|
540
|
+
document_symbol_provider = Requests::DocumentSymbol.provider if enabled_features["documentSymbols"]
|
541
|
+
document_link_provider = Requests::DocumentLink.provider if enabled_features["documentLink"]
|
542
|
+
code_lens_provider = Requests::CodeLens.provider if enabled_features["codeLens"]
|
543
|
+
hover_provider = Requests::Hover.provider if enabled_features["hover"]
|
544
|
+
folding_ranges_provider = Requests::FoldingRanges.provider if enabled_features["foldingRanges"]
|
545
|
+
semantic_tokens_provider = Requests::SemanticHighlighting.provider if enabled_features["semanticHighlighting"]
|
546
|
+
diagnostics_provider = Requests::Diagnostics.provider if enabled_features["diagnostics"]
|
547
|
+
on_type_formatting_provider = Requests::OnTypeFormatting.provider if enabled_features["onTypeFormatting"]
|
548
|
+
code_action_provider = Requests::CodeActions.provider if enabled_features["codeActions"]
|
549
|
+
inlay_hint_provider = Requests::InlayHints.provider if enabled_features["inlayHint"]
|
550
|
+
completion_provider = Requests::Completion.provider if enabled_features["completion"]
|
551
|
+
signature_help_provider = Requests::SignatureHelp.provider if enabled_features["signatureHelp"]
|
741
552
|
|
742
553
|
# Dynamically registered capabilities
|
743
554
|
file_watching_caps = options.dig(:capabilities, :workspace, :didChangeWatchedFiles)
|
data/lib/ruby_lsp/listener.rb
CHANGED
@@ -16,6 +16,7 @@ module RubyLsp
|
|
16
16
|
|
17
17
|
sig { params(dispatcher: Prism::Dispatcher).void }
|
18
18
|
def initialize(dispatcher)
|
19
|
+
super()
|
19
20
|
@dispatcher = dispatcher
|
20
21
|
end
|
21
22
|
|
@@ -29,54 +30,4 @@ module RubyLsp
|
|
29
30
|
sig { abstract.returns(ResponseType) }
|
30
31
|
def _response; end
|
31
32
|
end
|
32
|
-
|
33
|
-
# ExtensibleListener is an abstract class to be used by requests that accept addons.
|
34
|
-
class ExtensibleListener < Listener
|
35
|
-
extend T::Sig
|
36
|
-
extend T::Generic
|
37
|
-
|
38
|
-
ResponseType = type_member
|
39
|
-
|
40
|
-
abstract!
|
41
|
-
|
42
|
-
# When inheriting from ExtensibleListener, the `super` of constructor must be called **after** the subclass's own
|
43
|
-
# ivars have been initialized. This is because the constructor of ExtensibleListener calls
|
44
|
-
# `initialize_external_listener` which may depend on the subclass's ivars.
|
45
|
-
sig { params(dispatcher: Prism::Dispatcher).void }
|
46
|
-
def initialize(dispatcher)
|
47
|
-
super
|
48
|
-
@response_merged = T.let(false, T::Boolean)
|
49
|
-
@external_listeners = T.let(
|
50
|
-
Addon.addons.filter_map do |ext|
|
51
|
-
initialize_external_listener(ext)
|
52
|
-
end,
|
53
|
-
T::Array[RubyLsp::Listener[ResponseType]],
|
54
|
-
)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Merge responses from all external listeners into the base listener's response. We do this to return a single
|
58
|
-
# response to the editor including the results of all addons
|
59
|
-
sig { void }
|
60
|
-
def merge_external_listeners_responses!
|
61
|
-
@external_listeners.each { |l| merge_response!(l) }
|
62
|
-
end
|
63
|
-
|
64
|
-
sig { returns(ResponseType) }
|
65
|
-
def response
|
66
|
-
merge_external_listeners_responses! unless @response_merged
|
67
|
-
super
|
68
|
-
end
|
69
|
-
|
70
|
-
sig do
|
71
|
-
abstract.params(addon: RubyLsp::Addon).returns(T.nilable(RubyLsp::Listener[ResponseType]))
|
72
|
-
end
|
73
|
-
def initialize_external_listener(addon); end
|
74
|
-
|
75
|
-
# Does nothing by default. Requests that accept addons should override this method to define how to merge responses
|
76
|
-
# coming from external listeners
|
77
|
-
sig { abstract.params(other: Listener[T.untyped]).returns(T.self_type) }
|
78
|
-
def merge_response!(other)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
private_constant(:ExtensibleListener)
|
82
33
|
end
|