Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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: 0 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
<PackageVersion Include="bunit" Version="2.7.2" />
<PackageVersion Include="FluentAssertions" Version="[7.2.0]" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.3.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="5.3.0" />
Expand Down
6 changes: 6 additions & 0 deletions FastMoq-Release.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastMoq", "FastMoq\FastMoq.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastMoq.Abstractions", "FastMoq.Abstractions\FastMoq.Abstractions.csproj", "{970828D1-0EF2-4D0D-BF1B-BB85DEB38514}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastMoq.Generators", "FastMoq.Generators\FastMoq.Generators.csproj", "{3A865DC1-4C90-42F7-B0E9-25A31D7C432E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastMoq.Azure", "FastMoq.Azure\FastMoq.Azure.csproj", "{CADD0874-D3E6-40B3-A8D5-EB04047597EC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastMoq.Core", "FastMoq.Core\FastMoq.Core.csproj", "{2E2FC5C0-5B64-48BA-92F6-DF0DD46298E0}"
Expand Down Expand Up @@ -37,6 +39,10 @@ Global
{970828D1-0EF2-4D0D-BF1B-BB85DEB38514}.Debug|Any CPU.Build.0 = Release|Any CPU
{970828D1-0EF2-4D0D-BF1B-BB85DEB38514}.Release|Any CPU.ActiveCfg = Release|Any CPU
{970828D1-0EF2-4D0D-BF1B-BB85DEB38514}.Release|Any CPU.Build.0 = Release|Any CPU
{3A865DC1-4C90-42F7-B0E9-25A31D7C432E}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{3A865DC1-4C90-42F7-B0E9-25A31D7C432E}.Debug|Any CPU.Build.0 = Release|Any CPU
{3A865DC1-4C90-42F7-B0E9-25A31D7C432E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A865DC1-4C90-42F7-B0E9-25A31D7C432E}.Release|Any CPU.Build.0 = Release|Any CPU
{CADD0874-D3E6-40B3-A8D5-EB04047597EC}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{CADD0874-D3E6-40B3-A8D5-EB04047597EC}.Debug|Any CPU.Build.0 = Release|Any CPU
{CADD0874-D3E6-40B3-A8D5-EB04047597EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace FastMoq.Generators
{
/// <summary>
/// Marks a partial <c>MockerTestBase&lt;TComponent&gt;</c> test base for FastMoq's explicit compile-time harness generation path.
/// </summary>
/// <remarks>
/// <para>Apply this attribute only to partial test-base types that derive from <c>MockerTestBase&lt;TComponent&gt;</c>.</para>
/// <para>The first generator slice keeps opt-in explicit and emits constructor-signature metadata for the selected component path rather than enabling blanket automatic generation for every eligible type in a project.</para>
/// </remarks>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class FastMoqGeneratedTestTargetAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="FastMoqGeneratedTestTargetAttribute" /> class.
/// </summary>
/// <param name="componentType">The component under test that the generated harness path should target.</param>
/// <param name="constructorParameterTypes">An optional explicit constructor signature to use for the generated harness bootstrap.</param>
public FastMoqGeneratedTestTargetAttribute(Type componentType, params Type[] constructorParameterTypes)
{
ComponentType = componentType ?? throw new ArgumentNullException(nameof(componentType));
ConstructorParameterTypes = constructorParameterTypes ?? throw new ArgumentNullException(nameof(constructorParameterTypes));
}

/// <summary>
/// Gets the component under test that the generated harness path should target.
/// </summary>
public Type ComponentType { get; }

/// <summary>
/// Gets the optional explicit constructor signature that the generator should use.
/// </summary>
public IReadOnlyList<Type> ConstructorParameterTypes { get; }
}
}
138 changes: 126 additions & 12 deletions FastMoq.Analyzers.Tests/AnalyzerTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ namespace FastMoq.Analyzers.Tests
{
internal static class AnalyzerTestHelpers
{
private static readonly HashSet<string> ExcludedTrustedPlatformAssemblyNames = new(StringComparer.OrdinalIgnoreCase)
{
"FastMoq.Analyzers.Tests",
"FastMoq.Tests",
"FastMoq.Tests.Blazor",
"FastMoq.Tests.Web",
};

public static async Task<ImmutableArray<Diagnostic>> GetDiagnosticsAsync(string source, params DiagnosticAnalyzer[] analyzers)
{
return await GetDiagnosticsAsync(source, includeAzureFunctionsHelpers: false, includeMoqProviderPackage: true, includeNSubstituteProviderPackage: true, includeWebHelpers: true, analyzers).ConfigureAwait(false);
Expand Down Expand Up @@ -132,18 +140,58 @@ public static string NormalizeCode(string source)
.ToFullString();
}

public static Document CreateDocumentForTest(string source, bool includeAzureFunctionsHelpers = false, bool includeMoqProviderPackage = true, bool includeNSubstituteProviderPackage = true, bool includeWebHelpers = true)
public static Document CreateDocumentForTest(
string source,
bool includeAzureFunctionsHelpers = false,
bool includeMoqProviderPackage = true,
bool includeNSubstituteProviderPackage = true,
bool includeWebHelpers = true,
bool includeDatabaseHelpers = false,
bool includeAzureHelpers = false,
bool includeAggregatePackage = false)
{
return CreateDocument(source, includeAzureFunctionsHelpers, includeMoqProviderPackage, includeNSubstituteProviderPackage, includeWebHelpers);
return CreateDocument(
source,
includeAzureFunctionsHelpers,
includeMoqProviderPackage,
includeNSubstituteProviderPackage,
includeWebHelpers,
includeDatabaseHelpers,
includeAzureHelpers,
includeAggregatePackage);
}

private static Document CreateDocument(string source, bool includeAzureFunctionsHelpers = false, bool includeMoqProviderPackage = true, bool includeNSubstituteProviderPackage = true, bool includeWebHelpers = true)
private static Document CreateDocument(
string source,
bool includeAzureFunctionsHelpers = false,
bool includeMoqProviderPackage = true,
bool includeNSubstituteProviderPackage = true,
bool includeWebHelpers = true,
bool includeDatabaseHelpers = false,
bool includeAzureHelpers = false,
bool includeAggregatePackage = false)
{
var project = CreateProject([("Test.cs", source)], includeAzureFunctionsHelpers, includeMoqProviderPackage, includeNSubstituteProviderPackage, includeWebHelpers);
var project = CreateProject(
[("Test.cs", source)],
includeAzureFunctionsHelpers,
includeMoqProviderPackage,
includeNSubstituteProviderPackage,
includeWebHelpers,
includeDatabaseHelpers,
includeAzureHelpers,
includeAggregatePackage);
return project.Documents.Single();
}

private static Project CreateProject(IReadOnlyList<(string fileName, string source)> sources, bool includeAzureFunctionsHelpers = false, bool includeMoqProviderPackage = true, bool includeNSubstituteProviderPackage = true, bool includeWebHelpers = true)
private static Project CreateProject(
IReadOnlyList<(string fileName, string source)> sources,
bool includeAzureFunctionsHelpers = false,
bool includeMoqProviderPackage = true,
bool includeNSubstituteProviderPackage = true,
bool includeWebHelpers = true,
bool includeDatabaseHelpers = false,
bool includeAzureHelpers = false,
bool includeAggregatePackage = false)
{
var workspace = new AdhocWorkspace();
var projectId = ProjectId.CreateNewId();
Expand All @@ -153,7 +201,14 @@ private static Project CreateProject(IReadOnlyList<(string fileName, string sour
.WithProjectParseOptions(projectId, new CSharpParseOptions(LanguageVersion.Preview))
.WithProjectCompilationOptions(projectId, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

foreach (var metadataReference in GetMetadataReferences(includeAzureFunctionsHelpers, includeMoqProviderPackage, includeNSubstituteProviderPackage, includeWebHelpers))
foreach (var metadataReference in GetMetadataReferences(
includeAzureFunctionsHelpers,
includeMoqProviderPackage,
includeNSubstituteProviderPackage,
includeWebHelpers,
includeDatabaseHelpers,
includeAzureHelpers,
includeAggregatePackage))
{
solution = solution.AddMetadataReference(projectId, metadataReference);
}
Expand All @@ -167,33 +222,72 @@ private static Project CreateProject(IReadOnlyList<(string fileName, string sour
return solution.GetProject(projectId)!;
}

private static IEnumerable<MetadataReference> GetMetadataReferences(bool includeAzureFunctionsHelpers, bool includeMoqProviderPackage, bool includeNSubstituteProviderPackage, bool includeWebHelpers)
private static IEnumerable<MetadataReference> GetMetadataReferences(
bool includeAzureFunctionsHelpers,
bool includeMoqProviderPackage,
bool includeNSubstituteProviderPackage,
bool includeWebHelpers,
bool includeDatabaseHelpers,
bool includeAzureHelpers,
bool includeAggregatePackage)
{
if (includeAggregatePackage)
{
includeAzureFunctionsHelpers = true;
includeAzureHelpers = true;
includeDatabaseHelpers = true;
includeWebHelpers = true;
}

var references = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") is string trustedPlatformAssemblies)
{
foreach (var assemblyPath in trustedPlatformAssemblies.Split(Path.PathSeparator))
{
var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
if (ExcludedTrustedPlatformAssemblyNames.Contains(assemblyName))
{
continue;
}

if (!includeAggregatePackage &&
string.Equals(assemblyName, "FastMoq", StringComparison.OrdinalIgnoreCase))
{
continue;
}

if (!includeDatabaseHelpers &&
string.Equals(assemblyName, "FastMoq.Database", StringComparison.OrdinalIgnoreCase))
{
continue;
}

if (!includeAzureHelpers &&
string.Equals(assemblyName, "FastMoq.Azure", StringComparison.OrdinalIgnoreCase))
{
continue;
}

if (!includeWebHelpers &&
string.Equals(Path.GetFileNameWithoutExtension(assemblyPath), "FastMoq.Web", StringComparison.OrdinalIgnoreCase))
string.Equals(assemblyName, "FastMoq.Web", StringComparison.OrdinalIgnoreCase))
{
continue;
}

if (!includeAzureFunctionsHelpers &&
string.Equals(Path.GetFileNameWithoutExtension(assemblyPath), "FastMoq.AzureFunctions", StringComparison.OrdinalIgnoreCase))
string.Equals(assemblyName, "FastMoq.AzureFunctions", StringComparison.OrdinalIgnoreCase))
{
continue;
}

if (!includeMoqProviderPackage &&
string.Equals(Path.GetFileNameWithoutExtension(assemblyPath), "FastMoq.Provider.Moq", StringComparison.OrdinalIgnoreCase))
string.Equals(assemblyName, "FastMoq.Provider.Moq", StringComparison.OrdinalIgnoreCase))
{
continue;
}

if (!includeNSubstituteProviderPackage &&
string.Equals(Path.GetFileNameWithoutExtension(assemblyPath), "FastMoq.Provider.NSubstitute", StringComparison.OrdinalIgnoreCase))
string.Equals(assemblyName, "FastMoq.Provider.NSubstitute", StringComparison.OrdinalIgnoreCase))
{
continue;
}
Expand All @@ -203,12 +297,32 @@ private static IEnumerable<MetadataReference> GetMetadataReferences(bool include
}

references.Add(typeof(FastMoq.Mocker).Assembly.Location);
references.Add(typeof(FastMoq.Providers.FastMoqDefaultProviderAttribute).Assembly.Location);

if (includeAggregatePackage)
{
var aggregateAssemblyPath = Path.Combine(Path.GetDirectoryName(typeof(FastMoq.Mocker).Assembly.Location)!, "FastMoq.dll");
if (File.Exists(aggregateAssemblyPath))
{
references.Add(aggregateAssemblyPath);
}
}

if (includeWebHelpers)
{
references.Add(typeof(FastMoq.Web.Extensions.TestWebExtensions).Assembly.Location);
}

if (includeDatabaseHelpers)
{
references.Add(typeof(FastMoq.DbContextMockerExtensions).Assembly.Location);
}

if (includeAzureHelpers)
{
references.Add(typeof(FastMoq.Azure.Pageable.PageableBuilder).Assembly.Location);
}

if (includeMoqProviderPackage)
{
references.Add(typeof(FastMoq.Providers.MoqProvider.IFastMockMoqExtensions).Assembly.Location);
Expand All @@ -229,7 +343,7 @@ private static IEnumerable<MetadataReference> GetMetadataReferences(bool include
{
references.Add(typeof(FastMoq.AzureFunctions.Extensions.FunctionContextTestExtensions).Assembly.Location);
references.Add(typeof(Microsoft.Azure.Functions.Worker.FunctionContext).Assembly.Location);
references.Add(typeof(Azure.Core.Serialization.ObjectSerializer).Assembly.Location);
references.Add(typeof(global::Azure.Core.Serialization.ObjectSerializer).Assembly.Location);
}

return references.Select(path => MetadataReference.CreateFromFile(path));
Expand Down
5 changes: 5 additions & 0 deletions FastMoq.Analyzers.Tests/FastMoq.Analyzers.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@

<ItemGroup>
<ProjectReference Include="..\FastMoq.Analyzers\FastMoq.Analyzers.csproj" OutputItemType="Analyzer" />
<ProjectReference Include="..\FastMoq\FastMoq.csproj" />
<ProjectReference Include="..\FastMoq.Azure\FastMoq.Azure.csproj" />
<ProjectReference Include="..\FastMoq.AzureFunctions\FastMoq.AzureFunctions.csproj" />
<ProjectReference Include="..\FastMoq.Core\FastMoq.Core.csproj" />
<ProjectReference Include="..\FastMoq.Database\FastMoq.Database.csproj" />
<ProjectReference Include="..\FastMoq.Generators\FastMoq.Generators.csproj" />
<ProjectReference Include="..\FastMoq.Tests\FastMoq.Tests.csproj" />
<ProjectReference Include="..\FastMoq.Provider.Moq\FastMoq.Provider.Moq.csproj" />
Comment thread
cwinland marked this conversation as resolved.
<ProjectReference Include="..\FastMoq.Provider.NSubstitute\FastMoq.Provider.NSubstitute.csproj" />
<ProjectReference Include="..\FastMoq.Web\FastMoq.Web.csproj" />
Expand Down
Loading
Loading