ruby-lsp 0.20.1 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp +18 -3
  5. data/exe/ruby-lsp-launcher +127 -0
  6. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +56 -2
  7. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +21 -6
  8. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +1 -1
  9. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +5 -5
  10. data/lib/ruby_indexer/test/classes_and_modules_test.rb +2 -2
  11. data/lib/ruby_indexer/test/enhancements_test.rb +51 -19
  12. data/lib/ruby_indexer/test/index_test.rb +2 -2
  13. data/lib/ruby_indexer/test/instance_variables_test.rb +1 -1
  14. data/lib/ruby_indexer/test/method_test.rb +26 -0
  15. data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
  16. data/lib/ruby_lsp/addon.rb +9 -2
  17. data/lib/ruby_lsp/base_server.rb +14 -5
  18. data/lib/ruby_lsp/client_capabilities.rb +60 -0
  19. data/lib/ruby_lsp/document.rb +1 -1
  20. data/lib/ruby_lsp/global_state.rb +20 -19
  21. data/lib/ruby_lsp/internal.rb +2 -0
  22. data/lib/ruby_lsp/listeners/completion.rb +62 -0
  23. data/lib/ruby_lsp/listeners/definition.rb +48 -13
  24. data/lib/ruby_lsp/listeners/hover.rb +52 -0
  25. data/lib/ruby_lsp/requests/code_action_resolve.rb +1 -1
  26. data/lib/ruby_lsp/requests/completion.rb +7 -1
  27. data/lib/ruby_lsp/requests/completion_resolve.rb +1 -1
  28. data/lib/ruby_lsp/requests/definition.rb +26 -11
  29. data/lib/ruby_lsp/requests/document_symbol.rb +2 -1
  30. data/lib/ruby_lsp/requests/hover.rb +24 -6
  31. data/lib/ruby_lsp/requests/rename.rb +1 -1
  32. data/lib/ruby_lsp/requests/request.rb +1 -1
  33. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +11 -1
  34. data/lib/ruby_lsp/scripts/compose_bundle.rb +20 -0
  35. data/lib/ruby_lsp/scripts/compose_bundle_windows.rb +8 -0
  36. data/lib/ruby_lsp/server.rb +54 -16
  37. data/lib/ruby_lsp/setup_bundler.rb +108 -22
  38. data/lib/ruby_lsp/utils.rb +8 -0
  39. metadata +8 -3
@@ -1,16 +1,26 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ # If there's no top level Gemfile, don't load RuboCop from a global installation
5
+ begin
6
+ Bundler.with_original_env { Bundler.default_gemfile }
7
+ rescue Bundler::GemfileNotFound
8
+ return
9
+ end
10
+
11
+ # Ensure that RuboCop is available
4
12
  begin
5
13
  require "rubocop"
6
14
  rescue LoadError
7
15
  return
8
16
  end
9
17
 
18
+ # Ensure that RuboCop is at least version 1.4.0
10
19
  begin
11
20
  gem("rubocop", ">= 1.4.0")
12
21
  rescue LoadError
13
- raise StandardError, "Incompatible RuboCop version. Ruby LSP requires >= 1.4.0"
22
+ $stderr.puts "Incompatible RuboCop version. Ruby LSP requires >= 1.4.0"
23
+ return
14
24
  end
15
25
 
16
26
  if RuboCop.const_defined?(:LSP) # This condition will be removed when requiring RuboCop >= 1.61.
@@ -0,0 +1,20 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ def compose(raw_initialize)
5
+ require_relative "../setup_bundler"
6
+ require "json"
7
+ require "uri"
8
+ require_relative "../../core_ext/uri"
9
+
10
+ initialize_request = JSON.parse(raw_initialize, symbolize_names: true)
11
+ workspace_uri = initialize_request.dig(:params, :workspaceFolders, 0, :uri)
12
+ workspace_path = workspace_uri && URI(workspace_uri).to_standardized_path
13
+ workspace_path ||= Dir.pwd
14
+
15
+ env = RubyLsp::SetupBundler.new(workspace_path, launcher: true).setup!
16
+ File.write(
17
+ File.join(".ruby-lsp", "bundle_env"),
18
+ env.map { |k, v| "#{k}=#{v}" }.join("\n"),
19
+ )
20
+ end
@@ -0,0 +1,8 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "compose_bundle"
5
+
6
+ # When this is invoked on Windows, we pass the raw initialize as an argument to this script. On other platforms, we
7
+ # invoke the compose method from inside a forked process
8
+ compose(ARGV.first)
@@ -81,6 +81,8 @@ module RubyLsp
81
81
  workspace_did_change_watched_files(message)
