ruby-lsp 0.23.14 → 0.23.16

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp-launcher +9 -1
  4. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +2 -2
  5. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +6 -3
  6. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +4 -2
  7. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +60 -30
  8. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +5 -4
  9. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +5 -1
  10. data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
  11. data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
  12. data/lib/ruby_indexer/test/configuration_test.rb +6 -4
  13. data/lib/ruby_indexer/test/constant_test.rb +34 -34
  14. data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
  15. data/lib/ruby_indexer/test/index_test.rb +139 -135
  16. data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
  17. data/lib/ruby_indexer/test/method_test.rb +118 -118
  18. data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
  19. data/lib/ruby_indexer/test/rbs_indexer_test.rb +64 -70
  20. data/lib/ruby_indexer/test/test_case.rb +2 -2
  21. data/lib/ruby_lsp/document.rb +6 -1
  22. data/lib/ruby_lsp/erb_document.rb +12 -4
  23. data/lib/ruby_lsp/global_state.rb +1 -1
  24. data/lib/ruby_lsp/listeners/code_lens.rb +3 -3
  25. data/lib/ruby_lsp/listeners/completion.rb +24 -11
  26. data/lib/ruby_lsp/listeners/definition.rb +1 -1
  27. data/lib/ruby_lsp/listeners/document_link.rb +3 -1
  28. data/lib/ruby_lsp/listeners/document_symbol.rb +3 -3
  29. data/lib/ruby_lsp/listeners/folding_ranges.rb +8 -4
  30. data/lib/ruby_lsp/listeners/hover.rb +2 -2
  31. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +12 -5
  32. data/lib/ruby_lsp/listeners/signature_help.rb +5 -1
  33. data/lib/ruby_lsp/listeners/spec_style.rb +1 -1
  34. data/lib/ruby_lsp/listeners/test_style.rb +8 -8
  35. data/lib/ruby_lsp/requests/code_action_resolve.rb +14 -15
  36. data/lib/ruby_lsp/requests/completion_resolve.rb +1 -1
  37. data/lib/ruby_lsp/requests/hover.rb +2 -2
  38. data/lib/ruby_lsp/requests/on_type_formatting.rb +4 -2
  39. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +1 -2
  40. data/lib/ruby_lsp/requests/references.rb +2 -1
  41. data/lib/ruby_lsp/requests/rename.rb +8 -5
  42. data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
  43. data/lib/ruby_lsp/requests/semantic_highlighting.rb +4 -4
  44. data/lib/ruby_lsp/requests/show_syntax_tree.rb +2 -2
  45. data/lib/ruby_lsp/requests/support/common.rb +3 -1
  46. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
  47. data/lib/ruby_lsp/requests/support/source_uri.rb +5 -3
  48. data/lib/ruby_lsp/response_builders/document_symbol.rb +3 -2
  49. data/lib/ruby_lsp/response_builders/hover.rb +1 -1
  50. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +1 -1
  51. data/lib/ruby_lsp/ruby_document.rb +2 -2
  52. data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
  53. data/lib/ruby_lsp/server.rb +14 -5
  54. data/lib/ruby_lsp/setup_bundler.rb +7 -3
  55. data/lib/ruby_lsp/static_docs.rb +8 -1
  56. data/lib/ruby_lsp/store.rb +3 -2
  57. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +164 -0
  58. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
  59. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
  60. data/lib/ruby_lsp/type_inferrer.rb +4 -1
  61. data/lib/ruby_lsp/utils.rb +12 -2
  62. metadata +6 -6
  63. data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +0 -109
  64. data/lib/ruby_lsp/test_reporter.rb +0 -207
  65. data/lib/ruby_lsp/test_unit_test_runner.rb +0 -98
