simplecov 0.22.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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +71 -916
- data/exe/simplecov +11 -0
- data/lib/minitest/simplecov_plugin.rb +13 -5
- data/lib/simplecov/atomic_file.rb +70 -0
- data/lib/simplecov/autostart.rb +11 -0
- data/lib/simplecov/cli/clean.rb +87 -0
- data/lib/simplecov/cli/command_helpers.rb +55 -0
- data/lib/simplecov/cli/coverage.rb +86 -0
- data/lib/simplecov/cli/coverage_file.rb +65 -0
- data/lib/simplecov/cli/diff.rb +147 -0
- data/lib/simplecov/cli/dotfile.rb +111 -0
- data/lib/simplecov/cli/merge.rb +120 -0
- data/lib/simplecov/cli/open.rb +48 -0
- data/lib/simplecov/cli/report.rb +97 -0
- data/lib/simplecov/cli/run.rb +36 -0
- data/lib/simplecov/cli/serve/report_preparer.rb +29 -0
- data/lib/simplecov/cli/serve/static_file_handler.rb +122 -0
- data/lib/simplecov/cli/serve.rb +85 -0
- data/lib/simplecov/cli/uncovered.rb +103 -0
- data/lib/simplecov/cli.rb +163 -0
- data/lib/simplecov/color.rb +83 -0
- data/lib/simplecov/combine/branches_combiner.rb +54 -7
- data/lib/simplecov/combine/coverage_accumulator.rb +268 -0
- data/lib/simplecov/combine/identity_interner.rb +30 -0
- data/lib/simplecov/combine/interned_counts.rb +30 -0
- data/lib/simplecov/combine/lines_combiner.rb +53 -23
- data/lib/simplecov/combine/methods_combiner.rb +74 -0
- data/lib/simplecov/combine/results_combiner.rb +13 -36
- data/lib/simplecov/combine.rb +5 -23
- data/lib/simplecov/command_guesser.rb +104 -33
- data/lib/simplecov/configuration/coverage.rb +172 -0
- data/lib/simplecov/configuration/coverage_criteria.rb +154 -0
- data/lib/simplecov/configuration/eval_coverage.rb +41 -0
- data/lib/simplecov/configuration/filters.rb +164 -0
- data/lib/simplecov/configuration/formatting.rb +138 -0
- data/lib/simplecov/configuration/groups.rb +42 -0
- data/lib/simplecov/configuration/ignored_entries.rb +63 -0
- data/lib/simplecov/configuration/merging.rb +165 -0
- data/lib/simplecov/configuration/thresholds.rb +179 -0
- data/lib/simplecov/configuration.rb +83 -420
- data/lib/simplecov/coverage_json.rb +24 -0
- data/lib/simplecov/coverage_statistics.rb +16 -10
- data/lib/simplecov/coverage_violations.rb +159 -0
- data/lib/simplecov/defaults.rb +34 -23
- data/lib/simplecov/deprecation.rb +45 -0
- data/lib/simplecov/directive.rb +167 -0
- data/lib/simplecov/exit_codes/check.rb +33 -0
- data/lib/simplecov/exit_codes/exit_code_handling.rb +8 -2
- data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +18 -65
- data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +32 -0
- data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +17 -36
- data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +30 -0
- data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +37 -33
- data/lib/simplecov/exit_codes.rb +20 -0
- data/lib/simplecov/exit_handling.rb +128 -0
- data/lib/simplecov/file_list.rb +70 -24
- data/lib/simplecov/filter.rb +105 -26
- data/lib/simplecov/formatter/base.rb +118 -0
- data/lib/simplecov/formatter/coverage_json_writer.rb +97 -0
- data/lib/simplecov/formatter/html_formatter/public/index.html +87 -0
- data/lib/simplecov/formatter/html_formatter/viewer_data_validator.rb +96 -0
- data/lib/simplecov/formatter/html_formatter.rb +105 -0
- data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +88 -0
- data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +118 -0
- data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +93 -0
- data/lib/simplecov/formatter/json_formatter.rb +46 -0
- data/lib/simplecov/formatter/multi_formatter.rb +12 -8
- data/lib/simplecov/formatter/simple_formatter.rb +14 -11
- data/lib/simplecov/formatter.rb +16 -0
- data/lib/simplecov/group_names.rb +32 -0
- data/lib/simplecov/last_run.rb +18 -4
- data/lib/simplecov/lines_classifier.rb +48 -15
- data/lib/simplecov/load_global_config.rb +12 -4
- data/lib/simplecov/parallel_adapters/base.rb +78 -0
- data/lib/simplecov/parallel_adapters/generic.rb +45 -0
- data/lib/simplecov/parallel_adapters/parallel_tests.rb +93 -0
- data/lib/simplecov/parallel_adapters.rb +85 -0
- data/lib/simplecov/parallel_coordination.rb +134 -0
- data/lib/simplecov/parallel_result_merger.rb +230 -0
- data/lib/simplecov/process.rb +52 -12
- data/lib/simplecov/profiles/bundler_filter.rb +1 -1
- data/lib/simplecov/profiles/hidden_filter.rb +1 -1
- data/lib/simplecov/profiles/rails.rb +24 -10
- data/lib/simplecov/profiles/root_filter.rb +6 -5
- data/lib/simplecov/profiles/strict.rb +32 -0
- data/lib/simplecov/profiles/test_frameworks.rb +1 -4
- data/lib/simplecov/profiles.rb +32 -3
- data/lib/simplecov/report_deferral.rb +49 -0
- data/lib/simplecov/report_stamp.rb +28 -0
- data/lib/simplecov/result/missing_source_files_reporter.rb +49 -0
- data/lib/simplecov/result/source_file_builder.rb +51 -0
- data/lib/simplecov/result.rb +145 -26
- data/lib/simplecov/result_adapter.rb +139 -8
- data/lib/simplecov/result_merger/legacy_format_adapter.rb +28 -0
- data/lib/simplecov/result_merger/resultset_file.rb +74 -0
- data/lib/simplecov/result_merger/resultset_run_identity.rb +67 -0
- data/lib/simplecov/result_merger/resultset_store.rb +53 -0
- data/lib/simplecov/result_merger/unloaded_files.rb +103 -0
- data/lib/simplecov/result_merger.rb +109 -114
- data/lib/simplecov/result_processing.rb +218 -0
- data/lib/simplecov/run_identity.rb +77 -0
- data/lib/simplecov/simulate_coverage.rb +83 -12
- data/lib/simplecov/source_file/branch.rb +1 -3
- data/lib/simplecov/source_file/branch_builder.rb +114 -0
- data/lib/simplecov/source_file/builder_context.rb +28 -0
- data/lib/simplecov/source_file/line.rb +9 -4
- data/lib/simplecov/source_file/line_builder.rb +43 -0
- data/lib/simplecov/source_file/method.rb +58 -0
- data/lib/simplecov/source_file/method_builder.rb +60 -0
- data/lib/simplecov/source_file/ruby_data_parser.rb +110 -0
- data/lib/simplecov/source_file/skip_chunks.rb +72 -0
- data/lib/simplecov/source_file/source_loader.rb +79 -0
- data/lib/simplecov/source_file/statistics.rb +65 -0
- data/lib/simplecov/source_file.rb +66 -232
- data/lib/simplecov/static_coverage_extractor/condition_folding.rb +239 -0
- data/lib/simplecov/static_coverage_extractor/location_conventions.rb +236 -0
- data/lib/simplecov/static_coverage_extractor/method_collector.rb +62 -0
- data/lib/simplecov/static_coverage_extractor/prism_compat.rb +55 -0
- data/lib/simplecov/static_coverage_extractor/value_position.rb +74 -0
- data/lib/simplecov/static_coverage_extractor/visitor.rb +183 -0
- data/lib/simplecov/static_coverage_extractor.rb +110 -0
- data/lib/simplecov/unloaded_file_injector.rb +75 -0
- data/lib/simplecov/useless_results_remover.rb +16 -7
- data/lib/simplecov/version.rb +1 -1
- data/lib/simplecov-html.rb +4 -0
- data/lib/simplecov.rb +185 -380
- data/lib/simplecov_json_formatter.rb +4 -0
- data/sig/simplecov.rbs +1777 -0
- metadata +111 -62
- data/CHANGELOG.md +0 -191
- data/doc/alternate-formatters.md +0 -71
- data/doc/commercial-services.md +0 -25
- data/doc/editor-integration.md +0 -18
- data/lib/simplecov/combine/files_combiner.rb +0 -24
- data/lib/simplecov/default_formatter.rb +0 -20
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# Selection and validation of the coverage criteria Ruby's `Coverage`
|
|
5
|
+
# library should track. Supports `:line` (the historical default),
|
|
6
|
+
# `:branch`, `:method`, and `:oneshot_line`. The standalone `:eval`
|
|
7
|
+
# toggle lives in `eval_coverage.rb`.
|
|
8
|
+
module Configuration
|
|
9
|
+
SUPPORTED_COVERAGE_CRITERIA = %i[line branch method oneshot_line].freeze
|
|
10
|
+
DEFAULT_COVERAGE_CRITERION = :line
|
|
11
|
+
ONESHOT_LINE_COVERAGE_CRITERION = :oneshot_line
|
|
12
|
+
LINE_COVERAGE_ALTERNATIVES = {line: :oneshot_line, oneshot_line: :line}.freeze #: line_coverage_alternatives
|
|
13
|
+
private_constant :LINE_COVERAGE_ALTERNATIVES
|
|
14
|
+
|
|
15
|
+
# Enable one or more coverage criteria. `:eval` is accepted as a
|
|
16
|
+
# shorthand for the standalone eval-coverage toggle.
|
|
17
|
+
def enable_coverage(*criteria)
|
|
18
|
+
criteria.each { |criterion| criterion == :eval ? enable_eval_coverage : add_coverage_criterion(criterion) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Remove `criterion` from the set of enabled coverage criteria.
|
|
22
|
+
# `:eval` turns the standalone eval-coverage toggle back off,
|
|
23
|
+
# mirroring `enable_coverage`. Disabling every criterion raises at
|
|
24
|
+
# `start_tracking` (not here), so config files that toggle criteria
|
|
25
|
+
# in arbitrary order don't have to worry about transient empty states.
|
|
26
|
+
def disable_coverage(criterion)
|
|
27
|
+
return disable_eval_coverage if criterion == :eval
|
|
28
|
+
|
|
29
|
+
raise_if_criterion_unsupported(criterion)
|
|
30
|
+
coverage_criteria.delete(criterion)
|
|
31
|
+
@primary_coverage = nil if @primary_coverage == criterion
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def primary_coverage(criterion = nil)
|
|
35
|
+
if criterion.nil?
|
|
36
|
+
@primary_coverage ||= default_primary_coverage
|
|
37
|
+
else
|
|
38
|
+
raise_if_criterion_disabled(criterion)
|
|
39
|
+
@primary_coverage = criterion
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def coverage_criteria
|
|
44
|
+
@coverage_criteria ||= Set[DEFAULT_COVERAGE_CRITERION]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def coverage_criterion_enabled?(criterion)
|
|
48
|
+
coverage_criteria.member?(criterion)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Reset the criteria back to the lazy default (`Set[:line]`).
|
|
52
|
+
def clear_coverage_criteria
|
|
53
|
+
@coverage_criteria = nil
|
|
54
|
+
@primary_coverage = nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @api private — called from `SimpleCov.start_tracking` to fail
|
|
58
|
+
# fast when the user has disabled every coverage criterion.
|
|
59
|
+
def validate_coverage_criteria!
|
|
60
|
+
return unless coverage_criteria.empty?
|
|
61
|
+
|
|
62
|
+
raise SimpleCov::ConfigurationError,
|
|
63
|
+
"At least one coverage criterion must be enabled. " \
|
|
64
|
+
"Re-enable one with `enable_coverage :line`, `:branch`, or `:method`."
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Whether this run produces line data at all. The oneshot variant counts:
|
|
68
|
+
# `ResultAdapter` turns its executed-line list back into a line array. A
|
|
69
|
+
# branch-only or method-only run produces none, and `Coverage.result`
|
|
70
|
+
# entries for the files it loaded carry no `"lines"` key.
|
|
71
|
+
def line_coverage?
|
|
72
|
+
coverage_criterion_enabled?(DEFAULT_COVERAGE_CRITERION) ||
|
|
73
|
+
coverage_criterion_enabled?(ONESHOT_LINE_COVERAGE_CRITERION)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def branch_coverage?
|
|
77
|
+
branch_coverage_supported? && coverage_criterion_enabled?(:branch)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def branch_coverage_supported?
|
|
81
|
+
coverage_criterion_supported?(:branches)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def method_coverage?
|
|
85
|
+
method_coverage_supported? && coverage_criterion_enabled?(:method)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def method_coverage_supported?
|
|
89
|
+
coverage_criterion_supported?(:methods)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Ask the Coverage runtime itself whether a criterion is supported
|
|
93
|
+
# (Ruby >= 3.2). Older Rubies don't expose `Coverage.supported?`, so
|
|
94
|
+
# fall back to the historical engine check that line/branch/method
|
|
95
|
+
# were unavailable on JRuby. `:eval` was added later, so on older
|
|
96
|
+
# Rubies its fallback is "always unsupported" rather than the
|
|
97
|
+
# JRuby-only one above. The fallback arm is unreachable from the
|
|
98
|
+
# dogfood report, which runs on a newer Ruby.
|
|
99
|
+
# simplecov:disable
|
|
100
|
+
def coverage_criterion_supported?(criterion)
|
|
101
|
+
require "coverage"
|
|
102
|
+
return Coverage.supported?(criterion) if Coverage.respond_to?(:supported?)
|
|
103
|
+
|
|
104
|
+
criterion != :eval && RUBY_ENGINE != "jruby"
|
|
105
|
+
end
|
|
106
|
+
# simplecov:enable
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def add_coverage_criterion(criterion)
|
|
111
|
+
raise_if_criterion_unsupported(criterion)
|
|
112
|
+
incompatible = LINE_COVERAGE_ALTERNATIVES[criterion]
|
|
113
|
+
disable_coverage(incompatible) if incompatible
|
|
114
|
+
coverage_criteria << criterion
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# If `:line` is enabled, it's the default primary; otherwise fall
|
|
118
|
+
# back to whichever criterion the user actually enabled (in
|
|
119
|
+
# insertion order). Returning `:line` even when disabled would
|
|
120
|
+
# propagate broken state into `minimum_coverage 90`.
|
|
121
|
+
def default_primary_coverage
|
|
122
|
+
return DEFAULT_COVERAGE_CRITERION if coverage_criterion_enabled?(DEFAULT_COVERAGE_CRITERION)
|
|
123
|
+
|
|
124
|
+
# Set#first types as nilable, but an empty criteria set is rejected at
|
|
125
|
+
# start_tracking before any caller can observe a nil here.
|
|
126
|
+
_ = coverage_criteria.first
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def raise_if_criterion_disabled(criterion)
|
|
130
|
+
# `coverage :eval` by itself IS supported — it's a standalone
|
|
131
|
+
# toggle, never in the enabled-criteria set — so the generic
|
|
132
|
+
# "unsupported criterion" message below would mislead here.
|
|
133
|
+
if criterion == :eval
|
|
134
|
+
raise SimpleCov::ConfigurationError,
|
|
135
|
+
"Coverage criterion :eval only toggles measuring eval'd code; " \
|
|
136
|
+
"it cannot carry thresholds or serve as the primary criterion"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
raise_if_criterion_unsupported(criterion)
|
|
140
|
+
return if coverage_criterion_enabled?(criterion)
|
|
141
|
+
|
|
142
|
+
raise SimpleCov::ConfigurationError,
|
|
143
|
+
"Coverage criterion #{criterion}, is disabled! " \
|
|
144
|
+
"Please enable it first through enable_coverage #{criterion} (if supported)"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def raise_if_criterion_unsupported(criterion)
|
|
148
|
+
return if SUPPORTED_COVERAGE_CRITERIA.member?(criterion)
|
|
149
|
+
|
|
150
|
+
raise SimpleCov::ConfigurationError,
|
|
151
|
+
"Unsupported coverage criterion #{criterion}, supported values are #{SUPPORTED_COVERAGE_CRITERIA}"
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# The standalone eval-coverage toggle (`enable_coverage :eval`),
|
|
5
|
+
# instrumenting `eval`'d code on Rubies that support it. Kept separate
|
|
6
|
+
# from the criteria-set logic in `coverage_criteria.rb` because `:eval`
|
|
7
|
+
# is a boolean toggle, never a member of the enabled-criteria set.
|
|
8
|
+
module Configuration
|
|
9
|
+
def coverage_for_eval_supported?
|
|
10
|
+
coverage_criterion_supported?(:eval)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def coverage_for_eval_enabled?
|
|
14
|
+
@coverage_for_eval_enabled ||= false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# DEPRECATED: prefer `enable_coverage :eval`.
|
|
18
|
+
def enable_coverage_for_eval
|
|
19
|
+
SimpleCov::Deprecation.warn("`SimpleCov.enable_coverage_for_eval` is deprecated. " \
|
|
20
|
+
"Replace with `SimpleCov.enable_coverage :eval`.")
|
|
21
|
+
enable_eval_coverage
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
# Shared implementation backing both `enable_coverage :eval` and
|
|
27
|
+
# the deprecated `enable_coverage_for_eval`.
|
|
28
|
+
def enable_eval_coverage
|
|
29
|
+
if coverage_for_eval_supported?
|
|
30
|
+
@coverage_for_eval_enabled = true
|
|
31
|
+
else
|
|
32
|
+
warn "Coverage for eval is not available; Use Ruby 3.2.0 or later"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# No support check needed: off is a safe state on every Ruby.
|
|
37
|
+
def disable_eval_coverage
|
|
38
|
+
@coverage_for_eval_enabled = false
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# Inclusion and exclusion methods: `cover` and `skip`, plus the deprecated
|
|
5
|
+
# `track_files` and `add_filter` aliases.
|
|
6
|
+
module Configuration
|
|
7
|
+
attr_writer :filters
|
|
8
|
+
|
|
9
|
+
#
|
|
10
|
+
# Restrict the universe of files in the coverage report to those matching
|
|
11
|
+
# one or more globs, regexps, or block predicates. Multiple calls union;
|
|
12
|
+
# when any `cover` matcher is configured the report drops every file that
|
|
13
|
+
# doesn't match at least one of them.
|
|
14
|
+
#
|
|
15
|
+
# Strings are interpreted as shell globs (e.g. "lib/**/*.rb"), not
|
|
16
|
+
# substring matches — this is a deliberate departure from the legacy
|
|
17
|
+
# `add_filter` semantics and matches the way `track_files` already
|
|
18
|
+
# interprets its argument.
|
|
19
|
+
#
|
|
20
|
+
# When the matcher is a string-glob, `cover` also expands the glob on
|
|
21
|
+
# disk so files that exist but were never required during the run still
|
|
22
|
+
# appear in the report (at 0% coverage). This is the "include unloaded
|
|
23
|
+
# files" half of the legacy `track_files` behavior, rolled into the
|
|
24
|
+
# same call.
|
|
25
|
+
#
|
|
26
|
+
# SimpleCov.start do
|
|
27
|
+
# cover "lib/**/*.rb", "app/**/*.rb"
|
|
28
|
+
# cover(/_helper\.rb\z/)
|
|
29
|
+
# cover { |sf| sf.lines.count > 5 }
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
def cover(*args, &block)
|
|
33
|
+
args.each { |arg| cover_filters << build_cover_filter(arg) }
|
|
34
|
+
cover_filters << SimpleCov::BlockFilter.new(block) if block
|
|
35
|
+
cover_filters
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns the list of configured inclusion filters added via `cover`.
|
|
39
|
+
def cover_filters
|
|
40
|
+
@cover_filters ||= []
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns the list of string globs passed to `cover` — used by the
|
|
44
|
+
# disk-discovery pass in `SimpleCov.tracked_file_paths` so files
|
|
45
|
+
# matching a `cover` glob appear in the report even when they were
|
|
46
|
+
# never required during the suite.
|
|
47
|
+
#
|
|
48
|
+
# Walks into `ArrayFilter` entries (built when a caller passes an
|
|
49
|
+
# array to `cover`) so a glob nested inside `cover(["lib/**/*.rb",
|
|
50
|
+
# /helper\.rb\z/])` still drives unloaded-file discovery.
|
|
51
|
+
def cover_globs
|
|
52
|
+
collect_cover_globs(cover_filters)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# DEPRECATED: prefer `cover`, which both includes unloaded files (the
|
|
56
|
+
# historical `track_files` behavior) and restricts the report to the
|
|
57
|
+
# matching set.
|
|
58
|
+
def track_files(glob)
|
|
59
|
+
SimpleCov::Deprecation.warn("`SimpleCov.track_files` is deprecated. " \
|
|
60
|
+
"#{track_files_replacement_hint(glob)}")
|
|
61
|
+
@tracked_files = glob
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# `track_files(nil)` is the documented way to clear a previously-set
|
|
65
|
+
# glob, but `cover(nil)` raises `ConfigurationError`, so don't point
|
|
66
|
+
# users at it. The `cover` API has no direct equivalent for "reset
|
|
67
|
+
# the inclusion list" — point users at the `@cover_filters` reset.
|
|
68
|
+
def track_files_replacement_hint(glob)
|
|
69
|
+
if glob.nil?
|
|
70
|
+
"Replace with `SimpleCov.cover_filters.clear` — clearing the inclusion list."
|
|
71
|
+
else
|
|
72
|
+
"Replace with `SimpleCov.cover #{glob.inspect}` — `cover` includes unloaded files on disk " \
|
|
73
|
+
"(the historical `track_files` behavior) and also restricts the report to the matching set. " \
|
|
74
|
+
"If you want to keep additional files outside #{glob.inspect} in the report, pass every " \
|
|
75
|
+
"directory you care about, e.g. `cover #{glob.inspect}, \"app/**/*.rb\"`."
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Returns the glob used to include files that were not explicitly required.
|
|
80
|
+
def tracked_files
|
|
81
|
+
@tracked_files if defined?(@tracked_files)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Returns the list of configured exclusion filters added via `skip`
|
|
85
|
+
# (or the deprecated `add_filter`).
|
|
86
|
+
def filters
|
|
87
|
+
@filters ||= []
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
#
|
|
91
|
+
# Drop matching files from the coverage report. The inverse of `cover`.
|
|
92
|
+
#
|
|
93
|
+
# See README for the full grammar; `skip` accepts a String (path-segment
|
|
94
|
+
# substring), Regexp, block predicate, or Array of any of those.
|
|
95
|
+
#
|
|
96
|
+
def skip(filter_argument = nil, &)
|
|
97
|
+
filters << parse_filter(filter_argument, &)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# DEPRECATED: alias for `skip`. Same matcher grammar, identical behavior.
|
|
101
|
+
def add_filter(filter_argument = nil, &block)
|
|
102
|
+
example = block ? "`SimpleCov.skip { ... }`" : "`SimpleCov.skip #{filter_argument.inspect}`"
|
|
103
|
+
SimpleCov::Deprecation.warn("`SimpleCov.add_filter` is deprecated. " \
|
|
104
|
+
"Replace with `SimpleCov.skip` (same arguments, same behavior). Example: #{example}.")
|
|
105
|
+
skip(filter_argument, &block)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Remove any filters whose `filter_argument` equals the given value.
|
|
109
|
+
# Returns true when at least one filter was removed, false otherwise.
|
|
110
|
+
def remove_filter(filter_argument) # rubocop:disable Naming/PredicateMethod
|
|
111
|
+
before = filters.size
|
|
112
|
+
filters.reject! { |filter| filter.respond_to?(:filter_argument) && filter.filter_argument == filter_argument }
|
|
113
|
+
filters.size != before
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Remove every filter from the chain, including the defaults installed
|
|
117
|
+
# by `SimpleCov.start`.
|
|
118
|
+
def clear_filters
|
|
119
|
+
@filters = []
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Drop every filter previously installed (defaults plus anything
|
|
123
|
+
# earlier in this block) so subsequent `skip` calls start from a
|
|
124
|
+
# clean slate. Order matters — call this before your own `skip`
|
|
125
|
+
# invocations.
|
|
126
|
+
def no_default_skips
|
|
127
|
+
clear_filters
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
# The actual filter processor. Not meant for direct use.
|
|
133
|
+
def parse_filter(filter_argument = nil, &filter_proc)
|
|
134
|
+
filter = filter_argument || filter_proc
|
|
135
|
+
|
|
136
|
+
raise ArgumentError, "Please specify either a filter or a block to filter with" unless filter
|
|
137
|
+
|
|
138
|
+
SimpleCov::Filter.build_filter(filter)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Build a filter for a `cover` argument. Strings are treated as
|
|
142
|
+
# globs (not substrings — that's `skip`/`add_filter`'s semantics);
|
|
143
|
+
# everything else dispatches exactly like `add_filter`.
|
|
144
|
+
def build_cover_filter(arg)
|
|
145
|
+
SimpleCov::Filter.build_filter(arg, string_filter: SimpleCov::GlobFilter)
|
|
146
|
+
rescue SimpleCov::ConfigurationError
|
|
147
|
+
raise SimpleCov::ConfigurationError, "Unsupported `cover` argument #{arg.inspect}; " \
|
|
148
|
+
"expected a String glob, Regexp, Proc, " \
|
|
149
|
+
"SimpleCov::Filter, or Array of those."
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Walk a list of cover filters and return the string globs they hold,
|
|
153
|
+
# descending into `ArrayFilter` wrappers built by `cover(["a", "b"])`.
|
|
154
|
+
def collect_cover_globs(filter_list)
|
|
155
|
+
filter_list.flat_map do |filter|
|
|
156
|
+
case filter
|
|
157
|
+
when SimpleCov::GlobFilter then filter.filter_argument
|
|
158
|
+
when SimpleCov::ArrayFilter then collect_cover_globs(filter.filter_argument)
|
|
159
|
+
else []
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../formatter/multi_formatter"
|
|
4
|
+
|
|
5
|
+
module SimpleCov
|
|
6
|
+
# Formatter selection (`formatter` / `formatters`), reporting toggles
|
|
7
|
+
# (`print_errors`), and the deprecated `# :nocov:` token hook.
|
|
8
|
+
module Configuration
|
|
9
|
+
attr_writer :formatter, :print_error_status
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
# Gets or sets the configured formatter. Accepts a formatter class
|
|
13
|
+
# (instantiated fresh for every report) or a ready-built instance,
|
|
14
|
+
# which is how constructor options are passed — e.g.
|
|
15
|
+
# `formatter SimpleCov::Formatter::HTMLFormatter.new(silent: true)`
|
|
16
|
+
# to suppress the "Coverage report generated" status line (see
|
|
17
|
+
# #1240). Pass `false` (or `nil`) to opt out of formatting
|
|
18
|
+
# entirely — worker processes in big parallel CI setups (see #964)
|
|
19
|
+
# only need their `.resultset.json` on disk so a final
|
|
20
|
+
# `SimpleCov.collate` job can produce the report; running them
|
|
21
|
+
# without a formatter saves the per-job HTML/multi-formatter
|
|
22
|
+
# overhead.
|
|
23
|
+
#
|
|
24
|
+
def formatter(formatter = :__no_arg__)
|
|
25
|
+
case formatter
|
|
26
|
+
when :__no_arg__
|
|
27
|
+
@formatter
|
|
28
|
+
else
|
|
29
|
+
@formatter = formatter || nil # normalize `false` to `nil`
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Sets the configured formatters. Pass `[]` to opt out of
|
|
34
|
+
# formatting entirely; see `formatter` for the rationale.
|
|
35
|
+
def formatters(formatters = :__no_arg__)
|
|
36
|
+
case formatters
|
|
37
|
+
when :__no_arg__
|
|
38
|
+
configured = formatter
|
|
39
|
+
configured ? [configured] : []
|
|
40
|
+
else
|
|
41
|
+
self.formatters = formatters
|
|
42
|
+
formatters
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Sets the configured formatters. Equivalent to `formatters [...]`.
|
|
47
|
+
# Accepts a single formatter as well as an Array, matching the pre-1.0 behavior
|
|
48
|
+
# where `MultiFormatter.new` normalized its input. Elements may be
|
|
49
|
+
# formatter classes or ready-built instances; see `formatter`.
|
|
50
|
+
# `nil`, `false`, and `[]` all opt out of formatting entirely —
|
|
51
|
+
# `false` normalized like `formatter false` does, since `Array(false)`
|
|
52
|
+
# would otherwise smuggle it in as a "formatter" that can only fail.
|
|
53
|
+
def formatters=(formatters)
|
|
54
|
+
formatters = Array(formatters || nil)
|
|
55
|
+
@formatter = formatters.empty? ? nil : SimpleCov::Formatter::MultiFormatter.new(formatters)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
#
|
|
59
|
+
# Get or set whether SimpleCov colorizes its stderr diagnostics. Accepts
|
|
60
|
+
# `true` (always on), `false` (always off), or `:auto` (default: defer
|
|
61
|
+
# to `SimpleCov::Color`, which checks `$stderr.tty?` with `NO_COLOR`
|
|
62
|
+
# and `FORCE_COLOR` overrides). An explicit `true`/`false` wins over
|
|
63
|
+
# both auto-detection and the env vars, which is the right escape
|
|
64
|
+
# hatch when stderr is being piped through a wrapper that still
|
|
65
|
+
# renders ANSI in its own terminal (parallel_tests with
|
|
66
|
+
# `--combine-stderr`, log multiplexers, some CI runners). See #1157.
|
|
67
|
+
#
|
|
68
|
+
def color(value = :__no_arg__)
|
|
69
|
+
return defined?(@color) ? @color : :auto if value == :__no_arg__
|
|
70
|
+
|
|
71
|
+
@color = value
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Get or set whether SimpleCov prints its own diagnostic warnings to
|
|
76
|
+
# stderr. Covers per-check threshold violations, the trailing
|
|
77
|
+
# "SimpleCov failed with exit ..." summary, and the deferred-report /
|
|
78
|
+
# previous-error notices. Defaults to true. Set to false to silence
|
|
79
|
+
# SimpleCov entirely when parsing tooling output (see issue #1155).
|
|
80
|
+
#
|
|
81
|
+
def print_errors(value = :__no_arg__)
|
|
82
|
+
return defined?(@print_error_status) ? @print_error_status : true if value == :__no_arg__
|
|
83
|
+
|
|
84
|
+
@print_error_status = value
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
#
|
|
88
|
+
# Get or set whether `coverage.json` includes the full source-text
|
|
89
|
+
# array for every file. Defaults to true. Set to false when a
|
|
90
|
+
# downstream tool reads the project's source files directly and
|
|
91
|
+
# only needs the coverage metrics, so `coverage.json` doesn't carry
|
|
92
|
+
# a copy of the source tree (which dominates the payload on larger
|
|
93
|
+
# projects).
|
|
94
|
+
#
|
|
95
|
+
# The HTML report's embedded data always includes source — the
|
|
96
|
+
# client-side renderer needs it. Only `coverage.json` honors
|
|
97
|
+
# this setting.
|
|
98
|
+
#
|
|
99
|
+
# SimpleCov.start do
|
|
100
|
+
# source_in_json false
|
|
101
|
+
# end
|
|
102
|
+
#
|
|
103
|
+
def source_in_json(value = :__no_arg__)
|
|
104
|
+
return defined?(@source_in_json) ? @source_in_json : true if value == :__no_arg__
|
|
105
|
+
|
|
106
|
+
@source_in_json = value
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# DEPRECATED: alias for `print_errors`. Same value, same behavior.
|
|
110
|
+
def print_error_status
|
|
111
|
+
SimpleCov::Deprecation.warn("`SimpleCov.print_error_status` is deprecated. " \
|
|
112
|
+
"Replace with `SimpleCov.print_errors` (same value).")
|
|
113
|
+
defined?(@print_error_status) ? @print_error_status : true
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
#
|
|
117
|
+
# DEPRECATED: configure `# :nocov:` token override. Prefer
|
|
118
|
+
# `# simplecov:disable` / `# simplecov:enable` block comments (see
|
|
119
|
+
# SimpleCov::Directive). The `# :nocov:` toggle and this hook will
|
|
120
|
+
# be removed in a future release.
|
|
121
|
+
#
|
|
122
|
+
def nocov_token(nocov_token = nil)
|
|
123
|
+
SimpleCov::Deprecation.warn("`SimpleCov.nocov_token` and `SimpleCov.skip_token` are deprecated. " \
|
|
124
|
+
"Replace with `# simplecov:disable` / `# simplecov:enable` block comments.")
|
|
125
|
+
current_nocov_token(nocov_token)
|
|
126
|
+
end
|
|
127
|
+
alias skip_token nocov_token
|
|
128
|
+
|
|
129
|
+
# Internal accessor used by SimpleCov to recognise `# :nocov:`
|
|
130
|
+
# markers without emitting the public-API deprecation warning. Will
|
|
131
|
+
# be removed alongside the deprecated `nocov_token` setter.
|
|
132
|
+
def current_nocov_token(value = nil)
|
|
133
|
+
return @nocov_token if defined?(@nocov_token) && value.nil?
|
|
134
|
+
|
|
135
|
+
@nocov_token = value || "nocov"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# Group configuration is kept separate from inclusion and exclusion filters,
|
|
5
|
+
# while sharing their matcher parser through the main Configuration module.
|
|
6
|
+
module Configuration
|
|
7
|
+
# Returns the configured groups. Add groups using SimpleCov.group.
|
|
8
|
+
def groups
|
|
9
|
+
@groups ||= {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def groups=(new_groups)
|
|
13
|
+
new_groups = new_groups.to_h { |name, filter| [GroupNames.normalize(name), filter] }
|
|
14
|
+
GroupNames.validate!(new_groups.keys)
|
|
15
|
+
@groups = new_groups
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Define a display group for files. Same matcher grammar as `skip`,
|
|
19
|
+
# but instead of dropping the matching files it bins them under
|
|
20
|
+
# `group_name` for the formatter. Files matched by no group fall
|
|
21
|
+
# into the implicit "Ungrouped" bucket.
|
|
22
|
+
def group(group_name, filter_argument = nil, &)
|
|
23
|
+
group_name = GroupNames.normalize(group_name)
|
|
24
|
+
GroupNames.validate!([group_name])
|
|
25
|
+
groups[group_name] = parse_filter(filter_argument, &)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# DEPRECATED: alias for `group`. Same arguments, same behavior.
|
|
29
|
+
def add_group(group_name, filter_argument = nil, &block)
|
|
30
|
+
example = if block
|
|
31
|
+
"`SimpleCov.group #{group_name.inspect} { ... }`"
|
|
32
|
+
else
|
|
33
|
+
"`SimpleCov.group #{group_name.inspect}, #{filter_argument.inspect}`"
|
|
34
|
+
end
|
|
35
|
+
SimpleCov::Deprecation.warn(
|
|
36
|
+
"`SimpleCov.add_group` is deprecated. " \
|
|
37
|
+
"Replace with `SimpleCov.group` (same arguments, same behavior). Example: #{example}."
|
|
38
|
+
)
|
|
39
|
+
group(group_name, filter_argument, &block)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# Coverage-entry filters scoped to branch / method criteria. See
|
|
5
|
+
# `ignore_branches` and `ignore_methods`, and #1033 /
|
|
6
|
+
# #1046 for the synthetic-entry detection rationale.
|
|
7
|
+
module Configuration
|
|
8
|
+
# Branch types accepted by `ignore_branches`.
|
|
9
|
+
IGNORABLE_BRANCH_TYPES = %i[implicit_else eval_generated].freeze
|
|
10
|
+
# Method types accepted by `ignore_methods`.
|
|
11
|
+
IGNORABLE_METHOD_TYPES = %i[eval_generated].freeze
|
|
12
|
+
|
|
13
|
+
# Variadic; multiple calls union. Setting is recorded regardless
|
|
14
|
+
# of whether branch coverage is enabled at call time. See #1033, #1046.
|
|
15
|
+
def ignore_branches(*types)
|
|
16
|
+
types.each { |type| raise_if_branch_type_unsupported(type) }
|
|
17
|
+
ignored_branches.concat(types).uniq!
|
|
18
|
+
ignored_branches
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def ignored_branches
|
|
22
|
+
@ignored_branches ||= []
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ignored_branch?(type)
|
|
26
|
+
ignored_branches.include?(type)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# See `ignore_branches`. The only supported method-type token today
|
|
30
|
+
# is `:eval_generated`; see #1046 for the rationale.
|
|
31
|
+
def ignore_methods(*types)
|
|
32
|
+
types.each { |type| raise_if_method_type_unsupported(type) }
|
|
33
|
+
ignored_methods.concat(types).uniq!
|
|
34
|
+
ignored_methods
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def ignored_methods
|
|
38
|
+
@ignored_methods ||= []
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ignored_method?(type)
|
|
42
|
+
ignored_methods.include?(type)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def raise_if_branch_type_unsupported(type)
|
|
48
|
+
return if IGNORABLE_BRANCH_TYPES.member?(type)
|
|
49
|
+
|
|
50
|
+
raise SimpleCov::ConfigurationError,
|
|
51
|
+
"Unsupported branch type #{type.inspect} for `ignore_branches`. " \
|
|
52
|
+
"Supported values are #{IGNORABLE_BRANCH_TYPES.inspect}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def raise_if_method_type_unsupported(type)
|
|
56
|
+
return if IGNORABLE_METHOD_TYPES.member?(type)
|
|
57
|
+
|
|
58
|
+
raise SimpleCov::ConfigurationError,
|
|
59
|
+
"Unsupported method type #{type.inspect} for `ignore_methods`. " \
|
|
60
|
+
"Supported values are #{IGNORABLE_METHOD_TYPES.inspect}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|