mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
@@ -76,6 +76,24 @@ namespace CliFx.Tests
|
||||
public ValueTask ExecuteAsync(IConsole console) => default;
|
||||
}
|
||||
|
||||
[Command]
|
||||
private class EmptyOptionNameCommand : ICommand
|
||||
{
|
||||
[CommandOption("")]
|
||||
public string? Apples { get; set; }
|
||||
|
||||
public ValueTask ExecuteAsync(IConsole console) => default;
|
||||
}
|
||||
|
||||
[Command]
|
||||
private class SingleCharacterOptionNameCommand : ICommand
|
||||
{
|
||||
[CommandOption("a")]
|
||||
public string? Apples { get; set; }
|
||||
|
||||
public ValueTask ExecuteAsync(IConsole console) => default;
|
||||
}
|
||||
|
||||
[Command]
|
||||
private class DuplicateOptionNamesCommand : ICommand
|
||||
{
|
||||
|
||||
@@ -125,6 +125,26 @@ namespace CliFx.Tests
|
||||
Assert.Throws<CliFxException>(() => ApplicationSchema.Resolve(commandTypes));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Command_options_must_have_names_that_are_not_empty()
|
||||
{
|
||||
// Arrange
|
||||
var commandTypes = new[] {typeof(EmptyOptionNameCommand)};
|
||||
|
||||
// Act & assert
|
||||
Assert.Throws<CliFxException>(() => ApplicationSchema.Resolve(commandTypes));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Command_options_must_have_names_that_are_longer_than_one_character()
|
||||
{
|
||||
// Arrange
|
||||
var commandTypes = new[] {typeof(SingleCharacterOptionNameCommand)};
|
||||
|
||||
// Act & assert
|
||||
Assert.Throws<CliFxException>(() => ApplicationSchema.Resolve(commandTypes));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Command_options_must_have_unique_names()
|
||||
{
|
||||
|
||||
@@ -9,14 +9,14 @@ namespace CliFx.Attributes
|
||||
public class CommandOptionAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Option name.
|
||||
/// Option name (must be longer than a single character).
|
||||
/// Either <see cref="Name"/> or <see cref="ShortName"/> must be set.
|
||||
/// All options in a command must have different names (comparison is not case-sensitive).
|
||||
/// </summary>
|
||||
public string? Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Option short name.
|
||||
/// Option short name (single character).
|
||||
/// Either <see cref="Name"/> or <see cref="ShortName"/> must be set.
|
||||
/// All options in a command must have different short names (comparison is case-sensitive).
|
||||
/// </summary>
|
||||
|
||||
@@ -163,6 +163,35 @@ namespace CliFx.Domain
|
||||
|
||||
private static void ValidateOptions(CommandSchema command)
|
||||
{
|
||||
var emptyNameGroup = command.Options
|
||||
.Where(o => o.ShortName == null && string.IsNullOrWhiteSpace(o.Name))
|
||||
.ToArray();
|
||||
|
||||
if (emptyNameGroup.Any())
|
||||
{
|
||||
throw new CliFxException(new StringBuilder()
|
||||
.AppendLine($"Command {command.Type.FullName} contains one or more options that have empty names:")
|
||||
.AppendBulletList(emptyNameGroup.Select(o => o.Property.Name))
|
||||
.AppendLine()
|
||||
.Append("Options in a command must all have at least a name or a short name.")
|
||||
.ToString());
|
||||
}
|
||||
|
||||
var invalidNameGroup = command.Options
|
||||
.Where(o => !string.IsNullOrWhiteSpace(o.Name))
|
||||
.Where(o => o.Name.Length <= 1)
|
||||
.ToArray();
|
||||
|
||||
if (invalidNameGroup.Any())
|
||||
{
|
||||
throw new CliFxException(new StringBuilder()
|
||||
.AppendLine($"Command {command.Type.FullName} contains one or more options that have names that are too short:")
|
||||
.AppendBulletList(invalidNameGroup.Select(o => o.Property.Name))
|
||||
.AppendLine()
|
||||
.Append("Options in a command must all have names that are longer than a single character.")
|
||||
.ToString());
|
||||
}
|
||||
|
||||
var duplicateNameGroup = command.Options
|
||||
.Where(o => !string.IsNullOrWhiteSpace(o.Name))
|
||||
.GroupBy(o => o.Name, StringComparer.OrdinalIgnoreCase)
|
||||
|
||||
Reference in New Issue
Block a user