ruby-lsp 0.24.2 → 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 +18 -9
- 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/entry.rb +3 -1
- data/lib/ruby_indexer/test/configuration_test.rb +1 -1
- data/lib/ruby_lsp/addon.rb +13 -5
- data/lib/ruby_lsp/base_server.rb +9 -5
- data/lib/ruby_lsp/document.rb +13 -8
- data/lib/ruby_lsp/global_state.rb +21 -0
- data/lib/ruby_lsp/internal.rb +0 -2
- data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
- data/lib/ruby_lsp/requests/code_lens.rb +9 -3
- 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/request.rb +3 -1
- data/lib/ruby_lsp/requests/support/formatter.rb +9 -3
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +4 -2
- data/lib/ruby_lsp/response_builders/response_builder.rb +3 -3
- data/lib/ruby_lsp/server.rb +42 -20
- data/lib/ruby_lsp/setup_bundler.rb +48 -22
- data/lib/ruby_lsp/store.rb +0 -10
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +13 -1
- data/lib/ruby_lsp/utils.rb +44 -5
- metadata +1 -16
- data/lib/ruby_lsp/load_sorbet.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7637d6f68616069c2f8c0d870f3daf31808a1cccd8ab32d2bdaf1f67274f9b59
|
4
|
+
data.tar.gz: 7ea1d75ad921adbf01f69a0f5d2fba905673311c13b0999d44c08bdf54737053
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a354535a3853b0826635408fc46dc85cb7cee97c4993012dd983af11b8917121962d97bddf0853406b54f619faa8c2383cccca9638b4a0624309fb1e4c838249
|
7
|
+
data.tar.gz: 9e49e2436c63d90fc373b52ac9f6b65e83964fe108abd0a18fd46b655cd99bd55c471dd198624bb8701890f62175af2c9fcb50fcfa2bbf69e706406b9fa1e472
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.25.0
|
data/exe/ruby-lsp
CHANGED
@@ -88,13 +88,17 @@ if ENV["BUNDLE_GEMFILE"].nil?
|
|
88
88
|
exit exec(env, "#{base_command} exec ruby-lsp #{original_args.join(" ")}".strip)
|
89
89
|
end
|
90
90
|
|
91
|
+
$stdin.sync = true
|
92
|
+
$stdout.sync = true
|
93
|
+
$stderr.sync = true
|
94
|
+
$stdin.binmode
|
95
|
+
$stdout.binmode
|
96
|
+
$stderr.binmode
|
97
|
+
|
91
98
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
92
99
|
|
93
|
-
require "ruby_lsp/load_sorbet"
|
94
100
|
require "ruby_lsp/internal"
|
95
101
|
|
96
|
-
T::Utils.run_all_sig_blocks
|
97
|
-
|
98
102
|
if options[:debug]
|
99
103
|
if ["x64-mingw-ucrt", "x64-mingw32"].include?(RUBY_PLATFORM)
|
100
104
|
$stderr.puts "Debugging is not supported on Windows"
|
@@ -147,8 +151,10 @@ if options[:doctor]
|
|
147
151
|
return
|
148
152
|
end
|
149
153
|
|
154
|
+
server = RubyLsp::Server.new
|
155
|
+
|
150
156
|
# Ensure all output goes out stderr by default to allow puts/p/pp to work
|
151
157
|
# without specifying output device.
|
152
158
|
$> = $stderr
|
153
159
|
|
154
|
-
|
160
|
+
server.start
|
data/exe/ruby-lsp-check
CHANGED
@@ -3,13 +3,9 @@
|
|
3
3
|
|
4
4
|
# This executable checks if all automatic LSP requests run successfully on every Ruby file under the current directory
|
5
5
|
|
6
|
-
require "ruby_lsp/load_sorbet"
|
7
|
-
|
8
6
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
9
7
|
require "ruby_lsp/internal"
|
10
8
|
|
11
|
-
T::Utils.run_all_sig_blocks
|
12
|
-
|
13
9
|
files = Dir.glob("#{Dir.pwd}/**/*.rb")
|
14
10
|
|
15
11
|
puts "Verifying that all automatic LSP requests execute successfully. This may take a while..."
|
data/exe/ruby-lsp-launcher
CHANGED
@@ -6,6 +6,13 @@
|
|
6
6
|
# composed bundle
|
7
7
|
# !!!!!!!
|
8
8
|
|
9
|
+
$stdin.sync = true
|
10
|
+
$stdout.sync = true
|
11
|
+
$stderr.sync = true
|
12
|
+
$stdin.binmode
|
13
|
+
$stdout.binmode
|
14
|
+
$stderr.binmode
|
15
|
+
|
9
16
|
setup_error = nil
|
10
17
|
install_error = nil
|
11
18
|
reboot = false
|
@@ -28,7 +35,6 @@ else
|
|
28
35
|
# Read the initialize request before even starting the server. We need to do this to figure out the workspace URI.
|
29
36
|
# Editors are not required to spawn the language server process on the same directory as the workspace URI, so we need
|
30
37
|
# to ensure that we're setting up the bundle in the right place
|
31
|
-
$stdin.binmode
|
32
38
|
headers = $stdin.gets("\r\n\r\n")
|
33
39
|
content_length = headers[/Content-Length: (\d+)/i, 1].to_i
|
34
40
|
$stdin.read(content_length)
|
@@ -125,11 +131,8 @@ end
|
|
125
131
|
# Now that the bundle is set up, we can begin actually launching the server. Note that `Bundler.setup` will have already
|
126
132
|
# configured the load path using the version of the Ruby LSP present in the composed bundle. Do not push any Ruby LSP
|
127
133
|
# paths into the load path manually or we may end up requiring the wrong version of the gem
|
128
|
-
require "ruby_lsp/load_sorbet"
|
129
134
|
require "ruby_lsp/internal"
|
130
135
|
|
131
|
-
T::Utils.run_all_sig_blocks
|
132
|
-
|
133
136
|
if ARGV.include?("--debug")
|
134
137
|
if ["x64-mingw-ucrt", "x64-mingw32"].include?(RUBY_PLATFORM)
|
135
138
|
$stderr.puts "Debugging is not supported on Windows"
|
@@ -143,22 +146,28 @@ if ARGV.include?("--debug")
|
|
143
146
|
end
|
144
147
|
end
|
145
148
|
|
146
|
-
# Ensure all output goes out stderr by default to allow puts/p/pp to work without specifying output device.
|
147
|
-
$> = $stderr
|
148
|
-
|
149
149
|
initialize_request = JSON.parse(raw_initialize, symbolize_names: true) if raw_initialize
|
150
150
|
|
151
151
|
begin
|
152
|
-
RubyLsp::Server.new(
|
152
|
+
server = RubyLsp::Server.new(
|
153
153
|
install_error: install_error,
|
154
154
|
setup_error: setup_error,
|
155
155
|
initialize_request: initialize_request,
|
156
|
-
)
|
156
|
+
)
|
157
|
+
|
158
|
+
# Ensure all output goes out stderr by default to allow puts/p/pp to work without specifying output device.
|
159
|
+
$> = $stderr
|
160
|
+
|
161
|
+
server.start
|
157
162
|
rescue ArgumentError
|
158
163
|
# If the launcher is booting an outdated version of the server, then the initializer doesn't accept a keyword splat
|
159
164
|
# and we already read the initialize request from the stdin pipe. In this case, we need to process the initialize
|
160
165
|
# request manually and then start the main loop
|
161
166
|
server = RubyLsp::Server.new
|
167
|
+
|
168
|
+
# Ensure all output goes out stderr by default to allow puts/p/pp to work without specifying output device.
|
169
|
+
$> = $stderr
|
170
|
+
|
162
171
|
server.process_message(initialize_request)
|
163
172
|
server.start
|
164
173
|
end
|
@@ -20,7 +20,7 @@ module RubyIndexer
|
|
20
20
|
assert(uris.none? { |uri| uri.full_path.include?("test/fixtures") })
|
21
21
|
assert(uris.none? { |uri| uri.full_path.include?(bundle_path.join("minitest-reporters").to_s) })
|
22
22
|
assert(uris.none? { |uri| uri.full_path.include?(bundle_path.join("ansi").to_s) })
|
23
|
-
assert(uris.any? { |uri| uri.full_path.include?(bundle_path.join("
|
23
|
+
assert(uris.any? { |uri| uri.full_path.include?(bundle_path.join("prism").to_s) })
|
24
24
|
assert(uris.none? { |uri| uri.full_path == __FILE__ })
|
25
25
|
end
|
26
26
|
|
data/lib/ruby_lsp/addon.rb
CHANGED
@@ -182,24 +182,32 @@ module RubyLsp
|
|
182
182
|
# reading information into memory or even spawning a separate process
|
183
183
|
# @abstract
|
184
184
|
#: (GlobalState, Thread::Queue) -> void
|
185
|
-
def activate(global_state, outgoing_queue)
|
185
|
+
def activate(global_state, outgoing_queue)
|
186
|
+
raise AbstractMethodInvokedError
|
187
|
+
end
|
186
188
|
|
187
|
-
# Each add-on
|
189
|
+
# Each add-on must implement `MyAddon#deactivate` and use to perform any clean up, like shutting down a
|
188
190
|
# child process
|
189
191
|
# @abstract
|
190
192
|
#: -> void
|
191
|
-
def deactivate
|
193
|
+
def deactivate
|
194
|
+
raise AbstractMethodInvokedError
|
195
|
+
end
|
192
196
|
|
193
197
|
# Add-ons should override the `name` method to return the add-on name
|
194
198
|
# @abstract
|
195
199
|
#: -> String
|
196
|
-
def name
|
200
|
+
def name
|
201
|
+
raise AbstractMethodInvokedError
|
202
|
+
end
|
197
203
|
|
198
204
|
# Add-ons should override the `version` method to return a semantic version string representing the add-on's
|
199
205
|
# version. This is used for compatibility checks
|
200
206
|
# @abstract
|
201
207
|
#: -> String
|
202
|
-
def version
|
208
|
+
def version
|
209
|
+
raise AbstractMethodInvokedError
|
210
|
+
end
|
203
211
|
|
204
212
|
# Handle a response from a window/showMessageRequest request. Add-ons must include the addon_name as part of the
|
205
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
@@ -6,11 +6,11 @@ module RubyLsp
|
|
6
6
|
class BaseServer
|
7
7
|
#: (**untyped options) -> void
|
8
8
|
def initialize(**options)
|
9
|
+
@reader = MessageReader.new(options[:reader] || $stdin) #: MessageReader
|
10
|
+
@writer = MessageWriter.new(options[:writer] || $stdout) #: MessageWriter
|
9
11
|
@test_mode = options[:test_mode] #: bool?
|
10
12
|
@setup_error = options[:setup_error] #: StandardError?
|
11
13
|
@install_error = options[:install_error] #: StandardError?
|
12
|
-
@writer = Transport::Stdio::Writer.new #: Transport::Stdio::Writer
|
13
|
-
@reader = Transport::Stdio::Reader.new #: Transport::Stdio::Reader
|
14
14
|
@incoming_queue = Thread::Queue.new #: Thread::Queue
|
15
15
|
@outgoing_queue = Thread::Queue.new #: Thread::Queue
|
16
16
|
@cancelled_requests = [] #: Array[Integer]
|
@@ -36,7 +36,7 @@ module RubyLsp
|
|
36
36
|
|
37
37
|
#: -> void
|
38
38
|
def start
|
39
|
-
@reader.
|
39
|
+
@reader.each_message do |message|
|
40
40
|
method = message[:method]
|
41
41
|
|
42
42
|
# We must parse the document under a mutex lock or else we might switch threads and accept text edits in the
|
@@ -128,11 +128,15 @@ module RubyLsp
|
|
128
128
|
|
129
129
|
# @abstract
|
130
130
|
#: (Hash[Symbol, untyped] message) -> void
|
131
|
-
def process_message(message)
|
131
|
+
def process_message(message)
|
132
|
+
raise AbstractMethodInvokedError
|
133
|
+
end
|
132
134
|
|
133
135
|
# @abstract
|
134
136
|
#: -> void
|
135
|
-
def shutdown
|
137
|
+
def shutdown
|
138
|
+
raise AbstractMethodInvokedError
|
139
|
+
end
|
136
140
|
|
137
141
|
#: (Integer id, String message, ?type: Integer) -> void
|
138
142
|
def fail_request_and_notify(id, message, type: Constant::MessageType::INFO)
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -5,9 +5,8 @@ module RubyLsp
|
|
5
5
|
# @abstract
|
6
6
|
#: [ParseResultType]
|
7
7
|
class Document
|
8
|
-
extend T::Generic
|
9
|
-
|
10
8
|
class InvalidLocationError < StandardError; end
|
9
|
+
|
11
10
|
# This maximum number of characters for providing expensive features, like semantic highlighting and diagnostics.
|
12
11
|
# This is the same number used by the TypeScript extension in VS Code
|
13
12
|
MAXIMUM_CHARACTERS_FOR_EXPENSIVE_FEATURES = 100_000
|
@@ -61,7 +60,9 @@ module RubyLsp
|
|
61
60
|
|
62
61
|
# @abstract
|
63
62
|
#: -> Symbol
|
64
|
-
def language_id
|
63
|
+
def language_id
|
64
|
+
raise AbstractMethodInvokedError
|
65
|
+
end
|
65
66
|
|
66
67
|
#: [T] (String request_name) { (Document[ParseResultType] document) -> T } -> T
|
67
68
|
def cache_fetch(request_name, &block)
|
@@ -121,11 +122,15 @@ module RubyLsp
|
|
121
122
|
# Returns `true` if the document was parsed and `false` if nothing needed parsing
|
122
123
|
# @abstract
|
123
124
|
#: -> bool
|
124
|
-
def parse
|
125
|
+
def parse!
|
126
|
+
raise AbstractMethodInvokedError
|
127
|
+
end
|
125
128
|
|
126
129
|
# @abstract
|
127
130
|
#: -> bool
|
128
|
-
def syntax_error
|
131
|
+
def syntax_error?
|
132
|
+
raise AbstractMethodInvokedError
|
133
|
+
end
|
129
134
|
|
130
135
|
#: -> bool
|
131
136
|
def past_expensive_limit?
|
@@ -177,8 +182,6 @@ module RubyLsp
|
|
177
182
|
# See https://microsoft.github.io/language-server-protocol/specification/#positionEncodingKind for more information
|
178
183
|
# @abstract
|
179
184
|
class Scanner
|
180
|
-
extend T::Sig
|
181
|
-
|
182
185
|
LINE_BREAK = 0x0A #: Integer
|
183
186
|
# After character 0xFFFF, UTF-16 considers characters to have length 2 and we have to account for that
|
184
187
|
SURROGATE_PAIR_START = 0xFFFF #: Integer
|
@@ -193,7 +196,9 @@ module RubyLsp
|
|
193
196
|
# character index regardless of whether we are searching positions based on bytes, code units, or codepoints.
|
194
197
|
# @abstract
|
195
198
|
#: (Hash[Symbol, untyped] position) -> Integer
|
196
|
-
def find_char_position(position)
|
199
|
+
def find_char_position(position)
|
200
|
+
raise AbstractMethodInvokedError
|
201
|
+
end
|
197
202
|
end
|
198
203
|
|
199
204
|
# For the UTF-8 encoding, positions correspond to bytes
|
@@ -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
|
@@ -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
|
@@ -27,10 +27,16 @@ module RubyLsp
|
|
27
27
|
@document = document
|
28
28
|
@test_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
|
29
29
|
uri = document.uri
|
30
|
+
file_path = uri.full_path
|
31
|
+
code_lens_config = global_state.feature_configuration(:codeLens)
|
32
|
+
test_lenses_enabled = (!code_lens_config || code_lens_config.enabled?(:enableTestCodeLens)) &&
|
33
|
+
file_path && File.fnmatch?(TEST_PATH_PATTERN, file_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
|
30
34
|
|
31
35
|
if global_state.enabled_feature?(:fullTestDiscovery)
|
32
|
-
|
33
|
-
|
36
|
+
if test_lenses_enabled
|
37
|
+
Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
|
38
|
+
Listeners::SpecStyle.new(@test_builder, global_state, dispatcher, uri)
|
39
|
+
end
|
34
40
|
else
|
35
41
|
Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
|
36
42
|
end
|
@@ -38,7 +44,7 @@ module RubyLsp
|
|
38
44
|
Addon.addons.each do |addon|
|
39
45
|
addon.create_code_lens_listener(@response_builder, uri, dispatcher)
|
40
46
|
|
41
|
-
if global_state.enabled_feature?(:fullTestDiscovery)
|
47
|
+
if global_state.enabled_feature?(:fullTestDiscovery) && test_lenses_enabled
|
42
48
|
addon.create_discover_tests_listener(@test_builder, dispatcher, uri)
|
43
49
|
end
|
44
50
|
end
|
@@ -16,13 +16,13 @@ module RubyLsp
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
#: ((RubyDocument | ERBDocument)
|
20
|
-
def initialize(
|
19
|
+
#: (GlobalState, (RubyDocument | ERBDocument), Prism::Dispatcher) -> void
|
20
|
+
def initialize(global_state, document, dispatcher)
|
21
21
|
super()
|
22
22
|
|
23
23
|
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
24
24
|
.new #: ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint]
|
25
|
-
Listeners::InlayHints.new(@response_builder,
|
25
|
+
Listeners::InlayHints.new(global_state, @response_builder, dispatcher)
|
26
26
|
end
|
27
27
|
|
28
28
|
# @override
|
@@ -162,7 +162,7 @@ module RubyLsp
|
|
162
162
|
|
163
163
|
#: (Integer line, Integer character) -> void
|
164
164
|
def move_cursor_to(line, character)
|
165
|
-
return unless /Visual Studio Code|Cursor|VSCodium/.match?(@client_name)
|
165
|
+
return unless /Visual Studio Code|Cursor|VSCodium|Windsurf/.match?(@client_name)
|
166
166
|
|
167
167
|
position = Interface::Position.new(
|
168
168
|
line: line,
|
@@ -9,15 +9,21 @@ module RubyLsp
|
|
9
9
|
module Formatter
|
10
10
|
# @abstract
|
11
11
|
#: (URI::Generic, RubyLsp::RubyDocument) -> String?
|
12
|
-
def run_formatting(uri, document)
|
12
|
+
def run_formatting(uri, document)
|
13
|
+
raise AbstractMethodInvokedError
|
14
|
+
end
|
13
15
|
|
14
16
|
# @abstract
|
15
17
|
#: (URI::Generic, String, Integer) -> String?
|
16
|
-
def run_range_formatting(uri, source, base_indentation)
|
18
|
+
def run_range_formatting(uri, source, base_indentation)
|
19
|
+
raise AbstractMethodInvokedError
|
20
|
+
end
|
17
21
|
|
18
22
|
# @abstract
|
19
23
|
#: (URI::Generic, RubyLsp::RubyDocument) -> Array[Interface::Diagnostic]?
|
20
|
-
def run_diagnostic(uri, document)
|
24
|
+
def run_diagnostic(uri, document)
|
25
|
+
raise AbstractMethodInvokedError
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
@@ -24,7 +24,7 @@ module RubyLsp
|
|
24
24
|
filename = uri.to_standardized_path || uri.opaque #: as !nil
|
25
25
|
|
26
26
|
# Invoke RuboCop with just this file in `paths`
|
27
|
-
@format_runner.run(filename, document.source)
|
27
|
+
@format_runner.run(filename, document.source, document.parse_result)
|
28
28
|
@format_runner.formatted_source
|
29
29
|
end
|
30
30
|
|
@@ -40,7 +40,7 @@ module RubyLsp
|
|
40
40
|
def run_diagnostic(uri, document)
|
41
41
|
filename = uri.to_standardized_path || uri.opaque #: as !nil
|
42
42
|
# Invoke RuboCop with just this file in `paths`
|
43
|
-
@diagnostic_runner.run(filename, document.source)
|
43
|
+
@diagnostic_runner.run(filename, document.source, document.parse_result)
|
44
44
|
|
45
45
|
@diagnostic_runner.offenses.map do |offense|
|
46
46
|
Support::RuboCopDiagnostic.new(
|
@@ -81,6 +81,7 @@ module RubyLsp
|
|
81
81
|
@offenses = [] #: Array[::RuboCop::Cop::Offense]
|
82
82
|
@errors = [] #: Array[String]
|
83
83
|
@warnings = [] #: Array[String]
|
84
|
+
@prism_result = nil #: Prism::ParseLexResult?
|
84
85
|
|
85
86
|
args += DEFAULT_ARGS
|
86
87
|
rubocop_options = ::RuboCop::Options.new.parse(args).first
|
@@ -92,14 +93,15 @@ module RubyLsp
|
|
92
93
|
super(rubocop_options, config_store)
|
93
94
|
end
|
94
95
|
|
95
|
-
#: (String
|
96
|
-
def run(path, contents)
|
96
|
+
#: (String, String, Prism::ParseLexResult) -> void
|
97
|
+
def run(path, contents, prism_result)
|
97
98
|
# Clear Runner state between runs since we get a single instance of this class
|
98
99
|
# on every use site.
|
99
100
|
@errors = []
|
100
101
|
@warnings = []
|
101
102
|
@offenses = []
|
102
103
|
@options[:stdin] = contents
|
104
|
+
@prism_result = prism_result
|
103
105
|
|
104
106
|
super([path])
|
105
107
|
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -94,7 +94,13 @@ module RubyLsp
|
|
94
94
|
id: message[:id],
|
95
95
|
response:
|
96
96
|
Addon.addons.map do |addon|
|
97
|
-
|
97
|
+
version = begin
|
98
|
+
addon.version
|
99
|
+
rescue AbstractMethodInvokedError
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
|
103
|
+
{ name: addon.name, version: version, errored: addon.error? }
|
98
104
|
end,
|
99
105
|
),
|
100
106
|
)
|
@@ -203,10 +209,6 @@ module RubyLsp
|
|
203
209
|
|
204
210
|
configured_features = options.dig(:initializationOptions, :enabledFeatures)
|
205
211
|
|
206
|
-
configured_hints = options.dig(:initializationOptions, :featuresConfiguration, :inlayHint)
|
207
|
-
@store.features_configuration.dig(:inlayHint) #: as !nil
|
208
|
-
.configuration.merge!(configured_hints) if configured_hints
|
209
|
-
|
210
212
|
enabled_features = case configured_features
|
211
213
|
when Array
|
212
214
|
# If the configuration is using an array, then absent features are disabled and present ones are enabled. That's
|
@@ -360,6 +362,7 @@ module RubyLsp
|
|
360
362
|
|
361
363
|
perform_initial_indexing
|
362
364
|
check_formatter_is_available
|
365
|
+
update_server if @global_state.enabled_feature?(:launcher)
|
363
366
|
end
|
364
367
|
|
365
368
|
#: (Hash[Symbol, untyped] message) -> void
|
@@ -473,8 +476,8 @@ module RubyLsp
|
|
473
476
|
document_symbol = Requests::DocumentSymbol.new(uri, dispatcher)
|
474
477
|
document_link = Requests::DocumentLink.new(uri, parse_result.comments, dispatcher)
|
475
478
|
inlay_hint = Requests::InlayHints.new(
|
479
|
+
@global_state,
|
476
480
|
document,
|
477
|
-
@store.features_configuration.dig(:inlayHint), #: as !nil
|
478
481
|
dispatcher,
|
479
482
|
)
|
480
483
|
|
@@ -821,7 +824,6 @@ module RubyLsp
|
|
821
824
|
return
|
822
825
|
end
|
823
826
|
|
824
|
-
hints_configurations = @store.features_configuration.dig(:inlayHint) #: as !nil
|
825
827
|
dispatcher = Prism::Dispatcher.new
|
826
828
|
|
827
829
|
unless document.is_a?(RubyDocument) || document.is_a?(ERBDocument)
|
@@ -829,7 +831,7 @@ module RubyLsp
|
|
829
831
|
return
|
830
832
|
end
|
831
833
|
|
832
|
-
request = Requests::InlayHints.new(
|
834
|
+
request = Requests::InlayHints.new(@global_state, document, dispatcher)
|
833
835
|
dispatcher.visit(document.ast)
|
834
836
|
result = request.perform
|
835
837
|
document.cache_set("textDocument/inlayHint", result)
|
@@ -1405,8 +1407,38 @@ module RubyLsp
|
|
1405
1407
|
|
1406
1408
|
# We compose the bundle in a thread so that the LSP continues to work while we're checking for its validity. Once
|
1407
1409
|
# we return the response back to the editor, then the restart is triggered
|
1410
|
+
launch_bundle_compose("Recomposing the bundle ahead of restart") do |stderr, status|
|
1411
|
+
if status&.exitstatus == 0
|
1412
|
+
# Create a signal for the restart that it can skip composing the bundle and launch directly
|
1413
|
+
FileUtils.touch(already_composed_path)
|
1414
|
+
send_message(Result.new(id: id, response: { success: true }))
|
1415
|
+
else
|
1416
|
+
# This special error code makes the extension avoid restarting in case we already know that the composed
|
1417
|
+
# bundle is not valid
|
1418
|
+
send_message(
|
1419
|
+
Error.new(id: id, code: BUNDLE_COMPOSE_FAILED_CODE, message: "Failed to compose bundle\n#{stderr}"),
|
1420
|
+
)
|
1421
|
+
end
|
1422
|
+
end
|
1423
|
+
end
|
1424
|
+
|
1425
|
+
#: -> void
|
1426
|
+
def update_server
|
1427
|
+
return unless File.exist?(File.join(@global_state.workspace_path, ".ruby-lsp", "needs_update"))
|
1428
|
+
|
1429
|
+
launch_bundle_compose("Trying to update server") do |stderr, status|
|
1430
|
+
if status&.exitstatus == 0
|
1431
|
+
send_log_message("Successfully updated the server")
|
1432
|
+
else
|
1433
|
+
send_log_message("Failed to update server\n#{stderr}", type: Constant::MessageType::ERROR)
|
1434
|
+
end
|
1435
|
+
end
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
#: (String) { (IO, Process::Status?) -> void } -> Thread
|
1439
|
+
def launch_bundle_compose(log, &block)
|
1408
1440
|
Thread.new do
|
1409
|
-
send_log_message(
|
1441
|
+
send_log_message(log)
|
1410
1442
|
|
1411
1443
|
_stdout, stderr, status = Bundler.with_unbundled_env do
|
1412
1444
|
Open3.capture3(
|
@@ -1421,17 +1453,7 @@ module RubyLsp
|
|
1421
1453
|
)
|
1422
1454
|
end
|
1423
1455
|
|
1424
|
-
|
1425
|
-
# Create a signal for the restart that it can skip composing the bundle and launch directly
|
1426
|
-
FileUtils.touch(already_composed_path)
|
1427
|
-
send_message(Result.new(id: id, response: { success: true }))
|
1428
|
-
else
|
1429
|
-
# This special error code makes the extension avoid restarting in case we already know that the composed
|
1430
|
-
# bundle is not valid
|
1431
|
-
send_message(
|
1432
|
-
Error.new(id: id, code: BUNDLE_COMPOSE_FAILED_CODE, message: "Failed to compose bundle\n#{stderr}"),
|
1433
|
-
)
|
1434
|
-
end
|
1456
|
+
block.call(stderr, status)
|
1435
1457
|
end
|
1436
1458
|
end
|
1437
1459
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "sorbet-runtime"
|
5
4
|
require "bundler"
|
6
5
|
require "bundler/cli"
|
7
6
|
require "bundler/cli/install"
|
@@ -20,11 +19,16 @@ Bundler.ui.level = :silent
|
|
20
19
|
|
21
20
|
module RubyLsp
|
22
21
|
class SetupBundler
|
23
|
-
extend T::Sig
|
24
|
-
|
25
22
|
class BundleNotLocked < StandardError; end
|
26
23
|
class BundleInstallFailure < StandardError; end
|
27
24
|
|
25
|
+
module ThorPatch
|
26
|
+
#: -> IO
|
27
|
+
def stdout
|
28
|
+
$stderr
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
28
32
|
FOUR_HOURS = 4 * 60 * 60 #: Integer
|
29
33
|
|
30
34
|
#: (String project_path, **untyped options) -> void
|
@@ -61,6 +65,7 @@ module RubyLsp
|
|
61
65
|
@bundler_version = bundler_version #: Gem::Version?
|
62
66
|
@rails_app = rails_app? #: bool
|
63
67
|
@retry = false #: bool
|
68
|
+
@needs_update_path = @custom_dir + "needs_update" #: Pathname
|
64
69
|
end
|
65
70
|
|
66
71
|
# Sets up the composed bundle and returns the `BUNDLE_GEMFILE`, `BUNDLE_PATH` and `BUNDLE_APP_CONFIG` that should be
|
@@ -256,19 +261,50 @@ module RubyLsp
|
|
256
261
|
#: (Hash[String, String] env, ?force_install: bool) -> Hash[String, String]
|
257
262
|
def run_bundle_install_directly(env, force_install: false)
|
258
263
|
RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
|
264
|
+
return update(env) if @needs_update_path.exist?
|
259
265
|
|
260
266
|
# The ENV can only be merged after checking if an update is required because we depend on the original value of
|
261
267
|
# ENV["BUNDLE_GEMFILE"], which gets overridden after the merge
|
262
|
-
|
263
|
-
ENV
|
264
|
-
.merge!(env)
|
268
|
+
FileUtils.touch(@needs_update_path) if should_bundle_update?
|
269
|
+
ENV.merge!(env)
|
265
270
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
271
|
+
$stderr.puts("Ruby LSP> Checking if the composed bundle is satisfied...")
|
272
|
+
missing_gems = bundle_check
|
273
|
+
|
274
|
+
unless missing_gems.empty?
|
275
|
+
$stderr.puts(<<~MESSAGE)
|
276
|
+
Ruby LSP> Running bundle install because the following gems are not installed:
|
277
|
+
#{missing_gems.map { |g| "#{g.name}: #{g.version}" }.join("\n")}
|
278
|
+
MESSAGE
|
279
|
+
|
280
|
+
bundle_install
|
270
281
|
end
|
271
282
|
|
283
|
+
$stderr.puts("Ruby LSP> Bundle already satisfied")
|
284
|
+
env
|
285
|
+
rescue => e
|
286
|
+
$stderr.puts("Ruby LSP> Running bundle install because #{e.message}")
|
287
|
+
bundle_install
|
288
|
+
env
|
289
|
+
end
|
290
|
+
|
291
|
+
# Essentially the same as bundle check, but simplified
|
292
|
+
#: -> Array[Gem::Specification]
|
293
|
+
def bundle_check
|
294
|
+
definition = Bundler.definition
|
295
|
+
definition.validate_runtime!
|
296
|
+
definition.check!
|
297
|
+
definition.missing_specs
|
298
|
+
end
|
299
|
+
|
300
|
+
#: -> void
|
301
|
+
def bundle_install
|
302
|
+
Bundler::CLI::Install.new({ "no-cache" => true }).run
|
303
|
+
correct_relative_remote_paths if @custom_lockfile.exist?
|
304
|
+
end
|
305
|
+
|
306
|
+
#: (Hash[String, String]) -> Hash[String, String]
|
307
|
+
def update(env)
|
272
308
|
# Try to auto upgrade the gems we depend on, unless they are in the Gemfile as that would result in undesired
|
273
309
|
# source control changes
|
274
310
|
gems = ["ruby-lsp", "debug", "prism"].reject { |dep| @dependencies[dep] }
|
@@ -276,11 +312,9 @@ module RubyLsp
|
|
276
312
|
|
277
313
|
Bundler::CLI::Update.new({ conservative: true }, gems).run
|
278
314
|
correct_relative_remote_paths if @custom_lockfile.exist?
|
315
|
+
@needs_update_path.delete
|
279
316
|
@last_updated_path.write(Time.now.iso8601)
|
280
317
|
env
|
281
|
-
rescue Bundler::GemNotFound, Bundler::GitError
|
282
|
-
# If a gem is not installed, skip the upgrade and try to install it with a single retry
|
283
|
-
@retry ? env : run_bundle_install_directly(env, force_install: true)
|
284
318
|
end
|
285
319
|
|
286
320
|
#: (Hash[String, String] env) -> Hash[String, String]
|
@@ -440,15 +474,7 @@ module RubyLsp
|
|
440
474
|
def patch_thor_to_print_progress_to_stderr!
|
441
475
|
return unless defined?(Bundler::Thor::Shell::Basic)
|
442
476
|
|
443
|
-
Bundler::Thor::Shell::Basic.prepend(
|
444
|
-
extend T::Sig
|
445
|
-
|
446
|
-
sig { returns(IO) }
|
447
|
-
def stdout
|
448
|
-
$stderr
|
449
|
-
end
|
450
|
-
end)
|
451
|
-
|
477
|
+
Bundler::Thor::Shell::Basic.prepend(ThorPatch)
|
452
478
|
Bundler.ui.level = :info
|
453
479
|
end
|
454
480
|
end
|
data/lib/ruby_lsp/store.rb
CHANGED
@@ -5,9 +5,6 @@ module RubyLsp
|
|
5
5
|
class Store
|
6
6
|
class NonExistingDocumentError < StandardError; end
|
7
7
|
|
8
|
-
#: Hash[Symbol, RequestConfig]
|
9
|
-
attr_accessor :features_configuration
|
10
|
-
|
11
8
|
#: String
|
12
9
|
attr_accessor :client_name
|
13
10
|
|
@@ -15,13 +12,6 @@ module RubyLsp
|
|
15
12
|
def initialize(global_state)
|
16
13
|
@global_state = global_state
|
17
14
|
@state = {} #: Hash[String, Document[untyped]]
|
18
|
-
@features_configuration = {
|
19
|
-
inlayHint: RequestConfig.new({
|
20
|
-
enableAll: false,
|
21
|
-
implicitRescue: false,
|
22
|
-
implicitHashValue: false,
|
23
|
-
}),
|
24
|
-
} #: Hash[Symbol, RequestConfig]
|
25
15
|
@client_name = "Unknown" #: String
|
26
16
|
end
|
27
17
|
|
@@ -12,6 +12,18 @@ module RubyLsp
|
|
12
12
|
class LspReporter
|
13
13
|
include Singleton
|
14
14
|
|
15
|
+
# https://code.visualstudio.com/api/references/vscode-api#Position
|
16
|
+
#: type position = { line: Integer, character: Integer }
|
17
|
+
|
18
|
+
# https://code.visualstudio.com/api/references/vscode-api#Range
|
19
|
+
#: type range = { start: position, end: position }
|
20
|
+
|
21
|
+
# https://code.visualstudio.com/api/references/vscode-api#BranchCoverage
|
22
|
+
#: type branch_coverage = { executed: Integer, label: String, location: range }
|
23
|
+
|
24
|
+
# https://code.visualstudio.com/api/references/vscode-api#StatementCoverage
|
25
|
+
#: type statement_coverage = { executed: Integer, location: position, branches: Array[branch_coverage] }
|
26
|
+
|
15
27
|
#: bool
|
16
28
|
attr_reader :invoked_shutdown
|
17
29
|
|
@@ -125,7 +137,7 @@ module RubyLsp
|
|
125
137
|
# ["Foo", :bar, 6, 21, 6, 65] => 0
|
126
138
|
# }
|
127
139
|
# }
|
128
|
-
#: -> Hash[String,
|
140
|
+
#: -> Hash[String, statement_coverage]
|
129
141
|
def gather_coverage_results
|
130
142
|
# Ignore coverage results inside dependencies
|
131
143
|
bundle_path = Bundler.bundle_path.to_s
|
data/lib/ruby_lsp/utils.rb
CHANGED
@@ -5,7 +5,6 @@ module RubyLsp
|
|
5
5
|
# rubocop:disable RubyLsp/UseLanguageServerAliases
|
6
6
|
Interface = LanguageServer::Protocol::Interface
|
7
7
|
Constant = LanguageServer::Protocol::Constant
|
8
|
-
Transport = LanguageServer::Protocol::Transport
|
9
8
|
# rubocop:enable RubyLsp/UseLanguageServerAliases
|
10
9
|
|
11
10
|
# Used to indicate that a request shouldn't return a response
|
@@ -20,6 +19,7 @@ module RubyLsp
|
|
20
19
|
"Gemfile"
|
21
20
|
end #: String
|
22
21
|
GUESSED_TYPES_URL = "https://shopify.github.io/ruby-lsp/#guessed-types"
|
22
|
+
TEST_PATH_PATTERN = "**/{test,spec,features}/**/{*_test.rb,test_*.rb,*_spec.rb,*.feature}"
|
23
23
|
|
24
24
|
# Request delegation for embedded languages is not yet standardized into the language server specification. Here we
|
25
25
|
# use this custom error class as a way to return a signal to the client that the request should be delegated to the
|
@@ -31,6 +31,8 @@ module RubyLsp
|
|
31
31
|
CODE = -32900
|
32
32
|
end
|
33
33
|
|
34
|
+
class AbstractMethodInvokedError < StandardError; end
|
35
|
+
|
34
36
|
BUNDLE_COMPOSE_FAILED_CODE = -33000
|
35
37
|
|
36
38
|
# A notification to be sent to the client
|
@@ -50,7 +52,9 @@ module RubyLsp
|
|
50
52
|
|
51
53
|
# @abstract
|
52
54
|
#: -> Hash[Symbol, untyped]
|
53
|
-
def to_hash
|
55
|
+
def to_hash
|
56
|
+
raise AbstractMethodInvokedError
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
class Notification < Message
|
@@ -243,9 +247,6 @@ module RubyLsp
|
|
243
247
|
|
244
248
|
# A request configuration, to turn on/off features
|
245
249
|
class RequestConfig
|
246
|
-
#: Hash[Symbol, bool]
|
247
|
-
attr_accessor :configuration
|
248
|
-
|
249
250
|
#: (Hash[Symbol, bool] configuration) -> void
|
250
251
|
def initialize(configuration)
|
251
252
|
@configuration = configuration
|
@@ -255,6 +256,11 @@ module RubyLsp
|
|
255
256
|
def enabled?(feature)
|
256
257
|
@configuration[:enableAll] || @configuration[feature]
|
257
258
|
end
|
259
|
+
|
260
|
+
#: (Hash[Symbol, bool]) -> void
|
261
|
+
def merge!(hash)
|
262
|
+
@configuration.merge!(hash)
|
263
|
+
end
|
258
264
|
end
|
259
265
|
|
260
266
|
class SorbetLevel
|
@@ -299,4 +305,37 @@ module RubyLsp
|
|
299
305
|
#: -> bool
|
300
306
|
def true_or_higher? = @level == :true || @level == :strict
|
301
307
|
end
|
308
|
+
|
309
|
+
# Reads JSON RPC messages from the given IO in a loop
|
310
|
+
class MessageReader
|
311
|
+
#: (IO) -> void
|
312
|
+
def initialize(io)
|
313
|
+
@io = io
|
314
|
+
end
|
315
|
+
|
316
|
+
#: () { (Hash[Symbol, untyped]) -> void } -> void
|
317
|
+
def each_message(&block)
|
318
|
+
while (headers = @io.gets("\r\n\r\n"))
|
319
|
+
raw_message = @io.read(headers[/Content-Length: (\d+)/i, 1].to_i) #: as !nil
|
320
|
+
block.call(JSON.parse(raw_message, symbolize_names: true))
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Writes JSON RPC messages to the given IO
|
326
|
+
class MessageWriter
|
327
|
+
#: (IO) -> void
|
328
|
+
def initialize(io)
|
329
|
+
@io = io
|
330
|
+
end
|
331
|
+
|
332
|
+
#: (Hash[Symbol, untyped]) -> void
|
333
|
+
def write(message)
|
334
|
+
message[:jsonrpc] = "2.0"
|
335
|
+
json_message = message.to_json
|
336
|
+
|
337
|
+
@io.write("Content-Length: #{json_message.bytesize}\r\n\r\n#{json_message}")
|
338
|
+
@io.flush
|
339
|
+
end
|
340
|
+
end
|
302
341
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
@@ -63,20 +63,6 @@ dependencies:
|
|
63
63
|
- - "<"
|
64
64
|
- !ruby/object:Gem::Version
|
65
65
|
version: '5'
|
66
|
-
- !ruby/object:Gem::Dependency
|
67
|
-
name: sorbet-runtime
|
68
|
-
requirement: !ruby/object:Gem::Requirement
|
69
|
-
requirements:
|
70
|
-
- - ">="
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version: 0.5.10782
|
73
|
-
type: :runtime
|
74
|
-
prerelease: false
|
75
|
-
version_requirements: !ruby/object:Gem::Requirement
|
76
|
-
requirements:
|
77
|
-
- - ">="
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: 0.5.10782
|
80
66
|
description: An opinionated language server for Ruby
|
81
67
|
email:
|
82
68
|
- ruby@shopify.com
|
@@ -145,7 +131,6 @@ files:
|
|
145
131
|
- lib/ruby_lsp/listeners/spec_style.rb
|
146
132
|
- lib/ruby_lsp/listeners/test_discovery.rb
|
147
133
|
- lib/ruby_lsp/listeners/test_style.rb
|
148
|
-
- lib/ruby_lsp/load_sorbet.rb
|
149
134
|
- lib/ruby_lsp/node_context.rb
|
150
135
|
- lib/ruby_lsp/rbs_document.rb
|
151
136
|
- lib/ruby_lsp/requests/code_action_resolve.rb
|
data/lib/ruby_lsp/load_sorbet.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "sorbet-runtime"
|
5
|
-
|
6
|
-
begin
|
7
|
-
T::Configuration.default_checked_level = :never
|
8
|
-
# Suppresses call validation errors
|
9
|
-
T::Configuration.call_validation_error_handler = ->(*arg) {}
|
10
|
-
# Suppresses errors caused by T.cast, T.let, T.must, etc.
|
11
|
-
T::Configuration.inline_type_error_handler = ->(*arg) {}
|
12
|
-
# Suppresses errors caused by incorrect parameter ordering
|
13
|
-
T::Configuration.sig_validation_error_handler = ->(*arg) {}
|
14
|
-
rescue
|
15
|
-
# Need this rescue so that if another gem has
|
16
|
-
# already set the checked level by the time we
|
17
|
-
# get to it, we don't fail outright.
|
18
|
-
nil
|
19
|
-
end
|
20
|
-
|
21
|
-
module RubyLsp
|
22
|
-
# No-op all inline type assertions defined in T
|
23
|
-
module InlineTypeAssertions
|
24
|
-
def absurd(value)
|
25
|
-
value
|
26
|
-
end
|
27
|
-
|
28
|
-
def any(type_a, type_b, *types)
|
29
|
-
T::Types::Union.new([type_a, type_b, *types])
|
30
|
-
end
|
31
|
-
|
32
|
-
def assert_type!(value, type, checked: true)
|
33
|
-
value
|
34
|
-
end
|
35
|
-
|
36
|
-
def bind(value, type, checked: true)
|
37
|
-
value
|
38
|
-
end
|
39
|
-
|
40
|
-
def cast(value, type, checked: true)
|
41
|
-
value
|
42
|
-
end
|
43
|
-
|
44
|
-
def let(value, type, checked: true)
|
45
|
-
value
|
46
|
-
end
|
47
|
-
|
48
|
-
def must(arg)
|
49
|
-
arg
|
50
|
-
end
|
51
|
-
|
52
|
-
def nilable(type)
|
53
|
-
T::Types::Union.new([type, T::Utils::Nilable::NIL_TYPE])
|
54
|
-
end
|
55
|
-
|
56
|
-
def unsafe(value)
|
57
|
-
value
|
58
|
-
end
|
59
|
-
|
60
|
-
T.singleton_class.prepend(self)
|
61
|
-
end
|
62
|
-
end
|