Example #1
0
        /// <summary>
        ///     Parses the bebop config file and assigns entries to their corresponding commandline flag.
        /// </summary>
        /// <param name="flagStore">A <see cref="CommandLineFlags"/> instance.</param>
        /// <param name="configPath">The fully qualified path to the bebop config file, or null to trigger searching.</param>
        /// <returns>true if the config could be parsed without error, otherwise false.</returns>
        private static bool TryParseConfig(CommandLineFlags flagStore, string?configPath = null)
        {
            configPath ??= FindBebopConfig();
            if (string.IsNullOrWhiteSpace(configPath))
            {
                return(false);
            }
            if (!new FileInfo(configPath).Exists)
            {
                return(false);
            }
            using var doc = JsonDocument.Parse(File.ReadAllText(configPath));
            var root = doc.RootElement;

            if (root.TryGetProperty("inputFiles", out var inputFileElement))
            {
                flagStore.SchemaFiles = new List <string>(inputFileElement.GetArrayLength());
                foreach (var fileElement in inputFileElement.EnumerateArray())
                {
                    if (fileElement.GetString() is not {
                    } filePath)
                    {
                        continue;
                    }
                    flagStore.SchemaFiles.Add(filePath);
                }
            }
            if (root.TryGetProperty("inputDirectory", out var inputDirectoryElement))
            {
                flagStore.SchemaDirectory = inputDirectoryElement.GetString();
            }
            if (root.TryGetProperty("generators", out var generatorsElement))
            {
                foreach (var generatorElement in generatorsElement.EnumerateArray())
                {
                    if (generatorElement.TryGetProperty("alias", out var aliasElement) &&
                        generatorElement.TryGetProperty("destinationPath", out var destinationElement))
                    {
                        foreach (var flagAttribute in GetFlagAttributes()
                                 .Where(flagAttribute => flagAttribute.Attribute.IsGeneratorFlag &&
                                        flagAttribute.Attribute.Name.Equals(aliasElement.GetString())))
                        {
                            flagAttribute.Property.SetValue(flagStore, destinationElement.GetString());
                        }
                    }
                }
            }
            return(true);
        }
Example #2
0
        private static async Task <int> Main()
        {
            Log.Formatter = CommandLineFlags.FindLogFormatter(Environment.GetCommandLineArgs());

            if (!CommandLineFlags.TryParse(Environment.GetCommandLineArgs(), out _flags, out var message))
            {
                await Log.Error(new CompilerException(message));

                return(1);
            }



            if (_flags.Version)
            {
                await Lager.StandardOut($"{ReservedWords.CompilerName} {VersionInfo.Informational}");

                return(0);
            }

            if (_flags.Help)
            {
                await WriteHelpText();

                return(0);
            }
            if (_flags.CheckSchemaFile is not null)
            {
                if (string.IsNullOrWhiteSpace(_flags.CheckSchemaFile))
                {
                    await Log.Error(new CompilerException("No textual schema was read from standard input."));

                    return(1);
                }
                return(await CheckSchema(_flags.CheckSchemaFile));
            }
            if (_flags.CheckSchemaFiles is not null)
            {
                if (_flags.CheckSchemaFiles.Count > 0)
                {
                    return(await CheckSchemas(_flags.CheckSchemaFiles));
                }
                await Log.Error(new CompilerException("No schemas specified in check."));

                return(1);
            }

            if (!_flags.GetParsedGenerators().Any())
            {
                await Log.Error(new CompilerException("No code generators were specified."));

                return(1);
            }

            if (_flags.SchemaDirectory is not null && _flags.SchemaFiles is not null)
            {
                await Log.Error(
                    new CompilerException("Can't specify both an input directory and individual input files"));

                return(1);
            }

            List <string> paths;

            if (_flags.SchemaDirectory is not null)
            {
                paths = new DirectoryInfo(_flags.SchemaDirectory !)
                        .GetFiles($"*.{ReservedWords.SchemaExt}", SearchOption.AllDirectories)
                        .Select(f => f.FullName)
                        .ToList();
            }
            else if (_flags.SchemaFiles is not null)
            {
                paths = _flags.SchemaFiles;
            }
            else
            {
                await Log.Error(new CompilerException("Specify one or more input files with --dir or --files."));

                return(1);
            }
            if (paths.Count == 0)
            {
                await Log.Error(new CompilerException("No input files were found at the specified target location."));

                return(1);
            }

            foreach (var parsedGenerator in _flags.GetParsedGenerators())
            {
                if (!GeneratorUtils.ImplementedGenerators.ContainsKey(parsedGenerator.Alias))
                {
                    await Log.Error(new CompilerException($"'{parsedGenerator.Alias}' is not a recognized code generator"));

                    return(1);
                }
                if (string.IsNullOrWhiteSpace(parsedGenerator.OutputFile))
                {
                    await Log.Error(new CompilerException("No output file was specified."));

                    return(1);
                }
                var result = await CompileSchema(GeneratorUtils.ImplementedGenerators[parsedGenerator.Alias], paths, new FileInfo(parsedGenerator.OutputFile), _flags.Namespace ?? "");

                if (result != Ok)
                {
                    return(result);
                }
            }
            return(Ok);
        }