@@ -0,0 +1,164 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "json"
5
+ require "socket"
6
+ require "singleton"
7
+
8
+ module RubyLsp
9
+ class LspReporter
10
+ include Singleton
11
+
12
+ #: -> void
13
+ def initialize
14
+ port = ENV["RUBY_LSP_REPORTER_PORT"]
15
+ @io = if port
16
+ TCPSocket.new("localhost", port)
17
+ else
18
+ # For tests that don't spawn the TCP server
19
+ require "stringio"
20
+ StringIO.new
21
+ end #: IO | StringIO
22
+ end
23
+
24
+ #: -> void
25
+ def shutdown
26
+ # When running in coverage mode, we don't want to inform the extension that we finished immediately after running
27
+ # tests. We only do it after we finish processing coverage results, by invoking `internal_shutdown`
28
+ return if ENV["RUBY_LSP_TEST_RUNNER"] == "coverage"
29
+
30
+ internal_shutdown
31
+ end
32
+
33
+ # This method is intended to be used by the RubyLsp::LspReporter class itself only. If you're writing a custom test
34
+ # reporter, use `shutdown` instead
35
+ #: -> void
36
+ def internal_shutdown
37
+ send_message("finish")
38
+ @io.close
39
+ end
40
+
41
+ #: (id: String, uri: URI::Generic) -> void
42
+ def start_test(id:, uri:)
43
+ send_message("start", id: id, uri: uri.to_s)
44
+ end
45
+
46
+ #: (id: String, uri: URI::Generic) -> void
47
+ def record_pass(id:, uri:)
48
+ send_message("pass", id: id, uri: uri.to_s)
49
+ end
50
+
51
+ #: (id: String, message: String, uri: URI::Generic) -> void
52
+ def record_fail(id:, message:, uri:)
53
+ send_message("fail", id: id, message: message, uri: uri.to_s)
54
+ end
55
+
56
+ #: (id: String, uri: URI::Generic) -> void
57
+ def record_skip(id:, uri:)
58
+ send_message("skip", id: id, uri: uri.to_s)
59
+ end
60
+
61
+ #: (id: String, message: String?, uri: URI::Generic) -> void
62
+ def record_error(id:, message:, uri:)
63
+ send_message("error", id: id, message: message, uri: uri.to_s)
64
+ end
65
+
66
+ # Gather the results returned by Coverage.result and format like the VS Code test explorer expects
67
+ #
68
+ # Coverage result format:
69
+ #
70
+ # Lines are reported in order as an array where each number is the number of times it was executed. For example,
71
+ # the following says that line 0 was executed 1 time and line 1 executed 3 times: [1, 3].
72
+ # Nil values represent lines for which coverage is not available, like empty lines, comments or keywords like
73
+ # `else`
74
+ #
75
+ # Branches are a hash containing the name of the branch and the location where it is found in tuples with the
76
+ # following elements: [NAME, ID, START_LINE, START_COLUMN, END_LINE, END_COLUMN] as the keys and the value is the
77
+ # number of times it was executed
78
+ #
79
+ # Methods are a similar hash [ClassName, :method_name, START_LINE, START_COLUMN, END_LINE, END_COLUMN] => NUMBER
80
+ # OF EXECUTIONS
81
+ #
82
+ # Example:
83
+ # {
84
+ # "file_path" => {
85
+ # "lines" => [1, 2, 3, nil],
86
+ # "branches" => {
87
+ # ["&.", 0, 6, 21, 6, 65] => { [:then, 1, 6, 21, 6, 65] => 0, [:else, 5, 7, 0, 7, 87] => 1 }
88
+ # },
89
+ # "methods" => {
90
+ # ["Foo", :bar, 6, 21, 6, 65] => 0
91
+ # }
92
+ # }
93
+ #: -> Hash[String, StatementCoverage]
94
+ def gather_coverage_results
95
+ # Ignore coverage results inside dependencies
96
+ bundle_path = Bundler.bundle_path.to_s
97
+ default_gems_path = File.dirname(RbConfig::CONFIG["rubylibdir"])
98
+
99
+ result = Coverage.result.reject do |file_path, _coverage_info|
100
+ file_path.start_with?(bundle_path, default_gems_path, "eval")
101
+ end
102
+
103
+ result.to_h do |file_path, coverage_info|
104
+ # Format the branch coverage information as VS Code expects it and then group it based on the start line of
105
+ # the conditional that causes the branching. We need to match each line coverage data with the branches that
106
+ # spawn from that line
107
+ branch_by_line = coverage_info[:branches]
108
+ .flat_map do |branch, data|
109
+ branch_name, _branch_id, branch_start_line, _branch_start_col, _branch_end_line, _branch_end_col = branch
110
+
111
+ data.map do |then_or_else, execution_count|
112
+ name, _id, start_line, start_column, end_line, end_column = then_or_else
113
+
114
+ {
115
+ groupingLine: branch_start_line,
116
+ executed: execution_count,
117
+ location: {
118
+ start: { line: start_line, character: start_column },
119
+ end: { line: end_line, character: end_column },
120
+ },
121
+ label: "#{branch_name} #{name}",
122
+ }
123
+ end
124
+ end
125
+ .group_by { |branch| branch[:groupingLine] }
126
+
127
+ # Format the line coverage information, gathering any branch coverage data associated with that line
128
+ data = coverage_info[:lines].filter_map.with_index do |execution_count, line_index|
129
+ next if execution_count.nil?
130
+
131
+ {
132
+ executed: execution_count,
133
+ location: { line: line_index, character: 0 },
134
+ branches: branch_by_line[line_index] || [],
135
+ }
136
+ end
137
+
138
+ # The expected format is URI => { executed: number_of_times_executed, location: { ... }, branches: [ ... ] }
139
+ [URI::Generic.from_path(path: File.expand_path(file_path)).to_s, data]
140
+ end
141
+ end
142
+
143
+ private
144
+
145
+ #: (method_name: String?, params: untyped) -> void
146
+ def send_message(method_name, **params)
147
+ json_message = { method: method_name, params: params }.to_json
148
+ @io.write("Content-Length: #{json_message.bytesize}\r\n\r\n#{json_message}")
149
+ end
150
+ end
151
+ end
152
+
153
+ if ENV["RUBY_LSP_TEST_RUNNER"] == "coverage"
154
+ # Auto start coverage when running tests under that profile. This avoids the user from having to configure coverage
155
+ # manually for their project or adding extra dependencies
156
+ require "coverage"
157
+ Coverage.start(:all)
158
+
159
+ at_exit do
160
+ coverage_results = RubyLsp::LspReporter.instance.gather_coverage_results
161
+ File.write(File.join(".ruby-lsp", "coverage_result.json"), coverage_results.to_json)
162
+ RubyLsp::LspReporter.instance.internal_shutdown
163
+ end
164
+ end
@@ -0,0 +1,105 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require "minitest"
6
+ rescue LoadError
7
+ return
8
+ end
9
+
10
+ require_relative "lsp_reporter"
11
+ require "ruby_indexer/lib/ruby_indexer/uri"
12
+
13
+ module RubyLsp
14
+ # An override of the default progress reporter in Minitest to add color to the output
15
+ class ProgressReporterWithColor < Minitest::ProgressReporter
16
+ #: (Minitest::Result) -> void
17
+ def record(result)
18
+ color = if result.error?
19
+ "\e[31m" # red
20
+ elsif result.passed?
21
+ "\e[32m" # green
22
+ elsif result.skipped?
23
+ "\e[33m" # yellow
24
+ elsif result.failure
25
+ "\e[31m" # red
26
+ else
27
+ "\e[0m" # no color
28
+ end
29
+
30
+ io.print("#{color}#{result.result_code}\e[0m") # Reset color after printing
31
+ end
32
+ end
33
+
34
+ class MinitestReporter < Minitest::AbstractReporter
35
+ class << self
36
+ #: (Hash[untyped, untyped]) -> void
37
+ def minitest_plugin_init(_options)
38
+ # Remove the original progress reporter, so that we replace it with our own. We only do this if no other
39
+ # reporters were included by the application itself to avoid double reporting
40
+ reporters = Minitest.reporter.reporters
41
+
42
+ if reporters.all? { |r| r.is_a?(Minitest::ProgressReporter) || r.is_a?(Minitest::SummaryReporter) }
43
+ reporters.delete_if { |r| r.is_a?(Minitest::ProgressReporter) }
44
+ reporters << ProgressReporterWithColor.new
45
+ end
46
+
47
+ # Add the JSON RPC reporter
48
+ reporters << MinitestReporter.new
49
+ end
50
+ end
51
+
52
+ #: (singleton(Minitest::Test) test_class, String method_name) -> void
53
+ def prerecord(test_class, method_name)
54
+ uri = uri_from_test_class(test_class, method_name)
55
+ return unless uri
56
+
57
+ LspReporter.instance.start_test(id: "#{test_class.name}##{method_name}", uri: uri)
58
+ end
59
+
60
+ #: (Minitest::Result result) -> void
61
+ def record(result)
62
+ id = "#{result.klass}##{result.name}"
63
+ uri = uri_from_result(result)
64
+
65
+ if result.error?
66
+ message = result.failures.first.message
67
+ LspReporter.instance.record_error(id: id, uri: uri, message: message)
68
+ elsif result.passed?
69
+ LspReporter.instance.record_pass(id: id, uri: uri)
70
+ elsif result.skipped?
71
+ LspReporter.instance.record_skip(id: id, uri: uri)
72
+ elsif result.failure
73
+ message = result.failure.message
74
+ LspReporter.instance.record_fail(id: id, uri: uri, message: message)
75
+ end
76
+ end
77
+
78
+ #: -> void
79
+ def report
80
+ LspReporter.instance.shutdown
81
+ end
82
+
83
+ private
84
+
85
+ #: (Minitest::Result result) -> URI::Generic
86
+ def uri_from_result(result)
87
+ file = result.source_location[0]
88
+ absolute_path = File.expand_path(file, Dir.pwd)
89
+ URI::Generic.from_path(path: absolute_path)
90
+ end
91
+
92
+ #: (singleton(Minitest::Test) test_class, String method_name) -> URI::Generic?
93
+ def uri_from_test_class(test_class, method_name)
94
+ file, _line = test_class.instance_method(method_name).source_location
95
+ return unless file
96
+
97
+ return if file.start_with?("(eval at ") # test is dynamically defined
98
+
99
+ absolute_path = File.expand_path(file, Dir.pwd)
100
+ URI::Generic.from_path(path: absolute_path)
101
+ end
102
+ end
103
+ end
104
+
105
+ Minitest.extensions << RubyLsp::MinitestReporter
@@ -0,0 +1,94 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require "test/unit"
6
+ require "test/unit/ui/testrunner"
7
+ require "test/unit/ui/console/testrunner"
8
+ rescue LoadError
9
+ return
10
+ end
11
+
12
+ require_relative "lsp_reporter"
13
+ require "ruby_indexer/lib/ruby_indexer/uri"
14
+
15
+ module RubyLsp
16
+ class TestUnitReporter < Test::Unit::UI::Console::TestRunner
17
+ def initialize(suite, options = {})
18
+ super
19
+ @current_uri = nil #: URI::Generic?
20
+ @current_test_id = nil #: String?
21
+ end
22
+
23
+ private
24
+
25
+ #: (::Test::Unit::TestCase test) -> void
26
+ def test_started(test)
27
+ super
28
+
29
+ current_test = test
30
+ @current_uri = uri_for_test(current_test)
31
+ return unless @current_uri
32
+
33
+ @current_test_id = "#{current_test.class.name}##{current_test.method_name}"
34
+ LspReporter.instance.start_test(id: @current_test_id, uri: @current_uri)
35
+ end
36
+
37
+ #: (::Test::Unit::TestCase test) -> void
38
+ def test_finished(test)
39
+ super
40
+ return unless test.passed? && @current_uri && @current_test_id
41
+
42
+ LspReporter.instance.record_pass(id: @current_test_id, uri: @current_uri)
43
+ end
44
+
45
+ #: (::Test::Unit::Failure | ::Test::Unit::Error | ::Test::Unit::Pending result) -> void
46
+ def add_fault(result)
47
+ super
48
+ return unless @current_uri && @current_test_id
49
+
50
+ case result
51
+ when ::Test::Unit::Failure
52
+ LspReporter.instance.record_fail(id: @current_test_id, message: result.message, uri: @current_uri)
53
+ when ::Test::Unit::Error
54
+ LspReporter.instance.record_error(id: @current_test_id, message: result.message, uri: @current_uri)
55
+ when ::Test::Unit::Pending
56
+ LspReporter.instance.record_skip(id: @current_test_id, uri: @current_uri)
57
+ end
58
+ end
59
+
60
+ #: (Float) -> void
61
+ def finished(elapsed_time)
62
+ LspReporter.instance.shutdown
63
+ end
64
+
65
+ #: (::Test::Unit::TestCase test) -> URI::Generic?
66
+ def uri_for_test(test)
67
+ location = test.method(test.method_name).source_location
68
+ return unless location
69
+
70
+ file, _line = location
71
+ return if file.start_with?("(eval at ")
72
+
73
+ absolute_path = File.expand_path(file, Dir.pwd)
74
+ URI::Generic.from_path(path: absolute_path)
75
+ end
76
+
77
+ #: -> void
78
+ def attach_to_mediator
79
+ # Events we care about
80
+ @mediator.add_listener(Test::Unit::TestResult::FAULT, &method(:add_fault))
81
+ @mediator.add_listener(Test::Unit::TestCase::STARTED_OBJECT, &method(:test_started))
82
+ @mediator.add_listener(Test::Unit::TestCase::FINISHED_OBJECT, &method(:test_finished))
83
+ @mediator.add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED, &method(:finished))
84
+
85
+ # Other events needed for the console test runner to print
86
+ @mediator.add_listener(Test::Unit::UI::TestRunnerMediator::STARTED, &method(:started))
87
+ @mediator.add_listener(Test::Unit::TestSuite::STARTED_OBJECT, &method(:test_suite_started))
88
+ @mediator.add_listener(Test::Unit::TestSuite::FINISHED_OBJECT, &method(:test_suite_finished))
89
+ end
90
+ end
91
+ end
92
+
93
+ Test::Unit::AutoRunner.register_runner(:ruby_lsp) { |_auto_runner| RubyLsp::TestUnitReporter }
94
+ Test::Unit::AutoRunner.default_runner = :ruby_lsp
@@ -177,7 +177,10 @@ module RubyLsp
177
177
  # Returns the attached version of this type by removing the `<Class:...>` part from its name
