/// <summary>
        /// Create cil source-code representation of a <see cref="EnumDefinition"/>.
        /// </summary>
        /// <exception cref="Exceptions.InvalidAssemblyNameException">
        /// Thrown when a invalid assembly name is given.
        /// </exception>
        /// <exception cref="Exceptions.InvalidNamespaceException">
        /// Thrown when a invalid namespace identifier is given.
        /// </exception>
        /// <exception cref="Exceptions.OutOfBoundsValueException">
        /// Thrown when enum value does not fit in given storage-type.
        /// </exception>
        /// <param name="enumDefinition">Enum to generate cil source-code for</param>
        /// <param name="assemblyName">Name of the assembly to generate</param>
        /// <param name="namespace">Optional namespace to add the enum to</param>
        /// <param name="headerMode">Mode to use when adding a header</param>
        /// <param name="indentMode">Mode to use for indenting</param>
        /// <param name="spaceIndentSize">When indenting with spaces this controls how many</param>
        /// <param name="newlineMode">Mode to use for ending lines</param>
        /// <param name="storageType">Underlying enum storage-type to use</param>
        /// <param name="curlyBracketMode">Mode to use when writing curly brackets</param>
        /// <returns>String containing the genenerated cil sourcecode</returns>
        public static string ExportCil(
            this EnumDefinition enumDefinition,
            string assemblyName,
            string @namespace                   = null,
            HeaderMode headerMode               = HeaderMode.Default,
            CodeBuilder.IndentMode indentMode   = CodeBuilder.IndentMode.Spaces,
            int spaceIndentSize                 = 4,
            CodeBuilder.NewlineMode newlineMode = CodeBuilder.NewlineMode.Unix,
            StorageType storageType             = StorageType.Implicit,
            CurlyBracketMode curlyBracketMode   = CurlyBracketMode.NewLine)
        {
            if (enumDefinition == null)
            {
                throw new ArgumentNullException(nameof(enumDefinition));
            }

            if (string.IsNullOrEmpty(assemblyName) || !IdentifierValidator.Validate(assemblyName))
            {
                throw new InvalidAssemblyNameException(assemblyName);
            }

            if (!string.IsNullOrEmpty(@namespace) && !IdentifierValidator.ValidateNamespace(@namespace))
            {
                throw new InvalidNamespaceException(@namespace);
            }

            foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value)))
            {
                throw new OutOfBoundsValueException(storageType, oobEntry.Value);
            }

            var builder = new CodeBuilder(indentMode, spaceIndentSize, newlineMode);

            if (headerMode != HeaderMode.None)
            {
                builder.AddHeader();
                builder.WriteEndLine();
            }

            // Add reference to mscorlib.
            builder.WriteLine(".assembly extern mscorlib { }");
            builder.WriteEndLine();

            // Add assembly info.
            builder.Write($".assembly {assemblyName}");
            StartScope(builder, curlyBracketMode);
            builder.WriteLine(".ver 1:0:0:0");
            EndScope(builder);
            builder.WriteEndLine();

            // Add module info.
            builder.WriteLine($".module {assemblyName}.dll");
            builder.WriteEndLine();

            // Add enum class.
            builder.AddEnum(enumDefinition, storageType, curlyBracketMode, @namespace);

            return(builder.Build());
        }
        private static void AddNamespace(
            this CodeBuilder builder,
            string @namespace,
            Action <CodeBuilder> addContent,
            CurlyBracketMode curlyBracketMode)
        {
            builder.Write($"namespace {@namespace}");
            builder.StartScope(curlyBracketMode);

            addContent?.Invoke(builder);

            builder.EndScope();
        }
        /// <summary>
        /// Create csharp source-code representation of a <see cref="EnumDefinition"/>.
        /// </summary>
        /// <exception cref="Exceptions.InvalidNamespaceException">
        /// Thrown when a invalid namespace identifier is given.
        /// </exception>
        /// <exception cref="Exceptions.OutOfBoundsValueException">
        /// Thrown when enum value does not fit in given storage-type.
        /// </exception>
        /// <param name="enumDefinition">Enum to generate csharp source-code for</param>
        /// <param name="namespace">Optional namespace to add the enum to</param>
        /// <param name="headerMode">Mode to use when adding a header</param>
        /// <param name="indentMode">Mode to use for indenting</param>
        /// <param name="spaceIndentSize">When indenting with spaces this controls how many</param>
        /// <param name="newlineMode">Mode to use for ending lines</param>
        /// <param name="storageType">Underlying enum storage-type to use</param>
        /// <param name="curlyBracketMode">Mode to use when writing curly brackets</param>
        /// <returns>String containing the genenerated csharp sourcecode</returns>
        public static string ExportCSharp(
            this EnumDefinition enumDefinition,
            string @namespace                   = null,
            HeaderMode headerMode               = HeaderMode.Default,
            CodeBuilder.IndentMode indentMode   = CodeBuilder.IndentMode.Spaces,
            int spaceIndentSize                 = 4,
            CodeBuilder.NewlineMode newlineMode = CodeBuilder.NewlineMode.Unix,
            StorageType storageType             = StorageType.Implicit,
            CurlyBracketMode curlyBracketMode   = CurlyBracketMode.NewLine)
        {
            if (enumDefinition == null)
            {
                throw new ArgumentNullException(nameof(enumDefinition));
            }

            if (!string.IsNullOrEmpty(@namespace) && !IdentifierValidator.ValidateNamespace(@namespace))
            {
                throw new InvalidNamespaceException(@namespace);
            }

            foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value)))
            {
                throw new OutOfBoundsValueException(storageType, oobEntry.Value);
            }

            var builder = new CodeBuilder(indentMode, spaceIndentSize, newlineMode);

            if (headerMode != HeaderMode.None)
            {
                builder.AddHeader();
                builder.WriteEndLine();
            }

            builder.WriteLine("using System.CodeDom.Compiler;");
            builder.WriteEndLine();

            if (string.IsNullOrEmpty(@namespace))
            {
                builder.AddEnum(enumDefinition, storageType, curlyBracketMode);
            }
            else
            {
                builder.AddNamespace(
                    @namespace,
                    b => b.AddEnum(enumDefinition, storageType, curlyBracketMode),
                    curlyBracketMode);
            }

            return(builder.Build());
        }
        private static void AddEnum(
            this CodeBuilder builder,
            EnumDefinition enumDefinition,
            StorageType storageType,
            CurlyBracketMode curlyBracketMode)
        {
            var assemblyName = typeof(CSharpExporter).Assembly.GetName();

            if (!string.IsNullOrEmpty(enumDefinition.Comment))
            {
                builder.AddSummary(enumDefinition.Comment);
            }
            builder.WriteLine($"[GeneratedCode(\"{assemblyName.Name}\", \"{assemblyName.Version}\")]");
            if (storageType == StorageType.Implicit)
            {
                builder.Write($"public enum {enumDefinition.Identifier}");
            }
            else
            {
                builder.Write($"public enum {enumDefinition.Identifier} : {storageType.GetCSharpKeyword()}");
            }
            builder.StartScope(curlyBracketMode);

            var newlineBetweenEntries = enumDefinition.HasAnyEntryComments;
            var first = true;

            foreach (var entry in enumDefinition.Entries)
            {
                if (!first && newlineBetweenEntries)
                {
                    builder.WriteEndLine();
                }
                first = false;

                if (!string.IsNullOrEmpty(entry.Comment))
                {
                    builder.AddSummary(entry.Comment);
                }
                builder.WriteLine($"{entry.Name} = {entry.Value},");
            }

            builder.EndScope();
        }
        private static void AddEnum(
            this CodeBuilder builder,
            EnumDefinition enumDefinition,
            StorageType storageType,
            CurlyBracketMode curlyBracketMode,
            string @namespace = null)
        {
            var identifier = GetIdentifier(enumDefinition, @namespace);

            builder.Write($".class public sealed {identifier} extends [mscorlib]System.Enum");
            builder.StartScope(curlyBracketMode);

            var keyword = storageType.GetCilKeyword();

            builder.WriteLine($".field public specialname rtspecialname {keyword} value__");
            builder.WriteEndLine();
            foreach (var entry in enumDefinition.Entries)
            {
                builder.WriteLine($".field public static literal valuetype {identifier} {entry.Name} = {keyword}({entry.Value})");
            }

            builder.EndScope();
        }
        private static void StartScope(this CodeBuilder builder, CurlyBracketMode curlyBracketMode)
        {
            switch (curlyBracketMode)
            {
            case CurlyBracketMode.NewLine:
                if (builder.IsLineActive)
                {
                    builder.WriteEndLine();
                }
                builder.WriteLine("{");
                break;

            case CurlyBracketMode.SameLine:
                if (!builder.IsNewLine && !builder.IsSpace)
                {
                    builder.WriteSpace();
                }
                builder.Append("{");
                builder.WriteEndLine();
                break;
            }

            builder.BeginIndent();
        }
