ruby-lsp 0.23.21 → 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/VERSION +1 -1
- data/exe/ruby-lsp +10 -4
- data/exe/ruby-lsp-check +0 -4
- data/exe/ruby-lsp-launcher +25 -11
- data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +7 -1
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -4
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +9 -19
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +18 -7
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +2 -2
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
- data/lib/ruby_indexer/test/configuration_test.rb +1 -1
- data/lib/ruby_indexer/test/index_test.rb +24 -0
- data/lib/ruby_indexer/test/instance_variables_test.rb +24 -0
- data/lib/ruby_indexer/test/method_test.rb +17 -0
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +2 -2
- data/lib/ruby_indexer/test/reference_finder_test.rb +79 -14
- data/lib/ruby_lsp/addon.rb +29 -15
- data/lib/ruby_lsp/base_server.rb +14 -12
- data/lib/ruby_lsp/document.rb +158 -46
- data/lib/ruby_lsp/erb_document.rb +8 -3
- data/lib/ruby_lsp/global_state.rb +21 -0
- data/lib/ruby_lsp/internal.rb +0 -2
- data/lib/ruby_lsp/listeners/completion.rb +9 -1
- data/lib/ruby_lsp/listeners/hover.rb +7 -0
- data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
- data/lib/ruby_lsp/listeners/spec_style.rb +63 -20
- data/lib/ruby_lsp/listeners/test_discovery.rb +18 -15
- data/lib/ruby_lsp/listeners/test_style.rb +21 -10
- data/lib/ruby_lsp/requests/code_action_resolve.rb +3 -3
- data/lib/ruby_lsp/requests/code_lens.rb +14 -5
- data/lib/ruby_lsp/requests/completion.rb +1 -1
- data/lib/ruby_lsp/requests/definition.rb +1 -1
- data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/inlay_hints.rb +3 -3
- data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
- data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +10 -6
- data/lib/ruby_lsp/requests/rename.rb +8 -6
- data/lib/ruby_lsp/requests/request.rb +6 -7
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -1
- data/lib/ruby_lsp/requests/signature_help.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +1 -3
- data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +9 -3
- data/lib/ruby_lsp/response_builders/response_builder.rb +6 -8
- data/lib/ruby_lsp/ruby_document.rb +10 -5
- data/lib/ruby_lsp/server.rb +50 -49
- data/lib/ruby_lsp/setup_bundler.rb +51 -25
- data/lib/ruby_lsp/static_docs.rb +1 -0
- data/lib/ruby_lsp/store.rb +0 -10
- data/lib/ruby_lsp/test_helper.rb +1 -4
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +13 -5
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +43 -4
- data/lib/ruby_lsp/utils.rb +47 -11
- data/static_docs/break.md +103 -0
- metadata +4 -18
- data/lib/ruby_lsp/load_sorbet.rb +0 -62
data/lib/ruby_lsp/addon.rb
CHANGED
@@ -19,12 +19,8 @@ module RubyLsp
|
|
19
19
|
# end
|
20
20
|
# end
|
21
21
|
# ```
|
22
|
+
# @abstract
|
22
23
|
class Addon
|
23
|
-
extend T::Sig
|
24
|
-
extend T::Helpers
|
25
|
-
|
26
|
-
abstract!
|
27
|
-
|
28
24
|
@addons = [] #: Array[Addon]
|
29
25
|
@addon_classes = [] #: Array[singleton(Addon)]
|
30
26
|
# Add-on instances that have declared a handler to accept file watcher events
|
@@ -60,7 +56,13 @@ module RubyLsp
|
|
60
56
|
addon_files = Gem.find_files("ruby_lsp/**/addon.rb")
|
61
57
|
|
62
58
|
if include_project_addons
|
63
|
-
|
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)
|
64
66
|
end
|
65
67
|
|
66
68
|
errors = addon_files.filter_map do |addon_path|
|
@@ -178,22 +180,34 @@ module RubyLsp
|
|
178
180
|
|
179
181
|
# Each add-on should implement `MyAddon#activate` and use to perform any sort of initialization, such as
|
180
182
|
# reading information into memory or even spawning a separate process
|
181
|
-
|
182
|
-
|
183
|
+
# @abstract
|
184
|
+
#: (GlobalState, Thread::Queue) -> void
|
185
|
+
def activate(global_state, outgoing_queue)
|
186
|
+
raise AbstractMethodInvokedError
|
187
|
+
end
|
183
188
|
|
184
|
-
# Each add-on
|
189
|
+
# Each add-on must implement `MyAddon#deactivate` and use to perform any clean up, like shutting down a
|
185
190
|
# child process
|
186
|
-
|
187
|
-
|
191
|
+
# @abstract
|
192
|
+
#: -> void
|
193
|
+
def deactivate
|
194
|
+
raise AbstractMethodInvokedError
|
195
|
+
end
|
188
196
|
|
189
197
|
# Add-ons should override the `name` method to return the add-on name
|
190
|
-
|
191
|
-
|
198
|
+
# @abstract
|
199
|
+
#: -> String
|
200
|
+
def name
|
201
|
+
raise AbstractMethodInvokedError
|
202
|
+
end
|
192
203
|
|
193
204
|
# Add-ons should override the `version` method to return a semantic version string representing the add-on's
|
194
205
|
# version. This is used for compatibility checks
|
195
|
-
|
196
|
-
|
206
|
+
# @abstract
|
207
|
+
#: -> String
|
208
|
+
def version
|
209
|
+
raise AbstractMethodInvokedError
|
210
|
+
end
|
197
211
|
|
198
212
|
# Handle a response from a window/showMessageRequest request. Add-ons must include the addon_name as part of the
|
199
213
|
# original request so that the response is delegated to the correct add-on and must override this method to handle
|
data/lib/ruby_lsp/base_server.rb
CHANGED
@@ -2,19 +2,15 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
+
# @abstract
|
5
6
|
class BaseServer
|
6
|
-
extend T::Sig
|
7
|
-
extend T::Helpers
|
8
|
-
|
9
|
-
abstract!
|
10
|
-
|
11
7
|
#: (**untyped options) -> void
|
12
8
|
def initialize(**options)
|
9
|
+
@reader = MessageReader.new(options[:reader] || $stdin) #: MessageReader
|
10
|
+
@writer = MessageWriter.new(options[:writer] || $stdout) #: MessageWriter
|
13
11
|
@test_mode = options[:test_mode] #: bool?
|
14
12
|
@setup_error = options[:setup_error] #: StandardError?
|
15
13
|
@install_error = options[:install_error] #: StandardError?
|
16
|
-
@writer = Transport::Stdio::Writer.new #: Transport::Stdio::Writer
|
17
|
-
@reader = Transport::Stdio::Reader.new #: Transport::Stdio::Reader
|
18
14
|
@incoming_queue = Thread::Queue.new #: Thread::Queue
|
19
15
|
@outgoing_queue = Thread::Queue.new #: Thread::Queue
|
20
16
|
@cancelled_requests = [] #: Array[Integer]
|
@@ -40,7 +36,7 @@ module RubyLsp
|
|
40
36
|
|
41
37
|
#: -> void
|
42
38
|
def start
|
43
|
-
@reader.
|
39
|
+
@reader.each_message do |message|
|
44
40
|
method = message[:method]
|
45
41
|
|
46
42
|
# We must parse the document under a mutex lock or else we might switch threads and accept text edits in the
|
@@ -130,11 +126,17 @@ module RubyLsp
|
|
130
126
|
@incoming_queue << message
|
131
127
|
end
|
132
128
|
|
133
|
-
|
134
|
-
|
129
|
+
# @abstract
|
130
|
+
#: (Hash[Symbol, untyped] message) -> void
|
131
|
+
def process_message(message)
|
132
|
+
raise AbstractMethodInvokedError
|
133
|
+
end
|
135
134
|
|
136
|
-
|
137
|
-
|
135
|
+
# @abstract
|
136
|
+
#: -> void
|
137
|
+
def shutdown
|
138
|
+
raise AbstractMethodInvokedError
|
139
|
+
end
|
138
140
|
|
139
141
|
#: (Integer id, String message, ?type: Integer) -> void
|
140
142
|
def fail_request_and_notify(id, message, type: Constant::MessageType::INFO)
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -2,21 +2,16 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
+
# @abstract
|
5
6
|
#: [ParseResultType]
|
6
7
|
class Document
|
7
|
-
|
8
|
-
extend T::Helpers
|
9
|
-
extend T::Generic
|
10
|
-
|
11
|
-
class LocationNotFoundError < StandardError; end
|
8
|
+
class InvalidLocationError < StandardError; end
|
12
9
|
|
13
10
|
# This maximum number of characters for providing expensive features, like semantic highlighting and diagnostics.
|
14
11
|
# This is the same number used by the TypeScript extension in VS Code
|
15
12
|
MAXIMUM_CHARACTERS_FOR_EXPENSIVE_FEATURES = 100_000
|
16
13
|
EMPTY_CACHE = Object.new.freeze #: Object
|
17
14
|
|
18
|
-
abstract!
|
19
|
-
|
20
15
|
#: ParseResultType
|
21
16
|
attr_reader :parse_result
|
22
17
|
|
@@ -63,8 +58,11 @@ module RubyLsp
|
|
63
58
|
self.class == other.class && uri == other.uri && @source == other.source
|
64
59
|
end
|
65
60
|
|
66
|
-
|
67
|
-
|
61
|
+
# @abstract
|
62
|
+
#: -> Symbol
|
63
|
+
def language_id
|
64
|
+
raise AbstractMethodInvokedError
|
65
|
+
end
|
68
66
|
|
69
67
|
#: [T] (String request_name) { (Document[ParseResultType] document) -> T } -> T
|
70
68
|
def cache_fetch(request_name, &block)
|
@@ -122,11 +120,17 @@ module RubyLsp
|
|
122
120
|
end
|
123
121
|
|
124
122
|
# Returns `true` if the document was parsed and `false` if nothing needed parsing
|
125
|
-
|
126
|
-
|
123
|
+
# @abstract
|
124
|
+
#: -> bool
|
125
|
+
def parse!
|
126
|
+
raise AbstractMethodInvokedError
|
127
|
+
end
|
127
128
|
|
128
|
-
|
129
|
-
|
129
|
+
# @abstract
|
130
|
+
#: -> bool
|
131
|
+
def syntax_error?
|
132
|
+
raise AbstractMethodInvokedError
|
133
|
+
end
|
130
134
|
|
131
135
|
#: -> bool
|
132
136
|
def past_expensive_limit?
|
@@ -147,15 +151,18 @@ module RubyLsp
|
|
147
151
|
|
148
152
|
#: -> Scanner
|
149
153
|
def create_scanner
|
150
|
-
|
154
|
+
case @encoding
|
155
|
+
when Encoding::UTF_8
|
156
|
+
Utf8Scanner.new(@source)
|
157
|
+
when Encoding::UTF_16LE
|
158
|
+
Utf16Scanner.new(@source)
|
159
|
+
else
|
160
|
+
Utf32Scanner.new(@source)
|
161
|
+
end
|
151
162
|
end
|
152
163
|
|
164
|
+
# @abstract
|
153
165
|
class Edit
|
154
|
-
extend T::Sig
|
155
|
-
extend T::Helpers
|
156
|
-
|
157
|
-
abstract!
|
158
|
-
|
159
166
|
#: Hash[Symbol, untyped]
|
160
167
|
attr_reader :range
|
161
168
|
|
@@ -169,33 +176,114 @@ module RubyLsp
|
|
169
176
|
class Replace < Edit; end
|
170
177
|
class Delete < Edit; end
|
171
178
|
|
179
|
+
# Parent class for all position scanners. Scanners are used to translate a position given by the editor into a
|
180
|
+
# string index that we can use to find the right place in the document source. The logic for finding the correct
|
181
|
+
# index depends on the encoding negotiated with the editor, so we have different subclasses for each encoding.
|
182
|
+
# See https://microsoft.github.io/language-server-protocol/specification/#positionEncodingKind for more information
|
183
|
+
# @abstract
|
172
184
|
class Scanner
|
173
|
-
extend T::Sig
|
174
|
-
|
175
185
|
LINE_BREAK = 0x0A #: Integer
|
176
186
|
# After character 0xFFFF, UTF-16 considers characters to have length 2 and we have to account for that
|
177
187
|
SURROGATE_PAIR_START = 0xFFFF #: Integer
|
178
188
|
|
179
|
-
#:
|
180
|
-
def initialize
|
189
|
+
#: -> void
|
190
|
+
def initialize
|
181
191
|
@current_line = 0 #: Integer
|
182
192
|
@pos = 0 #: Integer
|
183
|
-
@source = source.codepoints #: Array[Integer]
|
184
|
-
@encoding = encoding
|
185
193
|
end
|
186
194
|
|
187
|
-
# Finds the character index inside the source string for a given line and column
|
195
|
+
# Finds the character index inside the source string for a given line and column. This method always returns the
|
196
|
+
# character index regardless of whether we are searching positions based on bytes, code units, or codepoints.
|
197
|
+
# @abstract
|
198
|
+
#: (Hash[Symbol, untyped] position) -> Integer
|
199
|
+
def find_char_position(position)
|
200
|
+
raise AbstractMethodInvokedError
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# For the UTF-8 encoding, positions correspond to bytes
|
205
|
+
class Utf8Scanner < Scanner
|
206
|
+
#: (String source) -> void
|
207
|
+
def initialize(source)
|
208
|
+
super()
|
209
|
+
@bytes = source.bytes #: Array[Integer]
|
210
|
+
@character_length = 0 #: Integer
|
211
|
+
end
|
212
|
+
|
213
|
+
# @override
|
214
|
+
#: (Hash[Symbol, untyped] position) -> Integer
|
215
|
+
def find_char_position(position)
|
216
|
+
# Each group of bytes is a character. We advance based on the number of bytes to count how many full characters
|
217
|
+
# we have in the requested offset
|
218
|
+
until @current_line == position[:line]
|
219
|
+
byte = @bytes[@pos] #: Integer?
|
220
|
+
raise InvalidLocationError unless byte
|
221
|
+
|
222
|
+
until LINE_BREAK == byte
|
223
|
+
@pos += character_byte_length(byte)
|
224
|
+
@character_length += 1
|
225
|
+
byte = @bytes[@pos]
|
226
|
+
raise InvalidLocationError unless byte
|
227
|
+
end
|
228
|
+
|
229
|
+
@pos += 1
|
230
|
+
@character_length += 1
|
231
|
+
@current_line += 1
|
232
|
+
end
|
233
|
+
|
234
|
+
# @character_length has the number of characters until the beginning of the line. We don't accumulate on it for
|
235
|
+
# the character part because locating the same position twice must return the same value
|
236
|
+
line_byte_offset = 0
|
237
|
+
line_characters = 0
|
238
|
+
|
239
|
+
while line_byte_offset < position[:character]
|
240
|
+
byte = @bytes[@pos + line_byte_offset] #: Integer?
|
241
|
+
raise InvalidLocationError unless byte
|
242
|
+
|
243
|
+
line_byte_offset += character_byte_length(byte)
|
244
|
+
line_characters += 1
|
245
|
+
end
|
246
|
+
|
247
|
+
@character_length + line_characters
|
248
|
+
end
|
249
|
+
|
250
|
+
private
|
251
|
+
|
252
|
+
#: (Integer) -> Integer
|
253
|
+
def character_byte_length(byte)
|
254
|
+
if byte < 0x80 # 1-byte character
|
255
|
+
1
|
256
|
+
elsif byte < 0xE0 # 2-byte character
|
257
|
+
2
|
258
|
+
elsif byte < 0xF0 # 3-byte character
|
259
|
+
3
|
260
|
+
else # 4-byte character
|
261
|
+
4
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# For the UTF-16 encoding, positions correspond to UTF-16 code units, which count characters beyond the surrogate
|
267
|
+
# pair as length 2
|
268
|
+
class Utf16Scanner < Scanner
|
269
|
+
#: (String) -> void
|
270
|
+
def initialize(source)
|
271
|
+
super()
|
272
|
+
@codepoints = source.codepoints #: Array[Integer]
|
273
|
+
end
|
274
|
+
|
275
|
+
# @override
|
188
276
|
#: (Hash[Symbol, untyped] position) -> Integer
|
189
277
|
def find_char_position(position)
|
190
278
|
# Find the character index for the beginning of the requested line
|
191
279
|
until @current_line == position[:line]
|
192
|
-
|
193
|
-
|
280
|
+
codepoint = @codepoints[@pos] #: Integer?
|
281
|
+
raise InvalidLocationError unless codepoint
|
194
282
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
283
|
+
until LINE_BREAK == @codepoints[@pos]
|
284
|
+
@pos += 1
|
285
|
+
codepoint = @codepoints[@pos] #: Integer?
|
286
|
+
raise InvalidLocationError unless codepoint
|
199
287
|
end
|
200
288
|
|
201
289
|
@pos += 1
|
@@ -204,29 +292,53 @@ module RubyLsp
|
|
204
292
|
|
205
293
|
# The final position is the beginning of the line plus the requested column. If the encoding is UTF-16, we also
|
206
294
|
# need to adjust for surrogate pairs
|
207
|
-
|
295
|
+
line_characters = 0
|
296
|
+
line_code_units = 0
|
208
297
|
|
209
|
-
|
210
|
-
|
298
|
+
while line_code_units < position[:character]
|
299
|
+
code_point = @codepoints[@pos + line_characters]
|
300
|
+
raise InvalidLocationError unless code_point
|
301
|
+
|
302
|
+
line_code_units += if code_point > SURROGATE_PAIR_START
|
303
|
+
2 # Surrogate pair, so we skip the next code unit
|
304
|
+
else
|
305
|
+
1 # Single code unit character
|
306
|
+
end
|
307
|
+
|
308
|
+
line_characters += 1
|
211
309
|
end
|
212
310
|
|
213
|
-
|
311
|
+
@pos + line_characters
|
214
312
|
end
|
313
|
+
end
|
215
314
|
|
216
|
-
|
217
|
-
|
218
|
-
#: (
|
219
|
-
def
|
220
|
-
|
315
|
+
# For the UTF-32 encoding, positions correspond directly to codepoints
|
316
|
+
class Utf32Scanner < Scanner
|
317
|
+
#: (String) -> void
|
318
|
+
def initialize(source)
|
319
|
+
super()
|
320
|
+
@codepoints = source.codepoints #: Array[Integer]
|
321
|
+
end
|
322
|
+
|
323
|
+
# @override
|
324
|
+
#: (Hash[Symbol, untyped] position) -> Integer
|
325
|
+
def find_char_position(position)
|
326
|
+
# Find the character index for the beginning of the requested line
|
327
|
+
until @current_line == position[:line]
|
328
|
+
codepoint = @codepoints[@pos] #: Integer?
|
329
|
+
raise InvalidLocationError unless codepoint
|
221
330
|
|
222
|
-
|
223
|
-
|
224
|
-
|
331
|
+
until LINE_BREAK == @codepoints[@pos]
|
332
|
+
@pos += 1
|
333
|
+
codepoint = @codepoints[@pos] #: Integer?
|
334
|
+
raise InvalidLocationError unless codepoint
|
335
|
+
end
|
225
336
|
|
226
|
-
|
337
|
+
@pos += 1
|
338
|
+
@current_line += 1
|
227
339
|
end
|
228
340
|
|
229
|
-
|
341
|
+
@pos + position[:character]
|
230
342
|
end
|
231
343
|
end
|
232
344
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
-
#: [ParseResultType = Prism::
|
5
|
+
#: [ParseResultType = Prism::ParseLexResult]
|
6
6
|
class ERBDocument < Document
|
7
7
|
#: String
|
8
8
|
attr_reader :host_language_source
|
@@ -31,11 +31,16 @@ module RubyLsp
|
|
31
31
|
@host_language_source = scanner.host_language
|
32
32
|
# Use partial script to avoid syntax errors in ERB files where keywords may be used without the full context in
|
33
33
|
# which they will be evaluated
|
34
|
-
@parse_result = Prism.
|
34
|
+
@parse_result = Prism.parse_lex(scanner.ruby, partial_script: true)
|
35
35
|
@code_units_cache = @parse_result.code_units_cache(@encoding)
|
36
36
|
true
|
37
37
|
end
|
38
38
|
|
39
|
+
#: -> Prism::ProgramNode
|
40
|
+
def ast
|
41
|
+
@parse_result.value.first
|
42
|
+
end
|
43
|
+
|
39
44
|
# @override
|
40
45
|
#: -> bool
|
41
46
|
def syntax_error?
|
@@ -53,7 +58,7 @@ module RubyLsp
|
|
53
58
|
char_position, _ = find_index_by_position(position)
|
54
59
|
|
55
60
|
RubyDocument.locate(
|
56
|
-
|
61
|
+
ast,
|
57
62
|
char_position,
|
58
63
|
code_units_cache: @code_units_cache,
|
59
64
|
node_types: node_types,
|
@@ -56,6 +56,17 @@ module RubyLsp
|
|
56
56
|
@enabled_feature_flags = {} #: Hash[Symbol, bool]
|
57
57
|
@mutex = Mutex.new #: Mutex
|
58
58
|
@telemetry_machine_id = nil #: String?
|
59
|
+
@feature_configuration = {
|
60
|
+
inlayHint: RequestConfig.new({
|
61
|
+
enableAll: false,
|
62
|
+
implicitRescue: false,
|
63
|
+
implicitHashValue: false,
|
64
|
+
}),
|
65
|
+
codeLens: RequestConfig.new({
|
66
|
+
enableAll: false,
|
67
|
+
enableTestCodeLens: true,
|
68
|
+
}),
|
69
|
+
} #: Hash[Symbol, RequestConfig]
|
59
70
|
end
|
60
71
|
|
61
72
|
#: [T] { -> T } -> T
|
@@ -175,9 +186,19 @@ module RubyLsp
|
|
175
186
|
@enabled_feature_flags = enabled_flags if enabled_flags
|
176
187
|
|
177
188
|
@telemetry_machine_id = options.dig(:initializationOptions, :telemetryMachineId)
|
189
|
+
|
190
|
+
options.dig(:initializationOptions, :featuresConfiguration)&.each do |feature_name, config|
|
191
|
+
@feature_configuration[feature_name]&.merge!(config)
|
192
|
+
end
|
193
|
+
|
178
194
|
notifications
|
179
195
|
end
|
180
196
|
|
197
|
+
#: (Symbol) -> RequestConfig?
|
198
|
+
def feature_configuration(feature_name)
|
199
|
+
@feature_configuration[feature_name]
|
200
|
+
end
|
201
|
+
|
181
202
|
#: (Symbol flag) -> bool?
|
182
203
|
def enabled_feature?(flag)
|
183
204
|
@enabled_feature_flags[:all] || @enabled_feature_flags[flag]
|
data/lib/ruby_lsp/internal.rb
CHANGED
@@ -6,8 +6,6 @@
|
|
6
6
|
yarp_require_paths = Gem.loaded_specs["yarp"]&.full_require_paths
|
7
7
|
$LOAD_PATH.delete_if { |path| yarp_require_paths.include?(path) } if yarp_require_paths
|
8
8
|
|
9
|
-
require "sorbet-runtime"
|
10
|
-
|
11
9
|
# Set Bundler's UI level to silent as soon as possible to prevent any prints to STDOUT
|
12
10
|
require "bundler"
|
13
11
|
Bundler.ui.level = :silent
|
@@ -516,6 +516,14 @@ module RubyLsp
|
|
516
516
|
|
517
517
|
entry_name = entry.name
|
518
518
|
owner_name = entry.owner&.name
|
519
|
+
new_text = entry_name
|
520
|
+
|
521
|
+
if entry_name.end_with?("=")
|
522
|
+
method_name = entry_name.delete_suffix("=")
|
523
|
+
|
524
|
+
# For writer methods, format as assignment and prefix "self." when no receiver is specified
|
525
|
+
new_text = node.receiver.nil? ? "self.#{method_name} = " : "#{method_name} = "
|
526
|
+
end
|
519
527
|
|
520
528
|
label_details = Interface::CompletionItemLabelDetails.new(
|
521
529
|
description: entry.file_name,
|
@@ -525,7 +533,7 @@ module RubyLsp
|
|
525
533
|
label: entry_name,
|
526
534
|
filter_text: entry_name,
|
527
535
|
label_details: label_details,
|
528
|
-
text_edit: Interface::TextEdit.new(range: range, new_text:
|
536
|
+
text_edit: Interface::TextEdit.new(range: range, new_text: new_text),
|
529
537
|
kind: Constant::CompletionItemKind::METHOD,
|
530
538
|
data: {
|
531
539
|
owner_name: owner_name,
|
@@ -7,6 +7,7 @@ module RubyLsp
|
|
7
7
|
include Requests::Support::Common
|
8
8
|
|
9
9
|
ALLOWED_TARGETS = [
|
10
|
+
Prism::BreakNode,
|
10
11
|
Prism::CallNode,
|
11
12
|
Prism::ConstantReadNode,
|
12
13
|
Prism::ConstantWriteNode,
|
@@ -54,6 +55,7 @@ module RubyLsp
|
|
54
55
|
|
55
56
|
dispatcher.register(
|
56
57
|
self,
|
58
|
+
:on_break_node_enter,
|
57
59
|
:on_constant_read_node_enter,
|
58
60
|
:on_constant_write_node_enter,
|
59
61
|
:on_constant_path_node_enter,
|
@@ -84,6 +86,11 @@ module RubyLsp
|
|
84
86
|
)
|
85
87
|
end
|
86
88
|
|
89
|
+
#: (Prism::BreakNode node) -> void
|
90
|
+
def on_break_node_enter(node)
|
91
|
+
handle_keyword_documentation(node.keyword)
|
92
|
+
end
|
93
|
+
|
87
94
|
#: (Prism::StringNode node) -> void
|
88
95
|
def on_string_node_enter(node)
|
89
96
|
if @path && File.basename(@path) == GEMFILE_NAME
|
@@ -8,10 +8,12 @@ module RubyLsp
|
|
8
8
|
|
9
9
|
RESCUE_STRING_LENGTH = "rescue".length #: Integer
|
10
10
|
|
11
|
-
#: (ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint]
|
12
|
-
def initialize(
|
11
|
+
#: (GlobalState, ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint], Prism::Dispatcher) -> void
|
12
|
+
def initialize(global_state, response_builder, dispatcher)
|
13
13
|
@response_builder = response_builder
|
14
|
-
@hints_configuration =
|
14
|
+
@hints_configuration = ( # rubocop:disable Style/RedundantParentheses
|
15
|
+
global_state.feature_configuration(:inlayHint) #: as !nil
|
16
|
+
) #: RequestConfig
|
15
17
|
|
16
18
|
dispatcher.register(self, :on_rescue_node_enter, :on_implicit_node_enter)
|
17
19
|
end
|