Skip to content

Commit 803dcbc

Browse files
committed
Bump version to 1.0.2
1 parent 177b0cc commit 803dcbc

6 files changed

Lines changed: 19 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
1.0.2 (2026-07-18)
2+
==================
3+
4+
## Bugfixes
5+
* The standalone `simplecov` CLI's colorizing subcommands (`report`, `uncovered`, `coverage`, `diff`) no longer crash with `NoMethodError: undefined method 'color'` when run in a project without a `.simplecov` file. The CLI deliberately loads only `simplecov/cli` rather than the full library, so `SimpleCov.color` was undefined unless a dotfile load had incidentally defined it — and `--no-color` was the only workaround, since the documented `NO_COLOR` env var was checked after the line that raised. `Color.enabled?` now treats missing configuration the same as its `:auto` default and falls through to `NO_COLOR` / `FORCE_COLOR` / TTY detection. Reported with an exemplary diagnosis by @hasghari. See #1231.
6+
* Branch tuples synthesized for tracked-but-unloaded files now match Ruby's `Coverage` for a safe-navigation call that takes a block. For `x&.foo { ... }` (and the second link of a chain like `x&.foo&.bar { ... }`) the extractor keyed the branch on the call node's full source range, which extends through the attached block, while `Coverage` ends the range at the call itself — so a simulated entry merging with a real one produced a phantom, permanently-missed branch, the same failure mode as the `elsif` fix in 1.0.1. Reported with an exemplary diagnosis and a suggested fix by @alexdeng-mp. See #1233.
7+
* Prompted by the two reports above, an exhaustive differential audit of `StaticCoverageExtractor` against Ruby's `Coverage` — a fuzzing harness that runs thousands of generated programs through both and diffs the branch tuples, now part of the spec suite (opt-in via `SIMPLECOV_FUZZ=1`) — surfaced and fixed four more mismatches of the same phantom-branch class. Conditions that are compile-time literals (`if true`, `if 1`, a ternary on a literal) are folded away by Ruby's compiler and no longer produce synthesized branches (`while true` still does — loops are not folded). On Ruby 3.3, three legacy conventions now match: the body range of a do-while (`begin ... end while`), the location of empty branch arms (which on 3.3 depends on whether the construct is in value or void position), and one-line pattern matching (`x => pattern` / `x in pattern`), which emits a `:case` branch on 3.3 and nothing on 3.4+. The audit also caught a crash on Ruby 3.3's stdlib Prism (0.19), which still exposes the else clause of `UnlessNode` / `CaseNode` / `CaseMatchNode` under its pre-1.3 name `consequent`: the extractor raised internally and silently dropped simulated branch and method data for any file containing `unless`/`else` or a `case` with an empty arm, unless a newer prism gem happened to be installed.
8+
* As a defensive layer against any future extractor drift, merging now treats an actually-executed file's branch and method data as authoritative: when a resultset that merely tracked a file (with simulated, statically-derived tuples) merges with one from a process that really loaded it, the synthesized tuples are dropped rather than unioned. This contains any undiscovered mismatch to denominator inflation on files no process loaded, instead of phantom misses on fully-covered ones. Line coverage still combines from both sides, so tracked-but-unloaded files keep contributing to the line denominator as before.
9+
* Method coverage no longer reports phantom uncovered methods for `define_method` / `define_singleton_method` blocks defined onto more than one receiver — e.g. a module's `included` hook defining the same block on every including class. Ruby records one method entry per receiver, all pointing at the same source location, so any receiver whose copy was never called showed as an uncovered method on a line with 100% line coverage. Entries are now aggregated by (name, source location) with hit counts summed, and cross-process merging matches methods on the same source identity rather than on the receiver class. Reported with an exemplary diagnosis by @bkuhlmann. See #1234.
10+
* Branch coverage under `enable_coverage :eval` no longer inflates denominators or reports phantom missed branches for templates compiled more than once — e.g. hanami-view compiles each template once per view class, and every `ERB.new(...).result` is a fresh compile. Ruby's `Coverage` emits a fresh set of branch entries per compile of the same file (nondeterministically through Ruby 4.0, consistently on current ruby master — see https://bugs.ruby-lang.org/issues/22203), each counting only the renders that flowed through that compile, so a side exercised under one compile appeared as a permanently-missed branch in another compile's entry at the same location, and `ignore_branches :implicit_else` swung the report wildly by stripping only the synthetic-else halves of the duplicates. Duplicated conditions are now aggregated by source location with arm counts summed. Reported with an exemplary diagnosis by @bkuhlmann. See #1235.
11+
112
1.0.1 (2026-07-14)
213
==================
314

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
simplecov (1.0.1)
4+
simplecov (1.0.2)
55

66
GEM
77
remote: https://rubygems.org/

lib/simplecov/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module SimpleCov
4-
VERSION = "1.0.1"
4+
VERSION = "1.0.2"
55
end

test_projects/faked_project/Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ../..
33
specs:
4-
simplecov (1.0.1)
4+
simplecov (1.0.2)
55

66
GEM
77
remote: https://rubygems.org/
@@ -136,7 +136,7 @@ CHECKSUMS
136136
rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
137137
rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
138138
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
139-
simplecov (1.0.1)
139+
simplecov (1.0.2)
140140
sys-uname (1.5.1) sha256=784d7e6491b0393c25cbbe5ac38324ac7be9fda083a6094832648af669386d7b
141141
test-unit (3.7.8) sha256=689d1ca53f4d46f678b4e5d68d8e4294f87fc5e8b9238cc4de7c5727e8d65943
142142

test_projects/monorepo/Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: /Users/erik/Code/Ruby/simplecov
33
specs:
4-
simplecov (1.0.1)
4+
simplecov (1.0.2)
55

66
PATH
77
remote: base
@@ -52,7 +52,7 @@ CHECKSUMS
5252
rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
5353
rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
5454
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
55-
simplecov (1.0.1)
55+
simplecov (1.0.2)
5656

5757
BUNDLED WITH
5858
4.0.16

test_projects/parallel_tests/Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ../..
33
specs:
4-
simplecov (1.0.1)
4+
simplecov (1.0.2)
55

66
GEM
77
remote: https://rubygems.org/
@@ -43,7 +43,7 @@ CHECKSUMS
4343
rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
4444
rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
4545
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
46-
simplecov (1.0.1)
46+
simplecov (1.0.2)
4747

4848
BUNDLED WITH
4949
4.0.16

0 commit comments

Comments
 (0)