diff --git a/README.md b/README.md
index 88ac302..4186680 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ PM> Install-Package M31.FluentApi
A package reference will be added to your `csproj` file. Moreover, since this library provides code via source code generation, consumers of your project don't need the reference to `M31.FluentApi`. Therefore, it is recommended to use the `PrivateAssets` metadata tag:
```xml
-
+
```
If you would like to examine the generated code, you may emit it by adding the following lines to your `csproj` file:
diff --git a/src/M31.FluentApi.Generator/AnalyzerReleases.Shipped.md b/src/M31.FluentApi.Generator/AnalyzerReleases.Shipped.md
index f0df066..7b4d393 100644
--- a/src/M31.FluentApi.Generator/AnalyzerReleases.Shipped.md
+++ b/src/M31.FluentApi.Generator/AnalyzerReleases.Shipped.md
@@ -50,4 +50,13 @@ M31FA018 | M31.Usage | Error | Generic types are not supported
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
M31FA021 | M31.Usage | Error | Reserved method name
-M31FA022 | M31.Usage | Error | Fluent lambda member without Fluent API
\ No newline at end of file
+M31FA022 | M31.Usage | Error | Fluent lambda member without Fluent API
+
+
+## Release 1.5.0
+
+### Removed Rules
+
+Rule ID | Category | Severity | Notes
+--------|----------|----------|-------
+M31FA007 | M31.Usage | Error | Partial types are not supported
\ No newline at end of file
diff --git a/src/M31.FluentApi.Generator/Commons/SyntaxNodeExtensions.cs b/src/M31.FluentApi.Generator/Commons/SyntaxNodeExtensions.cs
index 3fd582f..d234a00 100644
--- a/src/M31.FluentApi.Generator/Commons/SyntaxNodeExtensions.cs
+++ b/src/M31.FluentApi.Generator/Commons/SyntaxNodeExtensions.cs
@@ -5,10 +5,10 @@ namespace M31.FluentApi.Generator.Commons;
internal static class SyntaxNodeExtensions
{
- internal static bool IsTypeDeclarationOfInterest(
+ internal static bool IsClassStructOrRecordSyntax(
this SyntaxNode? syntaxNode, out TypeDeclarationSyntax typeDeclaration)
{
- if (syntaxNode.IsTypeDeclarationOfInterest())
+ if (syntaxNode.IsClassStructOrRecordSyntax())
{
typeDeclaration = (TypeDeclarationSyntax)syntaxNode!;
return true;
@@ -18,8 +18,26 @@ internal static bool IsTypeDeclarationOfInterest(
return false;
}
- internal static bool IsTypeDeclarationOfInterest(this SyntaxNode? syntaxNode)
+ internal static bool IsClassStructOrRecordSyntax(this SyntaxNode? syntaxNode)
{
return syntaxNode is ClassDeclarationSyntax or StructDeclarationSyntax or RecordDeclarationSyntax;
}
+
+ internal static bool IsFluentApiAttributeSyntax(this AttributeSyntax attributeSyntax)
+ {
+ string? name = ExtractName(attributeSyntax.Name);
+
+ // Note that we drop alias support for better performance.
+ return name is "FluentApi" or "FluentApiAttribute";
+
+ string? ExtractName(NameSyntax nameSyntax)
+ {
+ return nameSyntax switch
+ {
+ SimpleNameSyntax simpleNameSyntax => simpleNameSyntax.Identifier.Text, // without namespace
+ QualifiedNameSyntax qualifiedNameSyntax => qualifiedNameSyntax.Right.Identifier.Text, // fully qualified
+ _ => null
+ };
+ }
+ }
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Generator/M31.FluentApi.Generator.csproj b/src/M31.FluentApi.Generator/M31.FluentApi.Generator.csproj
index 17dfe6c..1f28998 100644
--- a/src/M31.FluentApi.Generator/M31.FluentApi.Generator.csproj
+++ b/src/M31.FluentApi.Generator/M31.FluentApi.Generator.csproj
@@ -11,7 +11,7 @@
true
true
true
- 1.4.0
+ 1.5.0
Kevin Schaal
The generator package for M31.FluentAPI. Don't install this package explicitly, install M31.FluentAPI instead.
fluentapi fluentbuilder fluentinterface fluentdesign fluent codegeneration
diff --git a/src/M31.FluentApi.Generator/SourceAnalyzers/FluentApiAnalyzer.cs b/src/M31.FluentApi.Generator/SourceAnalyzers/FluentApiAnalyzer.cs
index 2bd4182..21f528b 100644
--- a/src/M31.FluentApi.Generator/SourceAnalyzers/FluentApiAnalyzer.cs
+++ b/src/M31.FluentApi.Generator/SourceAnalyzers/FluentApiAnalyzer.cs
@@ -20,7 +20,12 @@ public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
- context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration);
+ context.RegisterSyntaxNodeAction(
+ AnalyzeNode,
+ SyntaxKind.ClassDeclaration,
+ SyntaxKind.StructDeclaration,
+ SyntaxKind.RecordDeclaration,
+ SyntaxKind.RecordStructDeclaration);
}
private void AnalyzeNode(SyntaxNodeAnalysisContext context)
@@ -51,21 +56,7 @@ private void AnalyzeNodeInternal(SyntaxNodeAnalysisContext context)
return;
}
- ImmutableArray syntaxReferences = symbol.DeclaringSyntaxReferences;
-
- if (syntaxReferences.Length == 0)
- {
- return;
- }
-
- SyntaxNode syntaxNode = syntaxReferences.First().GetSyntax();
-
- if (!syntaxNode.IsTypeDeclarationOfInterest(out TypeDeclarationSyntax typeDeclaration))
- {
- return;
- }
-
- if (ReportErrorDiagnosticForPartialKeyword(context, typeDeclaration, symbol))
+ if (context.Node is not TypeDeclarationSyntax typeDeclaration)
{
return;
}
@@ -92,23 +83,4 @@ private void AnalyzeNodeInternal(SyntaxNodeAnalysisContext context)
context.ReportDiagnostic(diagnostic);
}
}
-
- private bool ReportErrorDiagnosticForPartialKeyword(
- SyntaxNodeAnalysisContext context,
- TypeDeclarationSyntax typeDeclaration,
- INamedTypeSymbol symbol)
- {
- SyntaxToken partialKeyword = typeDeclaration.Modifiers.FirstOrDefault(
- m => m.IsKind(SyntaxKind.PartialKeyword));
-
- if (partialKeyword != default)
- {
- context.ReportDiagnostic(UnsupportedPartialType.CreateDiagnostic(
- partialKeyword,
- symbol.Name));
- return true;
- }
-
- return false;
- }
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Generator/SourceAnalyzers/FluentApiDiagnostics.cs b/src/M31.FluentApi.Generator/SourceAnalyzers/FluentApiDiagnostics.cs
index 6d56185..ad1edb0 100644
--- a/src/M31.FluentApi.Generator/SourceAnalyzers/FluentApiDiagnostics.cs
+++ b/src/M31.FluentApi.Generator/SourceAnalyzers/FluentApiDiagnostics.cs
@@ -18,7 +18,6 @@ internal static class FluentApiDiagnostics
DuplicateAttribute.Descriptor,
OrthogonalAttributeMisused.Descriptor,
DuplicateMainAttribute.Descriptor,
- UnsupportedPartialType.Descriptor,
InvalidFluentPredicateType.Descriptor,
InvalidFluentNullableType.Descriptor,
FluentNullableTypeWithoutNullableAnnotation.Descriptor,
@@ -144,22 +143,6 @@ internal static Diagnostic CreateDiagnostic(AttributeDataExtended attributeData)
}
}
- internal static class UnsupportedPartialType
- {
- internal static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor(
- id: "M31FA007",
- title: "Partial types are not supported",
- messageFormat: "Partial types are not supported. Remove partial keyword from type '{0}'.",
- category: "M31.Usage",
- defaultSeverity: DiagnosticSeverity.Error,
- isEnabledByDefault: true);
-
- internal static Diagnostic CreateDiagnostic(SyntaxToken partialKeyword, string typeName)
- {
- return Diagnostic.Create(Descriptor, partialKeyword.GetLocation(), typeName);
- }
- }
-
internal static class InvalidFluentPredicateType
{
internal static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor(
diff --git a/src/M31.FluentApi.Generator/SourceGenerators/SourceGenerator.cs b/src/M31.FluentApi.Generator/SourceGenerators/SourceGenerator.cs
index 2ab89c0..2159892 100644
--- a/src/M31.FluentApi.Generator/SourceGenerators/SourceGenerator.cs
+++ b/src/M31.FluentApi.Generator/SourceGenerators/SourceGenerator.cs
@@ -16,7 +16,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var infos = context.SyntaxProvider
.CreateSyntaxProvider(CanBeFluentApiClass, GetFluentApiClassInfo)
.Where(info => info is not null)
- .Collect() // Handle partial classes, get an array of related info objects into GenerateCode.
+ .Collect() // Handle partial classes, get an array of related info objects.
.SelectMany((infos, _) =>
infos.Distinct()); // Want to have every fluent API info object only once.
@@ -73,7 +73,7 @@ private void SourceOutputAction(SourceProductionContext ctx, FluentApiClassInfo
{
SyntaxNode? syntaxNode = ctx.Node.Parent?.Parent;
- if (!syntaxNode.IsTypeDeclarationOfInterest(out TypeDeclarationSyntax typeDeclaration))
+ if (!syntaxNode.IsClassStructOrRecordSyntax(out TypeDeclarationSyntax typeDeclaration))
{
return null;
}
@@ -106,22 +106,11 @@ private bool CanBeFluentApiClass(SyntaxNode node, CancellationToken cancellation
// The parent of the attribute is a list of attributes, the parent of the parent is the class.
SyntaxNode? syntaxNode = attributeSyntax.Parent?.Parent;
- if (!syntaxNode.IsTypeDeclarationOfInterest())
+ if (!syntaxNode.IsClassStructOrRecordSyntax())
{
return false;
}
- string? name = ExtractName(attributeSyntax.Name);
- return name is "FluentApi" or "FluentApiAttribute";
- }
-
- private string? ExtractName(NameSyntax nameSyntax)
- {
- return nameSyntax switch
- {
- SimpleNameSyntax simpleNameSyntax => simpleNameSyntax.Identifier.Text, // without namespace
- QualifiedNameSyntax qualifiedNameSyntax => qualifiedNameSyntax.Right.Identifier.Text, // fully qualified
- _ => null
- };
+ return attributeSyntax.IsFluentApiAttributeSyntax();
}
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/AnalyzerAndCodeFixTests.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/AnalyzerAndCodeFixTests.cs
index 7376b79..1562fdd 100644
--- a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/AnalyzerAndCodeFixTests.cs
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/AnalyzerAndCodeFixTests.cs
@@ -1,4 +1,6 @@
using System.Threading.Tasks;
+using M31.FluentApi.Tests.AnalyzerAndCodeFixes.Helpers;
+using Microsoft.CodeAnalysis.Testing;
using Xunit;
using static M31.FluentApi.Tests.AnalyzerAndCodeFixes.Helpers.TestSourceCodeReader;
using static M31.FluentApi.Generator.SourceAnalyzers.FluentApiDiagnostics;
@@ -13,7 +15,7 @@ public class AnalyzerAndCodeFixTests
[Fact]
public async Task CanDetectConflictingControlAttributes1()
{
- (string source, string fixedSource) = ReadSource("ConflictingControlAttributesClass1", "Student");
+ SourceWithFix source = ReadSource("ConflictingControlAttributesClass1", "Student");
var expectedDiagnostic1 = Verifier.Diagnostic(ConflictingControlAttributes.Descriptor.Id)
.WithLocation(13, 6);
@@ -21,13 +23,13 @@ public async Task CanDetectConflictingControlAttributes1()
var expectedDiagnostic2 = Verifier.Diagnostic(ConflictingControlAttributes.Descriptor.Id)
.WithLocation(14, 6);
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic1, expectedDiagnostic2);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic1, expectedDiagnostic2);
}
[Fact]
public async Task CanDetectConflictingControlAttributes2()
{
- (string source, string fixedSource) = ReadSource("ConflictingControlAttributesClass2", "Student");
+ SourceWithFix source = ReadSource("ConflictingControlAttributesClass2", "Student");
var expectedDiagnostic1 = Verifier.Diagnostic(ConflictingControlAttributes.Descriptor.Id)
.WithLocation(13, 6);
@@ -35,13 +37,13 @@ public async Task CanDetectConflictingControlAttributes2()
var expectedDiagnostic2 = Verifier.Diagnostic(ConflictingControlAttributes.Descriptor.Id)
.WithLocation(17, 6);
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic1, expectedDiagnostic2);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic1, expectedDiagnostic2);
}
[Fact]
public async Task CanDetectConflictingControlAttributes3()
{
- (string source, string fixedSource) = ReadSource("ConflictingControlAttributesClass3", "Student");
+ SourceWithFix source = ReadSource("ConflictingControlAttributesClass3", "Student");
var expectedDiagnostic1 = Verifier.Diagnostic(ConflictingControlAttributes.Descriptor.Id)
.WithLocation(16, 6);
@@ -49,185 +51,223 @@ public async Task CanDetectConflictingControlAttributes3()
var expectedDiagnostic2 = Verifier.Diagnostic(ConflictingControlAttributes.Descriptor.Id)
.WithLocation(17, 6);
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic1, expectedDiagnostic2);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic1, expectedDiagnostic2);
}
[Fact]
public async Task CanDetectFluentLambdaMemberWithoutFluentApiClass()
{
- (string source, _) = ReadSource("FluentLambdaMemberWithoutFluentApiClass", "Student");
+ SourceWithFix source = ReadSource("FluentLambdaMemberWithoutFluentApiClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(FluentLambdaMemberWithoutFluentApi.Descriptor.Id)
.WithLocation(14, 6)
.WithArguments("Address");
- await Verifier.VerifyCodeFixAsync(source, null, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectDuplicateMainAttribute()
{
- (string source, string fixedSource) = ReadSource("DuplicateMainAttributeClass", "Student");
+ SourceWithFix source = ReadSource("DuplicateMainAttributeClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(DuplicateMainAttribute.Descriptor.Id)
.WithLocation(11, 6);
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectGetMissingSetAndAddSetAccessor()
{
- (string source, string fixedSource) = ReadSource("GetMissingSetClass", "Student");
+ SourceWithFix source = ReadSource("GetMissingSetClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(MissingSetAccessor.Descriptor.Id)
.WithLocation(11, 9)
.WithArguments("Semester");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
+ }
+
+ [Fact]
+ public async Task CanDetectGetMissingSetAndAddSetAccessorForRecords()
+ {
+ SourceWithFix source = ReadSource("GetMissingSetRecord", "Student");
+
+ var expectedDiagnostic = Verifier.Diagnostic(MissingSetAccessor.Descriptor.Id)
+ .WithLocation(11, 9)
+ .WithArguments("Semester");
+
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
+ }
+
+ [Fact]
+ public async Task CanDetectGetMissingSetAndAddSetAccessorForRecordStructs()
+ {
+ SourceWithFix source = ReadSource("GetMissingSetRecordStruct", "Student");
+
+ var expectedDiagnostic = Verifier.Diagnostic(MissingSetAccessor.Descriptor.Id)
+ .WithLocation(11, 9)
+ .WithArguments("Semester");
+
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
+ }
+
+ [Fact]
+ public async Task CanDetectGetMissingSetAndAddSetAccessorForStructs()
+ {
+ SourceWithFix source = ReadSource("GetMissingSetStruct", "Student");
+
+ var expectedDiagnostic = Verifier.Diagnostic(MissingSetAccessor.Descriptor.Id)
+ .WithLocation(11, 9)
+ .WithArguments("Semester");
+
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectInvalidCollectionType()
{
- (string source, string fixedSource) = ReadSource("InvalidCollectionTypeClass", "Student");
+ SourceWithFix source = ReadSource("InvalidCollectionTypeClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(UnsupportedFluentCollectionType.Descriptor.Id)
.WithLocation(13, 12)
.WithArguments("string");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectInvalidFluentMethodReturnType()
{
- (string source, _) = ReadSource("InvalidFluentMethodReturnTypeClass", "Student");
+ SourceWithFix source = ReadSource("InvalidFluentMethodReturnTypeClass", "Student");
+
+ // Pass null for the fixed source because it does not compile. See also file Student.fixed.illustration.txt.
+ source = source with { FixedSource = null };
var expectedDiagnostic = Verifier.Diagnostic(InvalidFluentMethodReturnType.Descriptor.Id)
.WithLocation(14, 12)
.WithArguments("int");
- await Verifier.VerifyCodeFixAsync(source, null, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectInvalidFluentPredicateType()
{
- (string source, string fixedSource) = ReadSource("InvalidFluentPredicateTypeClass", "Student");
+ SourceWithFix source = ReadSource("InvalidFluentPredicateTypeClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(InvalidFluentPredicateType.Descriptor.Id)
.WithLocation(13, 12)
.WithArguments("string");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectInvalidNullableType()
{
- (string source, string fixedSource) = ReadSource("InvalidNullableTypeClass", "Student");
+ SourceWithFix source = ReadSource("InvalidNullableTypeClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(InvalidFluentNullableType.Descriptor.Id)
.WithLocation(10, 12)
.WithArguments("int");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectMissingBuilderStep()
{
- (string source, string fixedSource) = ReadSource("MissingBuilderStepClass", "Student");
+ SourceWithFix source = ReadSource("MissingBuilderStepClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(MissingBuilderStep.Descriptor.Id)
.WithLocation(12, 6)
.WithArguments(99);
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectMissingDefaultConstructor()
{
- (string source, string fixedSource) = ReadSource("MissingDefaultConstructorClass", "Student");
+ SourceWithFix source = ReadSource("MissingDefaultConstructorClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(MissingDefaultConstructor.Descriptor.Id)
.WithLocation(6, 14)
.WithArguments("Student");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectNullableTypeNoNullableAnnotation()
{
- (string source, string fixedSource) = ReadSource("NullableTypeNoNullableAnnotationClass", "Student");
+ SourceWithFix source = ReadSource("NullableTypeNoNullableAnnotationClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(FluentNullableTypeWithoutNullableAnnotation.Descriptor.Id)
.WithLocation(13, 12)
.WithArguments("string");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectOrthogonalAttributeInCompound()
{
- (string source, string fixedSource) = ReadSource("OrthogonalAttributeInCompoundClass", "Student");
+ SourceWithFix source = ReadSource("OrthogonalAttributeInCompoundClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(OrthogonalAttributeMisusedWithCompound.Descriptor.Id)
.WithLocation(16, 6)
.WithArguments("FluentDefault");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectOrthogonalAttributeWithoutMainAttribute()
{
- (string source, string fixedSource) = ReadSource("OrthogonalAttributeWithoutMainAttributeClass", "Student");
+ SourceWithFix source = ReadSource("OrthogonalAttributeWithoutMainAttributeClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(OrthogonalAttributeMisused.Descriptor.Id)
.WithLocation(10, 6)
.WithArguments("FluentDefault");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
- public async Task CanDetectPartialClass()
+ public async Task CanHandlePartialClass()
{
- (string source, string fixedSource) = ReadSource("PartialClass", "Student");
-
- var expectedDiagnostic = Verifier.Diagnostic(UnsupportedPartialType.Descriptor.Id)
- .WithLocation(8, 8)
- .WithArguments("Student");
+ SourceWithFix source1 = ReadSource("PartialClass", "Student1");
+ SourceWithFix source2 = ReadSource("PartialClass", "Student2");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(
+ new SourceWithFix[] { source1, source2 },
+ DiagnosticResult.EmptyDiagnosticResults);
}
[Fact]
public async Task CanDetectPrivateGetMissingSetAndAddSetAccessor()
{
- (string source, string fixedSource) = ReadSource("PrivateGetMissingSetClass", "Student");
+ SourceWithFix source = ReadSource("PrivateGetMissingSetClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(MissingSetAccessor.Descriptor.Id)
.WithLocation(11, 17)
.WithArguments("Semester");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
[Fact]
public async Task CanDetectPublicGetMissingSetAndAddPrivateSetAccessor()
{
- (string source, string fixedSource) = ReadSource("PublicGetMissingSetClass", "Student");
+ SourceWithFix source = ReadSource("PublicGetMissingSetClass", "Student");
var expectedDiagnostic = Verifier.Diagnostic(MissingSetAccessor.Descriptor.Id)
.WithLocation(11, 16)
.WithArguments("Semester");
- await Verifier.VerifyCodeFixAsync(source, fixedSource, expectedDiagnostic);
+ await Verifier.VerifyCodeFixAsync(source, expectedDiagnostic);
}
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/DiagnosticsDuringGenerationTests.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/DiagnosticsDuringGenerationTests.cs
index 4a59789..cc14b87 100644
--- a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/DiagnosticsDuringGenerationTests.cs
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/DiagnosticsDuringGenerationTests.cs
@@ -1,4 +1,5 @@
using System.Linq;
+using M31.FluentApi.Tests.AnalyzerAndCodeFixes.Helpers;
using M31.FluentApi.Tests.Helpers;
using Microsoft.CodeAnalysis;
using Xunit;
@@ -17,7 +18,7 @@ public void CanDetectDuplicateMethod1()
"WithName",
(11, 6), (14, 6));
- RunGeneratorAndCheckDiagnostics("DuplicateMethodClass1", expectedDiagnostic);
+ RunGeneratorAndCheckDiagnostics("DuplicateMethodClass1", "Student", expectedDiagnostic);
}
[Fact]
@@ -28,7 +29,7 @@ public void CanDetectDuplicateMethod2()
"WithFriend",
(12, 6), (15, 6));
- RunGeneratorAndCheckDiagnostics("DuplicateMethodClass2", expectedDiagnostic);
+ RunGeneratorAndCheckDiagnostics("DuplicateMethodClass2", "Student", expectedDiagnostic);
}
[Fact]
@@ -39,7 +40,7 @@ public void CanDetectDuplicateMethod3()
"WithName",
(14, 6), (20, 6));
- RunGeneratorAndCheckDiagnostics("DuplicateMethodClass3", expectedDiagnostic);
+ RunGeneratorAndCheckDiagnostics("DuplicateMethodClass3", "Student", expectedDiagnostic);
}
[Fact]
@@ -50,7 +51,7 @@ public void CanDetectDuplicateMethod4()
"Method1",
(12, 6), (17, 6), (22, 6));
- RunGeneratorAndCheckDiagnostics("DuplicateMethodClass4", expectedDiagnostic);
+ RunGeneratorAndCheckDiagnostics("DuplicateMethodClass4", "Student", expectedDiagnostic);
}
[Fact]
@@ -61,7 +62,17 @@ public void CanDetectDuplicateMethod5()
"Method1",
(12, 6), (17, 6));
- RunGeneratorAndCheckDiagnostics("DuplicateMethodClass5", expectedDiagnostic);
+ RunGeneratorAndCheckDiagnostics("DuplicateMethodClass5", "Student", expectedDiagnostic);
+ }
+
+ [Fact]
+ public void CanDetectDuplicateMethodPartialClass()
+ {
+ ExpectedDiagnostic expectedDiagnostic = new ExpectedDiagnostic(
+ DuplicateFluentApiMethod.Descriptor,
+ "WithName",
+ (10, 6), (11, 6));
+ RunGeneratorAndCheckDiagnostics("DuplicateMethodPartialClass", "Student1|Student2", expectedDiagnostic);
}
[Fact]
@@ -77,7 +88,7 @@ public void CanDetectReservedMethod1()
"InitialStep",
(17, 6));
- RunGeneratorAndCheckDiagnostics("ReservedMethodClass1", expectedDiagnostic1, expectedDiagnostic2);
+ RunGeneratorAndCheckDiagnostics("ReservedMethodClass1", "Student", expectedDiagnostic1, expectedDiagnostic2);
}
[Fact]
@@ -88,14 +99,18 @@ public void CanDetectReservedMethod2()
"InitialStep",
(12, 6));
- RunGeneratorAndCheckDiagnostics("ReservedMethodClass2", expectedDiagnostic1);
+ RunGeneratorAndCheckDiagnostics("ReservedMethodClass2", "Student", expectedDiagnostic1);
}
- private void RunGeneratorAndCheckDiagnostics(string testClassFolder,
+ private void RunGeneratorAndCheckDiagnostics(
+ string testClassFolder,
+ string classes,
params ExpectedDiagnostic[] expectedDiagnostics)
{
- (string source, _) = ReadSource(testClassFolder, "Student");
- Diagnostic[] diagnostics = ManualGenerator.RunGeneratorsAndGetDiagnostics(source).ToArray();
+ string[] splitClasses = classes.Split('|');
+ SourceWithFix[] sourceCodeWithFixes = splitClasses.Select(c => ReadSource(testClassFolder, c)).ToArray();
+ string[] sourceCode = sourceCodeWithFixes.Select(c => c.Source).ToArray();
+ Diagnostic[] diagnostics = ManualGenerator.RunGeneratorsAndGetDiagnostics(sourceCode).ToArray();
Assert.Equal(expectedDiagnostics.Length, diagnostics.Length);
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/AnalyzerAndCodeFixVerifier.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/AnalyzerAndCodeFixVerifier.cs
index bb61db0..cc8c7d9 100644
--- a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/AnalyzerAndCodeFixVerifier.cs
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/AnalyzerAndCodeFixVerifier.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -23,26 +24,34 @@ internal static DiagnosticResult Diagnostic(string diagnosticId)
}
internal static async Task VerifyCodeFixAsync(
- string source,
- string? fixedSource,
+ SourceWithFix source,
params DiagnosticResult[] expected)
{
- var test = new CodeFixTest(source, fixedSource, expected);
+ await VerifyCodeFixAsync(new SourceWithFix[] { source }, expected);
+ }
+
+ internal static async Task VerifyCodeFixAsync(
+ IReadOnlyCollection sourceCode,
+ params DiagnosticResult[] expected)
+ {
+ CodeFixTest test = new CodeFixTest(sourceCode, expected);
await test.RunAsync(CancellationToken.None);
}
private class CodeFixTest : CSharpCodeFixTest
{
internal CodeFixTest(
- string source,
- string? fixedSource,
+ IReadOnlyCollection sourceCode,
params DiagnosticResult[] expected)
{
- TestCode = source;
-
- if (fixedSource != null)
+ foreach (SourceWithFix source in sourceCode)
{
- FixedCode = fixedSource;
+ TestState.Sources.Add(source.Source);
+
+ if (source.FixedSource != null)
+ {
+ FixedState.Sources.Add(source.FixedSource);
+ }
}
ExpectedDiagnostics.AddRange(expected);
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/SourceWithFix.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/SourceWithFix.cs
new file mode 100644
index 0000000..6b46f95
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/SourceWithFix.cs
@@ -0,0 +1,3 @@
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.Helpers;
+
+internal record SourceWithFix(string Source, string? FixedSource);
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/TestSourceCodeReader.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/TestSourceCodeReader.cs
index f569c7b..f0703e0 100644
--- a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/TestSourceCodeReader.cs
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/Helpers/TestSourceCodeReader.cs
@@ -4,11 +4,11 @@ namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.Helpers;
internal static class TestSourceCodeReader
{
- internal static (string source, string fixedSource) ReadSource(string testClassFolder, string @class)
+ internal static SourceWithFix ReadSource(string testClassFolder, string @class)
{
string source = ReadTestClassCode(testClassFolder, $"{@class}.cs");
string fixedSource = TryReadTestClassCode(testClassFolder, $"{@class}.fixed.txt") ?? source;
- return (source, fixedSource);
+ return new SourceWithFix(source, fixedSource);
}
private static string ReadTestClassCode(string testClassFolder, string file)
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/DuplicateMethodPartialClass/Student1.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/DuplicateMethodPartialClass/Student1.cs
new file mode 100644
index 0000000..9cdbc79
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/DuplicateMethodPartialClass/Student1.cs
@@ -0,0 +1,13 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.DuplicateMethodPartialClass;
+
+[FluentApi]
+public partial class Student
+{
+ [FluentMember(0, "WithName")]
+ public string FirstName { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/DuplicateMethodPartialClass/Student2.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/DuplicateMethodPartialClass/Student2.cs
new file mode 100644
index 0000000..72779d5
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/DuplicateMethodPartialClass/Student2.cs
@@ -0,0 +1,12 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.DuplicateMethodPartialClass;
+
+public partial class Student
+{
+ [FluentMember(1, "WithName")]
+ public string LastName { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecord/Student.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecord/Student.cs
new file mode 100644
index 0000000..2a445ed
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecord/Student.cs
@@ -0,0 +1,12 @@
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.GetMissingSetRecord;
+
+[FluentApi]
+public record Student
+{
+ [FluentMember(0)]
+ int Semester { get; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecord/Student.fixed.txt b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecord/Student.fixed.txt
new file mode 100644
index 0000000..05955d0
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecord/Student.fixed.txt
@@ -0,0 +1,12 @@
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.GetMissingSetRecord;
+
+[FluentApi]
+public record Student
+{
+ [FluentMember(0)]
+ int Semester { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecordStruct/Student.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecordStruct/Student.cs
new file mode 100644
index 0000000..4ecadf3
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecordStruct/Student.cs
@@ -0,0 +1,12 @@
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.GetMissingSetRecordStruct;
+
+[FluentApi]
+public record struct Student
+{
+ [FluentMember(0)]
+ int Semester { get; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecordStruct/Student.fixed.txt b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecordStruct/Student.fixed.txt
new file mode 100644
index 0000000..d2bcce3
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetRecordStruct/Student.fixed.txt
@@ -0,0 +1,12 @@
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.GetMissingSetRecordStruct;
+
+[FluentApi]
+public record struct Student
+{
+ [FluentMember(0)]
+ int Semester { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetStruct/Student.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetStruct/Student.cs
new file mode 100644
index 0000000..7a287b4
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetStruct/Student.cs
@@ -0,0 +1,12 @@
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.GetMissingSetStruct;
+
+[FluentApi]
+public struct Student
+{
+ [FluentMember(0)]
+ int Semester { get; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetStruct/Student.fixed.txt b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetStruct/Student.fixed.txt
new file mode 100644
index 0000000..7309a07
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/GetMissingSetStruct/Student.fixed.txt
@@ -0,0 +1,12 @@
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.GetMissingSetStruct;
+
+[FluentApi]
+public struct Student
+{
+ [FluentMember(0)]
+ int Semester { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student1.cs
similarity index 62%
rename from src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student.cs
rename to src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student1.cs
index 8ead6aa..34824e3 100644
--- a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student.cs
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student1.cs
@@ -1,3 +1,5 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
// ReSharper disable All
using M31.FluentApi.Attributes;
@@ -8,5 +10,5 @@ namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.PartialClass;
public partial class Student
{
[FluentMember(0)]
- public int Semester { get; private set; }
+ public string FirstName { get; private set; }
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student2.cs b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student2.cs
new file mode 100644
index 0000000..91ea99a
--- /dev/null
+++ b/src/M31.FluentApi.Tests/AnalyzerAndCodeFixes/TestClasses/PartialClass/Student2.cs
@@ -0,0 +1,13 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.AnalyzerAndCodeFixes.TestClasses.PartialClass;
+
+public partial class Student
+{
+ [FluentMember(1)]
+ public string LastName { get; private set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/CodeGenerationExecutionTests.cs b/src/M31.FluentApi.Tests/CodeGeneration/CodeGenerationExecutionTests.cs
index 74bc57f..50d7b74 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/CodeGenerationExecutionTests.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/CodeGenerationExecutionTests.cs
@@ -253,6 +253,18 @@ public void CanExecuteGenericOverloadedPrivateMethodClass()
Assert.Equal(new string[] { "Called Method1(in T, ref string)" }, student7.Logs);
}
+ [Fact, Priority(1)]
+ public void CanExecutePartialClass()
+ {
+ var student = TestClasses.Abstract.PartialClass
+ .CreateStudent
+ .WithFirstName("Alice")
+ .WithLastName("King");
+
+ Assert.Equal("Alice", student.FirstName);
+ Assert.Equal("King", student.LastName);
+ }
+
[Fact, Priority(1)]
public void CanExecutePrivateConstructorClass()
{
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/Helpers/ListAndDictionary.cs b/src/M31.FluentApi.Tests/CodeGeneration/Helpers/ListAndDictionary.cs
index 37463fd..8835f1a 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/Helpers/ListAndDictionary.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/Helpers/ListAndDictionary.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
namespace M31.FluentApi.Tests.CodeGeneration.Helpers;
@@ -11,50 +12,50 @@ public class ListAndDictionary : List, IDictionary> GetEnumerator()
{
- throw new System.NotImplementedException();
+ throw new NotSupportedException();
}
public void Add(KeyValuePair item)
{
- throw new System.NotImplementedException();
+ throw new NotSupportedException();
}
public bool Contains(KeyValuePair item)
{
- throw new System.NotImplementedException();
+ throw new NotSupportedException();
}
public void CopyTo(KeyValuePair[] array, int arrayIndex)
{
- throw new System.NotImplementedException();
+ throw new NotSupportedException();
}
public bool Remove(KeyValuePair item)
{
- throw new System.NotImplementedException();
+ throw new NotSupportedException();
}
public bool IsReadOnly { get; } = false;
public void Add(TKey key, TValue value)
{
- throw new System.NotImplementedException();
+ throw new NotSupportedException();
}
public bool ContainsKey(TKey key)
{
- throw new System.NotImplementedException();
+ throw new NotSupportedException();
}
public bool TryGetValue(TKey key, out TValue value)
{
- throw new System.NotImplementedException();
+ throw new NotSupportedException();
}
public TValue this[TKey key]
{
- get => throw new System.NotImplementedException();
- set => throw new System.NotImplementedException();
+ get => throw new NotSupportedException();
+ set => throw new NotSupportedException();
}
public ICollection Keys { get; } = new List();
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClass/Address.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClass/Address.cs
new file mode 100644
index 0000000..9596251
--- /dev/null
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClass/Address.cs
@@ -0,0 +1,20 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+// ReSharper disable all
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.FluentLambdaClass;
+
+[FluentApi]
+public class Address
+{
+ [FluentMember(0)]
+ public string HouseNumber { get; set; }
+
+ [FluentMember(1)]
+ public string Street { get; set; }
+
+ [FluentMember(2, "InCity")]
+ public string City { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClass/Student.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClass/Student.cs
index 5eae71b..05c4798 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClass/Student.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClass/Student.cs
@@ -1,5 +1,6 @@
// Non-nullable member is uninitialized
#pragma warning disable CS8618
+// ReSharper disable all
using M31.FluentApi.Attributes;
@@ -13,17 +14,4 @@ public class Student
[FluentLambda(1)]
public Address Address { get; set; }
-}
-
-[FluentApi]
-public class Address
-{
- [FluentMember(0)]
- public string HouseNumber { get; set; }
-
- [FluentMember(1)]
- public string Street { get; set; }
-
- [FluentMember(2, "InCity")]
- public string City { get; set; }
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/Address.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/Address.cs
new file mode 100644
index 0000000..d2f28ec
--- /dev/null
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/Address.cs
@@ -0,0 +1,20 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+// ReSharper disable all
+
+using M31.FluentApi.Attributes;
+
+namespace SomeOtherNamespace;
+
+[FluentApi]
+public class Address
+{
+ [FluentMember(0)]
+ public string HouseNumber { get; set; }
+
+ [FluentMember(1)]
+ public string Street { get; set; }
+
+ [FluentMember(2, "InCity")]
+ public string City { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/CreateAddress.g.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/CreateAddress.g.cs
index 870b920..fbf7d47 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/CreateAddress.g.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/CreateAddress.g.cs
@@ -6,7 +6,6 @@
#nullable enable
using M31.FluentApi.Attributes;
-using SomeOtherNamespace;
namespace SomeOtherNamespace;
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/Student.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/Student.cs
index 662c79c..c9f93ab 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/Student.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaClassInDifferentNamespace/Student.cs
@@ -1,35 +1,18 @@
// Non-nullable member is uninitialized
-
#pragma warning disable CS8618
+// ReSharper disable all
using M31.FluentApi.Attributes;
using SomeOtherNamespace;
-namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.FluentLambdaClassInDifferentNamespace
-{
- [FluentApi]
- public class Student
- {
- [FluentMember(0)]
- public string Name { get; set; }
-
- [FluentLambda(1)]
- public Address Address { get; set; }
- }
-}
+namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.FluentLambdaClassInDifferentNamespace;
-namespace SomeOtherNamespace
+[FluentApi]
+public class Student
{
- [FluentApi]
- public class Address
- {
- [FluentMember(0)]
- public string HouseNumber { get; set; }
-
- [FluentMember(1)]
- public string Street { get; set; }
+ [FluentMember(0)]
+ public string Name { get; set; }
- [FluentMember(2, "InCity")]
- public string City { get; set; }
- }
+ [FluentLambda(1)]
+ public Address Address { get; set; }
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaNullablePropertyClass/Address.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaNullablePropertyClass/Address.cs
new file mode 100644
index 0000000..d82b623
--- /dev/null
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaNullablePropertyClass/Address.cs
@@ -0,0 +1,20 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+// ReSharper disable all
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.FluentLambdaNullablePropertyClass;
+
+[FluentApi]
+public class Address
+{
+ [FluentMember(0)]
+ public string HouseNumber { get; set; }
+
+ [FluentMember(1)]
+ public string Street { get; set; }
+
+ [FluentMember(2, "InCity")]
+ public string City { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaNullablePropertyClass/Student.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaNullablePropertyClass/Student.cs
index 3c18630..27ffe12 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaNullablePropertyClass/Student.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaNullablePropertyClass/Student.cs
@@ -1,5 +1,6 @@
// Non-nullable member is uninitialized
#pragma warning disable CS8618
+// ReSharper disable all
using M31.FluentApi.Attributes;
@@ -14,17 +15,4 @@ public class Student
[FluentLambda(1)]
[FluentNullable]
public Address? Address { get; set; }
-}
-
-[FluentApi]
-public class Address
-{
- [FluentMember(0)]
- public string HouseNumber { get; set; }
-
- [FluentMember(1)]
- public string Street { get; set; }
-
- [FluentMember(2, "InCity")]
- public string City { get; set; }
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaRecursiveClass/Student.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaRecursiveClass/Student.cs
index 00a8199..0769793 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaRecursiveClass/Student.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaRecursiveClass/Student.cs
@@ -1,5 +1,6 @@
// Non-nullable member is uninitialized
#pragma warning disable CS8618
+// ReSharper disable all
using M31.FluentApi.Attributes;
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaSingleStepClass/Address.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaSingleStepClass/Address.cs
new file mode 100644
index 0000000..8221382
--- /dev/null
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaSingleStepClass/Address.cs
@@ -0,0 +1,20 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+// ReSharper disable all
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.FluentLambdaSingleStepClass;
+
+[FluentApi]
+public class Address
+{
+ [FluentMember(0)]
+ public string HouseNumber { get; set; }
+
+ [FluentMember(1)]
+ public string Street { get; set; }
+
+ [FluentMember(2, "InCity")]
+ public string City { get; set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaSingleStepClass/Student.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaSingleStepClass/Student.cs
index cef0731..9b362cb 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaSingleStepClass/Student.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/FluentLambdaSingleStepClass/Student.cs
@@ -1,5 +1,6 @@
// Non-nullable member is uninitialized
#pragma warning disable CS8618
+// ReSharper disable all
using M31.FluentApi.Attributes;
@@ -10,17 +11,4 @@ public class Student
{
[FluentLambda(0)]
public Address Address { get; set; }
-}
-
-[FluentApi]
-public class Address
-{
- [FluentMember(0)]
- public string HouseNumber { get; set; }
-
- [FluentMember(1)]
- public string Street { get; set; }
-
- [FluentMember(2, "InCity")]
- public string City { get; set; }
}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/CreateStudent.expected.txt b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/CreateStudent.expected.txt
new file mode 100644
index 0000000..e7fc837
--- /dev/null
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/CreateStudent.expected.txt
@@ -0,0 +1,70 @@
+//
+// This code was generated by the library M31.FluentAPI.
+// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#nullable enable
+
+using M31.FluentApi.Attributes;
+using System.Reflection;
+
+namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.PartialClass;
+
+public class CreateStudent :
+ CreateStudent.ICreateStudent,
+ CreateStudent.IWithFirstName,
+ CreateStudent.IWithLastName
+{
+ private readonly Student student;
+ private static readonly PropertyInfo firstNamePropertyInfo;
+ private static readonly PropertyInfo lastNamePropertyInfo;
+
+ static CreateStudent()
+ {
+ firstNamePropertyInfo = typeof(Student).GetProperty("FirstName", BindingFlags.Instance | BindingFlags.Public)!;
+ lastNamePropertyInfo = typeof(Student).GetProperty("LastName", BindingFlags.Instance | BindingFlags.Public)!;
+ }
+
+ private CreateStudent()
+ {
+ student = new Student();
+ }
+
+ public static ICreateStudent InitialStep()
+ {
+ return new CreateStudent();
+ }
+
+ public static IWithLastName WithFirstName(string firstName)
+ {
+ CreateStudent createStudent = new CreateStudent();
+ CreateStudent.firstNamePropertyInfo.SetValue(createStudent.student, firstName);
+ return createStudent;
+ }
+
+ IWithLastName IWithFirstName.WithFirstName(string firstName)
+ {
+ CreateStudent.firstNamePropertyInfo.SetValue(student, firstName);
+ return this;
+ }
+
+ Student IWithLastName.WithLastName(string lastName)
+ {
+ CreateStudent.lastNamePropertyInfo.SetValue(student, lastName);
+ return student;
+ }
+
+ public interface ICreateStudent : IWithFirstName
+ {
+ }
+
+ public interface IWithFirstName
+ {
+ IWithLastName WithFirstName(string firstName);
+ }
+
+ public interface IWithLastName
+ {
+ Student WithLastName(string lastName);
+ }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/CreateStudent.g.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/CreateStudent.g.cs
new file mode 100644
index 0000000..e7fc837
--- /dev/null
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/CreateStudent.g.cs
@@ -0,0 +1,70 @@
+//
+// This code was generated by the library M31.FluentAPI.
+// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#nullable enable
+
+using M31.FluentApi.Attributes;
+using System.Reflection;
+
+namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.PartialClass;
+
+public class CreateStudent :
+ CreateStudent.ICreateStudent,
+ CreateStudent.IWithFirstName,
+ CreateStudent.IWithLastName
+{
+ private readonly Student student;
+ private static readonly PropertyInfo firstNamePropertyInfo;
+ private static readonly PropertyInfo lastNamePropertyInfo;
+
+ static CreateStudent()
+ {
+ firstNamePropertyInfo = typeof(Student).GetProperty("FirstName", BindingFlags.Instance | BindingFlags.Public)!;
+ lastNamePropertyInfo = typeof(Student).GetProperty("LastName", BindingFlags.Instance | BindingFlags.Public)!;
+ }
+
+ private CreateStudent()
+ {
+ student = new Student();
+ }
+
+ public static ICreateStudent InitialStep()
+ {
+ return new CreateStudent();
+ }
+
+ public static IWithLastName WithFirstName(string firstName)
+ {
+ CreateStudent createStudent = new CreateStudent();
+ CreateStudent.firstNamePropertyInfo.SetValue(createStudent.student, firstName);
+ return createStudent;
+ }
+
+ IWithLastName IWithFirstName.WithFirstName(string firstName)
+ {
+ CreateStudent.firstNamePropertyInfo.SetValue(student, firstName);
+ return this;
+ }
+
+ Student IWithLastName.WithLastName(string lastName)
+ {
+ CreateStudent.lastNamePropertyInfo.SetValue(student, lastName);
+ return student;
+ }
+
+ public interface ICreateStudent : IWithFirstName
+ {
+ }
+
+ public interface IWithFirstName
+ {
+ IWithLastName WithFirstName(string firstName);
+ }
+
+ public interface IWithLastName
+ {
+ Student WithLastName(string lastName);
+ }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/Student1.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/Student1.cs
new file mode 100644
index 0000000..76f664d
--- /dev/null
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/Student1.cs
@@ -0,0 +1,14 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.PartialClass;
+
+[FluentApi]
+public partial class Student
+{
+ [FluentMember(0)]
+ public string FirstName { get; private set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/Student2.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/Student2.cs
new file mode 100644
index 0000000..5e81e70
--- /dev/null
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestClasses/Abstract/PartialClass/Student2.cs
@@ -0,0 +1,13 @@
+// Non-nullable member is uninitialized
+#pragma warning disable CS8618
+// ReSharper disable All
+
+using M31.FluentApi.Attributes;
+
+namespace M31.FluentApi.Tests.CodeGeneration.TestClasses.Abstract.PartialClass;
+
+public partial class Student
+{
+ [FluentMember(1)]
+ public string LastName { get; private set; }
+}
\ No newline at end of file
diff --git a/src/M31.FluentApi.Tests/CodeGeneration/TestDataProvider.cs b/src/M31.FluentApi.Tests/CodeGeneration/TestDataProvider.cs
index 0d81de5..1025cb0 100644
--- a/src/M31.FluentApi.Tests/CodeGeneration/TestDataProvider.cs
+++ b/src/M31.FluentApi.Tests/CodeGeneration/TestDataProvider.cs
@@ -21,11 +21,11 @@ internal class TestDataProvider : IEnumerable