ruby-lsp 0.13.3 → 0.14.2

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-doctor +2 -0
  5. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +4 -8
  6. data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +5 -1
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -2
  8. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +10 -5
  9. data/lib/ruby_indexer/test/classes_and_modules_test.rb +9 -0
  10. data/lib/ruby_indexer/test/index_test.rb +54 -3
  11. data/lib/ruby_lsp/addon.rb +34 -17
  12. data/lib/ruby_lsp/check_docs.rb +8 -8
  13. data/lib/ruby_lsp/executor.rb +28 -10
  14. data/lib/ruby_lsp/internal.rb +8 -6
  15. data/lib/ruby_lsp/listeners/code_lens.rb +54 -55
  16. data/lib/ruby_lsp/listeners/completion.rb +22 -18
  17. data/lib/ruby_lsp/listeners/definition.rb +31 -29
  18. data/lib/ruby_lsp/listeners/document_highlight.rb +6 -11
  19. data/lib/ruby_lsp/listeners/document_link.rb +6 -12
  20. data/lib/ruby_lsp/listeners/document_symbol.rb +194 -55
  21. data/lib/ruby_lsp/listeners/folding_ranges.rb +19 -23
  22. data/lib/ruby_lsp/listeners/hover.rb +36 -34
  23. data/lib/ruby_lsp/listeners/inlay_hints.rb +7 -13
  24. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -124
  25. data/lib/ruby_lsp/listeners/signature_help.rb +15 -14
  26. data/lib/ruby_lsp/requests/code_lens.rb +11 -19
  27. data/lib/ruby_lsp/requests/completion.rb +7 -9
  28. data/lib/ruby_lsp/requests/definition.rb +10 -22
  29. data/lib/ruby_lsp/requests/document_highlight.rb +7 -5
  30. data/lib/ruby_lsp/requests/document_link.rb +7 -6
  31. data/lib/ruby_lsp/requests/document_symbol.rb +5 -11
  32. data/lib/ruby_lsp/requests/folding_ranges.rb +11 -6
  33. data/lib/ruby_lsp/requests/hover.rb +18 -24
  34. data/lib/ruby_lsp/requests/inlay_hints.rb +7 -8
  35. data/lib/ruby_lsp/requests/on_type_formatting.rb +12 -2
  36. data/lib/ruby_lsp/requests/semantic_highlighting.rb +10 -8
  37. data/lib/ruby_lsp/requests/signature_help.rb +53 -18
  38. data/lib/ruby_lsp/requests/support/common.rb +38 -10
  39. data/lib/ruby_lsp/requests/support/dependency_detector.rb +5 -1
  40. data/lib/ruby_lsp/requests.rb +0 -1
  41. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +29 -0
  42. data/lib/ruby_lsp/response_builders/document_symbol.rb +57 -0
  43. data/lib/ruby_lsp/response_builders/hover.rb +49 -0
  44. data/lib/ruby_lsp/response_builders/response_builder.rb +16 -0
  45. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +199 -0
  46. data/lib/ruby_lsp/response_builders/signature_help.rb +28 -0
  47. data/lib/ruby_lsp/response_builders.rb +13 -0
  48. data/lib/ruby_lsp/server.rb +3 -3
  49. data/lib/ruby_lsp/setup_bundler.rb +64 -23
  50. data/lib/ruby_lsp/store.rb +4 -4
  51. metadata +17 -11
  52. data/lib/ruby_lsp/listener.rb +0 -33
  53. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +0 -73
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28e657dce7a85c270d1c647a158fd1a1c5f81dca211844defd817070fd264126
4
- data.tar.gz: f129245dd0e632916573c0b9dcf04bfaa2c7b942b39aaa6aa1618dd70f13e69e
3
+ metadata.gz: 293c03761c9b7d497045546e3bf7ca88a08ed5556ad0ba52c205a9798e820ce5
4
+ data.tar.gz: 38157f012f3f1dc944186ac1530dc660d8662cb59ca7b12ad3b117655e0c1709
5
5
  SHA512:
