diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/BaseClasses_A_BaseClass.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/BaseClasses_A_BaseClass.g.cs index a6a2214..6a3f248 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/BaseClasses_A_BaseClass.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/BaseClasses_A_BaseClass.g.cs @@ -29,6 +29,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TestCases_SetOnlyPropertyE303C8557E.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TestCases_SetOnlyPropertyE303C8557E.g.cs index 56d6f17..4464043 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TestCases_SetOnlyPropertyE303C8557E.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TestCases_SetOnlyPropertyE303C8557E.g.cs @@ -27,6 +27,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/Tests_TestCases_BaseModel6634CD33B5.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/Tests_TestCases_BaseModel6634CD33B5.g.cs index fd7f330..b290e3c 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/Tests_TestCases_BaseModel6634CD33B5.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/Tests_TestCases_BaseModel6634CD33B5.g.cs @@ -30,6 +30,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TypeRegistry.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TypeRegistry.g.cs index b2cadc3..e337014 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TypeRegistry.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/TypeRegistry.g.cs @@ -43,6 +43,7 @@ public partial class TypeRegistry : Chickensoft.Introspection.ITypeRegistry { [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.ConcreteChildOne)] = new Chickensoft.Introspection.IdentifiableTypeMetadata("ConcreteChildOne", static (r) => r.Receive(), static () => System.Activator.CreateInstance(), new Chickensoft.Introspection.Generator.Tests.TestCases.ConcreteChildOne.MetatypeMetadata(), "concrete_child_one", 1), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.ConcreteChildTwo)] = new Chickensoft.Introspection.IdentifiableTypeMetadata("ConcreteChildTwo", static (r) => r.Receive(), static () => System.Activator.CreateInstance(), new Chickensoft.Introspection.Generator.Tests.TestCases.ConcreteChildTwo.MetatypeMetadata(), "concrete_child_two", 1), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.DerivedModel)] = new Chickensoft.Introspection.IntrospectiveTypeMetadata("DerivedModel", static (r) => r.Receive(), static () => System.Activator.CreateInstance(), new Chickensoft.Introspection.Generator.Tests.TestCases.DerivedModel.MetatypeMetadata(), 1), + [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.GenericStruct<>)] = new Chickensoft.Introspection.TypeMetadata("GenericStruct"), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.InitArgsModel)] = new Chickensoft.Introspection.IdentifiableTypeMetadata("InitArgsModel", static (r) => r.Receive(), static () => System.Activator.CreateInstance(), new Chickensoft.Introspection.Generator.Tests.TestCases.InitArgsModel.MetatypeMetadata(), "init_args_model", 1), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.JunkAttribute)] = new Chickensoft.Introspection.ConcreteTypeMetadata("JunkAttribute", static (r) => r.Receive(), static () => System.Activator.CreateInstance()), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.MyContainerClass)] = new Chickensoft.Introspection.ConcreteTypeMetadata("MyContainerClass", static (r) => r.Receive(), static () => System.Activator.CreateInstance()), @@ -51,6 +52,7 @@ public partial class TypeRegistry : Chickensoft.Introspection.ITypeRegistry { [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.MyType<>)] = new Chickensoft.Introspection.TypeMetadata("MyType"), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.NameOfId)] = new Chickensoft.Introspection.IdentifiableTypeMetadata("NameOfId", static (r) => r.Receive(), static () => System.Activator.CreateInstance(), new Chickensoft.Introspection.Generator.Tests.TestCases.NameOfId.MetatypeMetadata(), "NameOfId", 1), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.NoId)] = new Chickensoft.Introspection.IntrospectiveTypeMetadata("NoId", static (r) => r.Receive(), static () => System.Activator.CreateInstance(), new Chickensoft.Introspection.Generator.Tests.TestCases.NoId.MetatypeMetadata(), 1), + [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.NullablePropertyTypes)] = new Chickensoft.Introspection.IntrospectiveTypeMetadata("NullablePropertyTypes", static (r) => r.Receive(), static () => System.Activator.CreateInstance(), new Chickensoft.Introspection.Generator.Tests.TestCases.NullablePropertyTypes.MetatypeMetadata(), 1), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.One.Two)] = new Chickensoft.Introspection.ConcreteTypeMetadata("Two", static (r) => r.Receive(), static () => System.Activator.CreateInstance()), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.One.Two.IThree.Four)] = new Chickensoft.Introspection.ConcreteTypeMetadata("Four", static (r) => r.Receive(), static () => System.Activator.CreateInstance()), [typeof(Chickensoft.Introspection.Generator.Tests.TestCases.One.Two.IThree.Four.NestedType)] = new Chickensoft.Introspection.IdentifiableTypeMetadata("NestedType", static (r) => r.Receive(), static () => System.Activator.CreateInstance(), new Chickensoft.Introspection.Generator.Tests.TestCases.One.Two.IThree.Four.NestedType.MetatypeMetadata(), "nested_type", 1), diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/_MyContainerClass_MyModel67E837FC39.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/_MyContainerClass_MyModel67E837FC39.g.cs index 35b91ce..11671f1 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/_MyContainerClass_MyModel67E837FC39.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/_MyContainerClass_MyModel67E837FC39.g.cs @@ -27,12 +27,13 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { IsRequired: false, HasDefaultValue: true, Getter: static (object obj) => ((MyModel)obj).Age, - Setter: static (object obj, object? value) => ((MyModel)obj).Age = (int)value, + Setter: static (object obj, object? value) => ((MyModel)obj).Age = (int?)value, GenericType: new GenericType( OpenType: typeof(int), ClosedType: typeof(int), + IsNullable: true, Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { @@ -51,6 +52,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/er2_DeeplyNestedBaseClassAC795ED913.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/er2_DeeplyNestedBaseClassAC795ED913.g.cs index ae3f879..afcbb22 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/er2_DeeplyNestedBaseClassAC795ED913.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/er2_DeeplyNestedBaseClassAC795ED913.g.cs @@ -31,6 +31,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/her_A_B_C_D_SomeBaseClassECA01F390E.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/her_A_B_C_D_SomeBaseClassECA01F390E.g.cs index 779f88a..fe48607 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/her_A_B_C_D_SomeBaseClassECA01F390E.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/her_A_B_C_D_SomeBaseClassECA01F390E.g.cs @@ -33,6 +33,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/or_Tests_TestCases_MyType1CDCCD6086.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/or_Tests_TestCases_MyType1CDCCD6086.g.cs index 2b44a86..2164bf5 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/or_Tests_TestCases_MyType1CDCCD6086.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/or_Tests_TestCases_MyType1CDCCD6086.g.cs @@ -34,6 +34,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -58,6 +59,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(int), ClosedType: typeof(int), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -71,20 +73,13 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { IsRequired: false, HasDefaultValue: true, Getter: static (object obj) => ((MyType)obj).OptionalFloat, - Setter: static (object obj, object? value) => ((MyType)obj).OptionalFloat = (Nullable)value, + Setter: static (object obj, object? value) => ((MyType)obj).OptionalFloat = (float?)value, GenericType: new GenericType( - OpenType: typeof(Nullable<>), - ClosedType: typeof(Nullable), - Arguments: new GenericType[] { - new GenericType( - OpenType: typeof(float), - ClosedType: typeof(float), - Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), - GenericTypeGetter2: default - ) - }, - GenericTypeGetter: static receiver => receiver.Receive>(), + OpenType: typeof(float), + ClosedType: typeof(float), + IsNullable: true, + Arguments: System.Array.Empty(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { @@ -99,12 +94,13 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { IsRequired: false, HasDefaultValue: true, Getter: static (object obj) => ((MyType)obj).OptionalInt, - Setter: static (object obj, object? value) => ((MyType)obj).OptionalInt = (int)value, + Setter: static (object obj, object? value) => ((MyType)obj).OptionalInt = (int?)value, GenericType: new GenericType( OpenType: typeof(int), ClosedType: typeof(int), + IsNullable: true, Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/s_AttributesWithNamedArgs21E465F742.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/s_AttributesWithNamedArgs21E465F742.g.cs index 9620158..74b3e05 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/s_AttributesWithNamedArgs21E465F742.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/s_AttributesWithNamedArgs21E465F742.g.cs @@ -30,6 +30,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/s_TestCases_InitArgsModel651DDFA4A7.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/s_TestCases_InitArgsModel651DDFA4A7.g.cs index 620e289..cb0acbf 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/s_TestCases_InitArgsModel651DDFA4A7.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/s_TestCases_InitArgsModel651DDFA4A7.g.cs @@ -26,12 +26,13 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { IsRequired: false, HasDefaultValue: false, Getter: static (object obj) => ((InitArgsModel)obj).Address, - Setter: static (object obj, object? value) => ((InitArgsModel)obj).Address = (string)value, + Setter: static (object obj, object? value) => ((InitArgsModel)obj).Address = (string?)value, GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: true, Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { @@ -50,6 +51,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(int), ClosedType: typeof(int), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -70,8 +72,9 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: true, Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { @@ -90,6 +93,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(InitArgsEnum), ClosedType: typeof(InitArgsEnum), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -110,6 +114,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(InitArgsEnum), ClosedType: typeof(InitArgsEnum), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -130,6 +135,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -166,7 +172,7 @@ public object Construct(System.Collections.Generic.IReadOnlyDictionary(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ses_NullablePropertyTypesC877B09C3B.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ses_NullablePropertyTypesC877B09C3B.g.cs new file mode 100644 index 0000000..b065249 --- /dev/null +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ses_NullablePropertyTypesC877B09C3B.g.cs @@ -0,0 +1,199 @@ +#pragma warning disable +#nullable enable +namespace Chickensoft.Introspection.Generator.Tests.TestCases; + +using Chickensoft.Introspection; +using Chickensoft.Introspection.Generator.Tests.TestUtils; +using System; +using System.Collections.Generic; + +partial class NullablePropertyTypes : Chickensoft.Introspection.IIntrospective { + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public Chickensoft.Introspection.MixinBlackboard MixinState { get; } = new(); + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public Chickensoft.Introspection.IMetatype Metatype => ((Chickensoft.Introspection.IIntrospectiveTypeMetadata)Chickensoft.Introspection.Types.Graph.GetMetadata(typeof(NullablePropertyTypes))).Metatype; + + public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public System.Type Type => typeof(NullablePropertyTypes); + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public bool HasInitProperties { get; } = false; + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public System.Collections.Generic.IReadOnlyList Properties { get; } = new System.Collections.Generic.List() { + new Chickensoft.Introspection.PropertyMetadata( + Name: "Age", + IsInit: false, + IsRequired: false, + HasDefaultValue: false, + Getter: static (object obj) => ((NullablePropertyTypes)obj).Age, + Setter: static (object obj, object? value) => ((NullablePropertyTypes)obj).Age = (int?)value, + GenericType: new GenericType( + OpenType: typeof(int), + ClosedType: typeof(int), + IsNullable: true, + Arguments: System.Array.Empty(), + GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter2: default + ), + Attributes: new System.Collections.Generic.Dictionary() { + [typeof(TagAttribute)] = new System.Attribute[] { + new TagAttribute("age") + } + } + ), + new Chickensoft.Introspection.PropertyMetadata( + Name: "Map", + IsInit: false, + IsRequired: false, + HasDefaultValue: false, + Getter: static (object obj) => ((NullablePropertyTypes)obj).Map, + Setter: static (object obj, object? value) => ((NullablePropertyTypes)obj).Map = (Dictionary?>?>?)value, + GenericType: new GenericType( + OpenType: typeof(Dictionary<,>), + ClosedType: typeof(Dictionary?>?>), + IsNullable: true, + Arguments: new GenericType[] { + new GenericType( + OpenType: typeof(int), + ClosedType: typeof(int), + IsNullable: false, + Arguments: System.Array.Empty(), + GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter2: default + ), + new GenericType( + OpenType: typeof(Dictionary<,>), + ClosedType: typeof(Dictionary?>), + IsNullable: true, + Arguments: new GenericType[] { + new GenericType( + OpenType: typeof(string), + ClosedType: typeof(string), + IsNullable: false, + Arguments: System.Array.Empty(), + GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter2: default + ), + new GenericType( + OpenType: typeof(List<>), + ClosedType: typeof(List), + IsNullable: true, + Arguments: new GenericType[] { + new GenericType( + OpenType: typeof(object), + ClosedType: typeof(object), + IsNullable: true, + Arguments: System.Array.Empty(), + GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter2: default + ) + }, + GenericTypeGetter: static receiver => receiver.Receive?>(), + GenericTypeGetter2: default + ) + }, + GenericTypeGetter: static receiver => receiver.Receive?>?>(), + GenericTypeGetter2: static receiver => receiver.Receive?>() + ) + }, + GenericTypeGetter: static receiver => receiver.Receive?>?>?>(), + GenericTypeGetter2: static receiver => receiver.Receive?>?>() + ), + Attributes: new System.Collections.Generic.Dictionary() { + [typeof(TagAttribute)] = new System.Attribute[] { + new TagAttribute("map") + } + } + ), + new Chickensoft.Introspection.PropertyMetadata( + Name: "Name", + IsInit: false, + IsRequired: false, + HasDefaultValue: false, + Getter: static (object obj) => ((NullablePropertyTypes)obj).Name, + Setter: static (object obj, object? value) => ((NullablePropertyTypes)obj).Name = (string?)value, + GenericType: new GenericType( + OpenType: typeof(string), + ClosedType: typeof(string), + IsNullable: true, + Arguments: System.Array.Empty(), + GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter2: default + ), + Attributes: new System.Collections.Generic.Dictionary() { + [typeof(TagAttribute)] = new System.Attribute[] { + new TagAttribute("name") + } + } + ), + new Chickensoft.Introspection.PropertyMetadata( + Name: "Nullables", + IsInit: false, + IsRequired: false, + HasDefaultValue: false, + Getter: static (object obj) => ((NullablePropertyTypes)obj).Nullables, + Setter: static (object obj, object? value) => ((NullablePropertyTypes)obj).Nullables = (GenericStruct?>?)value, + GenericType: new GenericType( + OpenType: typeof(GenericStruct<>), + ClosedType: typeof(GenericStruct?>), + IsNullable: true, + Arguments: new GenericType[] { + new GenericType( + OpenType: typeof(GenericStruct<>), + ClosedType: typeof(GenericStruct), + IsNullable: true, + Arguments: new GenericType[] { + new GenericType( + OpenType: typeof(int), + ClosedType: typeof(int), + IsNullable: true, + Arguments: System.Array.Empty(), + GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter2: default + ) + }, + GenericTypeGetter: static receiver => receiver.Receive?>(), + GenericTypeGetter2: default + ) + }, + GenericTypeGetter: static receiver => receiver.Receive?>?>(), + GenericTypeGetter2: default + ), + Attributes: new System.Collections.Generic.Dictionary() { + [typeof(TagAttribute)] = new System.Attribute[] { + new TagAttribute("map_verbose") + } + } + ) + }; + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public System.Collections.Generic.IReadOnlyDictionary Attributes { get; } = new System.Collections.Generic.Dictionary() { + [typeof(MetaAttribute)] = new System.Attribute[] { + new MetaAttribute() + } + }; + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public System.Collections.Generic.IReadOnlyList Mixins { get; } = new System.Collections.Generic.List() { + }; + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public System.Collections.Generic.IReadOnlyDictionary> MixinHandlers { get; } = new System.Collections.Generic.Dictionary>() { + }; + + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public object Construct(System.Collections.Generic.IReadOnlyDictionary? args = null) { + return new NullablePropertyTypes(); + } + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public override bool Equals(object obj) => true; + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public override int GetHashCode() => base.GetHashCode(); + } +} +#nullable restore +#pragma warning restore diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/sts_TestCases_Collections23D60571D5.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/sts_TestCases_Collections23D60571D5.g.cs index 7b52abf..08eafb4 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/sts_TestCases_Collections23D60571D5.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/sts_TestCases_Collections23D60571D5.g.cs @@ -30,14 +30,17 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(Dictionary<,>), ClosedType: typeof(Dictionary, List>>), + IsNullable: false, Arguments: new GenericType[] { new GenericType( OpenType: typeof(List<>), ClosedType: typeof(List), + IsNullable: false, Arguments: new GenericType[] { new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -49,14 +52,17 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { new GenericType( OpenType: typeof(List<>), ClosedType: typeof(List>), + IsNullable: false, Arguments: new GenericType[] { new GenericType( OpenType: typeof(List<>), ClosedType: typeof(List), + IsNullable: false, Arguments: new GenericType[] { new GenericType( OpenType: typeof(int), ClosedType: typeof(int), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ts_TestCases_DerivedModel2583598D69.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ts_TestCases_DerivedModel2583598D69.g.cs index ea77808..8384dd0 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ts_TestCases_DerivedModel2583598D69.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ts_TestCases_DerivedModel2583598D69.g.cs @@ -30,6 +30,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(int), ClosedType: typeof(int), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ts_TestCases_PartialModelED2F9C08D8.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ts_TestCases_PartialModelED2F9C08D8.g.cs index d58a770..52f2a46 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ts_TestCases_PartialModelED2F9C08D8.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/ts_TestCases_PartialModelED2F9C08D8.g.cs @@ -30,6 +30,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(int), ClosedType: typeof(int), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -50,6 +51,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/wo_IThree_Four_NestedType7FDE758058.g.cs b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/wo_IThree_Four_NestedType7FDE758058.g.cs index eb01953..4598dfb 100644 --- a/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/wo_IThree_Four_NestedType7FDE758058.g.cs +++ b/Chickensoft.Introspection.Generator.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/wo_IThree_Four_NestedType7FDE758058.g.cs @@ -38,6 +38,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -58,12 +59,13 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { IsRequired: false, HasDefaultValue: true, Getter: static (object obj) => ((NestedType)obj).OptionalFloat, - Setter: static (object obj, object? value) => ((NestedType)obj).OptionalFloat = (float)value, + Setter: static (object obj, object? value) => ((NestedType)obj).OptionalFloat = (float?)value, GenericType: new GenericType( OpenType: typeof(float), ClosedType: typeof(float), + IsNullable: true, Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { @@ -78,12 +80,13 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { IsRequired: false, HasDefaultValue: true, Getter: static (object obj) => ((NestedType)obj).OptionalInt, - Setter: static (object obj, object? value) => ((NestedType)obj).OptionalInt = (int)value, + Setter: static (object obj, object? value) => ((NestedType)obj).OptionalInt = (int?)value, GenericType: new GenericType( OpenType: typeof(int), ClosedType: typeof(int), + IsNullable: true, Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { diff --git a/Chickensoft.Introspection.Generator.Tests/test/src/models/DeclaredPropertyTest.cs b/Chickensoft.Introspection.Generator.Tests/test/src/models/DeclaredPropertyTest.cs index e17e539..0047633 100644 --- a/Chickensoft.Introspection.Generator.Tests/test/src/models/DeclaredPropertyTest.cs +++ b/Chickensoft.Introspection.Generator.Tests/test/src/models/DeclaredPropertyTest.cs @@ -17,7 +17,7 @@ public void Equality() { IsNullable: false, DefaultValueExpression: null, GenericType: new GenericTypeNode( - "System.String", Children: ImmutableArray.Empty + "System.String", false, Children: ImmutableArray.Empty ), Attributes: ImmutableArray.Empty ); @@ -36,7 +36,7 @@ public void Equality() { IsNullable: false, DefaultValueExpression: null, GenericType: new GenericTypeNode( - "System.String", Children: ImmutableArray.Empty + "System.String", false, Children: ImmutableArray.Empty ), Attributes: ImmutableArray.Empty ) @@ -51,7 +51,7 @@ public void Equality() { IsNullable: false, DefaultValueExpression: null, GenericType: new GenericTypeNode( - "System.String", Children: ImmutableArray.Empty + "System.String", false, Children: ImmutableArray.Empty ), Attributes: new DeclaredAttribute[] { new("", ImmutableArray.Empty, ImmutableArray.Empty) @@ -66,7 +66,7 @@ public void Equality() { IsNullable: false, DefaultValueExpression: null, GenericType: new GenericTypeNode( - "System.String", Children: ImmutableArray.Empty + "System.String", false, Children: ImmutableArray.Empty ), Attributes: ImmutableArray.Empty ) diff --git a/Chickensoft.Introspection.Generator.Tests/test/src/models/GenericTypeNodeTest.cs b/Chickensoft.Introspection.Generator.Tests/test/src/models/GenericTypeNodeTest.cs index f29092b..61358c9 100644 --- a/Chickensoft.Introspection.Generator.Tests/test/src/models/GenericTypeNodeTest.cs +++ b/Chickensoft.Introspection.Generator.Tests/test/src/models/GenericTypeNodeTest.cs @@ -9,7 +9,7 @@ public class GenericTypeNodeTest { [Fact] public void Equality() { var node = new GenericTypeNode( - "Type", ImmutableArray.Empty + "Type", false, ImmutableArray.Empty ); node.Equals(null).ShouldBeFalse(); diff --git a/Chickensoft.Introspection.Generator.Tests/test_cases/NullablePropertyTypes.cs b/Chickensoft.Introspection.Generator.Tests/test_cases/NullablePropertyTypes.cs new file mode 100644 index 0000000..4ff8543 --- /dev/null +++ b/Chickensoft.Introspection.Generator.Tests/test_cases/NullablePropertyTypes.cs @@ -0,0 +1,28 @@ +namespace Chickensoft.Introspection.Generator.Tests.TestCases; + +using System; +using System.Collections.Generic; +using Chickensoft.Introspection; +using Chickensoft.Introspection.Generator.Tests.TestUtils; + +public struct GenericStruct { + public T Value { get; set; } +} + +[Meta] +public partial class NullablePropertyTypes { + [Tag("name")] + public string? Name { get; set; } + + [Tag("age")] + public int? Age { get; set; } + + // All types are nullable (except dictionary keys int and string) + [Tag("map")] + public Dictionary?>?>? Map { get; set; } + +#pragma warning disable IDE0001 + [Tag("map_verbose")] + public Nullable>>> Nullables { get; set; } +#pragma warning restore IDE0001 +} diff --git a/Chickensoft.Introspection.Generator/src/TypeGenerator.cs b/Chickensoft.Introspection.Generator/src/TypeGenerator.cs index 33da474..ffe3150 100644 --- a/Chickensoft.Introspection.Generator/src/TypeGenerator.cs +++ b/Chickensoft.Introspection.Generator/src/TypeGenerator.cs @@ -531,28 +531,15 @@ TypeDeclarationSyntax type hasSetter = hasSetter || isInit; - var isNullable = - property.Type is NullableTypeSyntax || - ( - property.Type is GenericNameSyntax generic && - generic.Identifier.ValueText == "Nullable" - ); + var propType = property.Type; + + var isNullable = propType.IsNullable(); + propType = property.Type.UnwrapNullable(); var defaultValueExpression = property.Initializer?.Value.NormalizeWhitespace().ToString(); - var propType = property.Type; - - if (property.Type is NullableTypeSyntax nullableType) { - propType = nullableType.ElementType; - } - - var genericType = propType is GenericNameSyntax genericSyntax - ? GenericTypeNode.Create(genericSyntax) - : new GenericTypeNode( - Type: propType.NormalizeWhitespace().ToString(), - Children: ImmutableArray.Empty - ); + var genericType = GenericTypeNode.Create(propType, isNullable); properties.Add( new DeclaredProperty( diff --git a/Chickensoft.Introspection.Generator/src/models/DeclaredProperty.cs b/Chickensoft.Introspection.Generator/src/models/DeclaredProperty.cs index bc3786f..6ece2b7 100644 --- a/Chickensoft.Introspection.Generator/src/models/DeclaredProperty.cs +++ b/Chickensoft.Introspection.Generator/src/models/DeclaredProperty.cs @@ -37,13 +37,15 @@ public void Write(IndentedTextWriter writer, string typeSimpleNameClosed) { ? $"static (object obj) => (({typeSimpleNameClosed})obj).{Name}" : "null"; + var type = GenericType.ClosedType; + var setter = HasSetter ? ( IsInit ? "null" : $"static (object obj, object? value) => " + $"(({typeSimpleNameClosed})obj)" + - $".{Name} = ({GenericType.ClosedType}){propertyValue}" + $".{Name} = ({type}){propertyValue}" ) : "null"; diff --git a/Chickensoft.Introspection.Generator/src/models/DeclaredType.cs b/Chickensoft.Introspection.Generator/src/models/DeclaredType.cs index 4099d27..e2e22d9 100644 --- a/Chickensoft.Introspection.Generator/src/models/DeclaredType.cs +++ b/Chickensoft.Introspection.Generator/src/models/DeclaredType.cs @@ -557,10 +557,17 @@ IEnumerable baseTypes var propStrings = allProperties .Where(prop => prop.IsInit || prop.IsRequired) .Select( - (prop) => - $"{prop.Name} = args.ContainsKey(\"{prop.Name}\") " + - $"? ({prop.GenericType.ClosedType})args[\"{prop.Name}\"] : " + - $"{(prop.DefaultValueExpression is { } value ? value : $"default({prop.GenericType.ClosedType})!")}" + (prop) => { + var bang = prop.GenericType.IsNullable ? "" : "!"; + return + $"{prop.Name} = args.ContainsKey(\"{prop.Name}\") " + + $"? ({prop.GenericType.ClosedType})args[\"{prop.Name}\"] : " + + $"{( + prop.DefaultValueExpression is { } value + ? value + : $"default({prop.GenericType.ClosedType}){bang}" + )}"; + } ); writer.WriteCommaSeparatedList( diff --git a/Chickensoft.Introspection.Generator/src/models/GenericTypeNode.cs b/Chickensoft.Introspection.Generator/src/models/GenericTypeNode.cs index 299d77d..41df54f 100644 --- a/Chickensoft.Introspection.Generator/src/models/GenericTypeNode.cs +++ b/Chickensoft.Introspection.Generator/src/models/GenericTypeNode.cs @@ -15,6 +15,7 @@ namespace Chickensoft.Introspection.Generator.Models; // types that comprise it. public sealed record GenericTypeNode( string Type, + bool IsNullable, ImmutableArray Children ) { /// @@ -23,39 +24,52 @@ ImmutableArray Children /// public string ClosedType => Type + TypeReference.GetGenerics( Children.Select(child => child.ClosedType).ToImmutableArray() - ); + ) + Q; + + public string OpenType => + Type + TypeReference.GetOpenGenerics(Children.Length) + Q; + + private string Q => IsNullable ? "?" : ""; /// /// Recursively constructs a generic type node from a generic name syntax. /// - /// Generic name syntax. + /// Generic name syntax. /// Generic type node tree. - public static GenericTypeNode Create(GenericNameSyntax genericName) { - var type = genericName.Identifier.NormalizeWhitespace().ToString(); - - var children = genericName.TypeArgumentList.Arguments - .Select(arg => arg switch { - GenericNameSyntax genericNameSyntax => Create(genericNameSyntax), - _ => new GenericTypeNode( - arg.NormalizeWhitespace().ToString(), - ImmutableArray.Empty - ) + public static GenericTypeNode Create( + TypeSyntax typeSyntax, bool isNullable + ) { + isNullable = isNullable || typeSyntax.IsNullable(); + typeSyntax = typeSyntax.UnwrapNullable(); + + if (typeSyntax is not GenericNameSyntax genericNameSyntax) { + return new GenericTypeNode( + typeSyntax.NormalizeWhitespace().ToString(), + IsNullable: isNullable, + Children: ImmutableArray.Empty + ); + } + + var type = genericNameSyntax.Identifier.NormalizeWhitespace().ToString(); + + var children = genericNameSyntax.TypeArgumentList.Arguments + .Select(arg => { + typeSyntax = typeSyntax.UnwrapNullable(); + isNullable = arg.IsNullable(); + + return Create(arg, isNullable); }) .ToImmutableArray(); - return new GenericTypeNode(type, children); + return new GenericTypeNode(type, isNullable, children); } public void Write(IndentedTextWriter writer) { - var openType = Type + TypeReference.GetOpenGenerics(Children.Length); - var closedType = Type + TypeReference.GetGenerics( - Children.Select(child => child.ClosedType).ToImmutableArray() - ); - writer.WriteLine("new GenericType("); writer.Indent++; - writer.WriteLine($"OpenType: typeof({openType.TrimEnd('?')}),"); - writer.WriteLine($"ClosedType: typeof({closedType.TrimEnd('?')}),"); + writer.WriteLine($"OpenType: typeof({OpenType.TrimEnd('?')}),"); + writer.WriteLine($"ClosedType: typeof({ClosedType.TrimEnd('?')}),"); + writer.WriteLine($"IsNullable: {(IsNullable ? "true" : "false")},"); if (Children.Length > 0) { writer.WriteLine("Arguments: new GenericType[] {"); @@ -76,7 +90,7 @@ public void Write(IndentedTextWriter writer) { writer.WriteLine( "GenericTypeGetter: static receiver => " + - $"receiver.Receive<{closedType}>()," + $"receiver.Receive<{ClosedType}>()," ); if (Children.Length >= 2) { writer.WriteLine( diff --git a/Chickensoft.Introspection.Generator/src/utils/Extensions.cs b/Chickensoft.Introspection.Generator/src/utils/Extensions.cs new file mode 100644 index 0000000..e27406c --- /dev/null +++ b/Chickensoft.Introspection.Generator/src/utils/Extensions.cs @@ -0,0 +1,22 @@ +namespace Chickensoft.Introspection.Generator.Utils; + +using Microsoft.CodeAnalysis.CSharp.Syntax; + +public static class Extensions { + public static bool IsNullable(this TypeSyntax type) { + return type is NullableTypeSyntax || ( + type is GenericNameSyntax generic && + generic.Identifier.ValueText == "Nullable" + ); + } + + public static TypeSyntax UnwrapNullable(this TypeSyntax type) { + return type switch { + NullableTypeSyntax nullable => nullable.ElementType, + GenericNameSyntax generic + when generic.Identifier.ValueText == "Nullable" => + generic.TypeArgumentList.Arguments.First(), + _ => type + }; + } +} diff --git a/Chickensoft.Introspection.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/Tests_TypeGraphTest_Model4FF6A4782E.g.cs b/Chickensoft.Introspection.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/Tests_TypeGraphTest_Model4FF6A4782E.g.cs index 1803b5f..a010f1e 100644 --- a/Chickensoft.Introspection.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/Tests_TypeGraphTest_Model4FF6A4782E.g.cs +++ b/Chickensoft.Introspection.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/Tests_TypeGraphTest_Model4FF6A4782E.g.cs @@ -37,6 +37,7 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: false, Arguments: System.Array.Empty(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default diff --git a/Chickensoft.Introspection.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/erMetadataTest_ChildModelD70FB8BF24.g.cs b/Chickensoft.Introspection.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/erMetadataTest_ChildModelD70FB8BF24.g.cs index c76dd5c..8be1705 100644 --- a/Chickensoft.Introspection.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/erMetadataTest_ChildModelD70FB8BF24.g.cs +++ b/Chickensoft.Introspection.Tests/.generated/Chickensoft.Introspection.Generator/Chickensoft.Introspection.Generator.TypeGenerator/erMetadataTest_ChildModelD70FB8BF24.g.cs @@ -37,8 +37,9 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: true, Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { @@ -70,8 +71,8 @@ public object Construct(System.Collections.Generic.IReadOnlyDictionary(), GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default @@ -57,8 +58,9 @@ public class MetatypeMetadata : Chickensoft.Introspection.IMetatype { GenericType: new GenericType( OpenType: typeof(string), ClosedType: typeof(string), + IsNullable: true, Arguments: System.Array.Empty(), - GenericTypeGetter: static receiver => receiver.Receive(), + GenericTypeGetter: static receiver => receiver.Receive(), GenericTypeGetter2: default ), Attributes: new System.Collections.Generic.Dictionary() { @@ -90,7 +92,7 @@ public object Construct(System.Collections.Generic.IReadOnlyDictionary receiver.Receive(), GenericTypeGetter2: (_) => throw new NotImplementedException() diff --git a/Chickensoft.Introspection.Tests/test/models/PropertyMetadataTest.cs b/Chickensoft.Introspection.Tests/test/models/PropertyMetadataTest.cs index f672304..397ca83 100644 --- a/Chickensoft.Introspection.Tests/test/models/PropertyMetadataTest.cs +++ b/Chickensoft.Introspection.Tests/test/models/PropertyMetadataTest.cs @@ -13,7 +13,7 @@ public void Initializes() { HasDefaultValue: false, Getter: _ => "Value", Setter: (_, _) => { }, - GenericType: new GenericType(typeof(string), typeof(string), [], _ => { }, _ => { }), + GenericType: new GenericType(typeof(string), typeof(string), false, [], _ => { }, _ => { }), Attributes: [] ); diff --git a/Chickensoft.Introspection/src/models/GenericType.cs b/Chickensoft.Introspection/src/models/GenericType.cs index 616d503..4da0410 100644 --- a/Chickensoft.Introspection/src/models/GenericType.cs +++ b/Chickensoft.Introspection/src/models/GenericType.cs @@ -3,18 +3,23 @@ namespace Chickensoft.Introspection; using System; /// -/// Generic type representation. +/// Type representation. /// -/// Open generic type. -/// Closed generic type. -/// Type arguments. +/// Open generic type, if generic. Otherwise the same +/// as . +/// Closed generic type, if generic. Otherwise just the +/// plain type. +/// True if the type is nullable. +/// Type arguments, if any. /// Action which invokes the generic type -/// receiver with the generic type. +/// receiver with the type. /// Action which invokes the generic type -/// receiver with its two child generic types. +/// receiver with its two child type arguments, if present. Obviously only +/// applies to types with exactly two type parameters. public record GenericType( Type OpenType, Type ClosedType, + bool IsNullable, GenericType[] Arguments, Action GenericTypeGetter, Action? GenericTypeGetter2