simplecov 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +148 -5
  3. data/exe/simplecov +0 -3
  4. data/lib/minitest/simplecov_plugin.rb +12 -9
  5. data/lib/simplecov/atomic_file.rb +16 -19
  6. data/lib/simplecov/autostart.rb +5 -7
  7. data/lib/simplecov/baseline/parser.rb +58 -0
  8. data/lib/simplecov/baseline.rb +170 -0
  9. data/lib/simplecov/cli/affected/changed_files.rb +57 -0
  10. data/lib/simplecov/cli/affected/selection.rb +117 -0
  11. data/lib/simplecov/cli/affected.rb +148 -0
  12. data/lib/simplecov/cli/badge/svg.rb +70 -0
  13. data/lib/simplecov/cli/badge.rb +62 -0
  14. data/lib/simplecov/cli/clean.rb +23 -24
  15. data/lib/simplecov/cli/command_helpers.rb +55 -19
  16. data/lib/simplecov/cli/completions/scripts.rb +114 -0
  17. data/lib/simplecov/cli/completions.rb +83 -0
  18. data/lib/simplecov/cli/coverage.rb +25 -28
  19. data/lib/simplecov/cli/coverage_file.rb +58 -14
  20. data/lib/simplecov/cli/dead_code/output.rb +100 -0
  21. data/lib/simplecov/cli/dead_code.rb +139 -0
  22. data/lib/simplecov/cli/diff/output.rb +45 -0
  23. data/lib/simplecov/cli/diff.rb +35 -67
  24. data/lib/simplecov/cli/dotfile.rb +83 -38
  25. data/lib/simplecov/cli/git.rb +41 -0
  26. data/lib/simplecov/cli/history/output.rb +135 -0
  27. data/lib/simplecov/cli/history.rb +67 -0
  28. data/lib/simplecov/cli/merge.rb +34 -39
  29. data/lib/simplecov/cli/open.rb +12 -15
  30. data/lib/simplecov/cli/patch/changed_lines.rb +149 -0
  31. data/lib/simplecov/cli/patch/output.rb +135 -0
  32. data/lib/simplecov/cli/patch.rb +169 -0
  33. data/lib/simplecov/cli/ratchet/output.rb +44 -0
  34. data/lib/simplecov/cli/ratchet.rb +83 -0
  35. data/lib/simplecov/cli/report.rb +18 -24
  36. data/lib/simplecov/cli/run.rb +8 -9
  37. data/lib/simplecov/cli/serve/report_preparer.rb +7 -6
  38. data/lib/simplecov/cli/serve/static_file_handler.rb +62 -56
  39. data/lib/simplecov/cli/serve.rb +27 -24
  40. data/lib/simplecov/cli/show/annotator.rb +87 -0
  41. data/lib/simplecov/cli/show/sweep.rb +36 -0
  42. data/lib/simplecov/cli/show.rb +133 -0
  43. data/lib/simplecov/cli/status/facts.rb +87 -0
  44. data/lib/simplecov/cli/status.rb +93 -0
  45. data/lib/simplecov/cli/tests/redundancy.rb +78 -0
  46. data/lib/simplecov/cli/tests.rb +148 -0
  47. data/lib/simplecov/cli/uncovered/misses.rb +37 -0
  48. data/lib/simplecov/cli/uncovered.rb +70 -32
  49. data/lib/simplecov/cli/usage.rb +152 -0
  50. data/lib/simplecov/cli/watch/live_report.rb +73 -0
  51. data/lib/simplecov/cli/watch/narrator.rb +55 -0
  52. data/lib/simplecov/cli/watch/poller.rb +45 -0
  53. data/lib/simplecov/cli/watch/session.rb +134 -0
  54. data/lib/simplecov/cli/watch/test_plan.rb +43 -0
  55. data/lib/simplecov/cli/watch.rb +85 -0
  56. data/lib/simplecov/cli.rb +43 -92
  57. data/lib/simplecov/color.rb +19 -37
  58. data/lib/simplecov/combine/branches_combiner.rb +7 -31
  59. data/lib/simplecov/combine/coverage_accumulator.rb +49 -142
  60. data/lib/simplecov/combine/identity_interner.rb +10 -13
  61. data/lib/simplecov/combine/interned_counts.rb +7 -9
  62. data/lib/simplecov/combine/lines_combiner.rb +20 -44
  63. data/lib/simplecov/combine/methods_combiner.rb +9 -35
  64. data/lib/simplecov/combine/results_combiner.rb +4 -21
  65. data/lib/simplecov/combine.rb +0 -6
  66. data/lib/simplecov/command_guesser.rb +20 -34
  67. data/lib/simplecov/configuration/baseline.rb +31 -0
  68. data/lib/simplecov/configuration/coverage.rb +91 -79
  69. data/lib/simplecov/configuration/coverage_criteria.rb +43 -54
  70. data/lib/simplecov/configuration/deprecations.rb +21 -0
  71. data/lib/simplecov/configuration/eval_coverage.rb +6 -10
  72. data/lib/simplecov/configuration/filters.rb +40 -73
  73. data/lib/simplecov/configuration/formatting.rb +74 -83
  74. data/lib/simplecov/configuration/groups.rb +19 -13
  75. data/lib/simplecov/configuration/history.rb +44 -0
  76. data/lib/simplecov/configuration/ignored_entries.rb +31 -22
  77. data/lib/simplecov/configuration/merging.rb +94 -62
  78. data/lib/simplecov/configuration/missed_caps.rb +51 -0
  79. data/lib/simplecov/configuration/production.rb +23 -0
  80. data/lib/simplecov/configuration/test_tracking.rb +48 -0
  81. data/lib/simplecov/configuration/thresholds.rb +33 -62
  82. data/lib/simplecov/configuration/view_coverage.rb +38 -0
  83. data/lib/simplecov/configuration.rb +70 -76
  84. data/lib/simplecov/configuration_error.rb +5 -0
  85. data/lib/simplecov/context_map/union.rb +81 -0
  86. data/lib/simplecov/context_map.rb +187 -0
  87. data/lib/simplecov/coverage_json.rb +2 -5
  88. data/lib/simplecov/coverage_statistics.rb +14 -24
  89. data/lib/simplecov/coverage_violations.rb +157 -64
  90. data/lib/simplecov/current_run.rb +61 -0
  91. data/lib/simplecov/defaults.rb +4 -23
  92. data/lib/simplecov/deprecation.rb +45 -27
  93. data/lib/simplecov/directive.rb +46 -62
  94. data/lib/simplecov/exit_codes/baseline_check.rb +46 -0
  95. data/lib/simplecov/exit_codes/check.rb +17 -11
  96. data/lib/simplecov/exit_codes/exit_code_handling.rb +21 -8
  97. data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +7 -10
  98. data/lib/simplecov/exit_codes/maximum_missed_check.rb +26 -0
  99. data/lib/simplecov/exit_codes/maximum_missed_per_file_check.rb +34 -0
  100. data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +7 -12
  101. data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +11 -10
  102. data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +7 -9
  103. data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +16 -17
  104. data/lib/simplecov/exit_codes.rb +16 -10
  105. data/lib/simplecov/exit_handling.rb +94 -59
  106. data/lib/simplecov/file_list.rb +20 -51
  107. data/lib/simplecov/filter.rb +43 -66
  108. data/lib/simplecov/formatter/base.rb +37 -55
  109. data/lib/simplecov/formatter/baseline_formatter.rb +98 -0
  110. data/lib/simplecov/formatter/coverage_json_writer.rb +29 -31
  111. data/lib/simplecov/formatter/html_formatter/public/index.html +15 -9
  112. data/lib/simplecov/formatter/html_formatter/viewer_data_validator.rb +74 -17
  113. data/lib/simplecov/formatter/html_formatter.rb +24 -41
  114. data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +50 -16
  115. data/lib/simplecov/formatter/json_formatter/production_section_formatter.rb +48 -0
  116. data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +43 -29
  117. data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +14 -10
  118. data/lib/simplecov/formatter/json_formatter.rb +7 -13
  119. data/lib/simplecov/formatter/multi_formatter.rb +5 -11
  120. data/lib/simplecov/formatter/simple_formatter.rb +2 -8
  121. data/lib/simplecov/formatter.rb +14 -10
  122. data/lib/simplecov/group_names.rb +13 -12
  123. data/lib/simplecov/history.rb +115 -0
  124. data/lib/simplecov/last_run.rb +6 -9
  125. data/lib/simplecov/lines_classifier.rb +31 -16
  126. data/lib/simplecov/load_global_config.rb +7 -7
  127. data/lib/simplecov/parallel_adapters/base.rb +13 -41
  128. data/lib/simplecov/parallel_adapters/generic.rb +7 -19
  129. data/lib/simplecov/parallel_adapters/parallel_tests.rb +21 -42
  130. data/lib/simplecov/parallel_adapters.rb +24 -55
  131. data/lib/simplecov/parallel_coordination.rb +39 -49
  132. data/lib/simplecov/parallel_result_merger/worker_payload.rb +33 -0
  133. data/lib/simplecov/parallel_result_merger.rb +67 -126
  134. data/lib/simplecov/process.rb +14 -32
  135. data/lib/simplecov/production/error.rb +11 -0
  136. data/lib/simplecov/production/file_sink.rb +130 -0
  137. data/lib/simplecov/production.rb +249 -0
  138. data/lib/simplecov/profiles/rails.rb +1 -12
  139. data/lib/simplecov/profiles/root_filter.rb +0 -4
  140. data/lib/simplecov/profiles/strict.rb +9 -19
  141. data/lib/simplecov/profiles.rb +11 -33
  142. data/lib/simplecov/report_deferral.rb +11 -15
  143. data/lib/simplecov/report_stamp.rb +6 -9
  144. data/lib/simplecov/result/filter_config.rb +19 -0
  145. data/lib/simplecov/result/missing_source_files_reporter.rb +8 -9
  146. data/lib/simplecov/result/serialization.rb +43 -0
  147. data/lib/simplecov/result/source_file_builder.rb +7 -12
  148. data/lib/simplecov/result.rb +68 -117
  149. data/lib/simplecov/result_adapter.rb +56 -68
  150. data/lib/simplecov/result_merger/contexts.rb +22 -0
  151. data/lib/simplecov/result_merger/legacy_format_adapter.rb +4 -8
  152. data/lib/simplecov/result_merger/resultset_file.rb +20 -27
  153. data/lib/simplecov/result_merger/resultset_run_identity.rb +23 -25
  154. data/lib/simplecov/result_merger/resultset_store.rb +23 -14
  155. data/lib/simplecov/result_merger/unloaded_files.rb +24 -32
  156. data/lib/simplecov/result_merger.rb +59 -58
  157. data/lib/simplecov/result_processing.rb +74 -119
  158. data/lib/simplecov/run_identity.rb +16 -18
  159. data/lib/simplecov/simulate_coverage.rb +34 -50
  160. data/lib/simplecov/source_file/branch.rb +8 -33
  161. data/lib/simplecov/source_file/branch_builder.rb +28 -47
  162. data/lib/simplecov/source_file/builder_context.rb +6 -13
  163. data/lib/simplecov/source_file/line.rb +13 -33
  164. data/lib/simplecov/source_file/line_builder.rb +9 -15
  165. data/lib/simplecov/source_file/method.rb +3 -7
  166. data/lib/simplecov/source_file/method_builder.rb +6 -15
  167. data/lib/simplecov/source_file/ruby_data_parser.rb +59 -66
  168. data/lib/simplecov/source_file/skip_chunks.rb +19 -28
  169. data/lib/simplecov/source_file/source_loader.rb +45 -35
  170. data/lib/simplecov/source_file/statistics.rb +10 -9
  171. data/lib/simplecov/source_file.rb +21 -51
  172. data/lib/simplecov/static_coverage_extractor/condition_folding.rb +63 -114
  173. data/lib/simplecov/static_coverage_extractor/location_conventions.rb +76 -121
  174. data/lib/simplecov/static_coverage_extractor/method_collector.rb +11 -24
  175. data/lib/simplecov/static_coverage_extractor/prism_compat.rb +15 -24
  176. data/lib/simplecov/static_coverage_extractor/value_position.rb +25 -38
  177. data/lib/simplecov/static_coverage_extractor/visitor.rb +47 -64
  178. data/lib/simplecov/static_coverage_extractor.rb +46 -62
  179. data/lib/simplecov/test_tracker/accessors.rb +34 -0
  180. data/lib/simplecov/test_tracker/constant_watch.rb +49 -0
  181. data/lib/simplecov/test_tracker/delta.rb +69 -0
  182. data/lib/simplecov/test_tracker/framework_hooks.rb +130 -0
  183. data/lib/simplecov/test_tracker.rb +162 -0
  184. data/lib/simplecov/unloaded_file_injector.rb +18 -31
  185. data/lib/simplecov/useless_results_remover.rb +7 -6
  186. data/lib/simplecov/version.rb +1 -1
  187. data/lib/simplecov/view_coverage/template_compiler.rb +83 -0
  188. data/lib/simplecov/view_coverage.rb +55 -0
  189. data/lib/simplecov-html.rb +1 -0
  190. data/lib/simplecov.rb +57 -113
  191. data/lib/simplecov_json_formatter.rb +1 -0
  192. data/man/simplecov.1 +349 -0
  193. data/sig/simplecov.rbs +523 -595
  194. metadata +72 -5
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+ require_relative "command_helpers"
5
+ require_relative "open"
6
+ require_relative "serve"
7
+ require_relative "affected"
8
+ require_relative "watch/poller"
9
+ require_relative "watch/live_report"
10
+ require_relative "watch/narrator"
11
+ require_relative "watch/test_plan"
12
+ require_relative "watch/session"
13
+
14
+ module SimpleCov
15
+ module CLI
16
+ # `simplecov watch <command...>`: the coverage inner loop. Serves the report
17
+ # the way `serve` does, polls the tracked files for saves, re-runs the given
18
+ # command on change, and pushes a reload to the open tab over server-sent
19
+ # events when the report regenerates. With a `track_tests` recording in the
20
+ # report, a save re-runs only the tests that touch the changed files, by the
21
+ # same selection walk `simplecov affected` uses.
22
+ module Watch
23
+ extend CommandHelpers
24
+
25
+ extend self
26
+
27
+ def run(args, stdout:, stderr:, **)
28
+ opts, command = parse(args)
29
+ return error(stderr, "missing command to run (e.g. `simplecov watch bundle exec rspec`)") if command.empty?
30
+
31
+ Serve.require_socket
32
+ server = bind(opts, stderr)
33
+ return 1 unless server
34
+
35
+ serve_session(server, command, opts, stdout, stderr)
36
+ end
37
+
38
+ def serve_session(server, command, opts, stdout, stderr)
39
+ launch_browser(server, stderr) if opts.fetch(:open)
40
+ session_for(command, opts, stdout, stderr).run(server)
41
+ ensure
42
+ server.close
43
+ end
44
+
45
+ # Fire-and-forget through the same platform opener `simplecov open` uses,
46
+ # detached so the session never waits on a browser. A platform with no known
47
+ # opener notes the URL instead of failing the watch.
48
+ def launch_browser(server, stderr)
49
+ url = "http://#{Serve.url_host(server.addr.fetch(3))}:#{server.addr.fetch(1)}/"
50
+ opener = Open.browser_opener
51
+ unless opener
52
+ return stderr.puts("simplecov watch: no known browser opener for this platform, open it yourself: #{url}")
53
+ end
54
+
55
+ Process.detach(spawn(*opener, url, out: File::NULL, err: File::NULL))
56
+ end
57
+
58
+ # `order` rather than `parse` stops at the first positional, so the runner
59
+ # command keeps its own flags: `simplecov watch bundle exec rspec --seed 1`
60
+ # passes --seed through untouched.
61
+ def parse(args)
62
+ opts = {port: 0, host: "127.0.0.1", interval: 0.5, open: false} #: Hash[Symbol, untyped]
63
+ rest =
64
+ build_parser do |parser|
65
+ parser.on("--port N", Integer) { |v| opts[:port] = v }
66
+ parser.on("--host HOST") { |v| opts[:host] = v }
67
+ parser.on("--interval SECONDS", Float) { |v| opts[:interval] = v }
68
+ parser.on("--open") { opts[:open] = true }
69
+ end.order(args)
70
+ [opts, rest]
71
+ end
72
+
73
+ def bind(opts, stderr)
74
+ (_ = TCPServer).new(opts.fetch(:host), opts.fetch(:port)) #: TCPServer
75
+ rescue SystemCallError, SocketError => e
76
+ error_nil(stderr, "cannot bind to #{opts.fetch(:host)}:#{opts.fetch(:port)} (#{e})")
77
+ end
78
+
79
+ def session_for(command, opts, stdout, stderr)
80
+ Session.new(command: command, dir: CLI.coverage_dir,
81
+ interval: opts.fetch(:interval), stdout: stdout, stderr: stderr)
82
+ end
83
+ end
84
+ end
85
+ end
data/lib/simplecov/cli.rb CHANGED
@@ -1,50 +1,67 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "optparse"
4
+ require_relative "version"
4
5
  require_relative "color"
