Skip to content

Commit 852c014

Browse files
authored
Prevent Minitest reporters from being mutated after LSP hooks (#3518)
1 parent 167189e commit 852c014

File tree

2 files changed

+26
-18
lines changed

2 files changed

+26
-18
lines changed

jekyll/test_explorer.markdown

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -126,27 +126,9 @@ ruby-lsp-test-exec bundle exec rspec spec/example_spec.rb
126126
When tests are running through any execution mode, we set the `RUBY_LSP_TEST_RUNNER` environment variable to allow
127127
users to customize behavior of their test suite if needed.
128128

129-
{: .important }
130-
The Ruby LSP uses a custom test reporter to be able to communicate between extension and server. Some gems that modify
131-
reporters may break this integration. The `RUBY_LSP_TEST_RUNNER` variable can be used to turn off these gems only when
132-
running under the Ruby LSP's integrations.
133-
134129
{: .important }
135130
Using coverage mode **does not require any extra dependencies or configuration** for collecting the coverage data. This is done automatically by the Ruby LSP through Ruby's built-in coverage API.
136131

137-
For example
138-
139-
```ruby
140-
# test/test_helper.rb
141-
142-
unless ENV["RUBY_LSP_TEST_RUNNER"]
143-
# Minitest reporters cannot be used when running through the Ruby LSP integrations as it breaks our custom reporter
144-
145-
require "minitest/reporters"
146-
Minitest::Reporters.use!(...)
147-
end
148-
```
149-
150132
Users can also differentiate between the mode of execution, which is the value of the `RUBY_LSP_TEST_RUNNER` variable:
151133

152134
```ruby

lib/ruby_lsp/test_reporters/minitest_reporter.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,30 @@ def record(result)
3030
end
3131
end
3232

33+
# This patch is here to prevent other gems from overriding or adding more Minitest reporters. Otherwise, they may
34+
# break the integration between the server and extension
35+
module PreventReporterOverridePatch
36+
@lsp_reporters = [] #: Array[Minitest::AbstractReporter]
37+
38+
class << self
39+
#: Array[Minitest::AbstractReporter]
40+
attr_accessor :lsp_reporters
41+
end
42+
43+
# Patch the writer to prevent replacing the entire array
44+
#: (untyped) -> void
45+
def reporters=(reporters)
46+
# Do nothing. We don't want other gems to override our reporter
47+
end
48+
49+
# Patch the reader to prevent appending more reporters. This method always returns a temporary copy of the real
50+
# reporters so that if any gem mutates it, it continues to return the original reporters
51+
#: -> Array[untyped]
52+
def reporters
53+
PreventReporterOverridePatch.lsp_reporters.dup
54+
end
55+
end
56+
3357
class MinitestReporter < Minitest::AbstractReporter
3458
class << self
3559
#: (Hash[untyped, untyped]) -> void
@@ -45,6 +69,8 @@ def minitest_plugin_init(_options)
4569

4670
# Add the JSON RPC reporter
4771
reporters << MinitestReporter.new
72+
PreventReporterOverridePatch.lsp_reporters = reporters
73+
Minitest.reporter.class.prepend(PreventReporterOverridePatch)
4874
end
4975
end
5076

0 commit comments

Comments
 (0)