82
82
  when "workspace/symbol"
83
83
  workspace_symbol(message)
84
+ when "window/showMessageRequest"
85
+ window_show_message_request(message)
84
86
  when "rubyLsp/textDocument/showSyntaxTree"
85
87
  text_document_show_syntax_tree(message)
86
88
  when "rubyLsp/workspace/dependencies"
@@ -140,6 +142,11 @@ module RubyLsp
140
142
 
141
143
  sig { params(include_project_addons: T::Boolean).void }
142
144
  def load_addons(include_project_addons: true)
145
+ # If invoking Bundler.setup failed, then the load path will not be configured properly and trying to load add-ons
146
+ # with Gem.find_files will find every single version installed of an add-on, leading to requiring several
147
+ # different versions of the same files. We cannot load add-ons if Bundler.setup failed
148
+ return if @setup_error
149
+
143
150
  errors = Addon.load_addons(@global_state, @outgoing_queue, include_project_addons: include_project_addons)
144
151
 
145
152
  if errors.any?
@@ -254,12 +261,13 @@ module RubyLsp
254
261
  version: VERSION,
255
262
  },
256
263
  formatter: @global_state.formatter,
264
+ degraded_mode: !!(@install_error || @setup_error),
257
265
  }
258
266
 
259
267
  send_message(Result.new(id: message[:id], response: response))
260
268
 
261
269
  # Not every client supports dynamic registration or file watching