5
6
  require_relative "cli/dotfile"
7
+ require_relative "cli/badge"
6
8
  require_relative "cli/clean"
9
+ require_relative "cli/completions"
7
10
  require_relative "cli/coverage_file"
8
11
  require_relative "cli/coverage"
12
+ require_relative "cli/dead_code"
9
13
  require_relative "cli/diff"
14
+ require_relative "cli/history"
10
15
  require_relative "cli/merge"
11
16
  require_relative "cli/open"
17
+ require_relative "cli/patch"
18
+ require_relative "cli/ratchet"
12
19
  require_relative "cli/report"
13
20
  require_relative "cli/run"
14
21
  require_relative "cli/serve"
22
+ require_relative "cli/show"
23
+ require_relative "cli/status"
24
+ require_relative "cli/tests"
25
+ require_relative "cli/affected"
15
26
  require_relative "cli/uncovered"
27
+ require_relative "cli/usage"
28
+ require_relative "cli/watch"
16
29
 
17
30
  module SimpleCov
18
- # Lightweight command-line front-end. `run` dispatches a subcommand
19
- # (`coverage`, `report`, `uncovered`, `merge`, `diff`, `open`, etc.)
20
- # see the `usage` text below for the full list, or run `simplecov help`.
21
- #
22
- # Read-only subcommands consume JSONFormatter output (`coverage.json`),
23
- # which the bundled HTMLFormatter already drops alongside the HTML, so
24
- # no runtime hooking is needed for those. Default paths follow the
25
- # project's `.simplecov` `SimpleCov.coverage_dir` setting when one is
26
- # present, so a project that writes its report somewhere other than
27
- # `coverage/` doesn't have to pass `--input` / `--report` every
28
- # invocation.
31
+ # Lightweight command-line front-end. Read-only subcommands consume
32
+ # JSONFormatter output, which the bundled HTMLFormatter already drops
33
+ # alongside the HTML, so no runtime hooking is needed for those. Default
34
+ # paths follow the project's `.simplecov` `coverage_dir` setting when one is
35
+ # present.
29
36
  module CLI