178
178
  #: -> Type
179
179
  def attached
180
- Type.new(T.must(@name.split("::")[..-2]).join("::"))
180
+ Type.new(
181
+ @name.split("::")[..-2] #: as !nil
182
+ .join("::"),
183
+ )
181
184
  end
182
185
  end
183
186
 
@@ -137,7 +137,12 @@ module RubyLsp
137
137
  #: -> Hash[Symbol, untyped]
138
138
  def to_hash
139
139
  hash = { method: @method }
140
- hash[:params] = T.unsafe(@params).to_hash if @params
140
+
141
+ if @params
142
+ hash[:params] = @params #: as untyped
143
+ .to_hash
144
+ end
145
+
141
146
  hash
142
147
  end
143
148
  end
@@ -181,7 +186,12 @@ module RubyLsp
181
186
  #: -> Hash[Symbol, untyped]
182
187
  def to_hash
183
188
  hash = { id: @id, method: @method }
184
- hash[:params] = T.unsafe(@params).to_hash if @params
189
+
190
+ if @params
191
+ hash[:params] = @params #: as untyped
192
+ .to_hash
193
+ end
194
+
185
195
  hash
186
196
  end
187
197
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.14
4
+ version: 0.23.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: language_server-protocol
@@ -194,7 +194,6 @@ files:
194
194
  - lib/ruby_lsp/response_builders/signature_help.rb