6
- metadata.gz: 3ab4afce37f672fd0d3c3ecc54c7b30247f893fc4b7b4f10549e13db4ab181c67a9b84da37dea9fbdd195e8d87ca2f2f794cbcce300c68b4709ee0ae3b3171b2
7
- data.tar.gz: ffdb3a1bdb2d5c4172f74c934da896bd6c19f09158effa137afd0443e79b8c2dfd392989997d5745616db58e1286191a9e35570bd69024779137e7aaf15bb987
6
+ metadata.gz: c4996e277088f015004df0f82e2cc47dc2f979f6658f9dfac19fe495c8c4deced3028b021e330ac0681dbfd79048e9033037c7ce93e6cc044c8ae6d91087e0df
7
+ data.tar.gz: 67c5c31c97c279f192b0b3d6c729c97a19f7aac4581eca037c0e5355cc0f3d3ed69fb4007a5f32985e046980324575e2e35a92ce81e8078b41ee5b6db711ac88
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [![Build Status](https://github.com/Shopify/ruby-lsp/workflows/CI/badge.svg)](https://github.com/Shopify/ruby-lsp/actions/workflows/ci.yml)
2
2
  [![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)
3
- [![Ruby DX Slack](https://img.shields.io/badge/Slack-Ruby%20DX-success?logo=slack)](https://join.slack.com/t/ruby-dx/shared_invite/zt-1zjp7lmgk-zL7bGvze8gj5hFaYS~r5vg)
3
+ [![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)
4
4
 
5
5
  # Ruby LSP
6
6
 
@@ -9,7 +9,7 @@ for Ruby, used to improve rich features in editors. It is a part of a wider goal
9
9
  experience to Ruby developers using modern standards for cross-editor features, documentation and debugging.
10
10
 
11
11
  Want to discuss Ruby developer experience? Consider joining the public
12
- [Ruby DX Slack workspace](https://join.slack.com/t/ruby-dx/shared_invite/zt-1zjp7lmgk-zL7bGvze8gj5hFaYS~r5vg).
12
+ [Ruby DX Slack workspace](https://join.slack.com/t/ruby-dx/shared_invite/zt-2c8zjlir6-uUDJl8oIwcen_FS_aA~b6Q).
13
13
 
14
14
  ## Usage
15
15
 
@@ -83,6 +83,10 @@ features. This is the mechanism that powers addons like
83
83
 
84
84
  - [Ruby LSP Rails](https://github.com/Shopify/ruby-lsp-rails)
85
85
  - [Ruby LSP RSpec](https://github.com/st0012/ruby-lsp-rspec)
86
+ - [Ruby LSP rubyfmt](https://github.com/jscharf/ruby-lsp-rubyfmt)
87
+
88
+ Other community driven addons can be found in [rubygems](https://rubygems.org/search?query=name%3A+ruby-lsp) by
89
+ searching for the `ruby-lsp` prefix.
86
90
 
87
91
  For instructions on how to create addons, see the [addons documentation](ADDONS.md).
88
92
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.13.3
1
+ 0.14.2
data/exe/ruby-lsp-doctor CHANGED
@@ -6,6 +6,8 @@ require "ruby_lsp/internal"
6
6
 
7
7
  index = RubyIndexer::Index.new
8
8
 
9
+ puts "Globbing for indexable files"
10
+
9
11
  RubyIndexer.configuration.indexables.each do |indexable|
10
12
  puts "indexing: #{indexable.full_path}"
11
13
  content = File.read(indexable.full_path)
@@ -13,9 +13,8 @@ module RuboCop
13
13
  # # Register without handler method.
14
14
  #
15
15
  # # bad
16
- # class MyListener < Listener
16
+ # class MyListener
17
17
  # def initialize(dispatcher)
18
- # super()
19
18
  # dispatcher.register(
20
19
  # self,
21
20
  # :on_string_node_enter,
@@ -24,9 +23,8 @@ module RuboCop
24
23
  # end
25
24
  #
26
25
  # # good
27
- # class MyListener < Listener
26
+ # class MyListener
28
27
  # def initialize(dispatcher)
29
- # super()
30
28
  # dispatcher.register(
31
29
  # self,
32
30
  # :on_string_node_enter,
@@ -41,9 +39,8 @@ module RuboCop
41
39
  # # Handler method without register.
42
40
  #
43
41
  # # bad
44
- # class MyListener < Listener
42
+ # class MyListener
45
43
  # def initialize(dispatcher)
46
- # super()
47
44
  # dispatcher.register(
48
45
  # self,
49
46
  # )
@@ -54,9 +51,8 @@ module RuboCop
54
51
  # end
55
52
  #
56
53
  # # good
57
- # class MyListener < Listener
54
+ # class MyListener
58
55
  # def initialize(dispatcher)
59
- # super()
60
56
  # dispatcher.register(
61
57
  # self,
62
58
  # :on_string_node_enter,
@@ -304,7 +304,11 @@ module RubyIndexer
304
304
  break unless comment
305
305
 
306
306
  comment_content = comment.location.slice.chomp
307
- next if comment_content.match?(RubyIndexer.configuration.magic_comment_regex)
307
+
308
+ # invalid encodings would raise an "invalid byte sequence" exception
309
+ if !comment_content.valid_encoding? || comment_content.match?(RubyIndexer.configuration.magic_comment_regex)
310
+ next
311
+ end
308
312
 
309
313
  comment_content.delete_prefix!("#")
310
314
  comment_content.delete_prefix!(" ")
@@ -192,6 +192,9 @@ module RubyIndexer
192
192
 
193
193
  # When working on a gem, we need to make sure that its gemspec dependencies can't be excluded. This is necessary
194
194
  # because Bundler doesn't assign groups to gemspec dependencies
195
+ #
196
+ # If the dependency is prerelease, `to_spec` may return `nil` due to a bug in older version of Bundler/RubyGems:
197
+ # https://github.com/Shopify/ruby-lsp/issues/1246
195
198
  this_gem = Bundler.definition.dependencies.find do |d|
196
199
  d.to_spec&.full_gem_path == Dir.pwd
197
200
  rescue Gem::MissingSpecError
@@ -203,7 +206,6 @@ module RubyIndexer
203
206
  excluded.each do |dependency|
204
207
  next unless dependency.runtime?
205
208
 
206
- # If the dependency is prerelease, to_spec may return `nil`
207
209
  spec = dependency.to_spec
208
210
  next unless spec
209
211
 
@@ -213,7 +215,7 @@ module RubyIndexer
213
215
 
214
216
  # If the transitive dependency is included as a transitive dependency of a gem outside of the development
215
217
  # group, skip it
216
- next if others.any? { |d| d.to_spec.dependencies.include?(transitive_dependency) }
218
+ next if others.any? { |d| d.to_spec&.dependencies&.include?(transitive_dependency) }
217
219
 
218
220
  excluded << transitive_dependency
219
221
  end
@@ -237,16 +237,21 @@ module RubyIndexer
237
237
  real_parts.join("::")
238
238
  end
239
239
 
240
- # Attempts to find a given method for a resolved fully qualified receiver name. Returns `nil` if the method does not
241
- # exist on that receiver
242
- sig { params(method_name: String, receiver_name: String).returns(T.nilable(Entry::Method)) }
240
+ # Attempts to find methods for a resolved fully qualified receiver name.
241
+ # Returns `nil` if the method does not exist on that receiver
242
+ sig { params(method_name: String, receiver_name: String).returns(T.nilable(T::Array[Entry::Member])) }
243
243
  def resolve_method(method_name, receiver_name)
244
- method_entries = T.cast(self[method_name], T.nilable(T::Array[Entry::Method]))
244
+ method_entries = self[method_name]
245
245
  owner_entries = self[receiver_name]
246
246
  return unless owner_entries && method_entries
247
247
 
248
248
  owner_name = T.must(owner_entries.first).name
249
- method_entries.find { |entry| entry.owner&.name == owner_name }
249
+ T.cast(
250
+ method_entries.grep(Entry::Member).select do |entry|
251
+ T.cast(entry, Entry::Member).owner&.name == owner_name
252
+ end,
253
+ T::Array[Entry::Member],
254
+ )
250
255
  end
251
256
 
252
257
  private
@@ -168,6 +168,15 @@ module RubyIndexer
168
168
  assert_equal("This Bar comment has 1 line padding", bar_entry.comments.join("\n"))
169
169
  end
170
170
 
171
+ def test_skips_comments_containing_invalid_encodings
172
+ index(<<~RUBY)
173
+ # comment \xBA
174
+ class Foo
175
+ end
176
+ RUBY
177
+ assert(@index["Foo"].first)
178
+ end
179
+
171
180
  def test_comments_can_be_attached_to_a_namespaced_class
172
181
  index(<<~RUBY)
173
182
  # This is a Foo comment
@@ -226,9 +226,60 @@ module RubyIndexer
226
226
  end
227
227
  RUBY
228
228
 
229
- entry = T.must(@index.resolve_method("baz", "Foo::Bar"))
230
- assert_equal("baz", entry.name)
231
- assert_equal("Foo::Bar", T.must(entry.owner).name)
229
+ entries = T.must(@index.resolve_method("baz", "Foo::Bar"))
230
+ assert_equal("baz", entries.first.name)
231
+ assert_equal("Foo::Bar", T.must(entries.first.owner).name)
232
+ end
233
+
234
+ def test_resolve_method_with_class_name_conflict
235
+ index(<<~RUBY)
236
+ class Array
237
+ end
238
+
239
+ class Foo
240
+ def Array(*args); end
241
+ end
242
+ RUBY
243
+
244
+ entries = T.must(@index.resolve_method("Array", "Foo"))
245
+ assert_equal("Array", entries.first.name)
246
+ assert_equal("Foo", T.must(entries.first.owner).name)
247
+ end
248
+
249
+ def test_resolve_method_attribute
250
+ index(<<~RUBY)
251
+ class Foo
252
+ attr_reader :bar
253
+ end
254
+ RUBY
255
+
256
+ entries = T.must(@index.resolve_method("bar", "Foo"))
257
+ assert_equal("bar", entries.first.name)
258
+ assert_equal("Foo", T.must(entries.first.owner).name)
259
+ end
260
+
261
+ def test_resolve_method_with_two_definitions
262
+ index(<<~RUBY)
263
+ class Foo
264
+ # Hello from first `bar`
265
+ def bar; end
266
+ end
267
+
268
+ class Foo
269
+ # Hello from second `bar`
270
+ def bar; end
271
+ end
272
+ RUBY
273
+
274
+ first_entry, second_entry = T.must(@index.resolve_method("bar", "Foo"))
275
+
276
+ assert_equal("bar", first_entry.name)
277
+ assert_equal("Foo", T.must(first_entry.owner).name)
278
+ assert_includes(first_entry.comments, "Hello from first `bar`")
279
+
280
+ assert_equal("bar", second_entry.name)
281
+ assert_equal("Foo", T.must(second_entry.owner).name)
282
+ assert_includes(second_entry.comments, "Hello from second `bar`")
232
283
  end
233
284
 
234
285
  def test_prefix_search_for_methods
@@ -25,21 +25,25 @@ module RubyLsp
25
25
 
26
26
  abstract!
27
27
 
28
+ @addons = T.let([], T::Array[Addon])
29
+ @addon_classes = T.let([], T::Array[T.class_of(Addon)])
30
+
28
31
  class << self
29
32
  extend T::Sig
30
33
 
34
+ sig { returns(T::Array[Addon]) }
35
+ attr_accessor :addons
36
+
37
+ sig { returns(T::Array[T.class_of(Addon)]) }
38
+ attr_reader :addon_classes
39
+
31
40
  # Automatically track and instantiate addon classes
32
41
  sig { params(child_class: T.class_of(Addon)).void }
33
42
  def inherited(child_class)
34
- addons << child_class.new
43
+ addon_classes << child_class
35
44
  super
36
45
  end
37
46
 
38
- sig { returns(T::Array[Addon]) }
39
- def addons
40
- @addons ||= T.let([], T.nilable(T::Array[Addon]))
41
- end
42
-
43
47
  # Discovers and loads all addons. Returns the list of activated addons
44
48
  sig { params(message_queue: Thread::Queue).returns(T::Array[Addon]) }
45
49
  def load_addons(message_queue)
@@ -48,15 +52,16 @@ module RubyLsp
48
52
  Gem.find_files("ruby_lsp/**/addon.rb").each do |addon|
49
53
  require File.expand_path(addon)
50
54
  rescue => e
51
- warn(e.message)
52
- warn(e.backtrace.to_s) # rubocop:disable Lint/RedundantStringCoercion
55
+ $stderr.puts(e.full_message)
53
56
  end
54
57
 
58
+ # Instantiate all discovered addon classes
59
+ self.addons = addon_classes.map(&:new)
60
+
55
61
  # Activate each one of the discovered addons. If any problems occur in the addons, we don't want to
56
62
  # fail to boot the server
57
63
  addons.each do |addon|
58
64
  addon.activate(message_queue)
59
- nil
60
65
  rescue => e
61
66
  addon.add_error(e)
62
67
  end
@@ -109,39 +114,51 @@ module RubyLsp
109
114
  # Creates a new CodeLens listener. This method is invoked on every CodeLens request
110
115
  sig do
111
116
  overridable.params(
117
+ response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
112
118
  uri: URI::Generic,
113
119
  dispatcher: Prism::Dispatcher,
114
- ).returns(T.nilable(Listener[T::Array[Interface::CodeLens]]))
120
+ ).void
115
121
  end
116
- def create_code_lens_listener(uri, dispatcher); end
122
+ def create_code_lens_listener(response_builder, uri, dispatcher); end
117
123
 
118
124
  # Creates a new Hover listener. This method is invoked on every Hover request
119
125
  sig do
120
126
  overridable.params(
127
+ response_builder: ResponseBuilders::Hover,
121
128
  nesting: T::Array[String],
122
129
  index: RubyIndexer::Index,
123
130
  dispatcher: Prism::Dispatcher,
124
- ).returns(T.nilable(Listener[T.nilable(Interface::Hover)]))
131
+ ).void
125
132
  end
126
- def create_hover_listener(nesting, index, dispatcher); end
133
+ def create_hover_listener(response_builder, nesting, index, dispatcher); end
127
134
 
128
135
  # Creates a new DocumentSymbol listener. This method is invoked on every DocumentSymbol request
129
136
  sig do
130
137
  overridable.params(
138
+ response_builder: ResponseBuilders::DocumentSymbol,
139
+ dispatcher: Prism::Dispatcher,
140
+ ).void
141
+ end
142
+ def create_document_symbol_listener(response_builder, dispatcher); end
143
+
144
+ sig do
145
+ overridable.params(
146
+ response_builder: ResponseBuilders::SemanticHighlighting,
131
147
  dispatcher: Prism::Dispatcher,
132
- ).returns(T.nilable(Listener[T::Array[Interface::DocumentSymbol]]))
148
+ ).void
133
149
  end
134
- def create_document_symbol_listener(dispatcher); end
150
+ def create_semantic_highlighting_listener(response_builder, dispatcher); end
135
151
 
136
152
  # Creates a new Definition listener. This method is invoked on every Definition request
137
153
  sig do
138
154
  overridable.params(
155
+ response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::Location],
139
156
  uri: URI::Generic,
140
157
  nesting: T::Array[String],
141
158
  index: RubyIndexer::Index,
142
159
  dispatcher: Prism::Dispatcher,
143
- ).returns(T.nilable(Listener[T.nilable(T.any(T::Array[Interface::Location], Interface::Location))]))
160
+ ).void
144
161
  end
145
- def create_definition_listener(uri, nesting, index, dispatcher); end
162
+ def create_definition_listener(response_builder, uri, nesting, index, dispatcher); end
146
163
  end
147
164
  end
@@ -6,7 +6,7 @@ require "objspace"
6
6
 
7
7
  module RubyLsp
8
8
  # This rake task checks that all requests or addons are fully documented. Add the rake task to your Rakefile and
9
- # specify the absolute path for all files that must be required in order to discover all listeners and their related
9
+ # specify the absolute path for all files that must be required in order to discover all requests and their related
10
10
  # GIFs
11
11
  #
12
12
  # # Rakefile
@@ -33,7 +33,7 @@ module RubyLsp
33
33
 
34
34
  sig { void }
35
35
  def define_task
36
- desc("Checks if all Ruby LSP listeners are documented")
36
+ desc("Checks if all Ruby LSP requests are documented")
37
37
  task(@name) { run_task }
38
38
  end
39
39
 
@@ -46,10 +46,10 @@ module RubyLsp
46
46
 
47
47
  sig { void }
48
48
  def run_task
49
- # Require all files configured to make sure all listeners are loaded
49
+ # Require all files configured to make sure all requests are loaded
50
50
  @file_list.each { |f| require(f.delete_suffix(".rb")) }
51
51
 
52
- # Find all classes that inherit from BaseRequest or Listener, which are the ones we want to make sure are
52
+ # Find all classes that inherit from BaseRequest, which are the ones we want to make sure are
53
53
  # documented
54
54
  features = ObjectSpace.each_object(Class).select do |k|
55
55
  klass = T.unsafe(k)
@@ -69,7 +69,7 @@ module RubyLsp
69
69
  lines = File.readlines(file_path)
70
70
  docs = []
71
71
 
72
- # Extract the documentation on top of the listener constant
72
+ # Extract the documentation on top of the request constant
73
73
  while (line = lines[line_number]&.strip) && line.start_with?("#")
74
74
  docs.unshift(line)
75
75
  line_number -= 1
@@ -115,8 +115,8 @@ module RubyLsp
115
115
  end
116
116
 
117
117
  if missing_docs.any?
118
- warn(<<~WARN)
119
- The following listeners are missing documentation:
118
+ $stderr.puts(<<~WARN)
119
+ The following requests are missing documentation:
120
120
 
121
121
  #{missing_docs.map { |k, v| "#{k}\n\n#{v.join("\n")}" }.join("\n\n")}
122
122
  WARN
@@ -124,7 +124,7 @@ module RubyLsp
124
124
  abort
125
125
  end
126
126
 
127
- puts "All listeners are documented!"
127
+ puts "All requests are documented!"
128
128
  end
129
129
  end
130
130
  end
@@ -25,7 +25,7 @@ module RubyLsp
25
25
  begin
26
26
  response = run(request)
27
27
  rescue StandardError, LoadError => e
28
- warn(e.message)
28
+ $stderr.puts(e.full_message)
29
29
  error = e
30
30
  end
31
31
 
@@ -55,7 +55,7 @@ module RubyLsp
55
55
  ),
56
56
  )
57
57
 
58
- warn(errored_addons.map(&:backtraces).join("\n\n"))
58
+ $stderr.puts(errored_addons.map(&:backtraces).join("\n\n"))
59
59
  end
60
60
 
61
61
  RubyVM::YJIT.enable if defined? RubyVM::YJIT.enable
@@ -63,7 +63,7 @@ module RubyLsp
63
63
  perform_initial_indexing
64
64
  check_formatter_is_available
65
65
 
66
- warn("Ruby LSP is ready")
66
+ $stderr.puts("Ruby LSP is ready")
67
67
  VOID
68
68
  when "textDocument/didOpen"
69
69
  text_document_did_open(
@@ -99,8 +99,7 @@ module RubyLsp
99
99
  folding_range = Requests::FoldingRanges.new(document.parse_result.comments, dispatcher)
100
100
  document_symbol = Requests::DocumentSymbol.new(dispatcher)
101
101
  document_link = Requests::DocumentLink.new(uri, document.comments, dispatcher)
102
- lenses_configuration = T.must(@store.features_configuration.dig(:codeLens))
103
- code_lens = Requests::CodeLens.new(uri, lenses_configuration, dispatcher)
102
+ code_lens = Requests::CodeLens.new(uri, dispatcher)
104
103
 
105
104
  semantic_highlighting = Requests::SemanticHighlighting.new(dispatcher)
106
105
  dispatcher.dispatch(document.tree)
@@ -113,7 +112,7 @@ module RubyLsp
113
112
  document.cache_set("textDocument/codeLens", code_lens.perform)
114
113
  document.cache_set(
115
114
  "textDocument/semanticTokens/full",
116
- Requests::Support::SemanticTokenEncoder.new.encode(semantic_highlighting.perform),
115
+ semantic_highlighting.perform,
117
116
  )
118
117
  document.cache_get(request[:method])
119
118
  when "textDocument/semanticTokens/range"
@@ -222,6 +221,8 @@ module RubyLsp
222
221
  workspace_symbol(request.dig(:params, :query))
223
222
  when "rubyLsp/textDocument/showSyntaxTree"
224
223
  show_syntax_tree(uri, request.dig(:params, :range))
224
+ when "rubyLsp/workspace/dependencies"
225
+ workspace_dependencies
225
226
  else
226
227
  VOID
227
228
  end
@@ -252,6 +253,22 @@ module RubyLsp
252
253
  VOID
253
254
  end
254
255
 
256
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
257
+ def workspace_dependencies
258
+ definition = Bundler.definition
259
+ dep_keys = definition.locked_deps.keys.to_set
260
+ definition.specs.map do |spec|
261
+ {
262
+ name: spec.name,
263
+ version: spec.version,
264
+ path: spec.full_gem_path,
265
+ dependency: dep_keys.include?(spec.name),
266
+ }
267
+ end
268
+ rescue Bundler::GemfileNotFound
269
+ []
270
+ end
271
+
255
272
  sig { void }
256
273
  def perform_initial_indexing
257
274
  # The begin progress invocation happens during `initialize`, so that the notification is sent before we are
@@ -361,7 +378,7 @@ module RubyLsp
361
378
  ).returns(T::Array[Interface::TextEdit])
362
379
  end
363
380
  def on_type_formatting(uri, position, character)
364
- Requests::OnTypeFormatting.new(@store.get(uri), position, character).perform
381
+ Requests::OnTypeFormatting.new(@store.get(uri), position, character, @store.client_name).perform
365
382
  end
366
383
 
367
384
  sig do
@@ -431,7 +448,7 @@ module RubyLsp
431
448
  request = Requests::SemanticHighlighting.new(dispatcher, range: start_line..end_line)
432
449
  dispatcher.visit(document.tree)
433
450
 
434
- Requests::Support::SemanticTokenEncoder.new.encode(request.perform)
451
+ request.perform
435
452
  end
436
453
 
437
454
  sig { params(id: String, title: String, percentage: Integer).void }
@@ -497,6 +514,9 @@ module RubyLsp
497
514
  workspace_uri = options.dig(:workspaceFolders, 0, :uri)
498
515
  @store.workspace_uri = URI(workspace_uri) if workspace_uri
499
516
 
517
+ client_name = options.dig(:clientInfo, :name)
518
+ @store.client_name = client_name if client_name
519
+
500
520
  encodings = options.dig(:capabilities, :general, :positionEncodings)
501
521
  @store.encoding = if encodings.nil? || encodings.empty?
502
522
  Constant::PositionEncodingKind::UTF16
@@ -519,9 +539,7 @@ module RubyLsp
519
539
  @store.experimental_features = options.dig(:initializationOptions, :experimentalFeaturesEnabled) || false
520
540
 
521
541
  configured_hints = options.dig(:initializationOptions, :featuresConfiguration, :inlayHint)
522
- configured_lenses = options.dig(:initializationOptions, :featuresConfiguration, :codeLens)
523
542
  T.must(@store.features_configuration.dig(:inlayHint)).configuration.merge!(configured_hints) if configured_hints
524
- T.must(@store.features_configuration.dig(:codeLens)).configuration.merge!(configured_lenses) if configured_lenses
525
543
 
526
544
  enabled_features = case configured_features
527
545
  when Array
@@ -7,13 +7,17 @@ yarp_require_paths = Gem.loaded_specs["yarp"]&.full_require_paths
7
7
  $LOAD_PATH.delete_if { |path| yarp_require_paths.include?(path) } if yarp_require_paths
8
8
 
9
9
  require "sorbet-runtime"
10
- require "prism"
11
- require "prism/visitor"
12
- require "language_server-protocol"
10
+
11
+ # Set Bundler's UI level to silent as soon as possible to prevent any prints to STDOUT
13
12
  require "bundler"
13
+ Bundler.ui.level = :silent
14
+
14
15
  require "uri"
15
16
  require "cgi"
16
17
  require "set"
18
+ require "prism"
19
+ require "prism/visitor"
20
+ require "language_server-protocol"
17
21
 
18
22
  require "ruby-lsp"
19
23
  require "ruby_indexer/ruby_indexer"
@@ -23,11 +27,9 @@ require "ruby_lsp/parameter_scope"
23
27
  require "ruby_lsp/server"
24
28
  require "ruby_lsp/executor"
25
29
  require "ruby_lsp/requests"
26
- require "ruby_lsp/listener"
30
+ require "ruby_lsp/response_builders"
27
31
  require "ruby_lsp/document"
28
32
  require "ruby_lsp/ruby_document"
29
33
  require "ruby_lsp/store"
30
34
  require "ruby_lsp/addon"
31
35
  require "ruby_lsp/requests/support/rubocop_runner"
32
-
33
- Bundler.ui.level = :silent