Example #3
0
        /// <summary>
        ///     Attempts to parse commandline flags into a <see cref="CommandLineFlags"/> instance
        /// </summary>
        /// <param name="args">the array of arguments to parse</param>
        /// <param name="flagStore">An instance which contains all parsed flags and their values</param>
        /// <param name="errorMessage">A human-friendly message describing why parsing failed.</param>
        /// <returns>
        ///     If the provided
        ///     <param name="args"></param>
        ///     were parsed this method returns true.
        /// </returns>
        public static bool TryParse(string[] args, out CommandLineFlags flagStore, out string errorMessage)
        {
            errorMessage = string.Empty;
            var props = GetFlagAttributes();

            var stringBuilder = new IndentedStringBuilder();

            stringBuilder.AppendLine("Usage:");
            stringBuilder.Indent(4);
            foreach (var prop in props.Where(prop => !string.IsNullOrWhiteSpace(prop.Attribute.UsageExample)))
            {
                stringBuilder.AppendLine($"{ReservedWords.CompilerName} {prop.Attribute.UsageExample}");
            }
            stringBuilder.Dedent(4);

            stringBuilder.AppendLine(string.Empty);
            stringBuilder.AppendLine(string.Empty);
            stringBuilder.AppendLine("Options:");
            stringBuilder.Indent(4);
            foreach (var prop in props)
            {
                stringBuilder.AppendLine($"--{prop.Attribute.Name}  {prop.Attribute.HelpText}");
            }

            flagStore = new CommandLineFlags(stringBuilder.ToString());

            var parsedFlags = GetFlags(args);

            if (parsedFlags.Count == 0)
            {
                if (TryParseConfig(flagStore))
                {
                    return(true);
                }
                errorMessage = "No commandline flags found.";
                return(false);
            }

            if (parsedFlags.ContainsKey("config"))
            {
                var configPath = parsedFlags["config"];
                if (string.IsNullOrWhiteSpace(configPath))
                {
                    configPath = null;
                }
                return(TryParseConfig(flagStore, configPath));
            }

            if (parsedFlags.ContainsKey("help"))
            {
                flagStore.Help = true;
                return(true);
            }

            if (parsedFlags.ContainsKey("version"))
            {
                flagStore.Version = true;
                return(true);
            }

            foreach (var flag in props)
            {
                if (!parsedFlags.ContainsKey(flag.Attribute.Name))
                {
                    continue;
                }

                var parsedValue  = parsedFlags[flag.Attribute.Name]?.Trim();
                var propertyType = flag.Property.PropertyType;
                if (flag.Attribute.Name.Equals("check-schema"))
                {
                    using var reader          = new StreamReader(Console.OpenStandardInput());
                    flagStore.CheckSchemaFile = reader.ReadToEnd();
                    continue;
                }
                if (propertyType == typeof(bool))
                {
                    flag.Property.SetValue(flagStore, true);
                    continue;
                }
                if (string.IsNullOrWhiteSpace(parsedValue))
                {
                    errorMessage = $"Commandline flag '{flag.Attribute.Name}' was not assigned a value.";
                    return(false);
                }
                if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List <>))
                {
                    Type itemType = propertyType.GetGenericArguments()[0];
                    if (!(Activator.CreateInstance(typeof(List <>).MakeGenericType(itemType)) is IList genericList))
                    {
                        errorMessage = $"Failed to activate '{flag.Property.Name}'.";
                        return(false);
                    }
                    foreach (var item in parsedValue.Split(" ",
                                                           StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))
                    {
                        genericList.Add(Convert.ChangeType(item.Trim(), itemType));
                    }
                    flag.Property.SetValue(flagStore, genericList, null);
                }
                else if (propertyType.IsEnum)
                {
                    if (!Enum.TryParse(propertyType, parsedValue, true, out var parsedEnum))
                    {
                        errorMessage = $"Failed to parse '{parsedValue}' into a member of '{propertyType}'.";
                        return(false);
                    }
                    flag.Property.SetValue(flagStore, parsedEnum, null);
                }
                else
                {
                    flag.Property.SetValue(flagStore, Convert.ChangeType(parsedValue, flag.Property.PropertyType),
                                           null);
                }
            }
            errorMessage = string.Empty;
            return(true);
        }