Skip to content

feat: support SimpleLambdaExpressionSyntax in callback validation#1042

Merged
rjmurillo merged 33 commits intomainfrom
feat/1012-simple-lambda-support
Mar 9, 2026
Merged

feat: support SimpleLambdaExpressionSyntax in callback validation#1042
rjmurillo merged 33 commits intomainfrom
feat/1012-simple-lambda-support

Conversation

@rjmurillo-bot
Copy link
Copy Markdown
Collaborator

@rjmurillo-bot rjmurillo-bot commented Mar 7, 2026

Summary

Closes #1012.

  • Widens TryGetCallbackLambda return type from ParenthesizedLambdaExpressionSyntax? to LambdaExpressionSyntax?, removing the explicit bail-out for SimpleLambdaExpressionSyntax in delegate constructors
  • Adds GetLambdaParameters helper to uniformly extract parameters from both ParenthesizedLambdaExpressionSyntax and SimpleLambdaExpressionSyntax
  • Adds GetDiagnosticNode helper for correct diagnostic span placement on each lambda form
  • Adds test cases for simple lambdas in delegate constructors (both valid and invalid patterns)

Test plan

  • All 2917 existing tests pass with zero failures
  • New valid patterns: new Action<string>(x => { }) and new Func<string, int>(x => 42) produce no diagnostic
  • New invalid patterns: new Action<int>(x => { }) (wrong type) and new Action<int>(x => { }) (argument count mismatch) produce Moq1100
  • dotnet build succeeds with zero warnings

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Broader support for simple lambdas and delegate-wrapped callbacks in validation and diagnostics.
    • Improved fixer: converts simple lambdas to parenthesized form, rebuilds parameter lists from the mocked method, preserves formatting, and skips unsafe fixes inside delegate-constructor contexts.
    • Better symbol resolution fallback when overload resolution fails.
  • Tests

    • Added/extended tests for simple-lambda callbacks, delegate-wrapped callbacks, and new fixer scenarios; updated expected parameter renames.
  • Chores

    • Test helper overload for configurable code-fix iteration counts.

)

TryGetCallbackLambda previously only handled ParenthesizedLambdaExpressionSyntax,
explicitly skipping SimpleLambdaExpressionSyntax in delegate constructors. This
caused the analyzer to miss validating single-parameter lambdas like
`new Action<int>(x => { })`.

Changes:
- Widen TryGetCallbackLambda return type to LambdaExpressionSyntax
- Add GetLambdaParameters helper to extract parameters from both lambda forms
- Add GetDiagnosticNode helper for correct diagnostic span placement
- Remove the SimpleLambdaExpressionSyntax bail-out guard
- Add test cases for simple lambdas in delegate constructors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rjmurillo-bot rjmurillo-bot requested a review from rjmurillo as a code owner March 7, 2026 22:45
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 7, 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 and fixer expanded to accept general LambdaExpressionSyntax (including SimpleLambdaExpressionSyntax in delegate constructors). New helpers extract lambda parameters and diagnostic nodes; the fixer gains separate paths for parenthesized and simple lambdas and builds parameter lists from the mocked method symbol. Tests and test helpers updated.

Changes

