simplecov 1.1.1 → 1.2.0

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 (194) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +148 -5
  3. data/exe/simplecov +0 -3
  4. data/lib/minitest/simplecov_plugin.rb +12 -9
  5. data/lib/simplecov/atomic_file.rb +16 -19
  6. data/lib/simplecov/autostart.rb +5 -7
  7. data/lib/simplecov/baseline/parser.rb +58 -0
  8. data/lib/simplecov/baseline.rb +170 -0
  9. data/lib/simplecov/cli/affected/changed_files.rb +57 -0
  10. data/lib/simplecov/cli/affected/selection.rb +117 -0
  11. data/lib/simplecov/cli/affected.rb +148 -0
  12. data/lib/simplecov/cli/badge/svg.rb +70 -0
  13. data/lib/simplecov/cli/badge.rb +62 -0
  14. data/lib/simplecov/cli/clean.rb +23 -24
  15. data/lib/simplecov/cli/command_helpers.rb +55 -19
  16. data/lib/simplecov/cli/completions/scripts.rb +114 -0
  17. data/lib/simplecov/cli/completions.rb +83 -0
  18. data/lib/simplecov/cli/coverage.rb +25 -28
  19. data/lib/simplecov/cli/coverage_file.rb +58 -14
  20. data/lib/simplecov/cli/dead_code/output.rb +100 -0
  21. data/lib/simplecov/cli/dead_code.rb +139 -0
  22. data/lib/simplecov/cli/diff/output.rb +45 -0
  23. data/lib/simplecov/cli/diff.rb +35 -67
  24. data/lib/simplecov/cli/dotfile.rb +83 -38
  25. data/lib/simplecov/cli/git.rb +41 -0
  26. data/lib/simplecov/cli/history/output.rb +135 -0
  27. data/lib/simplecov/cli/history.rb +67 -0
  28. data/lib/simplecov/cli/merge.rb +34 -39
  29. data/lib/simplecov/cli/open.rb +12 -15
  30. data/lib/simplecov/cli/patch/changed_lines.rb +149 -0
  31. data/lib/simplecov/cli/patch/output.rb +135 -0
  32. data/lib/simplecov/cli/patch.rb +169 -0
  33. data/lib/simplecov/cli/ratchet/output.rb +44 -0
  34. data/lib/simplecov/cli/ratchet.rb +83 -0
  35. data/lib/simplecov/cli/report.rb +18 -24
  36. data/lib/simplecov/cli/run.rb +8 -9
  37. data/lib/simplecov/cli/serve/report_preparer.rb +7 -6
  38. data/lib/simplecov/cli/serve/static_file_handler.rb +62 -56
  39. data/lib/simplecov/cli/serve.rb +27 -24
  40. data/lib/simplecov/cli/show/annotator.rb +87 -0
  41. data/lib/simplecov/cli/show/sweep.rb +36 -0
  42. data/lib/simplecov/cli/show.rb +133 -0
  43. data/lib/simplecov/cli/status/facts.rb +87 -0
  44. data/lib/simplecov/cli/status.rb +93 -0
  45. data/lib/simplecov/cli/tests/redundancy.rb +78 -0
  46. data/lib/simplecov/cli/tests.rb +148 -0
  47. data/lib/simplecov/cli/uncovered/misses.rb +37 -0
  48. data/lib/simplecov/cli/uncovered.rb +70 -32
  49. data/lib/simplecov/cli/usage.rb +152 -0
  50. data/lib/simplecov/cli/watch/live_report.rb +73 -0
  51. data/lib/simplecov/cli/watch/narrator.rb +55 -0
  52. data/lib/simplecov/cli/watch/poller.rb +45 -0
  53. data/lib/simplecov/cli/watch/session.rb +134 -0
  54. data/lib/simplecov/cli/watch/test_plan.rb +43 -0
  55. data/lib/simplecov/cli/watch.rb +85 -0
  56. data/lib/simplecov/cli.rb +43 -92
  57. data/lib/simplecov/color.rb +19 -37
  58. data/lib/simplecov/combine/branches_combiner.rb +7 -31
  59. data/lib/simplecov/combine/coverage_accumulator.rb +49 -142
  60. data/lib/simplecov/combine/identity_interner.rb +10 -13
  61. data/lib/simplecov/combine/interned_counts.rb +7 -9
  62. data/lib/simplecov/combine/lines_combiner.rb +20 -44
  63. data/lib/simplecov/combine/methods_combiner.rb +9 -35
  64. data/lib/simplecov/combine/results_combiner.rb +4 -21
  65. data/lib/simplecov/combine.rb +0 -6
  66. data/lib/simplecov/command_guesser.rb +20 -34
  67. data/lib/simplecov/configuration/baseline.rb +31 -0
  68. data/lib/simplecov/configuration/coverage.rb +91 -79
  69. data/lib/simplecov/configuration/coverage_criteria.rb +43 -54
  70. data/lib/simplecov/configuration/deprecations.rb +21 -0
  71. data/lib/simplecov/configuration/eval_coverage.rb +6 -10
  72. data/lib/simplecov/configuration/filters.rb +40 -73
  73. data/lib/simplecov/configuration/formatting.rb +74 -83
  74. data/lib/simplecov/configuration/groups.rb +19 -13
  75. data/lib/simplecov/configuration/history.rb +44 -0
  76. data/lib/simplecov/configuration/ignored_entries.rb +31 -22
  77. data/lib/simplecov/configuration/merging.rb +94 -62
  78. data/lib/simplecov/configuration/missed_caps.rb +51 -0
  79. data/lib/simplecov/configuration/production.rb +23 -0
  80. data/lib/simplecov/configuration/test_tracking.rb +48 -0
  81. data/lib/simplecov/configuration/thresholds.rb +33 -62
  82. data/lib/simplecov/configuration/view_coverage.rb +38 -0
  83. data/lib/simplecov/configuration.rb +70 -76
  84. data/lib/simplecov/configuration_error.rb +5 -0
  85. data/lib/simplecov/context_map/union.rb +81 -0
  86. data/lib/simplecov/context_map.rb +187 -0
  87. data/lib/simplecov/coverage_json.rb +2 -5
  88. data/lib/simplecov/coverage_statistics.rb +14 -24
  89. data/lib/simplecov/coverage_violations.rb +157 -64
  90. data/lib/simplecov/current_run.rb +61 -0
  91. data/lib/simplecov/defaults.rb +4 -23
  92. data/lib/simplecov/deprecation.rb +45 -27
  93. data/lib/simplecov/directive.rb +46 -62
  94. data/lib/simplecov/exit_codes/baseline_check.rb +46 -0
  95. data/lib/simplecov/exit_codes/check.rb +17 -11
  96. data/lib/simplecov/exit_codes/exit_code_handling.rb +21 -8
  97. data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +7 -10
  98. data/lib/simplecov/exit_codes/maximum_missed_check.rb +26 -0
  99. data/lib/simplecov/exit_codes/maximum_missed_per_file_check.rb +34 -0
  100. data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +7 -12
  101. data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +11 -10
  102. data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +7 -9
  103. data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +16 -17
  104. data/lib/simplecov/exit_codes.rb +16 -10
  105. data/lib/simplecov/exit_handling.rb +94 -59
  106. data/lib/simplecov/file_list.rb +20 -51
  107. data/lib/simplecov/filter.rb +43 -66
  108. data/lib/simplecov/formatter/base.rb +37 -55
  109. data/lib/simplecov/formatter/baseline_formatter.rb +98 -0
  110. data/lib/simplecov/formatter/coverage_json_writer.rb +29 -31
  111. data/lib/simplecov/formatter/html_formatter/public/index.html +15 -9
  112. data/lib/simplecov/formatter/html_formatter/viewer_data_validator.rb +74 -17
  113. data/lib/simplecov/formatter/html_formatter.rb +24 -41
  114. data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +50 -16
  115. data/lib/simplecov/formatter/json_formatter/production_section_formatter.rb +48 -0
  116. data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +43 -29
  117. data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +14 -10
  118. data/lib/simplecov/formatter/json_formatter.rb +7 -13
  119. data/lib/simplecov/formatter/multi_formatter.rb +5 -11
  120. data/lib/simplecov/formatter/simple_formatter.rb +2 -8
  121. data/lib/simplecov/formatter.rb +14 -10
  122. data/lib/simplecov/group_names.rb +13 -12
  123. data/lib/simplecov/history.rb +115 -0
  124. data/lib/simplecov/last_run.rb +6 -9
  125. data/lib/simplecov/lines_classifier.rb +31 -16
  126. data/lib/simplecov/load_global_config.rb +7 -7
  127. data/lib/simplecov/parallel_adapters/base.rb +13 -41
  128. data/lib/simplecov/parallel_adapters/generic.rb +7 -19
  129. data/lib/simplecov/parallel_adapters/parallel_tests.rb +21 -42
  130. data/lib/simplecov/parallel_adapters.rb +24 -55
  131. data/lib/simplecov/parallel_coordination.rb +39 -49
  132. data/lib/simplecov/parallel_result_merger/worker_payload.rb +33 -0
  133. data/lib/simplecov/parallel_result_merger.rb +67 -126
  134. data/lib/simplecov/process.rb +14 -32
  135. data/lib/simplecov/production/error.rb +11 -0
  136. data/lib/simplecov/production/file_sink.rb +130 -0
  137. data/lib/simplecov/production.rb +249 -0
  138. data/lib/simplecov/profiles/rails.rb +1 -12
  139. data/lib/simplecov/profiles/root_filter.rb +0 -4
  140. data/lib/simplecov/profiles/strict.rb +9 -19
  141. data/lib/simplecov/profiles.rb +11 -33
  142. data/lib/simplecov/report_deferral.rb +11 -15
  143. data/lib/simplecov/report_stamp.rb +6 -9
  144. data/lib/simplecov/result/filter_config.rb +19 -0
  145. data/lib/simplecov/result/missing_source_files_reporter.rb +8 -9
  146. data/lib/simplecov/result/serialization.rb +43 -0
  147. data/lib/simplecov/result/source_file_builder.rb +7 -12
  148. data/lib/simplecov/result.rb +68 -117
  149. data/lib/simplecov/result_adapter.rb +56 -68
  150. data/lib/simplecov/result_merger/contexts.rb +22 -0
  151. data/lib/simplecov/result_merger/legacy_format_adapter.rb +4 -8
  152. data/lib/simplecov/result_merger/resultset_file.rb +20 -27
  153. data/lib/simplecov/result_merger/resultset_run_identity.rb +23 -25
  154. data/lib/simplecov/result_merger/resultset_store.rb +23 -14
  155. data/lib/simplecov/result_merger/unloaded_files.rb +24 -32
  156. data/lib/simplecov/result_merger.rb +59 -58
  157. data/lib/simplecov/result_processing.rb +74 -119
  158. data/lib/simplecov/run_identity.rb +16 -18
  159. data/lib/simplecov/simulate_coverage.rb +34 -50
  160. data/lib/simplecov/source_file/branch.rb +8 -33
  161. data/lib/simplecov/source_file/branch_builder.rb +28 -47
  162. data/lib/simplecov/source_file/builder_context.rb +6 -13
  163. data/lib/simplecov/source_file/line.rb +13 -33
  164. data/lib/simplecov/source_file/line_builder.rb +9 -15
  165. data/lib/simplecov/source_file/method.rb +3 -7
  166. data/lib/simplecov/source_file/method_builder.rb +6 -15
  167. data/lib/simplecov/source_file/ruby_data_parser.rb +59 -66
  168. data/lib/simplecov/source_file/skip_chunks.rb +19 -28
  169. data/lib/simplecov/source_file/source_loader.rb +45 -35
  170. data/lib/simplecov/source_file/statistics.rb +10 -9
  171. data/lib/simplecov/source_file.rb +21 -51
  172. data/lib/simplecov/static_coverage_extractor/condition_folding.rb +63 -114
  173. data/lib/simplecov/static_coverage_extractor/location_conventions.rb +76 -121
  174. data/lib/simplecov/static_coverage_extractor/method_collector.rb +11 -24
  175. data/lib/simplecov/static_coverage_extractor/prism_compat.rb +15 -24
  176. data/lib/simplecov/static_coverage_extractor/value_position.rb +25 -38
  177. data/lib/simplecov/static_coverage_extractor/visitor.rb +47 -64
  178. data/lib/simplecov/static_coverage_extractor.rb +46 -62
  179. data/lib/simplecov/test_tracker/accessors.rb +34 -0
  180. data/lib/simplecov/test_tracker/constant_watch.rb +49 -0
  181. data/lib/simplecov/test_tracker/delta.rb +69 -0
  182. data/lib/simplecov/test_tracker/framework_hooks.rb +130 -0
  183. data/lib/simplecov/test_tracker.rb +162 -0
  184. data/lib/simplecov/unloaded_file_injector.rb +18 -31
  185. data/lib/simplecov/useless_results_remover.rb +7 -6
  186. data/lib/simplecov/version.rb +1 -1
  187. data/lib/simplecov/view_coverage/template_compiler.rb +83 -0
  188. data/lib/simplecov/view_coverage.rb +55 -0
  189. data/lib/simplecov-html.rb +1 -0
  190. data/lib/simplecov.rb +57 -113
  191. data/lib/simplecov_json_formatter.rb +1 -0
  192. data/man/simplecov.1 +349 -0
  193. data/sig/simplecov.rbs +523 -595
  194. metadata +72 -5
