Cover the untested analyzer and fixer paths and remove the dead ones - #1436
Merged
Merged
Conversation
Running the test suite with code coverage surfaced 16 rule files containing methods that no test ever executed. Each one was either a behavior with no regression protection or code that cannot be reached at all. Add the missing tests: - MA0168: the symbol action for parameters, as every test declared a top-level local function, leaving methods, constructors, indexers and delegates untested - MA0182: an internal type used only as an array element type - MA0062, MA0192 and MA0099: every enum underlying type, as only int was covered - MA0040 and MA0166: the nested member path (context.Request.RequestAborted) - MA0106: the AddOrUpdate code fix, and MA0105: the four AddOrUpdate and GetOrAdd parameter mappings, none of which was ever applied - MA0020: LongCount() to LongLength, and MA0031: Count(predicate) to Any(predicate) - MA0004, MA0008 and MA0161: the second offered code action - MA0214: a lambda and an anonymous method in the rewritten body - MA0213: flipping the relational operators - MA0179: the length < 1 and length <= 0 comparisons - MA0051: property accessors, constructors and destructors - MA0118: an explicit interface implementation, which offers no code fix Fix MA0023: the fixer matched NameEquals, which is a property initializer, against the constructor parameters, so an attribute using named arguments had RegexOptions.ExplicitCapture appended to the wrong argument, producing code that does not compile. Remove the code the coverage proved unreachable: - EqualityShouldBeCorrectlyImplementedAnalyzer: three methods with no caller - UseAnOverloadThatHasCancellationTokenAnalyzer: GetContainingType, with no caller - Both overload analyzers: the null name handling of NameAndType, as the name always comes from ISymbol.Name, and with it the IsInStaticContext call that only fed that check - OptimizeStringBuilderUsage: ReplaceToStringWithAppendFormat, which the analyzer has never reported - MergeIsPatternChecksFixer: the negated and binary pattern cases, as those patterns always have a PatternSyntax and return earlier - ValidateUnsafeAccessorAttributeUsageFixer: the method and fallback enumeration, as MA0146 only reports local functions - JSInvokableMethodsMustBePublicFixer: the symbol lookup and the last fallback - DoNotUseZeroToInitializeAnEnumValueFixer: the fallbacks of GetTargetEnumType, as the converted type resolves every reported position Line coverage of the rules goes from 90.6% to 91.8% and branch coverage from 78.1% to 79.7%.
This was referenced Sep 7, 2026
Closed
Closed
Closed
Bump Meziantou.Analyzer from 3.0.139 to 3.0.228
Analogy-LogViewer/Analogy.LogViewer.NLog.Targets#565
Closed
Closed
Bump Meziantou.Analyzer from 3.0.139 to 3.0.228
Analogy-LogViewer/Analogy.AspNetCore.LogProvider#549
Closed
Closed
This was referenced Sep 26, 2026
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.
Running the test suite with code coverage surfaced 16 rule files containing methods that no test ever executed. Each one turned out to be either a shipping behavior with no regression protection, or code that cannot be reached at all. This PR covers the former and deletes the latter.
Tests added
RegisterSymbolAction(SymbolKind.Parameter)handler. Every existing test declared a top-level local function, soin/ref readonlyparameters on methods, constructors, indexers and delegates were never analyzed.AnalyzeArrayCreationnever ran).intwas covered, leaving thesbyte/short/ushort/uint/long/ulongarms of the bit-set and zero checks cold.context.Request.RequestAborted).AddOrUpdatecode fix, which was registered but never applied by any test.AddOrUpdateandGetOrAddparameter mappings.LongCount()→LongLength, andCount(predicate)→Any(predicate).ConfigureAwait(true),LayoutKind.Sequential,UseShellExecute = true).<→>=, …). Only==/!=were covered.length < 1andlength <= 0comparisons.Bug fixed
UseRegexExplicitCaptureOptionsFixermatchedNameEquals(a property or field initializer) against the constructor parameters, so an attribute written with named arguments hadRegexOptions.ExplicitCaptureappended to the wrong argument:It now matches
NameColon, with a regression test.Unreachable code removed
EqualityShouldBeCorrectlyImplementedAnalyzer:HasMethodInHierarchy,IsEqualsMethodandIsCompareToMethodhad no caller.UseAnOverloadThatHasCancellationTokenAnalyzer:GetContainingTypehad no caller.NameAndType, as the name always comes fromISymbol.Name. This also removed a per-diagnosticIsInStaticContextcall that existed only to feed that dead check, and two usings that became unused.OptimizeStringBuilderUsage:ReplaceToStringWithAppendFormatand its fix method — the analyzer has never reported that value.MergeIsPatternChecksFixer: the negated and binary pattern cases plusTryGetPatternOperator. Anot/and/orpattern always has aPatternSyntax, so the early return wins (confirmed by coverage on both Roslyn 4.8 and 5.9).ValidateUnsafeAccessorAttributeUsageFixer: the method and fallback enumeration, as MA0146 is only reported forMethodKind.LocalFunction. The local function lookup also moved intoRegisterCodeFixesAsync, per the validate-before-registering guidance inAGENTS.md.JSInvokableMethodsMustBePublicFixer: theGetEnclosingSymbollookup and the last fallback, along with the semantic model they needed.DoNotUseZeroToInitializeAnEnumValueFixer: the four fallbacks ofGetTargetEnumType, as the converted type resolves every reported position (the new tests cover each of those syntactic positions).For the reviewer
Two things were deliberately left alone:
RemoveUnnecessaryBracesInTypeDeclarationFixer.ContainsCommentOrDirectiveInBracesis the single remaining never-executed lambda. It duplicates the analyzer's own guard, which is what the fixer guidance asks for, so it is unreachable by design and was kept.UseAttributeIsDefinedreversed comparisons look like an unfinished feature rather than dead code.IsValidLengthComparisonPatternhas a fully writtenlengthIsOnLeft: falsebranch (0 == length,1 > length,0 >= length, …) in both the analyzer and the fixer, but the analyzer only ever passeslengthIsOnLeft: trueand only inspects the left operand, so0 == x.Lengthreports nothing today. Tests for those six shapes were written, observed to fail, and then removed rather than deleting the branches: whether to wire the feature up or drop it is a product decision.Verification
dotnet buildon the whole solution: succeeds with no warnings.dotnet test --max-parallel-test-modules 2: 20,554 tests pass across Roslyn 4.8, 4.14, 5.0, 5.6 and 5.9 (the default project goes from 4,079 to 4,169 tests).dotnet run --project src/DocumentationGenerator: exits 0, no markdown changes.Rules/: 90.6% → 91.8% lines, 78.1% → 79.7% branches; rule files with a never-executed method drop from 16 to 1.