Esempio n. 7
0
        /// <summary>
        /// Generate enum file.
        /// </summary>
        /// <param name="inputJsonText">Input json text to generate the enum from</param>
        /// <param name="outputPath">Path where to save the generated enum to</param>
        /// <param name="outputType">Type of output to produce</param>
        /// <param name="collectionJPath">JPath to the collection in the input file</param>
        /// <param name="entryNameJPath">
        /// JPath to the name field in an entry in the input file</param>
        /// <param name="entryValueJPath">
        /// Optional JPath to the value field in an entry in the input file.
        /// </param>
        /// <param name="entryCommentJPath">
        /// Optional JPath to the comment field in an entry in the input file.
        /// </param>
        /// <param name="enumComment">
        /// Optional comment to add to the generated enum.
        /// </param>
        /// <param name="enumNamespace">
        /// Optional namespace to add the generated enum to.
        /// </param>
        /// <param name="headerMode">Mode to use when adding a header</param>
        /// <param name="indentMode">Mode to use when indenting text</param>
        /// <param name="indentSize">When indenting with spaces this controls how many</param>
        /// <param name="newlineMode">Mode to use when adding newlines to text</param>
        /// <param name="storageType">Storage type for the exported enum</param>
        /// <param name="curlyBracketMode">Mode to use when writing curly-brackets</param>
        /// <param name="logger">Optional logger for diagnostic output</param>
        public static void GenerateEnumToFile(
            string inputJsonText,
            string outputPath,
            OutputType outputType,
            string collectionJPath,
            string entryNameJPath,
            string entryValueJPath,
            string entryCommentJPath,
            string enumComment,
            string enumNamespace,
            HeaderMode headerMode,
            CodeBuilder.IndentMode indentMode,
            int indentSize,
            CodeBuilder.NewlineMode newlineMode,
            StorageType storageType,
            CurlyBracketMode curlyBracketMode,
            ILogger logger = null)
        {
            // Generate enum name.
            var enumName = GetEnumName(outputPath, logger);

            if (enumName == null)
            {
                return;
            }

            // Create mapping context.
            var context = Context.Create(
                collectionJPath,
                entryNameJPath,
                entryValueJPath,
                entryCommentJPath,
                logger);

            // Map enum.
            EnumDefinition enumDefinition = null;

            try
            {
                enumDefinition = context.MapEnum(inputJsonText, enumName, enumComment);
            }
            catch (JsonParsingFailureException)
            {
                logger?.LogCritical("Failed to parse input file: invalid json");
                return;
            }
            catch (MappingFailureException e)
            {
                logger?.LogCritical($"Failed to map enum: {e.InnerException.Message}");
                return;
            }

            // Export.
            byte[] output = null;
            switch (outputType)
            {
            case OutputType.CSharp:
                try
                {
                    output = Utf8NoBom.GetBytes(enumDefinition.ExportCSharp(
                                                    enumNamespace,
                                                    headerMode,
                                                    indentMode,
                                                    indentSize,
                                                    newlineMode,
                                                    storageType,
                                                    curlyBracketMode));
                }
                catch (Exception e)
                {
                    logger?.LogCritical($"Failed to generate csharp: {e.Message}");
                    return;
                }

                break;

            case OutputType.FSharp:
                try
                {
                    output = Utf8NoBom.GetBytes(enumDefinition.ExportFSharp(
                                                    string.IsNullOrEmpty(enumNamespace) ? "Generated" : enumNamespace,
                                                    headerMode,
                                                    indentSize,
                                                    newlineMode,
                                                    storageType));
                }
                catch (Exception e)
                {
                    logger?.LogCritical($"Failed to generate fsharp: {e.Message}");
                    return;
                }

                break;

            case OutputType.VisualBasic:
                try
                {
                    output = Utf8NoBom.GetBytes(enumDefinition.ExportVisualBasic(
                                                    enumNamespace,
                                                    headerMode,
                                                    indentMode,
                                                    indentSize,
                                                    newlineMode,
                                                    storageType));
                }
                catch (Exception e)
                {
                    logger?.LogCritical($"Failed to generate visual-basic: {e.Message}");
                    return;
                }

                break;

            case OutputType.Cil:
                try
                {
                    output = Utf8NoBom.GetBytes(enumDefinition.ExportCil(
                                                    assemblyName: enumName,
                                                    enumNamespace,
                                                    headerMode,
                                                    indentMode,
                                                    indentSize,
                                                    newlineMode,
                                                    storageType,
                                                    curlyBracketMode));
                }
                catch (Exception e)
                {
                    logger?.LogCritical($"Failed to generate cil: {e.Message}");
                    return;
                }

                break;

            case OutputType.ClassLibrary:
                try
                {
                    output = enumDefinition.ExportClassLibrary(
                        assemblyName: enumName,
                        enumNamespace,
                        storageType);
                }
                catch (Exception e)
                {
                    logger?.LogCritical($"Failed to generate classlibrary: {e.Message}");
                    return;
                }

                break;
            }

            // Write the file.
            try
            {
                var fullPath = Path.Combine(UnityEngine.Application.dataPath, outputPath);
                if (!fullPath.EndsWith(GetRequiredExtension(outputType), StringComparison.OrdinalIgnoreCase))
                {
                    fullPath = $"{fullPath}{GetDesiredExtension(outputType)}";
                }

                var outputDir = Path.GetDirectoryName(fullPath);
                if (!Directory.Exists(outputDir))
                {
                    logger?.LogDebug($"Creating output directory: '{outputDir}'");
                    Directory.CreateDirectory(outputDir);
                }

                File.WriteAllBytes(fullPath, output);
                logger?.LogInformation($"Saved enum: '{fullPath}'");
            }
            catch (Exception e)
            {
                logger?.LogCritical($"Failed to save enum: {e.Message}");
            }
        }