data/lib/simplecov.rb CHANGED
@@ -1,17 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- #
4
- # Code coverage for ruby. Please check out README for a full introduction.
5
- #
3
+ require "forwardable"
4
+ require_relative "simplecov/configuration_error"
5
+ require_relative "simplecov/current_run"
6
+
6
7
  module SimpleCov
7
- # Raised when a user's configuration is internally inconsistent e.g.
8
- # every coverage criterion has been disabled.
9
- class ConfigurationError < StandardError; end
10
-
11
- # Maps SimpleCov's criterion names to the keys `Coverage.start` expects.
12
- # Lives at module scope (not inside `class << self`) so it can be
13
- # declared in the RBS signatures; lexical scoping keeps every existing
14
- # reference inside the singleton class working.
8
+ # At module scope rather than inside `class << self` so it can be declared in
9
+ # the RBS signatures; lexical scoping keeps references inside the singleton
10
+ # class working.
15
11
  CRITERION_TO_RUBY_COVERAGE = {
16
12
  branch: :branches,
17
13
  line: :lines,
@@ -19,68 +15,38 @@ module SimpleCov
19
15
  oneshot_line: :oneshot_lines
20
16
  }.freeze
21
17
 
22
- class << self
23
- attr_accessor :pid
24
- # When this process started tracking coverage. Captured by SimpleCov.start
25
- # so JSONFormatter can detect when an existing coverage.json was written
26
- # by a sibling process running concurrently.
27
- attr_accessor :process_start_time
28
-
29
- # A monotonically increasing serial the parent assigns to each forked
30
- # subprocess (see SimpleCov::ProcessForkHook). The default `at_fork`
31
- # builds the worker's command_name from this rather than the OS pid:
32
- # the serial sequence is the same from one run to the next, so a re-run
33
- # overwrites the previous run's resultset entries instead of writing
34
- # uniquely-named ones that pile up until merge_timeout. See issue #1171.
35
- def subprocess_serial
36
- @subprocess_serial ||= 0
37
- end
18
+ # `SingleForwardable` rather than `Forwardable` on the singleton class,
19
+ # because RBS has no way to speak about the singleton class's own ancestors.
20
+ extend SingleForwardable
38
21
 
