Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Analyzers/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Moq1205 | Moq | Warning | EventSetupHandlerShouldMatchEventTypeAnalyzer
Moq1206 | Moq | Warning | ReturnsAsyncShouldBeUsedForAsyncMethodsAnalyzer
Moq1207 | Moq | Error | SetupSequenceShouldBeUsedOnlyForOverridableMembersAnalyzer
Moq1210 | Moq | Error | VerifyShouldBeUsedOnlyForOverridableMembersAnalyzer
Moq1300 | Usage | Error | AsShouldBeUsedOnlyForInterfaceAnalyzer (updated category from Moq to Usage)
Moq1301 | Moq | Warning | Mock.Get() should not take literals
Moq1302 | Moq | Warning | LINQ to Mocks expression should be valid (flags non-virtual members including fields, events, nested and chained accesses)
Moq1420 | Moq | Info | RedundantTimesSpecificationAnalyzer
Expand Down
10 changes: 6 additions & 4 deletions src/Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ namespace Moq.Analyzers;
public class AsShouldBeUsedOnlyForInterfaceAnalyzer : DiagnosticAnalyzer
{
private static readonly LocalizableString Title = "Moq: Invalid As type parameter";
private static readonly LocalizableString Message = "Mock.As() should take interfaces only";
private static readonly LocalizableString Message = "Mock.As() should take interfaces only, but '{0}' is not an interface";
Copy link

Copilot AI Jul 28, 2025

Choose a reason for hiding this comment

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

[nitpick] The description ends with a period while the message format string doesn't. For consistency, either both should have periods or neither should.

Suggested change
private static readonly LocalizableString Message = "Mock.As() should take interfaces only, but '{0}' is not an interface";
private static readonly LocalizableString Message = "Mock.As() should take interfaces only, but '{0}' is not an interface.";

Copilot uses AI. Check for mistakes.
private static readonly LocalizableString Description = "Mock.As() should take interfaces only.";

private static readonly DiagnosticDescriptor Rule = new(
DiagnosticIds.AsShouldOnlyBeUsedForInterfacesRuleId,
Title,
Message,
DiagnosticCategory.Moq,
DiagnosticCategory.Usage,
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: Description,
helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{DiagnosticIds.AsShouldOnlyBeUsedForInterfacesRuleId}.md");

/// <inheritdoc />
Expand Down Expand Up @@ -76,7 +78,7 @@ private static void Analyze(OperationAnalysisContext context, ImmutableArray<IMe
return;
}

if (typeArguments[0] is ITypeSymbol { TypeKind: not TypeKind.Interface })
if (typeArguments[0] is ITypeSymbol { TypeKind: not TypeKind.Interface } typeSymbol)
{
// Find the first As<T> generic type argument and report the diagnostic on it
GenericNameSyntax? asGeneric = invocationOperation.Syntax
Expand All @@ -86,7 +88,7 @@ private static void Analyze(OperationAnalysisContext context, ImmutableArray<IMe

TypeSyntax? typeArg = asGeneric?.TypeArgumentList.Arguments.FirstOrDefault();
Location location = typeArg?.GetLocation() ?? invocationOperation.Syntax.GetLocation();
context.ReportDiagnostic(location.CreateDiagnostic(Rule));
context.ReportDiagnostic(location.CreateDiagnostic(Rule, typeSymbol.Name));
}
}
}
1 change: 1 addition & 0 deletions src/Common/DiagnosticCategory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
internal static class DiagnosticCategory
{
internal const string Moq = nameof(Moq);
internal const string Usage = nameof(Usage);
}
Loading