ruby-lsp 0.13.3 → 0.14.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp-doctor +2 -0
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +4 -8
- data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +5 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -2
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +10 -5
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +9 -0
- data/lib/ruby_indexer/test/index_test.rb +54 -3
- data/lib/ruby_lsp/addon.rb +34 -17
- data/lib/ruby_lsp/check_docs.rb +8 -8
- data/lib/ruby_lsp/executor.rb +28 -10
- data/lib/ruby_lsp/internal.rb +8 -6
- data/lib/ruby_lsp/listeners/code_lens.rb +54 -55
- data/lib/ruby_lsp/listeners/completion.rb +22 -18
- data/lib/ruby_lsp/listeners/definition.rb +31 -29
- data/lib/ruby_lsp/listeners/document_highlight.rb +6 -11
- data/lib/ruby_lsp/listeners/document_link.rb +6 -12
- data/lib/ruby_lsp/listeners/document_symbol.rb +194 -55
- data/lib/ruby_lsp/listeners/folding_ranges.rb +19 -23
- data/lib/ruby_lsp/listeners/hover.rb +36 -34
- data/lib/ruby_lsp/listeners/inlay_hints.rb +7 -13
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -124
- data/lib/ruby_lsp/listeners/signature_help.rb +15 -14
- data/lib/ruby_lsp/requests/code_lens.rb +11 -19
- data/lib/ruby_lsp/requests/completion.rb +7 -9
- data/lib/ruby_lsp/requests/definition.rb +10 -22
- data/lib/ruby_lsp/requests/document_highlight.rb +7 -5
- data/lib/ruby_lsp/requests/document_link.rb +7 -6
- data/lib/ruby_lsp/requests/document_symbol.rb +5 -11
- data/lib/ruby_lsp/requests/folding_ranges.rb +11 -6
- data/lib/ruby_lsp/requests/hover.rb +18 -24
- data/lib/ruby_lsp/requests/inlay_hints.rb +7 -8
- data/lib/ruby_lsp/requests/on_type_formatting.rb +12 -2
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +10 -8
- data/lib/ruby_lsp/requests/signature_help.rb +53 -18
- data/lib/ruby_lsp/requests/support/common.rb +38 -10
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +5 -1
- data/lib/ruby_lsp/requests.rb +0 -1
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +29 -0
- data/lib/ruby_lsp/response_builders/document_symbol.rb +57 -0
- data/lib/ruby_lsp/response_builders/hover.rb +49 -0
- data/lib/ruby_lsp/response_builders/response_builder.rb +16 -0
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +199 -0
- data/lib/ruby_lsp/response_builders/signature_help.rb +28 -0
- data/lib/ruby_lsp/response_builders.rb +13 -0
- data/lib/ruby_lsp/server.rb +3 -3
- data/lib/ruby_lsp/setup_bundler.rb +64 -23
- data/lib/ruby_lsp/store.rb +4 -4
- metadata +17 -11
- data/lib/ruby_lsp/listener.rb +0 -33
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 293c03761c9b7d497045546e3bf7ca88a08ed5556ad0ba52c205a9798e820ce5
|
4
|
+
data.tar.gz: 38157f012f3f1dc944186ac1530dc660d8662cb59ca7b12ad3b117655e0c1709
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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-
|
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-
|
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.
|
1
|
+
0.14.2
|
data/exe/ruby-lsp-doctor
CHANGED
@@ -13,9 +13,8 @@ module RuboCop
|
|
13
13
|
# # Register without handler method.
|
14
14
|
#
|
15
15
|
# # bad
|
16
|
-
# class MyListener
|
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
|
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
|
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
|
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
|
-
|
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
|
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
|
241
|
-
# exist on that receiver
|
242
|
-
sig { params(method_name: String, receiver_name: String).returns(T.nilable(Entry::
|
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 =
|
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
|
-
|
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
|
-
|
230
|
-
assert_equal("baz",
|
231
|
-
assert_equal("Foo::Bar", T.must(
|
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
|
data/lib/ruby_lsp/addon.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
).
|
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
|
-
).
|
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
|
-
).
|
148
|
+
).void
|
133
149
|
end
|
134
|
-
def
|
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
|
-
).
|
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
|
data/lib/ruby_lsp/check_docs.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
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
|
-
|
119
|
-
The following
|
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
|
127
|
+
puts "All requests are documented!"
|
128
128
|
end
|
129
129
|
end
|
130
130
|
end
|
data/lib/ruby_lsp/executor.rb
CHANGED
@@ -25,7 +25,7 @@ module RubyLsp
|
|
25
25
|
begin
|
26
26
|
response = run(request)
|
27
27
|
rescue StandardError, LoadError => e
|
28
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/ruby_lsp/internal.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
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/
|
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
|