262
- if global_state.supports_watching_files
270
+ if @global_state.client_capabilities.supports_watching_files
263
271
  send_message(
264
272
  Request.new(
265
273
  id: @current_request_id,
@@ -290,6 +298,24 @@ module RubyLsp
290
298
  begin_progress("indexing-progress", "Ruby LSP: indexing files")
291
299
 
292
300
  global_state_notifications.each { |notification| send_message(notification) }
301
+
302
+ if @setup_error
303
+ send_message(Notification.telemetry(
304
+ type: "error",
305
+ errorMessage: @setup_error.message,
306
+ errorClass: @setup_error.class,
307
+ stack: @setup_error.backtrace&.join("\n"),
308
+ ))
309
+ end
310
+
311
+ if @install_error
312
+ send_message(Notification.telemetry(
313
+ type: "error",
314
+ errorMessage: @install_error.message,
315
+ errorClass: @install_error.class,
316
+ stack: @install_error.backtrace&.join("\n"),
317
+ ))
318
+ end
293
319
  end
294
320
 
295
321
  sig { void }
@@ -297,20 +323,22 @@ module RubyLsp
297
323
  load_addons
298
324
  RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
299
325
 
300
- if defined?(Requests::Support::RuboCopFormatter)
301
- begin
302
- @global_state.register_formatter("rubocop", Requests::Support::RuboCopFormatter.new)
303
- rescue RuboCop::Error => e
304
- # The user may have provided unknown config switches in .rubocop or
305
- # is trying to load a non-existant config file.
306
- send_message(Notification.window_show_message(
307
- "RuboCop configuration error: #{e.message}. Formatting will not be available.",
308
- type: Constant::MessageType::ERROR,
309
- ))
326
+ unless @setup_error
327
+ if defined?(Requests::Support::RuboCopFormatter)
328
+ begin
329
+ @global_state.register_formatter("rubocop", Requests::Support::RuboCopFormatter.new)
330
+ rescue RuboCop::Error => e
331
+ # The user may have provided unknown config switches in .rubocop or
332
+ # is trying to load a non-existent config file.
333
+ send_message(Notification.window_show_message(
334
+ "RuboCop configuration error: #{e.message}. Formatting will not be available.",
335
+ type: Constant::MessageType::ERROR,
336
+ ))
337
+ end
338
+ end
339
+ if defined?(Requests::Support::SyntaxTreeFormatter)
340
+ @global_state.register_formatter("syntax_tree", Requests::Support::SyntaxTreeFormatter.new)
310
341
  end
311
- end
312
- if defined?(Requests::Support::SyntaxTreeFormatter)
313
- @global_state.register_formatter("syntax_tree", Requests::Support::SyntaxTreeFormatter.new)
314
342
  end
315
343
 
316
344
  perform_initial_indexing
@@ -1017,7 +1045,7 @@ module RubyLsp
1017
1045
 
1018
1046
  sig { params(message: T::Hash[Symbol, T.untyped]).void }
1019
1047
  def workspace_dependencies(message)
1020
- response = begin
1048
+ response = if @global_state.top_level_bundle
1021
1049
  Bundler.with_original_env do
1022
1050
  definition = Bundler.definition
1023
1051
  dep_keys = definition.locked_deps.keys.to_set
@@ -1031,7 +1059,7 @@ module RubyLsp
1031
1059
  }
1032
1060
  end
1033
1061
  end
1034
- rescue Bundler::GemfileNotFound
1062
+ else
1035
1063
  []
1036
1064
  end
1037
1065
 
@@ -1138,6 +1166,7 @@ module RubyLsp
1138
1166
 
1139
1167
  sig { void }
1140
1168
  def check_formatter_is_available
1169
+ return if @setup_error
1141
1170
  # Warn of an unavailable `formatter` setting, e.g. `rubocop` on a project which doesn't have RuboCop.
1142
1171
  # Syntax Tree will always be available via Ruby LSP so we don't need to check for it.
1143
1172
  return unless @global_state.formatter == "rubocop"
@@ -1194,5 +1223,14 @@ module RubyLsp
1194
1223
  # The index expects snake case configurations, but VS Code standardizes on camel case settings
1195
1224
  configuration.apply_config(indexing_options.transform_keys { |key| key.to_s.gsub(/([A-Z])/, "_\\1").downcase })
1196
1225
  end
1226
+
1227
+ sig { params(message: T::Hash[Symbol, T.untyped]).void }
1228
+ def window_show_message_request(message)
1229
+ addon_name = message[:addon_name]
1230
+ addon = Addon.addons.find { |addon| addon.name == addon_name }
1231
+ return unless addon
1232
+
1233
+ addon.handle_window_show_message_response(message[:title])
1234
+ end
1197
1235
  end
1198
1236
  end
@@ -3,10 +3,14 @@
3
3
 
4
4
  require "sorbet-runtime"
5
5
  require "bundler"
6
+ require "bundler/cli"
7
+ require "bundler/cli/install"
8
+ require "bundler/cli/update"
6
9
  require "fileutils"
7
10
  require "pathname"
8
11
  require "digest"
9
12
  require "time"
13
+ require "uri"
10
14
 
11
15
  # This file is a script that will configure a custom bundle for the Ruby LSP. The custom bundle allows developers to use
12
16
  # the Ruby LSP without including the gem in their application's Gemfile while at the same time giving us access to the
@@ -27,6 +31,8 @@ module RubyLsp
27
31
  def initialize(project_path, **options)
28
32
  @project_path = project_path
29
33
  @branch = T.let(options[:branch], T.nilable(String))
34
+ @launcher = T.let(options[:launcher], T.nilable(T::Boolean))
35
+ patch_thor_to_print_progress_to_stderr! if @launcher
30
36
 
31
37
  # Regular bundle paths
32
38
  @gemfile = T.let(
@@ -47,6 +53,7 @@ module RubyLsp
47
53
  @custom_lockfile = T.let(@custom_dir + (@lockfile&.basename || "Gemfile.lock"), Pathname)
48
54
  @lockfile_hash_path = T.let(@custom_dir + "main_lockfile_hash", Pathname)
49
55
  @last_updated_path = T.let(@custom_dir + "last_updated", Pathname)
56
+ @error_path = T.let(@custom_dir + "install_error", Pathname)
50
57
 
51
58
  dependencies, bundler_version = load_dependencies
52
59
  @dependencies = T.let(dependencies, T::Hash[String, T.untyped])
@@ -59,7 +66,12 @@ module RubyLsp
59
66
  # used for running the server
60
67
  sig { returns(T::Hash[String, String]) }
61
68
  def setup!
62
- raise BundleNotLocked if @gemfile&.exist? && !@lockfile&.exist?
69
+ raise BundleNotLocked if !@launcher && @gemfile&.exist? && !@lockfile&.exist?
70
+
71
+ # Automatically create and ignore the .ruby-lsp folder for users
72
+ @custom_dir.mkpath unless @custom_dir.exist?
73
+ ignore_file = @custom_dir + ".gitignore"
74
+ ignore_file.write("*") unless ignore_file.exist?
63
75
 
64
76
  # Do not set up a custom bundle if LSP dependencies are already in the Gemfile
65
77
  if @dependencies["ruby-lsp"] &&
@@ -69,19 +81,9 @@ module RubyLsp
69
81
  "Ruby LSP> Skipping custom bundle setup since LSP dependencies are already in #{@gemfile}",
70
82
  )
71
83
 
72
- # If the user decided to add `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) to their Gemfile after
73
- # having already run the Ruby LSP, then we need to remove the `.ruby-lsp` folder, otherwise we will run `bundle
74
- # install` for the top level and try to execute the Ruby LSP using the custom bundle, which will fail since the
75
- # gems are not installed there
76
- @custom_dir.rmtree if @custom_dir.exist?
77
84
  return run_bundle_install
78
85
  end
79
86
 
80
- # Automatically create and ignore the .ruby-lsp folder for users
81
- @custom_dir.mkpath unless @custom_dir.exist?
82
- ignore_file = @custom_dir + ".gitignore"
83
- ignore_file.write("*") unless ignore_file.exist?
84
-
85
87
  write_custom_gemfile
86
88
 
87
89
  unless @gemfile&.exist? && @lockfile&.exist?
@@ -111,17 +113,19 @@ module RubyLsp
111
113
  def custom_bundle_dependencies
112
114
  @custom_bundle_dependencies ||= T.let(
113
115
  begin
116
+ original_bundle_gemfile = ENV["BUNDLE_GEMFILE"]
117
+
114
118
  if @custom_lockfile.exist?
115
119
  ENV["BUNDLE_GEMFILE"] = @custom_gemfile.to_s
116
120
  Bundler::LockfileParser.new(@custom_lockfile.read).dependencies
117
121
  else
118
122
  {}
119
123
  end
124
+ ensure
125
+ ENV["BUNDLE_GEMFILE"] = original_bundle_gemfile
120
126
  end,
121
127
  T.nilable(T::Hash[String, T.untyped]),
122
128
  )
123
- ensure
124
- ENV.delete("BUNDLE_GEMFILE")
125
129
  end
126
130
 
127
131
  sig { void }
@@ -134,7 +138,7 @@ module RubyLsp
134
138
 
135
139
  # If there's a top level Gemfile, we want to evaluate from the custom bundle. We get the source from the top level
136
140
  # Gemfile, so if there isn't one we need to add a default source
137
- if @gemfile&.exist?
141
+ if @gemfile&.exist? && @lockfile&.exist?
138
142
  parts << "eval_gemfile(File.expand_path(\"../#{@gemfile_name}\", __dir__))"
139
143
  else
140
144
  parts.unshift('source "https://rubygems.org"')
@@ -191,16 +195,54 @@ module RubyLsp
191
195
  env["BUNDLE_PATH"] = File.expand_path(env["BUNDLE_PATH"], @project_path)
192
196
  end
193
197
 
194
- # If there's a Bundler version locked, then we need to use that one to run bundle commands, so that the composed
195
- # lockfile is also locked to the same version. This avoids Bundler restarts on version mismatches
196
- base_bundle = if @bundler_version
198
+ return run_bundle_install_through_command(env) unless @launcher
199
+
200
+ # This same check happens conditionally when running through the command. For invoking the CLI directly, it's
201
+ # important that we ensure the Bundler version is set to avoid restarts
202
+ if @bundler_version
197
203
  env["BUNDLER_VERSION"] = @bundler_version.to_s
198
204
  install_bundler_if_needed
199
- "bundle _#{@bundler_version}_"
200
- else
201
- "bundle"
202
205
  end
203
206
 
207
+ begin
208
+ run_bundle_install_directly(env)
209
+ # If no error occurred, then clear previous errors
210
+ @error_path.delete if @error_path.exist?
211
+ $stderr.puts("Ruby LSP> Composed bundle installation complete")
212
+ rescue => e
213
+ # Write the error object to a file so that we can read it from the parent process
214
+ @error_path.write(Marshal.dump(e))
215
+ end
216
+
217
+ env
218
+ end
219
+
220
+ sig { params(env: T::Hash[String, String]).returns(T::Hash[String, String]) }
221
+ def run_bundle_install_directly(env)
222
+ RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
223
+ T.unsafe(ENV).merge!(env)
224
+
225
+ unless should_bundle_update?
226
+ Bundler::CLI::Install.new({}).run
227
+ correct_relative_remote_paths if @custom_lockfile.exist?
228
+ return env
229
+ end
230
+
231
+ # Try to auto upgrade the gems we depend on, unless they are in the Gemfile as that would result in undesired
232
+ # source control changes
233
+ gems = ["ruby-lsp", "debug", "prism"].reject { |dep| @dependencies[dep] }
234
+ gems << "ruby-lsp-rails" if @rails_app && !@dependencies["ruby-lsp-rails"]
235
+
236
+ Bundler::CLI::Update.new({ conservative: true }, gems).run
237
+ correct_relative_remote_paths if @custom_lockfile.exist?
238
+ @last_updated_path.write(Time.now.iso8601)
239
+ env
240
+ end
241
+
242
+ sig { params(env: T::Hash[String, String]).returns(T::Hash[String, String]) }
243
+ def run_bundle_install_through_command(env)
244
+ base_bundle = base_bundle_command(env)
245
+
204
246
  # If `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) are already in the Gemfile, then we shouldn't try
205
247
  # to upgrade them or else we'll produce undesired source control changes. If the custom bundle was just created
206
248
  # and any of `ruby-lsp`, `ruby-lsp-rails` or `debug` weren't a part of the Gemfile, then we need to run `bundle
@@ -238,7 +280,7 @@ module RubyLsp
238
280
  # Try to run the bundle install or update command. If that fails, it normally means that the custom lockfile is in
239
281
  # a bad state that no longer reflects the top level one. In that case, we can remove the whole directory, try
240
282
  # another time and give up if it fails again
241
- if !system(env, command) && !@retry && @custom_dir.exist?
283
+ if !system(env, command) && !@retry && @custom_gemfile.exist?
242
284
  @retry = true
243
285
  @custom_dir.rmtree
244
286
  $stderr.puts("Ruby LSP> Running bundle install failed. Trying to re-generate the custom bundle from scratch")
@@ -312,7 +354,7 @@ module RubyLsp
312
354
 
313
355
  # We should only apply the correction if the remote is a relative path. It might also be a URI, like
314
356
  # `https://rubygems.org` or an absolute path, in which case we shouldn't do anything
315
- if path&.start_with?(".")
357
+ if path && !URI(path).scheme
316
358
  "remote: #{File.expand_path(path, T.must(@gemfile).dirname)}"
317
359
  else
318
360
  match
@@ -331,5 +373,49 @@ module RubyLsp
331
373
 
332
374
  /class .* < (::)?Rails::Application/.match?(application_contents)
333
375
  end
376
+
377
+ # Returns the base bundle command we should use for this project, which will be:
378
+ # - `bundle` if there's no locked Bundler version and no `bin/bundle` binstub in the $PATH
379
+ # - `bundle _<version>_` if there's a locked Bundler version
380
+ # - `bin/bundle` if there's a `bin/bundle` binstub in the $PATH
381
+ sig { params(env: T::Hash[String, String]).returns(String) }
382
+ def base_bundle_command(env)
383
+ path_parts = if Gem.win_platform?
384
+ ENV["Path"] || ENV["PATH"] || ENV["path"] || ""
385
+ else
386
+ ENV["PATH"] || ""
387
+ end.split(File::PATH_SEPARATOR)
388
+
389
+ bin_dir = File.expand_path("bin", @project_path)
390
+ bundle_binstub = File.join(@project_path, "bin", "bundle")
391
+
392
+ if File.exist?(bundle_binstub) && path_parts.any? { |path| File.expand_path(path, @project_path) == bin_dir }
393
+ return bundle_binstub
394
+ end
395
+
396
+ if @bundler_version
397
+ env["BUNDLER_VERSION"] = @bundler_version.to_s
398
+ install_bundler_if_needed
399
+ return "bundle _#{@bundler_version}_"
400
+ end
401
+
402
+ "bundle"
403
+ end
404
+
405
+ sig { void }
406
+ def patch_thor_to_print_progress_to_stderr!
407
+ return unless defined?(Bundler::Thor::Shell::Basic)
408
+
409
+ Bundler::Thor::Shell::Basic.prepend(Module.new do
410
+ extend T::Sig
411
+
412
+ sig { returns(IO) }
413
+ def stdout
414
+ $stderr
415
+ end
416
+ end)
417
+
418
+ Bundler.ui.level = :info
419
+ end
334
420
  end
335
421
  end
@@ -79,6 +79,14 @@ module RubyLsp
79
79
  params: Interface::LogMessageParams.new(type: type, message: message),
80
80
  )
