Skip to content

Add :eval_generated filter for ignore_branches and ignore_methods#1196

Merged
sferik merged 1 commit into
mainfrom
ignore-eval-generated
May 27, 2026
Merged

Add :eval_generated filter for ignore_branches and ignore_methods#1196
sferik merged 1 commit into
mainfrom
ignore-eval-generated

Conversation

@sferik
Copy link
Copy Markdown
Collaborator

@sferik sferik commented May 27, 2026

Rails delegate (and other module_eval / class_eval / instance_eval macros that pass __FILE__ and __LINE__) inject method and branch entries into a file's coverage data even when the static source has nothing at that line. Ruby's Coverage library attributes the eval'd code to the caller's position, so a single delegate call shows up as a missed def and a missed if branch wherever the macro fires. The previous workaround was to disable eval coverage entirely, which loses the legitimate signal.

Adds the :eval_generated token to SimpleCov.ignore_branches and adds a new SimpleCov.ignore_methods with the same token. Both filters walk the static source through SimpleCov::StaticCoverageExtractor (Prism) and drop any Coverage tuple whose start line lacks a real def keyword (for methods) or branch construct (for branches). Line presence is the matcher, so a real branch or def that shares a line with an eval-generated entry survives. Prism ships with Ruby 3.3+, and on older Rubies gem install prism enables the filter, otherwise the setting is a no-op.

The filters are opt-in and stored regardless of which coverage criteria are enabled at call time, matching the existing ignore_branches lifecycle. Unknown tokens raise SimpleCov::ConfigurationError to catch typos. README and CHANGELOG updated, with specs covering the DSL, the new StaticCoverageExtractor.real_source_positions helper, and SourceFile integration.

This comment was marked as resolved.

Rails delegate (and other module_eval / class_eval / instance_eval
macros that pass __FILE__ and __LINE__) inject method and branch entries
into a file's coverage data even when the static source has nothing at
that line. Ruby's Coverage library attributes the eval'd code to the
caller's position, so a single delegate call shows up as a missed def
and a missed if branch wherever the macro fires. The previous workaround
was to disable eval coverage entirely, which loses the legitimate
signal.

Adds the :eval_generated token to SimpleCov.ignore_branches and adds a
new SimpleCov.ignore_methods with the same token. Both filters walk the
static source through SimpleCov::StaticCoverageExtractor (Prism) and
drop any Coverage tuple whose start line lacks a real def keyword (for
methods) or branch construct (for branches). Line presence is the
matcher, so a real branch or def that shares a line with an
eval-generated entry survives. Prism ships with Ruby 3.3+, and on older
Rubies gem install prism enables the filter, otherwise the setting is a
no-op.

The filters are opt-in and stored regardless of which coverage criteria
are enabled at call time, matching the existing ignore_branches
lifecycle. Unknown tokens raise SimpleCov::ConfigurationError to catch
typos. README and CHANGELOG updated, with specs covering the DSL, the
new StaticCoverageExtractor.real_source_positions helper, and SourceFile
integration.

Resolves #1046.
@sferik sferik force-pushed the ignore-eval-generated branch from 78b81a9 to ad7b76c Compare May 27, 2026 04:26
@sferik sferik merged commit dec1550 into main May 27, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants