ruby-lsp 0.16.1 → 0.16.3

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: b52249bb9ff4600edc041d0ac28d961c7670f5dad2475b632fa5ea87c02e1657
4
- data.tar.gz: c15ed4c4cd012c64f526ce3c31ca0f70a248467a44034dc6ffeed50cda94d9ad
3
+ metadata.gz: 906f8ef7ff4c3c0da126b61e41772b36989c93e391575099121c7a31184de81c
4
+ data.tar.gz: 67eb8cd92613348b9b2bf7163b458ed0ba7772e4c0304c01b80e3b0c4e8b34c7
5
5
  SHA512:
6
- metadata.gz: bf9936e23669e947cc802e5efe4fc5466528dff0e290d3daf255522cdca7e41d08802737da2f93b0690ca3abf3916a726926b454964f21a67bb661e902494390
7
- data.tar.gz: 6d6b39a1dfe90b54e4e20a1a4eda471a71418b85c94ee305c5e9b1a77be8251a304d0da9f4c72fae28773e14bdb1f316da12ce41ef436c2bc72d78903a647fb1
6
+ metadata.gz: e6b28979f399686bf62943bb49036ed26411a11439120f8ddf52f7c86310ecc8964d32de8fffe98c12686021f8d2b019c49347de4ced546a1a2e4e1b47726bfd
7
+ data.tar.gz: 3339ddda6a9450cf4449a0336a38ec4bdd95b4d81e9b2aa834bfd87db11f3bb2d0caf02e5ad4d0366f040d4718046e36744750e46ef9638b78a4235f0dfad1b7
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.16.1
1
+ 0.16.3
@@ -20,13 +20,13 @@ module RubyLsp
20
20
  sig { returns(URI::Generic) }
21
21
  attr_reader :uri
22
22
 
23
- sig { returns(String) }
23
+ sig { returns(Encoding) }
24
24
  attr_reader :encoding
25
25
 
26
- sig { params(source: String, version: Integer, uri: URI::Generic, encoding: String).void }
27
- def initialize(source:, version:, uri:, encoding: Constant::PositionEncodingKind::UTF8)
26
+ sig { params(source: String, version: Integer, uri: URI::Generic, encoding: Encoding).void }
27
+ def initialize(source:, version:, uri:, encoding: Encoding::UTF_8)
28
28
  @cache = T.let({}, T::Hash[String, T.untyped])
29
- @encoding = T.let(encoding, String)
29
+ @encoding = T.let(encoding, Encoding)
30
30
  @source = T.let(source, String)
31
31
  @version = T.let(version, Integer)
32
32
  @uri = T.let(uri, URI::Generic)
@@ -187,7 +187,7 @@ module RubyLsp
187
187
  # After character 0xFFFF, UTF-16 considers characters to have length 2 and we have to account for that
188
188
  SURROGATE_PAIR_START = T.let(0xFFFF, Integer)
189
189
 
190
- sig { params(source: String, encoding: String).void }
190
+ sig { params(source: String, encoding: Encoding).void }
191
191
  def initialize(source, encoding)
192
192
  @current_line = T.let(0, Integer)
193
193
  @pos = T.let(0, Integer)
@@ -209,7 +209,7 @@ module RubyLsp
209
209
  # need to adjust for surrogate pairs
210
210
  requested_position = @pos + position[:character]
211
211
 
212
- if @encoding == Constant::PositionEncodingKind::UTF16
212
+ if @encoding == Encoding::UTF_16LE
213
213
  requested_position -= utf_16_character_position_correction(@pos, requested_position)
214
214
  end
215
215
 
@@ -17,11 +17,15 @@ module RubyLsp
17
17
  sig { returns(RubyIndexer::Index) }
18
18
  attr_reader :index
19
19
 
20
+ sig { returns(Encoding) }
21
+ attr_reader :encoding
22
+
20
23
  sig { void }
21
24
  def initialize
22
25
  @workspace_uri = T.let(URI::Generic.from_path(path: Dir.pwd), URI::Generic)
26
+ @encoding = T.let(Encoding::UTF_8, Encoding)
23
27
 
