ruby-lsp 0.23.6 → 0.23.7

Sign up to get free protection for your applications and to get access to all the features.
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: []