ruby-lsp 0.26.2 → 0.26.9

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +7 -10
  4. data/exe/ruby-lsp-launcher +16 -3
  5. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +3 -2
  6. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +19 -0
  7. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +33 -27
  8. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +7 -2
  9. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +6 -2
  10. data/lib/ruby_lsp/base_server.rb +23 -12
  11. data/lib/ruby_lsp/global_state.rb +65 -33
  12. data/lib/ruby_lsp/listeners/definition.rb +34 -14
  13. data/lib/ruby_lsp/listeners/document_link.rb +62 -23
  14. data/lib/ruby_lsp/listeners/hover.rb +2 -2
  15. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +2 -2
  16. data/lib/ruby_lsp/requests/code_action_resolve.rb +33 -11
  17. data/lib/ruby_lsp/requests/code_actions.rb +20 -5
  18. data/lib/ruby_lsp/requests/completion_resolve.rb +8 -6
  19. data/lib/ruby_lsp/requests/support/package_url.rb +414 -0
  20. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +7 -1
  21. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +6 -10
  22. data/lib/ruby_lsp/requests/support/source_uri.rb +7 -6
  23. data/lib/ruby_lsp/requests/workspace_symbol.rb +20 -12
  24. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +3 -3
  25. data/lib/ruby_lsp/scripts/compose_bundle.rb +3 -3
  26. data/lib/ruby_lsp/scripts/compose_bundle_windows.rb +3 -1
  27. data/lib/ruby_lsp/server.rb +5 -2
  28. data/lib/ruby_lsp/setup_bundler.rb +68 -37
  29. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +50 -27
  30. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +1 -1
  31. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +1 -1
  32. metadata +3 -16
  33. data/lib/ruby_indexer/test/class_variables_test.rb +0 -140
  34. data/lib/ruby_indexer/test/classes_and_modules_test.rb +0 -770
  35. data/lib/ruby_indexer/test/configuration_test.rb +0 -279
  36. data/lib/ruby_indexer/test/constant_test.rb +0 -402
  37. data/lib/ruby_indexer/test/enhancements_test.rb +0 -325
  38. data/lib/ruby_indexer/test/global_variable_test.rb +0 -49
  39. data/lib/ruby_indexer/test/index_test.rb +0 -2276
  40. data/lib/ruby_indexer/test/instance_variables_test.rb +0 -264
  41. data/lib/ruby_indexer/test/method_test.rb +0 -990
  42. data/lib/ruby_indexer/test/prefix_tree_test.rb +0 -150
  43. data/lib/ruby_indexer/test/rbs_indexer_test.rb +0 -381
  44. data/lib/ruby_indexer/test/reference_finder_test.rb +0 -395
  45. data/lib/ruby_indexer/test/test_case.rb +0 -57
  46. data/lib/ruby_indexer/test/uri_test.rb +0 -85
