private void GenSchemaTypes(List <ExplorerItem> schema, StringWriter writer, DirectoryInfo root)
        {
            const string ForceRefresh = "Overby.LINQPad.FileDriver.Configuration.RuntimeConfiguration.ForceRefresh = true;";
            var          flatSchema   = schema.Flatten().ToArray();

            // alias all file/folder namespaces
            // this avoids conflicts in folder schema types
            // when referencing reader/record types
            // in namespaces that are named same as members
            using (writer.Region("File Namespace Aliases"))
                foreach (var tag in flatSchema.GetTags <IRefFileSystemInfo>())
                {
                    var nsFile = tag.FileSystemInfo.GetNameSpace(root);
                    var alias  = tag.FileSystemInfo.FullName.UniqueIdentifier();
                    writer.WriteLine($"using {alias} = {nsFile};");
                }

            Write(root, schema);

            foreach (var(item, tag) in flatSchema.WithTag <FolderTag>())
            {
                Write(tag.Folder, item.Children);
            }

            void Write(DirectoryInfo folder, IList <ExplorerItem> items)
            {
                if (items.Count == 0)
                {
                    return;
                }

                var fileItems = items.WithTag <FileTag>().ToArray();

                using var _1 = writer.Region(folder);
                using var _2 = writer.NameSpace(folder.GetNameSpace(root));

                // write file records/readers
                foreach (var(item, fileTag) in fileItems)
                {
                    var fileConfig = fileTag.FileConfig;
                    var(WriteRecordMembers, WriteEnumeratorImplementation) =
                        fileTag.CodeGenerator.GetCodeGenerators(fileConfig);

                    using (writer.Region(fileTag.File))
                        using (writer.NameSpace(fileTag.File.GetNameIdentifier()))
                        {
                            // record class
                            writer.MemberComment("Record type for " + fileTag.File.FullName);
                            using (writer.Brackets("public class " + RecordClassName))
                                WriteRecordMembers(writer);

                            // reader class
                            writer.MemberComment("Reader for " + fileTag.File.FullName);
                            using (writer.Brackets($"public class {ReaderClassName} : {IEnumerable(RecordClassName)}"))
                            {
                                // file path property
                                writer.MemberComment("Path to " + fileTag.File.FullName);
                                writer.WriteLine(@$ "
                                public string {ReaderFilePathPropertyName} => {fileTag.File.FullName.ToLiteral()};
        private string GenerateCode(ref string nameSpace, List <ExplorerItem> schema, DirectoryInfo root)
        {
            var writer = new StringWriter();

            using (writer.NameSpace(nameSpace))
            {
                // generate schema types
                using (writer.NameSpace(SchemaNameSpace))
                    GenSchemaTypes(schema, writer, root);
            }

            return(writer.ToString());
        }