ruby-lsp 0.23.10 → 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.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +12 -11
  5. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
  6. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +52 -77
  7. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +61 -144
  8. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +8 -6
  9. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +74 -183
  10. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +55 -181
  11. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  12. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +12 -14
  13. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +21 -44
  14. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +40 -58
  15. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +9 -16
  16. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +5 -9
  17. data/lib/ruby_indexer/test/classes_and_modules_test.rb +75 -0
  18. data/lib/ruby_indexer/test/configuration_test.rb +32 -2
  19. data/lib/ruby_indexer/test/index_test.rb +21 -0
  20. data/lib/ruby_indexer/test/method_test.rb +2 -2
  21. data/lib/ruby_lsp/addon.rb +32 -67
  22. data/lib/ruby_lsp/base_server.rb +12 -11
  23. data/lib/ruby_lsp/client_capabilities.rb +4 -6
  24. data/lib/ruby_lsp/document.rb +21 -32
  25. data/lib/ruby_lsp/erb_document.rb +17 -27
  26. data/lib/ruby_lsp/global_state.rb +30 -32
  27. data/lib/ruby_lsp/internal.rb +6 -0
  28. data/lib/ruby_lsp/listeners/code_lens.rb +21 -39
  29. data/lib/ruby_lsp/listeners/completion.rb +34 -53
  30. data/lib/ruby_lsp/listeners/definition.rb +35 -49
  31. data/lib/ruby_lsp/listeners/document_highlight.rb +60 -69
  32. data/lib/ruby_lsp/listeners/document_link.rb +9 -19
  33. data/lib/ruby_lsp/listeners/document_symbol.rb +34 -48
  34. data/lib/ruby_lsp/listeners/folding_ranges.rb +31 -38
  35. data/lib/ruby_lsp/listeners/hover.rb +37 -47
  36. data/lib/ruby_lsp/listeners/inlay_hints.rb +3 -10
  37. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +29 -35
  38. data/lib/ruby_lsp/listeners/signature_help.rb +4 -23
  39. data/lib/ruby_lsp/listeners/spec_style.rb +199 -0
  40. data/lib/ruby_lsp/listeners/test_style.rb +270 -0
  41. data/lib/ruby_lsp/node_context.rb +8 -35
  42. data/lib/ruby_lsp/rbs_document.rb +7 -5
  43. data/lib/ruby_lsp/requests/code_action_resolve.rb +10 -10
  44. data/lib/ruby_lsp/requests/code_actions.rb +5 -14
  45. data/lib/ruby_lsp/requests/code_lens.rb +4 -13
  46. data/lib/ruby_lsp/requests/completion.rb +4 -15
  47. data/lib/ruby_lsp/requests/completion_resolve.rb +4 -4
  48. data/lib/ruby_lsp/requests/definition.rb +4 -12
  49. data/lib/ruby_lsp/requests/diagnostics.rb +6 -9
  50. data/lib/ruby_lsp/requests/discover_tests.rb +74 -0
  51. data/lib/ruby_lsp/requests/document_highlight.rb +3 -11
  52. data/lib/ruby_lsp/requests/document_link.rb +4 -13
  53. data/lib/ruby_lsp/requests/document_symbol.rb +4 -7
  54. data/lib/ruby_lsp/requests/folding_ranges.rb +4 -7
  55. data/lib/ruby_lsp/requests/formatting.rb +4 -7
  56. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
  57. data/lib/ruby_lsp/requests/hover.rb +6 -16
  58. data/lib/ruby_lsp/requests/inlay_hints.rb +4 -13
  59. data/lib/ruby_lsp/requests/on_type_formatting.rb +17 -24
  60. data/lib/ruby_lsp/requests/prepare_rename.rb +3 -8
  61. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +4 -13
  62. data/lib/ruby_lsp/requests/range_formatting.rb +3 -4
  63. data/lib/ruby_lsp/requests/references.rb +5 -35
  64. data/lib/ruby_lsp/requests/rename.rb +9 -35
  65. data/lib/ruby_lsp/requests/request.rb +5 -17
  66. data/lib/ruby_lsp/requests/selection_ranges.rb +3 -3
  67. data/lib/ruby_lsp/requests/semantic_highlighting.rb +6 -23
  68. data/lib/ruby_lsp/requests/show_syntax_tree.rb +4 -5
  69. data/lib/ruby_lsp/requests/signature_help.rb +6 -24
  70. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  71. data/lib/ruby_lsp/requests/support/common.rb +12 -47
  72. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -14
  73. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +7 -10
  74. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +9 -15
  75. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  76. data/lib/ruby_lsp/requests/support/sorbet.rb +1 -7
  77. data/lib/ruby_lsp/requests/support/source_uri.rb +5 -16
  78. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +7 -10
  79. data/lib/ruby_lsp/requests/support/test_item.rb +60 -0
  80. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +4 -5
  81. data/lib/ruby_lsp/requests/workspace_symbol.rb +3 -3
  82. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +4 -4
  83. data/lib/ruby_lsp/response_builders/document_symbol.rb +8 -11
  84. data/lib/ruby_lsp/response_builders/hover.rb +5 -5
  85. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  86. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +18 -40
  87. data/lib/ruby_lsp/response_builders/signature_help.rb +4 -5
  88. data/lib/ruby_lsp/response_builders/test_collection.rb +34 -0
  89. data/lib/ruby_lsp/ruby_document.rb +15 -40
  90. data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +106 -0
  91. data/lib/ruby_lsp/scope.rb +6 -10
  92. data/lib/ruby_lsp/server.rb +169 -72
  93. data/lib/ruby_lsp/setup_bundler.rb +25 -17
  94. data/lib/ruby_lsp/store.rb +12 -28
  95. data/lib/ruby_lsp/test_helper.rb +3 -12
  96. data/lib/ruby_lsp/test_reporter.rb +71 -0
  97. data/lib/ruby_lsp/test_unit_test_runner.rb +96 -0
  98. data/lib/ruby_lsp/type_inferrer.rb +9 -13
  99. data/lib/ruby_lsp/utils.rb +27 -65
  100. metadata +12 -3
