static void GeneratePolymorphicRootSupport() { foreach (var polymorphicRootNode in polymorphicRootNodes) { var node = polymorphicRootNode.Key; var types = polymorphicRootNode.Value .Where(t => t.IsValidType()) .Where(t => t.IsAbstract == false); var nodeClass = GenClassSink(node); var enumName = node.PolymorphicRootTypeEnumName(); var module = nodeClass.module; module.content(""); if (!string.IsNullOrEmpty(nodeClass.namespaceName)) { module.content($"namespace {nodeClass.namespaceName} {{"); module.indent++; } EnumTable.PrintEnum(module, enumName, types.Select(t => t.UniqueName(false)), type => finalTypeEnum[baseClassMap[node]][type]); if (!string.IsNullOrEmpty(nodeClass.namespaceName)) { module.indent--; module.content($"}}"); } module.content(""); } GeneratePolymorphicCreatorFuncs(); }
public static EnumTable Load(string fileName) { try { var table = new EnumTable(); using (TextReader reader = File.OpenText(fileName)) { string line = null; while ((line = reader.ReadLine()) != null) { var record = line.Split(' '); table.records.Add(record[0], int.Parse(record[1])); } } return(table); } catch (Exception e) { Debug.Log("loading type table exception"); Debug.Log(e); } return(new EnumTable()); }
static void GeneratePolimorphismSupport() { foreach (var polymorphTask in polymorphicMap) { var baseClass = polymorphTask.Key; var children = polymorphTask.Value; var sink = GenClassSink(baseClass); var typesToGenPolymorphMethods = new List <Type> { baseClass }.Concat(children).ToList(); var typesThatCanBeConstructed = typesToGenPolymorphMethods.Where(t => t.IsValidType()).ToList(); var fileName = baseClass.TypeTableFileName(); var typeTable = EnumTable.Load(fileName); var validTypes = typesThatCanBeConstructed.Where(t => t.IsAbstract == false && t.IsValidType()) .ToList(); typeTable.UpdateWithNewTypes(validTypes.Select(t => t.UniqueName(false))); finalTypeEnum[baseClass] = typeTable.records; var finalTypeIndexedList = new List <Type>(); foreach (var type in validTypes) { var index = typeTable.records[type.UniqueName(false)]; finalTypeIndexedList.EnsureSizeWithNulls(index + 1); finalTypeIndexedList[index] = type; } EnumTable.PrintEnum(sink, TypeEnumName, typesThatCanBeConstructed.Where(t => t.IsValidType()) .Where(t => t.IsAbstract == false).Select(t => t.UniqueName(false)), type => typeTable.records[type]); GenClassIdFuncs(baseClass, typesToGenPolymorphMethods, sink); if (baseClass.NeedsPooledPolymorphConstruction()) { GenPolymorphicRootSetup(baseClass, sink, finalTypeIndexedList, true); GenPolymorphMaps(baseClass, typesThatCanBeConstructed, typesToGenPolymorphMethods, sink, true); } if (baseClass.NeedsClassicPolymorphConstruction() || (!baseClass.HasPool() && (baseClass.ReadGenFlags() & (GenTaskFlags.UpdateFrom | GenTaskFlags.Serialization)) != 0)) { GenPolymorphicRootSetup(baseClass, sink, finalTypeIndexedList, false); GenPolymorphMaps(baseClass, typesThatCanBeConstructed, typesToGenPolymorphMethods, sink, false); } } }
public static void Save(string fileName, EnumTable table) { try { //File.Create(fileName).WriteByte(1); var list = table.records.ToList(); list.Sort((p1, p2) => p1.Value.CompareTo(p2.Value)); using (TextWriter writer = File.CreateText(fileName)) { foreach (var record in list) { writer.WriteLine($"{record.Key} {record.Value}"); } } } catch (Exception e) { Debug.LogError("saving type table exception"); Debug.LogError(e); } }
// 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(); }