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