24
- @formatter = T.let(detect_formatter, String)
28
+ @formatter = T.let("auto", String)
25
29
  @test_library = T.let(detect_test_library, String)
26
30
  @typechecker = T.let(detect_typechecker, T::Boolean)
27
31
  @index = T.let(RubyIndexer::Index.new, RubyIndexer::Index)
@@ -42,6 +46,21 @@ module RubyLsp
42
46
  def apply_options(options)
43
47
  workspace_uri = options.dig(:workspaceFolders, 0, :uri)
44
48
  @workspace_uri = URI(workspace_uri) if workspace_uri
49
+
50
+ specified_formatter = options.dig(:initializationOptions, :formatter)
51
+ @formatter = specified_formatter if specified_formatter
52
+ @formatter = detect_formatter if @formatter == "auto"
53
+
54
+ encodings = options.dig(:capabilities, :general, :positionEncodings)
55
+ @encoding = if !encodings || encodings.empty?
56
+ Encoding::UTF_16LE
57
+ elsif encodings.include?(Constant::PositionEncodingKind::UTF8)
58
+ Encoding::UTF_8
59
+ elsif encodings.include?(Constant::PositionEncodingKind::UTF16)
60
+ Encoding::UTF_16LE
61
+ else
62
+ Encoding::UTF_32
63
+ end
45
64
  end
46
65
 
47
66
  sig { returns(String) }
@@ -49,6 +68,25 @@ module RubyLsp
49
68
  T.must(@workspace_uri.to_standardized_path)
50
69
  end
51
70
 
71
+ sig { returns(String) }
72
+ def encoding_name
73
+ case @encoding
74
+ when Encoding::UTF_8
75
+ Constant::PositionEncodingKind::UTF8
76
+ when Encoding::UTF_16LE
77
+ Constant::PositionEncodingKind::UTF16
78
+ else
79
+ Constant::PositionEncodingKind::UTF32
80
+ end
81
+ end
82
+
83
+ sig { params(gem_pattern: Regexp).returns(T::Boolean) }
84
+ def direct_dependency?(gem_pattern)
85
+ dependencies.any?(gem_pattern)
86
+ end
87
+
88
+ private
89
+
52
90
  sig { returns(String) }
53
91
  def detect_formatter
54
92
  # NOTE: Intentionally no $ at end, since we want to match rubocop-shopify, etc.
@@ -66,8 +104,10 @@ module RubyLsp
66
104
  if direct_dependency?(/^rspec/)
67
105
  "rspec"
68
106
  # A Rails app may have a dependency on minitest, but we would instead want to use the Rails test runner provided
69
- # by ruby-lsp-rails.
70
- elsif direct_dependency?(/^rails$/)
107
+ # by ruby-lsp-rails. A Rails app doesn't need to depend on the rails gem itself, individual components like
108
+ # activestorage may be added to the gemfile so that other components aren't downloaded. Check for the presence
109
+ # of bin/rails to support these cases.
110
+ elsif File.exist?(File.join(workspace_path, "bin/rails"))
71
111
  "rails"
72
112
  # NOTE: Intentionally ends with $ to avoid mis-matching minitest-reporters, etc. in a Rails app.
73
113
  elsif direct_dependency?(/^minitest$/)
@@ -79,11 +119,6 @@ module RubyLsp
79
119
  end
80
120
  end
81
121
 
82
- sig { params(gem_pattern: Regexp).returns(T::Boolean) }
83
- def direct_dependency?(gem_pattern)
84
- dependencies.any?(gem_pattern)
85
- end
86
-
87
122
  sig { returns(T::Boolean) }
88
123
  def detect_typechecker
89
124
  return false if ENV["RUBY_LSP_BYPASS_TYPECHECKER"]
@@ -68,17 +68,22 @@ module RubyLsp
68
68
  command: generate_test_command(group_stack: @group_stack),
69
69
  kind: :group,
70
70
  )
71
- end
72
71
 
73
- @group_id_stack.push(@group_id)
74
- @group_id += 1
72
+ @group_id_stack.push(@group_id)
73
+ @group_id += 1
74
+ end
75
75
  end
76
76
 
77
77
  sig { params(node: Prism::ClassNode).void }
78
78
  def on_class_node_leave(node)
