Skip to content

feat: Detect Implicit Object Creation (Mock<T> myMock = new()) - #1090

Merged
Brian Collamore (bcollamore) merged 14 commits into
mainfrom
bcoll/implicitobjectcreation
Apr 18, 2026
Merged

feat: Detect Implicit Object Creation (Mock<T> myMock = new())#1090
Brian Collamore (bcollamore) merged 14 commits into
mainfrom
bcoll/implicitobjectcreation

Conversation

@bcollamore

Copy link
Copy Markdown
Member

No description provided.

@bcollamore Brian Collamore (bcollamore) changed the title Detect Implicit Object Creation (Mock<T> myMock = new()) feat!: Detect Implicit Object Creation (Mock<T> myMock = new()) Apr 13, 2026
@bcollamore Brian Collamore (bcollamore) changed the title feat!: Detect Implicit Object Creation (Mock<T> myMock = new()) feat: Detect Implicit Object Creation (Mock<T> myMock = new()) Apr 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Moq disposable-mock analyzer/code-fix to detect target-typed implicit object creation (new()) and modernizes the Roslyn package versions needed to support that syntax.

Changes:

  • Extend MockDisposableClassesShouldSetupDisposeAnalyzer to analyze ImplicitObjectCreationExpression in addition to explicit new Mock<T>().
  • Update the Moq code fix and tests to cover target-typed new() cases.
  • Bump Roslyn-related NuGet packages (and adapt test helpers) to newer APIs; apply small IsKind(...) refactors across analyzers/code fixes.

Reviewed changes

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

Show a summary per file
File Description
Philips.CodeAnalysis.MoqAnalyzers/MockDisposableClassesShouldSetupDisposeAnalyzer.cs Register syntax actions for implicit object creation and resolve mocked type via semantic model.
Philips.CodeAnalysis.MoqAnalyzers/MockDisposableClassesShouldSetupDisposeCodeFixProvider.cs Broaden code fix node handling to ExpressionSyntax and add a branch for implicit new().
Philips.CodeAnalysis.Test/Moq/MockDisposableClassesShouldSetupDisposeAnalyzerTest.cs Add analyzer tests for Mock<T> x = new(); patterns.
Philips.CodeAnalysis.Test/Moq/MockDisposableClassesShouldSetupDisposeCodeFixProviderTest.cs Add code-fix tests for target-typed new() and argumented new(...).
Philips.CodeAnalysis.Test/Verifiers/DiagnosticVerifier.Helper.cs Implement AnalyzerConfigOptionsProvider.GlobalOptions for newer Roslyn APIs.
Philips.CodeAnalysis.Test/Helpers/TestAnalyzerConfigOptionsProvider.cs Implement AnalyzerConfigOptionsProvider.GlobalOptions for newer Roslyn APIs.
Philips.CodeAnalysis.Test/Philips.CodeAnalysis.Test.csproj Update Roslyn workspace package reference version.
Philips.CodeAnalysis.Common/Philips.CodeAnalysis.Common.csproj Update Roslyn workspace package reference version.
Directory.Build.Analyzer.props Update Microsoft.CodeAnalysis.Analyzers and Roslyn workspace package reference.
Philips.CodeAnalysis.Benchmark/Philips.CodeAnalysis.Benchmark.csproj Update Microsoft.CodeAnalysis package reference version.
Philips.CodeAnalysis.MsTestAnalyzers/TestMethodNameCodeFixProvider.cs Update rename API usage to SymbolRenameOptions and newer Renamer overload.
Philips.CodeAnalysis.MsTestAnalyzers/TestMethodNameAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MsTestAnalyzers/AvoidAssertConditionalAccessAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/NoRegionsInMethodAnalyzer.cs Refactor region detection to traverse directive trivia; add required usings.
Philips.CodeAnalysis.Test/Maintainability/Maintainability/NoRegionsInMethodAnalyzerTest.cs Adjust test inputs/expectations for region directive detection behavior.
Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/ProhibitDynamicKeywordAnalyzer.cs Fix message typo and adjust dynamic detection implementation.
Philips.CodeAnalysis.Test/Maintainability/Maintainability/ProhibitDynamicKeywordAnalyzerTest.cs Update test snippets to be compilable as complete types.
Philips.CodeAnalysis.MaintainabilityAnalyzers/Documentation/XmlDocumentationCodeFixProvider.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.Test/Maintainability/Documentation/XmlDocumentationShouldAddValueAnalyzerTest.cs Update test content scaffolding to include required type context.
Philips.CodeAnalysis.MaintainabilityAnalyzers/RuntimeFailure/DereferenceNullAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Readability/PreventUnnecessaryRangeChecksAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Readability/PreferNamedTuplesAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Naming/VariableNamingConventionAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Naming/EnforceBoolNamingConventionAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/MergeIfStatementsAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidStaticMethodAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidStaticClassesAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidPublicMemberVariableAnalyzer.cs Replace Kind() comparisons with IsKind(...).
Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAsyncVoidAnalyzer.cs Replace Kind() comparisons with IsKind(...).

@ajbarga

Copy link
Copy Markdown
Contributor

FindCurrentNode is unnecessary and can be removed

I traced the call path and verified locally that FindCurrentNode (lines 88-98 of the code fix provider) is dead complexity:

  1. The base class SingleDiagnosticCodeFixProvider<TSyntax>.RegisterCodeFixesAsync obtains the syntax root, finds node from it via GetNode, then passes the same document to ApplyFix.
  2. Inside ApplyFix, document.GetSyntaxRootAsync() returns the Roslyn-cached root — the same tree instance that node already belongs to.
  3. Re-locating the node by span via FindNode is redundant. Worse, getInnermostNodeForTie: true could return a node of a different type than expected, causing the as TNode cast to return null and the fix to silently bail out.

I removed FindCurrentNode entirely, used node directly, and all 35 tests (analyzer + code fix, including implicit new() and fix-all) still pass. The diff is minimal:

-			ExpressionSyntax currentNode = FindCurrentNode<ExpressionSyntax>(rootNode, node);
-			if (currentNode == null)
-			{
-				return document;
-			}
-
-			TypeSyntax declaredTypeToReplace = GetDeclaredTypeFromContext(currentNode);
-
-			if (currentNode is ImplicitObjectCreationExpressionSyntax)
+			TypeSyntax declaredTypeToReplace = GetDeclaredTypeFromContext(node);
+
+			if (node is ImplicitObjectCreationExpressionSyntax)
-			if (currentNode is ObjectCreationExpressionSyntax explicitObjectCreation &&
+			if (node is ObjectCreationExpressionSyntax explicitObjectCreation &&

And delete the FindCurrentNode method entirely.

…DisposeCodeFixProviderTest.cs

Co-authored-by: Alex Barga <99690046+ajbarga@users.noreply.github.com>
…DisposeAnalyzerTest.cs

Co-authored-by: Alex Barga <99690046+ajbarga@users.noreply.github.com>
The suggestion was applied inside a string literal, creating syntax
errors. Restored the original method and extracted the intended test.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ajbarga

Alex Barga (ajbarga) commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Brian Collamore (@bcollamore) clearly those suggestions had error, apologies. Resolved.

@sonarqubecloud

Copy link
Copy Markdown

@bcollamore
Brian Collamore (bcollamore) added this pull request to the merge queue Apr 18, 2026
Merged via the queue into main with commit d98ad1f Apr 18, 2026
12 checks passed
@bcollamore
Brian Collamore (bcollamore) deleted the bcoll/implicitobjectcreation branch April 18, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants