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