Skip to content

fix: Moq1203 false positives for ReturnsAsync and Callback chaining#886

Merged
rjmurillo merged 8 commits intomainfrom
fix/849-false-positive-moq1203
Feb 15, 2026
Merged

fix: Moq1203 false positives for ReturnsAsync and Callback chaining#886
rjmurillo merged 8 commits intomainfrom
fix/849-false-positive-moq1203

Conversation

@rjmurillo
Copy link
Copy Markdown
Owner

@rjmurillo rjmurillo commented Feb 15, 2026

Summary

  • Walk the full method chain in HasReturnValueSpecification instead of only checking the immediate parent, fixing false positives when Callback() precedes Returns()/Throws()
  • Recognize ReturnsAsync and ThrowsAsync as valid return value specification methods alongside Returns and Throws
  • Replace string-based method name matching with symbol-based detection using MoqKnownSymbols and ISymbolExtensions, consistent with project conventions
  • Fix IsInstanceOf to handle reduced extension methods (via ReducedFrom) so extension methods like ReturnsAsync/ThrowsAsync are correctly identified
  • Add tests exercising the OverloadResolutionFailure candidate symbol fallback path
  • Consolidate AnalyzerVerifier overloads and fix AllAnalyzersVerifier reflection lookup
  • Simplify HasReturnValueSymbol to scan all candidate symbols, not just OverloadResolutionFailure

Fixes #849

Test plan

  • All 20 regression tests pass (ReturnsAsync, Callback+Returns, Callback+ReturnsAsync, Callback+Throws)
  • All 122 Moq1203 tests pass (including 8 new OverloadResolutionFailure tests)
  • Full test suite (1925 tests) passes with no regressions
  • All changed lines have coverage; remaining gaps are pre-existing unreachable guard clauses
  • CI passes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Analyzer now reliably detects return/exception specifications (Returns/ReturnsAsync/Throws/ThrowsAsync) across fluent chains (including Callback) and handles async and overload-resolution edge cases.
  • Documentation
    • Guidance and examples updated to cover async variants, chain-aware placement, and clarified applicability/edge cases.
  • Tests
    • Added extensive regression and scenario tests for async chains, callback combinations, overload-resolution situations, and custom mock scenarios.

rjmurillo and others added 2 commits February 14, 2026 22:56
Reproduces #849 where Moq1203 false positives occur when:
- ReturnsAsync is used instead of Returns
- Callback is chained before Returns/Throws/ReturnsAsync

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HasReturnValueSpecification only checked the immediate parent of
the Setup call and only recognized Returns/Throws. This caused
false positives when Callback preceded Returns, or when
ReturnsAsync/ThrowsAsync was used instead of Returns/Throws.

Walk up through the full method chain and recognize all four
return value specification methods.

Fixes #849

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 15, 2026 06:59
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @rjmurillo, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses false positives in the Moq1203 analyzer by refining its logic for detecting return value specifications. The changes ensure that method chains involving Callback() and asynchronous return methods like ReturnsAsync() and ThrowsAsync() are correctly interpreted, preventing the analyzer from incorrectly flagging valid setups. This significantly improves the accuracy and reliability of the analyzer for common Moq usage patterns.

Highlights

  • Analyzer Logic Enhancement: The MethodSetupShouldSpecifyReturnValueAnalyzer now correctly identifies return value specifications even when Callback() methods are chained before Returns() or Throws() by traversing the full method chain.
  • Asynchronous Method Recognition: The analyzer has been updated to recognize ReturnsAsync and ThrowsAsync as valid return value specification methods, resolving false positives for asynchronous setups.
  • Regression Test Coverage: Five new regression test cases, each with four variants, have been added to cover all reported false positive patterns, ensuring the fixes are robust and prevent future regressions.
Changelog
  • src/Analyzers/MethodSetupShouldSpecifyReturnValueAnalyzer.cs
    • Updated the HasReturnValueSpecification method to walk the entire method chain, rather than just checking the immediate parent, to correctly identify return value specifications.
    • Introduced a new helper method IsReturnValueMethod to consolidate the logic for identifying return value methods, including Returns, ReturnsAsync, Throws, and ThrowsAsync.
  • tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs
    • Added a new Issue849_FalsePositiveTestData property containing five new test cases to cover scenarios involving ReturnsAsync and Callback chaining.
    • Created a new theory test method ShouldNotFlagSetupWithReturnsAsyncOrCallbackChaining to validate that the analyzer no longer flags false positives for the newly added test data.