Cohort / File(s) Summary
Analyzer
src/Analyzers/CallbackSignatureShouldMatchMockedMethodAnalyzer.cs
Replaced ParenthesizedLambdaExpressionSyntax-specific logic with LambdaExpressionSyntax handling. Added GetLambdaParameters() and GetDiagnosticNode() helpers. TryGetCallbackLambda() now returns LambdaExpressionSyntax and supports delegate-constructor callbacks. Validation entry points updated to accept LambdaExpressionSyntax.
Code Fixer
src/CodeFixes/CallbackSignatureShouldMatchMockedMethodFixer.cs
Added separate fix paths: FixParenthesizedCallbackSignatureAsync() and FixSimpleLambdaCallbackSignatureAsync(). New helpers: ResolveNewParameterListAsync(), FindSingleMockedMethod(), BuildParameterList(), GetParameterModifiers(), and IsInsideDelegateConstructor(). Preserves trivia and adds guarded early exits when semantic info is missing.
Common / Semantic
src/Common/SemanticModelExtensions.cs
In FindSetupMethodFromCallbackInvocation, fall back to the first CandidateSymbol when SymbolInfo.Symbol is null to continue overload-resolution flow.
Analyzer Tests
tests/Moq.Analyzers.Test/CallbackSignatureShouldMatchMockedMethodAnalyzerTests.cs
Added valid and invalid cases for delegate-constructor callbacks and simple-lambda patterns to exercise the new lambda-handling behavior.
Code-Fix Tests
tests/Moq.Analyzers.Test/CallbackSignatureShouldMatchMockedMethodCodeFixTests.cs
Added SimpleLambdaTestData() and tests asserting fixer behavior for simple vs parenthesized lambdas; updated expected parameter-renaming semantics; added helpers/templates for synthetic diagnostics.
Test Helpers
tests/Moq.Analyzers.Test/Helpers/CodeFixVerifier.cs
Added overload for VerifyCodeFixAsync to allow specifying numberOfIncrementalIterations and numberOfFixAllIterations for tests.
Other tests
tests/.../ReturnsDelegateShouldReturnTaskFixerTests.cs
Minor call-site update to pass named parameter for compiler diagnostics.

Sequence Diagram(s)

sequenceDiagram
    participant Source as Source (invocation + lambda)
    participant Analyzer as Analyzer
    participant Semantic as SemanticModel
    participant Diagnostic as DiagnosticReporter
    participant CodeFix as CodeFixProvider

    Source->>Analyzer: Parse invocation\nTryGetCallbackLambda (returns LambdaExpressionSyntax)
    Analyzer->>Analyzer: GetLambdaParameters()\nGetDiagnosticNode()
    Analyzer->>Semantic: Resolve setup / mocked method symbols
    Semantic-->>Analyzer: Method symbol(s) (or candidate)
    Analyzer->>Diagnostic: Report diagnostic at diagnostic node
    Diagnostic->>CodeFix: Request code fix
    CodeFix->>Semantic: FindSingleMockedMethod / ResolveNewParameterListAsync
    Semantic-->>CodeFix: Method symbol (or null)
    CodeFix->>CodeFix: BuildParameterList() (types, modifiers, names)
    CodeFix->>Source: Replace lambda (parenthesized or convert simple->parenthesized) preserving trivia
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • MattKotsenas
  • rjmurillo
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.68% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: support SimpleLambdaExpressionSyntax in callback validation' directly describes the main change—adding support for simple lambda expressions in callback validation.
Description check ✅ Passed The description includes a summary linking to issue #1012, key changes made, and test plan verification. It follows the template structure adequately with sufficient detail.
Linked Issues check ✅ Passed The PR successfully implements all coding requirements from #1012: widening TryGetCallbackLambda to support SimpleLambdaExpressionSyntax, adding GetLambdaParameters and GetDiagnosticNode helpers, and adding test coverage for simple lambdas in delegate constructors.
Out of Scope Changes check ✅ Passed All changes are directly aligned with #1012 objectives: analyzer enhancements for simple lambda support, code fix improvements, comprehensive test additions, and supporting utility updates in SemanticModelExtensions.

✏️ 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 feat/1012-simple-lambda-support

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

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 enhances the Moq.Analyzers callback validation logic to fully support SimpleLambdaExpressionSyntax when used within delegate constructors. Previously, these simple lambdas were explicitly skipped, leading to missed diagnostics. The changes involve refactoring the lambda detection and parameter extraction to handle both simple and parenthesized lambda forms consistently, ensuring that the analyzer correctly identifies signature mismatches for a broader range of callback expressions.