195
195
  - lib/ruby_lsp/response_builders/test_collection.rb
196
196
  - lib/ruby_lsp/ruby_document.rb
197
- - lib/ruby_lsp/ruby_lsp_reporter_plugin.rb
198
197
  - lib/ruby_lsp/scope.rb
199
198
  - lib/ruby_lsp/scripts/compose_bundle.rb
200
199
  - lib/ruby_lsp/scripts/compose_bundle_windows.rb
@@ -203,8 +202,9 @@ files:
203
202
  - lib/ruby_lsp/static_docs.rb
204
203
  - lib/ruby_lsp/store.rb
205
204
  - lib/ruby_lsp/test_helper.rb
206
- - lib/ruby_lsp/test_reporter.rb
207
- - lib/ruby_lsp/test_unit_test_runner.rb
205
+ - lib/ruby_lsp/test_reporters/lsp_reporter.rb
206
+ - lib/ruby_lsp/test_reporters/minitest_reporter.rb
207
+ - lib/ruby_lsp/test_reporters/test_unit_reporter.rb
208
208
  - lib/ruby_lsp/type_inferrer.rb
209
209
  - lib/ruby_lsp/utils.rb
210
210
  - static_docs/yield.md
@@ -228,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
228
228
  - !ruby/object:Gem::Version
