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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Product>Choice generator</Product>
<Company>ALTA Software llc.</Company>
<Copyright>Copyright © 2024 ALTA Software llc.</Copyright>
<Version>2.0.0</Version>
<Version>2.1.4</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
43 changes: 30 additions & 13 deletions src/AltaSoft.Choice.Generator/Executor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,12 @@ private static SourceCodeBuilder Process(INamedTypeSymbol typeSymbol, List<IProp
{
var fieldName = p.Name.ToFieldName();

sb.Append("private ").Append(p.TypeName).Append("? ").Append(fieldName).AppendLine(";").NewLine();
sb.Append("private ").Append(p.TypeName);
if (isOnly1Property)
sb.Append(" ");
else
sb.Append("? ");
sb.Append(fieldName).AppendLine(";").NewLine();

if (p.Summary is not null)
sb.AppendSummary(p.Summary);
Expand All @@ -127,11 +132,15 @@ private static SourceCodeBuilder Process(INamedTypeSymbol typeSymbol, List<IProp

sb.AppendIfNotEmpty(p.SetterAccessibility.GetPropertyAccessibilityString()).AppendLine("set")
.OpenBracket()
.Append(fieldName).AppendLine(" = value ?? throw new InvalidOperationException(\"Choice value cannot be null\");")
.AppendLines(processedProperties.Where(x => x.Name != p.Name).Select(v => $"{v.Name.ToFieldName()} = null;"))
.Append("ChoiceType = ChoiceOf.").Append(p.Name).AppendLine(";")
.CloseBracket()
.CloseBracket();
.Append(fieldName);
if (isOnly1Property)
sb.AppendLine(" = value;");
else
sb.AppendLine(" = value ?? throw new InvalidOperationException(\"Choice value cannot be null\");");
sb.AppendLines(processedProperties.Where(x => x.Name != p.Name).Select(v => $"{v.Name.ToFieldName()} = null;"))
.Append("ChoiceType = ChoiceOf.").Append(p.Name).AppendLine(";")
.CloseBracket()
.CloseBracket();

sb.NewLine();

Expand Down Expand Up @@ -179,9 +188,12 @@ private static SourceCodeBuilder Process(INamedTypeSymbol typeSymbol, List<IProp
.AppendBlock("returns", $"<c>true</c> if <see cref=\"{p}\"/> has a value; otherwise, <c>false</c>.");

sb.AppendLine("[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]");
sb.Append("public bool ShouldSerialize").Append(p).Append("() => ").Append(p)
.AppendLine(".HasValue;")
.NewLine();
sb.Append("public bool ShouldSerialize").Append(p).Append("() => ");
if (isOnly1Property)
sb.AppendLine("true;");
else
sb.Append(p).AppendLine(".HasValue;");
sb.NewLine();
}

sb.AppendSummary("<para>Choice enumeration</para>");
Expand Down Expand Up @@ -252,7 +264,6 @@ private static bool ProcessImplicitOperators(SourceCodeBuilder sb, string typeNa

private static void ProcessMatch(SourceCodeBuilder sb, List<PropertyDetails> processedProperties)
{

sb.AppendSummary("<para>Applies the appropriate function based on the current choice type</para>");
sb.AppendTypeParamDescription("TResult", "The return type of the provided match functions");
processedProperties.ForEach(x =>
Expand All @@ -276,10 +287,13 @@ private static void ProcessMatch(SourceCodeBuilder sb, List<PropertyDetails> pro

sb.AppendLine("return ChoiceType switch")
.OpenBracket();

var isOnlyProperty = processedProperties.Count == 1;

foreach (var prop in processedProperties)
{
sb.Append($"ChoiceOf.{prop.Name} => match").Append($"{prop.Name}({prop.Name}!")
.AppendIf(prop.TypeSymbol.IsValueType, ".Value")
.AppendIf(!isOnlyProperty && prop.TypeSymbol.IsValueType, ".Value")
.AppendLine("),");
}

Expand All @@ -291,7 +305,6 @@ private static void ProcessMatch(SourceCodeBuilder sb, List<PropertyDetails> pro

private static void ProcessSwitch(SourceCodeBuilder sb, List<PropertyDetails> processedProperties)
{

sb.AppendSummary("<para>Applies the appropriate Action based on the current choice type</para>");
processedProperties.ForEach(x =>
{
Expand All @@ -314,11 +327,14 @@ private static void ProcessSwitch(SourceCodeBuilder sb, List<PropertyDetails> pr

sb.AppendLine("switch (ChoiceType)")
.OpenBracket();

var isOnlyProperty = processedProperties.Count == 1;

foreach (var prop in processedProperties)
{
sb.AppendSwitchCase($"ChoiceOf.{prop.Name}")
.Append($"match{prop.Name}({prop.Name}!")
.AppendIf(prop.TypeSymbol.IsValueType, ".Value")
.AppendIf(!isOnlyProperty && prop.TypeSymbol.IsValueType, ".Value")
.AppendLine(");")
.AppendLine("return;")
.CloseSwitchCase()
Expand All @@ -345,3 +361,4 @@ private static void ProcessSwitch(SourceCodeBuilder sb, List<PropertyDetails> pr
"System.Xml.Schema"
];
}

4 changes: 2 additions & 2 deletions tests/AltaSoft.ChoiceGenerator.Tests/ChoiceGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,9 @@ public void ImplicitConversions_ShouldConvertCorrectly()
[Fact]
public void GenerateSinglePropertyChoice()
{
var choice = SinglePropertyChoice.CreateAsValue("value");
var choice = SinglePropertyStringChoice.CreateAsValue("value");

Assert.Equal(SinglePropertyChoice.ChoiceOf.Value, choice.ChoiceType);
Assert.Equal(SinglePropertyStringChoice.ChoiceOf.Value, choice.ChoiceType);
Assert.Equal("value", choice.Value);

var matched = choice.Match(_ => "ok");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace AltaSoft.ChoiceGenerator.Tests;

[Choice]
public sealed partial class SinglePropertyChoice
public sealed partial class SinglePropertyStringChoice
{
public required partial string Value { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using AltaSoft.Choice;

namespace AltaSoft.ChoiceGenerator.Tests;

[Choice]
public sealed partial class SinglePropertyDateOnlyChoice
{
public required partial string Value { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using AltaSoft.Choice;

namespace AltaSoft.ChoiceGenerator.Tests;

[Choice]
public sealed partial class SinglePropertyIntChoice
{
public required partial int Value { get; set; }
}
Loading