@@ -0,0 +1,414 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ # This is a copy of the implementation from the `package_url` gem with the
5
+ # following license. Original source can be found at:
6
+ # https://github.com/package-url/packageurl-ruby/blob/main/lib/package_url.rb
7
+
8
+ # MIT License
9
+ #
10
+ # Copyright (c) 2021 package-url
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ # of this software and associated documentation files (the "Software"), to deal
14
+ # in the Software without restriction, including without limitation the rights
15
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ # copies of the Software, and to permit persons to whom the Software is
17
+ # furnished to do so, subject to the following conditions:
18
+ #
19
+ # The above copyright notice and this permission notice shall be included in all
20
+ # copies or substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ # SOFTWARE.
29
+
30
+ require "uri"
31
+
32
+ # A package URL, or _purl_, is a URL string used to
33
+ # identify and locate a software package in a mostly universal and uniform way
34
+ # across programing languages, package managers, packaging conventions, tools,
35
+ # APIs and databases.
36
+ #
37
+ # A purl is a URL composed of seven components:
38
+ #
39
+ # ```
40
+ # scheme:type/namespace/name@version?qualifiers#subpath
41
+ # ```
42
+ #
43
+ # For example,
44
+ # the package URL for this Ruby package at version 0.1.0 is
45
+ # `pkg:ruby/mattt/packageurl-ruby@0.1.0`.
46
+ module RubyLsp
47
+ class PackageURL
48
+ # Raised when attempting to parse an invalid package URL string.
49
+ # @see #parse
50
+ class InvalidPackageURL < ArgumentError; end
51
+
52
+ # The URL scheme, which has a constant value of `"pkg"`.
53
+ def scheme
54
+ "pkg"
55
+ end
56
+
57
+ # The package type or protocol, such as `"gem"`, `"npm"`, and `"github"`.
58
+ attr_reader :type
59
+
60
+ # A name prefix, specific to the type of package.
61
+ # For example, an npm scope, a Docker image owner, or a GitHub user.
62
+ attr_reader :namespace
63
+
64
+ # The name of the package.
65
+ attr_reader :name
66
+
67
+ # The version of the package.
68
+ attr_reader :version
69
+
70
+ # Extra qualifying data for a package, specific to the type of package.
71
+ # For example, the operating system or architecture.
72
+ attr_reader :qualifiers
73
+
74
+ # An extra subpath within a package, relative to the package root.
75
+ attr_reader :subpath
76
+
77
+ # Constructs a package URL from its components
78
+ # @param type [String] The package type or protocol.
79
+ # @param namespace [String] A name prefix, specific to the type of package.
80
+ # @param name [String] The name of the package.
81
+ # @param version [String] The version of the package.
82
+ # @param qualifiers [Hash] Extra qualifying data for a package, specific to the type of package.
83
+ # @param subpath [String] An extra subpath within a package, relative to the package root.
84
+ def initialize(type:, name:, namespace: nil, version: nil, qualifiers: nil, subpath: nil)
85
+ raise ArgumentError, "type is required" if type.nil? || type.empty?
86
+ raise ArgumentError, "name is required" if name.nil? || name.empty?
87
+
88
+ @type = type.downcase
89
+ @namespace = namespace
90
+ @name = name
91
+ @version = version
92
+ @qualifiers = qualifiers
93
+ @subpath = subpath
94
+ end
95
+
96
+ # Creates a new PackageURL from a string.
97
+ # @param [String] string The package URL string.
98
+ # @raise [InvalidPackageURL] If the string is not a valid package URL.
99
+ # @return [PackageURL]
100
+ def self.parse(string)
101
+ components = {
102
+ type: nil,
103
+ namespace: nil,
104
+ name: nil,
105
+ version: nil,
106
+ qualifiers: nil,
107
+ subpath: nil,
108
+ }
109
+
110
+ # Split the purl string once from right on '#'
111
+ # - The left side is the remainder
112
+ # - Strip the right side from leading and trailing '/'
113
+ # - Split this on '/'
114
+ # - Discard any empty string segment from that split
115
+ # - Discard any '.' or '..' segment from that split
116
+ # - Percent-decode each segment
117
+ # - UTF-8-decode each segment if needed in your programming language
118
+ # - Join segments back with a '/'
119
+ # - This is the subpath
120
+ case string.rpartition("#")
121
+ in String => remainder, separator, String => subpath unless separator.empty?
122
+ subpath_components = []
123
+ subpath.split("/").each do |segment|
124
+ next if segment.empty? || segment == "." || segment == ".."
125
+
126
+ subpath_components << URI.decode_www_form_component(segment)
127
+ end
128
+
129
+ components[:subpath] = subpath_components.compact.join("/")
130
+
131
+ string = remainder
132
+ else
133
+ components[:subpath] = nil
134
+ end
135
+
136
+ # Split the remainder once from right on '?'
137
+ # - The left side is the remainder
138
+ # - The right side is the qualifiers string
139
+ # - Split the qualifiers on '&'. Each part is a key=value pair
140
+ # - For each pair, split the key=value once from left on '=':
141
+ # - The key is the lowercase left side
142
+ # - The value is the percent-decoded right side
143
+ # - UTF-8-decode the value if needed in your programming language
144
+ # - Discard any key/value pairs where the value is empty
145
+ # - If the key is checksums,
146
+ # split the value on ',' to create a list of checksums
147
+ # - This list of key/value is the qualifiers object
148
+ case string.rpartition("?")
149
+ in String => remainder, separator, String => qualifiers unless separator.empty?
150
+ components[:qualifiers] = {}
151
+
152
+ qualifiers.split("&").each do |pair|
153
+ case pair.partition("=")
154
+ in String => key, separator, String => value unless separator.empty?
155
+ key = key.downcase
156
+ value = URI.decode_www_form_component(value)
157
+ next if value.empty?
158
+
159
+ components[:qualifiers][key] = case key
160
+ when "checksums"
161
+ value.split(",")
162
+ else
163
+ value
164
+ end
165
+ else
166
+ next
167
+ end
168
+ end
169
+
170
+ string = remainder
171
+ else
172
+ components[:qualifiers] = nil
173
+ end
174
+
175
+ # Split the remainder once from left on ':'
176
+ # - The left side lowercased is the scheme
177
+ # - The right side is the remainder
178
+ case string.partition(":")
179
+ in "pkg", separator, String => remainder unless separator.empty?
180
+ string = remainder
181
+ else
182
+ raise InvalidPackageURL, 'invalid or missing "pkg:" URL scheme'
183
+ end
184
+
185
+ # Strip the remainder from leading and trailing '/'
186
+ # Use gsub to remove ALL leading slashes instead of just one
187
+ string = string.gsub(%r{^/+}, "").delete_suffix("/")
188
+ # - Split this once from left on '/'
189
+ # - The left side lowercased is the type
190
+ # - The right side is the remainder
191
+ case string.partition("/")
192
+ in String => type, separator, remainder unless separator.empty?
193
+ components[:type] = type
194
+
195
+ string = remainder
196
+ else
197
+ raise InvalidPackageURL, "invalid or missing package type"
198
+ end
199
+
200
+ # Split the remainder once from right on '@'
201
+ # - The left side is the remainder
202
+ # - Percent-decode the right side. This is the version.
203
+ # - UTF-8-decode the version if needed in your programming language
204
+ # - This is the version
205
+ case string.rpartition("@")
206
+ in String => remainder, separator, String => version unless separator.empty?
207
+ components[:version] = URI.decode_www_form_component(version)
208
+
209
+ string = remainder
210
+ else
211
+ components[:version] = nil
212
+ end
213
+
214
+ # Split the remainder once from right on '/'
215
+ # - The left side is the remainder
216
+ # - Percent-decode the right side. This is the name
217
+ # - UTF-8-decode this name if needed in your programming language
218
+ # - Apply type-specific normalization to the name if needed
219
+ # - This is the name
220
+ case string.rpartition("/")
221
+ in String => remainder, separator, String => name unless separator.empty?
222
+ components[:name] = URI.decode_www_form_component(name)
223
+
224
+ # Split the remainder on '/'
225
+ # - Discard any empty segment from that split
226
+ # - Percent-decode each segment
227
+ # - UTF-8-decode the each segment if needed in your programming language
228
+ # - Apply type-specific normalization to each segment if needed
229
+ # - Join segments back with a '/'
230
+ # - This is the namespace
231
+ components[:namespace] = remainder.split("/").map { |s| URI.decode_www_form_component(s) }.compact.join("/")
232
+ in _, _, String => name
233
+ components[:name] = URI.decode_www_form_component(name)
234
+ components[:namespace] = nil
235
+ end
236
+
237
+ # Ensure type and name are not nil before creating the PackageURL instance
238
+ raise InvalidPackageURL, "missing package type" if components[:type].nil?
239
+ raise InvalidPackageURL, "missing package name" if components[:name].nil?
240
+
241
+ # Create a new PackageURL with validated components
242
+ type = components[:type] || "" # This ensures type is never nil
243
+ name = components[:name] || "" # This ensures name is never nil
244
+
245
+ new(
246
+ type: type,
247
+ name: name,
248
+ namespace: components[:namespace],
249
+ version: components[:version],
250
+ qualifiers: components[:qualifiers],
251
+ subpath: components[:subpath],
252
+ )
253
+ end
254
+
255
+ # Returns a hash containing the
256
+ # scheme, type, namespace, name, version, qualifiers, and subpath components
257
+ # of the package URL.
258
+ def to_h
259
+ {
260
+ scheme: scheme,
261
+ type: @type,
262
+ namespace: @namespace,
263
+ name: @name,
264
+ version: @version,
265
+ qualifiers: @qualifiers,
266
+ subpath: @subpath,
267
+ }
268
+ end
269
+
270
+ # Returns a string representation of the package URL.
271
+ # Package URL representations are created according to the instructions from
272
+ # https://github.com/package-url/purl-spec/blob/0b1559f76b79829e789c4f20e6d832c7314762c5/PURL-SPECIFICATION.rst#how-to-build-purl-string-from-its-components.
273
+ def to_s
274
+ # Start a purl string with the "pkg:" scheme as a lowercase ASCII string
275
+ purl = "pkg:"
276
+
277
+ # Append the type string to the purl as a lowercase ASCII string
278
+ # Append '/' to the purl
279
+
280
+ purl += @type
281
+ purl += "/"
282
+
283
+ # If the namespace is not empty:
284
+ # - Strip the namespace from leading and trailing '/'
285
+ # - Split on '/' as segments
286
+ # - Apply type-specific normalization to each segment if needed
287
+ # - UTF-8-encode each segment if needed in your programming language
288
+ # - Percent-encode each segment
289
+ # - Join the segments with '/'
290
+ # - Append this to the purl
291
+ # - Append '/' to the purl
292
+ # - Strip the name from leading and trailing '/'
293
+ # - Apply type-specific normalization to the name if needed
294
+ # - UTF-8-encode the name if needed in your programming language
295
+ # - Append the percent-encoded name to the purl
296
+ #
297
+ # If the namespace is empty:
298
+ # - Apply type-specific normalization to the name if needed
299
+ # - UTF-8-encode the name if needed in your programming language
300
+ # - Append the percent-encoded name to the purl
301
+ case @namespace
302
+ in String => namespace unless namespace.empty?
303
+ segments = []
304
+ @namespace.delete_prefix("/").delete_suffix("/").split("/").each do |segment|
305
+ next if segment.empty?
306
+
307
+ segments << URI.encode_www_form_component(segment)
308
+ end
309
+ purl += segments.join("/")
310
+
311
+ purl += "/"
312
+ purl += URI.encode_www_form_component(@name.delete_prefix("/").delete_suffix("/"))
313
+ else
314
+ purl += URI.encode_www_form_component(@name)
315
+ end
316
+
317
+ # If the version is not empty:
318
+ # - Append '@' to the purl
319
+ # - UTF-8-encode the version if needed in your programming language
320
+ # - Append the percent-encoded version to the purl
321
+ case @version
322
+ in String => version unless version.empty?
323
+ purl += "@"
324
+ purl += URI.encode_www_form_component(@version)
325
+ else
326
+ nil
327
+ end
328
+
329
+ # If the qualifiers are not empty and not composed only of key/value pairs
330
+ # where the value is empty:
331
+ # - Append '?' to the purl
332
+ # - Build a list from all key/value pair:
333
+ # - discard any pair where the value is empty.
334
+ # - UTF-8-encode each value if needed in your programming language
335
+ # - If the key is checksums and this is a list of checksums
336
+ # join this list with a ',' to create this qualifier value
337
+ # - create a string by joining the lowercased key,
338
+ # the equal '=' sign and the percent-encoded value to create a qualifier
339
+ # - sort this list of qualifier strings lexicographically
340
+ # - join this list of qualifier strings with a '&' ampersand
341
+ # - Append this string to the purl
342
+ case @qualifiers
343
+ in Hash => qualifiers unless qualifiers.empty?
344
+ list = []
345
+ qualifiers.each do |key, value|
346
+ next if value.empty?
347
+
348
+ list << case [key, value]
349
+ in "checksums", Array => checksums
350
+ "#{key.downcase}=#{checksums.join(",")}"
351
+ else
352
+ "#{key.downcase}=#{URI.encode_www_form_component(value)}"
353
+ end
354
+ end
355
+
356
+ unless list.empty?
357
+ purl += "?"
358
+ purl += list.sort.join("&")
359
+ end
360
+ else
361
+ nil
362
+ end
363
+
364
+ # If the subpath is not empty and not composed only of
365
+ # empty, '.' and '..' segments:
366
+ # - Append '#' to the purl
367
+ # - Strip the subpath from leading and trailing '/'
368
+ # - Split this on '/' as segments
369
+ # - Discard empty, '.' and '..' segments
370
+ # - Percent-encode each segment
371
+ # - UTF-8-encode each segment if needed in your programming language
372
+ # - Join the segments with '/'
373
+ # - Append this to the purl
374
+ case @subpath
375
+ in String => subpath unless subpath.empty?
376
+ segments = []
377
+ subpath.delete_prefix("/").delete_suffix("/").split("/").each do |segment|
378
+ next if segment.empty? || segment == "." || segment == ".."
379
+
380
+ # Custom encoding for URL fragment segments:
381
+ # 1. Explicitly encode % as %25 to prevent double-encoding issues
382
+ # 2. Percent-encode special characters according to URL fragment rules
383
+ # 3. This ensures proper round-trip encoding/decoding with the parse method
384
+ segments << segment.gsub(/%|[^A-Za-z0-9\-\._~]/) do |m|
385
+ m == "%" ? "%25" : format("%%%02X", m.ord)
386
+ end
387
+ end
388
+
389
+ unless segments.empty?
390
+ purl += "#"
391
+ purl += segments.join("/")
392
+ end
393
+ else
394
+ nil
395
+ end
396
+
397
+ purl
398
+ end
399
+
400
+ # Returns an array containing the
401
+ # scheme, type, namespace, name, version, qualifiers, and subpath components
402
+ # of the package URL.
403
+ def deconstruct
404
+ [scheme, @type, @namespace, @name, @version, @qualifiers, @subpath]
405
+ end
406
+
407
+ # Returns a hash containing the
408
+ # scheme, type, namespace, name, version, qualifiers, and subpath components
409
+ # of the package URL.
410
+ def deconstruct_keys(_keys)
411
+ to_h
412
+ end
413
+ end
414
+ end
@@ -14,6 +14,12 @@ module RubyLsp
14
14
  fatal: Constant::DiagnosticSeverity::ERROR,