229
229
  version: '0'
230
230
  requirements: []
231
- rubygems_version: 3.6.6
231
+ rubygems_version: 3.6.8
232
232
  specification_version: 4
233
233
  summary: An opinionated language server for Ruby
234
234
  test_files: []
@@ -1,109 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- begin
5
- require "minitest"
6
- rescue LoadError
7
- return
8
- end
9
-
10
- require_relative "test_reporter"
11
- require "ruby_indexer/lib/ruby_indexer/uri"
12
-
13
- module Minitest
14
- module Reporters
15
- class RubyLspReporter < ::Minitest::AbstractReporter
16
- class << self
17
- #: (Hash[untyped, untyped]) -> void
18
- def minitest_plugin_init(_options)
19
- Minitest.reporter.reporters << RubyLspReporter.new
20
- end
21
- end
22
-
23
- #: (singleton(Minitest::Test) test_class, String method_name) -> void
24
- def prerecord(test_class, method_name)
25
- uri = uri_from_test_class(test_class, method_name)
26
- return unless uri
27
-
28
- RubyLsp::TestReporter.start_test(
29
- id: "#{test_class.name}##{method_name}",
30
- uri: uri,
31
- )
32
- end
33
-
34
- #: (Minitest::Result result) -> void
35
- def record(result)
36
- if result.error?
37
- record_error(result)
38
- elsif result.passed?
39
- record_pass(result)
40
- elsif result.skipped?
41
- record_skip(result)
42
- elsif result.failure
43
- record_fail(result)
44
- end
45
- end
46
-
47
- private
48
-
49
- #: (Minitest::Result result) -> void
50
- def record_pass(result)
51
- RubyLsp::TestReporter.record_pass(
52
- id: id_from_result(result),
53
- uri: uri_from_result(result),
54
- )
55
- end
56
-
57
- #: (Minitest::Result result) -> void
58
- def record_skip(result)
59
- RubyLsp::TestReporter.record_skip(
60
- id: id_from_result(result),
61
- uri: uri_from_result(result),
62
- )
63
- end
64
-
65
- #: (Minitest::Result result) -> void
66
- def record_fail(result)
67
- RubyLsp::TestReporter.record_fail(
68
- id: id_from_result(result),
69
- message: result.failure.message,
70
- uri: uri_from_result(result),
71
- )
72
- end
73
-
74
- #: (Minitest::Result result) -> void
75
- def record_error(result)
76
- RubyLsp::TestReporter.record_error(
77
- id: id_from_result(result),
78
- uri: uri_from_result(result),
79
- message: result.failures.first.message,
80
- )
81
- end
82
-
83
- #: (Minitest::Result result) -> String
84
- def id_from_result(result)
85
- "#{result.klass}##{result.name}"
86
- end
87
-
88
- #: (Minitest::Result result) -> URI::Generic
89
- def uri_from_result(result)
90
- file = result.source_location[0]
91
- absolute_path = File.expand_path(file, Dir.pwd)
92
- URI::Generic.from_path(path: absolute_path)
93
- end
94
-
95
- #: (singleton(Minitest::Test) test_class, String method_name) -> URI::Generic?
96
- def uri_from_test_class(test_class, method_name)
97
- file, _line = test_class.instance_method(method_name).source_location
98
- return unless file
99
-
100
- return if file.start_with?("(eval at ") # test is dynamically defined
101
-
102
- absolute_path = File.expand_path(file, Dir.pwd)
103
- URI::Generic.from_path(path: absolute_path)
104
- end
105
- end
106
- end
107
- end
108
-
109
- Minitest.extensions << Minitest::Reporters::RubyLspReporter