79
79
  @visibility_stack.pop
80
80
  @group_stack.pop
81
- @group_id_stack.pop
81
+
82
+ class_name = node.constant_path.slice
83
+
84
+ if @path && class_name.end_with?("Test")
85
+ @group_id_stack.pop
86
+ end
82
87
  end
83
88
 
84
89
  sig { params(node: Prism::DefNode).void }
@@ -163,7 +163,7 @@ module RubyLsp
163
163
 
164
164
  sig { params(line: String).returns(Integer) }
165
165
  def length_of_line(line)
166
- if @document.encoding == Constant::PositionEncodingKind::UTF16
166
+ if @document.encoding == Encoding::UTF_16LE
167
167
  line_length = 0
168
168
  line.codepoints.each do |codepoint|
169
169
  line_length += 1
@@ -118,19 +118,8 @@ module RubyLsp
118
118
  client_name = options.dig(:clientInfo, :name)
119
119
  @store.client_name = client_name if client_name
120
120
 
121
- encodings = options.dig(:capabilities, :general, :positionEncodings)
122
- @store.encoding = if encodings.nil? || encodings.empty?
123
- Constant::PositionEncodingKind::UTF16
124
- elsif encodings.include?(Constant::PositionEncodingKind::UTF8)
125
- Constant::PositionEncodingKind::UTF8
126
- else
127
- encodings.first
128
- end
129
-
130
121
  progress = options.dig(:capabilities, :window, :workDoneProgress)
131
122
  @store.supports_progress = progress.nil? ? true : progress
132
- formatter = options.dig(:initializationOptions, :formatter) || "auto"
133
-
134
123
  configured_features = options.dig(:initializationOptions, :enabledFeatures)
135
124
  @store.experimental_features = options.dig(:initializationOptions, :experimentalFeaturesEnabled) || false
136
125
 
@@ -170,14 +159,14 @@ module RubyLsp
170
159
  change: Constant::TextDocumentSyncKind::INCREMENTAL,
171
160
  open_close: true,
172
161
  ),
173
- position_encoding: @store.encoding,
162
+ position_encoding: @global_state.encoding_name,
174
163
  selection_range_provider: enabled_features["selectionRanges"],
175
164
  hover_provider: hover_provider,
176
165
  document_symbol_provider: document_symbol_provider,
177
166
  document_link_provider: document_link_provider,
178
167
  folding_range_provider: folding_ranges_provider,
179
168
  semantic_tokens_provider: semantic_tokens_provider,
180
- document_formatting_provider: enabled_features["formatting"] && formatter != "none",
169
+ document_formatting_provider: enabled_features["formatting"] && @global_state.formatter != "none",
181
170
  document_highlight_provider: enabled_features["documentHighlights"],
182
171
  code_action_provider: code_action_provider,
183
172
  document_on_type_formatting_provider: on_type_formatting_provider,
@@ -271,25 +260,31 @@ module RubyLsp
271
260
 
272
261
  sig { params(message: T::Hash[Symbol, T.untyped]).void }
273
262
  def text_document_did_open(message)
274
- text_document = message.dig(:params, :textDocument)
275
- @store.set(uri: text_document[:uri], source: text_document[:text], version: text_document[:version])
276
- rescue Errno::ENOENT
277
- # If someone re-opens the editor with a file that was deleted or doesn't exist in the current branch, we don't
278
- # want to crash
263
+ @mutex.synchronize do
264
+ text_document = message.dig(:params, :textDocument)
265
+ @store.set(
266
+ uri: text_document[:uri],
267
+ source: text_document[:text],
268
+ version: text_document[:version],
269
+ encoding: @global_state.encoding,
270
+ )
271
+ end
279
272
  end
280
273
 
281
274
  sig { params(message: T::Hash[Symbol, T.untyped]).void }
282
275
  def text_document_did_close(message)
283
- uri = message.dig(:params, :textDocument, :uri)
284
- @store.delete(uri)
276
+ @mutex.synchronize do
277
+ uri = message.dig(:params, :textDocument, :uri)
278
+ @store.delete(uri)
285
279
 