15
15
  }.freeze #: Hash[Symbol, Integer]
16
16
 
17
+ # Cops where adding a `rubocop:disable` inline comment would itself resolve the offense,
18
+ # causing Lint/RedundantCopDisableDirective to flag the disable as unnecessary.
19
+ SELF_RESOLVING_DISABLE_COPS = Set.new([
20
+ "Layout/EmptyComment",
21
+ ]).freeze #: Set[String]
22
+
17
23
  ENHANCED_DOC_URL = begin
18
24
  gem("rubocop", ">= 1.64.0")
19
25
  true
@@ -35,7 +41,7 @@ module RubyLsp
35
41
  code_actions = []
36
42
 
37
43
  code_actions << autocorrect_action if correctable?
38
- code_actions << disable_line_action
44
+ code_actions << disable_line_action unless SELF_RESOLVING_DISABLE_COPS.include?(@offense.cop_name)
39
45
 
40
46
  code_actions
41
47
  end
@@ -61,14 +61,6 @@ module RubyLsp
61
61
  "RuboCop::Formatter::BaseFormatter", # Suppress any output by using the base formatter
62
62
  ] #: Array[String]
63
63
 
64
- # Functionality was introduced in 1.75.0 but had issues with autocorrect
65
- REUSE_PRISM_RESULT = begin
66
- gem("rubocop", ">= 1.80.1")
67
- true
68
- rescue LoadError
69
- false
70
- end #: bool
71
-
72
64
  #: Array[::RuboCop::Cop::Offense]