Activity
  • The pull request description outlines a summary of the changes, including fixes for false positives related to Callback() and ReturnsAsync/ThrowsAsync.
  • A test plan is provided, indicating that all 20 new regression tests pass, and all 80 existing Moq1203 tests pass without regressions.
  • The PR was generated using Claude Code, indicating AI assistance in its creation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 15, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Analyzer expanded to detect Moq return-value specification methods anywhere in a setup call chain (e.g., after intermediate calls like Callback), now recognizing Returns, ReturnsAsync, Throws, and ThrowsAsync, using chain-walking symbol resolution with cancellation and an initialized SupportedDiagnostics property.

Changes

Cohort / File(s) Summary
Analyzer
src/Analyzers/MethodSetupShouldSpecifyReturnValueAnalyzer.cs
Reworked detection to walk member-access/invocation chains, accept MoqKnownSymbols, resolve overload/candidate symbols (cancellation-aware), centralized return-value checks via HasReturnValueSymbol, and changed SupportedDiagnostics to an initialized property.
Symbol helpers / Known symbols
src/Common/ISymbolExtensions.cs, src/Common/WellKnown/MoqKnownSymbols.cs
Added ISymbol extension checks for ReturnsAsync/ThrowsAsync and composite IsMoqReturnValueSpecificationMethod; added MoqKnownSymbols accessors for IThrows, ReturnsExtensions, and async members to expose method symbol sets for overload/candidate handling.
Tests
tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs, tests/Moq.Analyzers.Test/Helpers/AnalyzerVerifier.cs, tests/Moq.Analyzers.Test/Helpers/AllAnalyzersVerifier.cs
Added regression/data-driven tests for async variants, callback chaining, and overload-resolution candidates; introduced new VerifyAnalyzerAsync overloads and adjusted reflection-based verifier to match new signature; test scaffolding updated to include Task BarAsync().
Docs
docs/rules/Moq1203.md
Expanded guidance and examples to include ReturnsAsync/ThrowsAsync, clarified that return/exception specification may appear anywhere in fluent chain (including after Callback), and updated async examples.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Analyzer as Analyzer
participant Semantic as SemanticModel
participant Known as MoqKnownSymbols
participant SymbolExt as ISymbolExtensions

Analyzer->>Semantic: Analyze invocation/member-access chain
Semantic->>Known: Request Moq return-value symbols (Returns/ReturnsAsync/Throws/ThrowsAsync)
Known-->>Semantic: Return method symbols (may include overload candidates)
Semantic->>SymbolExt: Evaluate symbol(s) (IsMoqReturnValueSpecificationMethod)
SymbolExt-->>Analyzer: Match / no-match result (diagnostic decision)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • MattKotsenas
🚥 Pre-merge checks | ✅ 5 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main fix: addressing Moq1203 false positives for ReturnsAsync and Callback chaining, which directly matches the changeset's primary objective.
Linked Issues check ✅ Passed The PR comprehensively addresses #849 by fixing false positives for ReturnsAsync/ThrowsAsync methods and Callback chaining, recognizing async return-value specifications, and implementing symbol-based detection per requirements.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing Moq1203 false positives: symbol infrastructure updates, analyzer logic enhancements, documentation updates, and corresponding test coverage are all in-scope for this fix.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/849-false-positive-moq1203

Comment @coderabbitai help to get the list of available commands and usage tips.

@deepsource-io
Copy link
Copy Markdown

deepsource-io Bot commented Feb 15, 2026

DeepSource Code Review

DeepSource reviewed changes in the commit range dc4aea5..78447d0 on this pull request. Below is the summary for the review, and you can see the individual issues we found as review comments.

For detailed review results, please see the PR on DeepSource ↗

PR Report Card

Security × 0 issues Overall PR Quality   

Focus Area: Hygiene

Guidance
Fix 5 high-severity naming convention issues for methods with return type `Task` in tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs.
Reliability × 0 issues
Complexity × 1 issue
Hygiene × 5 issues

