ruby-lsp 0.17.17 → 0.18.3
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 +4 -110
- data/VERSION +1 -1
- data/exe/ruby-lsp +5 -11
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +14 -6
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +162 -27
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +110 -8
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +2 -2
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +24 -10
- data/lib/ruby_indexer/test/constant_test.rb +4 -4
- data/lib/ruby_indexer/test/enhancements_test.rb +2 -2
- data/lib/ruby_indexer/test/index_test.rb +68 -0
- data/lib/ruby_indexer/test/method_test.rb +257 -2
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
- data/lib/ruby_lsp/base_server.rb +21 -1
- data/lib/ruby_lsp/document.rb +5 -3
- data/lib/ruby_lsp/erb_document.rb +29 -10
- data/lib/ruby_lsp/global_state.rb +4 -3
- data/lib/ruby_lsp/internal.rb +40 -2
- data/lib/ruby_lsp/listeners/code_lens.rb +34 -5
- data/lib/ruby_lsp/listeners/completion.rb +20 -6
- data/lib/ruby_lsp/listeners/inlay_hints.rb +1 -16
- data/lib/ruby_lsp/listeners/signature_help.rb +55 -24
- data/lib/ruby_lsp/rbs_document.rb +5 -4
- data/lib/ruby_lsp/requests/code_action_resolve.rb +0 -15
- data/lib/ruby_lsp/requests/code_actions.rb +0 -10
- data/lib/ruby_lsp/requests/code_lens.rb +1 -11
- data/lib/ruby_lsp/requests/completion.rb +3 -20
- data/lib/ruby_lsp/requests/completion_resolve.rb +2 -10
- data/lib/ruby_lsp/requests/definition.rb +6 -20
- data/lib/ruby_lsp/requests/diagnostics.rb +0 -10
- data/lib/ruby_lsp/requests/document_highlight.rb +7 -14
- data/lib/ruby_lsp/requests/document_link.rb +0 -10
- data/lib/ruby_lsp/requests/document_symbol.rb +0 -17
- data/lib/ruby_lsp/requests/folding_ranges.rb +0 -10
- data/lib/ruby_lsp/requests/formatting.rb +0 -16
- data/lib/ruby_lsp/requests/hover.rb +9 -9
- data/lib/ruby_lsp/requests/inlay_hints.rb +2 -35
- data/lib/ruby_lsp/requests/on_type_formatting.rb +0 -10
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +0 -11
- data/lib/ruby_lsp/requests/request.rb +17 -1
- data/lib/ruby_lsp/requests/selection_ranges.rb +0 -10
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -23
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +0 -11
- data/lib/ruby_lsp/requests/signature_help.rb +5 -20
- data/lib/ruby_lsp/requests/support/common.rb +1 -1
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -0
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +2 -0
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +0 -11
- data/lib/ruby_lsp/requests/workspace_symbol.rb +0 -12
- data/lib/ruby_lsp/ruby_document.rb +4 -3
- data/lib/ruby_lsp/server.rb +45 -11
- data/lib/ruby_lsp/setup_bundler.rb +33 -15
- data/lib/ruby_lsp/type_inferrer.rb +8 -10
- data/lib/ruby_lsp/utils.rb +11 -1
- metadata +3 -6
- data/lib/ruby_lsp/check_docs.rb +0 -130
- data/lib/ruby_lsp/requests.rb +0 -64
- data/lib/ruby_lsp/response_builders.rb +0 -13
@@ -121,12 +121,13 @@ module RubyLsp
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
sig { override.returns(
|
125
|
-
def parse
|
126
|
-
return
|
124
|
+
sig { override.returns(T::Boolean) }
|
125
|
+
def parse!
|
126
|
+
return false unless @needs_parsing
|
127
127
|
|
128
128
|
@needs_parsing = false
|
129
129
|
@parse_result = Prism.parse(@source)
|
130
|
+
true
|
130
131
|
end
|
131
132
|
|
132
133
|
sig { override.returns(T::Boolean) }
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -9,12 +9,6 @@ module RubyLsp
|
|
9
9
|
sig { returns(GlobalState) }
|
10
10
|
attr_reader :global_state
|
11
11
|
|
12
|
-
sig { params(test_mode: T::Boolean).void }
|
13
|
-
def initialize(test_mode: false)
|
14
|
-
super
|
15
|
-
@global_state = T.let(GlobalState.new, GlobalState)
|
16
|
-
end
|
17
|
-
|
18
12
|
sig { override.params(message: T::Hash[Symbol, T.untyped]).void }
|
19
13
|
def process_message(message)
|
20
14
|
case message[:method]
|
@@ -98,6 +92,8 @@ module RubyLsp
|
|
98
92
|
when "$/cancelRequest"
|
99
93
|
@mutex.synchronize { @cancelled_requests << message[:params][:id] }
|
100
94
|
end
|
95
|
+
rescue DelegateRequestError
|
96
|
+
send_message(Error.new(id: message[:id], code: DelegateRequestError::CODE, message: "DELEGATE_REQUEST"))
|
101
97
|
rescue StandardError, LoadError => e
|
102
98
|
# If an error occurred in a request, we have to return an error response or else the editor will hang
|
103
99
|
if message[:id]
|
@@ -284,7 +280,15 @@ module RubyLsp
|
|
284
280
|
RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
|
285
281
|
|
286
282
|
if defined?(Requests::Support::RuboCopFormatter)
|
287
|
-
|
283
|
+
begin
|
284
|
+
@global_state.register_formatter("rubocop", Requests::Support::RuboCopFormatter.new)
|
285
|
+
rescue RuboCop::Error => e
|
286
|
+
# The user may have provided unknown config switches in .rubocop or
|
287
|
+
# is trying to load a non-existant config file.
|
288
|
+
send_message(Notification.window_show_error(
|
289
|
+
"RuboCop configuration error: #{e.message}. Formatting will not be available.",
|
290
|
+
))
|
291
|
+
end
|
288
292
|
end
|
289
293
|
if defined?(Requests::Support::SyntaxTreeFormatter)
|
290
294
|
@global_state.register_formatter("syntax_tree", Requests::Support::SyntaxTreeFormatter.new)
|
@@ -407,6 +411,7 @@ module RubyLsp
|
|
407
411
|
document_symbol = Requests::DocumentSymbol.new(uri, dispatcher)
|
408
412
|
document_link = Requests::DocumentLink.new(uri, parse_result.comments, dispatcher)
|
409
413
|
code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
|
414
|
+
inlay_hint = Requests::InlayHints.new(document, T.must(@store.features_configuration.dig(:inlayHint)), dispatcher)
|
410
415
|
dispatcher.dispatch(parse_result.value)
|
411
416
|
|
412
417
|
# Store all responses retrieve in this round of visits in the cache and then return the response for the request
|
@@ -415,6 +420,7 @@ module RubyLsp
|
|
415
420
|
document.cache_set("textDocument/documentSymbol", document_symbol.perform)
|
416
421
|
document.cache_set("textDocument/documentLink", document_link.perform)
|
417
422
|
document.cache_set("textDocument/codeLens", code_lens.perform)
|
423
|
+
document.cache_set("textDocument/inlayHint", inlay_hint.perform)
|
418
424
|
|
419
425
|
send_message(Result.new(id: message[:id], response: document.cache_get(message[:method])))
|
420
426
|
end
|
@@ -543,7 +549,7 @@ module RubyLsp
|
|
543
549
|
return
|
544
550
|
end
|
545
551
|
|
546
|
-
request = Requests::DocumentHighlight.new(document, params[:position], dispatcher)
|
552
|
+
request = Requests::DocumentHighlight.new(@global_state, document, params[:position], dispatcher)
|
547
553
|
dispatcher.dispatch(document.parse_result.value)
|
548
554
|
send_message(Result.new(id: message[:id], response: request.perform))
|
549
555
|
end
|
@@ -607,18 +613,35 @@ module RubyLsp
|
|
607
613
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
608
614
|
def text_document_inlay_hint(message)
|
609
615
|
params = message[:params]
|
616
|
+
document = @store.get(params.dig(:textDocument, :uri))
|
617
|
+
range = params.dig(:range, :start, :line)..params.dig(:range, :end, :line)
|
618
|
+
|
619
|
+
cached_response = document.cache_get("textDocument/inlayHint")
|
620
|
+
if cached_response != Document::EMPTY_CACHE
|
621
|
+
|
622
|
+
send_message(
|
623
|
+
Result.new(
|
624
|
+
id: message[:id],
|
625
|
+
response: cached_response.select { |hint| range.cover?(hint.position[:line]) },
|
626
|
+
),
|
627
|
+
)
|
628
|
+
return
|
629
|
+
end
|
630
|
+
|
610
631
|
hints_configurations = T.must(@store.features_configuration.dig(:inlayHint))
|
611
632
|
dispatcher = Prism::Dispatcher.new
|
612
|
-
document = @store.get(params.dig(:textDocument, :uri))
|
613
633
|
|
614
634
|
unless document.is_a?(RubyDocument) || document.is_a?(ERBDocument)
|
615
635
|
send_empty_response(message[:id])
|
616
636
|
return
|
617
637
|
end
|
618
638
|
|
619
|
-
request = Requests::InlayHints.new(document,
|
639
|
+
request = Requests::InlayHints.new(document, hints_configurations, dispatcher)
|
620
640
|
dispatcher.visit(document.parse_result.value)
|
621
|
-
|
641
|
+
result = request.perform
|
642
|
+
document.cache_set("textDocument/inlayHint", result)
|
643
|
+
|
644
|
+
send_message(Result.new(id: message[:id], response: result.select { |hint| range.cover?(hint.position[:line]) }))
|
622
645
|
end
|
623
646
|
|
624
647
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
@@ -740,6 +763,17 @@ module RubyLsp
|
|
740
763
|
|
741
764
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
742
765
|
def text_document_completion_item_resolve(message)
|
766
|
+
# When responding to a delegated completion request, it means we're handling a completion item that isn't related
|
767
|
+
# to Ruby (probably related to an ERB host language like HTML). We need to return the original completion item
|
768
|
+
# back to the editor so that it's displayed correctly
|
769
|
+
if message.dig(:params, :data, :delegateCompletion)
|
770
|
+
send_message(Result.new(
|
771
|
+
id: message[:id],
|
772
|
+
response: message[:params],
|
773
|
+
))
|
774
|
+
return
|
775
|
+
end
|
776
|
+
|
743
777
|
send_message(Result.new(
|
744
778
|
id: message[:id],
|
745
779
|
response: Requests::CompletionResolve.new(@global_state, message[:params]).perform,
|
@@ -27,7 +27,6 @@ module RubyLsp
|
|
27
27
|
def initialize(project_path, **options)
|
28
28
|
@project_path = project_path
|
29
29
|
@branch = T.let(options[:branch], T.nilable(String))
|
30
|
-
@experimental = T.let(options[:experimental], T.nilable(T::Boolean))
|
31
30
|
|
32
31
|
# Regular bundle paths
|
33
32
|
@gemfile = T.let(
|
@@ -56,7 +55,7 @@ module RubyLsp
|
|
56
55
|
|
57
56
|
# Sets up the custom bundle and returns the `BUNDLE_GEMFILE`, `BUNDLE_PATH` and `BUNDLE_APP_CONFIG` that should be
|
58
57
|
# used for running the server
|
59
|
-
sig { returns([String,
|
58
|
+
sig { returns(T::Hash[String, String]) }
|
60
59
|
def setup!
|
61
60
|
raise BundleNotLocked if @gemfile&.exist? && !@lockfile&.exist?
|
62
61
|
|
@@ -176,22 +175,18 @@ module RubyLsp
|
|
176
175
|
dependencies
|
177
176
|
end
|
178
177
|
|
179
|
-
sig { params(bundle_gemfile: T.nilable(Pathname)).returns([String,
|
178
|
+
sig { params(bundle_gemfile: T.nilable(Pathname)).returns(T::Hash[String, String]) }
|
180
179
|
def run_bundle_install(bundle_gemfile = @gemfile)
|
180
|
+
env = bundler_settings_as_env
|
181
|
+
env["BUNDLE_GEMFILE"] = bundle_gemfile.to_s
|
182
|
+
|
181
183
|
# If the user has a custom bundle path configured, we need to ensure that we will use the absolute and not
|
182
184
|
# relative version of it when running `bundle install`. This is necessary to avoid installing the gems under the
|
183
185
|
# `.ruby-lsp` folder, which is not the user's intention. For example, if the path is configured as `vendor`, we
|
184
186
|
# want to install it in the top level `vendor` and not `.ruby-lsp/vendor`
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
# Use the absolute `BUNDLE_PATH` to prevent accidentally creating unwanted folders under `.ruby-lsp`
|
189
|
-
env = {}
|
190
|
-
env["BUNDLE_GEMFILE"] = bundle_gemfile.to_s
|
191
|
-
env["BUNDLE_PATH"] = expanded_path if expanded_path
|
192
|
-
|
193
|
-
local_config_path = File.join(@project_path, ".bundle")
|
194
|
-
env["BUNDLE_APP_CONFIG"] = local_config_path if Dir.exist?(local_config_path)
|
187
|
+
if env["BUNDLE_PATH"]
|
188
|
+
env["BUNDLE_PATH"] = File.expand_path(env["BUNDLE_PATH"], @project_path)
|
189
|
+
end
|
195
190
|
|
196
191
|
# If `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) are already in the Gemfile, then we shouldn't try
|
197
192
|
# to upgrade them or else we'll produce undesired source control changes. If the custom bundle was just created
|
@@ -211,7 +206,6 @@ module RubyLsp
|
|
211
206
|
command << "ruby-lsp " unless @dependencies["ruby-lsp"]
|
212
207
|
command << "debug " unless @dependencies["debug"]
|
213
208
|
command << "ruby-lsp-rails " if @rails_app && !@dependencies["ruby-lsp-rails"]
|
214
|
-
command << "--pre" if @experimental
|
215
209
|
command.delete_suffix!(" ")
|
216
210
|
command << ")"
|
217
211
|
|
@@ -238,7 +232,31 @@ module RubyLsp
|
|
238
232
|
return setup!
|
239
233
|
end
|
240
234
|
|
241
|
-
|
235
|
+
env
|
236
|
+
end
|
237
|
+
|
238
|
+
# Gather all Bundler settings (global and local) and return them as a hash that can be used as the environment
|
239
|
+
sig { returns(T::Hash[String, String]) }
|
240
|
+
def bundler_settings_as_env
|
241
|
+
local_config_path = File.join(@project_path, ".bundle")
|
242
|
+
|
243
|
+
# If there's no Gemfile or if the local config path does not exist, we return an empty setting set (which has the
|
244
|
+
# global settings included). Otherwise, we also load the local settings
|
245
|
+
settings = begin
|
246
|
+
Dir.exist?(local_config_path) ? Bundler::Settings.new(local_config_path) : Bundler::Settings.new
|
247
|
+
rescue Bundler::GemfileNotFound
|
248
|
+
Bundler::Settings.new
|
249
|
+
end
|
250
|
+
|
251
|
+
# Map all settings to their environment variable names with `key_for` and their values. For example, the if the
|
252
|
+
# setting name `e` is `path` with a value of `vendor/bundle`, then it will return `"BUNDLE_PATH" =>
|
253
|
+
# "vendor/bundle"`
|
254
|
+
settings.all.to_h do |e|
|
255
|
+
key = Bundler::Settings.key_for(e)
|
256
|
+
value = Array(settings[e]).join(":").tr(" ", ":")
|
257
|
+
|
258
|
+
[key, value]
|
259
|
+
end
|
242
260
|
end
|
243
261
|
|
244
262
|
sig { returns(T::Boolean) }
|
@@ -7,13 +7,9 @@ module RubyLsp
|
|
7
7
|
class TypeInferrer
|
8
8
|
extend T::Sig
|
9
9
|
|
10
|
-
sig { params(
|
11
|
-
|
12
|
-
|
13
|
-
sig { params(index: RubyIndexer::Index, experimental_features: T::Boolean).void }
|
14
|
-
def initialize(index, experimental_features = true)
|
10
|
+
sig { params(index: RubyIndexer::Index).void }
|
11
|
+
def initialize(index)
|
15
12
|
@index = index
|
16
|
-
@experimental_features = experimental_features
|
17
13
|
end
|
18
14
|
|
19
15
|
sig { params(node_context: NodeContext).returns(T.nilable(Type)) }
|
@@ -93,8 +89,6 @@ module RubyLsp
|
|
93
89
|
|
94
90
|
Type.new("#{parts.join("::")}::#{last}::<Class:#{last}>")
|
95
91
|
else
|
96
|
-
return unless @experimental_features
|
97
|
-
|
98
92
|
raw_receiver = node.receiver&.slice
|
99
93
|
|
100
94
|
if raw_receiver
|
@@ -121,8 +115,12 @@ module RubyLsp
|
|
121
115
|
return Type.new(node_context.fully_qualified_name) if node_context.surrounding_method
|
122
116
|
|
123
117
|
# If we're not inside a method, then we're inside the body of a class or module, which is a singleton
|
124
|
-
# context
|
125
|
-
|
118
|
+
# context.
|
119
|
+
#
|
120
|
+
# If the class/module definition is using compact style (e.g.: `class Foo::Bar`), then we need to split the name
|
121
|
+
# into its individual parts to build the correct singleton name
|
122
|
+
parts = nesting.flat_map { |part| part.split("::") }
|
123
|
+
Type.new("#{parts.join("::")}::<Class:#{parts.last}>")
|
126
124
|
end
|
127
125
|
|
128
126
|
sig do
|
data/lib/ruby_lsp/utils.rb
CHANGED
@@ -25,7 +25,17 @@ module RubyLsp
|
|
25
25
|
end,
|
26
26
|
String,
|
27
27
|
)
|
28
|
-
GUESSED_TYPES_URL = "https://github.
|
28
|
+
GUESSED_TYPES_URL = "https://shopify.github.io/ruby-lsp/design-and-roadmap.html#guessed-types"
|
29
|
+
|
30
|
+
# Request delegation for embedded languages is not yet standardized into the language server specification. Here we
|
31
|
+
# use this custom error class as a way to return a signal to the client that the request should be delegated to the
|
32
|
+
# language server for the host language. The support for delegation is custom built on the client side, so each editor
|
33
|
+
# needs to implement their own until this becomes a part of the spec
|
34
|
+
class DelegateRequestError < StandardError
|
35
|
+
# A custom error code that clients can use to handle delegate requests. This is past the range of error codes listed
|
36
|
+
# by the specification to avoid conflicting with other error types
|
37
|
+
CODE = -32900
|
38
|
+
end
|
29
39
|
|
30
40
|
# A notification to be sent to the client
|
31
41
|
class Message
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -112,7 +112,6 @@ files:
|
|
112
112
|
- lib/ruby_indexer/test/test_case.rb
|
113
113
|
- lib/ruby_lsp/addon.rb
|
114
114
|
- lib/ruby_lsp/base_server.rb
|
115
|
-
- lib/ruby_lsp/check_docs.rb
|
116
115
|
- lib/ruby_lsp/document.rb
|
117
116
|
- lib/ruby_lsp/erb_document.rb
|
118
117
|
- lib/ruby_lsp/global_state.rb
|
@@ -132,7 +131,6 @@ files:
|
|
132
131
|
- lib/ruby_lsp/node_context.rb
|
133
132
|
- lib/ruby_lsp/parameter_scope.rb
|
134
133
|
- lib/ruby_lsp/rbs_document.rb
|
135
|
-
- lib/ruby_lsp/requests.rb
|
136
134
|
- lib/ruby_lsp/requests/code_action_resolve.rb
|
137
135
|
- lib/ruby_lsp/requests/code_actions.rb
|
138
136
|
- lib/ruby_lsp/requests/code_lens.rb
|
@@ -166,7 +164,6 @@ files:
|
|
166
164
|
- lib/ruby_lsp/requests/support/syntax_tree_formatter.rb
|
167
165
|
- lib/ruby_lsp/requests/type_hierarchy_supertypes.rb
|
168
166
|
- lib/ruby_lsp/requests/workspace_symbol.rb
|
169
|
-
- lib/ruby_lsp/response_builders.rb
|
170
167
|
- lib/ruby_lsp/response_builders/collection_response_builder.rb
|
171
168
|
- lib/ruby_lsp/response_builders/document_symbol.rb
|
172
169
|
- lib/ruby_lsp/response_builders/hover.rb
|
@@ -201,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
198
|
- !ruby/object:Gem::Version
|
202
199
|
version: '0'
|
203
200
|
requirements: []
|
204
|
-
rubygems_version: 3.5.
|
201
|
+
rubygems_version: 3.5.18
|
205
202
|
signing_key:
|
206
203
|
specification_version: 4
|
207
204
|
summary: An opinionated language server for Ruby
|
data/lib/ruby_lsp/check_docs.rb
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "ruby_lsp/internal"
|
5
|
-
require "objspace"
|
6
|
-
|
7
|
-
module RubyLsp
|
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 requests and their related
|
10
|
-
# GIFs
|
11
|
-
#
|
12
|
-
# # Rakefile
|
13
|
-
# request_files = FileList.new("#{__dir__}/lib/ruby_lsp/requests/*.rb") do |fl|
|
14
|
-
# fl.exclude(/base_request\.rb/)
|
15
|
-
# end
|
16
|
-
# gif_files = FileList.new("#{__dir__}/**/*.gif")
|
17
|
-
# RubyLsp::CheckDocs.new(request_files, gif_files)
|
18
|
-
# # Run with bundle exec rake ruby_lsp:check_docs
|
19
|
-
class CheckDocs < Rake::TaskLib
|
20
|
-
extend T::Sig
|
21
|
-
|
22
|
-
sig { params(require_files: Rake::FileList, gif_files: Rake::FileList).void }
|
23
|
-
def initialize(require_files, gif_files)
|
24
|
-
super()
|
25
|
-
|
26
|
-
@name = T.let("ruby_lsp:check_docs", String)
|
27
|
-
@file_list = require_files
|
28
|
-
@gif_list = gif_files
|
29
|
-
define_task
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
sig { void }
|
35
|
-
def define_task
|
36
|
-
desc("Checks if all Ruby LSP requests are documented")
|
37
|
-
task(@name) { run_task }
|
38
|
-
end
|
39
|
-
|
40
|
-
sig { params(request_path: String).returns(T::Boolean) }
|
41
|
-
def gif_exists?(request_path)
|
42
|
-
request_gif = request_path.gsub(".rb", ".gif").split("/").last
|
43
|
-
|
44
|
-
@gif_list.any? { |gif_path| gif_path.end_with?(request_gif) }
|
45
|
-
end
|
46
|
-
|
47
|
-
sig { void }
|
48
|
-
def run_task
|
49
|
-
# Require all files configured to make sure all requests are loaded
|
50
|
-
@file_list.each { |f| require(f.delete_suffix(".rb")) }
|
51
|
-
|
52
|
-
# Find all classes that inherit from BaseRequest, which are the ones we want to make sure are
|
53
|
-
# documented
|
54
|
-
features = ObjectSpace.each_object(Class).select do |k|
|
55
|
-
klass = T.unsafe(k)
|
56
|
-
klass < Requests::Request
|
57
|
-
end
|
58
|
-
|
59
|
-
missing_docs = T.let(Hash.new { |h, k| h[k] = [] }, T::Hash[String, T::Array[String]])
|
60
|
-
|
61
|
-
features.each do |klass|
|
62
|
-
class_name = T.unsafe(klass).name
|
63
|
-
file_path, line_number = Module.const_source_location(class_name)
|
64
|
-
next unless file_path && line_number
|
65
|
-
|
66
|
-
# Adjust the line number to start searching right above the class definition
|
67
|
-
line_number -= 2
|
68
|
-
|
69
|
-
lines = File.readlines(file_path)
|
70
|
-
docs = []
|
71
|
-
|
72
|
-
# Extract the documentation on top of the request constant
|
73
|
-
while (line = lines[line_number]&.strip) && line.start_with?("#")
|
74
|
-
docs.unshift(line)
|
75
|
-
line_number -= 1
|
76
|
-
end
|
77
|
-
|
78
|
-
documentation = docs.join("\n")
|
79
|
-
|
80
|
-
if docs.empty?
|
81
|
-
T.must(missing_docs[class_name]) << "No documentation found"
|
82
|
-
elsif !%r{\(https://microsoft.github.io/language-server-protocol/specification#.*\)}.match?(documentation)
|
83
|
-
T.must(missing_docs[class_name]) << <<~DOCS
|
84
|
-
Missing specification link. Requests and addons should include a link to the LSP specification for the
|
85
|
-
related feature. For example:
|
86
|
-
|
87
|
-
[Inlay hint](https://microsoft.github.io/language-server-protocol/specification#textDocument_inlayHint)
|
88
|
-
DOCS
|
89
|
-
elsif !documentation.include?("# Example")
|
90
|
-
T.must(missing_docs[class_name]) << <<~DOCS
|
91
|
-
Missing example. Requests and addons should include a code example that explains what the feature does.
|
92
|
-
|
93
|
-
# # Example
|
94
|
-
# ```ruby
|
95
|
-
# class Foo # <- information is shown here
|
96
|
-
# end
|
97
|
-
# ```
|
98
|
-
DOCS
|
99
|
-
elsif !/\[.* demo\]\(.*\.gif\)/.match?(documentation)
|
100
|
-
T.must(missing_docs[class_name]) << <<~DOCS
|
101
|
-
Missing demonstration GIF. Each request and addon must be documented with a GIF that shows the feature
|
102
|
-
working. For example:
|
103
|
-
|
104
|
-
# [Inlay hint demo](../../inlay_hint.gif)
|
105
|
-
DOCS
|
106
|
-
elsif !gif_exists?(file_path)
|
107
|
-
T.must(missing_docs[class_name]) << <<~DOCS
|
108
|
-
The GIF for the request documentation does not exist. Make sure to add it,
|
109
|
-
with the same naming as the request. For example:
|
110
|
-
|
111
|
-
# lib/ruby_lsp/requests/code_lens.rb
|
112
|
-
# foo/bar/code_lens.gif
|
113
|
-
DOCS
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
if missing_docs.any?
|
118
|
-
$stderr.puts(<<~WARN)
|
119
|
-
The following requests are missing documentation:
|
120
|
-
|
121
|
-
#{missing_docs.map { |k, v| "#{k}\n\n#{v.join("\n")}" }.join("\n\n")}
|
122
|
-
WARN
|
123
|
-
|
124
|
-
abort
|
125
|
-
end
|
126
|
-
|
127
|
-
puts "All requests are documented!"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
data/lib/ruby_lsp/requests.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module RubyLsp
|
5
|
-
# Supported features
|
6
|
-
#
|
7
|
-
# - [DocumentSymbol](rdoc-ref:RubyLsp::Requests::DocumentSymbol)
|
8
|
-
# - [DocumentLink](rdoc-ref:RubyLsp::Requests::DocumentLink)
|
9
|
-
# - [Hover](rdoc-ref:RubyLsp::Requests::Hover)
|
10
|
-
# - [FoldingRange](rdoc-ref:RubyLsp::Requests::FoldingRanges)
|
11
|
-
# - [SelectionRange](rdoc-ref:RubyLsp::Requests::SelectionRanges)
|
12
|
-
# - [SemanticHighlighting](rdoc-ref:RubyLsp::Requests::SemanticHighlighting)
|
13
|
-
# - [Formatting](rdoc-ref:RubyLsp::Requests::Formatting)
|
14
|
-
# - [OnTypeFormatting](rdoc-ref:RubyLsp::Requests::OnTypeFormatting)
|
15
|
-
# - [Diagnostic](rdoc-ref:RubyLsp::Requests::Diagnostics)
|
16
|
-
# - [CodeAction](rdoc-ref:RubyLsp::Requests::CodeActions)
|
17
|
-
# - [CodeActionResolve](rdoc-ref:RubyLsp::Requests::CodeActionResolve)
|
18
|
-
# - [DocumentHighlight](rdoc-ref:RubyLsp::Requests::DocumentHighlight)
|
19
|
-
# - [InlayHint](rdoc-ref:RubyLsp::Requests::InlayHints)
|
20
|
-
# - [Completion](rdoc-ref:RubyLsp::Requests::Completion)
|
21
|
-
# - [CompletionResolve](rdoc-ref:RubyLsp::Requests::CompletionResolve)
|
22
|
-
# - [CodeLens](rdoc-ref:RubyLsp::Requests::CodeLens)
|
23
|
-
# - [Definition](rdoc-ref:RubyLsp::Requests::Definition)
|
24
|
-
# - [ShowSyntaxTree](rdoc-ref:RubyLsp::Requests::ShowSyntaxTree)
|
25
|
-
# - [WorkspaceSymbol](rdoc-ref:RubyLsp::Requests::WorkspaceSymbol)
|
26
|
-
# - [SignatureHelp](rdoc-ref:RubyLsp::Requests::SignatureHelp)
|
27
|
-
|
28
|
-
module Requests
|
29
|
-
autoload :Request, "ruby_lsp/requests/request"
|
30
|
-
autoload :DocumentSymbol, "ruby_lsp/requests/document_symbol"
|
31
|
-
autoload :DocumentLink, "ruby_lsp/requests/document_link"
|
32
|
-
autoload :Hover, "ruby_lsp/requests/hover"
|
33
|
-
autoload :FoldingRanges, "ruby_lsp/requests/folding_ranges"
|
34
|
-
autoload :SelectionRanges, "ruby_lsp/requests/selection_ranges"
|
35
|
-
autoload :SemanticHighlighting, "ruby_lsp/requests/semantic_highlighting"
|
36
|
-
autoload :Formatting, "ruby_lsp/requests/formatting"
|
37
|
-
autoload :OnTypeFormatting, "ruby_lsp/requests/on_type_formatting"
|
38
|
-
autoload :Diagnostics, "ruby_lsp/requests/diagnostics"
|
39
|
-
autoload :CodeActions, "ruby_lsp/requests/code_actions"
|
40
|
-
autoload :CodeActionResolve, "ruby_lsp/requests/code_action_resolve"
|
41
|
-
autoload :DocumentHighlight, "ruby_lsp/requests/document_highlight"
|
42
|
-
autoload :InlayHints, "ruby_lsp/requests/inlay_hints"
|
43
|
-
autoload :Completion, "ruby_lsp/requests/completion"
|
44
|
-
autoload :CompletionResolve, "ruby_lsp/requests/completion_resolve"
|
45
|
-
autoload :CodeLens, "ruby_lsp/requests/code_lens"
|
46
|
-
autoload :Definition, "ruby_lsp/requests/definition"
|
47
|
-
autoload :ShowSyntaxTree, "ruby_lsp/requests/show_syntax_tree"
|
48
|
-
autoload :WorkspaceSymbol, "ruby_lsp/requests/workspace_symbol"
|
49
|
-
autoload :SignatureHelp, "ruby_lsp/requests/signature_help"
|
50
|
-
autoload :PrepareTypeHierarchy, "ruby_lsp/requests/prepare_type_hierarchy"
|
51
|
-
autoload :TypeHierarchySupertypes, "ruby_lsp/requests/type_hierarchy_supertypes"
|
52
|
-
|
53
|
-
# :nodoc:
|
54
|
-
module Support
|
55
|
-
autoload :RuboCopDiagnostic, "ruby_lsp/requests/support/rubocop_diagnostic"
|
56
|
-
autoload :SelectionRange, "ruby_lsp/requests/support/selection_range"
|
57
|
-
autoload :Annotation, "ruby_lsp/requests/support/annotation"
|
58
|
-
autoload :Sorbet, "ruby_lsp/requests/support/sorbet"
|
59
|
-
autoload :RailsDocumentClient, "ruby_lsp/requests/support/rails_document_client"
|
60
|
-
autoload :Common, "ruby_lsp/requests/support/common"
|
61
|
-
autoload :Formatter, "ruby_lsp/requests/support/formatter"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module RubyLsp
|
5
|
-
module ResponseBuilders
|
6
|
-
autoload :CollectionResponseBuilder, "ruby_lsp/response_builders/collection_response_builder"
|
7
|
-
autoload :DocumentSymbol, "ruby_lsp/response_builders/document_symbol"
|
8
|
-
autoload :Hover, "ruby_lsp/response_builders/hover"
|
9
|
-
autoload :ResponseBuilder, "ruby_lsp/response_builders/response_builder"
|
10
|
-
autoload :SemanticHighlighting, "ruby_lsp/response_builders/semantic_highlighting"
|
11
|
-
autoload :SignatureHelp, "ruby_lsp/response_builders/signature_help"
|
12
|
-
end
|
13
|
-
end
|