30
37
  COMMANDS = {
31
38
  "coverage" => Coverage,
39
+ "show" => Show,
32
40
  "run" => Run,
33
41
  "open" => Open,
34
42
  "report" => Report,
43
+ "status" => Status,
44
+ "history" => History,
35
45
  "uncovered" => Uncovered,
46
+ "tests" => Tests,
47
+ "affected" => Affected,
36
48
  "merge" => Merge,
37
49
  "diff" => Diff,
50
+ "patch" => Patch,
51
+ "ratchet" => Ratchet,
52
+ "dead-code" => DeadCode,
38
53
  "serve" => Serve,
39
- "clean" => Clean
54
+ "watch" => Watch,
55
+ "badge" => Badge,
56
+ "clean" => Clean,
57
+ "completions" => Completions
40
58
  }.freeze
41
59
 
42
- module_function
60
+ extend self
43
61
 
44
- # Resolved once per process. Walks up from cwd looking for a
45
- # `.simplecov`; if present, the file is loaded with
46
- # `SimpleCov.start` neutered so it can't trigger coverage tracking
47
- # or an at_exit hook just because we asked it for a config value.
62
+ # Resolved once per process, by walking up from cwd for a `.simplecov` and
63
+ # loading it with `SimpleCov.start` neutered so it can't trigger tracking
64
+ # just because we asked it for a config value.
48
65
  def coverage_dir
