Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
3446785
WIP
rjmurillo Jun 28, 2024
f5e634c
Add "As" analyzer with new structure
rjmurillo Jun 28, 2024
7dc69c5
Creating a DiagnosticDescriptor in a ctor had FP on removed rule
rjmurillo Jun 29, 2024
af269cc
Add filter for Moq types
rjmurillo Jul 1, 2024
9f7104d
Clean up analyzer warnings
rjmurillo Jul 1, 2024
02de353
Make rule help link constant
rjmurillo Jul 1, 2024
cbd113d
Add documentation link for each
rjmurillo Jul 1, 2024
3fdc010
WIP
rjmurillo Jul 2, 2024
650a62e
Add benchmark for Moq1201
rjmurillo Jul 2, 2024
3e48b57
Rename helper for adding Moq reference assemblies
rjmurillo Jul 2, 2024
3fc937a
Fix 1002 analyzer to also emit 1001 rule and drag race
rjmurillo Jul 2, 2024
7e5ddbc
Remove under performing constructor argument analyzer for interfaces
rjmurillo Jul 2, 2024
d6f7152
WIP
rjmurillo Jul 3, 2024
efbf0b2
Clean up analyzer messages
rjmurillo Jul 3, 2024
5a29a6b
Add VS Live Unit Testing (LUT) config
rjmurillo Jul 3, 2024
13ddad2
WIP
rjmurillo Jul 3, 2024
6a7c7ee
WIP
rjmurillo Jul 4, 2024
239c205
WIP
rjmurillo Jul 5, 2024
03d6c70
WIP
rjmurillo Jul 5, 2024
b2b11f9
Clean up analyzer warnings
rjmurillo Jul 5, 2024
92ba4e5
Separate ctor tests into separate files by topic
rjmurillo Jul 5, 2024
d0397bb
Clean up analyzer warnings
rjmurillo Jul 5, 2024
b5b2abb
Move old interface tests into new analyzer test collateral
rjmurillo Jul 5, 2024
086202a
Clean up analyzer warnings
rjmurillo Jul 5, 2024
90d3eeb
Remove base class for diagnostic analysis
rjmurillo Jul 5, 2024
926db96
Organize types and update analyzers to use constants and gitcommit
rjmurillo Jul 5, 2024
2cd5e07
Remove unused code
rjmurillo Jul 5, 2024
7f926d0
Convert Diagnostic.Create to extension method version
rjmurillo Jul 5, 2024
4fb7c5b
Remove unused code
rjmurillo Jul 5, 2024
c840c62
Refactor to use extension method for constructor detection
rjmurillo Jul 5, 2024
74c596a
Remove unused code
rjmurillo Jul 5, 2024
a93c9b2
Add test case for delegate that triggers analyzer
rjmurillo Jul 5, 2024
4a8bdd4
Add tests for private constructors
rjmurillo Jul 5, 2024
480e258
Add test cases for internal and protected internal
rjmurillo Jul 5, 2024
2732652
Add case that triggers identifier name syntax code path on behavior d…
rjmurillo Jul 5, 2024
1602432
Revert cases for internal and protected internal
rjmurillo Jul 5, 2024
e3a64b2
Clean up code analysis warnings
rjmurillo Jul 5, 2024
43bb547
Merge branch 'main' into feature/simplify-ctor-analyzer
rjmurillo Jul 6, 2024
fc5db74
Merge branch 'main' into feature/simplify-ctor-analyzer
rjmurillo Jul 8, 2024
cd74ad0
Merge branch 'main' into feature/simplify-ctor-analyzer
rjmurillo Jul 8, 2024
d5b0d74
Add missing inherit doc
rjmurillo Jul 8, 2024
91053b5
Remove extra case in switch statement
rjmurillo Jul 8, 2024
4a2cf08
Remove sealed keyword on Initiailize method for ctor analyzer
rjmurillo Jul 8, 2024
70cd7a8
Fix for SA1516
rjmurillo Jul 8, 2024
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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -401,4 +401,4 @@ dotnet_diagnostic.CA2016.severity = error
# S1135: Track uses of "TODO" tags
dotnet_diagnostic.S1135.severity = suggestion
# MA0026: Fix TODO comment
dotnet_diagnostic.MA0026.severity = none
dotnet_diagnostic.MA0026.severity = none
153 changes: 153 additions & 0 deletions .lutignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
## The .lutignore file is used by Live Unit Testing to ignore Visual Studio temporary files, build results,
## and files generated by popular Visual Studio add-ons when creating a private copy of the source tree that
## Live Unit Testing uses for its build.
##
## This file has same format as git's .gitignore file (https://git-scm.com/docs/gitignore). In fact, in the
## case where a .lutignore file is not found, but a .gitignore file is found, Live Unit Testing will use the
## .gitignore file directly for the above purpose.

# User-specific files
*.suo
*.user
*.userprefs
*.sln.docstates
.vs/
.vscode/
.packages/
.dotnet/
.tools/
.idea/

