static bool CanPerform(this Type t, GenTaskFlags flags) { if ((flags & GenTaskFlags.Serialization) != 0 && typeof(ISerializable).IsAssignableFrom(t)) { flags ^= GenTaskFlags.Serialization; } if ((flags & GenTaskFlags.UpdateFrom) != 0 && typeof(IUpdatableFrom <>) .MakeGenericType(t.TypeToUpdateFrom()).IsAssignableFrom(t)) { flags ^= GenTaskFlags.UpdateFrom; } if ((flags & GenTaskFlags.PooledUpdateFrom) != 0 && t.ReadGenFlags().HasFlag(GenTaskFlags.UpdateFrom)) { flags ^= GenTaskFlags.PooledUpdateFrom; } if ((flags & GenTaskFlags.PooledDeserialize) != 0 && t.ReadGenFlags().HasFlag(GenTaskFlags.Deserialize)) { flags ^= GenTaskFlags.PooledDeserialize; } if ((flags & GenTaskFlags.Hash) != 0 && typeof(IHashable).IsAssignableFrom(t)) { flags ^= GenTaskFlags.Hash; } return(flags == 0); }
public static MethodBuilder MakeGenMethod(Type type, GenTaskFlags currTask, string funcName, Type returnType, string args, bool disablebleFirstArg = false) { bool controllable = type.IsControllable(); var classSink = GenClassSink(type); var mode = controllable ? Mode.PartialClass : Mode.ExtensionMethod; var genericSuffix = mode == Mode.ExtensionMethod ? type.GenericParametersSuffix() : ""; var constraints = ""; if (genericSuffix.Length > 0) { constraints = type.GenericParametersConstraints(); } // TODO-- HACK rewrite bool IsCustomImpl = funcName.StartsWith("Base"); MethodType mType = MethodType.Instance; if (!controllable) { mType = disablebleFirstArg ? MethodType.StaticFunction : MethodType.Extension; } if (IsCustomImpl) { mType = MethodType.Instance; } else if (mode == Mode.PartialClass && type.HasBaseClassImplementingFlag(currTask)) { mType = MethodType.Override; } else if (type.IsValueType == false && mode == Mode.PartialClass && !type.IsSealed) { mType = MethodType.Virtual; } var method = classSink.Method(funcName, type, mType, returnType, args, genericSuffix, constraints); method.stubMode = stubMode; method.needBaseValCall = type.NeedBaseCallForFlag(currTask); if (mode == Mode.ExtensionMethod) { if (extensionsSignaturesGenerated.Contains(method.sig())) { method.doNotGen = true; } extensionsSignaturesGenerated.Add(method.sig()); } return(method); }
static GenTaskFlags DowngradeFlagsIfNeeded(Type t, GenTaskFlags flags, GenTaskFlags from, GenTaskFlags to) { if ((flags & (from | to)) == 0) { return(flags); } if (t.ReadGenFlags().HasFlag(from) == false) { return(ReplaceFlags(flags, from, to)); } return(flags); }
static bool HasBaseClassImplementingFlag(this Type type, GenTaskFlags flag) { var baseClass = type.BaseType; while (baseClass != null && baseClass != typeof(object)) { if ((baseClass.ReadGenFlags() & flag) != 0) { return(true); } baseClass = baseClass.BaseType; } return(false); }
static Type TopParentImplementingFlag(this Type type, GenTaskFlags flag) { Type acceptableClass = null; var baseClass = type; while (baseClass != null && baseClass != typeof(object)) { if ((baseClass.ReadGenFlags() & flag) != 0) { acceptableClass = baseClass; } baseClass = baseClass.BaseType; } return(acceptableClass); }
public static void CheckParameterlessConstructor(this Type t, GenTaskFlags flags) { if (t.IsValueType || t.GetConstructors().Length == 0) { return; } else { var constructor = t.GetConstructor(Type.EmptyTypes); if (constructor == null) { Error($"type {t} need a parameterless constructor to support {flags}"); } } }
static bool ProcessMembers(this Type type, GenTaskFlags currFlag, bool needMembersGen, Action <DataInfo> strategy) { bool hasMembers = false; foreach (var member in type.GetMembersForCodeGen(currFlag)) { member.carrierType = type; if (needMembersGen && !member.type.IsLoadableConfig()) { RequestGen(member.type, currFlag); } member.accessPrefix = type.AccessPrefixInGeneratedFunction(); strategy(member); hasMembers = true; } return(hasMembers); }
static bool NeedBaseCallForFlag(this Type t, GenTaskFlags flag) { return(t.IsControllable() && t.HasBaseClassImplementingFlag(flag) && (flag != GenTaskFlags.DefaultConstructor)); }
public GenTaskCustomImpl(GenTaskFlags flags, bool genBaseMethods = false) : base(flags) { this.flags = flags; this.genBaseMethods = genBaseMethods; }
public static void RequestGen(Type t, GenTaskFlags flags, bool allowGenericDeclRegister = false) { if (t == typeof(object)) { return; } if (t.IsPrimitive || t.IsEnum || t.IsGenericParameter || t == typeof(string) || t == typeof(byte[])) { return; } if (t.IsGenericTypeDecl() && allowGenericDeclRegister == false) { if (t.IsList() || t.IsLivableList()) { } else { return; } } GenTaskFlags registered; if (typeGenRequested.TryGetValue(t.NakedGenericDefinition(), out registered)) { if ((flags & ~registered) == 0) { return; } } if (t.IsInterface) { return; } // For list cases we need downgrade flags by element type var flagsCheckType = t; if (t.IsRef()) { return; } if (t.IsCell() || t.IsLivableSlot() || t.IsList() || t.IsArray) { var typeArg = t.FirstGenericArg(); flagsCheckType = typeArg; if (!typeArg.IsLoadableConfig()) { RequestGen(typeArg, flags); } } // Pool requests hacks flags = DowngradeFlagsIfNeeded(flagsCheckType, flags, GenTaskFlags.PooledUpdateFrom, GenTaskFlags.UpdateFrom); flags = DowngradeFlagsIfNeeded(flagsCheckType, flags, GenTaskFlags.PooledDeserialize, GenTaskFlags.Deserialize); if ((flags & (GenTaskFlags.Serialization | GenTaskFlags.UpdateFrom)) != 0) { if (t.IsArray == false) { t.CheckParameterlessConstructor(flags); } } if (t.IsControllable() && t.IsGenericType && t.IsValidType()) { genericInstances.TryGetOrNew(t.GetGenericTypeDefinition()).Add(t); } // For complex polymorphism cases if (t.IsList() == false && t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.IsControllable()) { RequestGen(t.BaseType, flags); } if (t.IsControllable()) { var generationSupportFlags = t.ReadGenFlags(); var interfaceSupportFlags = flags & ~generationSupportFlags; if (t.CanPerform(interfaceSupportFlags) == false) { Error($"Type {t} can not perform {interfaceSupportFlags} with its interfaces"); t.CanPerform(interfaceSupportFlags); // For debug. return; } flags &= ~interfaceSupportFlags; if (flags == 0) { return; } RegisterPolymorph(t); } else { if (t.IsAbstract) { Error($"Type {t} is abstract and can not be registered for flags: " + flags); } } // if (t.IsLivableGen() && t != typeof(Livable) && t.IsLivableContainer() == false) // { // var baseType = t.BaseType; // while (baseType != typeof(Livable)) // { // if (baseType.IsLivableGen() == false) // { // Error($"All ansestors of livable should have [GenLivable] tag, type {baseType} does not have one"); // return; // } // // baseType = baseType.BaseType; // } // } if (typeof(Livable).IsAssignableFrom(t) && t.IsLivableGen() == false) { Error($"type {t} is ancestor of livable but does not have [GenLivable] tag"); } if (typeGenRequested.TryGetValue(t, out registered)) { var newTasks = flags & (~registered); if (newTasks != 0) { typeGenRequested[t.NakedGenericDefinition()] = registered | flags; tasks.Push(new GenerationTask(t, newTasks)); } } else { typeGenRequested[t.NakedGenericDefinition()] = flags; tasks.Push(new GenerationTask(t, flags)); } }
static GenTaskFlags ReplaceFlags(GenTaskFlags flags, GenTaskFlags from, GenTaskFlags to) { return((flags & (~from)) | to); }
public GenInclude(GenTaskFlags flags) { this.flags = flags; }
public GenInclude() { this.flags = GenTaskFlags.All; }
public GenIgnore(GenTaskFlags flags) { this.flags = flags; }
public GenIgnore() { this.flags = GenTaskFlags.All; }
public GenerationTask(Type t, GenTaskFlags flags) { type = t; this.flags = flags; }
public static List <DataInfo> GetMembersForCodeGen(this Type type, GenTaskFlags flagRestriction = GenTaskFlags.None, bool inheretedMembers = false, bool ignoreCheck = true) { var fieldFlags = BindingFlags.Instance | BindingFlags.Public; if (type.IsControllable()) { fieldFlags |= BindingFlags.NonPublic; } if (inheretedMembers) { fieldFlags |= BindingFlags.FlattenHierarchy; } else { fieldFlags |= BindingFlags.DeclaredOnly; } var members = new List <DataInfo>(); foreach (var field in type.GetFields(fieldFlags)) { if (field.Name.Contains("<")) { continue; } if (field.Name.EndsWith("BackingField")) { continue; } var ignore = field.HasAttribute <GenIgnore>() ? field.GetCustomAttribute <GenIgnore>().flags : GenTaskFlags.None; ignore = ignore | (field.FieldType.HasAttribute <GenIgnore>() ? field.FieldType.GetCustomAttribute <GenIgnore>().flags : GenTaskFlags.None); // ignore = ignore | (field.HasAttribute<IgnoreFormatAttribute>() ? GenTaskFlags.All : GenTaskFlags.None); bool nullable = field.HasAttribute <CanBeNull>(); bool isStatic = field.HasAttribute <Immutable>(); if (nullable && field.FieldType.IsValueType) { throw new Exception("CanBeNull tag on value type is invalid on field " + field); } members.Add(new DataInfo { type = field.FieldType, baseAccess = field.Name, canBeNull = nullable, immutableData = isStatic, ingoreFlags = ignore, isPrivate = field.IsPrivate, isReadOnly = field.IsInitOnly, justData = field.HasAttribute <JustData>(), cantBeAncestor = field.HasAttribute <CantBeAncestor>(), defaultValue = ExtractDefaultValue(field), sharpMemberInfo = field }); } // Serialize properties only if GenInclude is set; foreach (var property in type.GetProperties(fieldFlags)) { GenTaskFlags flags; var forceCanBeNull = false; if (IsVectorElementProperty(property)) { flags = GenTaskFlags.All; } else if (property.GetCustomAttribute <GenInclude>() != null) { flags = property.GetCustomAttribute <GenInclude>().flags; } else { continue; } bool nullable = property.HasAttribute <CanBeNull>() || forceCanBeNull; bool isStatic = property.HasAttribute <Immutable>(); if (nullable && property.PropertyType.IsValueType) { throw new Exception("CanBeNull tag on value type is invalid on property " + property); } members.Add(new DataInfo { type = property.PropertyType, baseAccess = property.Name, canBeNull = nullable, immutableData = isStatic, ingoreFlags = ~flags, justData = property.HasAttribute <JustData>(), isPrivate = property.GetMethod.IsPrivate || (property.SetMethod != null && property.SetMethod.IsPrivate), cantBeAncestor = property.HasAttribute <CantBeAncestor>(), defaultValue = ExtractDefaultValue(property), sharpMemberInfo = property }); } // Ok then we have also a procedural members in some cases if (type.HasAttribute <HasRefId>()) { members.Add(new DataInfo { type = typeof(int), baseAccess = "Id" }); } // remove ignored members. if (ignoreCheck) { members.RemoveAll(m => (m.ingoreFlags & flagRestriction) != 0); } // Pastprocess members for some special cases foreach (var member in members) { member.realType = member.type; if (member.type.IsLivableContainer() && member.isReadOnly == false) { Error($"livable container {member} in type {type} shoud be marked readonly"); } member.insideConfigStorage = type.IsConfigStorage(); if (member.type.IsLivableSlot()) { member.canBeNull = true; } // Make cell look like usual field in codegeneration process. var isCell = member.type.IsCell(); if (isCell || member.type.IsLivableSlot()) { member.valueTransformer = n => n + ".value"; member.realType = member.type; member.type = member.type.FirstGenericArg(); member.isValueWrapper = isCell ? ValueVrapperType.Cell : ValueVrapperType.LivableSlot; } } return(members); }
public GenTask(GenTaskFlags flags) { this.flags = flags; }