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($"}}"); }
// 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(); }