From 86fdf72d9cd8e444a00b622c76cbc62b5bdf2d96 Mon Sep 17 00:00:00 2001 From: Alexey Golub Date: Tue, 13 Aug 2019 18:34:23 +0300 Subject: [PATCH] Validate available command schemas at the start of the application --- CliFx/CliApplication.cs | 71 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/CliFx/CliApplication.cs b/CliFx/CliApplication.cs index fd8fad0..79864f6 100644 --- a/CliFx/CliApplication.cs +++ b/CliFx/CliApplication.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using CliFx.Attributes; using CliFx.Exceptions; +using CliFx.Internal; using CliFx.Models; using CliFx.Services; @@ -36,6 +37,67 @@ namespace CliFx _commandHelpTextRenderer = commandHelpTextRenderer; } + private IReadOnlyList GetAvailableCommandSchemasValidationErrors(IReadOnlyList availableCommandSchemas) + { + var result = new List(); + + // Fail if there are no commands defined + if (!availableCommandSchemas.Any()) + { + result.Add("There are no commands defined in this application."); + } + + // Fail if there are multiple commands with the same name + var nonUniqueCommandNames = availableCommandSchemas + .Select(c => c.Name?.Trim()) + .GroupBy(i => i, StringComparer.OrdinalIgnoreCase) + .Where(g => g.Count() >= 2) + .SelectMany(g => g) + .Distinct() + .ToArray(); + + foreach (var commandName in nonUniqueCommandNames) + { + result.Add($"There are multiple commands defined with name [{commandName}]."); + } + + // Fail if there are multiple options with the same name inside the same command + foreach (var commandSchema in availableCommandSchemas) + { + var nonUniqueOptionNames = commandSchema.Options + .Where(o => !o.Name.IsNullOrWhiteSpace()) + .Select(o => o.Name) + .GroupBy(i => i, StringComparer.OrdinalIgnoreCase) + .Where(g => g.Count() >= 2) + .SelectMany(g => g) + .Distinct() + .ToArray(); + + foreach (var optionName in nonUniqueOptionNames) + { + result.Add( + $"There are multiple options defined with name [{optionName}] for command [{commandSchema.Name}]."); + } + + var nonUniqueOptionShortNames = commandSchema.Options + .Where(o => o.ShortName != null) + .Select(o => o.ShortName.Value) + .GroupBy(i => i) + .Where(g => g.Count() >= 2) + .SelectMany(g => g) + .Distinct() + .ToArray(); + + foreach (var optionShortName in nonUniqueOptionShortNames) + { + result.Add( + $"There are multiple options defined with short name [{optionShortName}] for command [{commandSchema.Name}]."); + } + } + + return result; + } + public async Task RunAsync(IReadOnlyList commandLineArguments) { try @@ -45,11 +107,12 @@ namespace CliFx var availableCommandSchemas = _commandSchemaResolver.GetCommandSchemas(_commandTypes); var matchingCommandSchema = availableCommandSchemas.FindByName(commandInput.CommandName); - // Fail if there are no commands defined - if (!availableCommandSchemas.Any()) + // Validate available command schemas + var validationErrors = GetAvailableCommandSchemasValidationErrors(availableCommandSchemas); + if (validationErrors.Any()) { - _console.WithForegroundColor(ConsoleColor.Red, - () => _console.Error.WriteLine("There are no commands defined in this application.")); + foreach (var error in validationErrors) + _console.WithForegroundColor(ConsoleColor.Red, () => _console.Output.WriteLine(error)); return -1; }