Highlights

  • Expanded Lambda Expression Support: The analyzer now correctly processes SimpleLambdaExpressionSyntax in addition to ParenthesizedLambdaExpressionSyntax for callback validation, specifically within delegate constructors.
  • Refactored Lambda Parameter Extraction: A new helper method, GetLambdaParameters, was introduced to uniformly extract parameters from both types of lambda expressions, simplifying the logic.
  • Improved Diagnostic Placement: A new GetDiagnosticNode helper method was added to ensure diagnostics are reported on the most appropriate syntax node for both ParenthesizedLambdaExpressionSyntax and SimpleLambdaExpressionSyntax.
  • Comprehensive Test Coverage: New test cases were added to validate the analyzer's behavior with simple lambdas in delegate constructors, covering both valid and invalid scenarios.
Changelog
  • src/Analyzers/CallbackSignatureShouldMatchMockedMethodAnalyzer.cs
    • Updated the type of callbackLambda variables from ParenthesizedLambdaExpressionSyntax? to LambdaExpressionSyntax? to accommodate both lambda forms.
    • Replaced direct access to callbackLambda.ParameterList.Parameters with a call to the new GetLambdaParameters helper.
    • Modified TryGetCallbackLambda to return LambdaExpressionSyntax? and directly cast to LambdaExpressionSyntax, removing the previous explicit bail-out for SimpleLambdaExpressionSyntax.
    • Introduced a new private static method GetLambdaParameters to extract parameters from either ParenthesizedLambdaExpressionSyntax or SimpleLambdaExpressionSyntax.
    • Introduced a new private static method GetDiagnosticNode to determine the correct syntax node for diagnostic reporting based on the lambda type.
    • Adjusted the ValidateCallbackAgainstSetup method signature to accept LambdaExpressionSyntax for callbackLambda.
    • Updated diagnostic creation to use GetDiagnosticNode for accurate span placement.
  • tests/Moq.Analyzers.Test/CallbackSignatureShouldMatchMockedMethodAnalyzerTests.cs
    • Added new valid test cases demonstrating correct callback validation for simple lambdas used in Action and Func<T, TResult> delegate constructors.
    • Included new invalid test cases to verify that Moq1100 diagnostics are correctly reported for simple lambdas in delegate constructors with type mismatches or argument count mismatches.
Activity
  • All 2917 existing tests passed with zero failures.
  • New valid patterns for simple lambdas in delegate constructors produced no diagnostic.
  • New invalid patterns for simple lambdas in delegate constructors (wrong type, argument count mismatch) correctly produced the Moq1100 diagnostic.
  • dotnet build succeeded with zero warnings.
  • The pull request was generated with Claude Code.
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.

@deepsource-io
Copy link
Copy Markdown

deepsource-io bot commented Mar 7, 2026

DeepSource Code Review

We reviewed changes in 4a7db6c...7e2930b on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade  

Focus Area: Hygiene
Security  

Reliability  

Complexity  

Hygiene  

Feedback

  • Style enforcement gap between tests and production
    • Test code repeatedly breaks naming and simple-style rules because the test projects don't share the same analyzer/formatter configuration as the library; unifying analyzer settings and applying code fixes in tests will stop these recurring violations.
  • Compiler diagnostics treated as advisory rather than blocking
    • Mechanical opportunities (const vs static readonly, redundant types, async naming) are left unfixed because relevant diagnostics aren't elevated; promoting those diagnostics to warnings/errors and failing CI on them prevents regression.
  • Mechanical fixes not automated
    • The issues are trivial and repetitive, so they persist when left to manual review. Add codefixers/format-on-save or pre-commit autofixes to remove this class of low-effort hygiene debt.

Code Review Summary

Analyzer Status Updated (UTC) Details
C# Mar 9, 2026 1:08a.m. Review ↗

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 extends the callback signature validation to support SimpleLambdaExpressionSyntax, which is a good improvement. The implementation is clean, using helper methods to handle both SimpleLambdaExpressionSyntax and ParenthesizedLambdaExpressionSyntax uniformly. The new test cases cover the changes well. My only concern is that the corresponding code fix provider (CallbackSignatureShouldMatchMockedMethodFixer) doesn't seem to be updated to handle simple lambdas, which means the code fix won't be available for these new scenarios. I've added a comment with more details.

