ruby-lsp 0.21.0 → 0.22.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.
@@ -81,8 +81,6 @@ 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)
86
84
  when "rubyLsp/textDocument/showSyntaxTree"
87
85
  text_document_show_syntax_tree(message)
88
86
  when "rubyLsp/workspace/dependencies"
@@ -108,6 +106,8 @@ module RubyLsp
108
106
  )
109
107
  when "$/cancelRequest"
110
108
  @mutex.synchronize { @cancelled_requests << message[:params][:id] }
109
+ when nil
110
+ process_response(message) if message[:result]
111
111
  end
112
112
  rescue DelegateRequestError
113
113
  send_message(Error.new(id: message[:id], code: DelegateRequestError::CODE, message: "DELEGATE_REQUEST"))
@@ -140,6 +140,15 @@ module RubyLsp
140
140
  send_log_message("Error processing #{message[:method]}: #{e.full_message}", type: Constant::MessageType::ERROR)
141
141
  end
142
142
 
143
+ # Process responses to requests that were sent to the client
144
+ sig { params(message: T::Hash[Symbol, T.untyped]).void }
145
+ def process_response(message)
146
+ case message.dig(:result, :method)
147
+ when "window/showMessageRequest"
148
+ window_show_message_request(message)
149
+ end
150
+ end
151
+
143
152
  sig { params(include_project_addons: T::Boolean).void }
144
153
  def load_addons(include_project_addons: true)
145
154
  # If invoking Bundler.setup failed, then the load path will not be configured properly and trying to load add-ons
@@ -188,8 +197,6 @@ module RubyLsp
188
197
  client_name = options.dig(:clientInfo, :name)
189
198
  @store.client_name = client_name if client_name
190
199
 
191
- progress = options.dig(:capabilities, :window, :workDoneProgress)
192
- @store.supports_progress = progress.nil? ? true : progress
193
200
  configured_features = options.dig(:initializationOptions, :enabledFeatures)
194
201
 
195
202
  configured_hints = options.dig(:initializationOptions, :featuresConfiguration, :inlayHint)
@@ -209,6 +216,13 @@ module RubyLsp
209
216
  Hash.new(true)
210
217
  end
211
218
 
219
+ bundle_env_path = File.join(".ruby-lsp", "bundle_env")
220
+ bundle_env = if File.exist?(bundle_env_path)
221
+ env = File.readlines(bundle_env_path).to_h { |line| T.cast(line.chomp.split("=", 2), [String, String]) }
222
+ FileUtils.rm(bundle_env_path)
223
+ env
224
+ end
225
+
212
226
  document_symbol_provider = Requests::DocumentSymbol.provider if enabled_features["documentSymbols"]
213
227
  document_link_provider = Requests::DocumentLink.provider if enabled_features["documentLink"]
214
228
  code_lens_provider = Requests::CodeLens.provider if enabled_features["codeLens"]
@@ -262,6 +276,7 @@ module RubyLsp
262
276
  },
263
277
  formatter: @global_state.formatter,
264
278
  degraded_mode: !!(@install_error || @setup_error),
279
+ bundle_env: bundle_env,
265
280
  }
266
281
 
267
282
  send_message(Result.new(id: message[:id], response: response))
@@ -597,6 +612,11 @@ module RubyLsp
597
612
  # don't want to format it
598
613
  path = uri.to_standardized_path
599
614
  unless path.nil? || path.start_with?(@global_state.workspace_path)
615
+ send_log_message(<<~MESSAGE)
616
+ Ignoring formatting request for file outside of the workspace.
617
+ Workspace path was set by editor as #{@global_state.workspace_path}.
618
+ File path requested for formatting was #{path}
619
+ MESSAGE
600
620
  send_empty_response(message[:id])
601
621
  return
602
622
  end
@@ -1105,7 +1125,7 @@ module RubyLsp
1105
1125
 
1106
1126
  sig { params(id: String, title: String, percentage: Integer).void }
1107
1127
  def begin_progress(id, title, percentage: 0)
1108
- return unless @store.supports_progress
1128
+ return unless @global_state.client_capabilities.supports_progress
1109
1129
 
1110
1130
  send_message(Request.new(
1111
1131
  id: @current_request_id,
@@ -1113,52 +1133,21 @@ module RubyLsp
1113
1133
  params: Interface::WorkDoneProgressCreateParams.new(token: id),
1114
1134
  ))
1115
1135
 