39
- # @api private — bump the serial in the parent before a fork so the
40
- # child inherits its own ordinal via copy-on-write.
41
- def next_subprocess_serial!
42
- @subprocess_serial = subprocess_serial + 1
43
- end
22
+ def_delegators :current_run,
23
+ :pid, :pid=, :process_start_time, :process_start_time=,
24
+ :subprocess_serial, :next_subprocess_serial!,
25
+ :forked_subprocess?, :mark_forked_subprocess!,
26
+ :result?, :collating_result?
44
27
 
45
- # @api private — true in a process that was forked while coverage was
46
- # running (set by SimpleCov::ProcessForkHook in the child). Such a child
47
- # stores its own slice but must not act as the final-result process: the
48
- # process that forked it merges every slice and produces the report. Only
49
- # consulted when no parallel-test adapter is active, since adapters answer
50
- # `first_worker?` themselves. See issue #1171.
51
- def forked_subprocess?
52
- !!(defined?(@forked_subprocess) && @forked_subprocess)
28
+ class << self
29
+ def current_run
30
+ @current_run ||= CurrentRun.new
53
31
  end
54
32
 
55
- # @api private — marked in the child immediately after a fork.
56
- def mark_forked_subprocess!
57
- @forked_subprocess = true
58
- end
59
- # Should we take care of at_exit behavior or something else? Used by the
60
- # minitest plugin. See lib/minitest/simplecov_plugin.rb.
33
+ # @api private
34
+ attr_writer :current_run
35
+
61
36
  attr_accessor :external_at_exit