73
65
  attr_reader :offenses
74
66
 
@@ -89,7 +81,7 @@ module RubyLsp
89
81
  @offenses = [] #: Array[::RuboCop::Cop::Offense]
90
82
  @errors = [] #: Array[String]
91
83
  @warnings = [] #: Array[String]
92
- @prism_result = nil #: Prism::ParseLexResult?
84
+ # @prism_result = nil #: Prism::ParseLexResult?
93
85
 
94
86
  args += DEFAULT_ARGS
95
87
  rubocop_options = ::RuboCop::Options.new.parse(args).first
@@ -109,7 +101,11 @@ module RubyLsp
109
101
  @warnings = []
110
102
  @offenses = []
111
103
  @options[:stdin] = contents
112
- @prism_result = prism_result if REUSE_PRISM_RESULT
104
+
105
+ # Setting the Prism result before running the RuboCop runner makes it reuse the existing AST and avoids
106
+ # double-parsing. Unfortunately, this leads to a bunch of cops failing to execute properly under LSP mode.
107
+ # Uncomment this once reusing the Prism result is more stable
108
+ # @prism_result = prism_result
113
109
 
114
110
  super([path])
115
111
 
@@ -5,6 +5,7 @@ require "uri/file"
5
5
 
6
6
  module URI
7
7
  # Must be kept in sync with the one in Tapioca
