ruby-lsp 0.4.4 → 0.5.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 +5 -86
- data/VERSION +1 -1
- data/exe/ruby-lsp +10 -1
- data/lib/ruby_lsp/check_docs.rb +112 -0
- data/lib/ruby_lsp/document.rb +13 -2
- data/lib/ruby_lsp/event_emitter.rb +86 -18
- data/lib/ruby_lsp/executor.rb +146 -45
- data/lib/ruby_lsp/extension.rb +104 -0
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listener.rb +14 -11
- data/lib/ruby_lsp/requests/base_request.rb +0 -5
- data/lib/ruby_lsp/requests/code_action_resolve.rb +1 -1
- data/lib/ruby_lsp/requests/code_actions.rb +1 -1
- data/lib/ruby_lsp/requests/code_lens.rb +82 -66
- data/lib/ruby_lsp/requests/diagnostics.rb +2 -2
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
- data/lib/ruby_lsp/requests/document_link.rb +17 -15
- data/lib/ruby_lsp/requests/document_symbol.rb +51 -31
- data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/formatting.rb +10 -11
- data/lib/ruby_lsp/requests/hover.rb +34 -19
- data/lib/ruby_lsp/requests/inlay_hints.rb +1 -1
- data/lib/ruby_lsp/requests/on_type_formatting.rb +5 -1
- data/lib/ruby_lsp/requests/path_completion.rb +21 -57
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +36 -0
- data/lib/ruby_lsp/requests/support/rubocop_diagnostics_runner.rb +0 -1
- data/lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb +0 -1
- data/lib/ruby_lsp/requests/support/syntax_tree_formatting_runner.rb +5 -2
- data/lib/ruby_lsp/requests.rb +15 -15
- data/lib/ruby_lsp/server.rb +44 -11
- data/lib/ruby_lsp/store.rb +1 -1
- data/lib/ruby_lsp/utils.rb +9 -8
- metadata +5 -3
data/lib/ruby_lsp/executor.rb
CHANGED
@@ -6,12 +6,12 @@ module RubyLsp
|
|
6
6
|
class Executor
|
7
7
|
extend T::Sig
|
8
8
|
|
9
|
-
sig { params(store: Store).void }
|
10
|
-
def initialize(store)
|
9
|
+
sig { params(store: Store, message_queue: Thread::Queue).void }
|
10
|
+
def initialize(store, message_queue)
|
11
11
|
# Requests that mutate the store must be run sequentially! Parallel requests only receive a temporary copy of the
|
12
12
|
# store
|
13
13
|
@store = store
|
14
|
-
@
|
14
|
+
@message_queue = message_queue
|
15
15
|
end
|
16
16
|
|
17
17
|
sig { params(request: T::Hash[Symbol, T.untyped]).returns(Result) }
|
@@ -25,7 +25,7 @@ module RubyLsp
|
|
25
25
|
error = e
|
26
26
|
end
|
27
27
|
|
28
|
-
Result.new(response: response, error: error, request_time: request_time
|
28
|
+
Result.new(response: response, error: error, request_time: request_time)
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
@@ -38,6 +38,24 @@ module RubyLsp
|
|
38
38
|
when "initialize"
|
39
39
|
initialize_request(request.dig(:params))
|
40
40
|
when "initialized"
|
41
|
+
Extension.load_extensions
|
42
|
+
|
43
|
+
errored_extensions = Extension.extensions.select(&:error?)
|
44
|
+
|
45
|
+
if errored_extensions.any?
|
46
|
+
@message_queue << Notification.new(
|
47
|
+
message: "window/showMessage",
|
48
|
+
params: Interface::ShowMessageParams.new(
|
49
|
+
type: Constant::MessageType::WARNING,
|
50
|
+
message: "Error loading extensions:\n\n#{errored_extensions.map(&:formatted_errors).join("\n\n")}",
|
51
|
+
),
|
52
|
+
)
|
53
|
+
|
54
|
+
warn(errored_extensions.map(&:backtraces).join("\n\n"))
|
55
|
+
end
|
56
|
+
|
57
|
+
check_formatter_is_available
|
58
|
+
|
41
59
|
warn("Ruby LSP is ready")
|
42
60
|
VOID
|
43
61
|
when "textDocument/didOpen"
|
@@ -47,7 +65,7 @@ module RubyLsp
|
|
47
65
|
request.dig(:params, :textDocument, :version),
|
48
66
|
)
|
49
67
|
when "textDocument/didClose"
|
50
|
-
@
|
68
|
+
@message_queue << Notification.new(
|
51
69
|
message: "textDocument/publishDiagnostics",
|
52
70
|
params: Interface::PublishDiagnosticsParams.new(uri: uri, diagnostics: []),
|
53
71
|
)
|
@@ -61,12 +79,33 @@ module RubyLsp
|
|
61
79
|
)
|
62
80
|
when "textDocument/foldingRange"
|
63
81
|
folding_range(uri)
|
64
|
-
when "textDocument/documentLink"
|
65
|
-
document_link(uri)
|
66
82
|
when "textDocument/selectionRange"
|
67
83
|
selection_range(uri, request.dig(:params, :positions))
|
68
|
-
when "textDocument/documentSymbol"
|
69
|
-
|
84
|
+
when "textDocument/documentSymbol", "textDocument/documentLink", "textDocument/codeLens"
|
85
|
+
document = @store.get(uri)
|
86
|
+
|
87
|
+
# If the response has already been cached by another request, return it
|
88
|
+
cached_response = document.cache_get(request[:method])
|
89
|
+
return cached_response if cached_response
|
90
|
+
|
91
|
+
# Run listeners for the document
|
92
|
+
emitter = EventEmitter.new
|
93
|
+
document_symbol = Requests::DocumentSymbol.new(emitter, @message_queue)
|
94
|
+
document_link = Requests::DocumentLink.new(uri, emitter, @message_queue)
|
95
|
+
code_lens = Requests::CodeLens.new(uri, emitter, @message_queue)
|
96
|
+
code_lens_extensions_listeners = Requests::CodeLens.listeners.map do |l|
|
97
|
+
T.unsafe(l).new(document.uri, emitter, @message_queue)
|
98
|
+
end
|
99
|
+
emitter.visit(document.tree) if document.parsed?
|
100
|
+
|
101
|
+
code_lens_extensions_listeners.each { |ext| code_lens.merge_response!(ext) }
|
102
|
+
|
103
|
+
# Store all responses retrieve in this round of visits in the cache and then return the response for the request
|
104
|
+
# we actually received
|
105
|
+
document.cache_set("textDocument/documentSymbol", document_symbol.response)
|
106
|
+
document.cache_set("textDocument/documentLink", document_link.response)
|
107
|
+
document.cache_set("textDocument/codeLens", code_lens.response)
|
108
|
+
document.cache_get(request[:method])
|
70
109
|
when "textDocument/semanticTokens/full"
|
71
110
|
semantic_tokens_full(uri)
|
72
111
|
when "textDocument/semanticTokens/range"
|
@@ -75,7 +114,7 @@ module RubyLsp
|
|
75
114
|
begin
|
76
115
|
formatting(uri)
|
77
116
|
rescue Requests::Formatting::InvalidFormatter => error
|
78
|
-
@
|
117
|
+
@message_queue << Notification.new(
|
79
118
|
message: "window/showMessage",
|
80
119
|
params: Interface::ShowMessageParams.new(
|
81
120
|
type: Constant::MessageType::ERROR,
|
@@ -85,7 +124,7 @@ module RubyLsp
|
|
85
124
|
|
86
125
|
nil
|
87
126
|
rescue StandardError => error
|
88
|
-
@
|
127
|
+
@message_queue << Notification.new(
|
89
128
|
message: "window/showMessage",
|
90
129
|
params: Interface::ShowMessageParams.new(
|
91
130
|
type: Constant::MessageType::ERROR,
|
@@ -111,7 +150,7 @@ module RubyLsp
|
|
111
150
|
begin
|
112
151
|
diagnostic(uri)
|
113
152
|
rescue StandardError => error
|
114
|
-
@
|
153
|
+
@message_queue << Notification.new(
|
115
154
|
message: "window/showMessage",
|
116
155
|
params: Interface::ShowMessageParams.new(
|
117
156
|
type: Constant::MessageType::ERROR,
|
@@ -123,25 +162,16 @@ module RubyLsp
|
|
123
162
|
end
|
124
163
|
when "textDocument/completion"
|
125
164
|
completion(uri, request.dig(:params, :position))
|
126
|
-
when "textDocument/codeLens"
|
127
|
-
code_lens(uri)
|
128
165
|
end
|
129
166
|
end
|
130
167
|
|
131
168
|
sig { params(uri: String).returns(T::Array[Interface::FoldingRange]) }
|
132
169
|
def folding_range(uri)
|
133
|
-
@store.cache_fetch(uri,
|
170
|
+
@store.cache_fetch(uri, "textDocument/foldingRange") do |document|
|
134
171
|
Requests::FoldingRanges.new(document).run
|
135
172
|
end
|
136
173
|
end
|
137
174
|
|
138
|
-
sig { params(uri: String).returns(T::Array[Interface::CodeLens]) }
|
139
|
-
def code_lens(uri)
|
140
|
-
@store.cache_fetch(uri, :code_lens) do |document|
|
141
|
-
Requests::CodeLens.new(document).run
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
175
|
sig do
|
146
176
|
params(
|
147
177
|
uri: String,
|
@@ -150,7 +180,6 @@ module RubyLsp
|
|
150
180
|
end
|
151
181
|
def hover(uri, position)
|
152
182
|
document = @store.get(uri)
|
153
|
-
document.parse
|
154
183
|
return if document.syntax_error?
|
155
184
|
|
156
185
|
target, parent = document.locate_node(position)
|
@@ -160,23 +189,17 @@ module RubyLsp
|
|
160
189
|
target = parent
|
161
190
|
end
|
162
191
|
|
163
|
-
|
164
|
-
EventEmitter.new
|
165
|
-
|
166
|
-
|
192
|
+
# Instantiate all listeners
|
193
|
+
emitter = EventEmitter.new
|
194
|
+
base_listener = Requests::Hover.new(emitter, @message_queue)
|
195
|
+
listeners = Requests::Hover.listeners.map { |l| l.new(emitter, @message_queue) }
|
167
196
|
|
168
|
-
|
169
|
-
|
170
|
-
@store.cache_fetch(uri, :document_link) do |document|
|
171
|
-
RubyLsp::Requests::DocumentLink.new(document).run
|
172
|
-
end
|
173
|
-
end
|
197
|
+
# Emit events for all listeners
|
198
|
+
emitter.emit_for_target(target)
|
174
199
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
Requests::DocumentSymbol.new(document).run
|
179
|
-
end
|
200
|
+
# Merge all responses into a single hover
|
201
|
+
listeners.each { |ext| base_listener.merge_response!(ext) }
|
202
|
+
base_listener.response
|
180
203
|
end
|
181
204
|
|
182
205
|
sig { params(uri: String, content_changes: T::Array[Document::EditShape], version: Integer).returns(Object) }
|
@@ -204,7 +227,7 @@ module RubyLsp
|
|
204
227
|
).returns(T.nilable(T::Array[T.nilable(Requests::Support::SelectionRange)]))
|
205
228
|
end
|
206
229
|
def selection_range(uri, positions)
|
207
|
-
ranges = @store.cache_fetch(uri,
|
230
|
+
ranges = @store.cache_fetch(uri, "textDocument/selectionRange") do |document|
|
208
231
|
Requests::SelectionRanges.new(document).run
|
209
232
|
end
|
210
233
|
|
@@ -224,7 +247,7 @@ module RubyLsp
|
|
224
247
|
|
225
248
|
sig { params(uri: String).returns(Interface::SemanticTokens) }
|
226
249
|
def semantic_tokens_full(uri)
|
227
|
-
@store.cache_fetch(uri,
|
250
|
+
@store.cache_fetch(uri, "textDocument/semanticTokens/full") do |document|
|
228
251
|
T.cast(
|
229
252
|
Requests::SemanticHighlighting.new(
|
230
253
|
document,
|
@@ -237,6 +260,9 @@ module RubyLsp
|
|
237
260
|
|
238
261
|
sig { params(uri: String).returns(T.nilable(T::Array[Interface::TextEdit])) }
|
239
262
|
def formatting(uri)
|
263
|
+
# If formatter is set to `auto` but no supported formatting gem is found, don't attempt to format
|
264
|
+
return if @store.formatter == "none"
|
265
|
+
|
240
266
|
Requests::Formatting.new(@store.get(uri), formatter: @store.formatter).run
|
241
267
|
end
|
242
268
|
|
@@ -291,7 +317,7 @@ module RubyLsp
|
|
291
317
|
|
292
318
|
case result
|
293
319
|
when Requests::CodeActionResolve::Error::EmptySelection
|
294
|
-
@
|
320
|
+
@message_queue << Notification.new(
|
295
321
|
message: "window/showMessage",
|
296
322
|
params: Interface::ShowMessageParams.new(
|
297
323
|
type: Constant::MessageType::ERROR,
|
@@ -300,7 +326,7 @@ module RubyLsp
|
|
300
326
|
)
|
301
327
|
raise Requests::CodeActionResolve::CodeActionError
|
302
328
|
when Requests::CodeActionResolve::Error::InvalidTargetRange
|
303
|
-
@
|
329
|
+
@message_queue << Notification.new(
|
304
330
|
message: "window/showMessage",
|
305
331
|
params: Interface::ShowMessageParams.new(
|
306
332
|
type: Constant::MessageType::ERROR,
|
@@ -315,7 +341,7 @@ module RubyLsp
|
|
315
341
|
|
316
342
|
sig { params(uri: String).returns(T.nilable(Interface::FullDocumentDiagnosticReport)) }
|
317
343
|
def diagnostic(uri)
|
318
|
-
response = @store.cache_fetch(uri,
|
344
|
+
response = @store.cache_fetch(uri, "textDocument/diagnostic") do |document|
|
319
345
|
Requests::Diagnostics.new(document).run
|
320
346
|
end
|
321
347
|
|
@@ -342,7 +368,44 @@ module RubyLsp
|
|
342
368
|
params(uri: String, position: Document::PositionShape).returns(T.nilable(T::Array[Interface::CompletionItem]))
|
343
369
|
end
|
344
370
|
def completion(uri, position)
|
345
|
-
|
371
|
+
document = @store.get(uri)
|
372
|
+
return unless document.parsed?
|
373
|
+
|
374
|
+
char_position = document.create_scanner.find_char_position(position)
|
375
|
+
matched, parent = document.locate(
|
376
|
+
T.must(document.tree),
|
377
|
+
char_position,
|
378
|
+
node_types: [SyntaxTree::Command, SyntaxTree::CommandCall, SyntaxTree::CallNode],
|
379
|
+
)
|
380
|
+
|
381
|
+
return unless matched && parent
|
382
|
+
|
383
|
+
target = case matched
|
384
|
+
when SyntaxTree::Command, SyntaxTree::CallNode, SyntaxTree::CommandCall
|
385
|
+
message = matched.message
|
386
|
+
return if message.is_a?(Symbol)
|
387
|
+
return unless message.value == "require"
|
388
|
+
|
389
|
+
args = matched.arguments
|
390
|
+
args = args.arguments if args.is_a?(SyntaxTree::ArgParen)
|
391
|
+
return if args.nil? || args.is_a?(SyntaxTree::ArgsForward)
|
392
|
+
|
393
|
+
argument = args.parts.first
|
394
|
+
return unless argument.is_a?(SyntaxTree::StringLiteral)
|
395
|
+
|
396
|
+
path_node = argument.parts.first
|
397
|
+
return unless path_node.is_a?(SyntaxTree::TStringContent)
|
398
|
+
return unless (path_node.location.start_char..path_node.location.end_char).cover?(char_position)
|
399
|
+
|
400
|
+
path_node
|
401
|
+
end
|
402
|
+
|
403
|
+
return unless target
|
404
|
+
|
405
|
+
emitter = EventEmitter.new
|
406
|
+
listener = Requests::PathCompletion.new(emitter, @message_queue)
|
407
|
+
emitter.emit_for_target(target)
|
408
|
+
listener.response
|
346
409
|
end
|
347
410
|
|
348
411
|
sig { params(options: T::Hash[Symbol, T.untyped]).returns(Interface::InitializeResult) }
|
@@ -359,7 +422,11 @@ module RubyLsp
|
|
359
422
|
end
|
360
423
|
|
361
424
|
formatter = options.dig(:initializationOptions, :formatter)
|
362
|
-
@store.formatter = formatter
|
425
|
+
@store.formatter = if formatter == "auto"
|
426
|
+
detected_formatter
|
427
|
+
else
|
428
|
+
formatter
|
429
|
+
end
|
363
430
|
|
364
431
|
configured_features = options.dig(:initializationOptions, :enabledFeatures)
|
365
432
|
experimental_features = options.dig(:initializationOptions, :experimentalFeaturesEnabled)
|
@@ -468,5 +535,39 @@ module RubyLsp
|
|
468
535
|
),
|
469
536
|
)
|
470
537
|
end
|
538
|
+
|
539
|
+
sig { returns(String) }
|
540
|
+
def detected_formatter
|
541
|
+
# NOTE: Intentionally no $ at end, since we want to match rubocop-shopify, etc.
|
542
|
+
if direct_dependency?(/^rubocop/)
|
543
|
+
"rubocop"
|
544
|
+
elsif direct_dependency?(/^syntax_tree$/)
|
545
|
+
"syntax_tree"
|
546
|
+
else
|
547
|
+
"none"
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
sig { params(gem_pattern: Regexp).returns(T::Boolean) }
|
552
|
+
def direct_dependency?(gem_pattern)
|
553
|
+
Bundler.locked_gems.dependencies.keys.grep(gem_pattern).any?
|
554
|
+
end
|
555
|
+
|
556
|
+
sig { void }
|
557
|
+
def check_formatter_is_available
|
558
|
+
# Warn of an unavailable `formatter` setting, e.g. `rubocop` on a project which doesn't have RuboCop.
|
559
|
+
# Syntax Tree will always be available via Ruby LSP so we don't need to check for it.
|
560
|
+
return unless @store.formatter == "rubocop"
|
561
|
+
|
562
|
+
unless defined?(RubyLsp::Requests::Support::RuboCopRunner)
|
563
|
+
@message_queue << Notification.new(
|
564
|
+
message: "window/showMessage",
|
565
|
+
params: Interface::ShowMessageParams.new(
|
566
|
+
type: Constant::MessageType::ERROR,
|
567
|
+
message: "Ruby LSP formatter is set to `rubocop` but RuboCop was not found in the bundle.",
|
568
|
+
),
|
569
|
+
)
|
570
|
+
end
|
571
|
+
end
|
471
572
|
end
|
472
573
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
# To register an extension, inherit from this class and implement both `name` and `activate`
|
6
|
+
#
|
7
|
+
# # Example
|
8
|
+
#
|
9
|
+
# ```ruby
|
10
|
+
# module MyGem
|
11
|
+
# class MyExtension < Extension
|
12
|
+
# def activate
|
13
|
+
# # Perform any relevant initialization
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# def name
|
17
|
+
# "My extension name"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# ```
|
22
|
+
class Extension
|
23
|
+
extend T::Sig
|
24
|
+
extend T::Helpers
|
25
|
+
|
26
|
+
abstract!
|
27
|
+
|
28
|
+
class << self
|
29
|
+
extend T::Sig
|
30
|
+
|
31
|
+
# Automatically track and instantiate extension classes
|
32
|
+
sig { params(child_class: T.class_of(Extension)).void }
|
33
|
+
def inherited(child_class)
|
34
|
+
extensions << child_class.new
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
sig { returns(T::Array[Extension]) }
|
39
|
+
def extensions
|
40
|
+
@extensions ||= T.let([], T.nilable(T::Array[Extension]))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Discovers and loads all extensions. Returns the list of activated extensions
|
44
|
+
sig { returns(T::Array[Extension]) }
|
45
|
+
def load_extensions
|
46
|
+
# Require all extensions entry points, which should be placed under
|
47
|
+
# `some_gem/lib/ruby_lsp/your_gem_name/extension.rb`
|
48
|
+
Gem.find_files("ruby_lsp/**/extension.rb").each do |extension|
|
49
|
+
require File.expand_path(extension)
|
50
|
+
rescue => e
|
51
|
+
warn(e.message)
|
52
|
+
warn(e.backtrace.to_s) # rubocop:disable Lint/RedundantStringCoercion
|
53
|
+
end
|
54
|
+
|
55
|
+
# Activate each one of the discovered extensions. If any problems occur in the extensions, we don't want to
|
56
|
+
# fail to boot the server
|
57
|
+
extensions.each do |extension|
|
58
|
+
extension.activate
|
59
|
+
nil
|
60
|
+
rescue => e
|
61
|
+
extension.add_error(e)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
sig { void }
|
67
|
+
def initialize
|
68
|
+
@errors = T.let([], T::Array[StandardError])
|
69
|
+
end
|
70
|
+
|
71
|
+
sig { params(error: StandardError).returns(T.self_type) }
|
72
|
+
def add_error(error)
|
73
|
+
@errors << error
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
sig { returns(T::Boolean) }
|
78
|
+
def error?
|
79
|
+
@errors.any?
|
80
|
+
end
|
81
|
+
|
82
|
+
sig { returns(String) }
|
83
|
+
def formatted_errors
|
84
|
+
<<~ERRORS
|
85
|
+
#{name}:
|
86
|
+
#{@errors.map(&:message).join("\n")}
|
87
|
+
ERRORS
|
88
|
+
end
|
89
|
+
|
90
|
+
sig { returns(String) }
|
91
|
+
def backtraces
|
92
|
+
@errors.filter_map(&:backtrace).join("\n\n")
|
93
|
+
end
|
94
|
+
|
95
|
+
# Each extension should implement `MyExtension#activate` and use to perform any sort of initialization, such as
|
96
|
+
# reading information into memory or even spawning a separate process
|
97
|
+
sig { abstract.void }
|
98
|
+
def activate; end
|
99
|
+
|
100
|
+
# Extensions should override the `name` method to return the extension name
|
101
|
+
sig { abstract.returns(String) }
|
102
|
+
def name; end
|
103
|
+
end
|
104
|
+
end
|
data/lib/ruby_lsp/internal.rb
CHANGED
data/lib/ruby_lsp/listener.rb
CHANGED
@@ -14,20 +14,23 @@ module RubyLsp
|
|
14
14
|
|
15
15
|
abstract!
|
16
16
|
|
17
|
+
sig { params(emitter: EventEmitter, message_queue: Thread::Queue).void }
|
18
|
+
def initialize(emitter, message_queue)
|
19
|
+
@emitter = emitter
|
20
|
+
@message_queue = message_queue
|
21
|
+
end
|
22
|
+
|
17
23
|
class << self
|
18
24
|
extend T::Sig
|
19
25
|
|
20
|
-
sig { returns(T
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
current_methods = instance_methods
|
29
|
-
block.call
|
30
|
-
@events = T.let(instance_methods - current_methods, T.nilable(T::Array[Symbol]))
|
26
|
+
sig { returns(T::Array[T.class_of(Listener)]) }
|
27
|
+
def listeners
|
28
|
+
@listeners ||= T.let([], T.nilable(T::Array[T.class_of(Listener)]))
|
29
|
+
end
|
30
|
+
|
31
|
+
sig { params(listener: T.class_of(Listener)).void }
|
32
|
+
def add_listener(listener)
|
33
|
+
listeners << listener
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
@@ -18,11 +18,6 @@ module RubyLsp
|
|
18
18
|
sig { params(document: Document, _kwargs: T.untyped).void }
|
19
19
|
def initialize(document, **_kwargs)
|
20
20
|
@document = document
|
21
|
-
|
22
|
-
# Parsing the document here means we're taking a lazy approach by only doing it when the first feature request
|
23
|
-
# is received by the server. This happens because {Document#parse} remembers if there are new edits to be parsed
|
24
|
-
@document.parse
|
25
|
-
|
26
21
|
super()
|
27
22
|
end
|
28
23
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
|
-
# 
|
7
7
|
#
|
8
8
|
# The [code action resolve](https://microsoft.github.io/language-server-protocol/specification#codeAction_resolve)
|
9
9
|
# request is used to to resolve the edit field for a given code action, if it is not already provided in the
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
|
-
# 
|
7
7
|
#
|
8
8
|
# The [code actions](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction)
|
9
9
|
# request informs the editor of RuboCop quick fixes that can be applied. These are accessible by hovering over a
|