ruby-lsp 0.22.1 → 0.23.10
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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp +12 -11
- data/exe/ruby-lsp-check +5 -5
- data/exe/ruby-lsp-launcher +41 -15
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +26 -20
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +191 -100
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +60 -30
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +174 -61
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +12 -0
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +16 -14
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +82 -61
- data/lib/{core_ext → ruby_indexer/lib/ruby_indexer}/uri.rb +29 -3
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +36 -0
- data/lib/ruby_indexer/ruby_indexer.rb +2 -1
- data/lib/ruby_indexer/test/class_variables_test.rb +140 -0
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +30 -6
- data/lib/ruby_indexer/test/configuration_test.rb +116 -51
- data/lib/ruby_indexer/test/enhancements_test.rb +2 -2
- data/lib/ruby_indexer/test/index_test.rb +143 -44
- data/lib/ruby_indexer/test/instance_variables_test.rb +20 -0
- data/lib/ruby_indexer/test/method_test.rb +86 -8
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
- data/lib/ruby_indexer/test/reference_finder_test.rb +90 -2
- data/lib/ruby_indexer/test/test_case.rb +2 -2
- data/lib/ruby_indexer/test/uri_test.rb +72 -0
- data/lib/ruby_lsp/addon.rb +9 -0
- data/lib/ruby_lsp/base_server.rb +17 -18
- data/lib/ruby_lsp/client_capabilities.rb +7 -1
- data/lib/ruby_lsp/document.rb +72 -10
- data/lib/ruby_lsp/erb_document.rb +5 -3
- data/lib/ruby_lsp/global_state.rb +42 -3
- data/lib/ruby_lsp/internal.rb +3 -1
- data/lib/ruby_lsp/listeners/code_lens.rb +9 -5
- data/lib/ruby_lsp/listeners/completion.rb +78 -6
- data/lib/ruby_lsp/listeners/definition.rb +80 -19
- data/lib/ruby_lsp/listeners/document_highlight.rb +3 -2
- data/lib/ruby_lsp/listeners/document_link.rb +21 -3
- data/lib/ruby_lsp/listeners/document_symbol.rb +12 -1
- data/lib/ruby_lsp/listeners/folding_ranges.rb +1 -1
- data/lib/ruby_lsp/listeners/hover.rb +59 -2
- data/lib/ruby_lsp/load_sorbet.rb +3 -3
- data/lib/ruby_lsp/rbs_document.rb +2 -2
- data/lib/ruby_lsp/requests/code_action_resolve.rb +90 -6
- data/lib/ruby_lsp/requests/code_actions.rb +57 -1
- data/lib/ruby_lsp/requests/completion.rb +8 -1
- data/lib/ruby_lsp/requests/completion_resolve.rb +2 -1
- data/lib/ruby_lsp/requests/definition.rb +7 -1
- data/lib/ruby_lsp/requests/diagnostics.rb +1 -1
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
- data/lib/ruby_lsp/requests/folding_ranges.rb +2 -6
- data/lib/ruby_lsp/requests/formatting.rb +2 -6
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/on_type_formatting.rb +2 -2
- data/lib/ruby_lsp/requests/prepare_rename.rb +51 -0
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +29 -2
- data/lib/ruby_lsp/requests/rename.rb +17 -7
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -4
- data/lib/ruby_lsp/requests/signature_help.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +2 -9
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +3 -3
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +13 -13
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +1 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -3
- data/lib/ruby_lsp/ruby_document.rb +80 -6
- data/lib/ruby_lsp/scripts/compose_bundle.rb +1 -1
- data/lib/ruby_lsp/server.rb +205 -61
- data/lib/ruby_lsp/setup_bundler.rb +50 -43
- data/lib/ruby_lsp/store.rb +7 -7
- data/lib/ruby_lsp/test_helper.rb +45 -11
- data/lib/ruby_lsp/type_inferrer.rb +60 -31
- data/lib/ruby_lsp/utils.rb +63 -3
- metadata +8 -8
- data/lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a0d78055f2f6bf861e581a5b5a2d1321d3a8452b23d638becb6e64da925d842
|
4
|
+
data.tar.gz: '0397aa5a123ed08757606db1be3690b50cba847a372f52da25fb64a6fb5816ce'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a14d101646bd32467724aeedb60892c5c06e775a57d749623cc1e76dbc42ee6d82eca10e2fa1149900365eff59ee57c20300bb043a3fdcf1330961b6bbd94918
|
7
|
+
data.tar.gz: 23b339c5854620771e7b505381dad64cf3e8d89ed2850a19c7a299e72d2363202e1e74327c05d27d8fb7fae508abb7141e5a858319b2841c8c914233e28e076e
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
[](https://github.com/Shopify/ruby-lsp/actions/workflows/ci.yml)
|
6
6
|
[](https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp)
|
7
|
-
[](https://join.slack.com/t/ruby-dx/shared_invite/zt-
|
7
|
+
[](https://join.slack.com/t/ruby-dx/shared_invite/zt-2yd77ayis-yAiVc1TX_kH0mHMBbi89dA)
|
8
8
|
|
9
9
|
# Ruby LSP
|
10
10
|
|
@@ -13,7 +13,7 @@ for Ruby, used to improve rich features in editors. It is a part of a wider goal
|
|
13
13
|
experience to Ruby developers using modern standards for cross-editor features, documentation and debugging.
|
14
14
|
|
15
15
|
Want to discuss Ruby developer experience? Consider joining the public
|
16
|
-
[Ruby DX Slack workspace](https://join.slack.com/t/ruby-dx/shared_invite/zt-
|
16
|
+
[Ruby DX Slack workspace](https://join.slack.com/t/ruby-dx/shared_invite/zt-2yd77ayis-yAiVc1TX_kH0mHMBbi89dA).
|
17
17
|
|
18
18
|
## Getting Started
|
19
19
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.23.10
|
data/exe/ruby-lsp
CHANGED
@@ -64,9 +64,9 @@ if ENV["BUNDLE_GEMFILE"].nil?
|
|
64
64
|
# which gives us the opportunity to control which specs are activated and enter degraded mode if any gems failed to
|
65
65
|
# install rather than failing to boot the server completely
|
66
66
|
if options[:launcher]
|
67
|
-
|
68
|
-
|
69
|
-
exit exec(
|
67
|
+
flags = []
|
68
|
+
flags << "--debug" if options[:debug]
|
69
|
+
exit exec(Gem.ruby, File.expand_path("ruby-lsp-launcher", __dir__), *flags)
|
70
70
|
end
|
71
71
|
|
72
72
|
require_relative "../lib/ruby_lsp/setup_bundler"
|
@@ -78,13 +78,14 @@ if ENV["BUNDLE_GEMFILE"].nil?
|
|
78
78
|
exit(78)
|
79
79
|
end
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
bundler_path = File.join(Gem.default_bindir, "bundle")
|
82
|
+
base_command = (!Gem.win_platform? && File.exist?(bundler_path) ? "#{Gem.ruby} #{bundler_path}" : "bundle").dup
|
83
|
+
|
84
|
+
if env["BUNDLER_VERSION"]
|
85
|
+
base_command << " _#{env["BUNDLER_VERSION"]}_"
|
85
86
|
end
|
86
87
|
|
87
|
-
exit exec(env, "#{
|
88
|
+
exit exec(env, "#{base_command} exec ruby-lsp #{original_args.join(" ")}".strip)
|
88
89
|
end
|
89
90
|
|
90
91
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
@@ -139,9 +140,9 @@ if options[:doctor]
|
|
139
140
|
|
140
141
|
puts "Globbing for indexable files"
|
141
142
|
|
142
|
-
index.configuration.
|
143
|
-
puts "indexing: #{
|
144
|
-
index.
|
143
|
+
index.configuration.indexable_uris.each do |uri|
|
144
|
+
puts "indexing: #{uri}"
|
145
|
+
index.index_file(uri)
|
145
146
|
end
|
146
147
|
return
|
147
148
|
end
|
data/exe/ruby-lsp-check
CHANGED
@@ -44,14 +44,14 @@ puts "\n"
|
|
44
44
|
puts "Verifying that indexing executes successfully. This may take a while..."
|
45
45
|
|
46
46
|
index = RubyIndexer::Index.new
|
47
|
-
|
47
|
+
uris = index.configuration.indexable_uris
|
48
48
|
|
49
|
-
|
50
|
-
index.
|
49
|
+
uris.each_with_index do |uri, i|
|
50
|
+
index.index_file(uri)
|
51
51
|
rescue => e
|
52
|
-
errors[
|
52
|
+
errors[uri.full_path] = e
|
53
53
|
ensure
|
54
|
-
print("\033[M\033[0KIndexed #{i + 1}/#{
|
54
|
+
print("\033[M\033[0KIndexed #{i + 1}/#{uris.length}") unless ENV["CI"]
|
55
55
|
end
|
56
56
|
puts "\n"
|
57
57
|
|
data/exe/ruby-lsp-launcher
CHANGED
@@ -7,14 +7,25 @@
|
|
7
7
|
# !!!!!!!
|
8
8
|
|
9
9
|
setup_error = nil
|
10
|
+
install_error = nil
|
11
|
+
reboot = false
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
workspace_uri = ARGV.first
|
14
|
+
|
15
|
+
raw_initialize = if workspace_uri && !workspace_uri.start_with?("--")
|
16
|
+
# If there's an argument without `--`, then it's the server asking to compose the bundle and passing to this
|
17
|
+
# executable the workspace URI. We can't require gems at this point, so we built a fake initialize request manually
|
18
|
+
reboot = true
|
19
|
+
"{\"params\":{\"workspaceFolders\":[{\"uri\":\"#{workspace_uri}\"}]}}"
|
20
|
+
else
|
21
|
+
# Read the initialize request before even starting the server. We need to do this to figure out the workspace URI.
|
22
|
+
# Editors are not required to spawn the language server process on the same directory as the workspace URI, so we need
|
23
|
+
# to ensure that we're setting up the bundle in the right place
|
24
|
+
$stdin.binmode
|
25
|
+
headers = $stdin.gets("\r\n\r\n")
|
26
|
+
content_length = headers[/Content-Length: (\d+)/i, 1].to_i
|
27
|
+
$stdin.read(content_length)
|
28
|
+
end
|
18
29
|
|
19
30
|
# Compose the Ruby LSP bundle in a forked process so that we can require gems without polluting the main process
|
20
31
|
# `$LOAD_PATH` and `Gem.loaded_specs`. Windows doesn't support forking, so we need a separate path to support it
|
@@ -40,7 +51,7 @@ end
|
|
40
51
|
|
41
52
|
begin
|
42
53
|
# Wait until the composed Bundle is finished
|
43
|
-
Process.
|
54
|
+
_, status = Process.wait2(pid)
|
44
55
|
rescue Errno::ECHILD
|
45
56
|
# In theory, the child process can finish before we even get to the wait call, but that is not an error
|
46
57
|
end
|
@@ -61,25 +72,40 @@ begin
|
|
61
72
|
|
62
73
|
require "bundler"
|
63
74
|
Bundler.ui.level = :silent
|
75
|
+
|
76
|
+
# This Marshal load can only happen after requiring Bundler because it will load a custom error class from Bundler
|
77
|
+
# itself. If we try to load before requiring, the class will not be defined and loading will fail
|
78
|
+
error_path = File.join(".ruby-lsp", "install_error")
|
79
|
+
install_error = if File.exist?(error_path)
|
80
|
+
Marshal.load(File.read(error_path))
|
81
|
+
end
|
82
|
+
|
64
83
|
Bundler.setup
|
65
84
|
$stderr.puts("Composed Bundle set up successfully")
|
66
85
|
end
|
67
86
|
rescue StandardError => e
|
68
87
|
# If installing gems failed for any reason, we don't want to exit the process prematurely. We can still provide most
|
69
88
|
# features in a degraded mode. We simply save the error so that we can report to the user that certain gems might be
|
70
|
-
# missing, but we respect the LSP life cycle
|
71
|
-
|
72
|
-
|
89
|
+
# missing, but we respect the LSP life cycle.
|
90
|
+
#
|
91
|
+
# If an install error occurred and one of the gems is not installed, Bundler.setup is guaranteed to fail with
|
92
|
+
# `Bundler::GemNotFound`. We don't set `setup_error` here because that would essentially report the same problem twice
|
93
|
+
# to telemetry, which is not useful
|
94
|
+
unless install_error && e.is_a?(Bundler::GemNotFound)
|
95
|
+
setup_error = e
|
96
|
+
$stderr.puts("Failed to set up composed Bundle\n#{e.full_message}")
|
97
|
+
end
|
73
98
|
|
74
99
|
# If Bundler.setup fails, we need to restore the original $LOAD_PATH so that we can still require the Ruby LSP server
|
75
100
|
# in degraded mode
|
76
101
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
77
102
|
end
|
78
103
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
104
|
+
# When performing a lockfile re-boot, this executable is invoked to set up the composed bundle ahead of time. In this
|
105
|
+
# flow, we are not booting the LSP yet, just checking if the bundle is valid before rebooting
|
106
|
+
if reboot
|
107
|
+
# Use the exit status to signal to the server if composing the bundle succeeded
|
108
|
+
exit(install_error || setup_error ? 1 : status&.exitstatus || 0)
|
83
109
|
end
|
84
110
|
|
85
111
|
# Now that the bundle is set up, we can begin actually launching the server. Note that `Bundler.setup` will have already
|
@@ -81,8 +81,8 @@ module RubyIndexer
|
|
81
81
|
.then { |dirs| File.join(@workspace_path, "{#{dirs.join(",")}}/**/*") }
|
82
82
|
end
|
83
83
|
|
84
|
-
sig { returns(T::Array[
|
85
|
-
def
|
84
|
+
sig { returns(T::Array[URI::Generic]) }
|
85
|
+
def indexable_uris
|
86
86
|
excluded_gems = @excluded_gems - @included_gems
|
87
87
|
locked_gems = Bundler.locked_gems&.specs
|
88
88
|
|
@@ -107,12 +107,12 @@ module RubyIndexer
|
|
107
107
|
[included_path, relative_path]
|
108
108
|
end
|
109
109
|
|
110
|
-
|
110
|
+
uris = T.let([], T::Array[URI::Generic])
|
111
111
|
|
112
112
|
# Handle top level files separately. The path below is an optimization to prevent descending down directories that
|
113
113
|
# are going to be excluded anyway, so we need to handle top level scripts separately
|
114
114
|
Dir.glob(File.join(@workspace_path, "*.rb"), flags).each do |path|
|
115
|
-
|
115
|
+
uris << URI::Generic.from_path(path: path)
|
116
116
|
end
|
117
117
|
|
118
118
|
# Add user specified patterns
|
@@ -134,7 +134,7 @@ module RubyIndexer
|
|
134
134
|
load_path_entry = $LOAD_PATH.find { |load_path| path.start_with?(load_path) }
|
135
135
|
end
|
136
136
|
|
137
|
-
|
137
|
+
uris << URI::Generic.from_path(path: path, load_path_entry: load_path_entry)
|
138
138
|
end
|
139
139
|
end
|
140
140
|
end
|
@@ -150,9 +150,9 @@ module RubyIndexer
|
|
150
150
|
end
|
151
151
|
|
152
152
|
# Remove user specified patterns
|
153
|
-
|
153
|
+
uris.reject! do |indexable|
|
154
154
|
excluded_patterns.any? do |pattern|
|
155
|
-
File.fnmatch?(pattern, indexable.full_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
|
155
|
+
File.fnmatch?(pattern, T.must(indexable.full_path), File::FNM_PATHNAME | File::FNM_EXTGLOB)
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
@@ -182,14 +182,14 @@ module RubyIndexer
|
|
182
182
|
|
183
183
|
if pathname.directory?
|
184
184
|
# If the default_path is a directory, we index all the Ruby files in it
|
185
|
-
|
185
|
+
uris.concat(
|
186
186
|
Dir.glob(File.join(default_path, "**", "*.rb"), File::FNM_PATHNAME | File::FNM_EXTGLOB).map! do |path|
|
187
|
-
|
187
|
+
URI::Generic.from_path(path: path, load_path_entry: RbConfig::CONFIG["rubylibdir"])
|
188
188
|
end,
|
189
189
|
)
|
190
190
|
elsif pathname.extname == ".rb"
|
191
191
|
# If the default_path is a Ruby file, we index it
|
192
|
-
|
192
|
+
uris << URI::Generic.from_path(path: default_path, load_path_entry: RbConfig::CONFIG["rubylibdir"])
|
193
193
|
end
|
194
194
|
end
|
195
195
|
|
@@ -204,10 +204,12 @@ module RubyIndexer
|
|
204
204
|
# duplicates or accidentally ignoring exclude patterns
|
205
205
|
next if spec.full_gem_path == @workspace_path
|
206
206
|
|
207
|
-
|
207
|
+
uris.concat(
|
208
208
|
spec.require_paths.flat_map do |require_path|
|
209
209
|
load_path_entry = File.join(spec.full_gem_path, require_path)
|
210
|
-
Dir.glob(File.join(load_path_entry, "**", "*.rb")).map!
|
210
|
+
Dir.glob(File.join(load_path_entry, "**", "*.rb")).map! do |path|
|
211
|
+
URI::Generic.from_path(path: path, load_path_entry: load_path_entry)
|
212
|
+
end
|
211
213
|
end,
|
212
214
|
)
|
213
215
|
rescue Gem::MissingSpecError
|
@@ -216,8 +218,8 @@ module RubyIndexer
|
|
216
218
|
# just ignore if they're missing
|
217
219
|
end
|
218
220
|
|
219
|
-
|
220
|
-
|
221
|
+
uris.uniq!(&:to_s)
|
222
|
+
uris
|
221
223
|
end
|
222
224
|
|
223
225
|
sig { returns(Regexp) }
|
@@ -271,6 +273,15 @@ module RubyIndexer
|
|
271
273
|
end
|
272
274
|
|
273
275
|
others.concat(this_gem.to_spec.dependencies) if this_gem
|
276
|
+
others.concat(
|
277
|
+
others.filter_map do |d|
|
278
|
+
d.to_spec&.dependencies
|
279
|
+
rescue Gem::MissingSpecError
|
280
|
+
nil
|
281
|
+
end.flatten,
|
282
|
+
)
|
283
|
+
others.uniq!
|
284
|
+
others.map!(&:name)
|
274
285
|
|
275
286
|
excluded.each do |dependency|
|
276
287
|
next unless dependency.runtime?
|
@@ -279,12 +290,7 @@ module RubyIndexer
|
|
279
290
|
next unless spec
|
280
291
|
|
281
292
|
spec.dependencies.each do |transitive_dependency|
|
282
|
-
|
283
|
-
next if others.any? { |d| d.name == transitive_dependency.name }
|
284
|
-
|
285
|
-
# If the transitive dependency is included as a transitive dependency of a gem outside of the development
|
286
|
-
# group, skip it
|
287
|
-
next if others.any? { |d| d.to_spec&.dependencies&.include?(transitive_dependency) }
|
293
|
+
next if others.include?(transitive_dependency.name)
|
288
294
|
|
289
295
|
excluded << transitive_dependency
|
290
296
|
end
|