49
66
  @coverage_dir ||= Dotfile.coverage_dir
50
67
  end
@@ -53,14 +70,10 @@ module SimpleCov
53
70
  File.join(coverage_dir, "coverage.json")
54
71
  end
55
72
 
56
- # Resolve "should this subcommand colorize?" once per invocation.
57
- # `--no-color` (opts[:no_color]) is the per-invocation kill-switch;
58
- # otherwise we defer to `SimpleCov::Color.enabled?`, which honors
59
- # `NO_COLOR` / `FORCE_COLOR` and falls back to `stream.tty?`.
60
73
  def color_enabled?(opts, stream)
61
74
  return false if opts[:no_color]
62
75
 
63
- SimpleCov::Color.enabled?(stream)
76
+ Color.enabled?(stream)
64
77
  end
65
78
 
66
79
  def default_report
@@ -71,93 +84,31 @@ module SimpleCov
71
84
  File.join(coverage_dir, ".resultset.json")
72
85
  end
73
86
 
74
- # Returns a process exit status (0 on success, non-zero on error).
75
87
  def run(argv, stdout: $stdout, stderr: $stderr)
76
88
  command, *rest = argv
77
89
  handler = COMMANDS[command]
78
90
  return dispatch(handler, command, rest, stdout: stdout, stderr: stderr) if handler