Code Review Summary

Analyzer Status Summary Details
C# 6 new issues detected. 2 existing issues fixed. Review ↗
How are these analyzer statuses calculated?

Administrators can configure which issue categories are reported and cause analysis to be marked as failed when detected. This helps prevent bad and insecure code from being introduced in the codebase. If you're an administrator, you can modify this in the repository's settings.

Comment thread tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs Outdated
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses false positives in the Moq1203 analyzer by correctly traversing the entire method chain to find return value specifications like Returns or Throws. The changes also properly recognize ReturnsAsync and ThrowsAsync. The implementation in HasReturnValueSpecification is robust, and the added regression tests are comprehensive and cover the reported issues well. I have one suggestion regarding code duplication in the test file to improve maintainability.

Comment thread tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs Outdated
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Feb 15, 2026

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.14% (target: -1.00%) 100.00% (target: 95.00%)
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (dc4aea5) 2020 1794 88.81%
Head commit (78447d0) 2045 (+25) 1819 (+25) 88.95% (+0.14%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#886) 34 34 100.00%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request attempts to fix false positives in the Moq1203 analyzer ("Method setup should specify a return value") that were introduced in v0.4.0. The issue (#849) reported that:

  1. ReturnsAsync() was not being recognized as a valid return value specification
  2. Method chaining with Callback() before Returns() or Throws() was incorrectly flagged

Changes:

  • Modified HasReturnValueSpecification to walk the entire method chain instead of only checking the immediate parent
  • Added IsReturnValueMethod helper to recognize ReturnsAsync and ThrowsAsync alongside Returns and Throws
  • Added 20 regression tests (5 test cases × 4 namespace/Moq version combinations) covering all reported false positive patterns

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/Analyzers/MethodSetupShouldSpecifyReturnValueAnalyzer.cs Updated HasReturnValueSpecification to walk full method chain and recognize ReturnsAsync/ThrowsAsync methods
tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs Added regression test data and test method for Issue #849 false positive scenarios

Comment thread src/Analyzers/MethodSetupShouldSpecifyReturnValueAnalyzer.cs Outdated
@coderabbitai coderabbitai Bot added analyzers Change that impacts an analyzer behavior bug releasable labels Feb 15, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs`:
- Around line 53-76: Add a regression test case for ThrowsAsync to
Issue849_FalsePositiveTestData so the analyzer test covers all four return-value
methods; edit the data array inside the Issue849_FalsePositiveTestData method to
include a new test string that calls Setup on a mock of IFoo for an async method
and specifies ThrowsAsync (also include a variant where Callback precedes
ThrowsAsync to mirror the existing patterns), then return the augmented data as
before with WithNamespaces() and WithMoqReferenceAssemblyGroups().

rjmurillo and others added 2 commits February 14, 2026 23:59
- Handle CandidateSymbols for overload resolution failure, matching
  the established pattern in SemanticModelExtensions
- Pass CancellationToken through to GetSymbolInfo for cancellation
  support
- Pass full MemberAccessExpressionSyntax (not .Name) to GetSymbolInfo,
  consistent with other call sites
- Update stale Description field and class xmldoc to list all four
  recognized methods (Returns, ReturnsAsync, Throws, ThrowsAsync)
- Add ThrowsAsync test coverage (direct and via Callback chaining)
- Add negative test: Callback-only setup still flags Moq1203
- Add negative test: async method without return specification flags
- Extract shared VerifyMock helper to eliminate duplicate test methods
- Update docs/rules/Moq1203.md with async and Callback chain examples

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cache SupportedDiagnostics with auto-property initializer (was
  allocating on every access via expression-bodied member)
- Add helpLinkUri to DiagnosticDescriptor (missing vs all other
  analyzers)
- Replace LINQ .Any() on CandidateSymbols with foreach to avoid
  ImmutableArray enumerator allocation in hot path
- Remove unused knownSymbols out parameter from TryGetSetupInvocation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/Analyzers/MethodSetupShouldSpecifyReturnValueAnalyzer.cs`:
- Around line 152-165: The loop in MethodSetupShouldSpecifyReturnValueAnalyzer
that walks from setupSyntax using the variable current only advances when the
parent is a MemberAccessExpressionSyntax, so wrapper nodes
(ParenthesizedExpressionSyntax, CastExpressionSyntax,
ConditionalAccessExpressionSyntax, etc.) can prematurely stop the walk and cause
false positives; update the while/advance logic around current (the chain-walk
that ultimately calls HasReturnValueSymbol) to first skip over wrapper nodes by
repeatedly setting current = current.Parent while the parent is one of those
wrapper node types, then continue checking for
MemberAccessExpressionSyntax/InvocationExpressionSyntax and calling
HasReturnValueSymbol, and add a regression test that covers a parenthesized
Setup invocation like (new Mock<IFoo>().Setup(...)).Returns(...).

Comment thread src/Analyzers/MethodSetupShouldSpecifyReturnValueAnalyzer.cs
rjmurillo and others added 2 commits February 15, 2026 08:59
Replace name-based string matching in IsReturnValueMethod with
symbol-based detection using MoqKnownSymbols and ISymbolExtensions
helpers, consistent with how other Moq methods are identified.

- Add IThrows, ReturnsExtensions symbols to MoqKnownSymbols
- Add IsMoqThrowsMethod, IsMoqReturnsAsyncMethod, IsMoqThrowsAsyncMethod,
  and IsMoqReturnValueSpecificationMethod helpers to ISymbolExtensions
- Fix IsInstanceOf to handle reduced extension methods via ReducedFrom
- Thread MoqKnownSymbols through the analyzer call chain
- Delete dead IsReturnValueMethod string matcher

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add tests that exercise the candidate symbol fallback path in
HasReturnValueSymbol, where Roslyn reports OverloadResolutionFailure
instead of resolving the method directly. Uses deliberately mismatched
argument types to force the fallback.

- Add AnalyzerVerifier overload accepting CompilerDiagnostics
- Add tests for return value method recognized via candidate symbols
- Add tests for non-return-value candidates still flagging Moq1203

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs (1)

174-237: 🧹 Nitpick | 🔵 Trivial

Consider extracting the common source template to reduce duplication.

Both VerifyMock and VerifyMockIgnoringCompilerErrors define identical IFoo interfaces and test class structures. If the interface needs to change in the future (e.g., adding a new method for testing), it would need to be updated in both places.

♻️ Proposed refactor to extract common template
+    private static string BuildTestSource(string `@namespace`, string mock)
+    {
+        return $$"""
+            {{`@namespace`}}
+
+            public interface IFoo
+            {
+                bool DoSomething(string value);
+                int GetValue();
+                int Calculate(int a, int b);
+                Task<int> BarAsync();
+                void DoVoidMethod();
+                void ProcessData(string data);
+                string Name { get; set; }
+            }
+
+            internal class UnitTest
+            {
+                private void Test()
+                {
+                    {{mock}}
+                }
+            }
+            """;
+    }
+
     private async Task VerifyMock(string referenceAssemblyGroup, string `@namespace`, string mock)
     {
-        string source = $$"""
-            {{`@namespace`}}
-
-            public interface IFoo
-            ...
-            """;
+        string source = BuildTestSource(`@namespace`, mock);
 
         output.WriteLine(source);
 
         await Verifier.VerifyAnalyzerAsync(
             source,
             referenceAssemblyGroup).ConfigureAwait(false);
     }
 
     private async Task VerifyMockIgnoringCompilerErrors(string referenceAssemblyGroup, string `@namespace`, string mock)
     {
-        string source = $$"""
-            {{`@namespace`}}
-
-            public interface IFoo
-            ...
-            """;
+        string source = BuildTestSource(`@namespace`, mock);
 
         output.WriteLine(source);
 
         await Verifier.VerifyAnalyzerAsync(
             source,
             referenceAssemblyGroup,
             CompilerDiagnostics.None).ConfigureAwait(false);
     }

Simplify HasReturnValueSymbol to check resolved symbol first, then scan
all candidates regardless of CandidateReason (not just
OverloadResolutionFailure). This prevents false positives when Roslyn
reports Ambiguous, Inaccessible, or other candidate reasons.

Consolidate AnalyzerVerifier overloads by folding CompilerDiagnostics
into the primary method as an optional parameter. Update
AllAnalyzersVerifier reflection to match the new 5-parameter signature.

Extract BuildSource in tests to eliminate duplicated source template.
Add test cases for Throws<T>() on async methods and Throws(Exception)
instance form with Callback chaining.

Clean up documentation: remove implementation details from Moq1203.md,
fix imprecise wording, remove redundant inline comments, fix inaccurate
XML doc returns tags, remove coupling parenthetical from MoqKnownSymbols.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rjmurillo rjmurillo changed the title Fix Moq1203 false positives for ReturnsAsync and Callback chaining fix: Moq1203 false positives for ReturnsAsync and Callback chaining Feb 15, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs`:
- Around line 57-93: Add a regression entry to Issue849_FalsePositiveTestData to
cover parenthesized setup chains so the chain-walk fix doesn't regress on
wrapper nodes; specifically, insert a test string like "(new
Mock<IFoo>().Setup(x => x.GetValue())).Returns(42);" into the IEnumerable
returned by Issue849_FalsePositiveTestData (the same array that already contains
ReturnsAsync/ThrowsAsync/Callback cases) so the analyzer test verifies that
parenthesized chains do not trigger Moq1203.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Feb 15, 2026
Rename VerifyMock and VerifyMockIgnoringCompilerErrors to follow the
project convention for private async methods (consistent with
VerifyAnalyzerDynamicallyAsync, CreateProjectAsync, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rjmurillo rjmurillo merged commit 6ec810c into main Feb 15, 2026
23 of 25 checks passed
@rjmurillo rjmurillo deleted the fix/849-false-positive-moq1203 branch February 15, 2026 23:29
rjmurillo added a commit that referenced this pull request Feb 17, 2026
…886)

## Summary
- Walk the full method chain in `HasReturnValueSpecification` instead of
only checking the immediate parent, fixing false positives when
`Callback()` precedes `Returns()`/`Throws()`
- Recognize `ReturnsAsync` and `ThrowsAsync` as valid return value
specification methods alongside `Returns` and `Throws`
- Replace string-based method name matching with symbol-based detection
using `MoqKnownSymbols` and `ISymbolExtensions`, consistent with project
conventions
- Fix `IsInstanceOf` to handle reduced extension methods (via
`ReducedFrom`) so extension methods like `ReturnsAsync`/`ThrowsAsync`
are correctly identified
- Add tests exercising the `OverloadResolutionFailure` candidate symbol
fallback path
- Consolidate `AnalyzerVerifier` overloads and fix
`AllAnalyzersVerifier` reflection lookup
- Simplify `HasReturnValueSymbol` to scan all candidate symbols, not
just `OverloadResolutionFailure`

Fixes #849

## Test plan
- [x] All 20 regression tests pass (ReturnsAsync, Callback+Returns,
Callback+ReturnsAsync, Callback+Throws)
- [x] All 122 Moq1203 tests pass (including 8 new
OverloadResolutionFailure tests)
- [x] Full test suite (1925 tests) passes with no regressions
- [x] All changed lines have coverage; remaining gaps are pre-existing
unreachable guard clauses
- [ ] CI passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Analyzer now reliably detects return/exception specifications
(Returns/ReturnsAsync/Throws/ThrowsAsync) across fluent chains
(including Callback) and handles async and overload-resolution edge
cases.
* **Documentation**
* Guidance and examples updated to cover async variants, chain-aware
placement, and clarified applicability/edge cases.
* **Tests**
* Added extensive regression and scenario tests for async chains,
callback combinations, overload-resolution situations, and custom mock
scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@abatishchev
Copy link
Copy Markdown

abatishchev commented Feb 19, 2026

A code like this:

validator.Setup(v => v.ValidateAsync(It.IsAny<ValidationContext<AsyncOperationResult>>(), It.IsAny<CancellationToken>()))
         .ReturnsAsync(result);

is flagged for Moq1203 after updating to 0.4.1-alpha. Would this be fixed by the PR too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

analyzers Change that impacts an analyzer behavior bug documentation releasable

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect detection/flagging of rule Moq1203 after upgrading to v0.4.0

3 participants