62
37
 
63
38
  # `:oneshot_line` data is folded into the `:line` bucket of
64
- # `coverage_statistics` by `ResultAdapter`, so use `:line` to look
65
- # up stats for either criterion.
39
+ # `coverage_statistics` by `ResultAdapter`. The cast is steep's: it narrows
40
+ # a union on `==` but not on `equal?`.
66
41
  def coverage_statistics_key(criterion)
67
- criterion == :oneshot_line ? :line : criterion
42
+ criterion.equal?(:oneshot_line) ? :line : _ = criterion
68
43
  end
69
44
 
70
- # Coerce to a proper boolean so rspec-mocks 4's predicate matcher
71
- # (`expect(...).not_to be_external_at_exit`) accepts the result.
45
+ # Coerced so rspec-mocks 4's predicate matcher accepts the result.
72
46
  def external_at_exit?
73
47
  !!@external_at_exit
74
48
  end
75
49
 
76
- #
77
- # Sets up SimpleCov to run against your project. See README for
78
- # the full DSL, or:
79
- #
80
- # SimpleCov.start
81
- # SimpleCov.start 'rails' # using a profile
82
- # SimpleCov.start { add_filter 'test' } # with a config block
83
- #
84
50
  def start(profile = nil, &)
85
51
  warn_about_start_in_dot_simplecov if @autoloading_dot_simplecov
86
52
 
@@ -90,15 +56,7 @@ module SimpleCov
90
56
  end
91
57
 
92
58
  # @api private
93
- #
94
- # Mark the duration of a `.simplecov` auto-load so any `SimpleCov.start`
95
- # call inside the file can warn about the impending migration to a
96
- # config-only file. Tracking still begins for backward compatibility;
97
- # the warning is the cue to move `SimpleCov.start` into a test helper.
98
- # See #581.
99
59
  def with_dot_simplecov_autoload
100
- # Read in the ensure clause, where flow analysis cannot see the
101
- # assignment above; anchor the type here.
102
60
  previous = @autoloading_dot_simplecov # : bool?
103
61
  @autoloading_dot_simplecov = true
104
62
  yield
@@ -119,62 +77,39 @@ module SimpleCov
119
77
  "See https://github.com/simplecov-ruby/simplecov/issues/581."
120
78
  end
121
79
 
122
- #
123
- # Install the at_exit hook that formats results and runs exit-code
124
- # checks. `SimpleCov.start` calls this automatically. Idempotent —
125
- # safe to call multiple times. Callers that drive the formatting
126
- # pipeline themselves (e.g., dogfood test setups) can skip it by
127
- # using `start_tracking` directly instead of `start`.
128
- #
129
80
  def install_at_exit_hook
130
81
  return if @at_exit_hook_installed
131
82
 
132
83
  @at_exit_hook_installed = true
