diff --git a/src/Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs b/src/Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs index 099df996e..5ec398e9e 100644 --- a/src/Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs +++ b/src/Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs @@ -44,7 +44,7 @@ private static void RegisterCompilationStartAction(CompilationStartAnalysisConte // Look for the Mock.As() method and provide it to Analyze to avoid looking it up multiple times. #pragma warning disable ECS0900 // Minimize boxing and unboxing ImmutableArray asMethods = mockTypes - .SelectMany(mockType => mockType.GetMembers(WellKnownTypeNames.As)) + .SelectMany(mockType => mockType.GetMembers(WellKnownMoqNames.AsMethodName)) .OfType() .Where(method => method.IsGenericMethod) .ToImmutableArray(); diff --git a/src/Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs b/src/Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs index 41107a6d3..02f1383a8 100644 --- a/src/Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs +++ b/src/Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs @@ -78,7 +78,7 @@ private static bool IsExpressionMockBehavior(SyntaxNodeAnalysisContext context, if (expression is MemberAccessExpressionSyntax memberAccessExpressionSyntax) { if (memberAccessExpressionSyntax.Expression is IdentifierNameSyntax identifierNameSyntax - && string.Equals(identifierNameSyntax.Identifier.ValueText, WellKnownTypeNames.MockBehavior, StringComparison.Ordinal)) + && string.Equals(identifierNameSyntax.Identifier.ValueText, WellKnownMoqNames.MockBehaviorTypeName, StringComparison.Ordinal)) { return true; } @@ -107,14 +107,14 @@ private static bool IsExpressionMockBehavior(SyntaxNodeAnalysisContext context, } if (typeSymbol != null - && string.Equals(typeSymbol.Name, WellKnownTypeNames.MockBehavior, StringComparison.Ordinal)) + && string.Equals(typeSymbol.Name, WellKnownMoqNames.MockBehaviorTypeName, StringComparison.Ordinal)) { return true; } } // Crude fallback to check if the expression is a Moq.MockBehavior enum - if (expression.ToString().StartsWith(WellKnownTypeNames.MoqBehavior, StringComparison.Ordinal)) + if (expression.ToString().StartsWith(WellKnownMoqNames.FullyQualifiedMoqBehaviorTypeName, StringComparison.Ordinal)) { return true; } @@ -205,18 +205,18 @@ private static void AnalyzeInstanceCall(SyntaxNodeAnalysisContext context) return; } - switch (genericNameSyntax.Identifier.Value) + if (genericNameSyntax.Identifier.Value is not string genericNameSyntaxIdentifierValue) { - case WellKnownTypeNames.Create: - AnalyzeInvocation(context, invocationExpressionSyntax, WellKnownTypeNames.MockFactory, true, true); - break; - - case WellKnownTypeNames.Of: - AnalyzeInvocation(context, invocationExpressionSyntax, WellKnownTypeNames.MockName, false, true); - break; + return; + } - default: - return; + if (string.Equals(genericNameSyntaxIdentifierValue, WellKnownMoqNames.CreateMethodName, StringComparison.Ordinal)) + { + AnalyzeInvocation(context, invocationExpressionSyntax, WellKnownMoqNames.MockFactoryTypeName, true, true); + } + else if (string.Equals(genericNameSyntaxIdentifierValue, WellKnownMoqNames.OfMethodName, StringComparison.Ordinal)) + { + AnalyzeInvocation(context, invocationExpressionSyntax, WellKnownMoqNames.MockTypeName, false, true); } } @@ -252,7 +252,7 @@ private static void AnalyzeInvocation( // We are calling MockRepository.Create or Mock.Of, determine which ArgumentListSyntax? argumentList = null; - if (WellKnownTypeNames.Of.Equals(method.Name, StringComparison.Ordinal)) + if (WellKnownMoqNames.OfMethodName.Equals(method.Name, StringComparison.Ordinal)) { // Mock.Of can specify condition for construction and MockBehavior, but // cannot specify constructor parameters @@ -286,7 +286,7 @@ private static void AnalyzeNewObject(SyntaxNodeAnalysisContext context) // Quick check if (!string.Equals( genericNameSyntax.Identifier.ValueText, - WellKnownTypeNames.MockName, + WellKnownMoqNames.MockTypeName, StringComparison.Ordinal)) { return; @@ -297,7 +297,7 @@ private static void AnalyzeNewObject(SyntaxNodeAnalysisContext context) if (symbolInfo.Symbol is not IMethodSymbol mockConstructorMethod || mockConstructorMethod.MethodKind != MethodKind.Constructor - || !string.Equals(mockConstructorMethod.ContainingType.ConstructedFrom.ContainingSymbol.Name, WellKnownTypeNames.Moq, StringComparison.Ordinal)) + || !string.Equals(mockConstructorMethod.ContainingType.ConstructedFrom.ContainingSymbol.Name, WellKnownMoqNames.MoqSymbolName, StringComparison.Ordinal)) { return; } diff --git a/src/Analyzers/SetExplicitMockBehaviorAnalyzer.cs b/src/Analyzers/SetExplicitMockBehaviorAnalyzer.cs index 1ccb05359..5752907c7 100644 --- a/src/Analyzers/SetExplicitMockBehaviorAnalyzer.cs +++ b/src/Analyzers/SetExplicitMockBehaviorAnalyzer.cs @@ -42,7 +42,7 @@ private static void RegisterCompilationStartAction(CompilationStartAnalysisConte } // Look for the MockBehavior type and provide it to Analyze to avoid looking it up multiple times. - INamedTypeSymbol? mockBehaviorSymbol = context.Compilation.GetTypeByMetadataName(WellKnownTypeNames.MoqBehavior); + INamedTypeSymbol? mockBehaviorSymbol = context.Compilation.GetTypeByMetadataName(WellKnownMoqNames.FullyQualifiedMoqBehaviorTypeName); if (mockBehaviorSymbol is null) { return; @@ -51,7 +51,7 @@ private static void RegisterCompilationStartAction(CompilationStartAnalysisConte // Look for the Mock.Of() method and provide it to Analyze to avoid looking it up multiple times. #pragma warning disable ECS0900 // Minimize boxing and unboxing ImmutableArray ofMethods = mockTypes - .SelectMany(mockType => mockType.GetMembers(WellKnownTypeNames.Of)) + .SelectMany(mockType => mockType.GetMembers(WellKnownMoqNames.OfMethodName)) .OfType() .Where(method => method.IsGenericMethod) .ToImmutableArray(); diff --git a/src/Common/CompilationExtensions.cs b/src/Common/CompilationExtensions.cs index a41692db6..ba775b298 100644 --- a/src/Common/CompilationExtensions.cs +++ b/src/Common/CompilationExtensions.cs @@ -34,6 +34,6 @@ public static ImmutableArray GetTypesByMetadataNames(this Comp /// public static ImmutableArray GetMoqMock(this Compilation compilation) { - return compilation.GetTypesByMetadataNames([WellKnownTypeNames.MoqMock, WellKnownTypeNames.MoqMock1, WellKnownTypeNames.MoqRepository]); + return compilation.GetTypesByMetadataNames([WellKnownMoqNames.FullyQualifiedMoqMockTypeName, WellKnownMoqNames.FullyQualifiedMoqMock1TypeName, WellKnownMoqNames.FullyQualifiedMoqRepositoryTypeName]); } } diff --git a/src/Common/MoqMethodDescriptorBase.cs b/src/Common/MoqMethodDescriptorBase.cs index 263922641..f531b8b71 100644 --- a/src/Common/MoqMethodDescriptorBase.cs +++ b/src/Common/MoqMethodDescriptorBase.cs @@ -11,8 +11,8 @@ /// internal abstract class MoqMethodDescriptorBase { - private static readonly string ContainingNamespace = WellKnownTypeNames.Moq; - private static readonly string ContainingType = WellKnownTypeNames.MockName; + private static readonly string ContainingNamespace = WellKnownMoqNames.MoqNamespace; + private static readonly string ContainingType = WellKnownMoqNames.MockTypeName; public abstract bool IsMatch(SemanticModel semanticModel, MemberAccessExpressionSyntax memberAccessSyntax, CancellationToken cancellationToken); diff --git a/src/Common/WellKnownMoqNames.cs b/src/Common/WellKnownMoqNames.cs new file mode 100644 index 000000000..fdedd9387 --- /dev/null +++ b/src/Common/WellKnownMoqNames.cs @@ -0,0 +1,74 @@ +namespace Moq.Analyzers.Common; + +/// +/// Provides well-known names and fully qualified names for commonly used Moq types, namespaces, and members. +/// +internal static class WellKnownMoqNames +{ + /// + /// Represents the namespace for the Moq library. + /// + internal static readonly string MoqNamespace = "Moq"; + + /// + /// Symbol name for Moq. + /// + internal static readonly string MoqSymbolName = "Moq"; + + /// + /// The name of the 'Moq.Mock' type. + /// + internal static readonly string MockTypeName = "Mock"; + + /// + /// The name of the 'Moq.MockBehavior' type. + /// This type specifies the behavior of the mock (Strict, Loose, etc.). + /// + internal static readonly string MockBehaviorTypeName = "MockBehavior"; + + /// + /// The name of the 'Moq.MockFactory' type. + /// This factory is used for creating multiple mock objects with a shared configuration. + /// + internal static readonly string MockFactoryTypeName = "MockFactory"; + + /// + /// Fully qualified name for the 'Moq.Mock' type. + /// + internal static readonly string FullyQualifiedMoqMockTypeName = $"{MoqNamespace}.{MockTypeName}"; + + /// + /// Fully qualified name for the generic version of 'Moq.Mock{T}'. + /// Represents mocks for specific types. + /// + internal static readonly string FullyQualifiedMoqMock1TypeName = $"{FullyQualifiedMoqMockTypeName}`1"; + + /// + /// Fully qualified name for the 'Moq.MockBehavior' type. + /// + internal static readonly string FullyQualifiedMoqBehaviorTypeName = $"{MoqNamespace}.{MockBehaviorTypeName}"; + + /// + /// Fully qualified name for the 'Moq.MockRepository' type. + /// This type acts as a container for multiple mocks and shared mock configurations. + /// + internal static readonly string FullyQualifiedMoqRepositoryTypeName = $"{MoqNamespace}.MockRepository"; + + /// + /// Represents the method name for the `As` method in Moq. + /// This method is used to cast mocks to interfaces. + /// + internal static readonly string AsMethodName = "As"; + + /// + /// Represents the method name for the `Create` method in Moq. + /// This method is used to create instances of mocks. + /// + internal static readonly string CreateMethodName = "Create"; + + /// + /// Represents the method name for the `Of` method in Moq. + /// This method is used to create a mock from a type without directly specifying the constructor. + /// + internal static readonly string OfMethodName = "Of"; +} diff --git a/src/Common/WellKnownTypeNames.cs b/src/Common/WellKnownTypeNames.cs deleted file mode 100644 index e47bc65d7..000000000 --- a/src/Common/WellKnownTypeNames.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Moq.Analyzers.Common; - -#pragma warning disable ECS0200 // Consider using readonly instead of const for flexibility - -internal static class WellKnownTypeNames -{ - internal const string Moq = nameof(Moq); - internal const string MockName = "Mock"; - internal const string MockBehavior = nameof(MockBehavior); - internal const string MockFactory = nameof(MockFactory); - internal const string MoqMock = $"{Moq}.{MockName}"; - internal const string MoqMock1 = $"{MoqMock}`1"; - internal const string MoqBehavior = $"{Moq}.{MockBehavior}"; - internal const string MoqRepository = $"{Moq}.MockRepository"; - internal const string As = nameof(As); - internal const string Create = nameof(Create); - internal const string Of = nameof(Of); -}