diff --git a/.github/workflows/BuildAndTest.yml b/.github/workflows/BuildAndTest.yml
new file mode 100644
index 0000000..db86bae
--- /dev/null
+++ b/.github/workflows/BuildAndTest.yml
@@ -0,0 +1,31 @@
+name: Build and Test
+
+on:
+ pull_request:
+ branches:
+ - '**'
+ push:
+ branches:
+ - 'main'
+
+jobs:
+ build-and-test:
+ name: Build and Test on ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [windows-2022]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup .NET 8 SDK
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '8.0.x'
+
+ - name: 'Build'
+ run: dotnet build "./FluentBuilder Solution.sln" -c Release
+
+ - name: 'Test'
+ run: dotnet test ./tests/FluentBuilderGeneratorTests/FluentBuilderGeneratorTests.csproj --no-build -c Release
\ No newline at end of file
diff --git a/FluentBuilder Solution.sln b/FluentBuilder Solution.sln
index 08f6784..07eea4b 100644
--- a/FluentBuilder Solution.sln
+++ b/FluentBuilder Solution.sln
@@ -46,6 +46,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuilderConsumerFileScopedNa
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub Actions", "GitHub Actions", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
ProjectSection(SolutionItems) = preProject
+ .github\workflows\BuildAndTest.yml = .github\workflows\BuildAndTest.yml
.github\workflows\CreateRelease.yml = .github\workflows\CreateRelease.yml
EndProjectSection
EndProject
diff --git a/FluentBuilder Solution.sln.DotSettings b/FluentBuilder Solution.sln.DotSettings
index d84748d..74a6126 100644
--- a/FluentBuilder Solution.sln.DotSettings
+++ b/FluentBuilder Solution.sln.DotSettings
@@ -1,3 +1,7 @@
+ True
+ True
True
+ True
+ True
True
\ No newline at end of file
diff --git a/src-examples/BuilderConsumerFileScopedNamespace/BuilderConsumerFileScopedNamespace.csproj b/src-examples/BuilderConsumerFileScopedNamespace/BuilderConsumerFileScopedNamespace.csproj
index d4efa64..285d5de 100644
--- a/src-examples/BuilderConsumerFileScopedNamespace/BuilderConsumerFileScopedNamespace.csproj
+++ b/src-examples/BuilderConsumerFileScopedNamespace/BuilderConsumerFileScopedNamespace.csproj
@@ -12,8 +12,8 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src-examples/BuilderConsumerNET45/BuilderConsumerNET45_viaNuGet.csproj b/src-examples/BuilderConsumerNET45/BuilderConsumerNET45_viaNuGet.csproj
index 1c9b54f..a908642 100644
--- a/src-examples/BuilderConsumerNET45/BuilderConsumerNET45_viaNuGet.csproj
+++ b/src-examples/BuilderConsumerNET45/BuilderConsumerNET45_viaNuGet.csproj
@@ -6,11 +6,11 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/src-examples/BuilderConsumerNET45/Program.cs b/src-examples/BuilderConsumerNET45/Program.cs
index c72526b..e92b991 100644
--- a/src-examples/BuilderConsumerNET45/Program.cs
+++ b/src-examples/BuilderConsumerNET45/Program.cs
@@ -14,7 +14,7 @@ static void Main(string[] args)
Console.WriteLine("t0 = " + JsonConvert.SerializeObject(t0));
var t1 = new ThingWithOnlyParameterizedConstructorsBuilder()
- .WithConstructor(1,2,"xxx")
+ .UsingConstructor(1,2,"xxx")
.Build();
Console.WriteLine("t1 = " + JsonConvert.SerializeObject(t1));
diff --git a/src-examples/BuilderConsumerNET72/BuilderConsumerNET72.csproj b/src-examples/BuilderConsumerNET72/BuilderConsumerNET72.csproj
index 65f4ae0..c7eaa31 100644
--- a/src-examples/BuilderConsumerNET72/BuilderConsumerNET72.csproj
+++ b/src-examples/BuilderConsumerNET72/BuilderConsumerNET72.csproj
@@ -1,4 +1,4 @@
-
+
Exe
diff --git a/src-examples/BuilderConsumerNET8_ViaNuGet/BuilderConsumerNET8_ViaNuGet.csproj b/src-examples/BuilderConsumerNET8_ViaNuGet/BuilderConsumerNET8_ViaNuGet.csproj
index 7e9a32e..8017749 100644
--- a/src-examples/BuilderConsumerNET8_ViaNuGet/BuilderConsumerNET8_ViaNuGet.csproj
+++ b/src-examples/BuilderConsumerNET8_ViaNuGet/BuilderConsumerNET8_ViaNuGet.csproj
@@ -10,7 +10,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src-examples/BuilderConsumerNET8_ViaNuGet/ClassWithPrivateSetter.cs b/src-examples/BuilderConsumerNET8_ViaNuGet/ClassWithPrivateSetter.cs
index 7202c51..046d62d 100644
--- a/src-examples/BuilderConsumerNET8_ViaNuGet/ClassWithPrivateSetter.cs
+++ b/src-examples/BuilderConsumerNET8_ViaNuGet/ClassWithPrivateSetter.cs
@@ -8,5 +8,11 @@ public class ClassWithPrivateSetter
public int Value1 { get; private set; }
public int Value2 { get; set; }
+
+ [AutoGenerateBuilder(FluentBuilderAccessibility.PublicAndPrivate)]
+ private class PrivateClass
+ {
+ public int Test { get; set; }
+ }
}
}
\ No newline at end of file
diff --git a/src-extensions/CSharp.SourceGenerators.Extensions/CSharp.SourceGenerators.Extensions.csproj b/src-extensions/CSharp.SourceGenerators.Extensions/CSharp.SourceGenerators.Extensions.csproj
index fc08acb..d8c172f 100644
--- a/src-extensions/CSharp.SourceGenerators.Extensions/CSharp.SourceGenerators.Extensions.csproj
+++ b/src-extensions/CSharp.SourceGenerators.Extensions/CSharp.SourceGenerators.Extensions.csproj
@@ -6,7 +6,7 @@
latest
enable
Stef Heyenrath
- Some extensions for a ISourceGenerator which can be used to execute a SourceGenerator manually which makes unit-testing easy.
+ Some extensions for a ISourceGenerator and IIncrementalGenerator which can be used to execute a SourceGenerator manually which makes unit-testing easy.
CSharp;SourceGenerator;SourceGenerators;Extensions;Execute;UnitTest;Test
icon.png
MIT
@@ -27,8 +27,8 @@
-
-
+
+
\ No newline at end of file
diff --git a/src-extensions/CSharp.SourceGenerators.Extensions/Compatibility/RequiredMemberAttribute.cs b/src-extensions/CSharp.SourceGenerators.Extensions/Compatibility/RequiredMemberAttribute.cs
new file mode 100644
index 0000000..67c9a7b
--- /dev/null
+++ b/src-extensions/CSharp.SourceGenerators.Extensions/Compatibility/RequiredMemberAttribute.cs
@@ -0,0 +1,13 @@
+// ReSharper disable once CheckNamespace
+namespace System.Runtime.CompilerServices;
+
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
+internal sealed class RequiredMemberAttribute : Attribute;
+
+[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
+internal sealed class CompilerFeatureRequiredAttribute(string featureName) : Attribute
+{
+ public string FeatureName { get; } = featureName;
+
+ public bool IsOptional { get; init; }
+}
\ No newline at end of file
diff --git a/src-extensions/CSharp.SourceGenerators.Extensions/Models/ExecuteResult.cs b/src-extensions/CSharp.SourceGenerators.Extensions/Models/ExecuteResult.cs
index 20e1617..fd7cd01 100644
--- a/src-extensions/CSharp.SourceGenerators.Extensions/Models/ExecuteResult.cs
+++ b/src-extensions/CSharp.SourceGenerators.Extensions/Models/ExecuteResult.cs
@@ -8,22 +8,32 @@ public class ExecuteResult
///
/// The internally used GeneratorDriver is also returned here to support using https://github.com/VerifyTests/Verify.SourceGenerators.
///
- public GeneratorDriver GeneratorDriver { get; set; } = null!;
+ public required GeneratorDriver GeneratorDriver { get; init; }
///
/// A list of generated files.
///
- public IReadOnlyList Files { get; set; } = new List();
+ public required IReadOnlyList Files { get; init; }
///
- /// A list of Errors
+ /// Gets the collection of diagnostics associated with the current operation or state.
///
- public IReadOnlyList ErrorMessages { get; set; } = new List();
+ public required IReadOnlyList Diagnostics { get; init; }
///
- /// A list of Warnings
+ /// A list of Error messages
///
- public IReadOnlyList WarningMessages { get; set; } = new List();
+ public required IReadOnlyList ErrorMessages { get; init; }
+
+ ///
+ /// A list of Warning messages
+ ///
+ public required IReadOnlyList WarningMessages { get; init; }
+
+ ///
+ /// A list of Information messages
+ ///
+ public required IReadOnlyList InformationMessages { get; init; }
///
/// Is the result valid.
diff --git a/src-extensions/CSharp.SourceGenerators.Extensions/SourceGeneratorExtensions.cs b/src-extensions/CSharp.SourceGenerators.Extensions/SourceGeneratorExtensions.cs
index 250fd1f..c1b1a11 100644
--- a/src-extensions/CSharp.SourceGenerators.Extensions/SourceGeneratorExtensions.cs
+++ b/src-extensions/CSharp.SourceGenerators.Extensions/SourceGeneratorExtensions.cs
@@ -29,7 +29,7 @@ public static ExecuteResult Execute(
IReadOnlyList? additionalTextPaths = null
)
{
- return Execute(sourceGenerator, $"GeneratedNamespace_{Guid.NewGuid().ToString().Replace("-", "")}", sources, additionalTextPaths);
+ return Execute(sourceGenerator, GetRandomAssemblyName(), sources, additionalTextPaths);
}
///
@@ -47,6 +47,52 @@ public static ExecuteResult Execute(
IReadOnlyList? additionalTextPaths = null
)
{
+ return ExecuteInternal(() => CSharpGeneratorDriver.Create(sourceGenerator), assemblyName, sources, additionalTextPaths);
+ }
+
+ ///
+ /// Executes and runs the specified .
+ ///
+ /// The SourceGenerator to execute.
+ /// Provide a list of sources which need to be analyzed and processed.
+ /// A list of additional files.
+ ///
+ public static ExecuteResult Execute(
+ this IIncrementalGenerator sourceGenerator,
+ IReadOnlyList sources,
+ IReadOnlyList? additionalTextPaths = null
+ )
+ {
+ return Execute(sourceGenerator, GetRandomAssemblyName(), sources, additionalTextPaths);
+ }
+
+ ///
+ /// Executes and runs the specified .
+ ///
+ /// The SourceGenerator to execute.
+ /// The assembly name.
+ /// Provide a list of sources which need to be analyzed and processed.
+ /// A list of additional files.
+ ///
+ public static ExecuteResult Execute(
+ this IIncrementalGenerator sourceGenerator,
+ string assemblyName,
+ IReadOnlyList sources,
+ IReadOnlyList? additionalTextPaths = null
+ )
+ {
+ return ExecuteInternal(() => CSharpGeneratorDriver.Create(sourceGenerator), assemblyName, sources, additionalTextPaths);
+ }
+
+ private static ExecuteResult ExecuteInternal(
+ Func driverFactory,
+ string assemblyName,
+ IReadOnlyList sources,
+ IReadOnlyList? additionalTextPaths = null
+ )
+ {
+ var driver = driverFactory();
+
var metadataReferences = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic)
.Select(a => MetadataReference.CreateFromFile(a.Location))
@@ -62,9 +108,7 @@ public static ExecuteResult Execute(
metadataReferences,
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
- var driver = CSharpGeneratorDriver
- .Create(sourceGenerator)
- .AddAdditionalTexts(ImmutableArray.CreateRange(additionalTexts));
+ driver = driver.AddAdditionalTexts(ImmutableArray.CreateRange(additionalTexts));
var executedDriver = driver.RunGeneratorsAndUpdateCompilation(
compilation,
@@ -74,8 +118,10 @@ public static ExecuteResult Execute(
return new ExecuteResult
{
GeneratorDriver = executedDriver,
- WarningMessages = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Warning).Select(d => d.GetMessage()).ToList(),
- ErrorMessages = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).Select(d => d.GetMessage()).ToList(),
+ Diagnostics = diagnostics,
+ InformationMessages = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Info).Select(d => d.GetMessage()).ToArray(),
+ WarningMessages = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Warning).Select(d => d.GetMessage()).ToArray(),
+ ErrorMessages = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).Select(d => d.GetMessage()).ToArray(),
Files = outputCompilation.SyntaxTrees
.Where(st => !sources.Any(s => s.Path == st.FilePath))
.Select(st => new FileResult
@@ -110,7 +156,7 @@ private static SyntaxTree GetSyntaxTree(SourceFile source)
}
else
{
- throw new InvalidOperationException("If AttributeToAddToClass is defined, the target must be a record or class.");
+ throw new InvalidOperationException("If AttributeToAddToClass is defined, the target must be a class or record.");
}
}
else if (source.AttributeToAddToInterface is not null && TryAddExtraAttribute(syntaxTree, source.AttributeToAddToInterface.Value, out var interfaceNode))
@@ -187,4 +233,9 @@ private static bool TryParseArguments(AnyOf attributeToA
attributeArgumentListSyntax = null;
return false;
}
+
+ private static string GetRandomAssemblyName()
+ {
+ return $"CSharp.SourceGenerators.Extensions.Generated_{Guid.NewGuid().ToString().Replace("-", "")}";
+ }
}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/AnalyzerReleases.Shipped.md b/src/FluentBuilderGenerator/AnalyzerReleases.Shipped.md
new file mode 100644
index 0000000..2080dcd
--- /dev/null
+++ b/src/FluentBuilderGenerator/AnalyzerReleases.Shipped.md
@@ -0,0 +1,3 @@
+; Shipped analyzer releases
+; https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
+
diff --git a/src/FluentBuilderGenerator/AnalyzerReleases.Unshipped.md b/src/FluentBuilderGenerator/AnalyzerReleases.Unshipped.md
new file mode 100644
index 0000000..418950c
--- /dev/null
+++ b/src/FluentBuilderGenerator/AnalyzerReleases.Unshipped.md
@@ -0,0 +1,10 @@
+; Unshipped analyzer release
+; https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
+
+### New Rules
+
+Rule ID | Category | Severity | Notes
+--------|----------|----------|-------
+FBGERR0001 | FluentBuilderGenerator | Error | DiagnosticDescriptors
+FBGINF0001 | FluentBuilderGenerator | Info | DiagnosticDescriptors
+FBGINF0002 | FluentBuilderGenerator | Info | DiagnosticDescriptors
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Compatibility/IsExternalInit.cs b/src/FluentBuilderGenerator/Compatibility/IsExternalInit.cs
index ec49e6d..12b2b60 100644
--- a/src/FluentBuilderGenerator/Compatibility/IsExternalInit.cs
+++ b/src/FluentBuilderGenerator/Compatibility/IsExternalInit.cs
@@ -2,4 +2,5 @@
// ReSharper disable once CheckNamespace
namespace System.Runtime.CompilerServices;
+// ReSharper disable once RedundantTypeDeclarationBody
internal class IsExternalInit { }
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Compatibility/NullableAttributes.cs b/src/FluentBuilderGenerator/Compatibility/NullableAttributes.cs
index a5fbb0e..066cbcb 100644
--- a/src/FluentBuilderGenerator/Compatibility/NullableAttributes.cs
+++ b/src/FluentBuilderGenerator/Compatibility/NullableAttributes.cs
@@ -4,7 +4,7 @@
namespace System.Diagnostics.CodeAnalysis;
/// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it.
-[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+[AttributeUsage(AttributeTargets.Parameter)]
internal sealed class NotNullWhenAttribute : Attribute
{
/// Initializes the attribute with the specified return value condition.
diff --git a/src/FluentBuilderGenerator/Constants/DiagnosticDescriptors.cs b/src/FluentBuilderGenerator/Constants/DiagnosticDescriptors.cs
new file mode 100644
index 0000000..42afe16
--- /dev/null
+++ b/src/FluentBuilderGenerator/Constants/DiagnosticDescriptors.cs
@@ -0,0 +1,34 @@
+using Microsoft.CodeAnalysis;
+
+namespace FluentBuilderGenerator.Constants;
+
+internal static class DiagnosticDescriptors
+{
+ internal static readonly DiagnosticDescriptor Error = new(
+ "FBGERR0001",
+ "Source generator exception",
+ "An exception occurred during source generation: {0}",
+ nameof(FluentBuilderGenerator),
+ DiagnosticSeverity.Error,
+ true,
+ "An unhandled exception occurred while generating source code."
+ );
+
+ internal static readonly DiagnosticDescriptor ClassOrRecordModifierShouldBeInternalOrPublic = new(
+ "FBGINF0001",
+ "Information",
+ "Class or Record modifier should be 'public' or 'internal'",
+ nameof(FluentBuilderGenerator),
+ DiagnosticSeverity.Info,
+ true
+ );
+
+ internal static readonly DiagnosticDescriptor CustomBuilderClassModifierShouldBePartialAndInternalOrPublic = new(
+ "FBGINF0002",
+ "Information",
+ "Custom builder class should be 'partial' and 'public' or 'internal'",
+ nameof(FluentBuilderGenerator),
+ DiagnosticSeverity.Info,
+ true
+ );
+}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Extensions/ExceptionExtensions.cs b/src/FluentBuilderGenerator/Extensions/ExceptionExtensions.cs
new file mode 100644
index 0000000..ce7edec
--- /dev/null
+++ b/src/FluentBuilderGenerator/Extensions/ExceptionExtensions.cs
@@ -0,0 +1,12 @@
+using FluentBuilderGenerator.Constants;
+using Microsoft.CodeAnalysis;
+
+namespace FluentBuilderGenerator.Extensions;
+
+internal static class ExceptionExtensions
+{
+ internal static Diagnostic ToDiagnostic(this Exception exception)
+ {
+ return Diagnostic.Create(DiagnosticDescriptors.Error, Location.None, exception);
+ }
+}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Extensions/PropertySymbolExtensions.cs b/src/FluentBuilderGenerator/Extensions/PropertySymbolExtensions.cs
index fe7fc89..77f11ed 100644
--- a/src/FluentBuilderGenerator/Extensions/PropertySymbolExtensions.cs
+++ b/src/FluentBuilderGenerator/Extensions/PropertySymbolExtensions.cs
@@ -37,7 +37,7 @@ internal static bool TryGetIDictionaryElementTypes(this IPropertyOrParameterSymb
if (type == FluentTypeKind.IDictionary && property.Type is INamedTypeSymbol namedTypeSymbol)
{
- if (namedTypeSymbol.IsGenericType && namedTypeSymbol.TypeArguments.Length == 2)
+ if (namedTypeSymbol is { IsGenericType: true, TypeArguments.Length: 2 })
{
if (namedTypeSymbol.TypeArguments[0] is INamedTypeSymbol key && namedTypeSymbol.TypeArguments[1] is INamedTypeSymbol value)
{
@@ -47,7 +47,7 @@ internal static bool TryGetIDictionaryElementTypes(this IPropertyOrParameterSymb
}
}
- tuple = default;
+ tuple = null;
return false;
}
diff --git a/src/FluentBuilderGenerator/Extensions/SymbolExtensions.cs b/src/FluentBuilderGenerator/Extensions/SymbolExtensions.cs
index a9a6630..12f6634 100644
--- a/src/FluentBuilderGenerator/Extensions/SymbolExtensions.cs
+++ b/src/FluentBuilderGenerator/Extensions/SymbolExtensions.cs
@@ -7,10 +7,10 @@ namespace FluentBuilderGenerator.Extensions;
internal static class SymbolExtensions
{
private static readonly string[] ExcludedAttributes =
- {
+ [
InternalClassNames.AsyncStateMachineAttribute ,
InternalClassNames.NullableAttribute
- };
+ ];
public static string GetDeterministicHashCodeAsString(this ISymbol symbol)
{
diff --git a/src/FluentBuilderGenerator/Extensions/SyntaxNodeExtensions.cs b/src/FluentBuilderGenerator/Extensions/SyntaxNodeExtensions.cs
index adda0a9..75d5e7a 100644
--- a/src/FluentBuilderGenerator/Extensions/SyntaxNodeExtensions.cs
+++ b/src/FluentBuilderGenerator/Extensions/SyntaxNodeExtensions.cs
@@ -17,14 +17,13 @@ public static string GetNamespace(this SyntaxNode syntaxNode)
{
// If we don't have a namespace at all we'll return an empty string
// This accounts for the "default namespace" case
- string nameSpace = string.Empty;
+ var nameSpace = string.Empty;
// Get the containing syntax node for the type declaration
// (could be a nested type, for example)
- SyntaxNode? potentialNamespaceParent = syntaxNode.Parent;
+ var potentialNamespaceParent = syntaxNode.Parent;
- // Keep moving "out" of nested classes etc until we get to a namespace
- // or until we run out of parents
+ // Keep moving "out" of nested classes until we get to a namespace or until we run out of parents
while (potentialNamespaceParent != null &&
potentialNamespaceParent is not NamespaceDeclarationSyntax
&& potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax)
diff --git a/src/FluentBuilderGenerator/Extensions/TypeDeclarationSyntaxExtensions.cs b/src/FluentBuilderGenerator/Extensions/TypeDeclarationSyntaxExtensions.cs
index 680575a..3e9dd3b 100644
--- a/src/FluentBuilderGenerator/Extensions/TypeDeclarationSyntaxExtensions.cs
+++ b/src/FluentBuilderGenerator/Extensions/TypeDeclarationSyntaxExtensions.cs
@@ -8,9 +8,9 @@ namespace FluentBuilderGenerator.Extensions;
///
internal static class TypeDeclarationSyntaxExtensions
{
- const char NESTED_CLASS_DELIMITER = '+';
- const char NAMESPACE_CLASS_DELIMITER = '.';
- const char TYPEPARAMETER_CLASS_DELIMITER = '`';
+ private const char NestedClassDelimiter = '+';
+ private const char NamespaceClassDelimiter = '.';
+ private const char TypeparameterClassDelimiter = '`';
public static string GetMetadataName(this TypeDeclarationSyntax source)
{
@@ -31,14 +31,14 @@ public static string GetMetadataName(this TypeDeclarationSyntax source)
var result = new StringBuilder();
for (var item = namespaces.First; item is not null; item = item.Next)
{
- result.Append(item.Value.Name).Append(NAMESPACE_CLASS_DELIMITER);
+ result.Append(item.Value.Name).Append(NamespaceClassDelimiter);
}
for (var item = types.First; item is not null; item = item.Next)
{
var type = item.Value;
AppendName(result, type);
- result.Append(NESTED_CLASS_DELIMITER);
+ result.Append(NestedClassDelimiter);
}
AppendName(result, source);
@@ -51,7 +51,7 @@ private static void AppendName(StringBuilder builder, TypeDeclarationSyntax type
var typeArguments = type.TypeParameterList?.ChildNodes().Count(node => node is TypeParameterSyntax) ?? 0;
if (typeArguments != 0)
{
- builder.Append(TYPEPARAMETER_CLASS_DELIMITER).Append(typeArguments);
+ builder.Append(TypeparameterClassDelimiter).Append(typeArguments);
}
}
}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/FileGenerators/ExtraFilesGenerator.cs b/src/FluentBuilderGenerator/FileGenerators/ExtraFilesGenerator.cs
index 2ae9143..f5f6931 100644
--- a/src/FluentBuilderGenerator/FileGenerators/ExtraFilesGenerator.cs
+++ b/src/FluentBuilderGenerator/FileGenerators/ExtraFilesGenerator.cs
@@ -3,163 +3,157 @@
using FluentBuilderGenerator.Extensions;
using FluentBuilderGenerator.Models;
using FluentBuilderGenerator.Types;
-using FluentBuilderGenerator.Wrappers;
namespace FluentBuilderGenerator.FileGenerators;
-internal class ExtraFilesGenerator(IGeneratorExecutionContextWrapper context) : IFileGenerator
+internal class ExtraFilesGenerator : IFileGenerator
{
private const string Name = "FluentBuilder.Extra.g.cs";
- private readonly bool _supportsNullable = context.SupportsNullable;
- private readonly bool _supportsGenericAttributes = context.SupportsGenericAttributes;
+ private readonly bool _supportsNullable;
+ private readonly bool _supportsGenericAttributes;
+
+ public ExtraFilesGenerator(bool supportsNullable, bool supportsGenericAttributes)
+ {
+ _supportsNullable = supportsNullable;
+ _supportsGenericAttributes = supportsGenericAttributes;
+ }
public FileData GenerateFile()
{
- var autoGenerateBuilderAttribute =
- $$"""
- [AttributeUsage(AttributeTargets.Class)]
- internal sealed class AutoGenerateBuilderAttribute : Attribute
- {
- public Type{{_supportsNullable.IIf("?")}} Type { get; }
- public bool HandleBaseClasses { get; }
- public FluentBuilderAccessibility Accessibility { get; }
- public FluentBuilderMethods Methods { get; }
-
- public AutoGenerateBuilderAttribute() : this(null, true, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(bool handleBaseClasses) : this(null, handleBaseClasses, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(FluentBuilderAccessibility accessibility) : this(null, true, accessibility, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(FluentBuilderMethods methods) : this(null, true, FluentBuilderAccessibility.Public, methods)
- {
- }
-
- public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderAccessibility accessibility) : this(null, handleBaseClasses, accessibility, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderMethods methods) : this(null, handleBaseClasses, FluentBuilderAccessibility.Public, methods)
- {
- }
-
- public AutoGenerateBuilderAttribute(Type{{_supportsNullable.IIf("?")}} type) : this(type, true, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(Type{{_supportsNullable.IIf("?")}} type, bool handleBaseClasses) : this(type, handleBaseClasses, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(Type{{_supportsNullable.IIf("?")}} type, FluentBuilderAccessibility accessibility) : this(type, true, accessibility, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(Type{{_supportsNullable.IIf("?")}} type, bool handleBaseClasses, FluentBuilderAccessibility accessibility) : this(type, handleBaseClasses, accessibility, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(Type{{_supportsNullable.IIf("?")}} type, bool handleBaseClasses, FluentBuilderMethods methods) : this(type, handleBaseClasses, FluentBuilderAccessibility.Public, methods)
- {
- }
-
- public AutoGenerateBuilderAttribute(Type{{_supportsNullable.IIf("?")}} type, bool handleBaseClasses, FluentBuilderAccessibility accessibility, FluentBuilderMethods methods)
- {
- Type = type;
- HandleBaseClasses = handleBaseClasses;
- Accessibility = accessibility;
- Methods = methods;
- }
- }
- """;
-
- const string autoGenerateBuilderAttributeGeneric =
- """
- [AttributeUsage(AttributeTargets.Class)]
- internal sealed class AutoGenerateBuilderAttribute : Attribute where T : class
- {
- public Type Type { get; }
- public bool HandleBaseClasses { get; }
- public FluentBuilderAccessibility Accessibility { get; }
- public FluentBuilderMethods Methods { get; }
-
- public AutoGenerateBuilderAttribute() : this(true, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(bool handleBaseClasses) : this(handleBaseClasses, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(FluentBuilderAccessibility accessibility) : this(true, accessibility, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderAccessibility accessibility) : this(handleBaseClasses, accessibility, FluentBuilderMethods.WithOnly)
- {
- }
-
- public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderMethods methods) : this(handleBaseClasses, FluentBuilderAccessibility.Public, methods)
- {
- }
-
- public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderAccessibility accessibility, FluentBuilderMethods methods)
- {
- Type = typeof(T);
- HandleBaseClasses = handleBaseClasses;
- Accessibility = accessibility;
- Methods = methods;
- }
- }
- """;
-
- var text =
- $$"""
- {{Header.Text}}
-
- {{_supportsNullable.IIf("#nullable enable")}}
- using System;
-
- namespace FluentBuilder
- {
- {{autoGenerateBuilderAttribute}}
-
- {{_supportsGenericAttributes.IIf(autoGenerateBuilderAttributeGeneric)}}
-
- [AttributeUsage(AttributeTargets.Property)]
- internal sealed class FluentBuilderIgnoreAttribute : Attribute
- {
- }
-
- [Flags]
- internal enum FluentBuilderAccessibility
- {
- Public = 0,
- PublicAndPrivate = 1
- }
-
- [Flags]
- internal enum FluentBuilderMethods
- {
- WithOnly = 0,
- WithAndWithout = 1
- }
- }
- {{_supportsNullable.IIf("#nullable restore")}}
- """;
+ var autoGenerateBuilderAttribute = $@"[AttributeUsage(AttributeTargets.Class)]
+ internal sealed class AutoGenerateBuilderAttribute : Attribute
+ {{
+ public Type{_supportsNullable.IIf("?")} Type {{ get; }}
+ public bool HandleBaseClasses {{ get; }}
+ public FluentBuilderAccessibility Accessibility {{ get; }}
+ public FluentBuilderMethods Methods {{ get; }}
+
+ public AutoGenerateBuilderAttribute() : this(null, true, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(bool handleBaseClasses) : this(null, handleBaseClasses, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(FluentBuilderAccessibility accessibility) : this(null, true, accessibility, FluentBuilderMethods.WithOnly)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(FluentBuilderMethods methods) : this(null, true, FluentBuilderAccessibility.Public, methods)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderAccessibility accessibility) : this(null, handleBaseClasses, accessibility, FluentBuilderMethods.WithOnly)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderMethods methods) : this(null, handleBaseClasses, FluentBuilderAccessibility.Public, methods)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(Type{_supportsNullable.IIf("?")} type) : this(type, true, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(Type{_supportsNullable.IIf("?")} type, bool handleBaseClasses) : this(type, handleBaseClasses, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(Type{_supportsNullable.IIf("?")} type, FluentBuilderAccessibility accessibility) : this(type, true, accessibility, FluentBuilderMethods.WithOnly)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(Type{_supportsNullable.IIf("?")} type, bool handleBaseClasses, FluentBuilderAccessibility accessibility) : this(type, handleBaseClasses, accessibility, FluentBuilderMethods.WithOnly)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(Type{_supportsNullable.IIf("?")} type, bool handleBaseClasses, FluentBuilderMethods methods) : this(type, handleBaseClasses, FluentBuilderAccessibility.Public, methods)
+ {{
+ }}
+
+ public AutoGenerateBuilderAttribute(Type{_supportsNullable.IIf("?")} type, bool handleBaseClasses, FluentBuilderAccessibility accessibility, FluentBuilderMethods methods)
+ {{
+ Type = type;
+ HandleBaseClasses = handleBaseClasses;
+ Accessibility = accessibility;
+ Methods = methods;
+ }}
+ }}";
+
+ var autoGenerateBuilderAttributeGeneric = @"[AttributeUsage(AttributeTargets.Class)]
+ internal sealed class AutoGenerateBuilderAttribute : Attribute where T : class
+ {
+ public Type Type { get; }
+ public bool HandleBaseClasses { get; }
+ public FluentBuilderAccessibility Accessibility { get; }
+ public FluentBuilderMethods Methods { get; }
+
+ public AutoGenerateBuilderAttribute() : this(true, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
+ {
+ }
+
+ public AutoGenerateBuilderAttribute(bool handleBaseClasses) : this(handleBaseClasses, FluentBuilderAccessibility.Public, FluentBuilderMethods.WithOnly)
+ {
+ }
+
+ public AutoGenerateBuilderAttribute(FluentBuilderAccessibility accessibility) : this(true, accessibility, FluentBuilderMethods.WithOnly)
+ {
+ }
+
+ public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderAccessibility accessibility) : this(handleBaseClasses, accessibility, FluentBuilderMethods.WithOnly)
+ {
+ }
+
+ public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderMethods methods) : this(handleBaseClasses, FluentBuilderAccessibility.Public, methods)
+ {
+ }
+
+ public AutoGenerateBuilderAttribute(bool handleBaseClasses, FluentBuilderAccessibility accessibility, FluentBuilderMethods methods)
+ {
+ Type = typeof(T);
+ HandleBaseClasses = handleBaseClasses;
+ Accessibility = accessibility;
+ Methods = methods;
+ }
+ }";
return new FileData
(
FileDataType.Attribute,
Name,
- text
+ $@"{Header.Text}
+
+{_supportsNullable.IIf("#nullable enable")}
+using System;
+
+namespace FluentBuilder
+{{
+ {autoGenerateBuilderAttribute}
+
+ {_supportsGenericAttributes.IIf(autoGenerateBuilderAttributeGeneric)}
+
+ [AttributeUsage(AttributeTargets.Property)]
+ internal sealed class FluentBuilderIgnoreAttribute : Attribute
+ {{
+ }}
+
+ [Flags]
+ internal enum FluentBuilderAccessibility
+ {{
+ Public = 0,
+ PublicAndPrivate = 1
+ }}
+
+ [Flags]
+ internal enum FluentBuilderMethods
+ {{
+ WithOnly = 0,
+ WithAndWithout = 1
+ }}
+}}
+{_supportsNullable.IIf("#nullable disable")}"
);
}
}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.IDictionary.cs b/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.IDictionary.cs
index 30cf837..ecc57b6 100644
--- a/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.IDictionary.cs
+++ b/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.IDictionary.cs
@@ -30,9 +30,9 @@ private StringBuilder GenerateWithIDictionaryBuilderActionMethod(
var cast = property.Type.TypeKind == TypeKind.Interface ? "" : $"({property.Type}) ";
return new StringBuilder()
- .AppendLine($" public {className} With{property.Name}(Action<{_context.AssemblyName}.FluentBuilder.{dictionaryBuilderName}> action, bool useObjectInitializer = true) => With{property.Name}(() =>")
+ .AppendLine($" public {className} With{property.Name}(Action<{_compilationHelper.AssemblyName}.FluentBuilder.{dictionaryBuilderName}> action, bool useObjectInitializer = true) => With{property.Name}(() =>")
.AppendLine(" {")
- .AppendLine($" var builder = new {_context.AssemblyName}.FluentBuilder.{dictionaryBuilderName}();")
+ .AppendLine($" var builder = new {_compilationHelper.AssemblyName}.FluentBuilder.{dictionaryBuilderName}();")
.AppendLine(" action(builder);")
.AppendLine($" return {cast}builder.Build(useObjectInitializer);")
.AppendLine(" });");
diff --git a/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.IEnumerable.cs b/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.IEnumerable.cs
index b28566f..6884382 100644
--- a/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.IEnumerable.cs
+++ b/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.IEnumerable.cs
@@ -20,11 +20,11 @@ private string CreateIEnumerableBuilderCode(ClassSymbol classSymbol)
//
//------------------------------------------------------------------------------
-{(_context.SupportsNullable ? "#nullable enable" : string.Empty)}
+{(_supportsNullable ? "#nullable enable" : string.Empty)}
using System;
using System.Collections;
using System.Collections.Generic;
-using {_context.AssemblyName}.FluentBuilder;
+using {_compilationHelper.AssemblyName}.FluentBuilder;
using {classSymbol.NamedTypeSymbol.ContainingNamespace};
namespace {classSymbol.BuilderNamespace}
@@ -37,7 +37,7 @@ public partial class {classSymbol.BuilderClassName} : Builder<{t}>
{GenerateBuildMethodForIEnumerableBuilder(classSymbol)}
}}
}}
-{(_context.SupportsNullable ? "#nullable disable" : string.Empty)}";
+{(_supportsNullable ? "#nullable disable" : string.Empty)}";
}
private static StringBuilder GenerateAddMethodsForIEnumerableBuilder(ClassSymbol classSymbol)
diff --git a/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.cs b/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.cs
index c605bb4..57258d1 100644
--- a/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.cs
+++ b/src/FluentBuilderGenerator/FileGenerators/FluentBuilderClassesGenerator.cs
@@ -1,51 +1,51 @@
// This source code is based on https://justsimplycode.com/2020/12/06/auto-generate-builders-using-source-generator-in-net-5
-using System.Text;
using FluentBuilderGenerator.Extensions;
using FluentBuilderGenerator.Helpers;
using FluentBuilderGenerator.Interfaces;
using FluentBuilderGenerator.Models;
-using FluentBuilderGenerator.SyntaxReceiver;
using FluentBuilderGenerator.Types;
using FluentBuilderGenerator.Wrappers;
using Microsoft.CodeAnalysis;
+using System.Text;
namespace FluentBuilderGenerator.FileGenerators;
internal partial class FluentBuilderClassesGenerator : IFilesGenerator
{
private static readonly string[] FluentBuilderIgnoreAttributeClassNames =
- {
+ [
"FluentBuilder.FluentBuilderIgnoreAttribute",
"FluentBuilderIgnoreAttribute",
"FluentBuilder.FluentBuilderIgnore",
"FluentBuilderIgnore"
- };
+ ];
private static readonly string[] SystemUsings =
- {
+ [
"System",
"System.Collections",
"System.Collections.Generic",
"System.Reflection"
- };
+ ];
private static readonly FileDataType[] ExtraBuilders =
- {
+ [
FileDataType.ArrayBuilder,
FileDataType.ICollectionBuilder,
FileDataType.IEnumerableBuilder,
FileDataType.IListBuilder,
FileDataType.IReadOnlyCollectionBuilder,
FileDataType.IReadOnlyListBuilder
- };
-
- private readonly IGeneratorExecutionContextWrapper _context;
- private readonly IAutoGenerateBuilderSyntaxReceiver _receiver;
+ ];
+ private readonly IList _items;
+ private readonly CompilationHelper _compilationHelper;
+ private readonly bool _supportsNullable;
- public FluentBuilderClassesGenerator(IGeneratorExecutionContextWrapper context, IAutoGenerateBuilderSyntaxReceiver receiver)
+ public FluentBuilderClassesGenerator(IList items, CompilationHelper compilationHelper, bool supportsNullable)
{
- _context = context;
- _receiver = receiver;
+ _items = items;
+ _compilationHelper = compilationHelper;
+ _supportsNullable = supportsNullable;
}
public IReadOnlyList GenerateFiles()
@@ -90,38 +90,42 @@ private string CreateClassBuilderCode(FluentData fluentData, ClassSymbol classSy
var propertiesCode = GenerateWithPropertyCode(fluentData, classSymbol, allClassSymbols);
var usings = SystemUsings.ToList();
- usings.Add($"{_context.AssemblyName}.FluentBuilder");
+ usings.Add($"{_compilationHelper.AssemblyName}.FluentBuilder");
usings.Add($"{classSymbol.NamedTypeSymbol.ContainingNamespace}");
usings.AddRange(propertiesCode.ExtraUsings);
var usingsAsStrings = string.Join("\r\n", usings.Distinct().Select(u => $"using {u};"));
- return
- $$"""
- {{Header.Text}}
-
- {{(_context.SupportsNullable ? "#nullable enable" : string.Empty)}}
- {{usingsAsStrings}}
-
- namespace {{classSymbol.BuilderNamespace}}
- {
- public static partial class {{classSymbol.BuilderClassName.ToSafeClassName()}}Extensions
- {
- {{fluentData.ClassModifier}} static {{classSymbol.BuilderClassName}} AsBuilder{{classSymbol.NamedTypeSymbol.GetTypeArguments()}}(this {{classSymbol.NamedTypeSymbol}} instance){{classSymbol.NamedTypeSymbol.GetWhereStatement()}}
- {
- return new {{classSymbol.BuilderClassName}}().UsingInstance(instance);
- }
- }
-
- {{fluentData.ClassModifier}} partial class {{classSymbol.BuilderClassName}} : Builder<{{classSymbol.NamedTypeSymbol}}>{{classSymbol.NamedTypeSymbol.GetWhereStatement()}}
- {
- {{propertiesCode.StringBuilder}}
- {{constructorCode.StringBuilder}}
- {{GenerateSeveralMethods(fluentData, classSymbol)}}
- }
- }
- {{(_context.SupportsNullable ? "#nullable disable" : string.Empty)}}
- """;
+ return $@"//------------------------------------------------------------------------------
+//
+// This code was generated by https://github.com/StefH/FluentBuilder version {System.Reflection.Assembly.GetExecutingAssembly().GetName().Version}
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+{(_supportsNullable ? "#nullable enable" : string.Empty)}
+{usingsAsStrings}
+
+namespace {classSymbol.BuilderNamespace}
+{{
+ public static partial class {classSymbol.BuilderClassName.ToSafeClassName()}Extensions
+ {{
+ {fluentData.ClassModifier} static {classSymbol.BuilderClassName} AsBuilder{classSymbol.NamedTypeSymbol.GetTypeArguments()}(this {classSymbol.NamedTypeSymbol} instance){classSymbol.NamedTypeSymbol.GetWhereStatement()}
+ {{
+ return new {classSymbol.BuilderClassName}().UsingInstance(instance);
+ }}
+ }}
+
+ {fluentData.ClassModifier} partial class {classSymbol.BuilderClassName} : Builder<{classSymbol.NamedTypeSymbol}>{classSymbol.NamedTypeSymbol.GetWhereStatement()}
+ {{
+{propertiesCode.StringBuilder}
+{constructorCode.StringBuilder}
+{GenerateSeveralMethods(fluentData, classSymbol)}
+ }}
+}}
+{(_supportsNullable ? "#nullable disable" : string.Empty)}";
}
private static (StringBuilder StringBuilder, IReadOnlyList ExtraUsings) GenerateUsingConstructorCode(
@@ -363,7 +367,7 @@ private StringBuilder GenerateWithIEnumerableBuilderActionMethod(
else
{
// Normal
- fullBuilderName = $"{_context.AssemblyName}.FluentBuilder.{kind}Builder{(typeSymbol == null ? string.Empty : "<" + typeSymbol.GenerateFullTypeName() + ">")}";
+ fullBuilderName = $"{_compilationHelper.AssemblyName}.FluentBuilder.{kind}Builder{(typeSymbol == null ? string.Empty : "<" + typeSymbol.GenerateFullTypeName() + ">")}";
}
// If the property.Type is an interface or array, no cast is needed. Else cast the interface to the real type.
@@ -554,9 +558,9 @@ private static void BuildPrivateSetMethod(StringBuilder output, string className
private IReadOnlyList<(ClassSymbol ClassSymbol, FluentData FluentData)> GetClassSymbols()
{
var classSymbols = new List<(ClassSymbol ClassSymbol, FluentData FluentData)>();
- foreach (var fluentDataItem in _receiver.CandidateFluentDataItems)
+ foreach (var fluentDataItem in _items)
{
- if (_context.TryGetNamedTypeSymbolByFullMetadataName(fluentDataItem, out var classSymbol))
+ if (_compilationHelper.TryGetNamedTypeSymbolByFullMetadataName(fluentDataItem, out var classSymbol))
{
classSymbols.Add((classSymbol, fluentDataItem));
}
diff --git a/src/FluentBuilderGenerator/FluentBuilderGenerator.csproj b/src/FluentBuilderGenerator/FluentBuilderGenerator.csproj
index baa87b5..36abfa4 100644
--- a/src/FluentBuilderGenerator/FluentBuilderGenerator.csproj
+++ b/src/FluentBuilderGenerator/FluentBuilderGenerator.csproj
@@ -1,7 +1,7 @@
-
+
- 0.11.0
+ 0.12.0
netstandard2.0
latest
true
@@ -28,6 +28,7 @@
true
enable
Debug;Release;DebugAttach
+ true
@@ -52,11 +53,11 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/src/FluentBuilderGenerator/FluentBuilderSourceGenerator.cs b/src/FluentBuilderGenerator/FluentBuilderSourceGenerator.cs
index 0153112..cc2173b 100644
--- a/src/FluentBuilderGenerator/FluentBuilderSourceGenerator.cs
+++ b/src/FluentBuilderGenerator/FluentBuilderSourceGenerator.cs
@@ -1,19 +1,22 @@
// This source code is based on https://justsimplycode.com/2020/12/06/auto-generate-builders-using-source-generator-in-net-5
using System.Text;
+using FluentBuilderGenerator.Extensions;
using FluentBuilderGenerator.FileGenerators;
+using FluentBuilderGenerator.Models;
using FluentBuilderGenerator.SyntaxReceiver;
using FluentBuilderGenerator.Types;
using FluentBuilderGenerator.Wrappers;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
namespace FluentBuilderGenerator;
-[Generator]
-internal class FluentBuilderSourceGenerator : ISourceGenerator
+[Generator(LanguageNames.CSharp)]
+internal class FluentBuilderSourceGenerator : IIncrementalGenerator
{
- public void Initialize(GeneratorInitializationContext context)
+ public void Initialize(IncrementalGeneratorInitializationContext context)
{
#if DEBUGATTACH
if (!System.Diagnostics.Debugger.IsAttached)
@@ -21,68 +24,114 @@ public void Initialize(GeneratorInitializationContext context)
System.Diagnostics.Debugger.Launch();
}
#endif
- context.RegisterForSyntaxNotifications(() => new AutoGenerateBuilderSyntaxReceiver());
- }
- public void Execute(GeneratorExecutionContext context)
- {
- var contextWrapper = new GeneratorExecutionContextWrapper(context);
+ var languageDataProvider = context.ParseOptionsProvider.Select(static (options, _) =>
+ {
+ if (options is not CSharpParseOptions csParseOptions)
+ {
+ throw new NotSupportedException($"Only {LanguageNames.CSharp} is supported.");
+ }
+
+ return new LanguageData
+ {
+ SupportsNullable = csParseOptions.LanguageVersion >= LanguageVersion.CSharp8,
+ SupportsGenericAttributes = csParseOptions.LanguageVersion >= LanguageVersion.CSharp11
+ };
+ });
+
+ var compilationHelperProvider = context.CompilationProvider.Select(static (compilation, _) => new CompilationHelper(compilation));
- try
+ var combinedProvider = languageDataProvider.Combine(compilationHelperProvider);
+
+ context.RegisterSourceOutput(combinedProvider, static (SourceProductionContext spc, (LanguageData LanguageData, CompilationHelper CompilationHelper) x) =>
{
- InjectGeneratedClasses(contextWrapper);
+ var assemblyName = x.CompilationHelper.AssemblyName;
+ var supportsNullable = x.LanguageData.SupportsNullable;
+
+ var generators = new IFileGenerator[]
+ {
+ new BaseBuilderGenerator(assemblyName, x.LanguageData.SupportsNullable),
+
+ new ExtraFilesGenerator(supportsNullable, x.LanguageData.SupportsGenericAttributes),
- if (context.SyntaxContextReceiver is not AutoGenerateBuilderSyntaxReceiver receiver)
+ new IDictionaryBuilderGenerator(assemblyName, supportsNullable),
+
+ new IEnumerableBuilderGenerator(assemblyName, FileDataType.ArrayBuilder, supportsNullable),
+ new IEnumerableBuilderGenerator(assemblyName, FileDataType.ICollectionBuilder, supportsNullable),
+ new IEnumerableBuilderGenerator(assemblyName, FileDataType.IEnumerableBuilder, supportsNullable),
+ new IEnumerableBuilderGenerator(assemblyName, FileDataType.IListBuilder, supportsNullable),
+ new IEnumerableBuilderGenerator(assemblyName, FileDataType.IReadOnlyCollectionBuilder, supportsNullable),
+ new IEnumerableBuilderGenerator(assemblyName, FileDataType.IReadOnlyListBuilder, supportsNullable),
+ };
+
+ foreach (var generator in generators)
{
- return;
+ var fileData = generator.GenerateFile();
+ spc.AddSource(fileData.FileName, SourceText.From(fileData.Text, Encoding.UTF8));
}
+ });
- InjectFluentBuilderClasses(contextWrapper, receiver);
- }
- catch (Exception exception)
+ var diagnostics = new List();
+
+ var fluentBuilderClassesProvider = context.SyntaxProvider
+ .CreateSyntaxProvider(
+ (syntaxNode, ct) => ShouldHandle(syntaxNode, ct, diagnostics),
+ (generatorSyntaxContext, ct) => Transform(generatorSyntaxContext, ct, diagnostics)
+ )
+ .Collect();
+
+ var combined2 = fluentBuilderClassesProvider.Combine(combinedProvider).Select((x, _) => new
{
- GenerateError(contextWrapper, exception);
- }
- }
-
- private static void GenerateError(IGeneratorExecutionContextWrapper context, Exception exception)
- {
- var message = $"/*\r\n{nameof(FluentBuilderSourceGenerator)}\r\n\r\n[Exception]\r\n{exception}\r\n\r\n[StackTrace]\r\n{exception.StackTrace}*/";
- context.AddSource("Error.g.cs", SourceText.From(message, Encoding.UTF8));
- }
+ Items = x.Left,
+ LanguageData = x.Right.Left,
+ CompilationHelper = x.Right.Right
+ });
- private static void InjectGeneratedClasses(IGeneratorExecutionContextWrapper context)
- {
- var generators = new IFileGenerator[]
+ context.RegisterSourceOutput(combined2, (sourceProductionContext, data) =>
{
- new BaseBuilderGenerator(context.AssemblyName, context.SupportsNullable),
+ foreach (var diagnostic in diagnostics)
+ {
+ sourceProductionContext.ReportDiagnostic(diagnostic);
+ }
- new ExtraFilesGenerator(context),
+ var generator = new FluentBuilderClassesGenerator(data.Items, data.CompilationHelper, data.LanguageData.SupportsNullable);
- new IDictionaryBuilderGenerator(context.AssemblyName, context.SupportsNullable),
+ try
+ {
+ foreach (var fileData in generator.GenerateFiles())
+ {
+ sourceProductionContext.AddSource(fileData.FileName, SourceText.From(fileData.Text, Encoding.UTF8));
+ }
+ }
+ catch (Exception exception)
+ {
+ var message = $"/*\r\n{nameof(FluentBuilderSourceGenerator)}\r\n\r\n[Exception]\r\n{exception}\r\n\r\n[StackTrace]\r\n{exception.StackTrace}*/";
+ sourceProductionContext.AddSource("Error.g.cs", SourceText.From(message, Encoding.UTF8));
- new IEnumerableBuilderGenerator(context.AssemblyName, FileDataType.ArrayBuilder, context.SupportsNullable),
- new IEnumerableBuilderGenerator(context.AssemblyName, FileDataType.ICollectionBuilder, context.SupportsNullable),
- new IEnumerableBuilderGenerator(context.AssemblyName, FileDataType.IEnumerableBuilder, context.SupportsNullable),
- new IEnumerableBuilderGenerator(context.AssemblyName, FileDataType.IListBuilder, context.SupportsNullable),
- new IEnumerableBuilderGenerator(context.AssemblyName, FileDataType.IReadOnlyCollectionBuilder, context.SupportsNullable),
- new IEnumerableBuilderGenerator(context.AssemblyName, FileDataType.IReadOnlyListBuilder, context.SupportsNullable),
- };
+ sourceProductionContext.ReportDiagnostic(exception.ToDiagnostic());
+ }
+ });
+ }
- foreach (var generator in generators)
+ private static bool ShouldHandle(SyntaxNode syntaxNode, CancellationToken _, List diagnostics)
+ {
+ var result = AutoGenerateBuilderSyntaxReceiver.CheckSyntaxNode(syntaxNode, out var diagnostic);
+ if (diagnostic != null)
{
- var data = generator.GenerateFile();
- context.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8));
+ diagnostics.Add(diagnostic);
}
+
+ return result;
}
- private static void InjectFluentBuilderClasses(IGeneratorExecutionContextWrapper context, IAutoGenerateBuilderSyntaxReceiver receiver)
+ private static FluentData Transform(GeneratorSyntaxContext gsc, CancellationToken _, List diagnostics)
{
- var generator = new FluentBuilderClassesGenerator(context, receiver);
-
- foreach (var data in generator.GenerateFiles())
+ var result = AutoGenerateBuilderSyntaxReceiver.HandleSyntaxNode(gsc.Node, gsc.SemanticModel, out var diagnostic);
+ if (diagnostic != null)
{
- context.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8));
+ diagnostics.Add(diagnostic);
}
+
+ return result;
}
}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Helpers/DefaultValueHelper.cs b/src/FluentBuilderGenerator/Helpers/DefaultValueHelper.cs
index 8f73587..94b5ffb 100644
--- a/src/FluentBuilderGenerator/Helpers/DefaultValueHelper.cs
+++ b/src/FluentBuilderGenerator/Helpers/DefaultValueHelper.cs
@@ -8,7 +8,7 @@ namespace FluentBuilderGenerator.Helpers;
internal static class DefaultValueHelper
{
- private static readonly SyntaxKind[] ExcludedSyntaxKinds = { SyntaxKind.SuppressNullableWarningExpression };
+ private static readonly SyntaxKind[] ExcludedSyntaxKinds = [SyntaxKind.SuppressNullableWarningExpression];
///
/// Check if the has a value set, in that case try to get that value and return it, and return the usings.
@@ -26,9 +26,9 @@ internal static (string DefaultValue, IReadOnlyList? ExtraUsings) GetDef
if (propertyDeclarationSyntax?.Initializer != null && !ExcludedSyntaxKinds.Contains(propertyDeclarationSyntax.Initializer.Value.Kind()))
{
- var thisUsings = rootSyntaxNode.FindDescendantNodes().Select(ud => ud.Name.ToString());
+ var thisUsings = rootSyntaxNode.FindDescendantNodes().Select(ud => ud.Name?.ToString()).OfType();
- var ancestorUsings = rootSyntaxNode.GetAncestorsUsings().Select(ud => ud.Name.ToString());
+ var ancestorUsings = rootSyntaxNode.GetAncestorsUsings().Select(ud => ud.Name?.ToString()).OfType();
var extraUsings = thisUsings.Union(ancestorUsings).Distinct().ToList();
@@ -108,7 +108,7 @@ private static string GetNewConstructor(ITypeSymbol typeSymbol)
var body = namedTypeSymbol.DelegateInvokeMethod.ReturnsVoid
? "{ }" // It's an Action
- : GetDefault(namedTypeSymbol.DelegateInvokeMethod.ReturnType); // It's an Func
+ : GetDefault(namedTypeSymbol.DelegateInvokeMethod.ReturnType); // It's a Func
return $"new {typeSymbol}(({string.Join(", ", delegateParameters)}) => {body})";
}
diff --git a/src/FluentBuilderGenerator/Interfaces/IPropertyOrParameterSymbol.cs b/src/FluentBuilderGenerator/Interfaces/IPropertyOrParameterSymbol.cs
index 62a7dea..19f2902 100644
--- a/src/FluentBuilderGenerator/Interfaces/IPropertyOrParameterSymbol.cs
+++ b/src/FluentBuilderGenerator/Interfaces/IPropertyOrParameterSymbol.cs
@@ -14,11 +14,4 @@ internal interface IPropertyOrParameterSymbol
ITypeSymbol Type { get; }
bool ExcludeFromIsSetLogic { get; }
-}
-
-internal record PropertyOrParameterSymbol(ISymbol Symbol, ITypeSymbol Type, bool ExcludeFromIsSetLogic) : IPropertyOrParameterSymbol
-{
- public PropertyType PropertyType => Symbol is IPropertySymbol ? PropertyType.Property : PropertyType.Parameter;
-
- public string Name => Symbol.Name;
}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Models/LanguageData.cs b/src/FluentBuilderGenerator/Models/LanguageData.cs
new file mode 100644
index 0000000..9733bf1
--- /dev/null
+++ b/src/FluentBuilderGenerator/Models/LanguageData.cs
@@ -0,0 +1,7 @@
+namespace FluentBuilderGenerator.Models;
+
+internal struct LanguageData
+{
+ public bool SupportsNullable { get; set; }
+ public bool SupportsGenericAttributes { get; set; }
+}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Models/PropertyOrParameterSymbol.cs b/src/FluentBuilderGenerator/Models/PropertyOrParameterSymbol.cs
new file mode 100644
index 0000000..17f1f93
--- /dev/null
+++ b/src/FluentBuilderGenerator/Models/PropertyOrParameterSymbol.cs
@@ -0,0 +1,12 @@
+using FluentBuilderGenerator.Interfaces;
+using FluentBuilderGenerator.Types;
+using Microsoft.CodeAnalysis;
+
+namespace FluentBuilderGenerator.Models;
+
+internal record PropertyOrParameterSymbol(ISymbol Symbol, ITypeSymbol Type, bool ExcludeFromIsSetLogic) : IPropertyOrParameterSymbol
+{
+ public PropertyType PropertyType => Symbol is IPropertySymbol ? PropertyType.Property : PropertyType.Parameter;
+
+ public string Name => Symbol.Name;
+}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/SyntaxReceiver/AttributeArgumentListParser.cs b/src/FluentBuilderGenerator/SyntaxReceiver/AttributeArgumentListParser.cs
index c3c6ca7..17b5e3a 100644
--- a/src/FluentBuilderGenerator/SyntaxReceiver/AttributeArgumentListParser.cs
+++ b/src/FluentBuilderGenerator/SyntaxReceiver/AttributeArgumentListParser.cs
@@ -76,14 +76,13 @@ public static FluentBuilderAttributeArguments Parse(AttributeSyntax? attributeSy
private static bool TryParseAsBoolean(ExpressionSyntax expressionSyntax, out bool value)
{
- value = default;
-
if (expressionSyntax is LiteralExpressionSyntax literalExpressionSyntax)
{
value = literalExpressionSyntax.Kind() == SyntaxKind.TrueLiteralExpression;
return true;
}
+ value = false;
return false;
}
diff --git a/src/FluentBuilderGenerator/SyntaxReceiver/AutoGenerateBuilderSyntaxReceiver.cs b/src/FluentBuilderGenerator/SyntaxReceiver/AutoGenerateBuilderSyntaxReceiver.cs
index 4ec415c..2f686d2 100644
--- a/src/FluentBuilderGenerator/SyntaxReceiver/AutoGenerateBuilderSyntaxReceiver.cs
+++ b/src/FluentBuilderGenerator/SyntaxReceiver/AutoGenerateBuilderSyntaxReceiver.cs
@@ -1,6 +1,7 @@
// This source code is based on https://justsimplycode.com/2020/12/06/auto-generate-builders-using-source-generator-in-net-5
using System.Diagnostics.CodeAnalysis;
+using FluentBuilderGenerator.Constants;
using FluentBuilderGenerator.Extensions;
using FluentBuilderGenerator.Models;
using FluentBuilderGenerator.Types;
@@ -9,64 +10,85 @@
namespace FluentBuilderGenerator.SyntaxReceiver;
-internal class AutoGenerateBuilderSyntaxReceiver : IAutoGenerateBuilderSyntaxReceiver
+internal static class AutoGenerateBuilderSyntaxReceiver
{
private const string ModifierPartial = "partial";
private const string ModifierPublic = "public";
private const string ModifierInternal = "internal";
- public IList CandidateFluentDataItems { get; } = new List();
-
- public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
+ public static bool CheckSyntaxNode(SyntaxNode syntaxNode, out Diagnostic? diagnostic)
{
- var syntaxNode = context.Node;
- var semanticModel = context.SemanticModel;
-
- switch (syntaxNode)
+ TypeDeclarationSyntax typeDeclarationSyntax;
+ if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax)
{
- case ClassDeclarationSyntax classDeclarationSyntax when TryGet(classDeclarationSyntax, semanticModel, out var classData):
- CandidateFluentDataItems.Add(classData);
- break;
-
- case RecordDeclarationSyntax recordDeclarationSyntax when TryGet(recordDeclarationSyntax, semanticModel, out var recordData):
- CandidateFluentDataItems.Add(recordData);
- break;
+ typeDeclarationSyntax = classDeclarationSyntax;
+ }
+ else if (syntaxNode is RecordDeclarationSyntax recordDeclarationSyntax)
+ {
+ typeDeclarationSyntax = recordDeclarationSyntax;
+ }
+ else
+ {
+ diagnostic = null;
+ return false;
}
- }
-
- private static bool TryGet(TypeDeclarationSyntax classDeclarationSyntax, SemanticModel semanticModel, out FluentData data)
- {
- data = default;
- var attributeList = classDeclarationSyntax.AttributeLists
+ var attributeList = typeDeclarationSyntax.AttributeLists
.FirstOrDefault(x => x.Attributes.Any(AttributeArgumentListParser.IsMatch));
if (attributeList is null)
{
- Console.WriteLine("ClassDeclarationSyntax should have the correct attribute.");
+ diagnostic = null;
return false;
}
- if (!TryGetClassModifier(classDeclarationSyntax, out var classModifier))
+ if (!TryGetModifier(typeDeclarationSyntax, out _))
+ {
+ diagnostic = Diagnostic.Create(DiagnosticDescriptors.ClassOrRecordModifierShouldBeInternalOrPublic, typeDeclarationSyntax.GetLocation());
+ return false;
+ }
+
+ diagnostic = null;
+ return true;
+ }
+
+ public static FluentData HandleSyntaxNode(SyntaxNode syntaxNode, SemanticModel semanticModel, out Diagnostic? diagnostic)
+ {
+ return syntaxNode switch
+ {
+ ClassDeclarationSyntax classDeclarationSyntax when TryGet(classDeclarationSyntax, semanticModel, out var data, out diagnostic) => data,
+ RecordDeclarationSyntax recordDeclarationSyntax when TryGet(recordDeclarationSyntax, semanticModel, out var data, out diagnostic) => data,
+ _ => throw new InvalidOperationException("Only classes or records are supported."),
+ };
+ }
+
+ private static bool TryGet(TypeDeclarationSyntax typeDeclarationSyntax, SemanticModel semanticModel, out FluentData data, out Diagnostic? diagnostic)
+ {
+ data = default;
+
+ var attributeList = typeDeclarationSyntax.AttributeLists
+ .FirstOrDefault(x => x.Attributes.Any(AttributeArgumentListParser.IsMatch))!;
+
+ if (!TryGetModifier(typeDeclarationSyntax, out var modifier))
{
- Console.WriteLine("Class modifier should be 'public' or 'internal'.");
+ diagnostic = Diagnostic.Create(DiagnosticDescriptors.ClassOrRecordModifierShouldBeInternalOrPublic, typeDeclarationSyntax.GetLocation());
return false;
}
var usings = new List();
- var ns = classDeclarationSyntax.GetNamespace();
+ var ns = typeDeclarationSyntax.GetNamespace();
if (!string.IsNullOrEmpty(ns))
{
usings.Add(ns);
}
- if (classDeclarationSyntax.TryGetParentSyntax(out CompilationUnitSyntax? cc))
+ if (typeDeclarationSyntax.TryGetParentSyntax(out CompilationUnitSyntax? cc))
{
usings.AddRange(cc.Usings.Select(@using => @using.Name!.ToString()));
}
// https://github.com/StefH/FluentBuilder/issues/36
- usings.AddRange(classDeclarationSyntax.GetAncestorsUsings().Select(@using => @using.Name!.ToString()));
+ usings.AddRange(typeDeclarationSyntax.GetAncestorsUsings().Select(@using => @using.Name!.ToString()));
usings = usings.Distinct().ToList();
@@ -74,18 +96,18 @@ private static bool TryGet(TypeDeclarationSyntax classDeclarationSyntax, Semanti
if (fluentBuilderAttributeArguments.RawTypeName != null) // The class which needs to be processed by the CustomBuilder is provided as type
{
- if (!AreBuilderClassModifiersValid(classDeclarationSyntax))
+ if (!AreBuilderClassModifiersValid(typeDeclarationSyntax))
{
- Console.WriteLine("Custom builder class should be 'partial' and 'public' or 'internal'.");
+ diagnostic = Diagnostic.Create(DiagnosticDescriptors.CustomBuilderClassModifierShouldBePartialAndInternalOrPublic, typeDeclarationSyntax.GetLocation());
return false;
}
data = new FluentData
{
Namespace = ns,
- ClassModifier = classModifier,
- ShortBuilderClassName = $"{classDeclarationSyntax.Identifier}",
- FullBuilderClassName = CreateFullBuilderClassName(ns, classDeclarationSyntax),
+ ClassModifier = modifier,
+ ShortBuilderClassName = $"{typeDeclarationSyntax.Identifier}",
+ FullBuilderClassName = CreateFullBuilderClassName(ns, typeDeclarationSyntax),
FullRawTypeName = fluentBuilderAttributeArguments.RawTypeName,
ShortTypeName = ConvertTypeName(fluentBuilderAttributeArguments.RawTypeName).Split('.').Last(),
MetadataName = ConvertTypeName(fluentBuilderAttributeArguments.RawTypeName),
@@ -96,17 +118,18 @@ private static bool TryGet(TypeDeclarationSyntax classDeclarationSyntax, Semanti
Methods = fluentBuilderAttributeArguments.Methods
};
+ diagnostic = null;
return true;
}
- var fullType = GetFullType(ns, classDeclarationSyntax, false); // FluentBuilderGeneratorTests.DTO.UserT
- var fullBuilderType = GetFullType(ns, classDeclarationSyntax, true);
- var metadataName = classDeclarationSyntax.GetMetadataName();
+ var fullType = GetFullType(ns, typeDeclarationSyntax, false); // FluentBuilderGeneratorTests.DTO.UserT
+ var fullBuilderType = GetFullType(ns, typeDeclarationSyntax, true);
+ var metadataName = typeDeclarationSyntax.GetMetadataName();
data = new FluentData
{
Namespace = ns,
- ClassModifier = classModifier,
+ ClassModifier = modifier,
ShortBuilderClassName = $"{fullBuilderType.Split('.').Last()}",
FullBuilderClassName = fullBuilderType,
FullRawTypeName = fullType,
@@ -119,6 +142,7 @@ private static bool TryGet(TypeDeclarationSyntax classDeclarationSyntax, Semanti
Methods = fluentBuilderAttributeArguments.Methods
};
+ diagnostic = null;
return true;
}
@@ -128,7 +152,7 @@ private static bool AreBuilderClassModifiersValid(MemberDeclarationSyntax classD
return modifiers.Contains(ModifierPartial) && (modifiers.Contains(ModifierPublic) || modifiers.Contains(ModifierInternal));
}
- private static bool TryGetClassModifier(MemberDeclarationSyntax classDeclarationSyntax, [NotNullWhen(true)] out string? modifier)
+ private static bool TryGetModifier(MemberDeclarationSyntax classDeclarationSyntax, [NotNullWhen(true)] out string? modifier)
{
var modifiers = classDeclarationSyntax.Modifiers.Select(m => m.ToString()).Distinct().ToArray();
if (modifiers.Contains(ModifierPublic))
@@ -143,7 +167,7 @@ private static bool TryGetClassModifier(MemberDeclarationSyntax classDeclaration
return true;
}
- modifier = default;
+ modifier = null;
return false;
}
diff --git a/src/FluentBuilderGenerator/SyntaxReceiver/IAutoGenerateBuilderSyntaxReceiver.cs b/src/FluentBuilderGenerator/SyntaxReceiver/IAutoGenerateBuilderSyntaxReceiver.cs
deleted file mode 100644
index 732493b..0000000
--- a/src/FluentBuilderGenerator/SyntaxReceiver/IAutoGenerateBuilderSyntaxReceiver.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using FluentBuilderGenerator.Models;
-using Microsoft.CodeAnalysis;
-
-namespace FluentBuilderGenerator.SyntaxReceiver;
-
-internal interface IAutoGenerateBuilderSyntaxReceiver : ISyntaxContextReceiver
-{
- public IList CandidateFluentDataItems { get; }
-}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Wrappers/GeneratorExecutionContextWrapper.cs b/src/FluentBuilderGenerator/Wrappers/CompilationHelper.cs
similarity index 52%
rename from src/FluentBuilderGenerator/Wrappers/GeneratorExecutionContextWrapper.cs
rename to src/FluentBuilderGenerator/Wrappers/CompilationHelper.cs
index b3a93ee..29f80b4 100644
--- a/src/FluentBuilderGenerator/Wrappers/GeneratorExecutionContextWrapper.cs
+++ b/src/FluentBuilderGenerator/Wrappers/CompilationHelper.cs
@@ -1,79 +1,52 @@
-using System.Diagnostics.CodeAnalysis;
-using FluentBuilderGenerator.Models;
-using FluentBuilderGenerator.Types;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Text;
-
-namespace FluentBuilderGenerator.Wrappers;
-
-internal class GeneratorExecutionContextWrapper : IGeneratorExecutionContextWrapper
-{
- private readonly GeneratorExecutionContext _context;
-
- public GeneratorExecutionContextWrapper(GeneratorExecutionContext context)
- {
- _context = context;
-
- if (context.ParseOptions is not CSharpParseOptions csharpParseOptions)
- {
- throw new NotSupportedException("Only C# is supported.");
- }
-
- // https://github.com/reactiveui/refit/blob/main/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
- SupportsNullable = csharpParseOptions.LanguageVersion >= LanguageVersion.CSharp8;
- SupportsGenericAttributes = csharpParseOptions.LanguageVersion >= LanguageVersion.CSharp11;
- NullableEnabled = context.Compilation.Options.NullableContextOptions == NullableContextOptions.Enable;
- }
-
- public string AssemblyName => _context.Compilation.AssemblyName ?? "FluentBuilder";
-
- public bool SupportsNullable { get; }
-
- public bool NullableEnabled { get; }
-
- public bool SupportsGenericAttributes { get; }
-
- public void AddSource(string hintName, SourceText sourceText) => _context.AddSource(hintName, sourceText);
-
- public bool TryGetNamedTypeSymbolByFullMetadataName(FluentData fluentDataItem, [NotNullWhen(true)] out ClassSymbol? classSymbol)
- {
- classSymbol = null;
-
- // The GetTypeByMetadataName method returns null if no type matches the full name or if 2 or more types (in different assemblies) match the full name.
- var symbol = _context.Compilation.GetTypeByMetadataName(fluentDataItem.MetadataName);
- if (symbol is not null)
- {
- classSymbol = new ClassSymbol
- {
- Type = FileDataType.Builder,
- FluentData = fluentDataItem,
- //BuilderNamespace = fluentDataItem.Namespace,
- //BuilderClassName = fluentDataItem.ShortBuilderClassName,
- //FullBuilderClassName = fluentDataItem.FullBuilderClassName,
- NamedTypeSymbol = symbol
- };
- return true;
- }
-
- foreach (var @using in fluentDataItem.Usings)
- {
- symbol = _context.Compilation.GetTypeByMetadataName($"{@using}.{fluentDataItem.MetadataName}");
- if (symbol is not null)
- {
- classSymbol = new ClassSymbol
- {
- Type = FileDataType.Builder,
- FluentData = fluentDataItem,
- //BuilderNamespace = fluentDataItem.Namespace,
- //BuilderClassName = fluentDataItem.ShortBuilderClassName,
- //FullBuilderClassName = fluentDataItem.FullBuilderClassName,
- NamedTypeSymbol = symbol
- };
- return true;
- }
- }
-
- return false;
- }
+using System.Diagnostics.CodeAnalysis;
+using FluentBuilderGenerator.Models;
+using FluentBuilderGenerator.Types;
+using Microsoft.CodeAnalysis;
+
+namespace FluentBuilderGenerator.Wrappers;
+
+internal class CompilationHelper(Compilation compilation)
+{
+ public string AssemblyName { get; } = compilation.AssemblyName ?? "FluentBuilder";
+
+ public bool TryGetNamedTypeSymbolByFullMetadataName(FluentData fluentDataItem, [NotNullWhen(true)] out ClassSymbol? classSymbol)
+ {
+ classSymbol = null;
+
+ // The GetTypeByMetadataName method returns null if no type matches the full name or if 2 or more types (in different assemblies) match the full name.
+ var symbol = compilation.GetTypeByMetadataName(fluentDataItem.MetadataName);
+ if (symbol is not null)
+ {
+ classSymbol = new ClassSymbol
+ {
+ Type = FileDataType.Builder,
+ FluentData = fluentDataItem,
+ //BuilderNamespace = fluentDataItem.Namespace,
+ //BuilderClassName = fluentDataItem.ShortBuilderClassName,
+ //FullBuilderClassName = fluentDataItem.FullBuilderClassName,
+ NamedTypeSymbol = symbol
+ };
+ return true;
+ }
+
+ foreach (var @using in fluentDataItem.Usings)
+ {
+ symbol = compilation.GetTypeByMetadataName($"{@using}.{fluentDataItem.MetadataName}");
+ if (symbol is not null)
+ {
+ classSymbol = new ClassSymbol
+ {
+ Type = FileDataType.Builder,
+ FluentData = fluentDataItem,
+ //BuilderNamespace = fluentDataItem.Namespace,
+ //BuilderClassName = fluentDataItem.ShortBuilderClassName,
+ //FullBuilderClassName = fluentDataItem.FullBuilderClassName,
+ NamedTypeSymbol = symbol
+ };
+ return true;
+ }
+ }
+
+ return false;
+ }
}
\ No newline at end of file
diff --git a/src/FluentBuilderGenerator/Wrappers/IGeneratorExecutionContextWrapper.cs b/src/FluentBuilderGenerator/Wrappers/IGeneratorExecutionContextWrapper.cs
deleted file mode 100644
index ddf82e7..0000000
--- a/src/FluentBuilderGenerator/Wrappers/IGeneratorExecutionContextWrapper.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using FluentBuilderGenerator.Models;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Text;
-
-namespace FluentBuilderGenerator.Wrappers;
-
-internal interface IGeneratorExecutionContextWrapper
-{
- ///
- public string AssemblyName { get; }
-
- public bool SupportsNullable { get; }
-
- public bool NullableEnabled { get; }
-
- public bool SupportsGenericAttributes { get; }
-
- ///
- public void AddSource(string hintName, SourceText sourceText);
-
- bool TryGetNamedTypeSymbolByFullMetadataName(FluentData fluentDataItem, [NotNullWhen(true)] out ClassSymbol? classSymbol);
-}
\ No newline at end of file
diff --git a/tests/FluentBuilderGeneratorTests/DTO/AbcTest.OtherNamespace.ClassOnOtherNamespaceBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/AbcTest.OtherNamespace.ClassOnOtherNamespaceBuilder.g.cs
index 9aec061..b771389 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/AbcTest.OtherNamespace.ClassOnOtherNamespaceBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/AbcTest.OtherNamespace.ClassOnOtherNamespaceBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/AbcTest.OtherNamespace.ClassOnOtherNamespace_IListBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/AbcTest.OtherNamespace.ClassOnOtherNamespace_IListBuilder.g.cs
index a555ce8..ef7aea3 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/AbcTest.OtherNamespace.ClassOnOtherNamespace_IListBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/AbcTest.OtherNamespace.ClassOnOtherNamespace_IListBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.AddressBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.AddressBuilder.g.cs
index 4fdc483..f4830fe 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.AddressBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.AddressBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_ArrayBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_ArrayBuilder.g.cs
index 0239cba..27a4646 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_ArrayBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_ArrayBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_ICollectionBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_ICollectionBuilder.g.cs
index 89e254e..6a3cd65 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_ICollectionBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_ICollectionBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IEnumerableBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IEnumerableBuilder.g.cs
index 98cb2c5..66b4b07 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IEnumerableBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IEnumerableBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IListBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IListBuilder.g.cs
index ad072c4..08f5f32 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IListBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IListBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IReadOnlyCollectionBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IReadOnlyCollectionBuilder.g.cs
index 786f164..0c07284 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IReadOnlyCollectionBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IReadOnlyCollectionBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IReadOnlyListBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IReadOnlyListBuilder.g.cs
index ac05e71..38d1df8 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IReadOnlyListBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/BuilderGeneratorTests.DTO.Address_IReadOnlyListBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/ClassWithPrivateBuilderClass.cs b/tests/FluentBuilderGeneratorTests/DTO/ClassWithPrivateBuilderClass.cs
new file mode 100644
index 0000000..e70afcc
--- /dev/null
+++ b/tests/FluentBuilderGeneratorTests/DTO/ClassWithPrivateBuilderClass.cs
@@ -0,0 +1,12 @@
+using FluentBuilder;
+
+namespace FluentBuilderGeneratorTests.DTO;
+
+public class ClassWithPrivateBuilderClass
+{
+ [AutoGenerateBuilder(FluentBuilderAccessibility.PublicAndPrivate)]
+ private class PrivateClass
+ {
+ public int Test { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.ArrayBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.ArrayBuilder.g.cs
index 0948134..d9d3afd 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.ArrayBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.ArrayBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.BaseBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.BaseBuilder.g.cs
index 6e3ee3c..dc5009b 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.BaseBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.BaseBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.Extra.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.Extra.g.cs
index 5c06069..4c9ee5e 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.Extra.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.Extra.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -129,4 +129,4 @@ internal enum FluentBuilderMethods
WithAndWithout = 1
}
}
-#nullable restore
\ No newline at end of file
+#nullable disable
\ No newline at end of file
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.ICollectionBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.ICollectionBuilder.g.cs
index 7c7e7d0..30fd5a9 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.ICollectionBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.ICollectionBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IDictionaryBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IDictionaryBuilder.g.cs
index b2ef15c..f70deaa 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IDictionaryBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IDictionaryBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IEnumerableBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IEnumerableBuilder.g.cs
index 46a1bce..b3adba9 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IEnumerableBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IEnumerableBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IListBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IListBuilder.g.cs
index ff8b9cc..fef14f7 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IListBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IListBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IReadOnlyCollectionBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IReadOnlyCollectionBuilder.g.cs
index 89dd673..b0097ea 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IReadOnlyCollectionBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IReadOnlyCollectionBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IReadOnlyListBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IReadOnlyListBuilder.g.cs
index 686fff7..bb1717b 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IReadOnlyListBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilder.IReadOnlyListBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.AddressBuilder_T_.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.AddressBuilder_T_.g.cs
index cad11dc..f239bc9 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.AddressBuilder_T_.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.AddressBuilder_T_.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.AddressTTBuilder_T1_T2_.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.AddressTTBuilder_T1_T2_.g.cs
index 1bf5b6b..1c447bc 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.AddressTTBuilder_T1_T2_.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.AddressTTBuilder_T1_T2_.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithFuncAndActionBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithFuncAndActionBuilder.g.cs
index 77fc406..47b073d 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithFuncAndActionBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithFuncAndActionBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithInitPropertiesBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithInitPropertiesBuilder.g.cs
index d0062c0..e35c965 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithInitPropertiesBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithInitPropertiesBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrimaryConstructorBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrimaryConstructorBuilder.g.cs
index 1bd03f4..63b33a8 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrimaryConstructorBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrimaryConstructorBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrivateSetter1Builder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrivateSetter1Builder.g.cs
index 9233fc2..7b66466 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrivateSetter1Builder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrivateSetter1Builder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrivateSetter2Builder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrivateSetter2Builder.g.cs
index 454b978..7f6d049 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrivateSetter2Builder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPrivateSetter2Builder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPropertyValueSetBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPropertyValueSetBuilder.g.cs
index cf36e8a..fd87873 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPropertyValueSetBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ClassWithPropertyValueSetBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.InternalClassBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.InternalClassBuilder.g.cs
index 7c8158b..2635b25 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.InternalClassBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.InternalClassBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.MyDummyClassBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.MyDummyClassBuilder.g.cs
index 0247e04..928adf6 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.MyDummyClassBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.MyDummyClassBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.MyInternalClassBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.MyInternalClassBuilder.g.cs
index e777e50..d8d31d1 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.MyInternalClassBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.MyInternalClassBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.RecordWithPrimaryConstructorBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.RecordWithPrimaryConstructorBuilder.g.cs
index 2ced2b2..17f3ac3 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.RecordWithPrimaryConstructorBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.RecordWithPrimaryConstructorBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.TestBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.TestBuilder.g.cs
index 455ac51..ba78426 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.TestBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.TestBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ThingBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ThingBuilder.g.cs
index 633710f..f7c7738 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ThingBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.ThingBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserBuilder.g.cs
index f9fc878..dfb8723 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTBuilder_T_.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTBuilder_T_.g.cs
index 0949f30..a79e4ad 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTBuilder_T_.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTBuilder_T_.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTWithAddressAndConstructorBuilder_T_.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTWithAddressAndConstructorBuilder_T_.g.cs
index 2d85ade..f65b4ee 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTWithAddressAndConstructorBuilder_T_.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTWithAddressAndConstructorBuilder_T_.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTWithAddressTBuilder_T_.g.cs b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTWithAddressTBuilder_T_.g.cs
index 005dd74..4edc14b 100644
--- a/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTWithAddressTBuilder_T_.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO/FluentBuilderGeneratorTests.DTO.UserTWithAddressTBuilder_T_.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO2/FluentBuilderGeneratorTests.DTO.Option_IListBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO2/FluentBuilderGeneratorTests.DTO.Option_IListBuilder.g.cs
index d6acb27..845c4f0 100644
--- a/tests/FluentBuilderGeneratorTests/DTO2/FluentBuilderGeneratorTests.DTO.Option_IListBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO2/FluentBuilderGeneratorTests.DTO.Option_IListBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/DTO2/FluentBuilderGeneratorTests.DTO2.MyOptionBuilder.g.cs b/tests/FluentBuilderGeneratorTests/DTO2/FluentBuilderGeneratorTests.DTO2.MyOptionBuilder.g.cs
index 676181f..d64e9ff 100644
--- a/tests/FluentBuilderGeneratorTests/DTO2/FluentBuilderGeneratorTests.DTO2.MyOptionBuilder.g.cs
+++ b/tests/FluentBuilderGeneratorTests/DTO2/FluentBuilderGeneratorTests.DTO2.MyOptionBuilder.g.cs
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/FileGenerator/FluentBuilderClassesGeneratorTests.cs b/tests/FluentBuilderGeneratorTests/FileGenerator/FluentBuilderClassesGeneratorTests.cs
deleted file mode 100644
index 3905d11..0000000
--- a/tests/FluentBuilderGeneratorTests/FileGenerator/FluentBuilderClassesGeneratorTests.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.IO;
-using System.Linq;
-using AwesomeAssertions;
-using FluentBuilderGenerator.FileGenerators;
-using FluentBuilderGenerator.Models;
-using FluentBuilderGenerator.SyntaxReceiver;
-using FluentBuilderGenerator.Types;
-using FluentBuilderGenerator.Wrappers;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Moq;
-using Xunit;
-
-namespace FluentBuilderGeneratorTests.FileGenerator;
-
-public class FluentBuilderClassesGeneratorTests
-{
- private const bool Write = true;
-
- private readonly Mock _contextMock;
- private readonly Mock _syntaxReceiverMock;
-
- private readonly FluentBuilderClassesGenerator _sut;
-
- public FluentBuilderClassesGeneratorTests()
- {
- _contextMock = new Mock();
- _contextMock.SetupGet(c => c.AssemblyName).Returns("FluentBuilderGeneratorTests");
- _contextMock.SetupGet(c => c.SupportsNullable).Returns(true);
- _contextMock.SetupGet(c => c.NullableEnabled).Returns(true);
-
- _syntaxReceiverMock = new Mock();
-
- _sut = new FluentBuilderClassesGenerator(_contextMock.Object, _syntaxReceiverMock.Object);
- }
-
- [Fact]
- public void GenerateFiles_WhenNoClassesFoundByReceiver_Should_NotGenerateFiles()
- {
- // Arrange
- _syntaxReceiverMock.SetupGet(r => r.CandidateFluentDataItems).Returns(new List());
-
- // Act
- var result = _sut.GenerateFiles();
-
- // Assert
- result.Should().BeEmpty();
-
- // Verify
- _syntaxReceiverMock.Verify(r => r.CandidateFluentDataItems, Times.Once());
- _syntaxReceiverMock.VerifyNoOtherCalls();
-
- _contextMock.VerifyNoOtherCalls();
- }
-
- [Fact(Skip = "needs fix")]
- public void GenerateFiles_WhenOneClassIsFoundByReceiver_Should_GenerateOneFile()
- {
- // Arrange : SyntaxReceiverMock
- var syntaxTree = CSharpSyntaxTree.ParseText(File.ReadAllText("./DTO/User.cs"));
- var root = syntaxTree.GetRoot();
- var @namespace = root.ChildNodes().OfType().Single();
- var @class = @namespace.ChildNodes().OfType().Single();
- var properties = @class.ChildNodes().OfType().ToList();
-
- var fluentData = new FluentData
- {
- BuilderType = BuilderType.Generated,
- Namespace = "FluentBuilderGeneratorTests.DTO",
- ShortBuilderClassName = "UserBuilder",
- FullBuilderClassName = "FluentBuilderGeneratorTests.DTO.UserBuilder",
- FullRawTypeName = "FluentBuilderGeneratorTests.DTO.User",
- ShortTypeName = "User",
- MetadataName = "FluentBuilderGeneratorTests.DTO.User",
- Usings = new List()
- };
- _syntaxReceiverMock.SetupGet(r => r.CandidateFluentDataItems).Returns(new[] { fluentData });
-
- // Arrange : ContextMock
- var namespaceSymbolMock = new Mock();
- namespaceSymbolMock.Setup(n => n.ToString()).Returns(@namespace.Name.ToString());
-
- var namedTypeSymbolMock = new Mock();
- namedTypeSymbolMock.SetupGet(n => n.Name).Returns("User");
- namedTypeSymbolMock.SetupGet(n => n.TypeArguments).Returns(ImmutableArray.Create());
-
- var membersMock = properties.Select(p =>
- {
- var setMethodMock = new Mock();
-
- var typeSymbol = new Mock();
- typeSymbol.SetupGet(t => t.Name).Returns(p.Type.ToString());
- typeSymbol.Setup(t => t.ToString()).Returns(p.Type.ToString());
- typeSymbol.SetupGet(ts => ts.AllInterfaces).Returns(ImmutableArray.Create());
-
- var propertySymbolMock = new Mock();
- propertySymbolMock.SetupGet(pt => pt.CanBeReferencedByName).Returns(true);
- propertySymbolMock.SetupGet(pt => pt.Name).Returns(p.Identifier.ValueText);
- propertySymbolMock.SetupGet(pt => pt.SetMethod).Returns(setMethodMock.Object);
- propertySymbolMock.SetupGet(pt => pt.Type).Returns(typeSymbol.Object);
-
- return propertySymbolMock;
- })
- .Select(p => (ISymbol)p.Object)
- .ToImmutableArray();
-
- var originalDefinitionMock = new Mock();
- originalDefinitionMock.Setup(o => o.ToString()).Returns("FluentBuilderGeneratorTests.DTO.User");
-
- var classSymbolMock = new Mock();
- classSymbolMock.SetupGet(n => n.ContainingNamespace).Returns(namespaceSymbolMock.Object);
- classSymbolMock.SetupGet(n => n.Name).Returns("User");
- classSymbolMock.SetupGet(n => n.OriginalDefinition).Returns(originalDefinitionMock.Object);
- classSymbolMock.Setup(n => n.GetMembers()).Returns(membersMock);
- classSymbolMock.SetupGet(n => n.TypeArguments).Returns(ImmutableArray.Create());
-
- var classSymbolConstructorMock = new Mock();
- classSymbolConstructorMock.SetupGet(c => c.DeclaredAccessibility).Returns(Accessibility.Public);
- classSymbolConstructorMock.SetupGet(c => c.Parameters).Returns(ImmutableArray.Empty);
- classSymbolMock.SetupGet(n => n.Constructors).Returns(ImmutableArray.Create(new[] { classSymbolConstructorMock.Object }));
-
- var classSymbol = new ClassSymbol
- {
- Type = FileDataType.Builder,
- FluentData = fluentData,
- //BuilderNamespace = fluentData.Namespace,
- //BuilderClassName = fluentData.ShortBuilderClassName,
- //FullBuilderClassName = fluentData.FullBuilderClassName,
- NamedTypeSymbol = classSymbolMock.Object
- };
- _contextMock.Setup(c => c.TryGetNamedTypeSymbolByFullMetadataName(It.IsAny(), out classSymbol)).Returns(true);
-
- // Act
- var result = _sut.GenerateFiles().ToList();
-
- // Assert
- result.Should().HaveCount(1);
- result[0].FileName.Should().Be("FluentBuilderGeneratorTests.DTO.UserBuilder.g.cs");
-
- var generated = result[0].Text;
- generated.Should().NotBeEmpty();
-
- if (Write) File.WriteAllText("../../../DTO/FluentBuilderGeneratorTests.DTO.UserBuilder.g.cs", generated);
-
- var generatedCode = CSharpSyntaxTree.ParseText(generated);
- var expectedCode = CSharpSyntaxTree.ParseText(File.ReadAllText("../../../DTO/FluentBuilderGeneratorTests.DTO.UserBuilder.g.cs"));
- generatedCode.Should().BeEquivalentTo(expectedCode);
-
- // Verify
- _syntaxReceiverMock.Verify(r => r.CandidateFluentDataItems, Times.Once());
- _syntaxReceiverMock.VerifyNoOtherCalls();
-
- _contextMock.Verify(c => c.TryGetNamedTypeSymbolByFullMetadataName(It.IsAny(), out It.Ref.IsAny), Times.Once());
- _contextMock.Verify(c => c.AssemblyName, Times.Once());
- _contextMock.Verify(c => c.SupportsNullable, Times.AtLeast(1));
- _contextMock.VerifyNoOtherCalls();
- }
-}
\ No newline at end of file
diff --git a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ClassWithFluentBuilderIgnore_Should_GenerateCorrectFiles.verified.txt b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ClassWithFluentBuilderIgnore_Should_GenerateCorrectFiles.verified.txt
index 9c83a6c..8fa5c48 100644
--- a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ClassWithFluentBuilderIgnore_Should_GenerateCorrectFiles.verified.txt
+++ b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ClassWithFluentBuilderIgnore_Should_GenerateCorrectFiles.verified.txt
@@ -3,7 +3,7 @@
Source:
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForAClassWithoutAPublicConstructor_Should_Create_ErrorFile.verified.txt b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForAClassWithoutAPublicConstructor_Should_Create_ErrorFile.verified.txt
deleted file mode 100644
index 23aeec9..0000000
--- a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForAClassWithoutAPublicConstructor_Should_Create_ErrorFile.verified.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- HintName: Error.g.cs,
- Source:
-/*
-FluentBuilderSourceGenerator
-
-[Exception]
-System.NotSupportedException: Unable to generate a FluentBuilder for the class 'System.AppDomain' because no public constructor is defined.
- at FluentBuilderGenerator.FileGenerators.FluentBuilderClassesGenerator.CreateClassBuilderCode(FluentData fluentData, ClassSymbol classSymbol, List`1 allClassSymbols) in {SolutionDirectory}src\FluentBuilderGenerator\FileGenerators\FluentBuilderClassesGenerator.cs:line 85
- at FluentBuilderGenerator.FileGenerators.FluentBuilderClassesGenerator.<>c__DisplayClass6_0.b__1(ValueTuple`2 classSymbol) in {SolutionDirectory}src\FluentBuilderGenerator\FileGenerators\FluentBuilderClassesGenerator.cs:line 56
- at System.Linq.Enumerable.SelectListIterator`2.MoveNext()
- at System.Collections.Generic.HashSet`1.UnionWith(IEnumerable`1 other)
- at System.Linq.Enumerable.UnionIterator`1.FillSet()
- at System.Linq.Enumerable.UnionIterator`1.ToList()
- at FluentBuilderGenerator.FileGenerators.FluentBuilderClassesGenerator.GenerateFiles() in {SolutionDirectory}src\FluentBuilderGenerator\FileGenerators\FluentBuilderClassesGenerator.cs:line 74
- at FluentBuilderGenerator.FluentBuilderSourceGenerator.InjectFluentBuilderClasses(IGeneratorExecutionContextWrapper context, IAutoGenerateBuilderSyntaxReceiver receiver) in {SolutionDirectory}src\FluentBuilderGenerator\FluentBuilderSourceGenerator.cs:line 83
- at FluentBuilderGenerator.FluentBuilderSourceGenerator.Execute(GeneratorExecutionContext context) in {SolutionDirectory}src\FluentBuilderGenerator\FluentBuilderSourceGenerator.cs:line 40
-
-[StackTrace]
- at FluentBuilderGenerator.FileGenerators.FluentBuilderClassesGenerator.CreateClassBuilderCode(FluentData fluentData, ClassSymbol classSymbol, List`1 allClassSymbols) in {SolutionDirectory}src\FluentBuilderGenerator\FileGenerators\FluentBuilderClassesGenerator.cs:line 85
- at FluentBuilderGenerator.FileGenerators.FluentBuilderClassesGenerator.<>c__DisplayClass6_0.b__1(ValueTuple`2 classSymbol) in {SolutionDirectory}src\FluentBuilderGenerator\FileGenerators\FluentBuilderClassesGenerator.cs:line 56
- at System.Linq.Enumerable.SelectListIterator`2.MoveNext()
- at System.Collections.Generic.HashSet`1.UnionWith(IEnumerable`1 other)
- at System.Linq.Enumerable.UnionIterator`1.FillSet()
- at System.Linq.Enumerable.UnionIterator`1.ToList()
- at FluentBuilderGenerator.FileGenerators.FluentBuilderClassesGenerator.GenerateFiles() in {SolutionDirectory}src\FluentBuilderGenerator\FileGenerators\FluentBuilderClassesGenerator.cs:line 74
- at FluentBuilderGenerator.FluentBuilderSourceGenerator.InjectFluentBuilderClasses(IGeneratorExecutionContextWrapper context, IAutoGenerateBuilderSyntaxReceiver receiver) in {SolutionDirectory}src\FluentBuilderGenerator\FluentBuilderSourceGenerator.cs:line 83
- at FluentBuilderGenerator.FluentBuilderSourceGenerator.Execute(GeneratorExecutionContext context) in {SolutionDirectory}src\FluentBuilderGenerator\FluentBuilderSourceGenerator.cs:line 40*/
-}
\ No newline at end of file
diff --git a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForSimpleClass_MethodsIsWithAndWithout_Should_GenerateCorrectFiles.verified.txt b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForSimpleClass_MethodsIsWithAndWithout_Should_GenerateCorrectFiles.verified.txt
index 9c83a6c..8fa5c48 100644
--- a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForSimpleClass_MethodsIsWithAndWithout_Should_GenerateCorrectFiles.verified.txt
+++ b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForSimpleClass_MethodsIsWithAndWithout_Should_GenerateCorrectFiles.verified.txt
@@ -3,7 +3,7 @@
Source:
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForSimpleClass_MethodsIsWithOnly_Should_GenerateCorrectFiles.verified.txt b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForSimpleClass_MethodsIsWithOnly_Should_GenerateCorrectFiles.verified.txt
index 9c83a6c..8fa5c48 100644
--- a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForSimpleClass_MethodsIsWithOnly_Should_GenerateCorrectFiles.verified.txt
+++ b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.GenerateFiles_ForSimpleClass_MethodsIsWithOnly_Should_GenerateCorrectFiles.verified.txt
@@ -3,7 +3,7 @@
Source:
//------------------------------------------------------------------------------
//
-// This code was generated by https://github.com/StefH/FluentBuilder version 0.11.0.0
+// This code was generated by https://github.com/StefH/FluentBuilder version 0.12.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.cs b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.cs
index 95c5207..39af48e 100644
--- a/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.cs
+++ b/tests/FluentBuilderGeneratorTests/FluentBuilderSourceGeneratorTests.cs
@@ -7,6 +7,7 @@
using CSharp.SourceGenerators.Extensions.Models;
using FluentBuilderGenerator;
using FluentBuilderGeneratorTests.DTO;
+using Microsoft.CodeAnalysis;
using VerifyTests;
using VerifyXunit;
using Xunit;
@@ -32,7 +33,27 @@ public FluentBuilderSourceGeneratorTests()
public static void ModuleInitializer() => VerifySourceGenerators.Enable();
[Fact]
- public Task GenerateFiles_ForAClassWithoutAPublicConstructor_Should_Create_ErrorFile()
+ public void GenerateFiles_ForClassWithPrivateBuilderClass_ShouldReturnDiagnostics()
+ {
+ // Arrange
+ var path = "./DTO/ClassWithPrivateBuilderClass.cs";
+ var sourceFile = new SourceFile
+ {
+ Path = path,
+ Text = File.ReadAllText(path)
+ };
+ IIncrementalGenerator sut = new FluentBuilderSourceGenerator();
+
+ // Act
+ var result = sut.Execute(Namespace, [sourceFile]);
+
+ // Assert
+ result.InformationMessages.Should().HaveCount(1);
+ result.InformationMessages[0].Should().Be("Class or Record modifier should be 'public' or 'internal'");
+ }
+
+ [Fact]
+ public void GenerateFiles_ForAClassWithoutAPublicConstructor_Should_Create_ErrorFile()
{
// Arrange
var path = "./DTO2/MyAppDomainBuilder.cs";
@@ -48,15 +69,12 @@ public Task GenerateFiles_ForAClassWithoutAPublicConstructor_Should_Create_Error
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Files.Should().HaveCount(NumFiles);
result.Files[NumFiles - 1].Path.Should().EndWith("Error.g.cs");
-
- // Verify
- var errorResult = result.GeneratorDriver.GetRunResult().Results.First().GeneratedSources.First(s => s.HintName.Contains("Error.g.cs"));
- return Verifier.Verify(errorResult);
+ result.Files[NumFiles - 1].Text.Should().NotBeEmpty();
}
[Fact]
@@ -72,7 +90,7 @@ public void GenerateFiles_ForAClassWithPublicParameterlessConstructors_Should_Ge
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -103,7 +121,7 @@ public void GenerateFiles_ForAClassWithOnlyParameterizedConstructors_Should_Gene
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -178,7 +196,7 @@ public void GenerateFiles_For2Classes_Should_GenerateCorrectFiles()
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFileUser, sourceFileBuilder });
+ var result = _sut.Execute(Namespace, [sourceFileUser, sourceFileBuilder]);
// Assert
result.Valid.Should().BeTrue();
@@ -281,7 +299,7 @@ public void GenerateFiles_ClassWithPrivateSetter_And_AccessibilityPublicAndPriva
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -318,7 +336,7 @@ public void GenerateFiles_ClassWithPrivateSetter_And_AccessibilityPublic_Should_
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -352,7 +370,7 @@ public Task GenerateFiles_ClassWithFluentBuilderIgnore_Should_GenerateCorrectFil
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -376,7 +394,7 @@ public Task GenerateFiles_ForSimpleClass_MethodsIsWithOnly_Should_GenerateCorrec
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -404,7 +422,7 @@ public Task GenerateFiles_ForSimpleClass_MethodsIsWithAndWithout_Should_Generate
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -452,7 +470,7 @@ public void GenerateFiles_ForClassWithArrayAndDictionaryProperty_Should_Generate
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -484,7 +502,7 @@ public void GenerateFiles_For1GenericClass_Should_GenerateCorrectFiles()
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -514,7 +532,7 @@ public void GenerateFiles_For1GenericClassTT_Should_GenerateCorrectFiles()
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -554,7 +572,7 @@ public void GenerateFiles_For2GenericClasses_Should_GenerateCorrectFiles()
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile1, sourceFile2 });
+ var result = _sut.Execute(Namespace, [sourceFile1, sourceFile2]);
// Assert
result.Valid.Should().BeTrue();
@@ -600,7 +618,7 @@ public void GenerateFiles_For2GenericClasses_WithDefaultConstructor_Should_Gener
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile1, sourceFile2 });
+ var result = _sut.Execute(Namespace, [sourceFile1, sourceFile2]);
// Assert
result.Valid.Should().BeTrue();
@@ -630,7 +648,7 @@ public void GenerateFiles_ClassWithReferenceToItself_Should_GenerateCorrectFiles
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -660,7 +678,7 @@ public void GenerateFiles_ClassWithFuncAndAction_Should_GenerateCorrectFiles()
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -690,7 +708,7 @@ public void GenerateFiles_ClassWithPropertyWhichHasAValue_Should_GenerateCorrect
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFile });
+ var result = _sut.Execute(Namespace, [sourceFile]);
// Assert
result.Valid.Should().BeTrue();
@@ -701,9 +719,6 @@ public void GenerateFiles_ClassWithPropertyWhichHasAValue_Should_GenerateCorrect
if (Write) File.WriteAllText($"../../../DTO/{builderFileName}", builder.Text);
builder.Text.Should().Be(File.ReadAllText($"../../../DTO/{builderFileName}"));
-
- //var b = new ClassWithCultureInfoBuilder();
- //var c = b.Build();
}
[Fact]
@@ -769,7 +784,7 @@ public void GenerateFiles_For2ClassesWithListBuilder_Should_GenerateCorrectFiles
};
// Act
- var result = _sut.Execute(Namespace, new[] { sourceFileTest, sourceFileOther });
+ var result = _sut.Execute(Namespace, [sourceFileTest, sourceFileOther]);
// Assert
result.Valid.Should().BeTrue();
@@ -797,8 +812,7 @@ public void GenerateFiles_ClassWithInitProperties_Should_GenerateCorrectFiles()
Text = File.ReadAllText(path),
AttributeToAddToClass = new ExtraAttribute
{
- Name = "FluentBuilder.AutoGenerateBuilder",
- //ArgumentList = new[] { "FluentBuilderAccessibility.PublicAndPrivate" }
+ Name = "FluentBuilder.AutoGenerateBuilder"
}
};