Skip to content

Commit 0441f36

Browse files
author
Joanna May
authored
Merge pull request #5 from chickensoft-games/fix/set-only
fix: allow set-only properties
2 parents afbfe14 + f83b2c6 commit 0441f36

File tree

7 files changed

+93
-4
lines changed

7 files changed

+93
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#pragma warning disable
2+
#nullable enable
3+
namespace Chickensoft.Introspection.Generator.Tests.TestCases;
4+
5+
partial record class SetOnlyProperty : Chickensoft.Introspection.IIntrospective {
6+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
7+
public Chickensoft.Introspection.MixinBlackboard MixinState { get; } = new();
8+
9+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
10+
public Chickensoft.Introspection.IMetatype Metatype => ((Chickensoft.Introspection.IIntrospectiveTypeMetadata)Chickensoft.Introspection.Types.Graph.GetMetadata(typeof(SetOnlyProperty))).Metatype;
11+
12+
public class MetatypeMetadata : Chickensoft.Introspection.IMetatype {
13+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
14+
public System.Type Type => typeof(SetOnlyProperty);
15+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
16+
public bool HasInitProperties { get; } = false;
17+
18+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
19+
public System.Collections.Generic.IReadOnlyList<Chickensoft.Introspection.PropertyMetadata> Properties { get; } = new System.Collections.Generic.List<Chickensoft.Introspection.PropertyMetadata>() {
20+
new Chickensoft.Introspection.PropertyMetadata(
21+
Name: "Value",
22+
IsInit: false,
23+
IsRequired: false,
24+
Getter: null,
25+
Setter: (object obj, object? value) => ((SetOnlyProperty)obj).Value = (string)value!,
26+
GenericType: new GenericType(
27+
OpenType: typeof(string),
28+
ClosedType: typeof(string),
29+
Arguments: System.Array.Empty<GenericType>(),
30+
GenericTypeGetter: receiver => receiver.Receive<string>(),
31+
GenericTypeGetter2: default
32+
),
33+
Attributes: new System.Collections.Generic.Dictionary<System.Type, System.Attribute[]>() {
34+
}
35+
)
36+
};
37+
38+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
39+
public System.Collections.Generic.IReadOnlyDictionary<System.Type, System.Attribute[]> Attributes { get; } = new System.Collections.Generic.Dictionary<System.Type, System.Attribute[]>() {
40+
[typeof(MetaAttribute)] = new System.Attribute[] {
41+
new MetaAttribute()
42+
}
43+
};
44+
45+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
46+
public System.Collections.Generic.IReadOnlyList<System.Type> Mixins { get; } = new System.Collections.Generic.List<System.Type>() {
47+
};
48+
49+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
50+
public System.Collections.Generic.IReadOnlyDictionary<System.Type, System.Action<object>> MixinHandlers { get; } = new System.Collections.Generic.Dictionary<System.Type, System.Action<object>>() {
51+
};
52+
53+
54+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
55+
public object Construct(System.Collections.Generic.IReadOnlyDictionary<string, object?>? args = null) {
56+
throw new System.NotImplementedException("SetOnlyProperty is not instantiable.");
57+
}
58+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
59+
public override bool Equals(object obj) => true;
60+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
61+
public override int GetHashCode() => base.GetHashCode();
62+
}
63+
}
64+
#nullable restore
65+
#pragma warning restore

Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TypeRegistry.g.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public partial class TypeRegistry : Chickensoft.Introspection.ITypeRegistry {
6565
[typeof(Chickensoft.Introspection.Generator.Tests.TestCases.OuterContainer.MidContainer.ZOtherContainer)] = new Chickensoft.Introspection.ConcreteTypeMetadata("ZOtherContainer", (r) => r.Receive<Chickensoft.Introspection.Generator.Tests.TestCases.OuterContainer.MidContainer.ZOtherContainer>(), () => System.Activator.CreateInstance<Chickensoft.Introspection.Generator.Tests.TestCases.OuterContainer.MidContainer.ZOtherContainer>()),
6666
[typeof(Chickensoft.Introspection.Generator.Tests.TestCases.PartialModel)] = new Chickensoft.Introspection.IdentifiableTypeMetadata("PartialModel", (r) => r.Receive<Chickensoft.Introspection.Generator.Tests.TestCases.PartialModel>(), () => System.Activator.CreateInstance<Chickensoft.Introspection.Generator.Tests.TestCases.PartialModel>(), new Chickensoft.Introspection.Generator.Tests.TestCases.PartialModel.MetatypeMetadata(), "multiple_partial_definitions", 1),
6767
[typeof(Chickensoft.Introspection.Generator.Tests.TestCases.PropertyModel)] = new Chickensoft.Introspection.AbstractIntrospectiveTypeMetadata("PropertyModel", (r) => r.Receive<Chickensoft.Introspection.Generator.Tests.TestCases.PropertyModel>(), new Chickensoft.Introspection.Generator.Tests.TestCases.PropertyModel.MetatypeMetadata()),
68+
[typeof(Chickensoft.Introspection.Generator.Tests.TestCases.SetOnlyProperty)] = new Chickensoft.Introspection.AbstractIntrospectiveTypeMetadata("SetOnlyProperty", (r) => r.Receive<Chickensoft.Introspection.Generator.Tests.TestCases.SetOnlyProperty>(), new Chickensoft.Introspection.Generator.Tests.TestCases.SetOnlyProperty.MetatypeMetadata()),
6869
[typeof(Chickensoft.Introspection.Generator.Tests.TestCases.SomeType)] = new Chickensoft.Introspection.IntrospectiveTypeMetadata("SomeType", (r) => r.Receive<Chickensoft.Introspection.Generator.Tests.TestCases.SomeType>(), () => System.Activator.CreateInstance<Chickensoft.Introspection.Generator.Tests.TestCases.SomeType>(), new Chickensoft.Introspection.Generator.Tests.TestCases.SomeType.MetatypeMetadata(), 1),
6970
[typeof(Chickensoft.Introspection.Generator.Tests.TestCases.StaticPropertyIsSkipped)] = new Chickensoft.Introspection.IntrospectiveTypeMetadata("StaticPropertyIsSkipped", (r) => r.Receive<Chickensoft.Introspection.Generator.Tests.TestCases.StaticPropertyIsSkipped>(), () => System.Activator.CreateInstance<Chickensoft.Introspection.Generator.Tests.TestCases.StaticPropertyIsSkipped>(), new Chickensoft.Introspection.Generator.Tests.TestCases.StaticPropertyIsSkipped.MetatypeMetadata(), 1),
7071
[typeof(Chickensoft.Introspection.Generator.Tests.TestCases.TraditionalNamespace.A)] = new Chickensoft.Introspection.ConcreteTypeMetadata("A", (r) => r.Receive<Chickensoft.Introspection.Generator.Tests.TestCases.TraditionalNamespace.A>(), () => System.Activator.CreateInstance<Chickensoft.Introspection.Generator.Tests.TestCases.TraditionalNamespace.A>()),

Chickensoft.Introspection.Generator.Tests/test/src/models/DeclaredPropertyTest.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public class DeclaredPropertyTest {
1010
public void Equality() {
1111
var prop = new DeclaredProperty(
1212
Name: "Name",
13+
HasGetter: true,
1314
HasSetter: true,
1415
IsInit: false,
1516
IsRequired: false,
@@ -27,6 +28,7 @@ public void Equality() {
2728
prop.ShouldBe(
2829
new DeclaredProperty(
2930
Name: "Name",
31+
HasGetter: true,
3032
HasSetter: true,
3133
IsInit: false,
3234
IsRequired: false,
@@ -40,6 +42,7 @@ public void Equality() {
4042

4143
new DeclaredProperty(
4244
Name: "Name",
45+
HasGetter: true,
4346
HasSetter: true,
4447
IsInit: false,
4548
IsRequired: false,
@@ -53,6 +56,7 @@ public void Equality() {
5356
).ShouldNotBe(
5457
new DeclaredProperty(
5558
Name: "Name",
59+
HasGetter: true,
5660
HasSetter: true,
5761
IsInit: false,
5862
IsRequired: false,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Chickensoft.Introspection.Generator.Tests.TestCases;
2+
3+
[Meta]
4+
public abstract partial record SetOnlyProperty {
5+
// No getter.
6+
public string Value { set { } }
7+
}

Chickensoft.Introspection.Generator/src/TypeGenerator.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,11 @@ TypeDeclarationSyntax type
502502

503503
var propertyAttributes = GetAttributes(property.AttributeLists);
504504

505+
var hasGetter = property.AccessorList?.Accessors
506+
.Any(
507+
accessor => accessor.IsKind(SyntaxKind.GetAccessorDeclaration)
508+
) ?? property.ExpressionBody is not null;
509+
505510
// Never identified a situation in which the accessor list is null.
506511
var hasSetter = property.AccessorList?.Accessors
507512
.Any(
@@ -540,6 +545,7 @@ property.Type is GenericNameSyntax generic &&
540545
properties.Add(
541546
new DeclaredProperty(
542547
Name: property.Identifier.ValueText,
548+
HasGetter: hasGetter,
543549
HasSetter: hasSetter,
544550
IsInit: isInit,
545551
IsRequired: isRequired,

Chickensoft.Introspection.Generator/src/models/DeclaredProperty.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ namespace Chickensoft.Introspection.Generator.Models;
99
/// Represents a property on a metatype. Properties are opt-in and persisted.
1010
/// </summary>
1111
/// <param name="Name">Name of the </param>
12+
/// <param name="HasGetter">True if the property has a getter.</param>
1213
/// <param name="HasSetter">True if the property has a setter.</param>
1314
/// <param name="IsNullable">True if the property is nullable.</param>
1415
/// <param name="GenericType">Type of the </param>
1516
/// <param name="Attributes">Attributes applied to the </param>
1617
public sealed record DeclaredProperty(
1718
string Name,
19+
bool HasGetter,
1820
bool HasSetter,
1921
bool IsInit,
2022
bool IsRequired,
@@ -28,6 +30,10 @@ public void Write(IndentedTextWriter writer, string typeSimpleNameClosed) {
2830

2931
var propertyValue = "value" + (IsNullable ? "" : "!");
3032

33+
var getter = HasGetter
34+
? $"(object obj) => (({typeSimpleNameClosed})obj).{Name}"
35+
: "null";
36+
3137
var setter = HasSetter
3238
? (
3339
IsInit
@@ -40,9 +46,7 @@ public void Write(IndentedTextWriter writer, string typeSimpleNameClosed) {
4046
writer.WriteLine($"Name: \"{Name}\",");
4147
writer.WriteLine($"IsInit: {(IsInit ? "true" : "false")},");
4248
writer.WriteLine($"IsRequired: {(IsRequired ? "true" : "false")},");
43-
writer.WriteLine(
44-
$"Getter: (object obj) => (({typeSimpleNameClosed})obj).{Name},"
45-
);
49+
writer.WriteLine($"Getter: {getter},");
4650
writer.WriteLine($"Setter: {setter},");
4751
writer.Write("GenericType: ");
4852
GenericType.Write(writer);
@@ -64,6 +68,7 @@ public void Write(IndentedTextWriter writer, string typeSimpleNameClosed) {
6468
public bool Equals(DeclaredProperty? other) =>
6569
other is not null &&
6670
Name == other.Name &&
71+
HasGetter == other.HasGetter &&
6772
HasSetter == other.HasSetter &&
6873
IsInit == other.IsInit &&
6974
IsNullable == other.IsNullable &&
@@ -72,6 +77,7 @@ other is not null &&
7277

7378
public override int GetHashCode() => HashCode.Combine(
7479
Name,
80+
HasGetter,
7581
HasSetter,
7682
IsInit,
7783
IsNullable,

Chickensoft.Introspection/src/models/PropertyMetadata.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public sealed record PropertyMetadata(
2121
string Name,
2222
bool IsInit,
2323
bool IsRequired,
24-
Func<object, object?> Getter,
24+
Func<object, object?>? Getter,
2525
Action<object, object?>? Setter,
2626
GenericType GenericType,
2727
Dictionary<Type, Attribute[]> Attributes

0 commit comments

Comments
 (0)