81
81
  end
82
+
83
+ sig { params(data: T::Hash[Symbol, T.untyped]).returns(Notification) }
84
+ def telemetry(data)
85
+ new(
86
+ method: "telemetry/event",
87
+ params: data,
88
+ )
89
+ end
82
90
  end
83
91
 
84
92
  extend T::Sig
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.1
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-16 00:00:00.000000000 Z
11
+ date: 2024-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: language_server-protocol
@@ -84,6 +84,7 @@ email:
84
84
  executables:
85
85
  - ruby-lsp
86
86
  - ruby-lsp-check
87
+ - ruby-lsp-launcher
87
88
  extensions: []
88
89
  extra_rdoc_files: []
89
90
  files:
@@ -92,6 +93,7 @@ files:
92
93
  - VERSION
93
94
  - exe/ruby-lsp
94
95
  - exe/ruby-lsp-check
96
+ - exe/ruby-lsp-launcher
95
97
  - lib/core_ext/uri.rb
96
98
  - lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb
97
99
  - lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb
@@ -121,6 +123,7 @@ files:
121
123
  - lib/ruby_indexer/test/test_case.rb
122
124
  - lib/ruby_lsp/addon.rb
123
125
  - lib/ruby_lsp/base_server.rb
126
+ - lib/ruby_lsp/client_capabilities.rb
124
127
  - lib/ruby_lsp/document.rb
125
128
  - lib/ruby_lsp/erb_document.rb
126
129
  - lib/ruby_lsp/global_state.rb
@@ -183,6 +186,8 @@ files:
183
186
  - lib/ruby_lsp/response_builders/signature_help.rb
184
187
  - lib/ruby_lsp/ruby_document.rb
185
188
  - lib/ruby_lsp/scope.rb
189
+ - lib/ruby_lsp/scripts/compose_bundle.rb
190
+ - lib/ruby_lsp/scripts/compose_bundle_windows.rb
186
191
  - lib/ruby_lsp/server.rb
187
192
  - lib/ruby_lsp/setup_bundler.rb
188
193
  - lib/ruby_lsp/static_docs.rb
@@ -212,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
217
  - !ruby/object:Gem::Version
213
218
  version: '0'
214
219
  requirements: []
215
- rubygems_version: 3.5.21
220
+ rubygems_version: 3.5.22
216
221
  signing_key:
217
222
  specification_version: 4
218
223
  summary: An opinionated language server for Ruby