From 2d3c221b48d6b62296784acbcad0ea8fe39c8659 Mon Sep 17 00:00:00 2001 From: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> Date: Sun, 11 Aug 2024 22:34:50 +0300 Subject: [PATCH] asd --- CliFx/Formatting/HelpConsoleFormatter.cs | 2 +- CliFx/Formatting/HelpContext.cs | 4 +- .../{InputSchema.cs => CommandInputSchema.cs} | 33 ++++---- ...OptionSchema.cs => CommandOptionSchema.cs} | 75 ++++++++++--------- ...terSchema.cs => CommandParameterSchema.cs} | 26 ++++--- CliFx/Schema/CommandSchema.cs | 32 ++++---- CliFx/Schema/PropertyBinding.cs | 8 +- 7 files changed, 98 insertions(+), 82 deletions(-) rename CliFx/Schema/{InputSchema.cs => CommandInputSchema.cs} (78%) rename CliFx/Schema/{OptionSchema.cs => CommandOptionSchema.cs} (66%) rename CliFx/Schema/{ParameterSchema.cs => CommandParameterSchema.cs} (62%) diff --git a/CliFx/Formatting/HelpConsoleFormatter.cs b/CliFx/Formatting/HelpConsoleFormatter.cs index 9a4b6e8..4a8d7a8 100644 --- a/CliFx/Formatting/HelpConsoleFormatter.cs +++ b/CliFx/Formatting/HelpConsoleFormatter.cs @@ -305,7 +305,7 @@ internal class HelpConsoleFormatter(ConsoleWriter consoleWriter, HelpContext con } } - private void WriteDefaultValue(InputSchema schema) + private void WriteDefaultValue(CommandInputSchema schema) { var defaultValue = context.CommandDefaultValues.GetValueOrDefault(schema); if (defaultValue is null) diff --git a/CliFx/Formatting/HelpContext.cs b/CliFx/Formatting/HelpContext.cs index 9f6b84e..a05ab44 100644 --- a/CliFx/Formatting/HelpContext.cs +++ b/CliFx/Formatting/HelpContext.cs @@ -7,7 +7,7 @@ internal class HelpContext( ApplicationMetadata applicationMetadata, ApplicationSchema applicationSchema, CommandSchema commandSchema, - IReadOnlyDictionary commandDefaultValues + IReadOnlyDictionary commandDefaultValues ) { public ApplicationMetadata ApplicationMetadata { get; } = applicationMetadata; @@ -16,6 +16,6 @@ internal class HelpContext( public CommandSchema CommandSchema { get; } = commandSchema; - public IReadOnlyDictionary CommandDefaultValues { get; } = + public IReadOnlyDictionary CommandDefaultValues { get; } = commandDefaultValues; } diff --git a/CliFx/Schema/InputSchema.cs b/CliFx/Schema/CommandInputSchema.cs similarity index 78% rename from CliFx/Schema/InputSchema.cs rename to CliFx/Schema/CommandInputSchema.cs index 94af029..962bfe8 100644 --- a/CliFx/Schema/InputSchema.cs +++ b/CliFx/Schema/CommandInputSchema.cs @@ -12,13 +12,17 @@ namespace CliFx.Schema; /// /// Describes an input of a command. /// -public abstract class InputSchema( +public abstract class CommandInputSchema( PropertyBinding property, string? description, IBindingConverter converter, IReadOnlyList validators ) { + internal abstract string Kind { get; } + + internal abstract string FormattedIdentifier { get; } + internal bool IsSequence { get; } = property.Type != typeof(string) && property.Type.TryGetEnumerableUnderlyingType() is not null; @@ -43,10 +47,6 @@ public abstract class InputSchema( /// public IReadOnlyList Validators { get; } = validators; - internal abstract string GetKind(); - - internal abstract string GetFormattedIdentifier(); - private void Validate(object? value) { var errors = Validators @@ -58,7 +58,7 @@ public abstract class InputSchema( { throw CliFxException.UserError( $""" - {GetKind()} {GetFormattedIdentifier()} has been provided with an invalid value. + {Kind} {FormattedIdentifier} has been provided with an invalid value. Error(s): {errors.Select(e => "- " + e.Message).JoinToString(Environment.NewLine)} """ @@ -93,7 +93,7 @@ public abstract class InputSchema( { throw CliFxException.UserError( $""" - {GetKind()} {GetFormattedIdentifier()} expects a single argument, but provided with multiple: + {Kind} {FormattedIdentifier} expects a single argument, but provided with multiple: {rawInputs.Select(v => '<' + v + '>').JoinToString(" ")} """ ); @@ -103,7 +103,7 @@ public abstract class InputSchema( { throw CliFxException.UserError( $""" - {GetKind()} {GetFormattedIdentifier()} cannot be set from the provided argument(s): + {Kind} {FormattedIdentifier} cannot be set from the provided argument(s): {rawInputs.Select(v => '<' + v + '>').JoinToString(" ")} Error: {ex.Message} """, @@ -111,13 +111,18 @@ public abstract class InputSchema( ); } } + + /// + public override string ToString() => FormattedIdentifier; } -// Generic version of the type is used to simplify initialization from the source-generated code -// and to enforce static references to all the types used in the binding. -// The non-generic version is used internally by the framework when operating in a dynamic context. -/// -public abstract class InputSchema< +/// +/// +/// Generic version of the type is used to simplify initialization from source-generated code and +/// to enforce static references to all types used in the binding. +/// The non-generic version is used internally by the framework when operating in a dynamic context. +/// +public abstract class CommandInputSchema< TCommand, [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods @@ -128,5 +133,5 @@ public abstract class InputSchema< string? description, BindingConverter converter, IReadOnlyList> validators -) : InputSchema(property, description, converter, validators) +) : CommandInputSchema(property, description, converter, validators) where TCommand : ICommand; diff --git a/CliFx/Schema/OptionSchema.cs b/CliFx/Schema/CommandOptionSchema.cs similarity index 66% rename from CliFx/Schema/OptionSchema.cs rename to CliFx/Schema/CommandOptionSchema.cs index 52cbd3b..598f80c 100644 --- a/CliFx/Schema/OptionSchema.cs +++ b/CliFx/Schema/CommandOptionSchema.cs @@ -9,7 +9,7 @@ namespace CliFx.Schema; /// /// Describes an option input of a command. /// -public class OptionSchema( +public class CommandOptionSchema( PropertyBinding property, string? name, char? shortName, @@ -18,8 +18,38 @@ public class OptionSchema( string? description, IBindingConverter converter, IReadOnlyList validators -) : InputSchema(property,description, converter, validators) +) : CommandInputSchema(property,description, converter, validators) { + internal override string Kind => "Option"; + + internal override string FormattedIdentifier + { + get + { + var buffer = new StringBuilder(); + + // Short name + if (ShortName is not null) + { + buffer.Append('-').Append(ShortName); + } + + // Separator + if (!string.IsNullOrWhiteSpace(Name) && ShortName is not null) + { + buffer.Append('|'); + } + + // Name + if (!string.IsNullOrWhiteSpace(Name)) + { + buffer.Append("--").Append(Name); + } + + return buffer.ToString(); + } + } + /// /// Option name. /// @@ -53,40 +83,15 @@ public class OptionSchema( internal bool MatchesEnvironmentVariable(string environmentVariableName) => !string.IsNullOrWhiteSpace(EnvironmentVariable) && string.Equals(EnvironmentVariable, environmentVariableName, StringComparison.Ordinal); - - internal override string GetKind() => "Option"; - - internal override string GetFormattedIdentifier() - { - var buffer = new StringBuilder(); - - // Short name - if (ShortName is not null) - { - buffer.Append('-').Append(ShortName); - } - - // Separator - if (!string.IsNullOrWhiteSpace(Name) && ShortName is not null) - { - buffer.Append('|'); - } - - // Name - if (!string.IsNullOrWhiteSpace(Name)) - { - buffer.Append("--").Append(Name); - } - - return buffer.ToString(); - } } -// Generic version of the type is used to simplify initialization from the source-generated code -// and to enforce static references to all the types used in the binding. -// The non-generic version is used internally by the framework when operating in a dynamic context. -/// -public class OptionSchema< +/// +/// +/// Generic version of the type is used to simplify initialization from source-generated code and +/// to enforce static references to all types used in the binding. +/// The non-generic version is used internally by the framework when operating in a dynamic context. +/// +public class CommandOptionSchema< TCommand, [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods @@ -102,7 +107,7 @@ public class OptionSchema< BindingConverter converter, IReadOnlyList> validators ) - : OptionSchema( + : CommandOptionSchema( property, name, shortName, diff --git a/CliFx/Schema/ParameterSchema.cs b/CliFx/Schema/CommandParameterSchema.cs similarity index 62% rename from CliFx/Schema/ParameterSchema.cs rename to CliFx/Schema/CommandParameterSchema.cs index 232fe68..b37e232 100644 --- a/CliFx/Schema/ParameterSchema.cs +++ b/CliFx/Schema/CommandParameterSchema.cs @@ -7,7 +7,7 @@ namespace CliFx.Schema; /// /// Describes a parameter input of a command. /// -public class ParameterSchema( +public class CommandParameterSchema( PropertyBinding property, int order, string name, @@ -15,8 +15,12 @@ public class ParameterSchema( string? description, IBindingConverter converter, IReadOnlyList validators -) : InputSchema(property, description, converter, validators) +) : CommandInputSchema(property, description, converter, validators) { + internal override string Kind => "Parameter"; + + internal override string FormattedIdentifier => IsSequence ? $"<{Name}>" : $"<{Name}...>"; + /// /// Order, in which the parameter is bound from the command-line arguments. /// @@ -31,17 +35,15 @@ public class ParameterSchema( /// Whether the parameter is required. /// public bool IsRequired { get; } = isRequired; - - internal override string GetKind() => "Parameter"; - - internal override string GetFormattedIdentifier() => IsSequence ? $"<{Name}>" : $"<{Name}...>"; } -// Generic version of the type is used to simplify initialization from the source-generated code -// and to enforce static references to all the types used in the binding. -// The non-generic version is used internally by the framework when operating in a dynamic context. -/// -public class ParameterSchema< +/// +/// +/// Generic version of the type is used to simplify initialization from source-generated code and +/// to enforce static references to all types used in the binding. +/// The non-generic version is used internally by the framework when operating in a dynamic context. +/// +public class CommandParameterSchema< TCommand, [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods @@ -55,5 +57,5 @@ public class ParameterSchema< string? description, BindingConverter converter, IReadOnlyList> validators -) : ParameterSchema(property, order, name, isRequired, description, converter, validators) +) : CommandParameterSchema(property, order, name, isRequired, description, converter, validators) where TCommand : ICommand; diff --git a/CliFx/Schema/CommandSchema.cs b/CliFx/Schema/CommandSchema.cs index 09bd3b4..fc027c8 100644 --- a/CliFx/Schema/CommandSchema.cs +++ b/CliFx/Schema/CommandSchema.cs @@ -9,13 +9,13 @@ using CliFx.Utils.Extensions; namespace CliFx.Schema; /// -/// Describes an individual command, along with its parameter and option inputs. +/// Describes an individual command, along with its inputs. /// public class CommandSchema( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type, string? name, string? description, - IReadOnlyList inputs + IReadOnlyList inputs ) { /// @@ -40,29 +40,29 @@ public class CommandSchema( public string? Description { get; } = description; /// - /// Inputs (parameters and options) of the command. + /// Command inputs. /// - public IReadOnlyList Inputs { get; } = inputs; + public IReadOnlyList Inputs { get; } = inputs; /// /// Parameter inputs of the command. /// - public IReadOnlyList Parameters { get; } = - inputs.OfType().ToArray(); + public IReadOnlyList Parameters { get; } = + inputs.OfType().ToArray(); /// /// Option inputs of the command. /// - public IReadOnlyList Options { get; } = inputs.OfType().ToArray(); + public IReadOnlyList Options { get; } = inputs.OfType().ToArray(); internal bool MatchesName(string? name) => !string.IsNullOrWhiteSpace(Name) ? string.Equals(name, Name, StringComparison.OrdinalIgnoreCase) : string.IsNullOrWhiteSpace(name); - internal IReadOnlyDictionary GetValues(ICommand instance) + internal IReadOnlyDictionary GetValues(ICommand instance) { - var result = new Dictionary(); + var result = new Dictionary(); foreach (var parameterSchema in Parameters) { @@ -135,7 +135,7 @@ public class CommandSchema( $""" Missing required parameter(s): {remainingRequiredParameterSchemas - .Select(p => p.GetFormattedIdentifier()) + .Select(p => p.FormattedIdentifier) .JoinToString(" ")} """ ); @@ -208,7 +208,7 @@ public class CommandSchema( $""" Missing required option(s): {remainingRequiredOptionSchemas - .Select(o => o.GetFormattedIdentifier()) + .Select(o => o.FormattedIdentifier) .JoinToString(", ")} """ ); @@ -222,12 +222,14 @@ public class CommandSchema( } } -// Generic version of the type is used to simplify initialization from the source-generated code -// and to enforce static references to all the types used in the binding. -// The non-generic version is used internally by the framework when operating in a dynamic context. /// +/// +/// Generic version of the type is used to simplify initialization from source-generated code and +/// to enforce static references to all types used in the binding. +/// The non-generic version is used internally by the framework when operating in a dynamic context. +/// public class CommandSchema< [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TCommand ->(string? name, string? description, IReadOnlyList inputs) +>(string? name, string? description, IReadOnlyList inputs) : CommandSchema(typeof(TCommand), name, description, inputs) where TCommand : ICommand; diff --git a/CliFx/Schema/PropertyBinding.cs b/CliFx/Schema/PropertyBinding.cs index 9b1b8d5..4d267d4 100644 --- a/CliFx/Schema/PropertyBinding.cs +++ b/CliFx/Schema/PropertyBinding.cs @@ -55,10 +55,12 @@ public class PropertyBinding( } } -// Generic version of the type is used to simplify initialization from the source-generated code -// and to enforce static references to all the types used in the binding. -// The non-generic version is used internally by the framework when operating in a dynamic context. /// +/// +/// Generic version of the type is used to simplify initialization from source-generated code and +/// to enforce static references to all types used in the binding. +/// The non-generic version is used internally by the framework when operating in a dynamic context. +/// public class PropertyBinding< TObject, [DynamicallyAccessedMembers(