133
- # Never defer in a forked child: Minitest pins its after_run at_exit
134
- # to the pid that armed autorun, so the deferral target can't fire
135
- # there and the child's resultset would be silently dropped. See
136
- # issue #1227.
84
+ # Never defer in a forked child: Minitest pins its after_run at_exit to
85
+ # the pid that armed autorun, so the deferral target can't fire there and
86
+ # the child's resultset would be silently dropped (#1227).
137
87
  defer_to_minitest_after_run if minitest_autorun_pending? && !forked_subprocess?
138
88
  Kernel.at_exit do
139
- next if SimpleCov.external_at_exit?
89
+ next if external_at_exit?
140
90
 
141
- SimpleCov.at_exit_behavior
91
+ at_exit_behavior
142
92
  end
143
93
  end
144
94
 
145
- #
146
- # Begin coverage tracking without applying configuration. Pairs with
147
- # `SimpleCov.configure { ... }` for callers that want to separate
148
- # the two — for example a dogfood test that has already started
149
- # `Coverage` itself before requiring simplecov, but still wants the
150
- # process_start_time / pid / fork-hook bookkeeping.
151
- #
152
95
  def start_tracking
153
96
  require "coverage"
154
97
  warn_if_jruby_full_trace_disabled
155
98
  validate_coverage_criteria!
156
- # simplecov:disable fork-hook is enabled via SimpleCov.enable_for_subprocesses, off by default
157
- require_relative "simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
158
- ::Process.respond_to?(:_fork)
159
- # simplecov:enable
99
+ require_relative "simplecov/process" if enabled_for_subprocesses? && Process.respond_to?(:_fork)
160
100
 
161
- # Select the parallel adapter and generate identities before any forks.
162
- SimpleCov::RunIdentity.prepare
101
+ # Must happen before any forks.
102
+ RunIdentity.prepare
163
103
 
164
- @result = nil
104
+ self.current_run = current_run.successor
165
105
  self.pid = Process.pid
166
106
  self.process_start_time = Time.now
167
107
 
168
108
  start_coverage_measurement
169
109
  end
170
110
 
171
- private
111
+ private
172
112
 
173
- #
174
- # Trigger Coverage.start with the configured criteria. Every supported
175
- # runtime (CRuby >= 3.2, JRuby >= 10, TruffleRuby >= 22) accepts the
176
- # criteria-hash form, so no compatibility fallback is needed.
177
- #
178
113
  def start_coverage_measurement
179
114
  start_arguments = coverage_criteria.to_h do |criterion|
180
115
  [CRITERION_TO_RUBY_COVERAGE.fetch(criterion), true]
@@ -183,15 +118,14 @@ module SimpleCov
183
118
  start_arguments[:eval] = true if coverage_for_eval_enabled?
184
119
 
185
120
  Coverage.start(**start_arguments) unless Coverage.running?
121
+ start_test_tracking
186
122
  end
187
123
 
188
- # `Rake::TestTask` runs `ruby -e 'require "minitest/autorun"; ...'`,
189
- # which means Minitest's at_exit registers before SimpleCov's. Since
190
- # at_exit fires LIFO, SimpleCov's hook would otherwise run *before*
191
- # Minitest gets a chance to invoke the tests — and format an empty
192
- # resultset. When we can see that Minitest is loaded and its autorun
193
- # is armed, route the report through `Minitest.after_run` instead,
194
- # which fires after the suite completes. See issues #1099 and #1112.
124
+ # `Rake::TestTask` runs `ruby -e 'require "minitest/autorun"; ...'`, so
125
+ # Minitest's at_exit registers before SimpleCov's and, at_exit being LIFO,
126
+ # SimpleCov's would format an empty resultset before the tests ever run.
127
+ # Routing through `Minitest.after_run` instead fires after the suite
128
+ # completes (#1099, #1112).
195
129
  def minitest_autorun_pending?
196
130
  return false unless defined?(Minitest) && Minitest.respond_to?(:after_run)
197
131
  return false unless Minitest.class_variable_defined?(:@@installed_at_exit)
@@ -201,19 +135,21 @@ module SimpleCov
201
135
 
202
136
  def defer_to_minitest_after_run
203
137
  self.external_at_exit = true
204
- Minitest.after_run { SimpleCov.at_exit_behavior }
138
+ Minitest.after_run { at_exit_behavior }
205
139
  end
206
140
 
207
141
  # JRuby coverage data is unreliable unless full-trace mode is enabled.
208
142
  # @see https://github.com/jruby/jruby/issues/1196
209
143
  # @see https://github.com/simplecov-ruby/simplecov/issues/420
210
144
  # @see https://github.com/simplecov-ruby/simplecov/issues/86
145
+ # mutant:disable — every line below the guard is JRuby-only, and no
146
+ # example running on the engine this suite runs on can reach one.
211
147
  def warn_if_jruby_full_trace_disabled
212
148
  return unless defined?(JRUBY_VERSION) && defined?(JRuby) # simplecov:disable — JRuby-only branch
213
149
 
214
150
  # simplecov:disable — JRuby-only branches; unreachable from CRuby
215
- # `org` is JRuby's Java-package entry point; it does not exist on
216
- # CRuby, so no RBS declaration can be truthful here.
151
+ # `org` is JRuby's Java-package entry point, absent on CRuby, so no RBS
152
+ # declaration can be truthful here.
217
153
  return if org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED # steep:ignore NoMethod
