simplecov 1.0.0 → 1.1.1

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +56 -1451
  3. data/lib/simplecov/atomic_file.rb +70 -0
  4. data/lib/simplecov/cli/clean.rb +43 -3
  5. data/lib/simplecov/cli/command_helpers.rb +55 -0
  6. data/lib/simplecov/cli/coverage.rb +23 -28
  7. data/lib/simplecov/cli/coverage_file.rb +65 -0
  8. data/lib/simplecov/cli/diff.rb +43 -47
  9. data/lib/simplecov/cli/dotfile.rb +21 -10
  10. data/lib/simplecov/cli/merge.rb +17 -13
  11. data/lib/simplecov/cli/open.rb +3 -5
  12. data/lib/simplecov/cli/report.rb +38 -25
  13. data/lib/simplecov/cli/run.rb +1 -1
  14. data/lib/simplecov/cli/serve/report_preparer.rb +29 -0
  15. data/lib/simplecov/cli/serve/static_file_handler.rb +122 -0
  16. data/lib/simplecov/cli/serve.rb +45 -99
  17. data/lib/simplecov/cli/uncovered.rb +20 -24
  18. data/lib/simplecov/cli.rb +15 -2
  19. data/lib/simplecov/color.rb +10 -1
  20. data/lib/simplecov/combine/branches_combiner.rb +43 -18
  21. data/lib/simplecov/combine/coverage_accumulator.rb +268 -0
  22. data/lib/simplecov/combine/identity_interner.rb +30 -0
  23. data/lib/simplecov/combine/interned_counts.rb +30 -0
  24. data/lib/simplecov/combine/lines_combiner.rb +48 -20
  25. data/lib/simplecov/combine/methods_combiner.rb +53 -5
  26. data/lib/simplecov/combine/results_combiner.rb +12 -36
  27. data/lib/simplecov/combine.rb +5 -23
  28. data/lib/simplecov/command_guesser.rb +66 -9
  29. data/lib/simplecov/configuration/coverage.rb +17 -16
  30. data/lib/simplecov/configuration/coverage_criteria.rb +37 -39
  31. data/lib/simplecov/configuration/eval_coverage.rb +41 -0
  32. data/lib/simplecov/configuration/filters.rb +11 -44
  33. data/lib/simplecov/configuration/formatting.rb +33 -14
  34. data/lib/simplecov/configuration/groups.rb +42 -0
  35. data/lib/simplecov/configuration/merging.rb +8 -7
  36. data/lib/simplecov/configuration/thresholds.rb +27 -22
  37. data/lib/simplecov/configuration.rb +21 -42
  38. data/lib/simplecov/coverage_json.rb +24 -0
  39. data/lib/simplecov/coverage_statistics.rb +5 -2
  40. data/lib/simplecov/coverage_violations.rb +17 -6
  41. data/lib/simplecov/defaults.rb +10 -6
  42. data/lib/simplecov/directive.rb +9 -4
  43. data/lib/simplecov/exit_codes/check.rb +33 -0
  44. data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +11 -20
  45. data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +4 -17
  46. data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +14 -23
  47. data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +14 -25
  48. data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +7 -20
  49. data/lib/simplecov/exit_codes.rb +17 -0
  50. data/lib/simplecov/exit_handling.rb +13 -43
  51. data/lib/simplecov/file_list.rb +14 -12
  52. data/lib/simplecov/filter.rb +43 -9
  53. data/lib/simplecov/formatter/base.rb +18 -1
  54. data/lib/simplecov/formatter/coverage_json_writer.rb +97 -0
  55. data/lib/simplecov/formatter/html_formatter/public/index.html +36 -5
  56. data/lib/simplecov/formatter/html_formatter/viewer_data_validator.rb +96 -0
  57. data/lib/simplecov/formatter/html_formatter.rb +71 -45
  58. data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +54 -50
  59. data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +78 -88
  60. data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +70 -76
  61. data/lib/simplecov/formatter/json_formatter.rb +5 -46
  62. data/lib/simplecov/formatter/multi_formatter.rb +8 -3
  63. data/lib/simplecov/formatter/simple_formatter.rb +8 -3
  64. data/lib/simplecov/formatter.rb +12 -0
  65. data/lib/simplecov/group_names.rb +32 -0
  66. data/lib/simplecov/last_run.rb +16 -9
  67. data/lib/simplecov/lines_classifier.rb +29 -8
  68. data/lib/simplecov/load_global_config.rb +5 -2
  69. data/lib/simplecov/parallel_adapters/base.rb +17 -0
  70. data/lib/simplecov/parallel_adapters/generic.rb +9 -8
  71. data/lib/simplecov/parallel_adapters/parallel_tests.rb +2 -2
  72. data/lib/simplecov/parallel_adapters.rb +4 -2
  73. data/lib/simplecov/parallel_coordination.rb +6 -1
  74. data/lib/simplecov/parallel_result_merger.rb +230 -0
  75. data/lib/simplecov/process.rb +22 -0
  76. data/lib/simplecov/report_deferral.rb +49 -0
  77. data/lib/simplecov/report_stamp.rb +28 -0
  78. data/lib/simplecov/result.rb +40 -10
  79. data/lib/simplecov/result_adapter.rb +79 -10
  80. data/lib/simplecov/result_merger/resultset_file.rb +43 -7
  81. data/lib/simplecov/result_merger/resultset_run_identity.rb +67 -0
  82. data/lib/simplecov/result_merger/resultset_store.rb +15 -12
  83. data/lib/simplecov/result_merger/unloaded_files.rb +103 -0
  84. data/lib/simplecov/result_merger.rb +69 -42
  85. data/lib/simplecov/result_processing.rb +85 -46
  86. data/lib/simplecov/run_identity.rb +77 -0
  87. data/lib/simplecov/simulate_coverage.rb +37 -12
  88. data/lib/simplecov/source_file/line.rb +2 -2
  89. data/lib/simplecov/source_file/method.rb +8 -2
  90. data/lib/simplecov/source_file/method_builder.rb +3 -1
  91. data/lib/simplecov/source_file/ruby_data_parser.rb +25 -3
  92. data/lib/simplecov/source_file/skip_chunks.rb +7 -10
  93. data/lib/simplecov/source_file/source_loader.rb +25 -9
  94. data/lib/simplecov/source_file/statistics.rb +24 -16
  95. data/lib/simplecov/source_file.rb +2 -2
  96. data/lib/simplecov/static_coverage_extractor/condition_folding.rb +239 -0
  97. data/lib/simplecov/static_coverage_extractor/location_conventions.rb +236 -0
  98. data/lib/simplecov/static_coverage_extractor/method_collector.rb +7 -0
  99. data/lib/simplecov/static_coverage_extractor/prism_compat.rb +55 -0
  100. data/lib/simplecov/static_coverage_extractor/value_position.rb +74 -0
  101. data/lib/simplecov/static_coverage_extractor/visitor.rb +74 -62
  102. data/lib/simplecov/unloaded_file_injector.rb +75 -0
  103. data/lib/simplecov/version.rb +1 -1
  104. data/lib/simplecov.rb +37 -17
  105. data/sig/simplecov.rbs +1777 -0
  106. metadata +32 -16
  107. data/doc/alternate-formatters.md +0 -66
  108. data/doc/commercial-services.md +0 -25
  109. data/doc/editor-integration.md +0 -18
  110. data/lib/simplecov/combine/files_combiner.rb +0 -30
  111. data/lib/simplecov/formatter/html_formatter/public/application.css +0 -1
  112. data/lib/simplecov/formatter/html_formatter/public/application.js +0 -18
  113. data/lib/simplecov/formatter/html_formatter/public/favicon_green.png +0 -0
  114. data/lib/simplecov/formatter/html_formatter/public/favicon_red.png +0 -0
  115. data/lib/simplecov/formatter/html_formatter/public/favicon_yellow.png +0 -0
  116. data/schemas/coverage-v1.0.schema.json +0 -306
  117. data/schemas/coverage.schema.json +0 -306
