ruby-lsp 0.23.6 → 0.23.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 563db8ddc06dc53f37db5ea4a42a48b7af8ed5bb2639c42e87e3c2bdd7fe38d1
4
- data.tar.gz: a1820031a007e14c42600fd897e43fad044f26e05f02e117c806821cdc46e9d7
3
+ metadata.gz: 46b72d1b9ba142496f64035b6b1ad54d096c0a28ae52311612bd118bc49e2956
4
+ data.tar.gz: 525dc46dcfc71ee57da51955a4034ceace3bbdd1eca7942b542ab2cd32d42ad4
5
5
  SHA512:
6
- metadata.gz: 2d28983a474a7b32486f20df65ec2a808ddf2be31bc0c4d7d62ae1c3fa24448b28699917d23b6f4f00045ff45e25aeff1e27c6a27d40c6a7dc6887be630f8828
7
- data.tar.gz: d10bd35268476cd2b2d319405dd58433d32df48a621cf4d45555cafb6e293d3bc4b3844afe7bf6dc0d39e68a5f5a7be70b935874796a3852a68ac5c61c592709
6
+ metadata.gz: '06690b76d284ca6abc05fc0e836af32a54c0a3cedea1fd53071648330a3b3b6e6d1a59ef205127f54a88e8cd3ca07c3840f25f1293e37737d705b2ea41719cb1'
7
+ data.tar.gz: bd6104ef180f122d0bb9d6d751213c43f0d19d0f203deb50e5d94583ff0aaf85559a040ca0371fc24506ff11a0d2742c14f1277226cc34d3a09d02730d46aed7
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![Build Status](https://github.com/Shopify/ruby-lsp/workflows/CI/badge.svg)](https://github.com/Shopify/ruby-lsp/actions/workflows/ci.yml)
6
6
  [![Ruby LSP extension](https://img.shields.io/badge/VS%20Code-Ruby%20LSP-success?logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp)
7
- [![Ruby DX Slack](https://img.shields.io/badge/Slack-Ruby%20DX-success?logo=slack)](https://join.slack.com/t/ruby-dx/shared_invite/zt-2c8zjlir6-uUDJl8oIwcen_FS_aA~b6Q)
7
+ [![Ruby DX Slack](https://img.shields.io/badge/Slack-Ruby%20DX-success?logo=slack)](https://join.slack.com/t/ruby-dx/shared_invite/zt-2yd77ayis-yAiVc1TX_kH0mHMBbi89dA)
8
8
 
9
9
  # Ruby LSP
10
10
 
@@ -13,7 +13,7 @@ for Ruby, used to improve rich features in editors. It is a part of a wider goal
13
13
  experience to Ruby developers using modern standards for cross-editor features, documentation and debugging.
14
14
 
15
15
  Want to discuss Ruby developer experience? Consider joining the public
16
- [Ruby DX Slack workspace](https://join.slack.com/t/ruby-dx/shared_invite/zt-2c8zjlir6-uUDJl8oIwcen_FS_aA~b6Q).
16
+ [Ruby DX Slack workspace](https://join.slack.com/t/ruby-dx/shared_invite/zt-2yd77ayis-yAiVc1TX_kH0mHMBbi89dA).
17
17
 
18
18
  ## Getting Started
19
19
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.23.6
1
+ 0.23.7
data/exe/ruby-lsp CHANGED
@@ -64,9 +64,9 @@ if ENV["BUNDLE_GEMFILE"].nil?
64
64
  # which gives us the opportunity to control which specs are activated and enter degraded mode if any gems failed to
65
65
  # install rather than failing to boot the server completely
66
66
  if options[:launcher]
67
- command = +"#{Gem.ruby} #{File.expand_path("ruby-lsp-launcher", __dir__)}"
68
- command << " --debug" if options[:debug]
69
- exit exec(command)
67
+ flags = []
68
+ flags << "--debug" if options[:debug]
69
+ exit exec(Gem.ruby, File.expand_path("ruby-lsp-launcher", __dir__), *flags)
70
70
  end
71
71
 
72
72
  require_relative "../lib/ruby_lsp/setup_bundler"
@@ -8,14 +8,24 @@
8
8
 
9
9
  setup_error = nil
10
10
  install_error = nil
11
+ reboot = false
11
12
 
12
- # Read the initialize request before even starting the server. We need to do this to figure out the workspace URI.
13
- # Editors are not required to spawn the language server process on the same directory as the workspace URI, so we need
14
- # to ensure that we're setting up the bundle in the right place
15
- $stdin.binmode
16
- headers = $stdin.gets("\r\n\r\n")
17
- content_length = headers[/Content-Length: (\d+)/i, 1].to_i
18
- raw_initialize = $stdin.read(content_length)
13
+ workspace_uri = ARGV.first
14
+
15
+ raw_initialize = if workspace_uri && !workspace_uri.start_with?("--")
16
+ # If there's an argument without `--`, then it's the server asking to compose the bundle and passing to this
17
+ # executable the workspace URI. We can't require gems at this point, so we built a fake initialize request manually
18
+ reboot = true
19
+ "{\"params\":{\"workspaceFolders\":[{\"uri\":\"#{workspace_uri}\"}]}}"
20
+ else
21
+ # Read the initialize request before even starting the server. We need to do this to figure out the workspace URI.
22
+ # Editors are not required to spawn the language server process on the same directory as the workspace URI, so we need
23
+ # to ensure that we're setting up the bundle in the right place
24
+ $stdin.binmode
25
+ headers = $stdin.gets("\r\n\r\n")
26
+ content_length = headers[/Content-Length: (\d+)/i, 1].to_i
27
+ $stdin.read(content_length)
28
+ end
19
29
 
20
30
  # Compose the Ruby LSP bundle in a forked process so that we can require gems without polluting the main process
21
31
  # `$LOAD_PATH` and `Gem.loaded_specs`. Windows doesn't support forking, so we need a separate path to support it
@@ -91,6 +101,13 @@ rescue StandardError => e
91
101
  $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
92
102
  end
93
103
 
104
+ # When performing a lockfile re-boot, this executable is invoked to set up the composed bundle ahead of time. In this
105
+ # flow, we are not booting the LSP yet, just checking if the bundle is valid before rebooting
106
+ if reboot
107
+ # Use the exit status to signal to the server if composing the bundle succeeded
108
+ exit(install_error || setup_error ? 1 : 0)
109
+ end
110
+
94
111
  # Now that the bundle is set up, we can begin actually launching the server. Note that `Bundler.setup` will have already
95
112
  # configured the load path using the version of the Ruby LSP present in the composed bundle. Do not push any Ruby LSP
96
113
  # paths into the load path manually or we may end up requiring the wrong version of the gem
@@ -19,7 +19,7 @@ module RubyLsp
19
19
  sig { returns(Interface::CodeActionRegistrationOptions) }
20
20
  def provider
21
21
  Interface::CodeActionRegistrationOptions.new(
22
- document_selector: [Interface::DocumentFilter.new(language: "ruby")],
22
+ document_selector: nil,
23
23
  resolve_provider: true,
24
24
  )
25
25
  end
@@ -15,7 +15,7 @@ module RubyLsp
15
15
  sig { returns(Interface::DiagnosticRegistrationOptions) }
16
16
  def provider
17
17
  Interface::DiagnosticRegistrationOptions.new(
18
- document_selector: [Interface::DocumentFilter.new(language: "ruby")],
18
+ document_selector: nil,
19
19
  inter_file_dependencies: false,
20
20
  workspace_diagnostics: false,
21
21
  )
@@ -13,13 +13,9 @@ module RubyLsp
13
13
  class << self
14
14
  extend T::Sig
15
15
 
16
- sig { returns(Interface::FoldingRangeRegistrationOptions) }
16
+ sig { returns(TrueClass) }
17
17
  def provider
18
- Interface::FoldingRangeRegistrationOptions.new(
19
- document_selector: [
20
- Interface::DocumentFilter.new(language: "ruby"),
21
- ],
22
- )
18
+ true
23
19
  end
24
20
  end
25
21
 
@@ -14,13 +14,9 @@ module RubyLsp
14
14
  class << self
15
15
  extend T::Sig
16
16
 
17
- sig { returns(Interface::DocumentFormattingRegistrationOptions) }
17
+ sig { returns(TrueClass) }
18
18
  def provider
19
- Interface::DocumentFormattingRegistrationOptions.new(
20
- document_selector: [
21
- Interface::DocumentFilter.new(language: "ruby"),
22
- ],
23
- )
19
+ true
24
20
  end
25
21
  end
26
22
 
@@ -14,7 +14,7 @@ module RubyLsp
14
14
  sig { returns(Interface::DocumentOnTypeFormattingRegistrationOptions) }
15
15
  def provider
16
16
  Interface::DocumentOnTypeFormattingRegistrationOptions.new(
17
- document_selector: [Interface::DocumentFilter.new(language: "ruby")],
17
+ document_selector: nil,
18
18
  first_trigger_character: "{",
19
19
  more_trigger_character: ["\n", "|", "d"],
20
20
  )
@@ -17,7 +17,7 @@ module RubyLsp
17
17
  sig { returns(Interface::SemanticTokensRegistrationOptions) }
18
18
  def provider
19
19
  Interface::SemanticTokensRegistrationOptions.new(
20
- document_selector: [{ language: "ruby" }, { language: "erb" }],
20
+ document_selector: nil,
21
21
  legend: Interface::SemanticTokensLegend.new(
22
22
  token_types: ResponseBuilders::SemanticHighlighting::TOKEN_TYPES.keys,
23
23
  token_modifiers: ResponseBuilders::SemanticHighlighting::TOKEN_MODIFIERS.keys,
@@ -106,6 +106,8 @@ module RubyLsp
106
106
  end,
107
107
  ),
108
108
  )
109
+ when "rubyLsp/composeBundle"
110
+ compose_bundle(message)
109
111
  when "$/cancelRequest"
110
112
  @global_state.synchronize { @cancelled_requests << message[:params][:id] }
111
113
  when nil
@@ -283,6 +285,7 @@ module RubyLsp
283
285
  document_range_formatting_provider: true,
284
286
  experimental: {
285
287
  addon_detection: true,
288
+ compose_bundle: true,
286
289
  },
287
290
  ),
288
291
  serverInfo: {
@@ -1282,5 +1285,37 @@ module RubyLsp
1282
1285
 
1283
1286
  addon.handle_window_show_message_response(result[:title])
1284
1287
  end
1288
+
1289
+ sig { params(message: T::Hash[Symbol, T.untyped]).void }
1290
+ def compose_bundle(message)
1291
+ already_composed_path = File.join(@global_state.workspace_path, ".ruby-lsp", "bundle_is_composed")
1292
+ command = "#{Gem.ruby} #{File.expand_path("../../exe/ruby-lsp-launcher", __dir__)} #{@global_state.workspace_uri}"
1293
+ id = message[:id]
1294
+
1295
+ begin
1296
+ Bundler::LockfileParser.new(Bundler.default_lockfile.read)
1297
+ rescue Bundler::LockfileError => e
1298
+ send_message(Error.new(id: id, code: BUNDLE_COMPOSE_FAILED_CODE, message: e.message))
1299
+ return
1300
+ end
1301
+
1302
+ # We compose the bundle in a thread so that the LSP continues to work while we're checking for its validity. Once
1303
+ # we return the response back to the editor, then the restart is triggered
1304
+ Thread.new do
1305
+ send_log_message("Recomposing the bundle ahead of restart")
1306
+ pid = Process.spawn(command)
1307
+ _, status = Process.wait2(pid)
1308
+
1309
+ if status&.exitstatus == 0
1310
+ # Create a signal for the restart that it can skip composing the bundle and launch directly
1311
+ FileUtils.touch(already_composed_path)
1312
+ send_message(Result.new(id: id, response: { success: true }))
1313
+ else
1314
+ # This special error code makes the extension avoid restarting in case we already know that the composed
1315
+ # bundle is not valid
1316
+ send_message(Error.new(id: id, code: BUNDLE_COMPOSE_FAILED_CODE, message: "Failed to compose bundle"))
1317
+ end
1318
+ end
1319
+ end
1285
1320
  end
1286
1321
  end
@@ -57,6 +57,7 @@ module RubyLsp
57
57
  @lockfile_hash_path = T.let(@custom_dir + "main_lockfile_hash", Pathname)
58
58
  @last_updated_path = T.let(@custom_dir + "last_updated", Pathname)
59
59
  @error_path = T.let(@custom_dir + "install_error", Pathname)
60
+ @already_composed_path = T.let(@custom_dir + "bundle_is_composed", Pathname)
60
61
 
61
62
  dependencies, bundler_version = load_dependencies
62
63
  @dependencies = T.let(dependencies, T::Hash[String, T.untyped])
@@ -71,6 +72,23 @@ module RubyLsp
71
72
  def setup!
72
73
  raise BundleNotLocked if !@launcher && @gemfile&.exist? && !@lockfile&.exist?
73
74
 
75
+ # If the bundle was composed ahead of time using our custom `rubyLsp/composeBundle` request, then we can skip the
76
+ # entire process and just return the composed environment
77
+ if @already_composed_path.exist?
78
+ $stderr.puts("Ruby LSP> Composed bundle was set up ahead of time. Skipping...")
79
+ @already_composed_path.delete
80
+
81
+ env = bundler_settings_as_env
82
+ env["BUNDLE_GEMFILE"] = @custom_gemfile.exist? ? @custom_gemfile.to_s : @gemfile.to_s
83
+
84
+ if env["BUNDLE_PATH"]
85
+ env["BUNDLE_PATH"] = File.expand_path(env["BUNDLE_PATH"], @project_path)
86
+ end
87
+
88
+ env["BUNDLER_VERSION"] = @bundler_version.to_s if @bundler_version
89
+ return env
90
+ end
91
+
74
92
  # Automatically create and ignore the .ruby-lsp folder for users
75
93
  @custom_dir.mkpath unless @custom_dir.exist?
76
94
  ignore_file = @custom_dir + ".gitignore"
@@ -37,6 +37,8 @@ module RubyLsp
37
37
  CODE = -32900
38
38
  end
39
39
 
40
+ BUNDLE_COMPOSE_FAILED_CODE = -33000
41
+
40
42
  # A notification to be sent to the client
41
43
  class Message
42
44
  extend T::Sig
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.6
4
+ version: 0.23.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-01-16 00:00:00.000000000 Z
10
+ date: 2025-01-28 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: language_server-protocol
@@ -218,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
218
  - !ruby/object:Gem::Version
219
219
  version: '0'
220
220
  requirements: []
221
- rubygems_version: 3.6.2
221
+ rubygems_version: 3.6.3
222
222
  specification_version: 4
223
223
  summary: An opinionated language server for Ruby
224
224
  test_files: []