private void ResolveDirectives(IReadOnlyList <Type> directiveTypes) { var directives = new Dictionary <string, DirectiveSchema>(); var invalidDirectives = new List <DirectiveSchema>(); foreach (Type?directiveType in directiveTypes) { DirectiveSchema directive = DirectiveSchemaResolver.Resolve(directiveType); if (!directives.TryAdd(directive.Name, directive)) { invalidDirectives.Add(directive); } } if (invalidDirectives.Count > 0) { IGrouping <string, DirectiveSchema>?duplicateNameGroup = invalidDirectives.Union(directives.Values) .GroupBy(c => c.Name, StringComparer.OrdinalIgnoreCase) .FirstOrDefault(); throw InternalTypinExceptions.DirectiveWithSameName(duplicateNameGroup.Key, duplicateNameGroup.ToArray()); } Directives = directives; }
/// <summary> /// Initializes an instance of <see cref="LineInputHandler"/>. /// </summary> public LineInputHandler(IConsole console, HashSet <ShortcutDefinition>?internalShortcuts = null, HashSet <ShortcutDefinition>?userDefinedShortcuts = null) : this(console) { if (internalShortcuts != null) { //TODO: maybe hashset is not the best collection //_shortcuts.Union(internalShortcuts); foreach (ShortcutDefinition shortcut in internalShortcuts) { if (!_shortcuts.Add(shortcut)) { //Replace when already exists _shortcuts.Remove(shortcut); _shortcuts.Add(shortcut); } } } if (userDefinedShortcuts != null) { //_shortcuts.Union(userDefinedShortcut); foreach (ShortcutDefinition shortcut in userDefinedShortcuts) { if (!_shortcuts.Add(shortcut)) { throw InternalTypinExceptions.DuplicatedShortcut(shortcut); } } } }
private static void ValidateParameters(CommandSchema command) { IGrouping <int, CommandParameterSchema>?duplicateOrderGroup = command.Parameters .GroupBy(a => a.Order) .FirstOrDefault(g => g.Count() > 1); if (duplicateOrderGroup != null) { throw InternalTypinExceptions.ParametersWithSameOrder( command, duplicateOrderGroup.Key, duplicateOrderGroup.ToArray() ); } IGrouping <string, CommandParameterSchema>?duplicateNameGroup = command.Parameters .Where(a => !string.IsNullOrWhiteSpace(a.Name)) .GroupBy(a => a.Name !, StringComparer.OrdinalIgnoreCase) .FirstOrDefault(g => g.Count() > 1); if (duplicateNameGroup != null) { throw InternalTypinExceptions.ParametersWithSameName( command, duplicateNameGroup.Key, duplicateNameGroup.ToArray() ); } CommandParameterSchema[]? nonScalarParameters = command.Parameters .Where(p => !p.IsScalar) .ToArray(); if (nonScalarParameters.Length > 1) { throw InternalTypinExceptions.TooManyNonScalarParameters( command, nonScalarParameters ); } CommandParameterSchema?nonLastNonScalarParameter = command.Parameters .OrderByDescending(a => a.Order) .Skip(1) .LastOrDefault(p => !p.IsScalar); if (nonLastNonScalarParameter != null) { throw InternalTypinExceptions.NonLastNonScalarParameter( command, nonLastNonScalarParameter ); } }
/// <summary> /// Resolves <see cref="CommandSchema"/>. /// </summary> public static CommandSchema Resolve(Type type) { if (!CommandSchema.IsCommandType(type)) { throw InternalTypinExceptions.InvalidCommandType(type); } CommandAttribute attribute = type.GetCustomAttribute <CommandAttribute>() !; string?name = attribute.Name; CommandOptionSchema[] builtInOptions = string.IsNullOrWhiteSpace(name) ? new[] { CommandOptionSchema.HelpOption, CommandOptionSchema.VersionOption } : new[] { CommandOptionSchema.HelpOption }; CommandParameterSchema?[] parameters = type.GetProperties() .Select(CommandParameterSchemaResolver.TryResolve) .Where(p => p != null) .ToArray(); CommandOptionSchema?[] options = type.GetProperties() .Select(CommandOptionSchemaResolver.TryResolve) .Where(o => o != null) .Concat(builtInOptions) .ToArray(); CommandSchema command = new CommandSchema( type, name, attribute.Description, attribute.Manual, attribute.InteractiveModeOnly, parameters !, options ! ); ValidateParameters(command); ValidateOptions(command); return(command); }
/// <summary> /// Resolves <see cref="DirectiveSchema"/>. /// </summary> public static DirectiveSchema Resolve(Type type) { if (!DirectiveSchema.IsDirectiveType(type)) { throw InternalTypinExceptions.InvalidDirectiveType(type); } DirectiveAttribute attribute = type.GetCustomAttribute <DirectiveAttribute>() !; string name = attribute.Name.TrimStart('[').TrimEnd(']'); if (string.IsNullOrWhiteSpace(name)) { throw InternalTypinExceptions.DirectiveNameIsInvalid(name, type); } return(new DirectiveSchema( type, name, attribute.Description, attribute.InteractiveModeOnly )); }
private void ResolveCommands(IReadOnlyList <Type> commandTypes) { CommandSchema?defaultCommand = null; var commands = new Dictionary <string, CommandSchema>(); var invalidCommands = new List <CommandSchema>(); foreach (Type commandType in commandTypes) { CommandSchema command = CommandSchemaResolver.Resolve(commandType); if (command.IsDefault) { defaultCommand = defaultCommand is null ? command : throw InternalTypinExceptions.TooManyDefaultCommands(); } else if (!commands.TryAdd(command.Name !, command)) { invalidCommands.Add(command); } } if (commands.Count == 0 && defaultCommand is null) { throw InternalTypinExceptions.NoCommandsDefined(); } if (invalidCommands.Count > 0) { IGrouping <string, CommandSchema> duplicateNameGroup = invalidCommands.Union(commands.Values) .GroupBy(c => c.Name !, StringComparer.OrdinalIgnoreCase) .FirstOrDefault(); throw InternalTypinExceptions.CommandsWithSameName(duplicateNameGroup.Key, duplicateNameGroup.ToArray()); } DefaultCommand = defaultCommand; Commands = commands; }
private static void ValidateOptions(CommandSchema command) { IEnumerable <CommandOptionSchema> noNameGroup = command.Options .Where(o => o.ShortName == null && string.IsNullOrWhiteSpace(o.Name)); if (noNameGroup.Any()) { throw InternalTypinExceptions.OptionsWithNoName( command, noNameGroup.ToArray() ); } IEnumerable <CommandOptionSchema> digitStartingGroup = command.Options .Where(o => char.IsDigit(o.ShortName ?? 'a') || char.IsDigit(o.Name?.FirstOrDefault() ?? 'a')); if (digitStartingGroup.Any()) { throw InternalTypinExceptions.OptionsWithDigitStartingName( command, digitStartingGroup.ToArray() ); } CommandOptionSchema[] invalidLengthNameGroup = command.Options .Where(o => !string.IsNullOrWhiteSpace(o.Name)) .Where(o => o.Name !.Length <= 1) .ToArray(); if (invalidLengthNameGroup.Any()) { throw InternalTypinExceptions.OptionsWithInvalidLengthName( command, invalidLengthNameGroup ); } IGrouping <string, CommandOptionSchema>?duplicateNameGroup = command.Options .Where(o => !string.IsNullOrWhiteSpace(o.Name)) .GroupBy(o => o.Name !, StringComparer.OrdinalIgnoreCase) .FirstOrDefault(g => g.Count() > 1); if (duplicateNameGroup != null) { throw InternalTypinExceptions.OptionsWithSameName( command, duplicateNameGroup.Key, duplicateNameGroup.ToArray() ); } IGrouping <char, CommandOptionSchema>?duplicateShortNameGroup = command.Options .Where(o => o.ShortName != null) .GroupBy(o => o.ShortName !.Value) .FirstOrDefault(g => g.Count() > 1); if (duplicateShortNameGroup != null) { throw InternalTypinExceptions.OptionsWithSameShortName( command, duplicateShortNameGroup.Key, duplicateShortNameGroup.ToArray() ); } IGrouping <string, CommandOptionSchema>?duplicateEnvironmentVariableNameGroup = command.Options .Where(o => !string.IsNullOrWhiteSpace(o.FallbackVariableName)) .GroupBy(o => o.FallbackVariableName !, StringComparer.OrdinalIgnoreCase) .FirstOrDefault(g => g.Count() > 1); if (duplicateEnvironmentVariableNameGroup != null) { throw InternalTypinExceptions.OptionsWithSameEnvironmentVariableName( command, duplicateEnvironmentVariableNameGroup.Key, duplicateEnvironmentVariableNameGroup.ToArray() ); } }