Report MA0102 on the event instead of its accessors - #1356
Merged
Conversation
This was referenced Aug 27, 2026
Closed
Closed
Open
Bump Meziantou.Analyzer from 3.0.103 to 3.0.190
Analogy-LogViewer/Analogy.LogViewer.OpenTelemetry#99
Open
Closed
Closed
Open
This was referenced Aug 31, 2026
Open
Bump Meziantou.Analyzer from 3.0.139 to 3.0.195
Analogy-LogViewer/Analogy.AspNetCore.LogProvider#544
Open
Open
Open
Open
Open
Open
Open
Open
Open
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.
MA0102 reported event accessors, whose fix does not compile
readonlycannot be applied to an event accessor —readonly add { }is CS1609. ButMakeMemberReadOnlyAnalyzerreported each accessorseparately, and the fixer put the modifier on the accessor whenever the sibling accessor did not already have it,
which for an event is always. So
Add readonlyonproduced
readonly add { }, which does not compile, and the analyzer kept reporting the accessor, so applying thefix again appended another
readonly. OnlyFix all occurrencesproduced valid code, because it saw bothdiagnostics at once and hoisted the modifier onto the event.
There is no fix for a single event accessor:
readonlyon an event covers both of them. So the analyzer nowcollects the accessors that can be readonly per event and reports the event once every one of its accessors
qualifies, the way it already reports the property rather than the accessor for an expression-bodied property. The
fixer adds the modifier to the event declaration, and the incremental fix and the fix all now agree.
An event whose accessors do not all qualify is no longer reported at all — previously the fixable-looking accessor
was reported on its own, and taking that fix would have produced a
readonlyevent with an accessor that writes toa field.
CannotBeReadOnly_EventWithOnlyOneReadOnlyAccessorcovers that, andCannotBeReadOnly_ReadOnlyEventcovers the already-readonly case.
CanBeReadOnly_Eventmoves fromShouldBatchFixCodeWithtoShouldFixCodeWith: the incremental fix produces theright code now, and the test harness compiles the fixed code, so it is a regression test for the CS1609.
MA0156 and MA0157 in the same test
The two rules contradict each other — "a method returning
IAsyncEnumerable<T>must / must not use theAsyncsuffix". Both are
isEnabledByDefault: falseand a project enables one of them, butWithAnalyzer<T>()enablesevery rule an analyzer supports, so the two code fixers fought over the same method: the fix for one produced code
the other reported. The two code fix tests now pin the rule they are about with
WithDefaultAnalyzerId.No production code changes for this one — it is a test that was configured in a way no real project can be.
Verification
Meziantou.Analyzer.Test.roslyn5.9: 3842 tests, 0 failures (2 new).MakeMemberReadOnlyAnalyzerTests+MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzerTestsalso runagainst roslyn4.8: 59 tests, 0 failures.
dotnet run --project src/DocumentationGeneratorreports no change.The MA0156/MA0157 half is unrelated to the MA0102 fix and can be split into its own PR if you prefer to review
them separately.