8
+ # https://github.com/Shopify/tapioca/blob/main/lib/tapioca/helpers/source_uri.rb
8
9
  class Source < URI::File
9
10
  COMPONENT = [
10
11
  :scheme,
@@ -21,16 +22,14 @@ module URI
21
22
  # have the uri gem in their own bundle and thus not use a compatible version.
22
23
  PARSER = const_defined?(:RFC2396_PARSER) ? RFC2396_PARSER : DEFAULT_PARSER #: RFC2396_Parser
23
24
 
24
- self #: as untyped # rubocop:disable Style/RedundantSelf
25
- .alias_method(:gem_name, :host)
26
- self #: as untyped # rubocop:disable Style/RedundantSelf
27
- .alias_method(:line_number, :fragment)
25
+ alias_method(:gem_name, :host)
26
+ alias_method(:line_number, :fragment)
28
27
 
29
28
  #: String?
30
29
  attr_reader :gem_version
31
30
 
32
31
  class << self
33
- #: (gem_name: String, gem_version: String?, path: String, line_number: String?) -> URI::Source
32
+ #: (gem_name: String, gem_version: String?, path: String, line_number: String?) -> instance
34
33
  def build(gem_name:, gem_version:, path:, line_number:)
35
34
  super(
36
35
  {
@@ -67,12 +66,14 @@ module URI
67
66
 
68
67
  #: -> String
69
68
  def to_s
70
- "source://#{gem_name}/#{gem_version}#{path}##{line_number}"
69
+ "source://#{gem_name}/#{gem_version}/#{path}##{line_number}"
71
70
  end
72
71
 
73
72
  if URI.respond_to?(:register_scheme)
73
+ # Handle URI 0.11.0 and newer https://github.com/ruby/uri/pull/26
74
74
  URI.register_scheme("SOURCE", self)
75
75
  else
76
+ # Fallback for URI <0.11.0
76
77
  @@schemes = @@schemes #: Hash[String, untyped] # rubocop:disable Style/ClassVars
77
78
  @@schemes["SOURCE"] = self
78
79
  end
@@ -20,17 +20,7 @@ module RubyLsp
20
20
  # @override
21
21
  #: -> Array[Interface::WorkspaceSymbol]
22
22
  def perform
23
- @index.fuzzy_search(@query).filter_map do |entry|
24
- uri = entry.uri
25
- file_path = uri.full_path
26
-
27
- # We only show symbols declared in the workspace
28
- in_dependencies = file_path && !not_in_dependencies?(file_path)
29
- next if in_dependencies
30
-
31
- # We should never show private symbols when searching the entire workspace
32
- next if entry.private?
33
-
23
+ fuzzy_search.filter_map do |entry|
34
24
  kind = kind_for_entry(entry)
35
25
  loc = entry.location
36
26
 
@@ -44,7 +34,7 @@ module RubyLsp
44
34
  container_name: container.join("::"),
45
35
  kind: kind,
46
36
  location: Interface::Location.new(
47
- uri: uri.to_s,
37
+ uri: entry.uri.to_s,
48
38
  range: Interface::Range.new(
49
39
  start: Interface::Position.new(line: loc.start_line - 1, character: loc.start_column),
50
40
  end: Interface::Position.new(line: loc.end_line - 1, character: loc.end_column),
@@ -53,6 +43,24 @@ module RubyLsp
53
43
  )
54
44
  end
55
45
  end
46
+
47
+ private
48
+
49
+ #: -> Array[RubyIndexer::Entry]
50
+ def fuzzy_search
51
+ @index.fuzzy_search(@query) do |entry|
52
+ file_path = entry.uri.full_path
53
+
54
+ # We only show symbols declared in the workspace
55
+ in_dependencies = file_path && !not_in_dependencies?(file_path)
56
+ next if in_dependencies
57
+
58
+ # We should never show private symbols when searching the entire workspace
59
+ next if entry.private?
60
+
61
+ true
62
+ end
63
+ end
56
64
  end
57
65
  end
58
66
  end
@@ -43,7 +43,7 @@ module RubyLsp
43
43
  async: 6,
44
44
  modification: 7,
45
45
  documentation: 8,
46
- default_library: 9,
46
+ defaultLibrary: 9,
47
47
  }.freeze #: Hash[Symbol, Integer]
48
48
 
49
49
  #: ((^(Integer arg0) -> Integer | Prism::CodeUnitsCache) code_units_cache) -> void
@@ -184,8 +184,8 @@ module RubyLsp
184
184
  end
185
185
 
186
186
  # Encode an array of modifiers to positions onto a bit flag
187
- # For example, [:default_library] will be encoded as
188
- # 0b1000000000, as :default_library is the 10th bit according
187
+ # For example, [:defaultLibrary] will be encoded as
188
+ # 0b1000000000, as :defaultLibrary is the 10th bit according
189
189
  # to the token modifiers index map.
190
190
  #: (Array[Integer] modifiers) -> Integer
191
191
  def encode_modifiers(modifiers)
@@ -1,18 +1,18 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
- def compose(raw_initialize)
4
+ def compose(raw_initialize, **options)
5
5
  require_relative "../setup_bundler"
6
6
  require "json"
7
7
  require "uri"
8
- require "ruby_indexer/lib/ruby_indexer/uri"
8
+ require_relative "../../ruby_indexer/lib/ruby_indexer/uri"
9
9
 
10
10
  initialize_request = JSON.parse(raw_initialize, symbolize_names: true)
11
11
  workspace_uri = initialize_request.dig(:params, :workspaceFolders, 0, :uri)
12
12
  workspace_path = workspace_uri && URI(workspace_uri).to_standardized_path
13
13
  workspace_path ||= Dir.pwd
14
14
 
15
- env = RubyLsp::SetupBundler.new(workspace_path, launcher: true).setup!
15
+ env = RubyLsp::SetupBundler.new(workspace_path, launcher: true, **options).setup!
16
16
 
17
17
  File.open(File.join(".ruby-lsp", "bundle_env"), "w") do |f|
18
18
  f.flock(File::LOCK_EX)
@@ -5,4 +5,6 @@ require_relative "compose_bundle"
5
5
 
6
6
  # When this is invoked on Windows, we pass the raw initialize as an argument to this script. On other platforms, we
7
7
  # invoke the compose method from inside a forked process
8
- compose(ARGV.first)
8
+ options = {}
9
+ options[:beta] = true if ARGV.include?("--beta")
10
+ compose(ARGV.first, **options)
@@ -3,6 +3,8 @@
3
3
 
4
4
  module RubyLsp
5
5
  class Server < BaseServer
6
+ NON_REPORTABLE_SETUP_ERRORS = [Bundler::GemNotFound, Bundler::GitError].freeze #: Array[singleton(StandardError)]
7
+
6
8
  # Only for testing
7
9
  #: GlobalState
8
10
  attr_reader :global_state
@@ -315,7 +317,7 @@ module RubyLsp
315
317
 
316
318
  global_state_notifications.each { |notification| send_message(notification) }
317
319
 
318
- if @setup_error
320
+ if @setup_error && NON_REPORTABLE_SETUP_ERRORS.none? { |error_class| @setup_error.is_a?(error_class) }
319
321
  send_message(Notification.telemetry(
320
322
  type: "error",
321
323
  errorMessage: @setup_error.message,
@@ -1211,7 +1213,7 @@ module RubyLsp
1211
1213
  }
1212
1214
  end
1213
1215
  end
1214
- rescue Bundler::GemNotFound, Bundler::GemfileNotFound
1216
+ rescue Bundler::GemNotFound, Bundler::GemfileNotFound, Errno::ENOENT
1215
1217
  []
1216
1218
  end
1217
1219
 
@@ -1436,6 +1438,7 @@ module RubyLsp
1436
1438
  ),
1437
1439
  File.expand_path("../../exe/ruby-lsp-launcher", __dir__),
1438
1440
  @global_state.workspace_uri.to_s,
1441
+ *ARGV,
1439
1442
  chdir: @global_state.workspace_path,
1440
1443
  )
1441
1444
  end