286
- # Clear diagnostics for the closed file, so that they no longer appear in the problems tab
287
- send_message(
288
- Notification.new(
289
- method: "textDocument/publishDiagnostics",
290
- params: Interface::PublishDiagnosticsParams.new(uri: uri.to_s, diagnostics: []),
291
- ),
292
- )
280
+ # Clear diagnostics for the closed file, so that they no longer appear in the problems tab
281
+ send_message(
282
+ Notification.new(
283
+ method: "textDocument/publishDiagnostics",
284
+ params: Interface::PublishDiagnosticsParams.new(uri: uri.to_s, diagnostics: []),
285
+ ),
286
+ )
287
+ end
293
288
  end
294
289
 
295
290
  sig { params(message: T::Hash[Symbol, T.untyped]).void }
@@ -19,6 +19,7 @@ module RubyLsp
19
19
  extend T::Sig
20
20
 
21
21
  class BundleNotLocked < StandardError; end
22
+ class BundleInstallFailure < StandardError; end
22
23
 
23
24
  FOUR_HOURS = T.let(4 * 60 * 60, Integer)
24
25
 
@@ -49,6 +50,7 @@ module RubyLsp
49
50
  @last_updated_path = T.let(@custom_dir + "last_updated", Pathname)
50
51
 
51
52
  @dependencies = T.let(load_dependencies, T::Hash[String, T.untyped])
53
+ @retry = T.let(false, T::Boolean)
52
54
  end
53
55
 
54
56
  # Sets up the custom bundle and returns the `BUNDLE_GEMFILE`, `BUNDLE_PATH` and `BUNDLE_APP_CONFIG` that should be
@@ -224,7 +226,17 @@ module RubyLsp
224
226
  # Add bundle update
225
227
  $stderr.puts("Ruby LSP> Running bundle install for the custom bundle. This may take a while...")
226
228
  $stderr.puts("Ruby LSP> Command: #{command}")
227
- system(env, command)
229
+
230
+ # Try to run the bundle install or update command. If that fails, it normally means that the custom lockfile is in
231
+ # a bad state that no longer reflects the top level one. In that case, we can remove the whole directory, try
232
+ # another time and give up if it fails again
233
+ if !system(env, command) && !@retry && @custom_dir.exist?
234
+ @retry = true
235
+ @custom_dir.rmtree
236
+ $stderr.puts("Ruby LSP> Running bundle install failed. Trying to re-generate the custom bundle from scratch")
237
+ return setup!
238
+ end
239
+
228
240
  [bundle_gemfile.to_s, expanded_path, env["BUNDLE_APP_CONFIG"]]
229
241
  end
230
242
 
@@ -5,9 +5,6 @@ module RubyLsp
5
5
  class Store
6
6
  extend T::Sig
7
7
 
8
- sig { returns(String) }
9
- attr_accessor :encoding
10
-
11
8
  sig { returns(T::Boolean) }
12
9
  attr_accessor :supports_progress
13
10
 
@@ -23,7 +20,6 @@ module RubyLsp
23
20
  sig { void }
24
21
  def initialize
25
22
  @state = T.let({}, T::Hash[String, Document])
26
- @encoding = T.let(Constant::PositionEncodingKind::UTF8, String)
27
23
  @supports_progress = T.let(true, T::Boolean)
28
24
  @experimental_features = T.let(false, T::Boolean)
29
25
  @features_configuration = T.let(
@@ -49,9 +45,9 @@ module RubyLsp
49
45
  T.must(@state[uri.to_s])
50
46
  end
51
47
 
52
- sig { params(uri: URI::Generic, source: String, version: Integer).void }
53
- def set(uri:, source:, version:)
54
- document = RubyDocument.new(source: source, version: version, uri: uri, encoding: @encoding)
48
+ sig { params(uri: URI::Generic, source: String, version: Integer, encoding: Encoding).void }
49
+ def set(uri:, source:, version:, encoding: Encoding::UTF_8)
50
+ document = RubyDocument.new(source: source, version: version, uri: uri, encoding: encoding)
55
51
  @state[uri.to_s] = document
56
52
  end
57
53
 
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.16.1
4
+ version: 0.16.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-04 00:00:00.000000000 Z
11
+ date: 2024-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: language_server-protocol