예제 #1
0
 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);
 }
예제 #2
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);
        }
예제 #3
0
 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);
 }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
 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}");
         }
     }
 }
예제 #7
0
        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);
        }
예제 #8
0
 static bool NeedBaseCallForFlag(this Type t, GenTaskFlags flag)
 {
     return(t.IsControllable() && t.HasBaseClassImplementingFlag(flag) && (flag != GenTaskFlags.DefaultConstructor));
 }
예제 #9
0
 public GenTaskCustomImpl(GenTaskFlags flags, bool genBaseMethods = false) : base(flags)
 {
     this.flags          = flags;
     this.genBaseMethods = genBaseMethods;
 }
예제 #10
0
        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));
            }
        }
예제 #11
0
 static GenTaskFlags ReplaceFlags(GenTaskFlags flags, GenTaskFlags from, GenTaskFlags to)
 {
     return((flags & (~from)) | to);
 }
예제 #12
0
 public GenInclude(GenTaskFlags flags)
 {
     this.flags = flags;
 }
예제 #13
0
 public GenInclude()
 {
     this.flags = GenTaskFlags.All;
 }
예제 #14
0
 public GenIgnore(GenTaskFlags flags)
 {
     this.flags = flags;
 }
예제 #15
0
 public GenIgnore()
 {
     this.flags = GenTaskFlags.All;
 }
예제 #16
0
 public GenerationTask(Type t, GenTaskFlags flags)
 {
     type       = t;
     this.flags = flags;
 }
예제 #17
0
        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);
        }
예제 #18
0
 public GenTask(GenTaskFlags flags)
 {
     this.flags = flags;
 }