ruby-lsp 0.23.11 → 0.23.12
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-launcher +12 -11
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +52 -77
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +61 -144
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +8 -6
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +73 -182
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +48 -181
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +12 -14
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +21 -44
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +40 -58
- data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +9 -16
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +5 -9
- data/lib/ruby_indexer/test/configuration_test.rb +32 -2
- data/lib/ruby_indexer/test/method_test.rb +2 -2
- data/lib/ruby_lsp/addon.rb +32 -67
- data/lib/ruby_lsp/base_server.rb +10 -10
- data/lib/ruby_lsp/client_capabilities.rb +4 -6
- data/lib/ruby_lsp/document.rb +21 -32
- data/lib/ruby_lsp/erb_document.rb +17 -27
- data/lib/ruby_lsp/global_state.rb +30 -32
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +21 -39
- data/lib/ruby_lsp/listeners/completion.rb +34 -53
- data/lib/ruby_lsp/listeners/definition.rb +35 -49
- data/lib/ruby_lsp/listeners/document_highlight.rb +60 -69
- data/lib/ruby_lsp/listeners/document_link.rb +9 -19
- data/lib/ruby_lsp/listeners/document_symbol.rb +34 -48
- data/lib/ruby_lsp/listeners/folding_ranges.rb +31 -38
- data/lib/ruby_lsp/listeners/hover.rb +37 -47
- data/lib/ruby_lsp/listeners/inlay_hints.rb +3 -10
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +29 -35
- data/lib/ruby_lsp/listeners/signature_help.rb +4 -23
- data/lib/ruby_lsp/listeners/spec_style.rb +199 -0
- data/lib/ruby_lsp/listeners/test_style.rb +136 -30
- data/lib/ruby_lsp/node_context.rb +8 -35
- data/lib/ruby_lsp/rbs_document.rb +7 -5
- data/lib/ruby_lsp/requests/code_action_resolve.rb +10 -10
- data/lib/ruby_lsp/requests/code_actions.rb +5 -14
- data/lib/ruby_lsp/requests/code_lens.rb +4 -13
- data/lib/ruby_lsp/requests/completion.rb +4 -15
- data/lib/ruby_lsp/requests/completion_resolve.rb +4 -4
- data/lib/ruby_lsp/requests/definition.rb +4 -12
- data/lib/ruby_lsp/requests/diagnostics.rb +6 -9
- data/lib/ruby_lsp/requests/discover_tests.rb +15 -3
- data/lib/ruby_lsp/requests/document_highlight.rb +3 -11
- data/lib/ruby_lsp/requests/document_link.rb +4 -13
- data/lib/ruby_lsp/requests/document_symbol.rb +4 -7
- data/lib/ruby_lsp/requests/folding_ranges.rb +4 -7
- data/lib/ruby_lsp/requests/formatting.rb +4 -7
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
- data/lib/ruby_lsp/requests/hover.rb +6 -16
- data/lib/ruby_lsp/requests/inlay_hints.rb +4 -13
- data/lib/ruby_lsp/requests/on_type_formatting.rb +17 -24
- data/lib/ruby_lsp/requests/prepare_rename.rb +3 -8
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +4 -13
- data/lib/ruby_lsp/requests/range_formatting.rb +3 -4
- data/lib/ruby_lsp/requests/references.rb +5 -35
- data/lib/ruby_lsp/requests/rename.rb +9 -35
- data/lib/ruby_lsp/requests/request.rb +5 -17
- data/lib/ruby_lsp/requests/selection_ranges.rb +3 -3
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +6 -23
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +4 -5
- data/lib/ruby_lsp/requests/signature_help.rb +6 -24
- data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
- data/lib/ruby_lsp/requests/support/common.rb +12 -49
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -14
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +7 -10
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +9 -15
- data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
- data/lib/ruby_lsp/requests/support/sorbet.rb +1 -7
- data/lib/ruby_lsp/requests/support/source_uri.rb +5 -16
- data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +7 -10
- data/lib/ruby_lsp/requests/support/test_item.rb +14 -13
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +4 -5
- data/lib/ruby_lsp/requests/workspace_symbol.rb +3 -3
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +4 -4
- data/lib/ruby_lsp/response_builders/document_symbol.rb +8 -11
- data/lib/ruby_lsp/response_builders/hover.rb +5 -5
- data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +18 -40
- data/lib/ruby_lsp/response_builders/signature_help.rb +4 -5
- data/lib/ruby_lsp/response_builders/test_collection.rb +5 -9
- data/lib/ruby_lsp/ruby_document.rb +15 -40
- data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +106 -0
- data/lib/ruby_lsp/scope.rb +6 -10
- data/lib/ruby_lsp/server.rb +125 -74
- data/lib/ruby_lsp/setup_bundler.rb +22 -15
- data/lib/ruby_lsp/store.rb +12 -28
- data/lib/ruby_lsp/test_helper.rb +3 -12
- data/lib/ruby_lsp/test_reporter.rb +71 -0
- data/lib/ruby_lsp/test_unit_test_runner.rb +96 -0
- data/lib/ruby_lsp/type_inferrer.rb +9 -13
- data/lib/ruby_lsp/utils.rb +27 -65
- metadata +8 -3
@@ -27,7 +27,7 @@ module RubyLsp
|
|
27
27
|
|
28
28
|
FOUR_HOURS = T.let(4 * 60 * 60, Integer)
|
29
29
|
|
30
|
-
|
30
|
+
#: (String project_path, **untyped options) -> void
|
31
31
|
def initialize(project_path, **options)
|
32
32
|
@project_path = project_path
|
33
33
|
@branch = T.let(options[:branch], T.nilable(String))
|
@@ -68,7 +68,7 @@ module RubyLsp
|
|
68
68
|
|
69
69
|
# Sets up the composed bundle and returns the `BUNDLE_GEMFILE`, `BUNDLE_PATH` and `BUNDLE_APP_CONFIG` that should be
|
70
70
|
# used for running the server
|
71
|
-
|
71
|
+
#: -> Hash[String, String]
|
72
72
|
def setup!
|
73
73
|
raise BundleNotLocked if !@launcher && @gemfile&.exist? && !@lockfile&.exist?
|
74
74
|
|
@@ -128,7 +128,7 @@ module RubyLsp
|
|
128
128
|
|
129
129
|
private
|
130
130
|
|
131
|
-
|
131
|
+
#: -> Hash[String, untyped]
|
132
132
|
def composed_bundle_dependencies
|
133
133
|
@composed_bundle_dependencies ||= T.let(
|
134
134
|
begin
|
@@ -147,7 +147,7 @@ module RubyLsp
|
|
147
147
|
)
|
148
148
|
end
|
149
149
|
|
150
|
-
|
150
|
+
#: -> void
|
151
151
|
def write_custom_gemfile
|
152
152
|
parts = [
|
153
153
|
"# This custom gemfile is automatically generated by the Ruby LSP.",
|
@@ -188,7 +188,7 @@ module RubyLsp
|
|
188
188
|
@custom_gemfile.write(content) unless @custom_gemfile.exist? && @custom_gemfile.read == content
|
189
189
|
end
|
190
190
|
|
191
|
-
|
191
|
+
#: -> [Hash[String, untyped], Gem::Version?]
|
192
192
|
def load_dependencies
|
193
193
|
return [{}, nil] unless @lockfile&.exist?
|
194
194
|
|
@@ -208,7 +208,7 @@ module RubyLsp
|
|
208
208
|
[dependencies, lockfile_parser.bundler_version]
|
209
209
|
end
|
210
210
|
|
211
|
-
|
211
|
+
#: (?Pathname? bundle_gemfile) -> Hash[String, String]
|
212
212
|
def run_bundle_install(bundle_gemfile = @gemfile)
|
213
213
|
env = bundler_settings_as_env
|
214
214
|
env["BUNDLE_GEMFILE"] = bundle_gemfile.to_s
|
@@ -259,7 +259,7 @@ module RubyLsp
|
|
259
259
|
env
|
260
260
|
end
|
261
261
|
|
262
|
-
|
262
|
+
#: (Hash[String, String] env, ?force_install: bool) -> Hash[String, String]
|
263
263
|
def run_bundle_install_directly(env, force_install: false)
|
264
264
|
RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
|
265
265
|
|
@@ -288,7 +288,7 @@ module RubyLsp
|
|
288
288
|
@retry ? env : run_bundle_install_directly(env, force_install: true)
|
289
289
|
end
|
290
290
|
|
291
|
-
|
291
|
+
#: (Hash[String, String] env) -> Hash[String, String]
|
292
292
|
def run_bundle_install_through_command(env)
|
293
293
|
# If `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) are already in the Gemfile, then we shouldn't try
|
294
294
|
# to upgrade them or else we'll produce undesired source control changes. If the composed bundle was just created
|
@@ -345,7 +345,7 @@ module RubyLsp
|
|
345
345
|
end
|
346
346
|
|
347
347
|
# Gather all Bundler settings (global and local) and return them as a hash that can be used as the environment
|
348
|
-
|
348
|
+
#: -> Hash[String, String]
|
349
349
|
def bundler_settings_as_env
|
350
350
|
local_config_path = File.join(@project_path, ".bundle")
|
351
351
|
|
@@ -357,10 +357,17 @@ module RubyLsp
|
|
357
357
|
Bundler::Settings.new
|
358
358
|
end
|
359
359
|
|
360
|
+
# List of Bundler settings that don't make sense for the composed bundle and are better controlled manually by the
|
361
|
+
# user
|
362
|
+
ignored_settings = ["bin", "cache_all", "cache_all_platforms"]
|
363
|
+
|
360
364
|
# Map all settings to their environment variable names with `key_for` and their values. For example, the if the
|
361
365
|
# setting name `e` is `path` with a value of `vendor/bundle`, then it will return `"BUNDLE_PATH" =>
|
362
366
|
# "vendor/bundle"`
|
363
|
-
settings
|
367
|
+
settings
|
368
|
+
.all
|
369
|
+
.reject { |setting| ignored_settings.include?(setting) }
|
370
|
+
.to_h do |e|
|
364
371
|
key = settings.key_for(e)
|
365
372
|
value = Array(settings[e]).join(":").tr(" ", ":")
|
366
373
|
|
@@ -368,7 +375,7 @@ module RubyLsp
|
|
368
375
|
end
|
369
376
|
end
|
370
377
|
|
371
|
-
|
378
|
+
#: -> void
|
372
379
|
def install_bundler_if_needed
|
373
380
|
# Try to find the bundler version specified in the lockfile in installed gems. If not found, install it
|
374
381
|
requirement = Gem::Requirement.new(@bundler_version.to_s)
|
@@ -377,7 +384,7 @@ module RubyLsp
|
|
377
384
|
Gem.install("bundler", @bundler_version.to_s)
|
378
385
|
end
|
379
386
|
|
380
|
-
|
387
|
+
#: -> bool
|
381
388
|
def should_bundle_update?
|
382
389
|
# If `ruby-lsp`, `ruby-lsp-rails` and `debug` are in the Gemfile, then we shouldn't try to upgrade them or else it
|
383
390
|
# will produce version control changes
|
@@ -400,7 +407,7 @@ module RubyLsp
|
|
400
407
|
|
401
408
|
# When a lockfile has remote references based on relative file paths, we need to ensure that they are pointing to
|
402
409
|
# the correct place since after copying the relative path is no longer valid
|
403
|
-
|
410
|
+
#: -> void
|
404
411
|
def correct_relative_remote_paths
|
405
412
|
content = @custom_lockfile.read
|
406
413
|
content.gsub!(/remote: (.*)/) do |match|
|
@@ -422,7 +429,7 @@ module RubyLsp
|
|
422
429
|
end
|
423
430
|
|
424
431
|
# Detects if the project is a Rails app by looking if the superclass of the main class is `Rails::Application`
|
425
|
-
|
432
|
+
#: -> bool
|
426
433
|
def rails_app?
|
427
434
|
config = Pathname.new("config/application.rb").expand_path
|
428
435
|
application_contents = config.read(external_encoding: Encoding::UTF_8) if config.exist?
|
@@ -431,7 +438,7 @@ module RubyLsp
|
|
431
438
|
/class .* < (::)?Rails::Application/.match?(application_contents)
|
432
439
|
end
|
433
440
|
|
434
|
-
|
441
|
+
#: -> void
|
435
442
|
def patch_thor_to_print_progress_to_stderr!
|
436
443
|
return unless defined?(Bundler::Thor::Shell::Basic)
|
437
444
|
|
data/lib/ruby_lsp/store.rb
CHANGED
@@ -3,17 +3,15 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
class Store
|
6
|
-
extend T::Sig
|
7
|
-
|
8
6
|
class NonExistingDocumentError < StandardError; end
|
9
7
|
|
10
|
-
|
8
|
+
#: Hash[Symbol, RequestConfig]
|
11
9
|
attr_accessor :features_configuration
|
12
10
|
|
13
|
-
|
11
|
+
#: String
|
14
12
|
attr_accessor :client_name
|
15
13
|
|
16
|
-
|
14
|
+
#: (GlobalState global_state) -> void
|
17
15
|
def initialize(global_state)
|
18
16
|
@global_state = global_state
|
19
17
|
@state = T.let({}, T::Hash[String, Document[T.untyped]])
|
@@ -30,7 +28,7 @@ module RubyLsp
|
|
30
28
|
@client_name = T.let("Unknown", String)
|
31
29
|
end
|
32
30
|
|
33
|
-
|
31
|
+
#: (URI::Generic uri) -> Document[untyped]
|
34
32
|
def get(uri)
|
35
33
|
document = @state[uri.to_s]
|
36
34
|
return document unless document.nil?
|
@@ -56,14 +54,7 @@ module RubyLsp
|
|
56
54
|
raise NonExistingDocumentError, uri.to_s
|
57
55
|
end
|
58
56
|
|
59
|
-
|
60
|
-
params(
|
61
|
-
uri: URI::Generic,
|
62
|
-
source: String,
|
63
|
-
version: Integer,
|
64
|
-
language_id: Document::LanguageId,
|
65
|
-
).returns(Document[T.untyped])
|
66
|
-
end
|
57
|
+
#: (uri: URI::Generic, source: String, version: Integer, language_id: Document::LanguageId) -> Document[untyped]
|
67
58
|
def set(uri:, source:, version:, language_id:)
|
68
59
|
@state[uri.to_s] = case language_id
|
69
60
|
when Document::LanguageId::ERB
|
@@ -75,46 +66,39 @@ module RubyLsp
|
|
75
66
|
end
|
76
67
|
end
|
77
68
|
|
78
|
-
|
69
|
+
#: (uri: URI::Generic, edits: Array[Hash[Symbol, untyped]], version: Integer) -> void
|
79
70
|
def push_edits(uri:, edits:, version:)
|
80
71
|
T.must(@state[uri.to_s]).push_edits(edits, version: version)
|
81
72
|
end
|
82
73
|
|
83
|
-
|
74
|
+
#: -> void
|
84
75
|
def clear
|
85
76
|
@state.clear
|
86
77
|
end
|
87
78
|
|
88
|
-
|
79
|
+
#: -> bool
|
89
80
|
def empty?
|
90
81
|
@state.empty?
|
91
82
|
end
|
92
83
|
|
93
|
-
|
84
|
+
#: (URI::Generic uri) -> void
|
94
85
|
def delete(uri)
|
95
86
|
@state.delete(uri.to_s)
|
96
87
|
end
|
97
88
|
|
98
|
-
|
89
|
+
#: (URI::Generic uri) -> bool
|
99
90
|
def key?(uri)
|
100
91
|
@state.key?(uri.to_s)
|
101
92
|
end
|
102
93
|
|
103
|
-
|
94
|
+
#: { (String uri, Document[untyped] document) -> void } -> void
|
104
95
|
def each(&block)
|
105
96
|
@state.each do |uri, document|
|
106
97
|
block.call(uri, document)
|
107
98
|
end
|
108
99
|
end
|
109
100
|
|
110
|
-
|
111
|
-
type_parameters(:T)
|
112
|
-
.params(
|
113
|
-
uri: URI::Generic,
|
114
|
-
request_name: String,
|
115
|
-
block: T.proc.params(document: Document[T.untyped]).returns(T.type_parameter(:T)),
|
116
|
-
).returns(T.type_parameter(:T))
|
117
|
-
end
|
101
|
+
#: [T] (URI::Generic uri, String request_name) { (Document[untyped] document) -> T } -> T
|
118
102
|
def cache_fetch(uri, request_name, &block)
|
119
103
|
get(uri).cache_fetch(request_name, &block)
|
120
104
|
end
|
data/lib/ruby_lsp/test_helper.rb
CHANGED
@@ -7,21 +7,11 @@ module RubyLsp
|
|
7
7
|
module TestHelper
|
8
8
|
class TestError < StandardError; end
|
9
9
|
|
10
|
-
extend T::Sig
|
11
10
|
extend T::Helpers
|
12
11
|
|
13
12
|
requires_ancestor { Kernel }
|
14
13
|
|
15
|
-
|
16
|
-
type_parameters(:T)
|
17
|
-
.params(
|
18
|
-
source: T.nilable(String),
|
19
|
-
uri: URI::Generic,
|
20
|
-
stub_no_typechecker: T::Boolean,
|
21
|
-
load_addons: T::Boolean,
|
22
|
-
block: T.proc.params(server: RubyLsp::Server, uri: URI::Generic).returns(T.type_parameter(:T)),
|
23
|
-
).returns(T.type_parameter(:T))
|
24
|
-
end
|
14
|
+
#: [T] (?String? source, ?URI::Generic uri, ?stub_no_typechecker: bool, ?load_addons: bool) { (RubyLsp::Server server, URI::Generic uri) -> T } -> T
|
25
15
|
def with_server(source = nil, uri = Kernel.URI("file:///fake.rb"), stub_no_typechecker: false, load_addons: true,
|
26
16
|
&block)
|
27
17
|
server = RubyLsp::Server.new(test_mode: true)
|
@@ -52,13 +42,14 @@ module RubyLsp
|
|
52
42
|
ensure
|
53
43
|
if load_addons
|
54
44
|
RubyLsp::Addon.addons.each(&:deactivate)
|
45
|
+
RubyLsp::Addon.addon_classes.clear
|
55
46
|
RubyLsp::Addon.addons.clear
|
56
47
|
end
|
57
48
|
server.run_shutdown
|
58
49
|
end
|
59
50
|
end
|
60
51
|
|
61
|
-
|
52
|
+
#: (RubyLsp::Server server) -> RubyLsp::Result
|
62
53
|
def pop_result(server)
|
63
54
|
result = server.pop_response
|
64
55
|
result = server.pop_response until result.is_a?(RubyLsp::Result) || result.is_a?(RubyLsp::Error)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
$stdout.binmode
|
7
|
+
$stdout.sync = true
|
8
|
+
$stderr.binmode
|
9
|
+
$stderr.sync = true
|
10
|
+
|
11
|
+
module RubyLsp
|
12
|
+
module TestReporter
|
13
|
+
class << self
|
14
|
+
#: (id: String, uri: URI::Generic) -> void
|
15
|
+
def start_test(id:, uri:)
|
16
|
+
params = {
|
17
|
+
id: id,
|
18
|
+
uri: uri.to_s,
|
19
|
+
}
|
20
|
+
send_message("start", params)
|
21
|
+
end
|
22
|
+
|
23
|
+
#: (id: String, uri: URI::Generic) -> void
|
24
|
+
def record_pass(id:, uri:)
|
25
|
+
params = {
|
26
|
+
id: id,
|
27
|
+
uri: uri.to_s,
|
28
|
+
}
|
29
|
+
send_message("pass", params)
|
30
|
+
end
|
31
|
+
|
32
|
+
#: (id: String, message: String, uri: URI::Generic) -> void
|
33
|
+
def record_fail(id:, message:, uri:)
|
34
|
+
params = {
|
35
|
+
id: id,
|
36
|
+
message: message,
|
37
|
+
uri: uri.to_s,
|
38
|
+
}
|
39
|
+
send_message("fail", params)
|
40
|
+
end
|
41
|
+
|
42
|
+
#: (id: String, message: String?, uri: URI::Generic) -> void
|
43
|
+
def record_skip(id:, message:, uri:)
|
44
|
+
params = {
|
45
|
+
id: id,
|
46
|
+
message: message,
|
47
|
+
uri: uri.to_s,
|
48
|
+
}
|
49
|
+
send_message("skip", params)
|
50
|
+
end
|
51
|
+
|
52
|
+
#: (id: String, message: String?, uri: URI::Generic) -> void
|
53
|
+
def record_error(id:, message:, uri:)
|
54
|
+
params = {
|
55
|
+
id: id,
|
56
|
+
message: message,
|
57
|
+
uri: uri.to_s,
|
58
|
+
}
|
59
|
+
send_message("error", params)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
#: (method_name: String?, params: Hash[String, untyped]) -> void
|
65
|
+
def send_message(method_name, params)
|
66
|
+
json_message = { method: method_name, params: params }.to_json
|
67
|
+
$stdout.write("Content-Length: #{json_message.bytesize}\r\n\r\n#{json_message}")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "test/unit"
|
5
|
+
require "test/unit/ui/testrunner"
|
6
|
+
require "ruby_lsp/test_reporter"
|
7
|
+
require "ruby_indexer/lib/ruby_indexer/uri"
|
8
|
+
|
9
|
+
module RubyLsp
|
10
|
+
class TestRunner < ::Test::Unit::UI::TestRunner
|
11
|
+
private
|
12
|
+
|
13
|
+
#: (::Test::Unit::TestCase test) -> void
|
14
|
+
def test_started(test)
|
15
|
+
current_test = test
|
16
|
+
@current_uri = uri_for_test(current_test)
|
17
|
+
return unless @current_uri
|
18
|
+
|
19
|
+
@current_test_id = "#{current_test.class.name}##{current_test.method_name}"
|
20
|
+
TestReporter.start_test(
|
21
|
+
id: @current_test_id,
|
22
|
+
uri: @current_uri,
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
#: (::Test::Unit::TestCase test) -> void
|
27
|
+
def test_finished(test)
|
28
|
+
if test.passed?
|
29
|
+
TestReporter.record_pass(
|
30
|
+
id: @current_test_id,
|
31
|
+
uri: @current_uri,
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
#: (::Test::Unit::Failure | ::Test::Unit::Error | ::Test::Unit::Pending result) -> void
|
37
|
+
def result_fault(result)
|
38
|
+
case result
|
39
|
+
when ::Test::Unit::Failure
|
40
|
+
record_failure(result)
|
41
|
+
when ::Test::Unit::Error
|
42
|
+
record_error(result)
|
43
|
+
when ::Test::Unit::Pending
|
44
|
+
record_skip(result)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
#: (::Test::Unit::Failure failure) -> void
|
49
|
+
def record_failure(failure)
|
50
|
+
TestReporter.record_fail(
|
51
|
+
id: @current_test_id,
|
52
|
+
message: failure.message,
|
53
|
+
uri: @current_uri,
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
#: (::Test::Unit::Error error) -> void
|
58
|
+
def record_error(error)
|
59
|
+
TestReporter.record_error(
|
60
|
+
id: @current_test_id,
|
61
|
+
message: error.message,
|
62
|
+
uri: @current_uri,
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
#: (::Test::Unit::Pending pending) -> void
|
67
|
+
def record_skip(pending)
|
68
|
+
TestReporter.record_skip(
|
69
|
+
id: @current_test_id,
|
70
|
+
message: pending.message,
|
71
|
+
uri: @current_uri,
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
#: (::Test::Unit::TestCase test) -> URI::Generic?
|
76
|
+
def uri_for_test(test)
|
77
|
+
location = test.method(test.method_name).source_location
|
78
|
+
return unless location # TODO: when might this be nil?
|
79
|
+
|
80
|
+
file, _line = location
|
81
|
+
return if file.start_with?("(eval at ") # test is dynamically defined (TODO: better way to check?)
|
82
|
+
|
83
|
+
absolute_path = File.expand_path(file, Dir.pwd)
|
84
|
+
URI::Generic.from_path(path: absolute_path)
|
85
|
+
end
|
86
|
+
|
87
|
+
#: -> void
|
88
|
+
def attach_to_mediator
|
89
|
+
@mediator.add_listener(Test::Unit::TestResult::FAULT, &method(:result_fault))
|
90
|
+
@mediator.add_listener(Test::Unit::TestCase::STARTED_OBJECT, &method(:test_started))
|
91
|
+
@mediator.add_listener(Test::Unit::TestCase::FINISHED_OBJECT, &method(:test_finished))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Test::Unit::AutoRunner.register_runner(:ruby_lsp) { |_auto_runner| RubyLsp::TestRunner }
|
@@ -5,14 +5,12 @@ module RubyLsp
|
|
5
5
|
# A minimalistic type checker to try to resolve types that can be inferred without requiring a type system or
|
6
6
|
# annotations
|
7
7
|
class TypeInferrer
|
8
|
-
|
9
|
-
|
10
|
-
sig { params(index: RubyIndexer::Index).void }
|
8
|
+
#: (RubyIndexer::Index index) -> void
|
11
9
|
def initialize(index)
|
12
10
|
@index = index
|
13
11
|
end
|
14
12
|
|
15
|
-
|
13
|
+
#: (NodeContext node_context) -> Type?
|
16
14
|
def infer_receiver_type(node_context)
|
17
15
|
node = node_context.node
|
18
16
|
|
@@ -31,7 +29,7 @@ module RubyLsp
|
|
31
29
|
|
32
30
|
private
|
33
31
|
|
34
|
-
|
32
|
+
#: (Prism::CallNode node, NodeContext node_context) -> Type?
|
35
33
|
def infer_receiver_for_call_node(node, node_context)
|
36
34
|
receiver = node.receiver
|
37
35
|
|
@@ -114,7 +112,7 @@ module RubyLsp
|
|
114
112
|
end
|
115
113
|
end
|
116
114
|
|
117
|
-
|
115
|
+
#: (String raw_receiver, Array[String] nesting) -> GuessedType?
|
118
116
|
def guess_type(raw_receiver, nesting)
|
119
117
|
guessed_name = raw_receiver
|
120
118
|
.delete_prefix("@")
|
@@ -130,7 +128,7 @@ module RubyLsp
|
|
130
128
|
GuessedType.new(name)
|
131
129
|
end
|
132
130
|
|
133
|
-
|
131
|
+
#: (NodeContext node_context) -> Type
|
134
132
|
def self_receiver_handling(node_context)
|
135
133
|
nesting = node_context.nesting
|
136
134
|
# If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
|
@@ -147,7 +145,7 @@ module RubyLsp
|
|
147
145
|
Type.new("#{parts.join("::")}::<Class:#{parts.last}>")
|
148
146
|
end
|
149
147
|
|
150
|
-
|
148
|
+
#: (NodeContext node_context) -> Type?
|
151
149
|
def infer_receiver_for_class_variables(node_context)
|
152
150
|
nesting_parts = node_context.nesting.dup
|
153
151
|
|
@@ -168,18 +166,16 @@ module RubyLsp
|
|
168
166
|
|
169
167
|
# A known type
|
170
168
|
class Type
|
171
|
-
|
172
|
-
|
173
|
-
sig { returns(String) }
|
169
|
+
#: String
|
174
170
|
attr_reader :name
|
175
171
|
|
176
|
-
|
172
|
+
#: (String name) -> void
|
177
173
|
def initialize(name)
|
178
174
|
@name = name
|
179
175
|
end
|
180
176
|
|
181
177
|
# Returns the attached version of this type by removing the `<Class:...>` part from its name
|
182
|
-
|
178
|
+
#: -> Type
|
183
179
|
def attached
|
184
180
|
Type.new(T.must(@name.split("::")[..-2]).join("::"))
|
185
181
|
end
|