79
91
  return stdout.puts(usage) || 0 if [nil, "help", "--help", "-h"].include?(command)
92
+ return stdout.puts("simplecov #{VERSION}") || 0 if %w[version --version -v].include?(command)
80
93
 
81
94
  stderr.puts("simplecov: unknown command #{command.inspect}", usage)
82
95
  1
83
96
  end
84
97
 
85
- # One rescue covers every subcommand's OptionParser, so a typo'd
86
- # flag or a malformed typed argument becomes a one-line error and
87
- # exit status 1 instead of an unhandled-exception backtrace.
98
+ # One rescue covers every subcommand's OptionParser, so a typo'd flag becomes
99
+ # a one-line error and exit status 1 instead of a backtrace.
88
100
  def dispatch(handler, command, rest, stdout:, stderr:)
89
101
  handler.run(rest, stdout: stdout, stderr: stderr)
102
+ rescue CommandHelpers::HelpRequested
103
+ stdout.puts(Usage.for(self, command))
104
+ 0
90
105
  rescue OptionParser::ParseError => e
91
- stderr.puts("simplecov #{command}: #{e.message} (run `simplecov help` for usage)")
106
+ stderr.puts("simplecov #{command}: #{e} (run `simplecov help` for usage)")
92
107
  1
93
108
  end
