public static void WriteToPath(string basePath)
        {
            foreach (var block in UdmfDefinitions.Blocks)
            {
                using (var blockStream = File.CreateText(Path.Combine(basePath, block.CodeName.ToPascalCase() + ".Generated.cs")))
                    using (var output = new IndentedWriter(blockStream))
                    {
                        output.Line(
                            $@"// Copyright (c) {DateTime.Today.Year}, David Aramant
// Distributed under the 3-clause BSD license.  For full terms see the file LICENSE. 

using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UdmfParsing.Udmf.WritingExtensions;

namespace UdmfParsing.Udmf");

                        output.OpenParen();
                        output.Line(
                            $"[GeneratedCode(\"{CurrentLibraryInfo.Name}\", \"{CurrentLibraryInfo.Version}\")]");
                        output.Line(
                            $"public sealed partial class {block.CodeName}");
                        output.OpenParen();

                        WriteProperties(block, output);

                        output.Line();

                        WriteConstructors(output, block);

                        output.Line();

                        WriteWriteToMethod(block, output);

                        output.Line();

                        WriteSemanticValidityMethods(output, block);
                        WriteCloneMethod(output, block);

                        output.CloseParen();
                        output.Line();
                        output.CloseParen(); // End namespace
                    }
            }
        }
        private static void WriteConstructors(IndentedWriter sb, Block block)
        {
            sb.Line($"public {block.CodeName}() {{ }}");
            sb.Line($"public {block.CodeName}(");
            sb.IncreaseIndent();

            foreach (var indexed in block.OrderedProperties().Select((param, index) => new { param, index }))
            {
                var property = indexed.param;
                var argument = $"{property.ConstructorArgumentType} {property.ConstructorArgumentName}" +
                               (property.IsRequired ? string.Empty : $" = {property.DefaultValue}");
                sb.Line(argument + (indexed.index == block.Properties.Count() - 1 ? ")" : ","));
            }

            sb.DecreaseIndent();
            sb.OpenParen();

            foreach (var property in block.OrderedProperties())
            {
                switch (property)
                {
                case Field field:
                    sb.Line($"{field.PropertyName} = {field.ConstructorArgumentName};");
                    break;

                case BlockList requiredBlockList when requiredBlockList.IsRequired:
                    sb.Line($"{requiredBlockList.PropertyName}.AddRange({requiredBlockList.ConstructorArgumentName});");
                    break;

                case BlockList blockList:
                    sb.Line($"{blockList.PropertyName}.AddRange({blockList.ConstructorArgumentName} ?? Enumerable.Empty<{blockList.SingularName}>());");
                    break;
                }
            }

            sb.Line(@"AdditionalSemanticChecks();");
            sb.CloseParen();
        }