예제 #1
0
 public MethodBuilder(SharpClassBuilder classBuilder, Type classType, string name, MethodType type, Type returnType, string args, string genericSuffix, string constraints)
 {
     this.classBuilder  = classBuilder;
     this.name          = name;
     this.type          = type;
     this.returnType    = returnType;
     this.args          = args;
     this.genericSuffix = genericSuffix;
     this.constraints   = constraints;
     this.classType     = classType;
 }
        static void GenPolymorphMaps(Type baseClass, List <Type> typesThatCanBeConstructed,
                                     List <Type> typesToGenPolymorphMethods, SharpClassBuilder sink, bool pooledMap)
        {
            // Class id overloaded functions
            foreach (var type in typesToGenPolymorphMethods)
            {
                if (type.ReadGenCustomFlags() == type.ReadGenFlags())
                {
                    continue;
                }

                var tSink = GenClassSink(type);

                var mType = type == baseClass ? MethodType.Virtual : MethodType.Override;

                var pooled = type.HasPool() && pooledMap;

                var newInstOfSameType = tSink.Method(PolymorphNewInstOfSameType, type, mType, baseClass,
                                                     pooledMap ? $"{PoolTypeName(null)} pool" : "");

                newInstOfSameType.doNotCallBaseMethod = true;

                if (type.IsAbstract)
                {
                    newInstOfSameType.content("throw new NotImplementedException();");
                }
                else if (type.IsGenericTypeDecl() && pooled)
                {
                    var genericPoolGetter = tSink.Method(GenericPoolGetter, type, MethodType.Instance,
                                                         typeof(IGenericPool), type.OptPoolArgDecl(type.HasPool()));
                    PrintGenericSwitch(type, genericPoolGetter,
                                       (t, s) => s.content($"return pool.{t.PersonalPoolName()};"));
                    genericPoolGetter.content("return null;");
                    newInstOfSameType.content(
                        $"return ({type.RealName()}){GenericPoolGetter}(pool).PopGeneric();");
                }
                else if (pooled)
                {
                    newInstOfSameType.content($"return pool.{type.GetFromPoolFunc()}();");
                }
                else
                {
                    newInstOfSameType.content($"return new {type.RealName()}();");
                }

                if (pooled)
                {
                }
            }
        }
        static void GenPolymorphicRootSetup(Type baseClass, SharpClassBuilder sink,
                                            List <Type> typeIndexer, bool pooled)
        {
            string poolTypeArgIfAny = pooled ? $"{baseClass.PoolTypeName()} ," : "";

            if (pooled)
            {
                sink.usingSink("ZergRush.Alive");
            }

            // Array with constructors
            var constructorsArrayName = $"polymorph{(pooled ? "Pulled" : "")}Constructors";

            sink.content(
                $"static Func<{poolTypeArgIfAny}{baseClass.RealName()}> [] {constructorsArrayName} =" +
                $" new Func<{poolTypeArgIfAny}{baseClass.RealName()}> [] {{");
            sink.indent++;
            if (stubMode == false)
            {
                for (var i = 0; i < typeIndexer.Count; i++)
                {
                    var type = typeIndexer[i];
                    sink.content(
                        $"{(pooled ? "pool" : "()")} => {(type != null ? NewInstExpr(type, pooled) : "null")}, // {i}");
                }
            }

            sink.indent--;
            sink.content($"}};");

            // Create function
            sink.content(
                $"public static {baseClass.RealName()} {PolymorphInstanceFuncNamePooled(pooled)}(" +
                $"{PolymorphClassIdType} typeId{baseClass.OptPoolSecondArgDecl(pooled)}) {{");
            sink.content($"\treturn {constructorsArrayName}[typeId]({(pooled ? "pool" : "")});");
            sink.content($"}}");
        }
        static void GenClassIdFuncs(Type baseClass, List <Type> typesToGenPolymorphMethods, SharpClassBuilder sink)
        {
            foreach (var type in typesToGenPolymorphMethods)
            {
                if (type.ReadGenCustomFlags() == type.ReadGenFlags())
                {
                    continue;
                }

                var tSink = GenClassSink(type);
                tSink.inheritance("IPolymorphable");
                if (type.IsAbstract)
                {
                    if (type == baseClass)
                    {
                        tSink.content(
                            $"public virtual {PolymorphClassIdType} {PolymorphClassIdFunc}(){{throw new NotImplementedException();}}");
                    }
                }
                else
                {
                    var mType         = type == baseClass ? MethodType.Virtual : MethodType.Override;
                    var classIdGetter = tSink.Method(PolymorphClassIdFunc, type, mType, PolymorphClassIdType, "");
                    classIdGetter.doNotCallBaseMethod = true;
                    if (type.IsGenericTypeDecl())
                    {
                        PrintGenericSwitch(type, classIdGetter,
                                           (t, s) => s.content(
                                               $"return ({PolymorphClassIdType}){TypeEnumName}.{t.UniqueName(false)};"));
                        classIdGetter.content("return 0;");
                    }
                    else
                    {
                        classIdGetter.content(
                            $"return ({PolymorphClassIdType}){TypeEnumName}.{type.UniqueName(false)};");
                    }
                }

                if (UseClassIdCaching)
                {
                    sink.content($"[GenIgnore] public {PolymorphClassIdTypeName} {PolymorphClassIdCached};");
                    var cachedGetter = sink.Method(PolymorphClassIdGetterName, baseClass, MethodType.Instance,
                                                   PolymorphClassIdType, "");
                    cachedGetter.content(
                        $"return {PolymorphClassIdCached} == 0 ? {PolymorphClassIdCached} = {PolymorphClassIdFunc}() : {PolymorphClassIdCached};");
                }
            }
        }
