From 86db6864f18af3a9c17e822637bf5c45c6fc9753 Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Sun, 3 Apr 2022 02:19:00 +0300 Subject: [PATCH] Nullable Attributes --- Esiur/Data/NullableAttribute.cs | 5 +- Esiur/Data/RepresentationType.cs | 101 ++++++++++++++-- Esiur/Data/TransmissionType.cs | 7 +- Esiur/Esiur.csproj | 2 +- Esiur/Resource/Template/TypeTemplate.cs | 146 ++++++++++++++++++------ 5 files changed, 213 insertions(+), 48 deletions(-) diff --git a/Esiur/Data/NullableAttribute.cs b/Esiur/Data/NullableAttribute.cs index ac8fde7..3bba156 100644 --- a/Esiur/Data/NullableAttribute.cs +++ b/Esiur/Data/NullableAttribute.cs @@ -13,11 +13,12 @@ public sealed class NullableAttribute : Attribute { public readonly byte[] Flags; - public readonly byte Flag; + //public readonly byte Flag; public NullableAttribute(byte flag) { - Flag = flag;// new byte[] { flag }; + //Flag = flag; + Flags = new byte[] { flag }; } public NullableAttribute(byte[] flags) { diff --git a/Esiur/Data/RepresentationType.cs b/Esiur/Data/RepresentationType.cs index 0d355ad..c10d142 100644 --- a/Esiur/Data/RepresentationType.cs +++ b/Esiur/Data/RepresentationType.cs @@ -5,6 +5,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Dynamic; +using System.Linq; using System.Text; namespace Esiur.Data @@ -50,6 +51,84 @@ namespace Esiur.Data public class RepresentationType { + + static RepresentationTypeIdentifier[] refTypes = new RepresentationTypeIdentifier[] + { + RepresentationTypeIdentifier.Dynamic, + RepresentationTypeIdentifier.RawData, + RepresentationTypeIdentifier.String, + RepresentationTypeIdentifier.Resource, + RepresentationTypeIdentifier.Record, + RepresentationTypeIdentifier.Map, + RepresentationTypeIdentifier.List, + RepresentationTypeIdentifier.TypedList, + RepresentationTypeIdentifier.TypedMap, + RepresentationTypeIdentifier.Tuple2, + RepresentationTypeIdentifier.Tuple3, + RepresentationTypeIdentifier.Tuple4, + RepresentationTypeIdentifier.Tuple5, + RepresentationTypeIdentifier.Tuple6, + RepresentationTypeIdentifier.Tuple7, + RepresentationTypeIdentifier.TypedRecord, + RepresentationTypeIdentifier.TypedResource + }; + + public void SetNull(List flags) + { + if (refTypes.Contains(Identifier)) + { + Nullable = (flags.FirstOrDefault() == 2); + if (flags.Count > 0) + flags.RemoveAt(0); + } + + foreach (var st in SubTypes) + st.SetNull(flags); + } + + public void SetNull(byte flag) + { + if (refTypes.Contains(Identifier)) + { + Nullable = (flag == 2); + } + + foreach (var st in SubTypes) + st.SetNull(flag); + } + + + public void SetNotNull(List flags) + { + if (refTypes.Contains(Identifier)) + { + Nullable = (flags.FirstOrDefault() != 1); + if (flags.Count > 0) + flags.RemoveAt(0); + } + + foreach (var st in SubTypes) + st.SetNotNull(flags); + } + + + public override string ToString() + { + if (SubTypes != null && SubTypes.Length > 0) + return Identifier.ToString() + "<" + String.Join(",", SubTypes.Select(x => x.ToString())) + ">" + (Nullable ? "?" : ""); + return Identifier.ToString() + (Nullable ? "?" : ""); + } + public void SetNotNull(byte flag) + { + if (refTypes.Contains(Identifier)) + { + Nullable = (flag != 1); + } + + foreach (var st in SubTypes) + st.SetNotNull(flag); + } + public Type? GetRuntimeType() { return Identifier switch @@ -89,21 +168,21 @@ namespace Esiur.Data public RepresentationType?[] SubTypes = new RepresentationType[3]; - public static RepresentationType? FromType(Type type, bool forceNullable = false) + public static RepresentationType? FromType(Type type)//, bool forceNullable = false) { - var nullable = forceNullable; + var nullable = false;// = forceNullable; - if (!forceNullable) + //if (!forceNullable) + //{ + var nullType = System.Nullable.GetUnderlyingType(type); + + if (nullType != null) { - var nullType = System.Nullable.GetUnderlyingType(type); - - if (nullType != null) - { - type = nullType; - nullable = true; - } + type = nullType; + nullable = true; } + //} if (type.IsGenericType) { @@ -167,7 +246,7 @@ namespace Esiur.Data { var args = type.GetGenericArguments(); var subTypes = new RepresentationType[args.Length]; - for(var i = 0; i < args.Length; i++) + for (var i = 0; i < args.Length; i++) { subTypes[i] = FromType(args[i]); if (subTypes[i] == null) diff --git a/Esiur/Data/TransmissionType.cs b/Esiur/Data/TransmissionType.cs index d016c4a..1ff3584 100644 --- a/Esiur/Data/TransmissionType.cs +++ b/Esiur/Data/TransmissionType.cs @@ -222,7 +222,7 @@ public struct TransmissionType ulong cl = (ulong)(1 << (exp -1)); if (ends - offset < cl) - return (ends - offset - (uint)cl, null); + return (cl - (ends - offset), null); //offset += (uint)cl; @@ -233,13 +233,16 @@ public struct TransmissionType ulong cll = (ulong)(h >> 3) & 0x7; if (ends - offset < cll) - return (ends - offset - (uint)cll, null); + return (cll - (ends - offset), null); ulong cl = 0; for (uint i = 0; i < cll; i++) cl = cl << 8 | data[offset++]; + if (ends - offset < cl) + return (cl - (ends - offset), null); + return (1 + cl + cll, new TransmissionType((TransmissionTypeIdentifier)(h & 0xC7), cls, h & 0x7, offset, cl)); } } diff --git a/Esiur/Esiur.csproj b/Esiur/Esiur.csproj index d91b6ce..662ed8d 100644 --- a/Esiur/Esiur.csproj +++ b/Esiur/Esiur.csproj @@ -6,7 +6,7 @@ Ahmed Kh. Zamil http://www.esiur.com true - 2.2.1 + 2.2.2 https://github.com/esiur/esiur-dotnet Ahmed Kh. Zamil diff --git a/Esiur/Resource/Template/TypeTemplate.cs b/Esiur/Resource/Template/TypeTemplate.cs index 5ca9e73..bdb9d9a 100644 --- a/Esiur/Resource/Template/TypeTemplate.cs +++ b/Esiur/Resource/Template/TypeTemplate.cs @@ -239,8 +239,8 @@ public class TypeTemplate foreach (var f in tmp.functions) { var functionReturnTypes = GetDistributedTypes(f.MethodInfo.ReturnType); - //.Select(x => Warehouse.GetTemplateByType(x)) - //.Where(x => x != null && !bag.Contains(x)) + //.Select(x => Warehouse.GetTemplateByType(x)) + //.Where(x => x != null && !bag.Contains(x)) foreach (var functionReturnType in functionReturnTypes) { @@ -394,7 +394,8 @@ public class TypeTemplate bool classIsPublic = type.IsEnum || (type.GetCustomAttribute() != null); - var addConstant = (FieldInfo ci, PublicAttribute publicAttr) => { + var addConstant = (FieldInfo ci, PublicAttribute publicAttr) => + { var annotationAttr = ci.GetCustomAttribute(true); var nullableAttr = ci.GetCustomAttribute(true); @@ -416,16 +417,35 @@ public class TypeTemplate var addProperty = (PropertyInfo pi, PublicAttribute publicAttr) => { - var annotationAttr = pi.GetCustomAttribute(true); - var storageAttr = pi.GetCustomAttribute(true); - var nullableAttr = pi.GetCustomAttribute(true); + var propType = RepresentationType.FromType(pi.PropertyType);//, nullableAttr != null && nullableAttr.Flag == 2); - var attrType = RepresentationType.FromType(pi.PropertyType, nullableAttr != null && nullableAttr.Flag == 2); - - if (attrType == null) + if (propType == null) throw new Exception($"Unsupported type `{pi.PropertyType}` in property `{type.Name}.{pi.Name}`"); - var pt = new PropertyTemplate(this, (byte)properties.Count, publicAttr?.Name ?? pi.Name, pi.DeclaringType != type, attrType); + var annotationAttr = pi.GetCustomAttribute(true); + var storageAttr = pi.GetCustomAttribute(true); + + var nullableContextAttr = pi.GetCustomAttribute(true); + var nullableAttr = pi.GetCustomAttribute(true); + + var flags = nullableAttr?.Flags?.ToList() ?? new List(); + + if (nullableContextAttr?.Flag == 2) + { + if (flags.Count == 1) + propType.SetNotNull(flags.FirstOrDefault()); + else + propType.SetNotNull(flags); + } + else + { + if (flags.Count == 1) + propType.SetNull(flags.FirstOrDefault()); + else + propType.SetNull(flags); + } + + var pt = new PropertyTemplate(this, (byte)properties.Count, publicAttr?.Name ?? pi.Name, pi.DeclaringType != type, propType); if (storageAttr != null) pt.Recordable = storageAttr.Mode == StorageMode.Recordable; @@ -436,28 +456,44 @@ public class TypeTemplate pt.ReadExpansion = GetTypeAnnotationName(pi.PropertyType); pt.PropertyInfo = pi; - + properties.Add(pt); }; var addEvent = (EventInfo ei, PublicAttribute publicAttr) => { + var argType = ei.EventHandlerType.GenericTypeArguments[0]; + var evtType = RepresentationType.FromType(argType);//, argIsNull); + + if (evtType == null) + throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`"); var annotationAttr = ei.GetCustomAttribute(true); var listenableAttr = ei.GetCustomAttribute(true); var nullableAttr = ei.GetCustomAttribute(true); + var nullableContextAttr = ei.GetCustomAttribute(true); - var argIsNull = nullableAttr != null && - nullableAttr.Flags != null && - nullableAttr.Flags.Length > 1 && - nullableAttr.Flags[1] == 2; + var flags = nullableAttr?.Flags?.ToList() ?? new List(); - var argType = ei.EventHandlerType.GenericTypeArguments[0]; - var evtType = RepresentationType.FromType(argType, argIsNull); + // skip the eventHandler class + if (flags.Count > 1) + flags = flags.Skip(1).ToList(); - if (evtType == null) - throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`"); + if (nullableContextAttr?.Flag == 2) + { + if (flags.Count == 1) + evtType.SetNotNull(flags.FirstOrDefault()); + else + evtType.SetNotNull(flags); + } + else + { + if (flags.Count == 1) + evtType.SetNull(flags.FirstOrDefault()); + else + evtType.SetNull(flags); + } var et = new EventTemplate(this, (byte)events.Count, publicAttr?.Name ?? ei.Name, ei.DeclaringType != type, evtType); et.EventInfo = ei; @@ -471,7 +507,7 @@ public class TypeTemplate events.Add(et); }; - var addAttribute = (PropertyInfo pi, AttributeAttribute attributeAttr)=> + var addAttribute = (PropertyInfo pi, AttributeAttribute attributeAttr) => { var an = attributeAttr.Name ?? pi.Name; var at = new AttributeTemplate(this, 0, an, pi.DeclaringType != type); @@ -482,17 +518,43 @@ public class TypeTemplate var addFunction = (MethodInfo mi, PublicAttribute publicAttr) => { + + var rtType = RepresentationType.FromType(mi.ReturnType); + + if (rtType == null) + throw new Exception($"Unsupported type `{mi.ReturnType}` in method `{type.Name}.{mi.Name}` return"); + var annotationAttr = mi.GetCustomAttribute(true); var nullableAttr = mi.GetCustomAttribute(true); var nullableContextAttr = mi.GetCustomAttribute(true); - var contextIsNull = nullableContextAttr != null && nullableContextAttr.Flag == 2; + var flags = nullableAttr?.Flags?.ToList() ?? new List(); - var returnType = RepresentationType.FromType(mi.ReturnType, - nullableAttr != null ? nullableAttr.Flag == 2 : contextIsNull); + var rtNullableAttr = mi.ReturnTypeCustomAttributes.GetCustomAttributes(typeof(NullableAttribute), true).FirstOrDefault() as NullableAttribute; + var rtNullableContextAttr = mi.ReturnTypeCustomAttributes + .GetCustomAttributes(typeof(NullableContextAttribute), true) + .FirstOrDefault() as NullableContextAttribute + ?? nullableContextAttr; - if (returnType == null) - throw new Exception($"Unsupported type `{mi.ReturnType}` in method `{type.Name}.{mi.Name}` return"); + var rtFlags = rtNullableAttr?.Flags?.ToList() ?? new List(); + + + + + if (rtNullableContextAttr?.Flag == 2) + { + if (rtFlags.Count == 1) + rtType.SetNotNull(rtFlags.FirstOrDefault()); + else + rtType.SetNotNull(rtFlags); + } + else + { + if (rtFlags.Count == 1) + rtType.SetNull(rtFlags.FirstOrDefault()); + else + rtType.SetNull(rtFlags); + } var args = mi.GetParameters(); @@ -504,15 +566,33 @@ public class TypeTemplate var arguments = args.Select(x => { - var xNullableAttr = x.GetCustomAttribute(true); - var xNullableContextAttr = x.GetCustomAttribute(true); - - var argType = RepresentationType.FromType(x.ParameterType, - xNullableAttr != null ? xNullableAttr.Flag == 2 : contextIsNull); + var argType = RepresentationType.FromType(x.ParameterType); if (argType == null) throw new Exception($"Unsupported type `{x.ParameterType}` in method `{type.Name}.{mi.Name}` parameter `{x.Name}`"); + + var argNullableAttr = x.GetCustomAttribute(true); + var argNullableContextAttr = x.GetCustomAttribute(true) ?? nullableContextAttr; + + var argFlags = argNullableAttr?.Flags?.ToList() ?? new List(); + + + if (argNullableContextAttr?.Flag == 2) + { + if (argFlags.Count == 1) + argType.SetNotNull(argFlags.FirstOrDefault()); + else + argType.SetNotNull(argFlags); + } + else + { + if (rtFlags.Count == 1) + argType.SetNull(argFlags.FirstOrDefault()); + else + argType.SetNull(argFlags); + } + return new ArgumentTemplate() { Name = x.Name, @@ -525,7 +605,7 @@ public class TypeTemplate var fn = publicAttr.Name ?? mi.Name; - var ft = new FunctionTemplate(this, (byte)functions.Count, fn, mi.DeclaringType != type, arguments, returnType);// mi.ReturnType == typeof(void)); + var ft = new FunctionTemplate(this, (byte)functions.Count, fn, mi.DeclaringType != type, arguments, rtType); if (annotationAttr != null) ft.Expansion = annotationAttr.Annotation; @@ -535,6 +615,8 @@ public class TypeTemplate ft.MethodInfo = mi; functions.Add(ft); + Console.WriteLine(rtType.ToString() + " " + fn); + }; @@ -583,7 +665,7 @@ public class TypeTemplate if (privateAttr != null) continue; - var publicAttr = ei.GetCustomAttribute(true); + var publicAttr = ei.GetCustomAttribute(true); addEvent(ei, publicAttr); }