data/sig/simplecov.rbs ADDED
@@ -0,0 +1,1777 @@
1
+ # Code coverage for Ruby. See the README for a full introduction.
2
+ module SimpleCov
3
+ # A coverage criterion that can be enabled, measured, and reported.
4
+ type criterion = :line | :branch | :method
5
+ type line_coverage_alternatives = Hash[criterion | :oneshot_line, :line | :oneshot_line]
6
+
7
+ # Anything accepted by `skip` / `group` (and the deprecated
8
+ # `add_filter` / `add_group`): a path-segment substring, a Regexp, a
9
+ # prebuilt Filter, a predicate on the SourceFile, or an Array of those.
10
+ type filter_arg = String | Regexp | Filter[untyped] | ^(SourceFile source_file) -> boolish | Array[filter_arg]
11
+
12
+ # Anything accepted by `cover`: a shell-glob String, Regexp, Proc,
13
+ # prebuilt Filter, or an Array of those.
14
+ type cover_arg = String | Regexp | ^(SourceFile source_file) -> boolish | Filter[untyped] | Array[cover_arg]
15
+
16
+ # Raised when a user's configuration is internally inconsistent — e.g.
17
+ # every coverage criterion has been disabled.
18
+ class ConfigurationError < StandardError
19
+ end
20
+
21
+ module GroupNames
22
+ UNGROUPED: String
23
+
24
+ def self?.normalize: (untyped group_name) -> String
25
+
26
+ def self?.validate!: (Array[String] group_names) -> Array[String]
27
+ end
28
+
29
+ # Maps SimpleCov's criterion names to the keys `Coverage.start` expects.
30
+ CRITERION_TO_RUBY_COVERAGE: Hash[Symbol, Symbol]
31
+
32
+ extend Configuration
33
+
34
+ self.@subprocess_serial: Integer?
35
+ self.@forked_subprocess: bool?
36
+ self.@autoloading_dot_simplecov: bool?
37
+ self.@dot_simplecov_start_warned: bool?
38
+ self.@at_exit_hook_installed: bool?
39
+ self.@run_id: String?
40
+ self.@worker_id: String?
41
+
42
+ attr_accessor self.pid: Integer?
43
+
44
+ # When this process started tracking coverage.
45
+ attr_accessor self.process_start_time: Time?
46
+
47
+ def self.run_id: () -> String
48
+
49
+ def self.worker_id: () -> String
50
+
51
+ # Should something external (e.g. the Minitest plugin) own the
52
+ # at_exit behavior instead of SimpleCov's own hook?
53
+ attr_accessor self.external_at_exit: bool?
54
+
55
+ def self.external_at_exit?: () -> bool
56
+
57
+ # A monotonically increasing serial assigned to each forked
58
+ # subprocess; the default `at_fork` builds worker command names from it.
59
+ def self.subprocess_serial: () -> Integer
60
+
61
+ def self.next_subprocess_serial!: () -> Integer
62
+
63
+ def self.forked_subprocess?: () -> bool
64
+
65
+ def self.mark_forked_subprocess!: () -> void
66
+
67
+ # `:oneshot_line` stats are folded into the `:line` bucket, so use
68
+ # the returned criterion to look up `coverage_statistics`.
69
+ def self.coverage_statistics_key: ((criterion | :oneshot_line) criterion) -> criterion
70
+
71
+ # Sets up SimpleCov to run against your project:
72
+ #
73
+ # SimpleCov.start
74
+ # SimpleCov.start 'rails' # using a profile
75
+ # SimpleCov.start { skip 'test' } # with a config block
76
+ #
77
+ def self.start: (?(String | Symbol)? profile) ?{ () [self: singleton(SimpleCov)] -> void } -> void
78
+
79
+ def self.with_dot_simplecov_autoload: [T] () { () -> T } -> T
80
+
81
+ def self.warn_about_start_in_dot_simplecov: () -> void
82
+
83
+ # Install the at_exit hook that formats results and runs exit-code
84
+ # checks. Idempotent; `SimpleCov.start` calls this automatically.
85
+ def self.install_at_exit_hook: () -> void
86
+
87
+ # Reset at_exit state a forked child inherits from its parent (a
88
+ # possibly consumed hook and a Minitest deferral pid-pinned to the
89
+ # parent), so the child re-arms a hook that fires at its own exit.
90
+ # Called by the fork hook; see issue #1227.
91
+ def self.reset_inherited_at_exit_state!: () -> void
92
+
93
+ # Begin coverage tracking without applying configuration. Pairs with
94
+ # `SimpleCov.configure { ... }`.
95
+ def self.start_tracking: () -> void
96
+
97
+ # Implementation details of `start` / `start_tracking` (private in Ruby;
98
+ # RBS cannot mark singleton methods private).
99
+ def self.start_coverage_measurement: () -> void
100
+
101
+ def self.minitest_autorun_pending?: () -> bool
102
+
103
+ def self.defer_to_minitest_after_run: () -> void
104
+
105
+ def self.warn_if_jruby_full_trace_disabled: () -> void
106
+ end
107
+
108
+ # ----- version -----
109
+
110
+ module SimpleCov
111
+ VERSION: String
112
+ end
113
+
114
+ # ----- result_processing -----
115
+
116
+ # Result-building façade: turns the raw `Coverage.result` hash into a
117
+ # `SimpleCov::Result`, applies filters and groups, drives merging, and
118
+ # exposes the `collate` entry point.
119
+ module SimpleCov
120
+ self.@result: Result?
121
+ self.@collating_result: bool?
122
+
123
+ # Collate a series of resultset files into a single merged report. By
124
+ # default ignores `merge_timeout` so every listed resultset merges;
125
+ # pass `ignore_timeout: false` to honor it. `processes:` above 1 fans the
126
+ # merge out across that many forked workers, for an identical report;
127
+ # anything below 1 is taken as 1.
128
+ def self.collate: (Array[String] result_filenames, ?(String | Symbol)? profile, ?processes: Integer, ?ignore_timeout: bool) ?{ () [self: singleton(SimpleCov)] -> void } -> void
129
+
130
+ # The result for the current coverage run, merged across test suites
131
+ # when merging is active. nil when no coverage was tracked.
132
+ def self.result: () -> Result?
133
+
134
+ # The memoized result, or false/nil when it has not been computed yet.
135
+ def self.result?: () -> (Result | false | nil)
136
+
137
+ def self.collating_result?: () -> boolish
138
+
139
+ # Applies the configured filters to the given source files.
140
+ def self.filtered: ((Array[SourceFile] | FileList) files) -> FileList
141
+
142
+ # Bin the given source files by group filter. Files matched by no
143
+ # group fall into the implicit "Ungrouped" bucket.
144
+ def self.grouped: ((Array[SourceFile] | FileList) files, ?groups: Hash[String, Filter[untyped]]) -> Hash[String, FileList]
145
+
146
+ # Applies the profile of the given name to the configuration.
147
+ def self.load_profile: ((String | Symbol) name) -> void
148
+
149
+ # Clear the cached result. Primarily useful in testing.
150
+ def self.clear_result: () -> void
151
+
152
+ def self.write_last_run: (Result result) -> void
153
+
154
+ # Round coverage down to two decimals.
155
+ def self.round_coverage: (Numeric coverage) -> Numeric
156
+
157
+ # Implementation details of `collate` / `result` (private in Ruby;
158
+ # RBS cannot mark singleton methods private).
159
+ def self.initial_setup: ((String | Symbol)? profile) ?{ () [self: singleton(SimpleCov)] -> void } -> void
160
+
161
+ def self.grouped_file_set: (Hash[String, FileList] grouped) -> Set[SourceFile]
162
+
163
+ def self.unloaded_file_discovery_globs: () -> Array[String]
164
+
165
+ # Every path this process was told to track, whether or not it loaded them.
166
+ # Recorded on the result (and from there into the resultset) so that a merge
167
+ # in another process can inject the ones nobody loaded without needing this
168
+ # process's `cover` / `track_files` configuration.
169
+ def self.tracked_file_paths: () -> Array[String]
170
+
171
+ # Add simulated coverage for each of `candidate_paths` the result doesn't
172
+ # already carry, and return it with the set of paths added.
173
+ #
174
+ # @api private — the seam `SimpleCov::ResultMerger` injects through.
175
+ def self.inject_unloaded_files: (Hash[String, untyped] result, Array[String] candidate_paths, ?synthesize: bool?, ?lines: bool?) -> [Hash[String, untyped], Set[String]]
176
+
177
+ # Build this process's slice of the coverage result. `standalone` is true
178
+ # when no merge step follows, which makes this the final result: it is the
179
+ # one that reports dropped source files, and the one that injects unloaded
180
+ # files. When a merge does follow, both jobs belong to the merged result.
181
+ def self.collect_own_coverage: (standalone: bool) -> void
182
+
183
+ def self.process_coverage_result: (report: bool, ?inject_unloaded: bool) -> void
184
+ end
185
+
186
+ # ----- configuration -----
187
+
188
+ # Bundles the configuration options used for SimpleCov. All methods
189
+ # defined here are usable from SimpleCov directly.
190
+ module SimpleCov
191
+ module Configuration
192
+ @root: String
193
+ @coverage_dir: String
194
+ @coverage_dir_explicit: bool?
195
+ @coverage_path: String?
196
+ @coverage_path_explicit: bool?
197
+ @command_name: String?
198
+ @profiles: Profiles?
199
+ @at_exit: Proc?
200
+ @at_fork: Proc?
201
+ @project_name: String?
202
+
203
+ # The root for the project, defaulting to the current working
204
+ # directory. Get, or set with `SimpleCov.root('/my/project/path')`.
205
+ def root: (?String? root) -> String
206
+
207
+ # The name of the output and cache directory. Defaults to "coverage".
208
+ def coverage_dir: (?String? dir) -> String
209
+
210
+ # The full path to the output directory. By default `root` +
211
+ # `coverage_dir`; assign an absolute path to pin the destination
212
+ # regardless of later `root` / `coverage_dir` changes (see #716).
213
+ def coverage_path: (?String? path) -> String
214
+
215
+ # The name of the command (a.k.a. test suite) currently running.
216
+ # Auto-detected when not set explicitly.
217
+ def command_name: (?String? name) -> String
218
+
219
+ # The hash of available profiles.
220
+ def profiles: () -> Profiles
221
+
222
+ # Configure SimpleCov in a block. A zero-argument block runs with the
223
+ # configuration target as `self`; a parameterized block keeps its lexical
224
+ # `self` and receives the target explicitly:
225
+ #
226
+ # SimpleCov.configure { skip "test" }
227
+ # SimpleCov.configure { |config| config.skip caller_filter }
228
+ #
229
+ def configure: () { () [self: self] -> untyped } -> self
230
+ | () { (self config) -> untyped } -> self
231
+
232
+ # Gets or sets the behavior that processes coverage results at
233
+ # process exit. The default stores/merges the current result and
234
+ # formats only from the final reporting process.
235
+ def at_exit: () ?{ () -> void } -> Proc
236
+
237
+ # Whether SimpleCov has anything to do at exit: coverage is being
238
+ # tracked, or a result has already been assembled (e.g. by collate).
239
+ def active_session?: () -> boolish
240
+
241
+ # Gets or sets the behavior run in a newly forked process. The
242
+ # block receives the child pid. The default renames the command
243
+ # from the fork serial, silences errors, and restarts SimpleCov.
244
+ def at_fork: () ?{ (Integer pid) -> void } -> Proc
245
+
246
+ # The project name — defaults to the last dirname in `root`,
247
+ # capitalized, with underscores replaced by spaces.
248
+ def project_name: (?String? new_name) -> String
249
+
250
+ end
251
+ end
252
+
253
+ # ----- configuration/coverage_criteria -----
254
+
255
+ # Selection and validation of the coverage criteria Ruby's `Coverage`
256
+ # library should track: `:line` (default), `:branch`, `:method`, and
257
+ # `:oneshot_line`. The standalone `:eval` toggle lives in
258
+ # `configuration/eval_coverage.rb`.
259
+ module SimpleCov
260
+ module Configuration
261
+ # Members are line, branch, method, and oneshot_line (%i[] literals
262
+ # infer as Array[Symbol]).
263
+ SUPPORTED_COVERAGE_CRITERIA: Array[Symbol]
264
+
265
+ DEFAULT_COVERAGE_CRITERION: :line
266
+
267
+ ONESHOT_LINE_COVERAGE_CRITERION: :oneshot_line
268
+
269
+ LINE_COVERAGE_ALTERNATIVES: line_coverage_alternatives
270
+
271
+ @primary_coverage: (criterion | :oneshot_line)?
272
+ @coverage_criteria: Set[criterion | :oneshot_line]?
273
+ @coverage_for_eval_enabled: bool?
274
+
275
+ # Enable one or more coverage criteria. `:eval` is accepted as a
276
+ # shorthand for the standalone eval-coverage toggle. `:line` and
277
+ # `:oneshot_line` replace each other; the last enabled mode wins.
278
+ def enable_coverage: (*(criterion | :oneshot_line | :eval) criteria) -> void
279
+
280
+ # Remove `criterion` from the set of enabled coverage criteria.
281
+ # `:eval` turns the standalone eval-coverage toggle back off.
282
+ # Disabling every criterion raises at `start_tracking`, not here.
283
+ def disable_coverage: ((criterion | :oneshot_line | :eval) criterion) -> void
284
+
285
+ # Gets the report's leading criterion, or sets it. The setter
286
+ # validates at runtime that the criterion is enabled; the parameter
287
+ # type also rejects unknown criteria statically.
288
+ def primary_coverage: (?(criterion | :oneshot_line)? criterion) -> (criterion | :oneshot_line)
289
+
290
+ # The currently enabled criteria. Defaults to `Set[:line]`.
291
+ def coverage_criteria: () -> Set[criterion | :oneshot_line]
292
+
293
+ # Any Symbol is accepted: asking whether an unknown criterion is
294
+ # enabled is a legitimate question (the answer is false), and the
295
+ # private validators rely on it.
296
+ def coverage_criterion_enabled?: (Symbol criterion) -> bool
297
+
298
+ # Reset the criteria back to the lazy default (`Set[:line]`).
299
+ def clear_coverage_criteria: () -> void
300
+
301
+ def validate_coverage_criteria!: () -> void
302
+
303
+ # Whether this run produces line data at all. The oneshot variant counts:
304
+ # `ResultAdapter` turns its executed-line list back into a line array. A
305
+ # branch-only or method-only run produces none, and `Coverage.result`
306
+ # entries for the files it loaded carry no `"lines"` key.
307
+ def line_coverage?: () -> bool
308
+
309
+ def branch_coverage?: () -> bool
310
+
311
+ def branch_coverage_supported?: () -> bool
312
+
313
+ def method_coverage?: () -> bool
314
+
315
+ def method_coverage_supported?: () -> bool
316
+
317
+ # Whether the running Ruby's Coverage library supports the given
318
+ # criterion, named in Coverage's own plural vocabulary
319
+ # (`:lines`, `:branches`, `:methods`, `:oneshot_lines`, `:eval`).
320
+ def coverage_criterion_supported?: (Symbol criterion) -> bool
321
+
322
+ private
323
+
324
+ def add_coverage_criterion: ((criterion | :oneshot_line) criterion) -> void
325
+
326
+ def default_primary_coverage: () -> (criterion | :oneshot_line)
327
+
328
+ # Validators: any Symbol is accepted at the type level; the whole
329
+ # point of these is raising ConfigurationError on bad input.
330
+ def raise_if_criterion_disabled: (Symbol criterion) -> void
331
+
332
+ def raise_if_criterion_unsupported: (Symbol criterion) -> void
333
+ end
334
+ end
335
+
336
+ # ----- configuration/eval_coverage -----
337
+
338
+ # The standalone eval-coverage toggle (`enable_coverage :eval`),
339
+ # instrumenting `eval`'d code on Rubies that support it. A boolean
340
+ # toggle, never a member of the enabled-criteria set.
341
+ module SimpleCov
342
+ module Configuration
343
+ def coverage_for_eval_supported?: () -> bool
344
+
345
+ def coverage_for_eval_enabled?: () -> bool
346
+
347
+ # DEPRECATED: use `enable_coverage :eval` instead.
348
+ def enable_coverage_for_eval: () -> void
349
+
350
+ private
351
+
352
+ def enable_eval_coverage: () -> void
353
+
354
+ def disable_eval_coverage: () -> void
355
+ end
356
+ end
357
+
358
+ # ----- configuration/coverage -----
359
+
360
+ # The criterion-first `coverage` configuration method: naming a
361
+ # criterion enables it, and every threshold is declared with the same
362
+ # syntax regardless of criterion.
363
+ #
364
+ # SimpleCov.start do
365
+ # coverage :line do
366
+ # minimum 90
367
+ # minimum_per_file 80
368
+ # minimum_per_file 100, only: "app/mailers/request_mailer.rb"
369
+ # maximum_drop 5
370
+ # end
371
+ #
372
+ # coverage :branch, minimum: 80
373
+ # end
374
+ module SimpleCov
375
+ module Configuration
376
+ # Members are minimum, maximum, exact, maximum_drop, and
377
+ # minimum_per_file (%i[] literals infer as Array[Symbol]).
378
+ COVERAGE_THRESHOLD_OPTIONS: Array[Symbol]
379
+
380
+ # Configure (and, unless `enabled: false`, enable) a coverage
381
+ # criterion. `primary: true` makes it the report's leading
382
+ # criterion; `oneshot: true` (only for `:line`) selects
383
+ # oneshot-lines mode. Threshold keywords mirror the block verbs
384
+ # for one-liner use. Returns the criterion symbol the thresholds
385
+ # were stored under.
386
+ # The threshold keywords (minimum:, maximum:, exact:, maximum_drop:,
387
+ # minimum_per_file:) arrive via **thresholds in the implementation, so
388
+ # they are typed as a Numeric kwarg splat. The block runs under
389
+ # instance_eval, which also yields the receiver as an optional argument.
390
+ def coverage: ((criterion | :eval) criterion, ?primary: bool, ?enabled: bool, ?oneshot: bool, **Numeric thresholds) ?{ (?CoverageCriterion) [self: CoverageCriterion] -> void } -> (criterion | :oneshot_line | :eval)
391
+
392
+ private
393
+
394
+ def apply_threshold_options: (CoverageCriterion configurator, Hash[Symbol, Numeric] options) -> void
395
+
396
+ def enable_coverage_criterion: ((criterion | :eval) criterion, enabled: bool, oneshot: bool) -> (criterion | :oneshot_line | :eval)
397
+
398
+ def resolve_criterion_variant: ((criterion | :eval) criterion, bool oneshot) -> (criterion | :oneshot_line | :eval)
399
+
400
+ # Threshold-store writers used by CoverageCriterion via `send`.
401
+ # They accept any criterion Symbol; `raise_on_invalid_coverage`
402
+ # rejects invalid ones (including `:eval`) at runtime.
403
+ def store_overall_threshold: (Symbol setting, Symbol criterion, Numeric percent) -> void
404
+
405
+ def store_minimum_per_file: (Symbol criterion, Numeric percent, (String | Regexp)? target) -> void
406
+
407
+ def store_minimum_per_group: (Symbol criterion, Numeric percent, String group_name) -> void
408
+
409
+ public
410
+
411
+ # Receiver for a `coverage <criterion> do ... end` block. Each verb
412
+ # writes a threshold for the single criterion the block configures,
413
+ # so values are always plain percentages.
414
+ class CoverageCriterion
415
+ @config: Configuration
416
+ @criterion: Symbol
417
+
418
+ def initialize: (Configuration config, Symbol criterion) -> void
419
+
420
+ # Overall (suite-wide) minimum for this criterion.
421
+ def minimum: (Numeric percent) -> void
422
+
423
+ # Overall maximum: fails the build if coverage rises above it.
424
+ def maximum: (Numeric percent) -> void
425
+
426
+ # Pin coverage to an exact figure (sets both minimum and maximum).
427
+ def exact: (Numeric percent) -> void
428
+
429
+ # Maximum allowed drop between runs (0 refuses any drop).
430
+ def maximum_drop: (Numeric percent) -> void
431
+
432
+ # Per-file minimum. With no `only:`, the default for every file;
433
+ # with `only:` (String path or Regexp), an override for matches.
434
+ def minimum_per_file: (Numeric percent, ?only: (String | Regexp)?) -> void
435
+
436
+ # Per-group minimum for the named group (defined via `group`).
437
+ def minimum_per_group: (Numeric percent, only: String) -> void
438
+
439
+ # Make this criterion the report's primary (leading) criterion.
440
+ def primary: () -> void
441
+ end
442
+ end
443
+ end
444
+
445
+ # ----- configuration/filters -----
446
+
447
+ # Inclusion / exclusion / grouping methods: `cover`, `skip`, `group`,
448
+ # plus the deprecated `track_files` / `add_filter` / `add_group` aliases.
449
+ module SimpleCov
450
+ module Configuration
451
+ attr_writer filters: Array[Filter[untyped]]
452
+
453
+ attr_writer groups: Hash[String, Filter[untyped]]
454
+
455
+ @cover_filters: Array[Filter[untyped]]?
456
+ @tracked_files: String?
457
+
458
+ # Restrict the report to files matching one or more shell globs,
459
+ # regexps, or block predicates. Multiple calls union. String globs
460
+ # are also expanded on disk so unloaded files appear at 0% coverage.
461
+ def cover: (*cover_arg args) ?{ (SourceFile source_file) -> boolish } -> Array[Filter[untyped]]
462
+
463
+ # The configured inclusion filters added via `cover`.
464
+ def cover_filters: () -> Array[Filter[untyped]]
465
+
466
+ # The string globs passed to `cover`, driving unloaded-file discovery.
467
+ def cover_globs: () -> Array[String]
468
+
469
+ # DEPRECATED: use `cover` instead.
470
+ def track_files: (String? glob) -> String?
471
+
472
+ def track_files_replacement_hint: (String? glob) -> String
473
+
474
+ # The glob used to include files that were not explicitly required.
475
+ def tracked_files: () -> String?
476
+
477
+ # The configured exclusion filters added via `skip` (or the
478
+ # deprecated `add_filter`).
479
+ def filters: () -> Array[Filter[untyped]]
480
+
481
+ # Drop matching files from the coverage report. The inverse of
482
+ # `cover`. Strings match at path-segment boundaries.
483
+ def skip: (?filter_arg? filter_argument) ?{ (SourceFile source_file) -> boolish } -> Array[Filter[untyped]]
484
+
485
+ # DEPRECATED: use `skip` instead (same arguments, same behavior).
486
+ def add_filter: (?filter_arg? filter_argument) ?{ (SourceFile source_file) -> boolish } -> Array[Filter[untyped]]
487
+
488
+ # Remove any filters whose `filter_argument` equals the given
489
+ # value. Returns true when at least one filter was removed.
490
+ def remove_filter: (untyped filter_argument) -> bool
491
+
492
+ # Remove every filter from the chain, including the defaults
493
+ # installed by `SimpleCov.start`.
494
+ def clear_filters: () -> Array[Filter[untyped]]
495
+
496
+ # The configured groups. Add groups using `group`.
497
+ def groups: () -> Hash[String, Filter[untyped]]
498
+
499
+ # Define a display group for files. Same matcher grammar as `skip`,
500
+ # but bins matches under `group_name` instead of dropping them.
501
+ def group: (String group_name, ?filter_arg? filter_argument) ?{ (SourceFile source_file) -> boolish } -> Filter[untyped]
502
+
503
+ # DEPRECATED: use `group` instead (same arguments, same behavior).
504
+ def add_group: (String group_name, ?filter_arg? filter_argument) ?{ (SourceFile source_file) -> boolish } -> Filter[untyped]
505
+
506
+ # Drop every previously installed filter (defaults included) so
507
+ # subsequent `skip` calls start from a clean slate.
508
+ def no_default_skips: () -> Array[Filter[untyped]]
509
+
510
+ private
511
+
512
+ def parse_filter: (?filter_arg? filter_argument) ?{ (SourceFile source_file) -> boolish } -> Filter[untyped]
513
+
514
+ def build_cover_filter: (cover_arg arg) -> Filter[untyped]
515
+
516
+ def collect_cover_globs: (Array[Filter[untyped]] filter_list) -> Array[String]
517
+ end
518
+ end
519
+
520
+ # ----- configuration/formatting -----
521
+
522
+ # Formatter selection (`formatter` / `formatters`), reporting toggles
523
+ # (`print_errors`, `color`, `source_in_json`), and the deprecated
524
+ # `# :nocov:` token hook.
525
+ module SimpleCov
526
+ module Configuration
527
+ # A formatter is a Class whose instances respond to `format(result)`
528
+ # (including the anonymous Class built by `MultiFormatter.new`).
529
+ attr_writer formatter: Class?
530
+
531
+ attr_writer print_error_status: bool
532
+
533
+ @color: bool | :auto
534
+ @source_in_json: bool
535
+ @nocov_token: String
536
+
537
+ # Gets or sets the configured formatter. Pass `false` (or `nil`) to
538
+ # opt out of formatting entirely (see #964).
539
+ def formatter: (?(Class | false | :__no_arg__)? formatter) -> Class?
540
+
541
+ # Gets the formatter chain, or sets it. Accepts an Array, a single
542
+ # formatter, or nil / `[]` to opt out of formatting entirely.
543
+ # Returns the passed value when setting.
544
+ def formatters: (?(Array[Class] | Class | :__no_arg__)? formatters) -> (Array[Class] | Class | nil)
545
+
546
+ # Sets the configured formatters (single formatters are wrapped;
547
+ # nil / `[]` opts out of formatting entirely).
548
+ def formatters=: ((Array[Class] | Class)? formatters) -> void
549
+
550
+ # Whether stderr diagnostics are colorized: `true`, `false`, or
551
+ # `:auto` (default — respects TTY, NO_COLOR, and FORCE_COLOR).
552
+ def color: (?(bool | :auto | :__no_arg__) value) -> (bool | :auto)
553
+
554
+ # Whether SimpleCov prints its own diagnostic warnings to stderr.
555
+ # Defaults to true.
556
+ def print_errors: (?(bool | :__no_arg__) value) -> bool
557
+
558
+ # Whether `coverage.json` embeds the full source text of every
559
+ # file. Defaults to true.
560
+ def source_in_json: (?(bool | :__no_arg__) value) -> bool
561
+
562
+ # DEPRECATED: use `print_errors` instead (same value).
563
+ def print_error_status: () -> bool
564
+
565
+ # DEPRECATED: use `# simplecov:disable` / `# simplecov:enable`
566
+ # directive comments instead of `# :nocov:` toggles.
567
+ def nocov_token: (?String? nocov_token) -> String
568
+
569
+ # DEPRECATED: alias for `nocov_token`.
570
+ alias skip_token nocov_token
571
+
572
+ def current_nocov_token: (?String? value) -> String
573
+ end
574
+ end
575
+
576
+ # ----- configuration/ignored_entries -----
577
+
578
+ # Coverage-entry filters scoped to branch / method criteria. See
579
+ # `ignore_branches` / `ignore_methods` and #1033 / #1046.
580
+ module SimpleCov
581
+ module Configuration
582
+ # Branch types accepted by `ignore_branches`: implicit_else and
583
+ # eval_generated (%i[] literals infer as Array[Symbol]).
584
+ IGNORABLE_BRANCH_TYPES: Array[Symbol]
585
+
586
+ # Method types accepted by `ignore_methods`: eval_generated (%i[]
587
+ # literals infer as Array[Symbol]).
588
+ IGNORABLE_METHOD_TYPES: Array[Symbol]
589
+
590
+ @ignored_branches: Array[Symbol]?
591
+ @ignored_methods: Array[Symbol]?
592
+
593
+ # Opt out of synthetic branch entries. Variadic; multiple calls
594
+ # union. Recorded even when branch coverage is not (yet) enabled.
595
+ def ignore_branches: (*(:implicit_else | :eval_generated) types) -> Array[Symbol]
596
+
597
+ def ignored_branches: () -> Array[Symbol]
598
+
599
+ def ignored_branch?: (Symbol type) -> bool
600
+
601
+ # Opt out of synthetic method entries (currently `:eval_generated` only).
602
+ def ignore_methods: (*:eval_generated types) -> Array[Symbol]
603
+
604
+ def ignored_methods: () -> Array[Symbol]
605
+
606
+ def ignored_method?: (Symbol type) -> bool
607
+
608
+ private
609
+
610
+ def raise_if_branch_type_unsupported: (Symbol type) -> void
611
+
612
+ def raise_if_method_type_unsupported: (Symbol type) -> void
613
+ end
614
+ end
615
+
616
+ # ----- configuration/merging -----
617
+
618
+ # Result merging and subprocess / parallel-test coordination:
619
+ # `merging`, `merge_subprocesses`, `merge_timeout`, `finalize_merge`,
620
+ # `parallel_tests`, `parallel_wait_timeout`.
621
+ module SimpleCov
622
+ module Configuration
623
+ # `defined?`-guarded module state. Declared non-nil where every
624
+ # read is guarded, so readers don't have to refute a nil that
625
+ # cannot be observed.
626
+ @enable_for_subprocesses: bool
627
+ @parallel_tests: bool?
628
+ @use_merging: bool
629
+ @finalize_merge: bool
630
+ @finalize_merge_explicit: bool
631
+ @finalize_merge_inference_warned: bool
632
+ @merge_timeout: Integer?
633
+ @parallel_wait_timeout: Integer?
634
+
635
+ # Get or set whether SimpleCov hooks `Process._fork` to attach
636
+ # itself to subprocesses (e.g. Rails' `parallelize(workers:)`).
637
+ # Defaults to false.
638
+ def merge_subprocesses: (?bool? value) -> bool
639
+
640
+ def enabled_for_subprocesses?: () -> bool
641
+
642
+ # Get or set whether SimpleCov auto-requires the `parallel_tests`
643
+ # gem when it sees its environment variables. nil (the default)
644
+ # means auto-detect. See #1018.
645
+ def parallel_tests: (?(:__no_arg__ | bool)? value) -> bool?
646
+
647
+ # DEPRECATED: use `merge_subprocesses` instead (same value).
648
+ def enable_for_subprocesses: (?bool? value) -> bool
649
+
650
+ # Get or set whether to merge results from multiple test suites
651
+ # into a single coverage report. Defaults to true.
652
+ def merging: (?bool? use) -> bool
653
+
654
+ # Get or set whether SimpleCov's selected final process owns merge processing:
655
+ # waiting for sibling workers, merging, formatting, enforcing
656
+ # thresholds, and writing `.last_run.json`. Defaults to true except
657
+ # for recognized multi-worker parallel runs writing to a custom
658
+ # coverage destination (those likely finalize via an external
659
+ # `SimpleCov.collate` step). See #1215.
660
+ def finalize_merge: (?(:__no_arg__ | bool) value) -> bool
661
+
662
+ def finalize_merge?: () -> bool
663
+
664
+ def merge_finalization_owner?: () -> boolish
665
+
666
+ # DEPRECATED: use `merging` instead (same value, same behavior).
667
+ # Returns nil when merging had already been disabled.
668
+ def use_merging: (?bool? use) -> bool
669
+
670
+ # The maximum age (in seconds) of a resultset to still be included
671
+ # in merged results. Defaults to 600.
672
+ def merge_timeout: (?Integer? seconds) -> Integer
673
+
674
+ # How long (in seconds) the reporting process waits for remaining
675
+ # parallel-test workers to write their resultsets before it
676
+ # proceeds with a partial merge. Defaults to 60. See #1171.
677
+ def parallel_wait_timeout: (?Integer? seconds) -> Integer
678
+
679
+ private
680
+
681
+ def inferred_finalize_merge?: () -> bool
682
+
683
+ def parallel_worker_environment?: () -> bool
684
+
685
+ def explicit_custom_coverage_destination?: () -> bool
686
+
687
+ def explicit_coverage_destination?: () -> boolish
688
+
689
+ def warn_about_inferred_finalize_merge: () -> void
690
+
691
+ def inferred_finalize_merge_warning: () -> String
692
+
693
+ # Host contract: defined on SimpleCov itself (result_processing.rb).
694
+ # This module is only ever extended onto SimpleCov, where both methods
695
+ # are available to `merge_finalization_owner?`.
696
+ def collating_result?: () -> boolish
697
+
698
+ def final_result_process?: () -> boolish
699
+ end
700
+ end
701
+
702
+ # ----- configuration/thresholds -----
703
+
704
+ # Coverage threshold configuration: `minimum_coverage`,
705
+ # `maximum_coverage`, `expected_coverage`, `maximum_coverage_drop`,
706
+ # `refuse_coverage_drop`, and the deprecated by-file / by-group forms.
707
+ module SimpleCov
708
+ module Configuration
709
+ # Thresholds are stored per criterion; a bare Numeric argument is
710
+ # normalized to `{primary_coverage => value}`. Keys are criterion
711
+ # symbols — Symbol rather than the `criterion` alias because the
712
+ # stores also carry `:oneshot_line`, and the validating setters are
713
+ # the layer that rejects unknown symbols (with ConfigurationError).
714
+ type coverage_thresholds = Hash[Symbol, Numeric]
715
+
716
+ @minimum_coverage: coverage_thresholds?
717
+ @maximum_coverage: coverage_thresholds?
718
+ @maximum_coverage_drop: coverage_thresholds?
719
+ @minimum_coverage_by_file: coverage_thresholds?
720
+ @minimum_coverage_by_file_overrides: Hash[String | Regexp, coverage_thresholds]?
721
+ @minimum_coverage_by_group: Hash[String, coverage_thresholds]?
722
+
723
+ # The minimum overall coverage required for the suite to pass.
724
+ # Default: none (0%, disabled).
725
+ def minimum_coverage: (?(Numeric | coverage_thresholds)? coverage) -> coverage_thresholds
726
+
727
+ def raise_on_invalid_coverage: (coverage_thresholds coverage, String coverage_setting) -> void
728
+
729
+ # The maximum overall coverage allowed — an unexpected jump above
730
+ # it fails the build. Pair with `minimum_coverage` (or use
731
+ # `expected_coverage`) to pin coverage. See #187.
732
+ def maximum_coverage: (?(Numeric | coverage_thresholds)? coverage) -> coverage_thresholds
733
+
734
+ # Pin the suite to an exact figure: sets both `minimum_coverage`
735
+ # and `maximum_coverage`. See #187.
736
+ def expected_coverage: (?(Numeric | coverage_thresholds)? coverage) -> coverage_thresholds
737
+
738
+ # The maximum coverage drop between runs allowed for the suite to
739
+ # pass. Default: none (100%, disabled).
740
+ def maximum_coverage_drop: (?(Numeric | coverage_thresholds)? coverage_drop) -> coverage_thresholds
741
+
742
+ # DEPRECATED: use `coverage(criterion) { minimum_per_file ... }`.
743
+ # Symbol keys declare per-criterion defaults; String / Regexp keys
744
+ # declare per-path overrides.
745
+ def minimum_coverage_by_file: () -> coverage_thresholds
746
+ | ((Numeric | Hash[Symbol | String | Regexp, Numeric | coverage_thresholds]) coverage) -> Hash[String | Regexp, coverage_thresholds]
747
+
748
+ # The per-path overrides set via `minimum_coverage_by_file` (or
749
+ # `coverage(criterion) { minimum_per_file N, only: ... }`).
750
+ def minimum_coverage_by_file_overrides: () -> Hash[String | Regexp, coverage_thresholds]
751
+
752
+ # DEPRECATED: use `coverage(criterion) { minimum_per_group ... }`.
753
+ def minimum_coverage_by_group: () -> Hash[String, coverage_thresholds]
754
+ | (Hash[String, Numeric | coverage_thresholds] coverage) -> Hash[String, coverage_thresholds]
755
+
756
+ # Refuse any coverage drop for the given criteria (all enabled
757
+ # criteria when none are given). Coverage may only increase.
758
+ def refuse_coverage_drop: (*(criterion | :oneshot_line) criteria) -> coverage_thresholds
759
+
760
+ private
761
+
762
+ # Shared normalize-and-validate step behind every threshold setter.
763
+ def normalized_threshold: ((Numeric | coverage_thresholds) coverage, String setting) -> coverage_thresholds
764
+
765
+ def partition_per_file_thresholds: (Hash[Symbol | String | Regexp, Numeric | coverage_thresholds] coverage) -> [coverage_thresholds, Hash[String | Regexp, coverage_thresholds]]
766
+
767
+ def validate_per_file_key: ((Symbol | String | Regexp) key) -> void
768
+
769
+ def minimum_possible_coverage_exceeded: (String coverage_option) -> void
770
+
771
+ def per_file_coverage_replacement: (coverage_thresholds defaults, Hash[String | Regexp, coverage_thresholds] overrides) -> String
772
+
773
+ def per_group_coverage_replacement: (Hash[String, Numeric | coverage_thresholds] coverage) -> String
774
+
775
+ def render_coverage_blocks: (Hash[Symbol, Array[String]] by_criterion) -> String
776
+ end
777
+ end
778
+
779
+ # ----- result -----
780
+
781
+ module SimpleCov
782
+ # A coverage result built from the Hash Ruby's Coverage library
783
+ # produces: filename => per-criterion coverage data.
784
+ class Result
785
+ extend Forwardable
786
+
787
+ attr_reader original_result: Hash[String, untyped]
788
+
789
+ # Every path the producing process was told to track, loaded or not.
790
+ attr_reader tracked_files: Array[String]
791
+ attr_reader run_id: String?
792
+ attr_reader worker_id: String?
793
+ attr_reader files: FileList
794
+ alias source_files files
795
+ # The writers accept the strict types; the ivars stay nilable because
796
+ # both default to nil and are lazily backfilled by the readers.
797
+ attr_writer created_at (): Time
798
+ attr_writer command_name (): String
799
+
800
+ @created_at: Time?
801
+ @command_name: String?
802
+ @groups_config: Hash[String, Filter[untyped]]
803
+ @groups: Hash[String, FileList]?
804
+
805
+ # Bundles filter and grouping configuration. Every field defaults to
806
+ # the SimpleCov singleton's configuration; tests pass a custom
807
+ # instance (e.g. `filters: []`) to opt out.
808
+ class FilterConfig
809
+ attr_reader filters: Array[Filter[untyped]]
810
+ attr_reader cover_filters: Array[Filter[untyped]]
811
+ attr_reader groups: Hash[String, Filter[untyped]]
812
+
813
+ def initialize: (?filters: Array[Filter[untyped]], ?cover_filters: Array[Filter[untyped]], ?groups: Hash[String, Filter[untyped]]) -> void
814
+ end
815
+
816
+ def initialize: (Hash[String, untyped] original_result, ?command_name: String?, ?created_at: Time?, ?not_loaded_files: Set[String], ?tracked_files: _ToA[String], ?run_id: String?, ?worker_id: String?, ?report: bool, ?filter_config: FilterConfig) -> void
817
+
818
+ def filenames: () -> Array[String]
819
+ # Accepts an absolute or project-relative path (resolved against SimpleCov.root).
820
+ def source_file_for: (String path) -> SourceFile?
821
+ def coverage_for: (String path) -> Hash[criterion, CoverageStatistics]?
822
+ def groups: () -> Hash[String, FileList]
823
+ # Returns nil when formatting is opted out of (`formatter false` /
824
+ # `formatters []`); otherwise whatever the configured formatter returns.
825
+ def format!: () -> untyped
826
+ def created_at: () -> Time
827
+ def command_name: () -> String
828
+ def to_hash: () -> Hash[String, Hash[String, untyped]]
829
+ def self.from_hash: (Hash[String, untyped] hash) -> Array[Result]
830
+
831
+ # Delegated to #files (see FileList).
832
+ def covered_percent: (?criterion) -> Float?
833
+ def covered_percentages: () -> Array[Float?]
834
+ def least_covered_file: () -> String?
835
+ def covered_strength: (?criterion) -> Float?
836
+ def covered_lines: () -> Integer?
837
+ def missed_lines: () -> Integer?
838
+ def total_branches: () -> Integer?
839
+ def covered_branches: () -> Integer?
840
+ def missed_branches: () -> Integer?
841
+ def total_methods: () -> Integer?
842
+ def covered_methods: () -> Integer?
843
+ def missed_methods: () -> Integer?
844
+ def coverage_statistics: () -> Hash[criterion, CoverageStatistics]
845
+ | (criterion) -> CoverageStatistics?
846
+ def coverage_statistics_by_file: () -> Hash[criterion, Array[CoverageStatistics]]
847
+ def total_lines: () -> Integer?
848
+
849
+ private
850
+
851
+ def initialize_coordination_metadata: (_ToA[String] tracked_files, String? run_id, String? worker_id) -> void
852
+ def warn_about_missing_source_files: (Array[String] missing, Integer input_size) -> void
853
+ def coverage: () -> Hash[String, untyped]
854
+ def apply_filters!: (Array[Filter[untyped]] filters) -> void
855
+ def apply_cover_filters!: (Array[Filter[untyped]] cover_filters) -> void
856
+ end
857
+ end
858
+
859
+ # ----- file_list -----
860
+
861
+ module SimpleCov
862
+ # An Enumerable of SourceFile instances with aggregate coverage
863
+ # helpers. Aggregate readers return nil when the corresponding
864
+ # criterion was not enabled for the run.
865
+ class FileList
866
+ include Enumerable[SimpleCov::SourceFile]
867
+ extend Forwardable
868
+
869
+ def initialize: (Array[SourceFile] files) -> void
870
+
871
+ @files: Array[SourceFile]
872
+ @coverage_statistics: Hash[criterion, CoverageStatistics]?
873
+ @coverage_statistics_by_file: Hash[criterion, Array[CoverageStatistics]]?
874
+
875
+ # Delegated to the underlying Array.
876
+ def each: () { (SourceFile) -> void } -> void
877
+ | () -> Enumerator[SourceFile, untyped]
878
+ def size: () -> Integer
879
+ def length: () -> Integer
880
+ def map: [U] () { (SourceFile) -> U } -> Array[U]
881
+ def count: () -> Integer
882
+ | (untyped) -> Integer
883
+ | () { (SourceFile) -> boolish } -> Integer
884
+ def empty?: () -> bool
885
+ def to_a: () -> Array[SourceFile]
886
+ def to_ary: () -> Array[SourceFile]
887
+
888
+ def coverage_statistics: () -> Hash[criterion, CoverageStatistics]
889
+ | (criterion) -> CoverageStatistics?
890
+ def coverage_statistics_by_file: () -> Hash[criterion, Array[CoverageStatistics]]
891
+
892
+ def covered_lines: () -> Integer?
893
+ def missed_lines: () -> Integer?
894
+ def never_lines: () -> Integer
895
+ def skipped_lines: () -> Integer
896
+ def covered_percentages: () -> Array[Float?]
897
+ def least_covered_file: () -> String?
898
+ def lines_of_code: () -> Integer?
899
+ def covered_percent: (?criterion) -> Float?
900
+ def covered_strength: (?criterion) -> Float?
901
+
902
+ def total_branches: () -> Integer?
903
+ def covered_branches: () -> Integer?
904
+ def missed_branches: () -> Integer?
905
+ def branch_covered_percent: () -> Float?
906
+
907
+ def total_methods: () -> Integer?
908
+ def covered_methods: () -> Integer?
909
+ def missed_methods: () -> Integer?
910
+ def method_covered_percent: () -> Float?
911
+
912
+ private
913
+
914
+ def compute_coverage_statistics_by_file: () -> Hash[criterion, Array[CoverageStatistics]]
915
+ def compute_coverage_statistics: () -> Hash[criterion, CoverageStatistics]
916
+ def enabled_criteria_for_reporting: () -> Array[criterion]
917
+ end
918
+ end
919
+
920
+ # ----- source_file -----
921
+
922
+ module SimpleCov
923
+ # A source file with its coverage data, source lines, and helpers to
924
+ # interpret that data.
925
+ class SourceFile
926
+ include BuilderContext
927
+
928
+ # Full absolute path to the file.
929
+ attr_reader filename: String
930
+ # Coverage.result-shaped data for this file, e.g.
931
+ # {"lines" => [...], "branches" => {...}, "methods" => {...}}.
932
+ attr_reader coverage_data: Hash[String, untyped]
933
+
934
+ def initialize: (String filename, Hash[String, untyped] coverage_data, ?loaded: bool) -> void
935
+
936
+ # Memoization backing for the lazy readers below.
937
+ @loaded: bool
938
+ @src: Array[String]?
939
+ @coverage_statistics: Hash[criterion, CoverageStatistics]?
940
+ @lines: Array[Line]?
941
+ @covered_lines: Array[Line]?
942
+ @missed_lines: Array[Line]?
943
+ @never_lines: Array[Line]?
944
+ @skipped_lines: Array[Line]?
945
+ @branches: Array[Branch]?
946
+ @total_branches: Array[Branch]?
947
+ @branches_report: Hash[Integer, Array[[ Symbol, Integer ]]]?
948
+ @covered_branches: Array[Branch]?
949
+ @missed_branches: Array[Branch]?
950
+ @methods: Array[Method]?
951
+ @covered_methods: Array[Method]?
952
+ @missed_methods: Array[Method]?
953
+
954
+ # Project-relative path with no leading separator (e.g. "lib/foo.rb").
955
+ def project_filename: () -> String
956
+ # Source lines, read lazily.
957
+ def src: () -> Array[String]
958
+ alias source src
959
+
960
+ # With no argument returns a Hash keyed by every supported criterion
961
+ # (disabled criteria collapse to 0/0/0); pass a criterion to get that
962
+ # one CoverageStatistics.
963
+ def coverage_statistics: () -> Hash[criterion, CoverageStatistics]
964
+ | (criterion) -> CoverageStatistics?
965
+
966
+ def lines: () -> Array[Line]
967
+ alias source_lines lines
968
+ def covered_lines: () -> Array[Line]
969
+ def missed_lines: () -> Array[Line]
970
+ def never_lines: () -> Array[Line]
971
+ def skipped_lines: () -> Array[Line]
972
+ def lines_of_code: () -> Integer
973
+ # 1-based line lookup.
974
+ def line: (Integer number) -> Line?
975
+ def covered_percent: (?criterion) -> Float?
976
+ def covered_strength: (?criterion) -> Float?
977
+ def no_lines?: () -> bool
978
+ def relevant_lines: () -> Integer
979
+
980
+ def branches: () -> Array[Branch]
981
+ def no_branches?: () -> bool
982
+ # DEPRECATED: use `covered_percent(:branch)`.
983
+ def branches_coverage_percent: () -> Float?
984
+ # All relevant (covered + missed) branches, not a count.
985
+ def total_branches: () -> Array[Branch]
986
+ # line number => Array of [branch type, hit count] pairs.
987
+ def branches_report: () -> Hash[Integer, Array[[ Symbol, Integer ]]]
988
+ def covered_branches: () -> Array[Branch]
989
+ def missed_branches: () -> Array[Branch]
990
+ def branches_for_line: (Integer line_number) -> Array[[ Symbol, Integer ]]
991
+ def line_with_missed_branch?: (Integer line_number) -> bool
992
+
993
+ def methods: () -> Array[Method]
994
+ def covered_methods: () -> Array[Method]
995
+ def missed_methods: () -> Array[Method]
996
+ # DEPRECATED: use `covered_percent(:method)`.
997
+ def methods_coverage_percent: () -> Float?
998
+
999
+ # Whether this file was added via `cover` / `track_files` but never
1000
+ # loaded during the run.
1001
+ def not_loaded?: () -> bool
1002
+ end
1003
+ end
1004
+
1005
+ # ----- source_file/line -----
1006
+
1007
+ module SimpleCov
1008
+ class SourceFile
1009
+ # A single source line with its coverage: nil (not relevant, e.g. a
1010
+ # comment), 0 (missed), or >= 1 (times executed).
1011
+ class Line
1012
+ attr_reader src: String
1013
+ attr_reader line_number: Integer
1014
+ attr_reader coverage: Integer?
1015
+ attr_reader skipped: bool
1016
+
1017
+ alias source src
1018
+ alias line line_number
1019
+ alias number line_number
1020
+
1021
+ # Raises ArgumentError unless src is a String, line_number an
1022
+ # Integer, and coverage an Integer or nil.
1023
+ def initialize: (String src, Integer line_number, Integer? coverage) -> void
1024
+
1025
+ def missed?: () -> bool
1026
+ def covered?: () -> bool
1027
+ def never?: () -> bool
1028
+ def skipped!: () -> void
1029
+ def skipped?: () -> bool
1030
+ # "covered", "missed", "skipped", or "never" — useful e.g. as a css class.
1031
+ def status: () -> String?
1032
+ end
1033
+ end
1034
+ end
1035
+
1036
+ # ----- source_file/branch -----
1037
+
1038
+ module SimpleCov
1039
+ class SourceFile
1040
+ # A single branch detected in the coverage data.
1041
+ class Branch
1042
+ attr_reader start_line: Integer
1043
+ attr_reader end_line: Integer
1044
+ attr_reader coverage: Integer
1045
+ # Branch arm type as reported by Coverage (:then, :else, :when, ...).
1046
+ attr_reader type: Symbol
1047
+
1048
+ @inline: bool
1049
+ @skipped: bool
1050
+
1051
+ def initialize: (start_line: Integer, end_line: Integer, coverage: Integer, inline: bool, type: Symbol) -> void
1052
+
1053
+ def inline?: () -> bool
1054
+ def covered?: () -> bool
1055
+ def missed?: () -> bool
1056
+ # The line the branch is reported on: its own start line when
1057
+ # inline, otherwise the line above (the if/else itself).
1058
+ def report_line: () -> Integer
1059
+ def skipped!: () -> void
1060
+ def skipped?: () -> bool
1061
+ def overlaps_with?: (Range[Integer] line_range) -> bool
1062
+ # [branch type, hit count]
1063
+ def report: () -> [ Symbol, Integer ]
1064
+ end
1065
+ end
1066
+ end
1067
+
1068
+ # ----- source_file/method -----
1069
+
1070
+ module SimpleCov
1071
+ class SourceFile
1072
+ # A single method detected in the coverage data.
1073
+ class Method
1074
+ attr_reader source_file: SourceFile
1075
+ attr_reader coverage: Integer
1076
+ # A Module when the data comes straight from Coverage, a String
1077
+ # after a JSON round-trip through a resultset.
1078
+ attr_reader class_name: Module | String
1079
+ attr_reader method_name: Symbol | String
1080
+ attr_reader start_line: Integer?
1081
+ attr_reader start_col: Integer?
1082
+ attr_reader end_line: Integer?
1083
+ attr_reader end_col: Integer?
1084
+
1085
+ @skipped: bool
1086
+ @lines: Array[Line]?
1087
+
1088
+ # info is the Coverage method key minus its class entry:
1089
+ # [class_name, method_name, start_line, start_col, end_line, end_col].
1090
+ def initialize: (SourceFile source_file, [ Module | String, Symbol | String, Integer?, Integer?, Integer?, Integer? ] info, Integer coverage) -> void
1091
+
1092
+ def covered?: () -> bool
1093
+ def skipped?: () -> bool
1094
+ def skipped!: () -> void
1095
+ def missed?: () -> bool
1096
+ # The source lines spanned by this method ([] when the location is unknown).
1097
+ def lines: () -> Array[Line]
1098
+ def overlaps_with?: (Range[Integer] line_range) -> bool
1099
+ def to_s: () -> String
1100
+ end
1101
+ end
1102
+ end
1103
+
1104
+ # ----- source_file/statistics -----
1105
+
1106
+ module SimpleCov
1107
+ class SourceFile
1108
+ # Builds the CoverageStatistics triple (:line/:branch/:method) for a
1109
+ # SourceFile; disabled or empty criteria collapse to 0/0/0.
1110
+ class Statistics
1111
+ @source_file: SourceFile
1112
+
1113
+ def initialize: (SourceFile source_file) -> void
1114
+
1115
+ def call: () -> Hash[criterion, CoverageStatistics]
1116
+
1117
+ private
1118
+
1119
+ def line_statistics: () -> Hash[criterion, CoverageStatistics]
1120
+
1121
+ def branch_statistics: () -> Hash[criterion, CoverageStatistics]
1122
+
1123
+ def method_statistics: () -> Hash[criterion, CoverageStatistics]
1124
+
1125
+ def coverage_statistics: (Array[Line | Branch | Method] covered, Array[Line | Branch | Method] missed, ?omitted: Integer, ?percent: Float?) -> CoverageStatistics
1126
+ end
1127
+ end
1128
+ end
1129
+
1130
+ # ----- source_file/builder_context -----
1131
+
1132
+ module SimpleCov
1133
+ class SourceFile
1134
+ # Helpers shared by the per-criterion builders (LineBuilder /
1135
+ # BranchBuilder / MethodBuilder). Mixed into SourceFile so each
1136
+ # builder can ask the file for its skip-chunk ranges and Prism-derived
1137
+ # real source positions without duplicating the memoization.
1138
+ module BuilderContext
1139
+ # Positions extracted from the parsed source: branch start lines,
1140
+ # and [method name, line] pairs. Method names are Symbols from
1141
+ # runtime data and Strings after a JSON round-trip.
1142
+ type real_positions = { branches: Set[Integer], methods: Set[[untyped, Integer]] }
1143
+
1144
+ @skip_chunks: SkipChunks?
1145
+ @real_source_positions: real_positions?
1146
+
1147
+ # Skip-chunk lookup for the named criterion (`:line`, `:branch`,
1148
+ # `:method`).
1149
+ def skip_chunks_for: (criterion) -> Array[Range[Integer]]
1150
+
1151
+ # Memoized set of real source positions extracted via Prism. Returns
1152
+ # nil when Prism is unavailable or parsing fails, signaling callers
1153
+ # to keep every Coverage entry (no false drops). The `defined?`
1154
+ # guard preserves a nil memoization across calls.
1155
+ def real_source_positions: () -> real_positions?
1156
+
1157
+ # Provided by the including class (SourceFile).
1158
+ def filename: () -> String
1159
+ def src: () -> Array[String]
1160
+ end
1161
+ end
1162
+ end
1163
+
1164
+ # ----- coverage_statistics -----
1165
+
1166
+ module SimpleCov
1167
+ # Uniform per-criterion coverage statistics. Counts are Integers;
1168
+ # percent and strength are Floats. `percent` is 100.0 whenever nothing
1169
+ # was missed, including the 0-of-0 case; `strength` is 0.0 when there
1170
+ # is nothing to cover.
1171
+ class CoverageStatistics
1172
+ # Seed for the reduce in .from: covered, missed, omitted, strength.
1173
+ ZERO_STATS: [Integer, Integer, Integer, Float]
1174
+
1175
+ attr_reader total: Integer
1176
+ attr_reader covered: Integer
1177
+ attr_reader missed: Integer
1178
+ attr_reader omitted: Integer
1179
+ attr_reader strength: Float
1180
+ attr_reader percent: Float
1181
+
1182
+ def self.from: (Array[CoverageStatistics] coverage_statistics) -> CoverageStatistics
1183
+
1184
+ # `percent:` overrides the computed percentage (used to report 0%
1185
+ # for tracked-but-never-loaded files).
1186
+ def initialize: (covered: Integer, missed: Integer, ?omitted: Integer, ?total_strength: Integer | Float, ?percent: Float?) -> void
1187
+
1188
+ private
1189
+
1190
+ def compute_percent: (Integer covered, Integer missed, Integer total) -> Float
1191
+ def compute_strength: (Integer | Float total_strength, Integer total) -> Float
1192
+ end
1193
+ end
1194
+
1195
+ # ----- last_run -----
1196
+
1197
+ module SimpleCov
1198
+ # Reads and writes coverage/.last_run.json — the previous run's
1199
+ # coverage percentages used by MaximumCoverageDropCheck.
1200
+ module LastRun
1201
+ def self.last_run_path: () -> String
1202
+
1203
+ # nil when the file does not exist, is blank, or does not hold a
1204
+ # JSON object. Keys are symbolized.
1205
+ def self.read: () -> Hash[Symbol, untyped]?
1206
+
1207
+ def self.write: (Hash[Symbol, untyped] json) -> void
1208
+
1209
+ def self.invalid_last_run: () -> nil
1210
+ end
1211
+ end
1212
+
1213
+ # ----- filter -----
1214
+
1215
+ module SimpleCov
1216
+ # Base filter class. Inherit and override `matches?` to create custom
1217
+ # filters. `T` is the type of the configured filter argument.
1218
+ class Filter[T]
1219
+ attr_reader filter_argument: T
1220
+
1221
+ def initialize: (T filter_argument) -> void
1222
+
1223
+ # The base implementation raises NotImplementedError.
1224
+ def matches?: (SourceFile source_file) -> boolish
1225
+
1226
+ # Whether the verdict depends only on the path, so it can be decided
1227
+ # before the file has any coverage.
1228
+ def path_only?: () -> bool
1229
+
1230
+ def self.build_filter: (filter_arg filter_argument, ?string_filter: singleton(Filter)) -> Filter[untyped]
1231
+
1232
+ def self.class_for_argument: (filter_arg filter_argument) -> singleton(Filter)
1233
+
1234
+ # Maps raw filter-argument classes (String, Regexp, Array, Proc) to
1235
+ # the Filter subclass that handles them. Private class method.
1236
+ self.@filter_classes_by_argument_type: Hash[Class, singleton(Filter)]?
1237
+
1238
+ def self.filter_classes_by_argument_type: () -> Hash[Class, singleton(Filter)]
1239
+ end
1240
+
1241
+ # Matches when the project path contains the configured string at a
1242
+ # path-segment boundary ("lib" matches "lib/foo.rb" but not "library/").
1243
+ class StringFilter < Filter[String]
1244
+ def matches?: (SourceFile source_file) -> bool
1245
+
1246
+ # Whether the verdict depends only on the path, so it can be decided
1247
+ # before the file has any coverage.
1248
+ def path_only?: () -> bool
1249
+
1250
+ private
1251
+
1252
+ @segment_pattern: Regexp?
1253
+
1254
+ def segment_pattern: () -> Regexp
1255
+
1256
+ def compute_segment_pattern: () -> Regexp
1257
+ end
1258
+
1259
+ # Matches when the project path matches the configured Regexp.
1260
+ class RegexFilter < Filter[Regexp]
1261
+ def matches?: (SourceFile source_file) -> bool
1262
+
1263
+ # Whether the verdict depends only on the path, so it can be decided
1264
+ # before the file has any coverage.
1265
+ def path_only?: () -> bool
1266
+ end
1267
+
1268
+ # Matches when the configured block returns truthy for the source file.
1269
+ class BlockFilter < Filter[^(SourceFile) -> boolish]
1270
+ def matches?: (SourceFile source_file) -> boolish
1271
+
1272
+ # Whether the verdict depends only on the path, so it can be decided
1273
+ # before the file has any coverage.
1274
+ def path_only?: () -> bool
1275
+ end
1276
+
1277
+ # Matches when the project path matches the configured shell glob
1278
+ # (e.g. "lib/**/*.rb").
1279
+ class GlobFilter < Filter[String]
1280
+ def matches?: (SourceFile source_file) -> bool
1281
+
1282
+ # Whether the verdict depends only on the path, so it can be decided
1283
+ # before the file has any coverage.
1284
+ def path_only?: () -> bool
1285
+ end
1286
+
1287
+ # Matches when any of the component filters built from the array's
1288
+ # elements match. Note: `filter_argument` holds the built Filter
1289
+ # objects, not the raw array passed to `new`.
1290
+ class ArrayFilter < Filter[Array[Filter[untyped]]]
1291
+ def initialize: (Array[filter_arg] filter_argument) -> void
1292
+
1293
+ def matches?: (SourceFile source_file) -> boolish
1294
+
1295
+ # Whether the verdict depends only on the path, so it can be decided
1296
+ # before the file has any coverage.
1297
+ def path_only?: () -> bool
1298
+ end
1299
+ end
1300
+
1301
+ # ----- formatter -----
1302
+
1303
+ module SimpleCov
1304
+ # Namespace for result formatters. A formatter is any class whose
1305
+ # instances respond to `#format(result)` and that can be instantiated
1306
+ # with no arguments, or a ready-built instance responding to
1307
+ # `#format(result)`; wire one up via `SimpleCov.formatter=` or
1308
+ # `SimpleCov.formatters=`.
1309
+ module Formatter
1310
+ # Structural interface for custom formatter instances.
1311
+ interface _Formatter
1312
+ def format: (SimpleCov::Result result) -> untyped
1313
+ end
1314
+
1315
+ # Normalizes a configured formatter — class or ready-built
1316
+ # instance — into an instance. See #1240.
1317
+ def self.instance_for: (untyped formatter) -> untyped
1318
+
1319
+ # Instantiates a formatter class when necessary and dispatches the result.
1320
+ def self.format: (untyped formatter, SimpleCov::Result result) -> untyped
1321
+ end
1322
+ end
1323
+
1324
+ # ----- formatter/base -----
1325
+
1326
+ module SimpleCov
1327
+ module Formatter
1328
+ # @api private — shared scaffolding for formatters that write a
1329
+ # report to an output directory and emit the "Coverage report
1330
+ # generated for X to Y" status line on stderr. Subclasses implement
1331
+ # `format`.
1332
+ class Base
1333
+ @silent: bool
1334
+ @output_dir: String?
1335
+
1336
+ # `output_dir` defaults to `SimpleCov.coverage_path` when nil.
1337
+ def initialize: (?silent: bool, ?output_dir: String?) -> void
1338
+
1339
+ private
1340
+
1341
+ # Subclasses prepend a marker (e.g. "JSON ") to the summary line.
1342
+ def message_prefix: () -> String
1343
+
1344
+ def output_path: () -> String
1345
+
1346
+ # Directory (relative to cwd when inside it) plus the subclass's
1347
+ # `entry_point_filename`, for the status line. See issue #197.
1348
+ def displayable_output_path: () -> String
1349
+
1350
+ def relative_or_absolute_output_path: () -> String
1351
+
1352
+ # Subclasses name the report's entry-point file (`index.html`,
1353
+ # `coverage.json`); nil leaves the bare directory in the status line.
1354
+ def entry_point_filename: () -> String?
1355
+
1356
+ # Prints `output_message` to stderr unless silent; the one home of
1357
+ # the "status lines go to stderr, not through warn" decision (#1225).
1358
+ def emit_status: (SimpleCov::Result result) -> void
1359
+
1360
+ def output_message: (SimpleCov::Result result) -> String
1361
+
1362
+ # nil for branch/method criteria with nothing to measure, so the
1363
+ # summary doesn't print "Branch coverage: 0 / 0 (100.00%)" noise.
1364
+ def stats_line: (Symbol criterion, SimpleCov::CoverageStatistics stat) -> String?
1365
+ end
1366
+ end
1367
+ end
1368
+
1369
+ # ----- formatter/simple_formatter -----
1370
+
1371
+ module SimpleCov
1372
+ module Formatter
1373
+ # Renders the result as a plain-text string, one section per group.
1374
+ # Returns the string; does not write anything to disk.
1375
+ class SimpleFormatter
1376
+ def format: (SimpleCov::Result result) -> String
1377
+
1378
+ private
1379
+
1380
+ def format_group: (String name, SimpleCov::FileList files, SimpleCov::criterion criterion) -> String
1381
+ end
1382
+ end
1383
+ end
1384
+
1385
+ # ----- formatter/multi_formatter -----
1386
+
1387
+ module SimpleCov
1388
+ module Formatter
1389
+ # Wraps multiple formatters so one configured formatter can drive
1390
+ # several output formats (HTML + JSON, etc.) in a single run.
1391
+ class MultiFormatter
1392
+ # Shared `#format` implementation, included into the anonymous
1393
+ # classes that `MultiFormatter.new` builds. Formatter errors are
1394
+ # rescued and mapped to nil, so the result array can hold nils.
1395
+ module InstanceMethods
1396
+ def format: (SimpleCov::Result result) -> Array[untyped]
1397
+
1398
+ # Defined via `define_method` on each class `MultiFormatter.new`
1399
+ # builds; declared here so users of those classes type-check.
1400
+ def formatters: () -> Array[untyped]
1401
+ end
1402
+
1403
+ # Returns a newly built Class (not a MultiFormatter instance) whose
1404
+ # instances respond to `#format` and `#formatters`. The argument is
1405
+ # normalized with `Array()`: a single formatter, an array of
1406
+ # formatters, or nil are all accepted.
1407
+ def self.new: (?untyped formatters) -> Class
1408
+ end
1409
+ end
1410
+ end
1411
+
1412
+ # ----- formatter/html_formatter -----
1413
+
1414
+ module SimpleCov
1415
+ module Formatter
1416
+ # Writes the HTML report as a single self-contained index.html (the
1417
+ # compiled template with the coverage JSON substituted at the data
1418
+ # marker), and coverage.json as a side artifact (shared serialization
1419
+ # via JSONFormatter.build_hash).
1420
+ class HTMLFormatter < Base
1421
+ DATA_MARKER: "<!-- SIMPLECOV_COVERAGE_DATA -->"
1422
+
1423
+ # The sibling files a 1.0.0 through 1.0.3 report wrote next to
1424
+ # index.html, removed by format when an earlier version left them.
1425
+ LEGACY_REPORT_FILES: Array[String]
1426
+
1427
+ def format: (SimpleCov::Result result) -> void
1428
+
1429
+ # Generate HTML from a pre-existing coverage.json file without a
1430
+ # live SimpleCov::Result or a running test suite.
1431
+ def format_from_json: (String json_path, String output_dir) -> void
1432
+
1433
+ private
1434
+
1435
+ def entry_point_filename: () -> String
1436
+
1437
+ def source_less_hash: (Hash[Symbol, untyped] hash) -> Hash[Symbol, untyped]
1438
+
1439
+ # Write coverage.json and index.html, then clear any legacy
1440
+ # sibling files an earlier version left in the output directory.
1441
+ def write_report_files: (Hash[untyped, untyped] json_hash, Hash[untyped, untyped] viewer_hash, SimpleCov::Result result) -> void
1442
+
1443
+ # Substitute the coverage JSON into the compiled template.
1444
+ def render_report: (String json) -> String
1445
+
1446
+ def public_dir: () -> String
1447
+ end
1448
+ end
1449
+ end
1450
+
1451
+ # ----- formatter/coverage_json_writer -----
1452
+
1453
+ module SimpleCov
1454
+ module Formatter
1455
+ # Shared writer for the coverage.json artifact (JSONFormatter's
1456
+ # report and HTMLFormatter's side file): one pretty-printed binary
1457
+ # write plus the issue-#1171 concurrent-overwrite warning.
1458
+ module CoverageJSONWriter
1459
+ FILENAME: "coverage.json"
1460
+
1461
+ META_SCAN_BYTES: Integer
1462
+
1463
+ def self?.write: (untyped output_path, Hash[Symbol, untyped] hash, SimpleCov::Result result) -> String
1464
+
1465
+ # Warns when an existing coverage.json is newer than this process's
1466
+ # start time (a concurrent sibling writer). See issue #1171.
1467
+ def self?.warn_if_concurrent_overwrite: (String path, SimpleCov::Result result) -> void
1468
+
1469
+ # timestamp stays untyped (not Time) so the comparison sites don't
1470
+ # require the stdlib `time` extension sigs; the value is produced by
1471
+ # Time.iso8601 at runtime.
1472
+ def self?.existing_meta: (String path) -> ({ timestamp: untyped, command_name: untyped })?
1473
+
1474
+ def self?.parse_meta: (String path) -> Hash[Symbol, untyped]?
1475
+
1476
+ # Bounded head read that parses just the flat meta object of files
1477
+ # this module wrote; nil on any miss so parse_meta falls back to a
1478
+ # full parse.
1479
+ def self?.parse_meta_head: (String path) -> Hash[Symbol, untyped]?
1480
+
1481
+ def self?.parse_meta_full: (String path) -> Hash[Symbol, untyped]?
1482
+ end
1483
+ end
1484
+ end
1485
+
1486
+ # ----- formatter/json_formatter -----
1487
+
1488
+ module SimpleCov
1489
+ module Formatter
1490
+ # Writes coverage results as JSON to coverage/coverage.json.
1491
+ class JSONFormatter < Base
1492
+ FILENAME: "coverage.json"
1493
+
1494
+ # The hash serialized to coverage.json ($schema, meta, total,
1495
+ # coverage, groups, errors). `include_source:` defaults to
1496
+ # `SimpleCov.source_in_json`; pass true to force the per-file
1497
+ # source arrays regardless of the global setting.
1498
+ def self.build_hash: (SimpleCov::Result result, ?include_source: bool) -> Hash[Symbol, untyped]
1499
+
1500
+ def format: (SimpleCov::Result result) -> void
1501
+
1502
+ private
1503
+
1504
+ def message_prefix: () -> String
1505
+
1506
+ def entry_point_filename: () -> String
1507
+ end
1508
+ end
1509
+ end
1510
+
1511
+ # ----- exit_codes -----
1512
+
1513
+ module SimpleCov
1514
+ # Exit codes SimpleCov uses when a coverage check fails.
1515
+ module ExitCodes
1516
+ SUCCESS: 0
1517
+
1518
+ EXCEPTION: 1
1519
+
1520
+ MINIMUM_COVERAGE: 2
1521
+
1522
+ MAXIMUM_COVERAGE_DROP: 3
1523
+
1524
+ MAXIMUM_COVERAGE: 4
1525
+
1526
+ # Threshold-violation reports and exit-status notices: enforcement
1527
+ # output on stderr, deliberately not routed through Kernel#warn.
1528
+ def self.print_error: (String message) -> void
1529
+ end
1530
+ end
1531
+
1532
+ # ----- exit_codes/exit_code_handling -----
1533
+
1534
+ module SimpleCov
1535
+ module ExitCodes
1536
+ # The threshold-limit readers ExitCodeHandling consults. Satisfied by
1537
+ # SimpleCov's own configuration, or by any object exposing the same
1538
+ # readers (see the dogfood check in spec/helper.rb for an example
1539
+ # built from a plain Data class).
1540
+ interface _CoverageLimits
1541
+ def minimum_coverage: () -> Hash[Symbol, Numeric]
1542
+
1543
+ def minimum_coverage_by_file: () -> Hash[Symbol, Numeric]
1544
+
1545
+ def minimum_coverage_by_file_overrides: () -> untyped
1546
+
1547
+ def minimum_coverage_by_group: () -> untyped
1548
+
1549
+ def maximum_coverage: () -> Hash[Symbol, Numeric]
1550
+
1551
+ def maximum_coverage_drop: () -> Hash[Symbol, Numeric]
1552
+ end
1553
+
1554
+ # Runs every coverage check against the result and returns the exit
1555
+ # code of the first failing one, or SUCCESS when all pass.
1556
+ module ExitCodeHandling
1557
+ def self?.call: (SimpleCov::Result result, coverage_limits: _CoverageLimits) -> Integer
1558
+
1559
+ def self?.coverage_checks: (SimpleCov::Result result, _CoverageLimits coverage_limits) -> Array[untyped]
1560
+ end
1561
+ end
1562
+ end
1563
+
1564
+ # ----- profiles -----
1565
+
1566
+ module SimpleCov
1567
+ # Registry of named configuration procs, loadable via
1568
+ # `SimpleCov.start :rails` and definable via
1569
+ # `SimpleCov.profiles.define(:foo) { ... }`. The stored blocks are
1570
+ # evaluated through `SimpleCov.configure`, so they self-bind to the
1571
+ # configuration DSL.
1572
+ # A stored profile block. The self-type is untyped because the block
1573
+ # is written against the configuration DSL but stored as a plain Proc;
1574
+ # it self-binds when SimpleCov.configure evaluates it.
1575
+ type profile_proc = ^() [self: untyped] -> void
1576
+
1577
+ class Profiles < Hash[Symbol, profile_proc]
1578
+ # Raises SimpleCov::ConfigurationError when the name is taken.
1579
+ # The block runs via instance_exec against the SimpleCov module itself
1580
+ # (which extends Configuration), not a Configuration instance.
1581
+ def define: (Symbol | String name) { () [self: singleton(SimpleCov)] -> void } -> profile_proc
1582
+
1583
+ # Applies the named profile via SimpleCov.configure.
1584
+ def load: (Symbol | String name) -> void
1585
+
1586
+ # Returns the proc for the given profile name, autoloading bundled
1587
+ # ("simplecov/profiles/<name>") or plugin-gem
1588
+ # ("simplecov-profile-<name>") profiles on first lookup. Raises
1589
+ # SimpleCov::ConfigurationError when none is found.
1590
+ def fetch_proc: (Symbol | String name) -> profile_proc
1591
+
1592
+ private
1593
+
1594
+ # Tries `require "simplecov/profiles/<name>"`, then
1595
+ # `require "simplecov-profile-<name>"`; swallows LoadError so
1596
+ # fetch_proc raises the user-facing error.
1597
+ def autoload_profile: (Symbol name) -> void
1598
+ end
1599
+ end
1600
+
1601
+ # ----- parallel_adapters -----
1602
+
1603
+ module SimpleCov
1604
+ # Registry + selection for parallel-test-runner adapters. An adapter is
1605
+ # a class (used as a singleton, never instantiated) answering the
1606
+ # `_Adapter` contract; subclass `ParallelAdapters::Base` to inherit
1607
+ # no-op defaults. Register custom adapters via
1608
+ # `SimpleCov::ParallelAdapters.register MyRunnerAdapter`.
1609
+ module ParallelAdapters
1610
+ # The class-level contract an adapter must answer. `singleton(Base)`
1611
+ # and its subclasses satisfy this structurally.
1612
+ interface _Adapter
1613
+ def active?: () -> boolish
1614
+
1615
+ def first_worker?: () -> bool
1616
+
1617
+ def wait_for_siblings: () -> void
1618
+
1619
+ def native_wait?: () -> boolish
1620
+
1621
+ def expected_worker_count: () -> Integer
1622
+ end
1623
+
1624
+ # Registry state. Declared on both the instance and singleton sides
1625
+ # because `module_function` bodies type-check as instance methods
1626
+ # while runtime state lives on the module itself.
1627
+ @adapters: Array[_Adapter]?
1628
+
1629
+ self.@adapters: Array[_Adapter]?
1630
+
1631
+ # Memoized current adapter. Distinguishes "not yet computed" (ivar
1632
+ # undefined) from "computed, no adapter active" (nil), hence the
1633
+ # `defined?` guard in the implementation.
1634
+ @current: _Adapter?
1635
+
1636
+ self.@current: _Adapter?
1637
+
1638
+ # Adapters in selection order: user-registered adapters first, then
1639
+ # ParallelTestsAdapter, then GenericAdapter.
1640
+ def self?.adapters: () -> Array[_Adapter]
1641
+
1642
+ # Registers a custom adapter at the front of the selection list and
1643
+ # returns it. Clears the memoized `current` selection.
1644
+ def self?.register: (_Adapter adapter) -> _Adapter
1645
+
1646
+ # The first registered adapter whose `active?` returns true, or nil
1647
+ # when no recognized parallel runner is active (single-worker run).
1648
+ def self?.current: () -> _Adapter?
1649
+
1650
+ # Clears the memoized `current` selection (primarily for tests that
1651
+ # mutate env vars between examples).
1652
+ def self?.reset_current!: () -> void
1653
+ end
1654
+ end
1655
+
1656
+ # ----- parallel_adapters/base -----
1657
+
1658
+ module SimpleCov
1659
+ module ParallelAdapters
1660
+ # No-op defaults for a parallel-test-runner adapter: behave like a
1661
+ # single-process run. Real adapters subclass and override what they
1662
+ # need. The contract methods are class methods; adapters are never
1663
+ # instantiated.
1664
+ class Base
1665
+ # Should this adapter be selected for the current process? The
1666
+ # first registered adapter whose `active?` returns truthy wins.
1667
+ def self.active?: () -> boolish
1668
+
1669
+ # Should THIS worker do the final-result work (wait for siblings,
1670
+ # merge resultsets, run threshold checks, format the report)?
1671
+ # Defaults to true for the single-process case.
1672
+ def self.first_worker?: () -> bool
1673
+
1674
+ # Optional: block until sibling workers have finished writing
1675
+ # their resultsets. The no-op default leaves synchronization to
1676
+ # SimpleCov's resultset polling fallback.
1677
+ def self.wait_for_siblings: () -> void
1678
+
1679
+ # Does `wait_for_siblings` block until every sibling process has
1680
+ # exited? When true, a settled resultset count below
1681
+ # `expected_worker_count` is accepted as final.
1682
+ def self.native_wait?: () -> boolish
1683
+
1684
+ # How many parallel workers participate in this run. Defaults to 1.
1685
+ def self.expected_worker_count: () -> Integer
1686
+
1687
+ # The user's explicit `SimpleCov.parallel_tests false` opt-out.
1688
+ def self.forced_off?: () -> bool
1689
+
1690
+ # Shared PARALLEL_TEST_GROUPS parsing; 1 for unset, empty,
1691
+ # non-numeric, or non-positive values.
1692
+ def self.parallel_test_groups_count: () -> Integer
1693
+ end
1694
+ end
1695
+ end
1696
+
1697
+ # ----- parallel_adapters/generic -----
1698
+
1699
+ module SimpleCov
1700
+ module ParallelAdapters
1701
+ # Catch-all adapter for runners that follow the `TEST_ENV_NUMBER` /
1702
+ # `PARALLEL_TEST_GROUPS` env-var convention without shipping a Ruby
1703
+ # API (parallel_rspec, knapsack-style splitters, custom CI sharding).
1704
+ # Activates when `TEST_ENV_NUMBER` is set, unless
1705
+ # `SimpleCov.parallel_tests false` opted out.
1706
+ class GenericAdapter < Base
1707
+ def self.active?: () -> bool
1708
+
1709
+ # First worker is TEST_ENV_NUMBER "" (parallel_tests convention)
1710
+ # or "1" (runners that number from 1).
1711
+ def self.first_worker?: () -> bool
1712
+
1713
+ def self.expected_worker_count: () -> Integer
1714
+ end
1715
+ end
1716
+ end
1717
+
1718
+ # ----- parallel_adapters/parallel_tests -----
1719
+
1720
+ module SimpleCov
1721
+ module ParallelAdapters
1722
+ # Adapter for grosser/parallel_tests. Requires the full native
1723
+ # coordination contract (ParallelTests constant loaded,
1724
+ # TEST_ENV_NUMBER and PARALLEL_PID_FILE set); env-var-only setups
1725
+ # fall through to GenericAdapter.
1726
+ class ParallelTestsAdapter < Base
1727
+ def self.active?: () -> bool
1728
+
1729
+ # Delegates to ParallelTests.first_process? (the first started
1730
+ # process does the final-result work; see issue #922).
1731
+ def self.first_worker?: () -> bool
1732
+
1733
+ # Uses ParallelTests.wait_for_other_processes_to_finish when the
1734
+ # pid-file contract is present.
1735
+ def self.wait_for_siblings: () -> void
1736
+
1737
+ def self.native_wait?: () -> bool
1738
+
1739
+ def self.expected_worker_count: () -> Integer
1740
+
1741
+ # Auto-requires parallel_tests when installed and the env vars it
1742
+ # sets are present; a missing gem is treated as "not using
1743
+ # parallel_tests" (see issue #1018).
1744
+ def self.ensure_loaded: () -> void
1745
+
1746
+ def self.env_suggests_parallel_tests?: () -> bool
1747
+
1748
+ def self.native_parallel_tests_environment?: () -> bool
1749
+ end
1750
+ end
1751
+ end
1752
+
1753
+ # ----- deprecation -----
1754
+
1755
+ module SimpleCov
1756
+ # Emits legacy-API deprecation warnings, deduplicated by the source
1757
+ # location that triggered them (see issue #1204).
1758
+ module Deprecation
1759
+ # Warns about a deprecated API at most once per call-site location.
1760
+ # `message` is the notice without the `[DEPRECATION]` tag or location
1761
+ # prefix; `location` defaults to the caller of the deprecated method.
1762
+ def self?.warn: (String message, ?location: String?) -> void
1763
+
1764
+ # Dedup keys (locations, or messages when no backtrace is available)
1765
+ # already emitted by this process. Declared on both the instance and
1766
+ # singleton sides because `module_function` bodies type-check as
1767
+ # instance methods while runtime state lives on the module itself.
1768
+ @emitted: Set[String]?
1769
+
1770
+ self.@emitted: Set[String]?
1771
+
1772
+ def self?.emitted: () -> Set[String]
1773
+
1774
+ # @api private — reset emitted state between tests.
1775
+ def self?.reset!: () -> void
1776
+ end
1777
+ end