예제 #5
0
        // You shall not dare to try to unfuck this.
        public static void Gen(bool stubs)
        {
            if (EditorApplication.isCompiling)
            {
                Debug.LogError("Application is compiling codegen run is not recomended");
                return;
            }

            EditorUtility.DisplayProgressBar("Running codegen", "creating tasks", 0);

            var genDir = new DirectoryInfo(GenPath);

            var typesEnumerable =
                from assembly in AppDomain.CurrentDomain.GetAssemblies()
                from t in assembly.GetTypes()
                select t;

            allTypesInAssemblies.AddRange(typesEnumerable.ToList());

            typeGenRequested.Clear();
            tasks.Clear();
            genericInstances.Clear();
            polymorphicMap.Clear();
            baseClassMap.Clear();
            extensionsSignaturesGenerated.Clear();
            classes.Clear();
            parents.Clear();
            hasErrors = false;

            stubMode = stubs;
            context  = new GeneratorContext(new GenInfo {
                sharpGenPath = GenPath
            }, stubMode);
            clientOnlyContext = new GeneratorContext(new GenInfo {
                sharpGenPath = GenPathClient
            }, stubMode);

            foreach (var type in allTypesInAssemblies)
            {
                foreach (var methodInfo in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
                {
                    if (methodInfo.HasAttribute <CodeGenExtension>())
                    {
                        methodInfo.Invoke(null, null);
                    }
                }

                if (type.ReadGenFlags() != GenTaskFlags.None)
                {
                    RequestGen(type, type.ReadGenFlags(), true);
                }
            }

            extensionSink = context.createSharpClass("SerializationExtensions", isStatic: true, isPartial: true);
            extensionSink.usingSink("System.IO");
            extensionSink.usingSink("ZergRush.Alive");

            extensionClientSink = clientOnlyContext.createSharpClass("SerializationExtensions", isStatic: true, isPartial: true);
            extensionClientSink.usingSink("System.IO");
            extensionClientSink.usingSink("ZergRush.Alive");


            while (tasks.Count > 0)
            {
                var task = tasks.Pop();
                var type = task.type;

                if (type.HasAttribute <DoNotGen>())
                {
                    continue;
                }

                var classSink = GenClassSink(task.type);

                classSink.indent++;

                Action <GenTaskFlags, Action <string> > checkFlag = (flag, gen) =>
                {
                    if ((task.flags & flag) != 0)
                    {
                        bool isCustom          = false;
                        bool needGenBase       = false;
                        var  genTaskCustomImpl = type.GetCustomImplAttr();
                        if (genTaskCustomImpl != null)
                        {
                            if ((genTaskCustomImpl.flags & flag) != 0)
                            {
                                isCustom    = true;
                                needGenBase = genTaskCustomImpl.genBaseMethods;
                            }
                        }

                        if (isCustom && needGenBase == false)
                        {
                            return;
                        }
                        string funcPrefix = isCustom ? "Base" : "";
                        gen(funcPrefix);
                    }
                };

                checkFlag(GenTaskFlags.UpdateFrom, funcPrefix => GenUpdateFrom(type, false, funcPrefix));
                checkFlag(GenTaskFlags.PooledUpdateFrom, funcPrefix => GenUpdateFrom(type, true, funcPrefix));
                checkFlag(GenTaskFlags.Deserialize, funcPrefix => GenerateDeserialize(type, false, funcPrefix));
                checkFlag(GenTaskFlags.PooledDeserialize, funcPrefix => GenerateDeserialize(type, true, funcPrefix));
                checkFlag(GenTaskFlags.Serialize, funcPrefix => GenerateSerialize(type, funcPrefix));
                checkFlag(GenTaskFlags.Hash, funcPrefix => GenHashing(type, funcPrefix));
                checkFlag(GenTaskFlags.UIDGen, funcPrefix => GenUIDFunc(type, funcPrefix));
                checkFlag(GenTaskFlags.CollectConfigs, funcPrefix => GenCollectConfigs(type, funcPrefix));
                checkFlag(GenTaskFlags.LifeSupport, funcPrefix => GenerateLivable(type, funcPrefix));
                checkFlag(GenTaskFlags.OwnershipHierarchy, funcPrefix => GenerateHierarchyAndId(type, funcPrefix));
                checkFlag(GenTaskFlags.OwnershipHierarchy, funcPrefix => GenerateConstructionFromRoot(type));
                checkFlag(GenTaskFlags.DefaultConstructor, funcPrefix => GenerateConstructor(type));
                checkFlag(GenTaskFlags.CompareChech, funcPrefix => GenerateComparisonFunc(type, funcPrefix));
                checkFlag(GenTaskFlags.JsonSerialization, funcPrefix => GenerateJsonSerialization(type, funcPrefix));
                checkFlag(GenTaskFlags.Pooled, funcPrefix => GeneratePoolSupportMethods(type));
                //checkFlag(GenTaskFlags.PrintHash, funcPrefix => GeneratePrintHash(type, funcPrefix));

                classSink.indent--;
            }

            GenerateFieldWrappers();
            GeneratePolimorphismSupport();
            GeneratePolymorphicRootSupport();
            // Do not change anythign if there is any errors
            if (hasErrors)
            {
                EditorUtility.ClearProgressBar();
                return;
            }

            EditorUtility.DisplayProgressBar("Running codegen", "writing cs files", 0.5f);

            foreach (FileInfo file in genDir.GetFiles())
            {
                // Skip metafiles for clean commit messages.
                if (file.Name.EndsWith("meta") || file.Name.EndsWith("txt"))
                {
                    continue;
                }
                file.Delete();
            }

            foreach (var typeEnumTable in finalTypeEnum)
            {
                EnumTable.Save(typeEnumTable.Key.TypeTableFileName(), new EnumTable {
                    records = typeEnumTable.Value
                });
            }

            context.Commit();
            clientOnlyContext.Commit();
            AssetDatabase.Refresh();

            EditorUtility.ClearProgressBar();
        }
예제 #6
0
 public SharpClassBuilder Class(string name, string namespaceName, bool isStruct, bool isSealed, bool isPartial, bool isStatic)
 {
     sharpClassBuilder = new SharpClassBuilder(this, name, namespaceName, isStruct, isSealed, isPartial, isStatic, stubMode);
     classes.Add(sharpClassBuilder);
     return(sharpClassBuilder);
 }