fix: Moq1203 false positive when Setup call is wrapped in parentheses#895
fix: Moq1203 false positive when Setup call is wrapped in parentheses#895
Conversation
…#887) The chain walk in HasReturnValueSpecification only advanced when the immediate parent was a MemberAccessExpressionSyntax. If the Setup call was wrapped in parentheses, a ParenthesizedExpressionSyntax blocked the walk, causing a false positive. Add GetParentSkippingParentheses extension to SyntaxNodeExtensions that walks through ParenthesizedExpressionSyntax wrappers. Use it in the while loop condition so (mock.Setup(...)).Returns(42) is recognized. Fixes #887 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 📝 WalkthroughWalkthroughFixes a false positive in MethodSetupShouldSpecifyReturnValueAnalyzer by skipping parenthesized expression wrappers when traversing member-access chains so return-value specifications (e.g., .Returns()) are correctly detected for parenthesized Setup calls. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Summary of ChangesHello @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 a false positive in the Moq1203 analyzer, which incorrectly flagged Highlights
Changelog
Activity
Using Gemini Code AssistThe 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
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 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
|
DeepSource reviewed changes in the commit range For detailed review results, please see the PR on DeepSource ↗ PR Report CardCode Review Summary
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. |
There was a problem hiding this comment.
Code Review
The pull request effectively addresses the false positive for Moq1203 when Setup calls are wrapped in parentheses. The introduction of the GetParentSkippingParentheses extension method is a clean and reusable solution to correctly traverse the syntax tree. The added regression tests are comprehensive, covering various scenarios with single and nested parentheses, callback chaining, ReturnsAsync, and Throws, which thoroughly validates the fix. The changes are well-implemented and maintain code quality.
Coverage summary from CodacySee diff coverage on Codacy
Coverage variation details
Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: Diff coverage details
Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: See your quality gate settings Change summary preferences |
There was a problem hiding this comment.
Pull request overview
Fixes a Moq1203 false positive by ensuring the analyzer’s fluent-call chain walk can traverse through parenthesized Setup(...) expressions (e.g., (mock.Setup(...)).Returns(...)).
Changes:
- Add
GetParentSkippingParenthesesto centralize “skipParenthesizedExpressionSyntaxwrappers” logic. - Update
MethodSetupShouldSpecifyReturnValueAnalyzer.HasReturnValueSpecificationto use the new helper when walking the chain. - Add regression test cases for parenthesized/nested-parenthesized fluent setups, including chaining scenarios.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs | Adds regression data + theories for issue #887 (parenthesized fluent setups). |
| src/Common/SyntaxNodeExtensions.cs | Introduces GetParentSkippingParentheses helper extension. |
| src/Analyzers/MethodSetupShouldSpecifyReturnValueAnalyzer.cs | Uses GetParentSkippingParentheses during member-access chain traversal to avoid premature exit on parentheses. |
tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs
Show resolved
Hide resolved
tests/Moq.Analyzers.Test/MethodSetupShouldSpecifyReturnValueAnalyzerTests.cs
Outdated
Show resolved
Hide resolved
Replace invalid C# expression statements (CS0201) with discard assignments to keep test expressions valid while preserving parenthesized wrapping. This ensures the IOperation tree is properly formed during test execution. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@MattKotsenas FYI - TIL that the order by which the analyzer walks (top down vs bottom up) matters. In 1203 the analyzer walks UP (setup -> parent -> returns). Parenthesis break this upward walk. When you walk down (so we'd trigger this analyzer on Returns/Callback) and down into .Expression and find the Setup call. When parenthesis wrap Setup, memberAccess.Expression is ParenthesizedExpressionSyntax instead of InvocationExpressionSyntax. So the analyzers return null and skip. Spot checking looks like 1206 and 1100 also are impacted by this. 1203 is the worst because it's a FP whereas 1206 and 1100 are FN so less noticed. |
…#895) ## Summary - Fix false positive Moq1203 when `Setup(...)` call is wrapped in parentheses - Add `GetParentSkippingParentheses` extension to `SyntaxNodeExtensions` for reuse - Add 9 regression test cases covering single/nested parentheses, Callback chaining, ReturnsAsync, and Throws Fixes #887 ## Root cause The chain walk in `HasReturnValueSpecification` checked `current?.Parent is MemberAccessExpressionSyntax`. When Setup was wrapped in parentheses like `(mock.Setup(...)).Returns(42)`, the parent was `ParenthesizedExpressionSyntax`, so the walk exited early and missed `.Returns()`. ## Fix One-line change: `current?.Parent` becomes `current?.GetParentSkippingParentheses()`, where the new extension walks through any `ParenthesizedExpressionSyntax` wrappers before returning the logical parent. ## Test plan - [x] 9 new test cases (single/nested parens with Returns, Throws, ReturnsAsync, Callback chain, intermediate chain parens, diagnostic cases for sync and async) - [x] All 1964 tests pass - [x] PR review workflow (code-reviewer, silent-failure-hunter, test-analyzer, code-simplifier) passed locally 🤖 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 correctly ignores extra parentheses when evaluating Setup expressions, preventing false positives about missing return-value specifications. * **Tests** * Added regression tests covering parenthesized Setup expressions (both with and without return-value specifications) to ensure correct detection and prevent regressions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Setup(...)call is wrapped in parenthesesGetParentSkippingParenthesesextension toSyntaxNodeExtensionsfor reuseFixes #887
Root cause
The chain walk in
HasReturnValueSpecificationcheckedcurrent?.Parent is MemberAccessExpressionSyntax. When Setup was wrapped in parentheses like(mock.Setup(...)).Returns(42), the parent wasParenthesizedExpressionSyntax, so the walk exited early and missed.Returns().Fix
One-line change:
current?.Parentbecomescurrent?.GetParentSkippingParentheses(), where the new extension walks through anyParenthesizedExpressionSyntaxwrappers before returning the logical parent.Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests