Skip to content

feat: migrate Moq properties#21

Merged
vbreuss merged 3 commits into
mainfrom
topic/migrate-properties
Apr 5, 2026
Merged

feat: migrate Moq properties#21
vbreuss merged 3 commits into
mainfrom
topic/migrate-properties

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented Apr 5, 2026

Adds migration support for Moq property setups in the Moq→Mockolate code fix provider, with accompanying tests and updated example snippets.

Changes:

  • Extend MoqCodeFixProvider to rewrite Setup(x => x.Prop) and SetupProperty(...) into Mockolate’s property setup APIs.
  • Add new code-fix tests covering direct and nested property setups, plus SetupProperty with/without default values.
  • Update migration example file to demonstrate property setup migrations and recursive-mock property patterns.

@vbreuss vbreuss self-assigned this Apr 5, 2026
@vbreuss vbreuss added the enhancement New feature or request label Apr 5, 2026
Copilot AI review requested due to automatic review settings April 5, 2026 15:16
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 5, 2026

Test Results

  3 files  ± 0    3 suites  ±0   1m 59s ⏱️ +2s
 49 tests + 4   49 ✅ + 4  0 💤 ±0  0 ❌ ±0 
147 runs  +12  147 ✅ +12  0 💤 ±0  0 ❌ ±0 

Results for commit cd3b3c1. ± Comparison against base commit b693d02.

♻️ This comment has been updated with latest results.

Copy link
Copy Markdown

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

Adds migration support for Moq property setups in the Moq→Mockolate code fix provider, with accompanying tests and updated example snippets.

Changes:

  • Extend MoqCodeFixProvider to rewrite Setup(x => x.Prop) and SetupProperty(...) into Mockolate’s property setup APIs.
  • Add new code-fix tests covering direct and nested property setups, plus SetupProperty with/without default values.
  • Update migration example file to demonstrate property setup migrations and recursive-mock property patterns.

Reviewed changes

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

File Description
Tests/Mockolate.Migration.Tests/MoqCodeFixProviderTests.SetupTests.cs Adds new test cases validating property setup and SetupProperty migrations.
Tests/Mockolate.Migration.Example.Tests/MoqMigrationExamples.cs Extends example outputs/inputs to include property-related migration examples.
Source/Mockolate.Migration.Analyzers.CodeFixers/MoqCodeFixProvider.cs Implements syntax rewrites for property Setup(...) and SetupProperty(...) patterns.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Tests/Mockolate.Migration.Example.Tests/MoqMigrationExamples.cs
@vbreuss vbreuss force-pushed the topic/migrate-properties branch from 13144b6 to 3721ba4 Compare April 5, 2026 15:42
Copilot AI review requested due to automatic review settings April 5, 2026 15:43
@vbreuss vbreuss force-pushed the topic/migrate-properties branch from 3721ba4 to 1e02ee1 Compare April 5, 2026 15:43
# Conflicts:
#	Source/Mockolate.Migration.Analyzers.CodeFixers/MoqCodeFixProvider.cs
#	Tests/Mockolate.Migration.Example.Tests/MoqMigrationExamples.cs
#	Tests/Mockolate.Migration.Tests/MoqCodeFixProviderTests.NewMockTests.cs
@vbreuss vbreuss enabled auto-merge (squash) April 5, 2026 15:47
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 5, 2026

@vbreuss vbreuss merged commit 6fdefa2 into main Apr 5, 2026
9 checks passed
@vbreuss vbreuss deleted the topic/migrate-properties branch April 5, 2026 15:49
Copy link
Copy Markdown

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

Source/Mockolate.Migration.Analyzers.CodeFixers/MoqCodeFixProvider.cs:207

  • IsMockBehaviorArgument relies on symbol?.ContainingType?.ToDisplayString() == "Moq.MockBehavior". ToDisplayString() defaults to a minimally-qualified format, which often returns just MockBehavior (no namespace), so this check can silently fail and prevent the code fix from running for new Mock<T>(MockBehavior.*).

Consider using a symbol-based comparison instead (e.g., compare ContainingNamespace+Name, or compare against semanticModel.Compilation.GetTypeByMetadataName("Moq.MockBehavior"), or use the existing GloballyQualifiedNonGeneric() helper from TypeExtensions).

			_ => null,
		};

	private static bool IsMockBehaviorArgument(ArgumentSyntax argument, SemanticModel? semanticModel, CancellationToken cancellationToken)
	{
		if (semanticModel is not null)
		{

Source/Mockolate.Migration.Analyzers.CodeFixers/MoqCodeFixProvider.cs:230

  • HasStrictMockBehavior checks symbol?.ToDisplayString() == "Moq.MockBehavior.Strict". As with other ToDisplayString() comparisons, this is likely to produce a minimally-qualified string (e.g., MockBehavior.Strict), causing strict behavior to be missed and the migrated CreateMock(...) call to omit ThrowingWhenNotSetup().

Use a more robust symbol identity check (namespace + containing type + member name), or compare via GetTypeByMetadataName("Moq.MockBehavior") and then validate the enum member name is Strict.

			or "MockBehavior.Default" or "Moq.MockBehavior.Default";
	}

	private static bool HasStrictMockBehavior(ExpressionSyntax expressionSyntax, SemanticModel? semanticModel, CancellationToken cancellationToken)
	{
		if (expressionSyntax is not ObjectCreationExpressionSyntax { ArgumentList.Arguments: { Count: 1, } arguments, })
		{
			return false;
		}

		if (semanticModel is not null)
		{
			ISymbol? symbol = semanticModel.GetSymbolInfo(arguments[0].Expression, cancellationToken).Symbol;
			return symbol?.ToDisplayString() == "Moq.MockBehavior.Strict";
		}

Source/Mockolate.Migration.Analyzers.CodeFixers/MoqCodeFixProvider.cs:199

  • GetTypeArgument (and HasStrictMockBehavior) don’t handle target-typed new(...) with a MockBehavior argument (i.e., ImplicitObjectCreationExpressionSyntax with 1 argument). Since the analyzer reports on OperationKind.ObjectCreation for Moq Mock, this means Mock<IFoo> m = new(MockBehavior.Strict); would not be fixable even though it’s a common Moq pattern.

Add a case for ImplicitObjectCreationExpressionSyntax with 1 argument where the argument is a MockBehavior, and plumb that through to strict/loose handling as appropriate.

		return document.WithSyntaxRoot(compilationUnit);
	}

	private static TypeSyntax? GetTypeArgument(ExpressionSyntax expressionSyntax, SemanticModel? semanticModel, CancellationToken cancellationToken) =>
		expressionSyntax switch
		{
			ObjectCreationExpressionSyntax
				{
					Type: GenericNameSyntax { TypeArgumentList.Arguments: { Count: 1, } args, },
					ArgumentList.Arguments.Count: 0,
					Initializer: null,
				}
				=> args[0],
			ObjectCreationExpressionSyntax
				{
					Type: GenericNameSyntax { TypeArgumentList.Arguments: { Count: 1, } args, },
					ArgumentList: { Arguments: { Count: 1, } arguments, },
					Initializer: null,
				} when IsMockBehaviorArgument(arguments[0], semanticModel, cancellationToken)
				=> args[0],
			ImplicitObjectCreationExpressionSyntax { ArgumentList.Arguments.Count: 0, Initializer: null, }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 5, 2026

This is addressed in release v0.2.0.

@github-actions github-actions Bot added the state: released The issue is released label Apr 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request state: released The issue is released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants