Skip to content

Commit 1f2bbe7

Browse files
committed
Smart enum ctor should ignore abstract properties.
1 parent 11671fe commit 1f2bbe7

File tree

5 files changed

+80
-7
lines changed

5 files changed

+80
-7
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<Copyright>(c) $([System.DateTime]::Now.Year), Pawel Gerr. All rights reserved.</Copyright>
5-
<VersionPrefix>7.3.0</VersionPrefix>
5+
<VersionPrefix>7.4.0</VersionPrefix>
66
<Authors>Pawel Gerr</Authors>
77
<GenerateDocumentationFile>true</GenerateDocumentationFile>
88
<PackageProjectUrl>https://github.com/PawelGerr/Thinktecture.Runtime.Extensions</PackageProjectUrl>

src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/InstanceMemberInfo.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public sealed class InstanceMemberInfo : IMemberState, IEquatable<InstanceMember
1313
public string Name { get; }
1414
public bool IsStatic { get; }
1515
public bool IsErroneous { get; }
16+
public bool IsAbstract { get; }
1617
public ValueObjectMemberSettings ValueObjectMemberSettings { get; }
1718

1819
public SpecialType SpecialType => _typedMemberState.SpecialType;
@@ -35,14 +36,16 @@ private InstanceMemberInfo(
3536
string name,
3637
(IFieldSymbol?, IPropertySymbol?) symbol,
3738
bool isStatic,
38-
bool isErroneous)
39+
bool isErroneous,
40+
bool isAbstract)
3941
{
4042
_typedMemberState = typedMemberState;
4143
_symbol = symbol;
4244

4345
Name = name;
4446
IsStatic = isStatic;
4547
IsErroneous = isErroneous;
48+
IsAbstract = isAbstract;
4649
ValueObjectMemberSettings = settings;
4750
}
4851

@@ -58,7 +61,7 @@ private InstanceMemberInfo(
5861
var symbol = allowedCaptureSymbols ? field : null;
5962
var settings = populateValueObjectMemberSettings ? ValueObjectMemberSettings.Create(field, field.Type, allowedCaptureSymbols) : ValueObjectMemberSettings.None;
6063

61-
return new(factory.Create(field.Type), settings, field.Name, (symbol, null), field.IsStatic, field.Type.TypeKind == TypeKind.Error);
64+
return new(factory.Create(field.Type), settings, field.Name, (symbol, null), field.IsStatic, field.Type.TypeKind == TypeKind.Error, field.IsAbstract);
6265
}
6366

6467
public static InstanceMemberInfo? CreateOrNull(
@@ -73,7 +76,7 @@ private InstanceMemberInfo(
7376
var symbol = allowedCaptureSymbols ? property : null;
7477
var settings = populateValueObjectMemberSettings ? ValueObjectMemberSettings.Create(property, property.Type, allowedCaptureSymbols) : ValueObjectMemberSettings.None;
7578

76-
return new(factory.Create(property.Type), settings, property.Name, (null, symbol), property.IsStatic, property.Type.TypeKind == TypeKind.Error);
79+
return new(factory.Create(property.Type), settings, property.Name, (null, symbol), property.IsStatic, property.Type.TypeKind == TypeKind.Error, property.IsAbstract);
7780
}
7881

7982
public Location? GetIdentifierLocation(CancellationToken cancellationToken)
@@ -113,6 +116,7 @@ public bool Equals(InstanceMemberInfo? other)
113116
&& Name == other.Name
114117
&& IsStatic == other.IsStatic
115118
&& IsErroneous == other.IsErroneous
119+
&& IsAbstract == other.IsAbstract
116120
&& ValueObjectMemberSettings.Equals(other.ValueObjectMemberSettings);
117121
}
118122

@@ -124,6 +128,7 @@ public override int GetHashCode()
124128
hashCode = (hashCode * 397) ^ Name.GetHashCode();
125129
hashCode = (hashCode * 397) ^ IsStatic.GetHashCode();
126130
hashCode = (hashCode * 397) ^ IsErroneous.GetHashCode();
131+
hashCode = (hashCode * 397) ^ IsAbstract.GetHashCode();
127132
hashCode = (hashCode * 397) ^ ValueObjectMemberSettings.GetHashCode();
128133

129134
return hashCode;

src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumCodeGenerator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,7 @@ private void GenerateCreateInvalidItem(IMemberState keyProperty)
920920
private void GenerateConstructors()
921921
{
922922
var ownCtorArgs = _state.AssignableInstanceFieldsAndProperties
923+
.Where(p => !p.IsAbstract)
923924
.Select(a => new ConstructorArgument(a.TypeFullyQualifiedWithNullability, a.ArgumentName))
924925
.ToList();
925926

@@ -1124,7 +1125,7 @@ private void GenerateConstructor(
11241125
this.IsValid = isValid;");
11251126
}
11261127

1127-
foreach (var memberInfo in _state.AssignableInstanceFieldsAndProperties)
1128+
foreach (var memberInfo in _state.AssignableInstanceFieldsAndProperties.Where(p => !p.IsAbstract))
11281129
{
11291130
_sb.Append(@"
11301131
this.").Append(memberInfo.Name).Append(" = ").Append(memberInfo.ArgumentName.Escaped).Append(";");

test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6450,4 +6450,64 @@ void AddItem(global::Thinktecture.Tests.TestEnum item, string itemName)
64506450

64516451
""");
64526452
}
6453+
6454+
[Fact]
6455+
public void Should_generate_class_with_abstract_property()
6456+
{
6457+
var source = """
6458+
using System;
6459+
6460+
namespace Thinktecture.Tests
6461+
{
6462+
[SmartEnum<string>]
6463+
public abstract partial class TestEnum
6464+
{
6465+
public static readonly TestEnum Item1 = null!;
6466+
public static readonly TestEnum Item2 = null!;
6467+
6468+
public abstract int Value { get; }
6469+
6470+
private sealed class ConcreteEnum : TestEnum
6471+
{
6472+
public override int Value => 100;
6473+
6474+
public ConcreteEnum(int key)
6475+
: base(key)
6476+
{
6477+
}
6478+
}
6479+
}
6480+
}
6481+
""";
6482+
var outputs = GetGeneratedOutputs<SmartEnumSourceGenerator>(source, typeof(IEnum<>).Assembly);
6483+
outputs.Should().HaveCount(6);
6484+
6485+
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
6486+
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
6487+
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
6488+
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.ComparisonOperators.g.cs")).Value;
6489+
var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
6490+
var derivedTypes = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.DerivedTypes.g.cs")).Value;
6491+
6492+
AssertOutput(mainOutput, _MAIN_OUTPUT_STRING_BASED_CLASS);
6493+
AssertOutput(comparableOutput, _COMPARABLE_OUTPUT_CLASS_STRING_BASED);
6494+
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_CLASS_STRING_BASED);
6495+
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_OUTPUT_CLASS_STRING_BASED);
6496+
AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_CLASS);
6497+
AssertOutput(derivedTypes, _GENERATED_HEADER + """
6498+
6499+
namespace Thinktecture.Tests;
6500+
6501+
partial class TestEnum
6502+
{
6503+
[global::System.Runtime.CompilerServices.ModuleInitializer]
6504+
internal static void DerivedTypesModuleInit()
6505+
{
6506+
var enumType = typeof(global::Thinktecture.Tests.TestEnum);
6507+
global::Thinktecture.Internal.KeyedValueObjectMetadataLookup.AddDerivedType(enumType, typeof(global::Thinktecture.Tests.TestEnum.ConcreteEnum));
6508+
}
6509+
}
6510+
6511+
""");
6512+
}
64536513
}

test/Thinktecture.Runtime.Extensions.Tests.Shared/TestEnums/AbstractEnum.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ namespace Thinktecture.Runtime.Tests.TestEnums;
33
[SmartEnum<int>(IsValidatable = true)]
44
public abstract partial class AbstractEnum
55
{
6-
public static readonly AbstractEnum Item = new ValidItem(1);
6+
public static readonly AbstractEnum Item = new ValidItem(1, 200);
7+
8+
public abstract int Value { get; }
79

810
private static AbstractEnum CreateInvalidItem(int key)
911
{
@@ -12,6 +14,8 @@ private static AbstractEnum CreateInvalidItem(int key)
1214

1315
private sealed class InvalidItem : AbstractEnum
1416
{
17+
public override int Value => 100;
18+
1519
public InvalidItem(int key)
1620
: base(key, false)
1721
{
@@ -20,9 +24,12 @@ public InvalidItem(int key)
2024

2125
private sealed class ValidItem : AbstractEnum
2226
{
23-
public ValidItem(int key)
27+
public override int Value { get; }
28+
29+
public ValidItem(int key, int value)
2430
: base(key)
2531
{
32+
Value = value;
2633
}
2734
}
2835
}

0 commit comments

Comments
 (0)