@@ -27,7 +27,7 @@ module RubyLsp
27
27
 
28
28
  FOUR_HOURS = T.let(4 * 60 * 60, Integer)
29
29
 
30
- sig { params(project_path: String, options: T.untyped).void }
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
- sig { returns(T::Hash[String, String]) }
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
- sig { returns(T::Hash[String, T.untyped]) }
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
- sig { void }
150
+ #: -> void
151
151
  def write_custom_gemfile
152
152
  parts = [
153
153
  "# This custom gemfile is automatically generated by the Ruby LSP.",
@@ -158,7 +158,8 @@ module RubyLsp
158
158
  # If there's a top level Gemfile, we want to evaluate from the composed bundle. We get the source from the top
159
159
  # level Gemfile, so if there isn't one we need to add a default source
160
160
  if @gemfile&.exist? && @lockfile&.exist?
161
- parts << "eval_gemfile(File.expand_path(\"../#{@gemfile_name}\", __dir__))"
161
+ gemfile_path = @gemfile.relative_path_from(@custom_dir.realpath)
162
+ parts << "eval_gemfile(File.expand_path(\"#{gemfile_path}\", __dir__))"
162
163
  else
163
164
  parts.unshift('source "https://rubygems.org"')
164
165
  end
@@ -187,7 +188,7 @@ module RubyLsp
187
188
  @custom_gemfile.write(content) unless @custom_gemfile.exist? && @custom_gemfile.read == content
188
189
  end
189
190
 
190
- sig { returns([T::Hash[String, T.untyped], T.nilable(Gem::Version)]) }
191
+ #: -> [Hash[String, untyped], Gem::Version?]
191
192
  def load_dependencies
192
193
  return [{}, nil] unless @lockfile&.exist?
193
194
 
@@ -207,7 +208,7 @@ module RubyLsp
207
208
  [dependencies, lockfile_parser.bundler_version]
208
209
  end
209
210
 
210
- sig { params(bundle_gemfile: T.nilable(Pathname)).returns(T::Hash[String, String]) }
211
+ #: (?Pathname? bundle_gemfile) -> Hash[String, String]
211
212
  def run_bundle_install(bundle_gemfile = @gemfile)
212
213
  env = bundler_settings_as_env
213
214
  env["BUNDLE_GEMFILE"] = bundle_gemfile.to_s
@@ -258,7 +259,7 @@ module RubyLsp
258
259
  env
259
260
  end
260
261
 
261
- sig { params(env: T::Hash[String, String], force_install: T::Boolean).returns(T::Hash[String, String]) }
262
+ #: (Hash[String, String] env, ?force_install: bool) -> Hash[String, String]
262
263
  def run_bundle_install_directly(env, force_install: false)
263
264
  RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
264
265
 
@@ -287,7 +288,7 @@ module RubyLsp
287
288
  @retry ? env : run_bundle_install_directly(env, force_install: true)
288
289
  end
289
290
 
290
- sig { params(env: T::Hash[String, String]).returns(T::Hash[String, String]) }
291
+ #: (Hash[String, String] env) -> Hash[String, String]
291
292
  def run_bundle_install_through_command(env)
292
293
  # If `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) are already in the Gemfile, then we shouldn't try
293
294
  # to upgrade them or else we'll produce undesired source control changes. If the composed bundle was just created
@@ -344,7 +345,7 @@ module RubyLsp
344
345
  end
345
346
 
346
347
  # Gather all Bundler settings (global and local) and return them as a hash that can be used as the environment
347
- sig { returns(T::Hash[String, String]) }
348
+ #: -> Hash[String, String]
348
349
  def bundler_settings_as_env
349
350
  local_config_path = File.join(@project_path, ".bundle")
350
351
 
@@ -356,18 +357,25 @@ module RubyLsp
356
357
  Bundler::Settings.new
357
358
  end
358
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
+
359
364
  # Map all settings to their environment variable names with `key_for` and their values. For example, the if the
360
365
  # setting name `e` is `path` with a value of `vendor/bundle`, then it will return `"BUNDLE_PATH" =>
361
366
  # "vendor/bundle"`
362
- settings.all.to_h do |e|
363
- key = Bundler::Settings.key_for(e)
367
+ settings
368
+ .all
369
+ .reject { |setting| ignored_settings.include?(setting) }
370
+ .to_h do |e|
371
+ key = settings.key_for(e)
364
372
  value = Array(settings[e]).join(":").tr(" ", ":")
365
373
 
366
374
  [key, value]
367
375
  end
368
376
  end
369
377
 
370
- sig { void }
378
+ #: -> void
371
379
  def install_bundler_if_needed
372
380
  # Try to find the bundler version specified in the lockfile in installed gems. If not found, install it
373
381
  requirement = Gem::Requirement.new(@bundler_version.to_s)
@@ -376,7 +384,7 @@ module RubyLsp
376
384
  Gem.install("bundler", @bundler_version.to_s)
377
385
  end
378
386
 
379
- sig { returns(T::Boolean) }
387
+ #: -> bool
380
388
  def should_bundle_update?
381
389
  # If `ruby-lsp`, `ruby-lsp-rails` and `debug` are in the Gemfile, then we shouldn't try to upgrade them or else it
382
390
  # will produce version control changes
@@ -399,7 +407,7 @@ module RubyLsp
399
407
 
400
408
  # When a lockfile has remote references based on relative file paths, we need to ensure that they are pointing to
401
409
  # the correct place since after copying the relative path is no longer valid
402
- sig { void }
410
+ #: -> void
403
411
  def correct_relative_remote_paths
404
412
  content = @custom_lockfile.read
405
413
  content.gsub!(/remote: (.*)/) do |match|
@@ -421,7 +429,7 @@ module RubyLsp
421
429
  end
422
430
 
423
431
  # Detects if the project is a Rails app by looking if the superclass of the main class is `Rails::Application`
424
- sig { returns(T::Boolean) }
432
+ #: -> bool
425
433
  def rails_app?
426
434
  config = Pathname.new("config/application.rb").expand_path
427
435
  application_contents = config.read(external_encoding: Encoding::UTF_8) if config.exist?
@@ -430,7 +438,7 @@ module RubyLsp
430
438
  /class .* < (::)?Rails::Application/.match?(application_contents)
431
439
  end
432
440
 
433
- sig { void }
441
+ #: -> void
434
442
  def patch_thor_to_print_progress_to_stderr!
435
443
  return unless defined?(Bundler::Thor::Shell::Basic)
436
444
 
@@ -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
- sig { returns(T::Hash[Symbol, RequestConfig]) }
8
+ #: Hash[Symbol, RequestConfig]
11
9
  attr_accessor :features_configuration
12
10
 
13
- sig { returns(String) }
11
+ #: String
14
12
  attr_accessor :client_name
15
13
 
16
- sig { params(global_state: GlobalState).void }
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
- sig { params(uri: URI::Generic).returns(Document[T.untyped]) }
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
- sig do
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
- sig { params(uri: URI::Generic, edits: T::Array[T::Hash[Symbol, T.untyped]], version: Integer).void }
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
- sig { void }
74
+ #: -> void
84
75
  def clear
85
76
  @state.clear
86
77
  end
87
78
 
88
- sig { returns(T::Boolean) }
79
+ #: -> bool
89
80
  def empty?
90
81
  @state.empty?
91
82
  end
92
83
 
93
- sig { params(uri: URI::Generic).void }
84
+ #: (URI::Generic uri) -> void
94
85
  def delete(uri)
95
86
  @state.delete(uri.to_s)
96
87
  end
97
88
 
98
- sig { params(uri: URI::Generic).returns(T::Boolean) }
89
+ #: (URI::Generic uri) -> bool
99
90
  def key?(uri)
100
91
  @state.key?(uri.to_s)
101
92
  end
102
93
 
103
- sig { params(block: T.proc.params(uri: String, document: Document[T.untyped]).void).void }
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
- sig do
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
@@ -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
- sig do
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
- sig { params(server: RubyLsp::Server).returns(RubyLsp::Result) }
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
- extend T::Sig
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
- sig { params(node_context: NodeContext).returns(T.nilable(Type)) }
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
- sig { params(node: Prism::CallNode, node_context: NodeContext).returns(T.nilable(Type)) }
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
- sig { params(raw_receiver: String, nesting: T::Array[String]).returns(T.nilable(GuessedType)) }
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
- sig { params(node_context: NodeContext).returns(Type) }
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
- sig { params(node_context: NodeContext).returns(T.nilable(Type)) }
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
- extend T::Sig
172
-
173
- sig { returns(String) }
169
+ #: String
174
170
  attr_reader :name
175
171
 
176
- sig { params(name: String).void }
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
- sig { returns(Type) }
178
+ #: -> Type
183
179
  def attached
184
180
  Type.new(T.must(@name.split("::")[..-2]).join("::"))
185
181
  end