ruby-lsp 0.11.2 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/exe/ruby-lsp +2 -1
- data/exe/ruby-lsp-doctor +16 -0
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +5 -1
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +205 -0
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +23 -106
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -6
- data/lib/ruby_indexer/lib/ruby_indexer/visitor.rb +101 -49
- data/lib/ruby_indexer/ruby_indexer.rb +1 -0
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +49 -16
- data/lib/ruby_indexer/test/constant_test.rb +99 -36
- data/lib/ruby_indexer/test/index_test.rb +1 -1
- data/lib/ruby_indexer/test/method_test.rb +73 -0
- data/lib/ruby_indexer/test/test_case.rb +5 -1
- data/lib/ruby_lsp/addon.rb +8 -8
- data/lib/ruby_lsp/document.rb +14 -14
- data/lib/ruby_lsp/executor.rb +89 -53
- data/lib/ruby_lsp/internal.rb +7 -2
- data/lib/ruby_lsp/listener.rb +6 -6
- data/lib/ruby_lsp/requests/base_request.rb +1 -9
- data/lib/ruby_lsp/requests/code_action_resolve.rb +3 -3
- data/lib/ruby_lsp/requests/code_lens.rb +30 -30
- data/lib/ruby_lsp/requests/completion.rb +83 -32
- data/lib/ruby_lsp/requests/definition.rb +21 -15
- data/lib/ruby_lsp/requests/diagnostics.rb +1 -1
- data/lib/ruby_lsp/requests/document_highlight.rb +508 -31
- data/lib/ruby_lsp/requests/document_link.rb +24 -17
- data/lib/ruby_lsp/requests/document_symbol.rb +42 -42
- data/lib/ruby_lsp/requests/folding_ranges.rb +83 -77
- data/lib/ruby_lsp/requests/hover.rb +22 -17
- data/lib/ruby_lsp/requests/inlay_hints.rb +6 -6
- data/lib/ruby_lsp/requests/selection_ranges.rb +13 -105
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +92 -92
- data/lib/ruby_lsp/requests/support/annotation.rb +3 -3
- data/lib/ruby_lsp/requests/support/common.rb +5 -5
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -0
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +10 -7
- data/lib/ruby_lsp/requests/support/sorbet.rb +28 -28
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
- data/lib/ruby_lsp/requests.rb +0 -1
- data/lib/ruby_lsp/setup_bundler.rb +8 -5
- metadata +19 -17
- data/lib/ruby_lsp/event_emitter.rb +0 -351
- data/lib/ruby_lsp/requests/support/highlight_target.rb +0 -118
data/lib/ruby_lsp/executor.rb
CHANGED
@@ -92,14 +92,14 @@ module RubyLsp
|
|
92
92
|
return cached_response if cached_response
|
93
93
|
|
94
94
|
# Run listeners for the document
|
95
|
-
|
96
|
-
folding_range = Requests::FoldingRanges.new(document.parse_result.comments,
|
97
|
-
document_symbol = Requests::DocumentSymbol.new(
|
98
|
-
document_link = Requests::DocumentLink.new(uri, document.comments,
|
99
|
-
code_lens = Requests::CodeLens.new(uri,
|
95
|
+
dispatcher = Prism::Dispatcher.new
|
96
|
+
folding_range = Requests::FoldingRanges.new(document.parse_result.comments, dispatcher, @message_queue)
|
97
|
+
document_symbol = Requests::DocumentSymbol.new(dispatcher, @message_queue)
|
98
|
+
document_link = Requests::DocumentLink.new(uri, document.comments, dispatcher, @message_queue)
|
99
|
+
code_lens = Requests::CodeLens.new(uri, dispatcher, @message_queue)
|
100
100
|
|
101
|
-
semantic_highlighting = Requests::SemanticHighlighting.new(
|
102
|
-
|
101
|
+
semantic_highlighting = Requests::SemanticHighlighting.new(dispatcher, @message_queue)
|
102
|
+
dispatcher.dispatch(document.tree)
|
103
103
|
|
104
104
|
# Store all responses retrieve in this round of visits in the cache and then return the response for the request
|
105
105
|
# we actually received
|
@@ -210,21 +210,31 @@ module RubyLsp
|
|
210
210
|
# stuck indexing files
|
211
211
|
RubyIndexer.configuration.load_config
|
212
212
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
message
|
221
|
-
|
222
|
-
|
223
|
-
|
213
|
+
Thread.new do
|
214
|
+
begin
|
215
|
+
@index.index_all do |percentage|
|
216
|
+
progress("indexing-progress", percentage)
|
217
|
+
true
|
218
|
+
rescue ClosedQueueError
|
219
|
+
# Since we run indexing on a separate thread, it's possible to kill the server before indexing is complete.
|
220
|
+
# In those cases, the message queue will be closed and raise a ClosedQueueError. By returning `false`, we
|
221
|
+
# tell the index to stop working immediately
|
222
|
+
false
|
223
|
+
end
|
224
|
+
rescue StandardError => error
|
225
|
+
@message_queue << Notification.new(
|
226
|
+
message: "window/showMessage",
|
227
|
+
params: Interface::ShowMessageParams.new(
|
228
|
+
type: Constant::MessageType::ERROR,
|
229
|
+
message: "Error while indexing: #{error.message}",
|
230
|
+
),
|
231
|
+
)
|
232
|
+
end
|
224
233
|
|
225
|
-
|
226
|
-
|
227
|
-
|
234
|
+
# Always end the progress notification even if indexing failed or else it never goes away and the user has no
|
235
|
+
# way of dismissing it
|
236
|
+
end_progress("indexing-progress")
|
237
|
+
end
|
228
238
|
end
|
229
239
|
|
230
240
|
sig { params(query: T.nilable(String)).returns(T::Array[Interface::WorkspaceSymbol]) }
|
@@ -247,20 +257,20 @@ module RubyLsp
|
|
247
257
|
document = @store.get(uri)
|
248
258
|
target, parent, nesting = document.locate_node(
|
249
259
|
position,
|
250
|
-
node_types: [
|
260
|
+
node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode],
|
251
261
|
)
|
252
262
|
|
253
|
-
target = parent if target.is_a?(
|
263
|
+
target = parent if target.is_a?(Prism::ConstantReadNode) && parent.is_a?(Prism::ConstantPathNode)
|
254
264
|
|
255
|
-
|
265
|
+
dispatcher = Prism::Dispatcher.new
|
256
266
|
base_listener = Requests::Definition.new(
|
257
267
|
uri,
|
258
268
|
nesting,
|
259
269
|
@index,
|
260
|
-
|
270
|
+
dispatcher,
|
261
271
|
@message_queue,
|
262
272
|
)
|
263
|
-
|
273
|
+
dispatcher.dispatch_once(target)
|
264
274
|
base_listener.response
|
265
275
|
end
|
266
276
|
|
@@ -279,16 +289,16 @@ module RubyLsp
|
|
279
289
|
|
280
290
|
if (Requests::Hover::ALLOWED_TARGETS.include?(parent.class) &&
|
281
291
|
!Requests::Hover::ALLOWED_TARGETS.include?(target.class)) ||
|
282
|
-
(parent.is_a?(
|
292
|
+
(parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
|
283
293
|
target = parent
|
284
294
|
end
|
285
295
|
|
286
296
|
# Instantiate all listeners
|
287
|
-
|
288
|
-
hover = Requests::Hover.new(@index, nesting,
|
297
|
+
dispatcher = Prism::Dispatcher.new
|
298
|
+
hover = Requests::Hover.new(@index, nesting, dispatcher, @message_queue)
|
289
299
|
|
290
300
|
# Emit events for all listeners
|
291
|
-
|
301
|
+
dispatcher.dispatch_once(target)
|
292
302
|
|
293
303
|
hover.response
|
294
304
|
end
|
@@ -367,9 +377,9 @@ module RubyLsp
|
|
367
377
|
document = @store.get(uri)
|
368
378
|
|
369
379
|
target, parent = document.locate_node(position)
|
370
|
-
|
371
|
-
listener = Requests::DocumentHighlight.new(target, parent,
|
372
|
-
|
380
|
+
dispatcher = Prism::Dispatcher.new
|
381
|
+
listener = Requests::DocumentHighlight.new(target, parent, dispatcher, @message_queue)
|
382
|
+
dispatcher.visit(document.tree)
|
373
383
|
listener.response
|
374
384
|
end
|
375
385
|
|
@@ -380,9 +390,9 @@ module RubyLsp
|
|
380
390
|
start_line = range.dig(:start, :line)
|
381
391
|
end_line = range.dig(:end, :line)
|
382
392
|
|
383
|
-
|
384
|
-
listener = Requests::InlayHints.new(start_line..end_line,
|
385
|
-
|
393
|
+
dispatcher = Prism::Dispatcher.new
|
394
|
+
listener = Requests::InlayHints.new(start_line..end_line, dispatcher, @message_queue)
|
395
|
+
dispatcher.visit(document.tree)
|
386
396
|
listener.response
|
387
397
|
end
|
388
398
|
|
@@ -444,13 +454,13 @@ module RubyLsp
|
|
444
454
|
start_line = range.dig(:start, :line)
|
445
455
|
end_line = range.dig(:end, :line)
|
446
456
|
|
447
|
-
|
457
|
+
dispatcher = Prism::Dispatcher.new
|
448
458
|
listener = Requests::SemanticHighlighting.new(
|
449
|
-
|
459
|
+
dispatcher,
|
450
460
|
@message_queue,
|
451
461
|
range: start_line..end_line,
|
452
462
|
)
|
453
|
-
|
463
|
+
dispatcher.visit(document.tree)
|
454
464
|
|
455
465
|
Requests::Support::SemanticTokenEncoder.new.encode(listener.response)
|
456
466
|
end
|
@@ -471,29 +481,29 @@ module RubyLsp
|
|
471
481
|
# the node, as it could not be a constant
|
472
482
|
target_node_types = if ("A".."Z").cover?(document.source[char_position - 1])
|
473
483
|
char_position -= 1
|
474
|
-
[
|
484
|
+
[Prism::ConstantReadNode, Prism::ConstantPathNode]
|
475
485
|
else
|
476
|
-
[
|
486
|
+
[Prism::CallNode]
|
477
487
|
end
|
478
488
|
|
479
489
|
matched, parent, nesting = document.locate(document.tree, char_position, node_types: target_node_types)
|
480
490
|
return unless matched && parent
|
481
491
|
|
482
492
|
target = case matched
|
483
|
-
when
|
493
|
+
when Prism::CallNode
|
484
494
|
message = matched.message
|
485
495
|
return unless message == "require"
|
486
496
|
|
487
497
|
args = matched.arguments&.arguments
|
488
|
-
return if args.nil? || args.is_a?(
|
498
|
+
return if args.nil? || args.is_a?(Prism::ForwardingArgumentsNode)
|
489
499
|
|
490
500
|
argument = args.first
|
491
|
-
return unless argument.is_a?(
|
501
|
+
return unless argument.is_a?(Prism::StringNode)
|
492
502
|
return unless (argument.location.start_offset..argument.location.end_offset).cover?(char_position)
|
493
503
|
|
494
504
|
argument
|
495
|
-
when
|
496
|
-
if parent.is_a?(
|
505
|
+
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
506
|
+
if parent.is_a?(Prism::ConstantPathNode) && matched.is_a?(Prism::ConstantReadNode)
|
497
507
|
parent
|
498
508
|
else
|
499
509
|
matched
|
@@ -502,19 +512,19 @@ module RubyLsp
|
|
502
512
|
|
503
513
|
return unless target
|
504
514
|
|
505
|
-
|
515
|
+
dispatcher = Prism::Dispatcher.new
|
506
516
|
listener = Requests::Completion.new(
|
507
517
|
@index,
|
508
518
|
nesting,
|
509
|
-
|
519
|
+
dispatcher,
|
510
520
|
@message_queue,
|
511
521
|
)
|
512
|
-
|
522
|
+
dispatcher.dispatch_once(target)
|
513
523
|
listener.response
|
514
524
|
end
|
515
525
|
|
516
|
-
sig { params(id: String, title: String).void }
|
517
|
-
def begin_progress(id, title)
|
526
|
+
sig { params(id: String, title: String, percentage: Integer).void }
|
527
|
+
def begin_progress(id, title, percentage: 0)
|
518
528
|
return unless @store.supports_progress
|
519
529
|
|
520
530
|
@message_queue << Request.new(
|
@@ -526,7 +536,29 @@ module RubyLsp
|
|
526
536
|
message: "$/progress",
|
527
537
|
params: Interface::ProgressParams.new(
|
528
538
|
token: id,
|
529
|
-
value: Interface::WorkDoneProgressBegin.new(
|
539
|
+
value: Interface::WorkDoneProgressBegin.new(
|
540
|
+
kind: "begin",
|
541
|
+
title: title,
|
542
|
+
percentage: percentage,
|
543
|
+
message: "#{percentage}% completed",
|
544
|
+
),
|
545
|
+
),
|
546
|
+
)
|
547
|
+
end
|
548
|
+
|
549
|
+
sig { params(id: String, percentage: Integer).void }
|
550
|
+
def progress(id, percentage)
|
551
|
+
return unless @store.supports_progress
|
552
|
+
|
553
|
+
@message_queue << Notification.new(
|
554
|
+
message: "$/progress",
|
555
|
+
params: Interface::ProgressParams.new(
|
556
|
+
token: id,
|
557
|
+
value: Interface::WorkDoneProgressReport.new(
|
558
|
+
kind: "report",
|
559
|
+
percentage: percentage,
|
560
|
+
message: "#{percentage}% completed",
|
561
|
+
),
|
530
562
|
),
|
531
563
|
)
|
532
564
|
end
|
@@ -542,6 +574,9 @@ module RubyLsp
|
|
542
574
|
value: Interface::WorkDoneProgressEnd.new(kind: "end"),
|
543
575
|
),
|
544
576
|
)
|
577
|
+
rescue ClosedQueueError
|
578
|
+
# If the server was killed and the message queue is already closed, there's no way to end the progress
|
579
|
+
# notification
|
545
580
|
end
|
546
581
|
|
547
582
|
sig { params(options: T::Hash[Symbol, T.untyped]).returns(Interface::InitializeResult) }
|
@@ -557,7 +592,8 @@ module RubyLsp
|
|
557
592
|
encodings.first
|
558
593
|
end
|
559
594
|
|
560
|
-
|
595
|
+
progress = options.dig(:capabilities, :window, :workDoneProgress)
|
596
|
+
@store.supports_progress = progress.nil? ? true : progress
|
561
597
|
formatter = options.dig(:initializationOptions, :formatter) || "auto"
|
562
598
|
@store.formatter = if formatter == "auto"
|
563
599
|
DependencyDetector.instance.detected_formatter
|
data/lib/ruby_lsp/internal.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
# If YARP is in the bundle, we have to remove it from the $LOAD_PATH because it contains a default export named `prism`
|
5
|
+
# that will conflict with the actual Prism gem
|
6
|
+
yarp_require_paths = Gem.loaded_specs["yarp"]&.full_require_paths
|
7
|
+
$LOAD_PATH.delete_if { |path| yarp_require_paths.include?(path) } if yarp_require_paths
|
8
|
+
|
4
9
|
require "sorbet-runtime"
|
5
|
-
require "
|
10
|
+
require "prism"
|
11
|
+
require "prism/visitor"
|
6
12
|
require "language_server-protocol"
|
7
13
|
require "bundler"
|
8
14
|
require "uri"
|
@@ -16,7 +22,6 @@ require "ruby_lsp/utils"
|
|
16
22
|
require "ruby_lsp/parameter_scope"
|
17
23
|
require "ruby_lsp/server"
|
18
24
|
require "ruby_lsp/executor"
|
19
|
-
require "ruby_lsp/event_emitter"
|
20
25
|
require "ruby_lsp/requests"
|
21
26
|
require "ruby_lsp/listener"
|
22
27
|
require "ruby_lsp/store"
|
data/lib/ruby_lsp/listener.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
# Listener is an abstract class to be used by requests for listening to events emitted when visiting an AST using the
|
6
|
-
#
|
6
|
+
# Prism::Dispatcher.
|
7
7
|
class Listener
|
8
8
|
extend T::Sig
|
9
9
|
extend T::Helpers
|
@@ -14,9 +14,9 @@ module RubyLsp
|
|
14
14
|
|
15
15
|
abstract!
|
16
16
|
|
17
|
-
sig { params(
|
18
|
-
def initialize(
|
19
|
-
@
|
17
|
+
sig { params(dispatcher: Prism::Dispatcher, message_queue: Thread::Queue).void }
|
18
|
+
def initialize(dispatcher, message_queue)
|
19
|
+
@dispatcher = dispatcher
|
20
20
|
@message_queue = message_queue
|
21
21
|
end
|
22
22
|
|
@@ -43,8 +43,8 @@ module RubyLsp
|
|
43
43
|
# When inheriting from ExtensibleListener, the `super` of constructor must be called **after** the subclass's own
|
44
44
|
# ivars have been initialized. This is because the constructor of ExtensibleListener calls
|
45
45
|
# `initialize_external_listener` which may depend on the subclass's ivars.
|
46
|
-
sig { params(
|
47
|
-
def initialize(
|
46
|
+
sig { params(dispatcher: Prism::Dispatcher, message_queue: Thread::Queue).void }
|
47
|
+
def initialize(dispatcher, message_queue)
|
48
48
|
super
|
49
49
|
@response_merged = T.let(false, T::Boolean)
|
50
50
|
@external_listeners = T.let(
|
@@ -4,7 +4,7 @@
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
6
|
# :nodoc:
|
7
|
-
class BaseRequest <
|
7
|
+
class BaseRequest < Prism::Visitor
|
8
8
|
extend T::Sig
|
9
9
|
extend T::Helpers
|
10
10
|
include Support::Common
|
@@ -19,14 +19,6 @@ module RubyLsp
|
|
19
19
|
|
20
20
|
sig { abstract.returns(Object) }
|
21
21
|
def run; end
|
22
|
-
|
23
|
-
# YARP implements `visit_all` using `map` instead of `each` for users who want to use the pattern
|
24
|
-
# `result = visitor.visit(tree)`. However, we don't use that pattern and should avoid producing a new array for
|
25
|
-
# every single node visited
|
26
|
-
sig { params(nodes: T::Array[T.nilable(YARP::Node)]).void }
|
27
|
-
def visit_all(nodes)
|
28
|
-
nodes.each { |node| visit(node) }
|
29
|
-
end
|
30
22
|
end
|
31
23
|
end
|
32
24
|
end
|
@@ -55,7 +55,7 @@ module RubyLsp
|
|
55
55
|
|
56
56
|
# Find the closest statements node, so that we place the refactor in a valid position
|
57
57
|
closest_statements, parent_statements = @document
|
58
|
-
.locate(@document.tree, start_index, node_types: [
|
58
|
+
.locate(@document.tree, start_index, node_types: [Prism::StatementsNode, Prism::BlockNode])
|
59
59
|
|
60
60
|
return Error::InvalidTargetRange if closest_statements.nil? || closest_statements.child_nodes.compact.empty?
|
61
61
|
|
@@ -66,11 +66,11 @@ module RubyLsp
|
|
66
66
|
distance <= 0 ? Float::INFINITY : distance
|
67
67
|
end)
|
68
68
|
|
69
|
-
return Error::InvalidTargetRange if closest_node.is_a?(
|
69
|
+
return Error::InvalidTargetRange if closest_node.is_a?(Prism::MissingNode)
|
70
70
|
|
71
71
|
closest_node_loc = closest_node.location
|
72
72
|
# If the parent expression is a single line block, then we have to extract it inside of the oneline block
|
73
|
-
if parent_statements.is_a?(
|
73
|
+
if parent_statements.is_a?(Prism::BlockNode) &&
|
74
74
|
parent_statements.location.start_line == parent_statements.location.end_line
|
75
75
|
|
76
76
|
variable_source = " #{NEW_VARIABLE_NAME} = #{extracted_source};"
|
@@ -25,36 +25,36 @@ module RubyLsp
|
|
25
25
|
ResponseType = type_member { { fixed: T::Array[Interface::CodeLens] } }
|
26
26
|
|
27
27
|
BASE_COMMAND = T.let((File.exist?("Gemfile.lock") ? "bundle exec ruby" : "ruby") + " -Itest ", String)
|
28
|
-
ACCESS_MODIFIERS = T.let([
|
28
|
+
ACCESS_MODIFIERS = T.let([:public, :private, :protected], T::Array[Symbol])
|
29
29
|
SUPPORTED_TEST_LIBRARIES = T.let(["minitest", "test-unit"], T::Array[String])
|
30
30
|
|
31
31
|
sig { override.returns(ResponseType) }
|
32
32
|
attr_reader :_response
|
33
33
|
|
34
|
-
sig { params(uri: URI::Generic,
|
35
|
-
def initialize(uri,
|
34
|
+
sig { params(uri: URI::Generic, dispatcher: Prism::Dispatcher, message_queue: Thread::Queue).void }
|
35
|
+
def initialize(uri, dispatcher, message_queue)
|
36
36
|
@uri = T.let(uri, URI::Generic)
|
37
37
|
@_response = T.let([], ResponseType)
|
38
38
|
@path = T.let(uri.to_standardized_path, T.nilable(String))
|
39
39
|
# visibility_stack is a stack of [current_visibility, previous_visibility]
|
40
|
-
@visibility_stack = T.let([[
|
40
|
+
@visibility_stack = T.let([[:public, :public]], T::Array[T::Array[T.nilable(Symbol)]])
|
41
41
|
@class_stack = T.let([], T::Array[String])
|
42
42
|
|
43
|
-
super(
|
43
|
+
super(dispatcher, message_queue)
|
44
44
|
|
45
|
-
|
45
|
+
dispatcher.register(
|
46
46
|
self,
|
47
|
-
:
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
47
|
+
:on_class_node_enter,
|
48
|
+
:on_class_node_leave,
|
49
|
+
:on_def_node_enter,
|
50
|
+
:on_call_node_enter,
|
51
|
+
:on_call_node_leave,
|
52
52
|
)
|
53
53
|
end
|
54
54
|
|
55
|
-
sig { params(node:
|
56
|
-
def
|
57
|
-
@visibility_stack.push([
|
55
|
+
sig { params(node: Prism::ClassNode).void }
|
56
|
+
def on_class_node_enter(node)
|
57
|
+
@visibility_stack.push([:public, :public])
|
58
58
|
class_name = node.constant_path.slice
|
59
59
|
@class_stack.push(class_name)
|
60
60
|
|
@@ -68,19 +68,19 @@ module RubyLsp
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
sig { params(node:
|
72
|
-
def
|
71
|
+
sig { params(node: Prism::ClassNode).void }
|
72
|
+
def on_class_node_leave(node)
|
73
73
|
@visibility_stack.pop
|
74
74
|
@class_stack.pop
|
75
75
|
end
|
76
76
|
|
77
|
-
sig { params(node:
|
78
|
-
def
|
77
|
+
sig { params(node: Prism::DefNode).void }
|
78
|
+
def on_def_node_enter(node)
|
79
79
|
class_name = @class_stack.last
|
80
80
|
return unless class_name&.end_with?("Test")
|
81
81
|
|
82
82
|
visibility, _ = @visibility_stack.last
|
83
|
-
if visibility ==
|
83
|
+
if visibility == :public
|
84
84
|
method_name = node.name.to_s
|
85
85
|
if @path && method_name.start_with?("test_")
|
86
86
|
add_test_code_lens(
|
@@ -93,8 +93,8 @@ module RubyLsp
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
sig { params(node:
|
97
|
-
def
|
96
|
+
sig { params(node: Prism::CallNode).void }
|
97
|
+
def on_call_node_enter(node)
|
98
98
|
name = node.name
|
99
99
|
arguments = node.arguments
|
100
100
|
|
@@ -103,7 +103,7 @@ module RubyLsp
|
|
103
103
|
if arguments.nil?
|
104
104
|
@visibility_stack.pop
|
105
105
|
@visibility_stack.push([name, name])
|
106
|
-
elsif arguments.arguments.first.is_a?(
|
106
|
+
elsif arguments.arguments.first.is_a?(Prism::DefNode)
|
107
107
|
visibility, _ = @visibility_stack.pop
|
108
108
|
@visibility_stack.push([name, visibility])
|
109
109
|
end
|
@@ -111,9 +111,9 @@ module RubyLsp
|
|
111
111
|
return
|
112
112
|
end
|
113
113
|
|
114
|
-
if @path&.include?("Gemfile") && name ==
|
114
|
+
if @path&.include?("Gemfile") && name == :gem && arguments
|
115
115
|
first_argument = arguments.arguments.first
|
116
|
-
return unless first_argument.is_a?(
|
116
|
+
return unless first_argument.is_a?(Prism::StringNode)
|
117
117
|
|
118
118
|
remote = resolve_gem_remote(first_argument)
|
119
119
|
return unless remote
|
@@ -122,15 +122,15 @@ module RubyLsp
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
-
sig { params(node:
|
126
|
-
def
|
125
|
+
sig { params(node: Prism::CallNode).void }
|
126
|
+
def on_call_node_leave(node)
|
127
127
|
_, prev_visibility = @visibility_stack.pop
|
128
128
|
@visibility_stack.push([prev_visibility, prev_visibility])
|
129
129
|
end
|
130
130
|
|
131
131
|
sig { override.params(addon: Addon).returns(T.nilable(Listener[ResponseType])) }
|
132
132
|
def initialize_external_listener(addon)
|
133
|
-
addon.create_code_lens_listener(@uri, @
|
133
|
+
addon.create_code_lens_listener(@uri, @dispatcher, @message_queue)
|
134
134
|
end
|
135
135
|
|
136
136
|
sig { override.params(other: Listener[ResponseType]).returns(T.self_type) }
|
@@ -141,7 +141,7 @@ module RubyLsp
|
|
141
141
|
|
142
142
|
private
|
143
143
|
|
144
|
-
sig { params(node:
|
144
|
+
sig { params(node: Prism::Node, name: String, command: String, kind: Symbol).void }
|
145
145
|
def add_test_code_lens(node, name:, command:, kind:)
|
146
146
|
# don't add code lenses if the test library is not supported or unknown
|
147
147
|
return unless SUPPORTED_TEST_LIBRARIES.include?(DependencyDetector.instance.detected_test_library) && @path
|
@@ -183,7 +183,7 @@ module RubyLsp
|
|
183
183
|
)
|
184
184
|
end
|
185
185
|
|
186
|
-
sig { params(gem_name:
|
186
|
+
sig { params(gem_name: Prism::StringNode).returns(T.nilable(String)) }
|
187
187
|
def resolve_gem_remote(gem_name)
|
188
188
|
spec = Gem::Specification.stubs.find { |gem| gem.name == gem_name.content }&.to_spec
|
189
189
|
return if spec.nil?
|
@@ -215,7 +215,7 @@ module RubyLsp
|
|
215
215
|
command
|
216
216
|
end
|
217
217
|
|
218
|
-
sig { params(node:
|
218
|
+
sig { params(node: Prism::CallNode, remote: String).void }
|
219
219
|
def add_open_gem_remote_code_lens(node, remote)
|
220
220
|
@_response << create_code_lens(
|
221
221
|
node,
|