218
154
 
219
155
  warn 'Coverage may be inaccurate; set the "--debug" command line option, ' \
@@ -224,8 +160,6 @@ module SimpleCov
224
160
  end
225
161
  end
226
162
 
227
- # requires are down here for a load order reason I'm not sure what it is about
228
- require "forwardable"
229
163
  require_relative "simplecov/color"
230
164
  require_relative "simplecov/deprecation"
231
165
  require_relative "simplecov/group_names"
@@ -244,8 +178,18 @@ require_relative "simplecov/result"
244
178
  require_relative "simplecov/filter"
245
179
  require_relative "simplecov/formatter"
246
180
  require_relative "simplecov/last_run"
181
+ require_relative "simplecov/history"
247
182
  require_relative "simplecov/report_stamp"
183
+ require_relative "simplecov/baseline"
248
184
  require_relative "simplecov/lines_classifier"
185
+ require_relative "simplecov/context_map"
186
+ require_relative "simplecov/context_map/union"
187
+ require_relative "simplecov/test_tracker/constant_watch"
188
+ require_relative "simplecov/test_tracker/delta"
189
+ require_relative "simplecov/test_tracker"
190
+ require_relative "simplecov/test_tracker/framework_hooks"
191
+ require_relative "simplecov/test_tracker/accessors"
192
+ SimpleCov.extend SimpleCov::TestTracker::Accessors
249
193
  require_relative "simplecov/result_merger"
250
194
  require_relative "simplecov/parallel_result_merger"
251
195
  require_relative "simplecov/parallel_adapters"
@@ -264,12 +208,12 @@ require_relative "simplecov/combine/results_combiner"
264
208
  require_relative "simplecov/useless_results_remover"
265
209
  require_relative "simplecov/simulate_coverage"
266
210
  require_relative "simplecov/unloaded_file_injector"
211
+ require_relative "simplecov/view_coverage"
267
212
  require_relative "simplecov/result_processing"
268
213
  require_relative "simplecov/exit_handling"
269
214
  require_relative "simplecov/report_deferral"
270
215
  require_relative "simplecov/parallel_coordination"
271
216
 
272
- # Load default config
273
217
  # simplecov:disable — env-var never set in the dogfooded test process
274
218
  # (sandbox fixture subprocesses set it via simplecov/no_defaults)
275
219
  require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Backward-compatibility shim: simplecov_json_formatter is now part of simplecov.
4
+
4
5
  require_relative "simplecov/formatter/json_formatter"