1116
- send_message(Notification.new(
1117
- method: "$/progress",
1118
- params: Interface::ProgressParams.new(
1119
- token: id,
1120
- value: Interface::WorkDoneProgressBegin.new(
1121
- kind: "begin",
1122
- title: title,
1123
- percentage: percentage,
1124
- message: "#{percentage}% completed",
1125
- ),
1126
- ),
1127
- ))
1136
+ send_message(Notification.progress_begin(id, title, percentage: percentage, message: "#{percentage}% completed"))
1128
1137
  end
1129
1138
 
1130
1139
  sig { params(id: String, percentage: Integer).void }
1131
1140
  def progress(id, percentage)
1132
- return unless @store.supports_progress
1141
+ return unless @global_state.client_capabilities.supports_progress
1133
1142
 
1134
- send_message(
1135
- Notification.new(
1136
- method: "$/progress",
1137
- params: Interface::ProgressParams.new(
1138
- token: id,
1139
- value: Interface::WorkDoneProgressReport.new(
1140
- kind: "report",
1141
- percentage: percentage,
1142
- message: "#{percentage}% completed",
1143
- ),
1144
- ),
1145
- ),
1146
- )
1143
+ send_message(Notification.progress_report(id, percentage: percentage, message: "#{percentage}% completed"))
1147
1144
  end
1148
1145
 
1149
1146
  sig { params(id: String).void }
1150
1147
  def end_progress(id)
1151
- return unless @store.supports_progress
1148
+ return unless @global_state.client_capabilities.supports_progress
1152
1149
 
1153
- send_message(
1154
- Notification.new(
1155
- method: "$/progress",
1156
- params: Interface::ProgressParams.new(
1157
- token: id,
1158
- value: Interface::WorkDoneProgressEnd.new(kind: "end"),
1159
- ),
1160
- ),
1161
- )
1150
+ send_message(Notification.progress_end(id))
1162
1151
  rescue ClosedQueueError
1163
1152
  # If the server was killed and the message queue is already closed, there's no way to end the progress
1164
1153
  # notification
@@ -1226,11 +1215,14 @@ module RubyLsp
1226
1215
 
1227
1216
  sig { params(message: T::Hash[Symbol, T.untyped]).void }
1228
1217
  def window_show_message_request(message)
1229
- addon_name = message[:addon_name]
1218
+ result = message[:result]
1219
+ return unless result
1220
+
1221
+ addon_name = result[:addon_name]
1230
1222
  addon = Addon.addons.find { |addon| addon.name == addon_name }
1231
1223
  return unless addon
1232
1224
 
1233
- addon.handle_window_show_message_response(message[:title])
1225
+ addon.handle_window_show_message_response(result[:title])
1234
1226
  end
1235
1227
  end
1236
1228
  end
@@ -12,7 +12,7 @@ require "digest"
12
12
  require "time"
13
13
  require "uri"
14
14
 
15
- # This file is a script that will configure a custom bundle for the Ruby LSP. The custom bundle allows developers to use
15
+ # This file is a script that will configure a composed bundle for the Ruby LSP. The composed bundle allows developers to use
16
16
  # the Ruby LSP without including the gem in their application's Gemfile while at the same time giving us access to the
17
17
  # exact locked versions of dependencies.
18
18
 
@@ -62,7 +62,7 @@ module RubyLsp
62
62
  @retry = T.let(false, T::Boolean)
63
63
  end
64
64
 
65
- # Sets up the custom bundle and returns the `BUNDLE_GEMFILE`, `BUNDLE_PATH` and `BUNDLE_APP_CONFIG` that should be
65
+ # Sets up the composed bundle and returns the `BUNDLE_GEMFILE`, `BUNDLE_PATH` and `BUNDLE_APP_CONFIG` that should be
66
66
  # used for running the server
67
67
  sig { returns(T::Hash[String, String]) }
68
68
  def setup!
@@ -73,12 +73,12 @@ module RubyLsp
73
73
  ignore_file = @custom_dir + ".gitignore"
74
74
  ignore_file.write("*") unless ignore_file.exist?
75
75
 
76
- # Do not set up a custom bundle if LSP dependencies are already in the Gemfile
76
+ # Do not set up a composed bundle if LSP dependencies are already in the Gemfile
77
77
  if @dependencies["ruby-lsp"] &&
78
78
  @dependencies["debug"] &&
79
79
  (@rails_app ? @dependencies["ruby-lsp-rails"] : true)
80
80
  $stderr.puts(
81
- "Ruby LSP> Skipping custom bundle setup since LSP dependencies are already in #{@gemfile}",
81
+ "Ruby LSP> Skipping composed bundle setup since LSP dependencies are already in #{@gemfile}",
82
82
  )
83
83
 
84
84
  return run_bundle_install
@@ -96,7 +96,7 @@ module RubyLsp
96
96
 
