fix(matching): attribute coverage to generic and overloaded methods - #4
Open
pavelsem wants to merge 1 commit into
Open
fix(matching): attribute coverage to generic and overloaded methods#4pavelsem wants to merge 1 commit into
pavelsem wants to merge 1 commit into
Conversation
A generic method and an overload set both scored 0.0 coverage however well tested, because the two canonical keys could not be equal: Roslyn MyApp.Helper.TryConvertToNumeric<>(string, out T) Cobertura MyApp.Helper.TryConvertToNumeric(string, ref T) Three independent mismatches, each of which alone is enough to lose the match: 1. Method-level generic arity. Roslyn knows the method is generic and writes Foo<>; a Cobertura <method name> usually carries no arity, so neither the exact pass nor the name-only fallback can match. The fallback strips the signature but keeps the arity marker. 2. Parameter modifiers. Roslyn writes `out T`/`in T`; the CLR records one by-ref marker, normalized here to `ref T`. 3. Nullable-reference annotations. Roslyn writes `string?`; a CLR signature cannot express it. 2 and 3 only break the exact-signature pass — but that is the only pass able to resolve an overload set, since the name-only fallback rightly refuses multiple candidates. So overloads went unmatched too. The fix, in two parts: * NormalizeSignatureForMatching reduces a signature to what BOTH sides can express: out/in/ref fold to ref, and `?` is dropped on both sides (so Roslyn's `int?` and Cobertura's Nullable<int> still agree). The canonical key is a matching key, not a display name. * A new arity-relaxed pass sits between the exact and name-only passes. Arity is deliberately KEPT in the exact key so a real Find<T>/Find<T,U> pair stays distinguishable; the new pass only relaxes it, and only when exactly one candidate remains. Ambiguity declines rather than guessing — inventing coverage is worse than reporting none. Verified against a production solution's coverlet output (127 methods, one project): 7 methods gained their real coverage, 0 lost any, crappyMethodCount 7 -> 3, totalCrap 1411 -> 711. TryConvertToNumeric<T> goes 0.00 -> 1.00 and CRAP 552 -> 23 against a Cobertura that always said branch-rate="1" for it. Across that whole solution 51 of 51 crappy generics had read exactly 0.000 — not one generic anywhere carried coverage. Tests: 223 pass in Core. Four existing assertions changed, each a deliberate contract change with the reason recorded at the test: the two generic-key tests now pass unchanged, Cobertura_NullableType loses its `?`, and the overload test that asserted 0.0 was never ambiguous — it is split into the case that now resolves and a genuinely ambiguous one that must still refuse. Not fixed here: Cli.Tests FullPipeline_MinCrapFilter fails on a clean checkout of b173d10 as well, unrelated to matching.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A generic method and an overload set both scored 0.0 coverage however well tested, because the two canonical keys could not be equal:
Roslyn MyApp.Helper.TryConvertToNumeric<>(string, out T)
Cobertura MyApp.Helper.TryConvertToNumeric(string, ref T)
Three independent mismatches, each of which alone is enough to lose the match:
out T/in T; the CLR records one by-ref marker, normalized here toref T.string?; a CLR signature cannot express it.2 and 3 only break the exact-signature pass — but that is the only pass able to resolve an overload set, since the name-only fallback rightly refuses multiple candidates. So overloads went unmatched too.
The fix, in two parts:
?is dropped on both sides (so Roslyn'sint?and Cobertura's Nullable still agree). The canonical key is a matching key, not a display name.Verified against a production solution's coverlet output (127 methods, one project): 7 methods gained their real coverage, 0 lost any, crappyMethodCount 7 -> 3, totalCrap 1411 -> 711.
TryConvertToNumeric goes 0.00 -> 1.00 and CRAP 552 -> 23 against a Cobertura that always said branch-rate="1" for it. Across that whole solution 51 of 51 crappy generics had read exactly 0.000 — not one generic anywhere carried coverage.
Tests: 223 pass in Core. Four existing assertions changed, each a deliberate contract change with the reason recorded at the test: the two generic-key tests now pass unchanged, Cobertura_NullableType loses its
?, and the overload test that asserted 0.0 was never ambiguous — it is split into the case that now resolves and a genuinely ambiguous one that must still refuse.Not fixed here: Cli.Tests FullPipeline_MinCrapFilter fails on a clean checkout of b173d10 as well, unrelated to matching.