The fixer previously only searched for ParameterListSyntax ancestors,
which does not exist for simple lambdas. Now handles both cases:
- Parenthesized lambdas: replace ParameterListSyntax (existing path)
- Simple lambdas: convert to ParenthesizedLambdaExpressionSyntax

Extracted FindSingleMockedMethod and BuildParameterList to reduce
duplication between the two fix paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rjmurillo rjmurillo added analyzers Change that impacts an analyzer behavior releasable labels Mar 7, 2026
@codacy-production
Copy link
Copy Markdown

codacy-production bot commented Mar 7, 2026

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.20% (target: -1.00%) 93.46% (target: 95.00%)
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (4a7db6c) 2508 2247 89.59%
Head commit (7e2930b) 2578 (+70) 2315 (+68) 89.80% (+0.20%)

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 (#1042) 107 100 93.46%

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

- Replace fragile .Parent chain with .Ancestors().OfType<>() pattern
- Extract magic string "Fix Moq callback signature" to private const
- Cap .ToArray() allocation with .Take(2) in FindSingleMockedMethod

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rjmurillo-bot
Copy link
Copy Markdown
Collaborator Author

Simplification pass (rjmurillo-bot): Replaced fragile .Parent chain with .Ancestors().OfType<>(), extracted magic string to const, capped .ToArray() allocation with .Take(2). See commit 6fa1f5d.

@coderabbitai coderabbitai bot requested a review from MattKotsenas March 7, 2026 23:48
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/CodeFixes/CallbackSignatureShouldMatchMockedMethodFixer.cs`:
- Around line 134-142: The new ParenthesizedLambdaExpressionSyntax currently
loses the original simple lambda's trivia; call WithTriviaFrom(simpleLambda) on
parenthesizedLambda before replacing the node so leading/trailing comments and
whitespace are preserved (i.e. create parenthesizedLambda, run
parenthesizedLambda = parenthesizedLambda.WithTriviaFrom(simpleLambda), then use
root.ReplaceNode(simpleLambda, parenthesizedLambda) and return
document.WithSyntaxRoot(newRoot)).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0a21b5fd-1091-425d-a5ec-eaed690b5b80

📥 Commits

Reviewing files that changed from the base of the PR and between 5ef7753 and 6fa1f5d.

📒 Files selected for processing (3)
  • src/Analyzers/CallbackSignatureShouldMatchMockedMethodAnalyzer.cs
  • src/CodeFixes/CallbackSignatureShouldMatchMockedMethodFixer.cs
  • tests/Moq.Analyzers.Test/CallbackSignatureShouldMatchMockedMethodAnalyzerTests.cs

rjmurillo and others added 2 commits March 7, 2026 16:06
…ambda

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ents

Extract ResolveNewParameterListAsync to eliminate DRY violation between
FixParenthesizedCallbackSignatureAsync and FixSimpleLambdaCallbackSignatureAsync.
Both methods shared identical semantic model resolution, symbol lookup, and
parameter list construction. Add comments explaining the intentional
SimpleLambdaExpressionSyntax fallthrough and the Take(2) short-circuit.

Refs: PR #1042 review findings #2 and #3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 8, 2026
Add SimpleLambdaTestData and ShouldFixSimpleLambdaCallbackSignature
covering the FixSimpleLambdaCallbackSignatureAsync method. Tests verify:
- Simple lambda with wrong parameter type gets rewritten to
  parenthesized lambda with correct type
- Simple lambda with wrong parameter count gets rewritten to
  parenthesized lambda with correct parameters

Uses CompilerDiagnostics.None because the fixer corrects the lambda
parameters but does not update the outer delegate constructor type.

Refs: PR #1042 review finding #1, issue #1012

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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/CodeFixes/CallbackSignatureShouldMatchMockedMethodFixer.cs`:
- Around line 73-83: The fixer Replace of lambda parameters in
FixParenthesizedCallbackSignatureAsync can produce invalid code when the lambda
is wrapped in an explicit delegate construction (e.g., new Action<int>(...));
update the logic in FixParenthesizedCallbackSignatureAsync (and the similar
handling around lines 85-103) to detect if oldParameters' ancestor is an
ObjectCreationExpressionSyntax constructing a delegate type and either (a)
update the constructed delegate type to match the new parameter types when
feasible (use ResolveNewParameterListAsync result to compute the delegate's type
arguments) or (b) bail out / suppress this code action for that case so we don't
produce a mismatched explicit delegate constructor; ensure you reference and use
ResolveNewParameterListAsync, and check for ObjectCreationExpressionSyntax /
SimpleName/GenericName on the Type node before replacing parameters.
- Around line 153-161: BuildParameterList currently builds parameters from
mockedMethod without preserving original lambda parameter names, which breaks
callback bodies; change BuildParameterList to accept the original lambda
parameter nodes (e.g., a ParameterListSyntax.Parameters collection or
SimpleLambdaExpressionSyntax.Parameter) and map by position so that for each
mockedMethod.Parameters you reuse the original identifier when one exists at the
same index, only synthesizing a new name for newly added parameters; update the
method signature (e.g., BuildParameterList(SemanticModel semanticModel,
IMethodSymbol mockedMethod, int position, IEnumerable<ParameterSyntax>
originalParameters) or similar), use
originalParameters.ElementAtOrDefault(index) to pick the identifier token for
SyntaxFactory.Identifier, and keep type and modifiers logic the same for each
parameter.

In
`@tests/Moq.Analyzers.Test/CallbackSignatureShouldMatchMockedMethodCodeFixTests.cs`:
- Around line 259-318: The test suite currently only covers block-bodied lambdas
inside explicit delegate construction (in SimpleLambdaTestData /
ShouldFixSimpleLambdaCallbackSignature) and misses the expression-bodied case;
add a new test case that uses a direct expression-bodied lambda (e.g. a
Returns({|Moq1100:x|} => 42) or Callback({|Moq1100:x|} => 42)) so the fixer's
ExpressionBody branch is exercised end-to-end, update SimpleLambdaTestData to
include that string pair (original and expected quickFix) and ensure the new
case is compiled within the same Template used by
ShouldFixSimpleLambdaCallbackSignature and included in
WithNamespaces().WithMoqReferenceAssemblyGroups().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8b295aca-96a2-4def-85cd-b2a30a3a2924

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa1f5d and bba05ba.

📒 Files selected for processing (2)
  • src/CodeFixes/CallbackSignatureShouldMatchMockedMethodFixer.cs
  • tests/Moq.Analyzers.Test/CallbackSignatureShouldMatchMockedMethodCodeFixTests.cs

rjmurillo and others added 2 commits March 7, 2026 17:05
When a lambda is wrapped in an explicit delegate constructor like
new Action<int>((int x) => { }), replacing only the lambda parameters
produces invalid code (CS1661). Bail out for parenthesized lambdas
inside ObjectCreationExpressionSyntax to avoid offering a broken fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BuildParameterList now reuses the original parameter identifiers when
they exist at the same index position. This prevents breaking callback
bodies that reference the original names. For example,
.Callback((int i) => i.ToString()) no longer renames i to s.

Also adds expression-bodied simple lambda test coverage for the
ExpressionBody branch in the fixer.

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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/CodeFixes/CallbackSignatureShouldMatchMockedMethodFixer.cs`:
- Around line 90-109: FixSimpleLambdaCallbackSignatureAsync currently lacks the
same delegate-constructor early return as
FixParenthesizedCallbackSignatureAsync, so add the same bail-out guard used in
FixParenthesizedCallbackSignatureAsync to FixSimpleLambdaCallbackSignatureAsync
(i.e., detect when the lambda is being passed into a delegate
ObjectCreationExpression/constructor and return the original document without
changing the lambda); place this check before constructing the
ParenthesizedLambdaExpressionSyntax in FixSimpleLambdaCallbackSignatureAsync so
the fixer will skip converting simple lambdas that are inside delegate
constructors.

In
`@tests/Moq.Analyzers.Test/CallbackSignatureShouldMatchMockedMethodCodeFixTests.cs`:
- Around line 319-321: The test currently suppresses compilation diagnostics
(using CompilerDiagnostics.None) for cases where the fixer only updates lambda
parameters but not outer delegate types; once you add the bail-out in
FixSimpleLambdaCallbackSignatureAsync, split expectations: for
delegate-constructor scenarios assert the fixer returns an unchanged document
(mirror the pattern used in
FixerReturnsUnchangedDocumentWhenSetupMethodNotFound) and for direct
simple-lambda scenarios assert the code-fix produces a compiling result (call
VerifyCodeFixAsync without suppressing diagnostics or with
CompilerDiagnostics.Errors) so the test verifies the fix actually compiles.
- Around line 259-276: The tests in SimpleLambdaTestData assert the fixer
produces rewritten lambdas with mismatched parameter types (e.g., new
Action<int>((string x) => ...)), which won't compile; after adding the bail-out
in FixSimpleLambdaCallbackSignatureAsync you should update those test cases to
expect no change (i.e., the original document remains unchanged) instead of the
non-compiling replacements—modify the three affected entries in
SimpleLambdaTestData to use the original input as the expected output.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f8ee4461-6b72-4191-afce-1cb19191285d

📥 Commits

Reviewing files that changed from the base of the PR and between bba05ba and 04a79b5.

📒 Files selected for processing (2)
  • src/CodeFixes/CallbackSignatureShouldMatchMockedMethodFixer.cs
  • tests/Moq.Analyzers.Test/CallbackSignatureShouldMatchMockedMethodCodeFixTests.cs

Add IsInsideDelegateConstructor guard to both RegisterCodeFixesAsync
(preventing code action registration) and FixSimpleLambdaCallbackSignatureAsync
(defense-in-depth) for simple lambdas inside delegate constructors.
This matches the existing bail-out behavior for parenthesized lambdas.

Update test expectations so delegate constructor cases expect the
diagnostic to persist (fixer does not modify the document). Add
CodeFixVerifier overload accepting iteration counts for bail-out tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 8, 2026
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 8, 2026
renovate bot and others added 4 commits March 8, 2026 16:05
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[Meziantou.Analyzer](https://github.com/meziantou/Meziantou.Analyzer)
| `3.0.19` → `3.0.20` |
![age](https://developer.mend.io/api/mc/badges/age/nuget/Meziantou.Analyzer/3.0.20?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/Meziantou.Analyzer/3.0.19/3.0.20?slim=true)
|

---

### Release Notes

<details>
<summary>meziantou/Meziantou.Analyzer (Meziantou.Analyzer)</summary>

###
[`v3.0.20`](https://github.com/meziantou/Meziantou.Analyzer/releases/tag/3.0.20)

[Compare
Source](https://github.com/meziantou/Meziantou.Analyzer/compare/3.0.19...3.0.20)

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/3.0.20>

#### What's Changed

- Fix MA0068 false positive for C# 14 extension block parameters by
[@&#8203;Copilot](https://github.com/Copilot) in
[#&#8203;1053](https://github.com/meziantou/Meziantou.Analyzer/pull/1053)

**Full Changelog**:
<meziantou/Meziantou.Analyzer@3.0.19...3.0.20>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/rjmurillo/moq.analyzers).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41OS4wIiwidXBkYXRlZEluVmVyIjoiNDMuNTkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…1050)

## Summary
- Introduces `FilteredArgumentList`, a zero-allocation `readonly struct`
that wraps `SeparatedSyntaxList<ArgumentSyntax>` with a skip index
- Replaces `ToArray()` + `RemoveAt()` pattern in
`ConstructorArgumentsShouldMatchAnalyzer.VerifyMockAttempt`, eliminating
1-2 intermediate array allocations per `Mock<T>` constructor invocation
when `MockBehavior` is present
- All consumers (`AnyConstructorsFound`, `VerifyInterfaceMockAttempt`,
`VerifyDelegateMockAttempt`, `VerifyClassMockAttempt`,
`FormatArguments`) updated to use the struct's indexed access and
`Count` property

Closes #450

## Test plan
- [x] All 2978 existing tests pass with zero failures
- [x] Clean build with zero warnings
- [x] No behavioral changes; only allocation reduction

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

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

## Summary by CodeRabbit

* **Refactor**
* Improved internal handling of constructor argument processing in the
analyzer for more efficient mock verification.

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

---------

Co-authored-by: Richard Murillo <rjmurillo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…ifier (#1049)

## Summary
- Removes `CompositeAnalyzer` and its entire project
(`Moq.Analyzers.Test.Analyzers`), which was dead code not referenced by
any test
- Keeps `AllAnalyzersVerifier`, which is actively used by 4 test classes
for false-positive verification
- Both used reflection to discover all `DiagnosticAnalyzer` types, but
only `AllAnalyzersVerifier` was wired into the test suite

## Details
`CompositeAnalyzer` wrapped all analyzers into a single
`DiagnosticAnalyzer` subclass. `AllAnalyzersVerifier` runs each analyzer
individually through `AnalyzerVerifier<T>`. The latter approach gives
better test isolation and diagnostic attribution. Since
`CompositeAnalyzer` had zero usages, removing it is the correct
reconciliation.

**Files removed:**
- `tests/Moq.Analyzers.Test.Analyzers/CompositeAnalyzer.cs`
-
`tests/Moq.Analyzers.Test.Analyzers/Moq.Analyzers.Test.Analyzers.csproj`

**Files modified:**
- `Moq.Analyzers.sln` (removed project entry and build configurations)
- `tests/Moq.Analyzers.Test/Moq.Analyzers.Test.csproj` (removed project
reference)

## Test plan
- [x] Solution builds with zero warnings and zero errors
- [x] All 2978 tests pass

Closes #530

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

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

## Summary by CodeRabbit

* **Chores**
* Removed test analyzer project from the solution structure and updated
related project configurations to streamline the build setup.

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

---------

Co-authored-by: Richard Murillo <rjmurillo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary

Resolves #980. Extracts duplicated logic from three analyzer groups
without changing behavior.

- **Overridable member check**: `IsOverridableOrAllowedMockMember`
extracted to `ISymbolExtensions`, replacing identical private methods
(`IsPropertyOrMethod`, `IsOverridableOrTaskResultMember`,
`IsAllowedMockMember`) in
`SetupShouldBeUsedOnlyForOverridableMembersAnalyzer`,
`SetupSequenceShouldBeUsedOnlyForOverridableMembersAnalyzer`, and
`VerifyShouldBeUsedOnlyForOverridableMembersAnalyzer`
- **MockBehavior reporting**: Added `TryReportMockBehaviorDiagnostic`
and `TryHandleMissingMockBehaviorParameter` overloads with `messageArgs`
plus shared `GetMockedTypeName` to `MockBehaviorDiagnosticAnalyzerBase`,
removing duplicate methods from `SetExplicitMockBehaviorAnalyzer` and
`SetStrictMockBehaviorAnalyzer`
- **Event argument validation**: Replaced
`RaiseEventArgumentsShouldMatchEventSignatureAnalyzer.ValidateArgumentTypesWithEventName`
with existing `EventSyntaxExtensions.ValidateEventArgumentTypes`

Net result: 122 lines added, 285 lines removed (163 lines reduced).

## Test plan

- [x] All 2901 existing tests pass with zero failures
- [x] Build succeeds with zero warnings
- [x] No diagnostic IDs, messages, or categories changed
- [x] No analyzer behavior changed, only structure

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

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

* **Refactor**
* Consolidated mock-behavior diagnostic reporting to a single path with
support for formatted messages and overload-aware reporting.
* Replaced many inlined helpers with shared reporting/handling flows for
strict/explicit mock analyses.
* Switched event-argument validation to context-based extension calls
for consistency.
* Centralized overridable/allowed-member checks into a single symbol
extension used by setup, verify, and sequence analyzers.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Richard Murillo <rjmurillo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ rjmurillo
❌ rjmurillo-bot
You have signed the CLA already but the status is still pending? Let us recheck it.

@rjmurillo rjmurillo added dependencies Pull requests that update a dependency file build labels Mar 8, 2026
rjmurillo and others added 3 commits March 8, 2026 16:12
Add 6 new tests covering critical gaps in PR #1042:
- Analyzer: parenthesized lambda in delegate constructor (valid/invalid type/count)
- Fixer: parenthesized lambda in delegate constructor bail-out
- Fixer: direct simple lambda conversion for Returns (not just Callback)
- SemanticModel: overload resolution failure fallback to candidate symbols

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
## Summary

- Add `THIRD-PARTY-NOTICES.TXT` covering
`Microsoft.CodeAnalysis.AnalyzerUtilities` (MIT, .NET Foundation and
Contributors), the only third-party assembly bundled in the shipped
NuGet package.
- Pack the notices file into the NuGet package root alongside
`README.md`.
- Document a repeatable 7-step attribution procedure in
`CONTRIBUTING.md` under Dependency Management, covering how to research
licenses, identify authoritative copyright holders, and handle
license-specific requirements (MIT, BSD, Apache-2.0).

## Motivation

The project bundles `Microsoft.CodeAnalysis.AnalyzerUtilities.dll`
inside the shipped `.nupkg`. Its MIT license requires reproducing the
copyright notice and license text. No third-party notices file existed
previously.

## What is and is not in scope

Only **bundled** assemblies require attribution. Compile-time-only
Roslyn SDK references (`Microsoft.CodeAnalysis.CSharp`, `.Workspaces`)
are already present in the user's host and are not distributed. Dev-only
tools (analyzers, test frameworks, benchmarks) are also excluded.

## Test plan

- [x] `dotnet build` succeeds with zero warnings
- [ ] Verify `THIRD-PARTY-NOTICES.TXT` appears in the packed `.nupkg`
root
- [ ] Review CONTRIBUTING.md rendering for the new attribution procedure
section

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

Co-authored-by: Richard Murillo <rjmurillo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rjmurillo and others added 3 commits March 8, 2026 16:33
Extract VerifySimpleLambdaConversionAsync helper to replace three
near-identical test methods. Delegate CreateSyntheticDiagnostic to
CreateSyntheticDiagnosticAtSpan to remove duplicated descriptor
construction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rjmurillo
rjmurillo previously approved these changes Mar 8, 2026
- Use candidate iteration instead of blind [0] selection
- Check BaseObjectCreationExpressionSyntax for target-typed new
- Change FixTitle to const

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rjmurillo and others added 4 commits March 8, 2026 17:22
Revert FixTitle from const back to static readonly per project's
EffectiveCSharp analyzer rule ECS0200. Extract GetChangedTextAsync
helper to eliminate duplicated CodeAction text extraction in tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rify candidate fallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rjmurillo rjmurillo merged commit c9d21cb into main Mar 9, 2026
40 of 43 checks passed
@rjmurillo rjmurillo deleted the feat/1012-simple-lambda-support branch March 9, 2026 01:37
@rjmurillo rjmurillo added this to the vNext milestone Mar 9, 2026
rjmurillo added a commit that referenced this pull request Mar 9, 2026
Integrate symbol-based detection (#1030) and simple lambda support (#1042)
from main with error handling improvements (#1040) on this branch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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 build dependencies Pull requests that update a dependency file documentation feature releasable

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support SimpleLambdaExpressionSyntax in delegate constructors for callback validation

3 participants