94
109
 
95
110
  def usage
96
- <<~USAGE
97
- Usage: simplecov <command> [options]
98
-
99
- Commands:
100
- run <command...> Execute <command> with simplecov pre-loaded
101
- (so a coverage report is generated even
102
- when the project has no test_helper hook)
103
- coverage <path> Print coverage stats for the given file
104
- report Print the overall summary and group totals
105
- uncovered List the lowest-coverage files
106
- merge <files...> Merge multiple .resultset.json files
107
- diff <baseline> Show per-file coverage delta vs baseline
108
- open Open the HTML report in the default browser
109
- serve Serve the coverage report over HTTP
110
- clean Remove the coverage report directory
111
- help Show this message
112
-
113
- Default paths follow SimpleCov.coverage_dir from a project's
114
- `.simplecov` when one is present (#{coverage_dir} for this run).
115
-
116
- coverage / report / uncovered / diff options:
117
- --input PATH Read from PATH instead of #{default_input}
118
- --no-color Disable colorized percentages
119
- (also honors NO_COLOR / FORCE_COLOR env)
120
-
121
- coverage options:
122
- --json Print the file's JSON entry verbatim
123
-
124
- report options:
125
- --json Emit totals and group sections as JSON
126
-
127
- uncovered options:
128
- --threshold N Only show files below N% coverage
129
- --top N Show at most N files (default: 10)
130
- --criterion C line, branch, or method (default: line)
131
- --json Emit results as a JSON array (for CI)
132
-
133
- merge options:
134
- --output PATH Write merged resultset to PATH
135
- (default: #{default_resultset})
136
- --honor-timeout Drop entries older than merge_timeout
137
- --dry-run Print what would be written without
138
- actually writing
139
- -q, --quiet Suppress the success status line
140
-
141
- diff options:
142
- --fail-on-drop Exit non-zero when any file's coverage
143
- dropped vs the baseline (deleted
144
- files don't count as drops)
145
- --json Emit results as a JSON array (for CI)
146
- --threshold N Only show files whose absolute delta
147
- in any criterion is at least N%
148
-
149
- open options:
150
- --report PATH Open PATH instead of #{default_report}
151
-
152
- serve options:
153
- --port N Bind to port N (default: random open port)
154
- --host HOST Bind to HOST (default: 127.0.0.1)
155
-
156
- clean options:
157
- --dry-run Print what would be removed without
158
- deleting anything
159
- -q, --quiet Suppress status lines
160
- USAGE
111
+ Usage.text(self)
161
112
  end
162
113
  end
163
114
  end
@@ -1,22 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleCov
4
- # ANSI colorization for stderr diagnostics. Thresholds mirror the
5
- # HTML formatter (>= 90 green, >= 75 yellow, otherwise red) so a
6
- # team's mental model of "what's the cutoff" is the same whether
7
- # they're reading the terminal output or the HTML report.
8
- #
9
- # Color precedence, highest first:
10
- #
11
- # - `SimpleCov.color = true` / `false` (programmatic override, wins
12
- # over everything; default is `:auto` which falls through)
13
- # - `NO_COLOR` env var (any non-empty value) → off (see no-color.org)
14
- # - `FORCE_COLOR` env var (any non-empty value) → on
15
- # - `stream.tty?` fallback
16
- #
17
- # `NO_COLOR` wins over `FORCE_COLOR` if both env vars are set.
4
+ # ANSI colorization for stderr diagnostics. Thresholds mirror the HTML
5
+ # formatter so a team's mental model of "what's the cutoff" is the same in
6
+ # the terminal and in the report.
18
7
  module Color
19
- GREEN_THRESHOLD = 90
8
+ GREEN_THRESHOLD = 90
20
9
  YELLOW_THRESHOLD = 75
21
10
 
22
11
  ANSI = {
@@ -26,51 +15,44 @@ module SimpleCov
26
15
  reset: "\e[0m"
27
16
  }.freeze
28
17
 
29
- module_function
18
+ extend self
30
19
 
31
- # `stream` is the IO that the colorized text is destined for. The
32
- # formatter writes to stderr, so that's the default. CLI subcommands
33
- # that print to stdout should pass `$stdout` so a redirected pipe
34
- # doesn't get ANSI sequences. See the module-level comment for
35
- # precedence.
20
+ # Precedence, highest first: an explicit `SimpleCov.color` true/false (the
21
+ # default `:auto` falls through), then `NO_COLOR`, then `FORCE_COLOR`, then
22
+ # `stream.tty?`. `NO_COLOR` wins over `FORCE_COLOR` when both are set.
23
+ #
24
+ # `stream` is the IO the colorized text is destined for. CLI subcommands
25
+ # that print to stdout should pass `$stdout` so a redirected pipe doesn't
26
+ # get ANSI sequences.
27
+ #
28
+ # `SimpleCov.color` only exists once the full library is loaded, and the
29
+ # standalone CLI loads this file without it, so a missing config reads as
30
+ # its `:auto` default. A parallel runner can also close a worker's stdio
31
+ # before its at_exit hooks run, and a closed stream is not a tty.
36
32
  def enabled?(stream = $stderr)
37
- # `SimpleCov.color` only exists once the full library is loaded.
38
- # The standalone CLI (`exe/simplecov`) loads `simplecov/color`
39
- # without `simplecov` itself to stay lightweight, so treat a
40
- # missing config the same as its `:auto` default: fall through to
41
- # the env vars and tty check below.
42
33
  config = SimpleCov.color if SimpleCov.respond_to?(:color)
43
34
  return config if [true, false].include?(config)
44
35
  return false if env_set?("NO_COLOR")
45
- return true if env_set?("FORCE_COLOR")
36
+ return true if env_set?("FORCE_COLOR")
46
37
 
47
38
  stream.tty?
48
39
  rescue IOError
49
- # A parallel runner can close a worker's stdio before its at_exit
50
- # hooks run (rspec-conductor does). A closed stream is not a tty.
51
40
  false
52
41
  end
53
42
 
54
43
  def for_percent(percent)
55
- return :green if percent >= GREEN_THRESHOLD
44
+ return :green if percent >= GREEN_THRESHOLD
56
45
  return :yellow if percent >= YELLOW_THRESHOLD
57
46
 
58
47
  :red
59
48
  end
60
49
 
61
- # Wrap `text` in the ANSI sequence for `color` (a key of ANSI).
62
- # Returns the bare text if color is disabled. The `enabled:`
63
- # keyword lets callers (e.g., CLI subcommands honoring `--no-color`)
64
- # override the auto-detection without touching env vars.
65
50
  def colorize(text, color, enabled: enabled?)
66
51
  return text unless enabled
67
52
 
68
53
  "#{ANSI.fetch(color)}#{text}#{ANSI.fetch(:reset)}"
69
54
  end
70
55
 
71
- # Render `percent` as a fixed "NN.NN%" string colored by which
72
- # threshold band it falls into. Callers that want a different
73
- # rendering of the number can pass the pre-rendered `text`.
74
56
  def colorize_percent(percent, text = nil, enabled: enabled?)
75
57
  colorize(text || format("%.2f%%", percent), for_percent(percent), enabled: enabled)
76
58
  end
@@ -6,49 +6,29 @@ require_relative "interned_counts"
6
6
 
7
7
  module SimpleCov
8
8
  module Combine
9
- #
10
- # Combine different branch coverage results on single file.
11
- #
12
- # Should be called through `CoverageAccumulator`.
13
9
  module BranchesCombiner
14
- module_function
10
+ extend self
15
11
 
16
- #
17
- # Return merged branches or the existed branch if other is missing.
18
- #
19
- # Branches inside files are always same if they exist, the difference only in coverage count.
20
- # Branch coverage report for any conditional case is built from hash, it's key is a condition and
21
- # it's body is a hash << keys from condition and value is coverage rate >>.
22
- # ex: branches => { [:if, 3, 8, 6, 8, 36] =>
23
- # {[:then, 4, 8, 6, 8, 12] => 1, [:else, 5, 8, 6, 8, 36] => 2}, ... }
24
- # We create copy of result and update it values depending on the combined branches coverage values.
25
- #
26
- # @return [Hash]
27
- #
28
12
  def combine(coverage_a, coverage_b)
29
13
  merged = absorb({}, coverage_a) #: Hash[untyped, [untyped, Hash[untyped, untyped]]]
30
14
  materialize(absorb(merged, coverage_b))
31
15
  end
32
16
 
33
17
  # Folds `coverage` into `target`, an interned table keyed by condition
34
- # identity. Kept interned (rather than turned back into tuple keys per
35
- # merge) so a fold over N resultsets interns each condition once
36
- # instead of re-interning the whole accumulated table N times.
37
- #
38
- # @return [Hash] `target`
18
+ # identity. Kept interned rather than turned back into tuple keys per merge,
19
+ # so a fold over N resultsets interns each condition once instead of
20
+ # re-interning the whole accumulated table N times.
39
21
  def absorb(target, coverage)
40
22
  return target unless coverage
41
23
 
42
24
  coverage.each do |condition, branches_inside|
43
25
  entry = target[identities[condition]] ||= new_condition(condition)
44
- InternedCounts.absorb_counts(entry[1], branches_inside, identities)
26
+ InternedCounts.absorb_counts(entry.fetch(1), branches_inside, identities)
45
27
  end
46
28
 
47
29
  target
48
30
  end
49
31
 
50
- # Split out so the empty arm table has somewhere to carry its type
51
- # annotation. Only allocated the first time a condition is seen.
52
32
  def new_condition(condition)
53
33
  arms = {} #: Hash[untyped, untyped]
54
34
  [condition, arms]
@@ -56,20 +36,16 @@ module SimpleCov
56
36
 
57
37
  # Turns an interned table back into the tuple-keyed hash the rest of
58
38
  # SimpleCov reads. Done once, at the end of a fold.
59
- #
60
- # @return [Hash]
61
39
  def materialize(target)
62
40
  target.values.to_h { |condition, branches| [condition, branches.values.to_h] }
63
41
  end
64
42
 
65
- # Bounded by the project's branch count, like `RubyDataParser`'s parse
66
- # cache.
67
43
  def identities
68
44
  @identities ||= IdentityInterner.build { |tuple| tuple_identity(tuple) }
69
45
  end
70
46
 
71
- # Branches match on source span, whatever ids the recording processes
72
- # handed them (issue #1233).
47
+ # Branches match on source span, whatever ids the recording processes handed
48
+ # them (#1233).
73
49
  def tuple_identity(tuple)
74
50
  type, _id, start_line, start_column, end_line, end_column = SourceFile::RubyDataParser.call(tuple)
75
51
  [type, start_line, start_column, end_line, end_column].freeze