97
97
  if @custom_lockfile.exist? && @lockfile_hash_path.exist? && @lockfile_hash_path.read == current_lockfile_hash
98
98
  $stderr.puts(
99
- "Ruby LSP> Skipping custom bundle setup since #{@custom_lockfile} already exists and is up to date",
99
+ "Ruby LSP> Skipping composed bundle setup since #{@custom_lockfile} already exists and is up to date",
100
100
  )
101
101
  return run_bundle_install(@custom_gemfile)
102
102
  end
@@ -110,8 +110,8 @@ module RubyLsp
110
110
  private
111
111
 
112
112
  sig { returns(T::Hash[String, T.untyped]) }
113
- def custom_bundle_dependencies
114
- @custom_bundle_dependencies ||= T.let(
113
+ def composed_bundle_dependencies
114
+ @composed_bundle_dependencies ||= T.let(
115
115
  begin
116
116
  original_bundle_gemfile = ENV["BUNDLE_GEMFILE"]
117
117
 
@@ -136,8 +136,8 @@ module RubyLsp
136
136
  "",
137
137
  ]
138
138
 
139
- # If there's a top level Gemfile, we want to evaluate from the custom bundle. We get the source from the top level
140
- # Gemfile, so if there isn't one we need to add a default source
139
+ # If there's a top level Gemfile, we want to evaluate from the composed bundle. We get the source from the top
140
+ # level Gemfile, so if there isn't one we need to add a default source
141
141
  if @gemfile&.exist? && @lockfile&.exist?
142
142
  parts << "eval_gemfile(File.expand_path(\"../#{@gemfile_name}\", __dir__))"
143
143
  else
@@ -187,7 +187,7 @@ module RubyLsp
187
187
  env = bundler_settings_as_env
188
188
  env["BUNDLE_GEMFILE"] = bundle_gemfile.to_s
189
189
 
190
- # If the user has a custom bundle path configured, we need to ensure that we will use the absolute and not
190
+ # If the user has a composed bundle path configured, we need to ensure that we will use the absolute and not
191
191
  # relative version of it when running `bundle install`. This is necessary to avoid installing the gems under the
192
192
  # `.ruby-lsp` folder, which is not the user's intention. For example, if the path is configured as `vendor`, we
193
193
  # want to install it in the top level `vendor` and not `.ruby-lsp/vendor`
@@ -244,7 +244,7 @@ module RubyLsp
244
244
  base_bundle = base_bundle_command(env)
245
245
 
246
246
  # If `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) are already in the Gemfile, then we shouldn't try
247
- # to upgrade them or else we'll produce undesired source control changes. If the custom bundle was just created
247
+ # to upgrade them or else we'll produce undesired source control changes. If the composed bundle was just created
248
248
  # and any of `ruby-lsp`, `ruby-lsp-rails` or `debug` weren't a part of the Gemfile, then we need to run `bundle
249
249
  # install` for the first time to generate the Gemfile.lock with them included or else Bundler will complain that
250
250
  # they're missing. We can only update if the custom `.ruby-lsp/Gemfile.lock` already exists and includes all gems
@@ -274,16 +274,16 @@ module RubyLsp
274
274
  command << "1>&2"
275
275
 
276
276
  # Add bundle update
277
- $stderr.puts("Ruby LSP> Running bundle install for the custom bundle. This may take a while...")
277
+ $stderr.puts("Ruby LSP> Running bundle install for the composed bundle. This may take a while...")
278
278
  $stderr.puts("Ruby LSP> Command: #{command}")
279
279
 
280
- # Try to run the bundle install or update command. If that fails, it normally means that the custom lockfile is in
281
- # a bad state that no longer reflects the top level one. In that case, we can remove the whole directory, try
280
+ # Try to run the bundle install or update command. If that fails, it normally means that the composed lockfile is
281
+ # in a bad state that no longer reflects the top level one. In that case, we can remove the whole directory, try
282
282
  # another time and give up if it fails again
283
283
  if !system(env, command) && !@retry && @custom_gemfile.exist?
284
284
  @retry = true
285
285
  @custom_dir.rmtree
286
- $stderr.puts("Ruby LSP> Running bundle install failed. Trying to re-generate the custom bundle from scratch")
286
+ $stderr.puts("Ruby LSP> Running bundle install failed. Trying to re-generate the composed bundle from scratch")
287
287
  return setup!
288
288
  end
289
289
 
@@ -330,14 +330,14 @@ module RubyLsp
330
330
  if @rails_app
331
331
  return false if @dependencies.values_at("ruby-lsp", "ruby-lsp-rails", "debug").all?
332
332
 
333
- # If the custom lockfile doesn't include `ruby-lsp`, `ruby-lsp-rails` or `debug`, we need to run bundle install
334
- # before updating
335
- return false if custom_bundle_dependencies.values_at("ruby-lsp", "debug", "ruby-lsp-rails").any?(&:nil?)
333
+ # If the composed lockfile doesn't include `ruby-lsp`, `ruby-lsp-rails` or `debug`, we need to run bundle
334
+ # install before updating
335
+ return false if composed_bundle_dependencies.values_at("ruby-lsp", "debug", "ruby-lsp-rails").any?(&:nil?)
336
336
  else
337
337
  return false if @dependencies.values_at("ruby-lsp", "debug").all?
338
338
 
339
- # If the custom lockfile doesn't include `ruby-lsp` or `debug`, we need to run bundle install before updating
340
- return false if custom_bundle_dependencies.values_at("ruby-lsp", "debug").any?(&:nil?)
339
+ # If the composed lockfile doesn't include `ruby-lsp` or `debug`, we need to run bundle install before updating
340
+ return false if composed_bundle_dependencies.values_at("ruby-lsp", "debug").any?(&:nil?)
341
341
  end
342
342
 
343
343
  # If the last updated file doesn't exist or was updated more than 4 hours ago, we should update
@@ -359,6 +359,9 @@ module RubyLsp
359
359
  else
360
360
  match
361
361
  end
362
+ rescue URI::InvalidURIError, URI::InvalidComponentError
363
+ # If the path raises an invalid error, it might be a git ssh path, which indeed isn't a URI
364
+ match
362
365
  end
363
366
 
364
367
  @custom_lockfile.write(content)
@@ -7,9 +7,6 @@ module RubyLsp
7
7
 
8
8
  class NonExistingDocumentError < StandardError; end
9
9
 
10
- sig { returns(T::Boolean) }
11
- attr_accessor :supports_progress
12
-
13
10
  sig { returns(T::Hash[Symbol, RequestConfig]) }
14
11
  attr_accessor :features_configuration
15
12
 
@@ -19,7 +16,6 @@ module RubyLsp
19
16
  sig { void }
20
17
  def initialize
21
18
  @state = T.let({}, T::Hash[String, Document[T.untyped]])
22
- @supports_progress = T.let(true, T::Boolean)
23
19
  @features_configuration = T.let(
24
20
  {
25
21
  inlayHint: RequestConfig.new({
@@ -87,6 +87,61 @@ module RubyLsp
87
87
  params: data,
88
88
  )
89
89
  end
90
+
91
+ sig do
92
+ params(
93
+ id: String,
94
+ title: String,
95
+ percentage: T.nilable(Integer),
96
+ message: T.nilable(String),
97
+ ).returns(Notification)
98
+ end
99
+ def progress_begin(id, title, percentage: nil, message: nil)
100
+ new(
101
+ method: "$/progress",
102
+ params: Interface::ProgressParams.new(
103
+ token: id,
104
+ value: Interface::WorkDoneProgressBegin.new(
105
+ kind: "begin",
106
+ title: title,
107
+ percentage: percentage,
108
+ message: message,
109
+ ),
110
+ ),
111
+ )
112
+ end
113
+
114
+ sig do
115
+ params(
116
+ id: String,
117
+ percentage: T.nilable(Integer),
118
+ message: T.nilable(String),
119
+ ).returns(Notification)
120
+ end
121
+ def progress_report(id, percentage: nil, message: nil)
122
+ new(
123
+ method: "$/progress",
124
+ params: Interface::ProgressParams.new(
125
+ token: id,
126
+ value: Interface::WorkDoneProgressReport.new(
127
+ kind: "report",
128
+ percentage: percentage,
129
+ message: message,
130
+ ),
131
+ ),
132
+ )
133
+ end
134
+
135
+ sig { params(id: String).returns(Notification) }
136
+ def progress_end(id)
137
+ Notification.new(
138
+ method: "$/progress",
139
+ params: Interface::ProgressParams.new(
140
+ token: id,
141
+ value: Interface::WorkDoneProgressEnd.new(kind: "end"),
142
+ ),
143
+ )
144
+ end
90
145
  end
91
146
 
92
147
  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.21.0
4
+ version: 0.22.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-31 00:00:00.000000000 Z
11
+ date: 2024-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: language_server-protocol
@@ -217,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
217
  - !ruby/object:Gem::Version
218
218
  version: '0'
219
219
  requirements: []
220
- rubygems_version: 3.5.22
220
+ rubygems_version: 3.5.23
221
221
  signing_key:
222
222
  specification_version: 4
223
223
  summary: An opinionated language server for Ruby