Skip to content

refactor(analyser): split null guard from out-var check in code fix providers - #848

Merged
samtrion merged 3 commits into
mainfrom
fix/stryker-codefix-register-safe-mode-cs0165
Nov 4, 2026
Merged

samtrion merged 3 commits into
mainfrom
fix/stryker-codefix-register-safe-mode-cs0165

Conversation

@samtrion

@samtrion samtrion commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The latest mutation run (Stryker 5.0.0, solution mode, MTP runner) logs for four code fix providers:

An unidentified mutation in .../ThrowIfCountCodeFixProvider.cs resulted in a compile error (at 46:45) with id: CS0165, message: Use of unassigned local variable comparison
Safe Mode! Stryker will remove all mutations in RegisterCodeFixesAsync and mark them as compile error.

Same for ThrowIfLengthCodeFixProvider (46:45), ThrowIfNullOrEmptyCodeFixProvider (45:45, helperName) and ThrowIfOutOfRangeCodeFixProvider (46:55). According to the mutation report these files have 23, 23, 23 and 26 CompileError mutants (95 in total; per-file counts come from the report, not the log) with 0 Killed/Survived. Overall 439 of 1749 mutants (25.1 %) are compile errors.

Root cause

In RegisterCodeFixesAsync the guard was ifStatement is null || !TryGet...(..., out var x) || x is null. Some mutants of this combined condition break definite assignment of the out variable (CS0165), Stryker cannot recover the single mutant and removes all mutants of the method. The identified trigger is the out-var combined with the preceding ifStatement is null || operand; the proof is the before/after Stryker run, not the source reading alone.

Change

Split the guard into if (ifStatement is null) { return; } and if (!TryGet...(..., out var x) || x is null) { return; } in the four RegisterCodeFixesAsync methods. Nothing else is touched (ApplyFixAsync and the other providers are intentionally left alone; the log shows no Safe Mode for them).

Before / After

Run: https://github.com/dailydevops/arguments/actions/runs/40806141355 (mutation.yml on this branch) vs. the latest run on main (2026-10-27).

metric before after
CS0165 "unidentified mutation" warnings 4 0
"Safe Mode!" lines 4 0
Mutants created 1749 1753
CompileError 439 (25.1 %) 379 (21.6 %)
NoCoverage 605 653
Ignored (block already covered filter) 270 286
Tested 435 435
Killed / Survived 261 / 97 261 / 97
Mutation score 27.10 % 25.82 %
Duration 6:47 6:55

Honest reading: the Safe Mode removals and CS0165 warnings are gone and 60 fewer mutants are compile errors (less than the estimated 95). Those mutants were reclassified, not made testable: they now show up as NoCoverage (+48) and Ignored (+16), the tested set (435) and killed/survived counts are unchanged. Because NoCoverage mutants count against the score, the overall score drops from 27.10 % to 25.82 % even though the report is now more accurate. Killing these mutants requires tests that exercise RegisterCodeFixesAsync of the four providers; that is out of scope here.

Risk / what this does not change

Pure restructuring of an early-return guard; behaviour is identical. The build passes locally; the local test run could not be executed here (apphost copy error), so CI is the check.

…roviders

In RegisterCodeFixesAsync of the Count, Length, NullOrEmpty and OutOfRange
code fix providers the null check of the if statement was chained with the
TryGet... out-var check in a single || condition. Stryker mutants of that
guard break definite assignment of the out variable (CS0165), which makes
Stryker enter Safe Mode and drop all mutants of the whole method as compile
errors.

Splitting the guard into two statements keeps the behaviour identical and
lets the mutants be compiled and tested.
@codecov

codecov Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.31%. Comparing base (b49a9f3) to head (44d8e7c).
⚠️ Report is 13 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #848      +/-   ##
==========================================
+ Coverage   90.75%   91.31%   +0.55%     
==========================================
  Files          39       39              
  Lines        2185     2187       +2     
  Branches      381      385       +4     
==========================================
+ Hits         1983     1997      +14     
+ Misses        121      113       -8     
+ Partials       81       77       -4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@samtrion
samtrion merged commit 5596768 into main Nov 4, 2026
13 checks passed
@samtrion
samtrion deleted the fix/stryker-codefix-register-safe-mode-cs0165 branch November 4, 2026 00:27
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.

1 participant