data/man/simplecov.1 ADDED
@@ -0,0 +1,349 @@
1
+ .TH SIMPLECOV 1 "2026-08-24" "simplecov 1.2.0" "User Commands"
2
+ .SH NAME
3
+ simplecov \- coverage reports and questions from the terminal
4
+ .SH SYNOPSIS
5
+ .B simplecov
6
+ .I command
7
+ .RI [ options ]
8
+ .SH DESCRIPTION
9
+ The simplecov command reads the JSON report a SimpleCov run writes next to its
10
+ HTML report (coverage/coverage.json by default) and answers coverage questions
11
+ from the terminal. Default paths follow SimpleCov.coverage_dir from a
12
+ project's .simplecov when one is present. Every command answers \-\-help with
13
+ its own usage.
14
+ .SH COMMANDS
15
+ .TP
16
+ .B run <command...>
17
+ Execute <command> with SimpleCov pre\-loaded
18
+ .TP
19
+ .B coverage <path>
20
+ Print coverage stats for the given file
21
+ .TP
22
+ .B show <path>
23
+ Print the file's source annotated with hit counts and misses
24
+ .TP
25
+ .B report
26
+ Print the overall summary and group totals
27
+ .TP
28
+ .B status
29
+ Report freshness: age, commit distance, recorded tests
30
+ .TP
31
+ .B history
32
+ Print the recorded coverage trend, a sparkline per criterion
33
+ .TP
34
+ .B badge
35
+ Render the coverage percent as an SVG badge
36
+ .TP
37
+ .B uncovered
38
+ List the lowest\-coverage files
39
+ .TP
40
+ .B tests [<path>[:<line>]]
41
+ List recorded tests for a file or line (needs track_tests)
42
+ .TP
43
+ .B affected
44
+ List test files touching code changed since a git ref (needs track_tests)
45
+ .TP
46
+ .B merge <files...>
47
+ Merge multiple .resultset.json files
48
+ .TP
49
+ .B diff <baseline>
50
+ Show per\-file coverage delta vs baseline
51
+ .TP
52
+ .B patch
53
+ Show coverage of the lines a change touched
54
+ .TP
55
+ .B ratchet
56
+ Rewrite the per\-file coverage baseline, only ever tightening
57
+ .TP
58
+ .B dead\-code
59
+ Cross production coverage with the report to find dead code
60
+ .TP
61
+ .B open
62
+ Open the HTML report in the default browser
63
+ .TP
64
+ .B serve
65
+ Serve the coverage report over HTTP
66
+ .TP
67
+ .B watch <command...>
68
+ Re\-run <command> on save and live\-reload the served report
69
+ .TP
70
+ .B clean
71
+ Remove the coverage report directory
72
+ .TP
73
+ .B completions <shell>
74
+ Emit the completion script for fish, bash, or zsh
75
+ .TP
76
+ .B help
77
+ Show this message
78
+ .TP
79
+ .B version
80
+ Print the version (also \-\-version / \-v)
81
+ .SH OPTIONS
82
+ .SS coverage
83
+ .TP
84
+ .B \-\-input PATH
85
+ Read from PATH instead of coverage/coverage.json
86
+ .TP
87
+ .B \-\-no\-color
88
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
89
+ .TP
90
+ .B \-\-json
91
+ Print the file's JSON entry verbatim
92
+ .SS show
93
+ .TP
94
+ .B \-\-input PATH
95
+ Read from PATH instead of coverage/coverage.json
96
+ .TP
97
+ .B \-\-no\-color
98
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
99
+ .TP
100
+ .B \-\-uncovered\-only
101
+ Print only <path>:<ranges> of the missed lines
102
+ .TP
103
+ .B \-\-json
104
+ Emit path, missed lines, per\-line hits, and markers as JSON
105
+ .SS report
106
+ .TP
107
+ .B \-\-input PATH
108
+ Read from PATH instead of coverage/coverage.json
109
+ .TP
110
+ .B \-\-no\-color
111
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
112
+ .TP
113
+ .B \-\-json
114
+ Emit totals and group sections as JSON
115
+ .SS status
116
+ .TP
117
+ .B \-\-input PATH
118
+ Read from PATH instead of coverage/coverage.json
119
+ .TP
120
+ .B \-\-no\-color
121
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
122
+ .TP
123
+ .B \-\-json
124
+ Emit the freshness facts as a JSON object
125
+ .SS history
126
+ .TP
127
+ .B \-\-input PATH
128
+ Read from PATH instead of the coverage directory's .history.json
129
+ .TP
130
+ .B \-\-file PATH
131
+ Follow one file's trajectory instead of the totals
132
+ .TP
133
+ .B \-\-json
134
+ Emit the entries (or the file's trajectory) as JSON
135
+ .TP
136
+ .B \-\-no\-color
137
+ Disable colorized deltas (also honors NO_COLOR / FORCE_COLOR env)
138
+ .SS badge
139
+ .TP
140
+ .B \-\-input PATH
141
+ Read from PATH instead of coverage/coverage.json
142
+ .TP
143
+ .B \-\-output PATH
144
+ Write the badge to PATH instead of stdout
145
+ .TP
146
+ .B \-\-criterion C
147
+ line, branch, or method (default: line)
148
+ .TP
149
+ .B \-\-label TEXT
150
+ The badge's left\-side text (default: the criterion's, like "line coverage")
151
+ .SS uncovered
152
+ .TP
153
+ .B \-\-input PATH
154
+ Read from PATH instead of coverage/coverage.json
155
+ .TP
156
+ .B \-\-no\-color
157
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
158
+ .TP
159
+ .B \-\-threshold N
160
+ Only show files below N% coverage
161
+ .TP
162
+ .B \-\-top N
163
+ Show at most N files (default: 10)
164
+ .TP
165
+ .B \-\-criterion C
166
+ line, branch, or method (default: line)
167
+ .TP
168
+ .B \-\-missing
169
+ Append the missed line ranges to each row
170
+ .TP
171
+ .B \-\-annotate github
172
+ Emit ::warning workflow commands instead of rows
173
+ .TP
174
+ .B \-\-json
175
+ Emit results as a JSON array (for CI)
176
+ .SS tests
177
+ .TP
178
+ .B \-\-input PATH
179
+ Read from PATH instead of coverage/coverage.json
180
+ .TP
181
+ .B \-\-no\-color
182
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
183
+ .TP
184
+ .B \-\-redundant
185
+ List only tests whose covered lines other tests also cover
186
+ .TP
187
+ .B \-\-json
188
+ Emit the test ids as a JSON array
189
+ .SS affected
190
+ .TP
191
+ .B \-\-input PATH
192
+ Read from PATH instead of coverage/coverage.json
193
+ .TP
194
+ .B \-\-no\-color
195
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
196
+ .TP
197
+ .B \-\-base REF
198
+ Diff against the merge base of REF and HEAD (default: origin's HEAD, else
199
+ main)
200
+ .TP
201
+ .B \-\-run <command...>
202
+ Run <command> (all args after \-\-run) with the selection appended, or bare on
203
+ a full\-suite fallback, exiting with the command's status
204
+ .TP
205
+ .B \-\-json
206
+ Emit {full_suite, triggers, tests} as a JSON object
207
+ .SS merge
208
+ .TP
209
+ .B \-\-output PATH
210
+ Write merged resultset to PATH (default: coverage/.resultset.json)
211
+ .TP
212
+ .B \-\-honor\-timeout
213
+ Drop entries older than merge_timeout
214
+ .TP
215
+ .B \-\-dry\-run
216
+ Print what would be written without writing
217
+ .TP
218
+ .B \-q, \-\-quiet
219
+ Suppress the success status line
220
+ .SS diff
221
+ .TP
222
+ .B \-\-input PATH
223
+ Read from PATH instead of coverage/coverage.json
224
+ .TP
225
+ .B \-\-no\-color
226
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
227
+ .TP
228
+ .B \-\-fail\-on\-drop
229
+ Exit non\-zero when any file's coverage dropped vs baseline (deletions don't
230
+ count)
231
+ .TP
232
+ .B \-\-json
233
+ Emit results as a JSON array (for CI)
234
+ .TP
235
+ .B \-\-threshold N
236
+ Only show files whose absolute delta in any criterion is at least N%
237
+ .SS patch
238
+ .TP
239
+ .B \-\-input PATH
240
+ Read from PATH instead of coverage/coverage.json
241
+ .TP
242
+ .B \-\-no\-color
243
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
244
+ .TP
245
+ .B \-\-base REF
246
+ Diff against the merge\-base of REF for the touched lines (default: origin's
247
+ HEAD, else main, or in CI the PR's target branch)
248
+ .TP
249
+ .B \-\-minimum N
250
+ Exit non\-zero when patch coverage on any measured criterion is below N%
251
+ .TP
252
+ .B \-\-find\-renames
253
+ Follow a renamed file instead of counting the moved file as all\-new
254
+ .TP
255
+ .B \-\-json
256
+ Emit results as a JSON array (for CI)
257
+ .SS ratchet
258
+ .TP
259
+ .B \-\-input PATH
260
+ Read from PATH instead of coverage/coverage.json
261
+ .TP
262
+ .B \-\-no\-color
263
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
264
+ .TP
265
+ .B \-\-baseline PATH
266
+ The baseline file to rewrite (default: the project's `baseline_file`,
267
+ \&.simplecov_baseline.yml)
268
+ .TP
269
+ .B \-\-init
270
+ Regenerate from scratch: add entries for new files and reset every floor to
271
+ the current state
272
+ .TP
273
+ .B \-\-dry\-run
274
+ Print what would change without writing
275
+ .TP
276
+ .B \-\-json
277
+ Emit the summary (tightened / pruned / regressed entries) as JSON
278
+ .SS dead-code
279
+ .TP
280
+ .B \-\-input PATH
281
+ Read from PATH instead of coverage/coverage.json
282
+ .TP
283
+ .B \-\-no\-color
284
+ Disable colorized percentages (also honors NO_COLOR / FORCE_COLOR env)
285
+ .TP
286
+ .B \-\-production PATH
287
+ The production coverage file a SimpleCov::Production sink wrote (default: the
288
+ project's `production_coverage`, required when none is configured)
289
+ .TP
290
+ .B \-\-untested\-in\-production
291
+ Print code production runs that no test covers, instead of the dead rows
292
+ .TP
293
+ .B \-\-json
294
+ Emit every category (dead, possibly dead, untested in production) as JSON
295
+ .SS open
296
+ .TP
297
+ .B \-\-report PATH
298
+ Open PATH instead of coverage/index.html
299
+ .SS serve
300
+ .TP
301
+ .B \-\-port N
302
+ Bind to port N (default: random open port)
303
+ .TP
304
+ .B \-\-host HOST
305
+ Bind to HOST (default: 127.0.0.1)
306
+ .SS watch
307
+ .TP
308
+ .B \-\-port N
309
+ Bind to port N (default: random open port)
310
+ .TP
311
+ .B \-\-host HOST
312
+ Bind to HOST (default: 127.0.0.1)
313
+ .TP
314
+ .B \-\-interval SECONDS
315
+ Poll the tracked files this often (default: 0.5)
316
+ .TP
317
+ .B \-\-open
318
+ Open the served report in the default browser
319
+ .SS clean
320
+ .TP
321
+ .B \-\-dry\-run
322
+ Print what would be removed without deleting
323
+ .TP
324
+ .B \-q, \-\-quiet
325
+ Suppress status lines
326
+ .SH ENVIRONMENT
327
+ .TP
328
+ .B NO_COLOR
329
+ Disable colorized output. FORCE_COLOR forces it on, and \-\-no\-color beats
330
+ both.
331
+ .TP
332
+ .B SIMPLECOV_MERGE_TIMEOUT
333
+ Override merge_timeout in seconds. The watch command sets it for child runs so
334
+ subset re\-runs keep merging into a whole report.
335
+ .SH FILES
336
+ .TP
337
+ .B coverage/coverage.json
338
+ The JSON report the read\-only commands consume. The bundled HTML formatter
339
+ writes it alongside index.html.
340
+ .TP
341
+ .B coverage/.resultset.json
342
+ The merged raw resultset the merge command reads and writes.
343
+ .TP
344
+ .B .simplecov
345
+ Project configuration. Its SimpleCov.coverage_dir setting moves every default
346
+ path above.
347
+ .SH SEE ALSO
348
+ Full documentation with examples for every command lives in docs/CLI.md in the
349
+ source tree and at https://github.com/simplecov\-ruby/simplecov