# Build results
[Dd]ebug/
[Rr]elease/
[Bb]inaries/
[Bb]in/
[Oo]bj/
x64/
TestResults/

# Debug artifactss
launchSettings.json

# Click-Once directory
publish/

# Publish Web Output
*.Publish.xml

# NuGet Packages Directory
packages/

# NuGet V3 artifacts
[Nn]u[Gg]et.exe
*-packages.config
*.nuget.props
*.nuget.targets
project.lock.json
msbuild.binlog
*.project.lock.json

# Miscellaneous
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.wrn
*.vspscc
*.vssscc
.builds
*.pidb
*.scc
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings

# Visual Studio cache files
*.sln.ide/

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
*.VC.opendb
*.VC.db

# Windows Store app package directory
AppPackages/

# Visual Studio profiler
*.psess
*.vsp
*.vspx

# Guidance Automation Toolkit
*.gpState

# ReSharper
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
*.ncrunch*
.*crunch*.local.xml

# Upgrade backups
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
App_Data/*.mdf
App_Data/*.ldf

#LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml

# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Mac desktop service store files
.DS_Store

# WPF temp projects
*wpftmp.*
6 changes: 6 additions & 0 deletions Moq.Analyzers.lutconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<LUTConfig Version="1.0">
<Repository />
<ParallelBuilds>true</ParallelBuilds>
<ParallelTestRuns>true</ParallelTestRuns>
<TestCaseTimeout>180000</TestCaseTimeout>
</LUTConfig>
2 changes: 2 additions & 0 deletions Moq.Analyzers.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
Comment thread
rjmurillo marked this conversation as resolved.
<s:Boolean x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=Moq_002EAnalyzers_002EBenchmarks_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
18 changes: 9 additions & 9 deletions src/Moq.Analyzers/AnalyzerReleases.Shipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
Moq1101 | Moq | Warning | CallbackSignatureAnalyzer
Moq1002 | Moq | Warning | ShouldNotAllowParametersForMockedInterfaceAnalyzer
Moq1001 | Moq | Warning | ShouldNotMockSealedClassesAnalyzer
Moq1101 | Moq | Warning | CallbackSignatureAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1101.md)
Moq1002 | Moq | Warning | ShouldNotAllowParametersForMockedInterfaceAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1002.md)
Moq1001 | Moq | Warning | ShouldNotMockSealedClassesAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1001.md)

## Release 0.0.3.40797

Expand All @@ -25,37 +25,37 @@ Moq1003 | Moq | Warning | MatchingConstructorParametersAnalyzer

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
Moq1100 | Moq | Warning | CallbackSignatureShouldMatchMockedMethodAnalyzer
Moq1000 | Moq | Warning | ConstructorArgumentsShouldMatchAnalyzer
Moq1100 | Moq | Warning | CallbackSignatureShouldMatchMockedMethodAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1100.md)
Moq1000 | Moq | Warning | ConstructorArgumentsShouldMatchAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1000.md)

## Release 0.0.6

### Removed Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
Moq1003 | Moq | Warning | ConstructorArgumentsShouldMatchAnalyzer
Moq1003 | Moq | Warning | ConstructorArgumentsShouldMatchAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1003.md)

## Release 0.0.7

### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
Moq1200 | Moq | Error | SetupShouldBeUsedOnlyForOverridableMembersAnalyzer
Moq1200 | Moq | Error | SetupShouldBeUsedOnlyForOverridableMembersAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1200.md)

## Release 0.0.8

### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
Moq1300 | Moq | Error | AsShouldBeUsedOnlyForInterfaceAnalyzer
Moq1300 | Moq | Error | AsShouldBeUsedOnlyForInterfaceAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1300.md)

## Release 0.0.9

### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
Moq1201 | Moq | Error | SetupShouldNotIncludeAsyncResultAnalyzer
Moq1201 | Moq | Error | SetupShouldNotIncludeAsyncResultAnalyzer, [Documentation](https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/Moq1201.md)
54 changes: 29 additions & 25 deletions src/Moq.Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,57 @@ namespace Moq.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class AsShouldBeUsedOnlyForInterfaceAnalyzer : DiagnosticAnalyzer
{
internal const string RuleId = "Moq1300";
private const string Title = "Moq: Invalid As type parameter";
private const string Message = "Mock.As() should take interfaces only";

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

/// <inheritdoc />
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);
Comment thread
rjmurillo marked this conversation as resolved.

/// <inheritdoc />
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();

context.RegisterCompilationStartAction(RegisterCompilationStartAction);
}

context.RegisterCompilationStartAction(static context =>
private void RegisterCompilationStartAction(CompilationStartAnalysisContext context)
{
// Ensure Moq is referenced in the compilation
ImmutableArray<INamedTypeSymbol> mockTypes = context.Compilation.GetMoqMock();
if (mockTypes.IsEmpty)
{
// Ensure Moq is referenced in the compilation
ImmutableArray<INamedTypeSymbol> mockTypes = context.Compilation.GetMoqMock();
if (mockTypes.IsEmpty)
{
return;
}
return;
}

// Look for the Mock.As() method and provide it to Analyze to avoid looking it up multiple times.
ImmutableArray<IMethodSymbol> asMethods = mockTypes
.SelectMany(mockType => mockType.GetMembers(WellKnownTypeNames.As))
.OfType<IMethodSymbol>()
.Where(method => method.IsGenericMethod)
.ToImmutableArray();

// Look for the Mock.As() method and provide it to Analyze to avoid looking it up multiple times.
ImmutableArray<IMethodSymbol> asMethods = mockTypes
.SelectMany(mockType => mockType.GetMembers("As"))
.OfType<IMethodSymbol>()
.Where(method => method.IsGenericMethod)
.ToImmutableArray();
if (asMethods.IsEmpty)
{
return;
}
if (asMethods.IsEmpty)
{
return;
}

context.RegisterOperationAction(context => Analyze(context, asMethods), OperationKind.Invocation);
});
context.RegisterOperationAction(
operationAnalysisContext => Analyze(operationAnalysisContext, asMethods),
OperationKind.Invocation);
}

private static void Analyze(OperationAnalysisContext context, ImmutableArray<IMethodSymbol> wellKnownAsMethods)
private void Analyze(OperationAnalysisContext context, ImmutableArray<IMethodSymbol> wellKnownAsMethods)
{
if (context.Operation is not IInvocationOperation invocationOperation)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Diagnostics;

namespace Moq.Analyzers;

/// <summary>
Expand All @@ -8,7 +6,7 @@ namespace Moq.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class CallbackSignatureShouldMatchMockedMethodAnalyzer : DiagnosticAnalyzer
{
internal const string RuleId = "Moq1100";
internal const string RuleId = DiagnosticIds.BadCallbackParameters;
private const string Title = "Moq: Bad callback parameters";
private const string Message = "Callback signature must match the signature of the mocked method";

Expand All @@ -19,7 +17,7 @@ public class CallbackSignatureShouldMatchMockedMethodAnalyzer : DiagnosticAnalyz
DiagnosticCategory.Moq,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/main/docs/rules/{RuleId}.md");
helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{RuleId}.md");

/// <inheritdoc />
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Microsoft.CodeAnalysis.Operations;

namespace Moq.Analyzers;
namespace Moq.Analyzers.Common;
Comment thread
rjmurillo marked this conversation as resolved.

internal static class CompilationExtensions
{
Expand All @@ -27,7 +25,7 @@ public static ImmutableArray<INamedTypeSymbol> GetTypesByMetadataNames(this Comp
}

/// <summary>
/// Get the Moq.Mock and Moq.Mock`1 type symbols (if part of the compilation).
/// Get the Moq.MockRepository, Moq.Mock and Moq.Mock`1 type symbols (if part of the compilation).
/// </summary>
/// <param name="compilation">The <see cref="Compilation"/> to inspect.</param>
/// <returns>
Expand All @@ -36,6 +34,6 @@ public static ImmutableArray<INamedTypeSymbol> GetTypesByMetadataNames(this Comp
/// </returns>
public static ImmutableArray<INamedTypeSymbol> GetMoqMock(this Compilation compilation)
{
return compilation.GetTypesByMetadataNames([WellKnownTypeNames.MoqMock, WellKnownTypeNames.MoqMock1]);
return compilation.GetTypesByMetadataNames([WellKnownTypeNames.MoqMock, WellKnownTypeNames.MoqMock1, WellKnownTypeNames.MoqRepository]);
}
}
21 changes: 21 additions & 0 deletions src/Moq.Analyzers/Common/CompilationOptionsExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Moq.Analyzers.Common;
Comment thread
rjmurillo marked this conversation as resolved.

internal static class CompilationOptionsExtensions
{
/// <summary>
/// Determines if the diagnostic identified by the given identifier is currently suppressed.
/// </summary>
/// <param name="compilationOptions">The compilation options that will be used to determine if the diagnostic is currently suppressed.</param>
/// <param name="descriptor">The diagnostic descriptor to check.</param>
/// <returns>True if the diagnostic is currently suppressed.</returns>
internal static bool IsAnalyzerSuppressed(this CompilationOptions compilationOptions, DiagnosticDescriptor descriptor)
Comment thread
rjmurillo marked this conversation as resolved.
{
switch (descriptor.GetEffectiveSeverity(compilationOptions))
{
case ReportDiagnostic.Suppress:
return true;
default:
return false;
}
}
}
6 changes: 6 additions & 0 deletions src/Moq.Analyzers/Common/DiagnosticCategory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Moq.Analyzers.Common;
Comment thread
rjmurillo marked this conversation as resolved.

internal static class DiagnosticCategory
{
internal const string Moq = nameof(Moq);
}
Loading