mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Refactor with C# 12 features
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Basic.Reference.Assemblies.Net70" Version="1.4.5" />
|
<PackageReference Include="Basic.Reference.Assemblies.Net70" Version="1.4.5" />
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.0" PrivateAssets="all" />
|
<PackageReference Include="coverlet.collector" Version="6.0.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
<PackageReference Include="CSharpier.MsBuild" Version="0.26.5" PrivateAssets="all" />
|
||||||
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" PrivateAssets="all" />
|
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" PrivateAssets="all" />
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
|
|||||||
@@ -13,12 +13,10 @@ using Microsoft.CodeAnalysis.Text;
|
|||||||
|
|
||||||
namespace CliFx.Analyzers.Tests.Utils;
|
namespace CliFx.Analyzers.Tests.Utils;
|
||||||
|
|
||||||
internal class AnalyzerAssertions : ReferenceTypeAssertions<DiagnosticAnalyzer, AnalyzerAssertions>
|
internal class AnalyzerAssertions(DiagnosticAnalyzer analyzer)
|
||||||
|
: ReferenceTypeAssertions<DiagnosticAnalyzer, AnalyzerAssertions>(analyzer)
|
||||||
{
|
{
|
||||||
protected override string Identifier { get; } = "analyzer";
|
protected override string Identifier => "analyzer";
|
||||||
|
|
||||||
public AnalyzerAssertions(DiagnosticAnalyzer analyzer)
|
|
||||||
: base(analyzer) { }
|
|
||||||
|
|
||||||
private Compilation Compile(string sourceCode)
|
private Compilation Compile(string sourceCode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
<PackageReference Include="CSharpier.MsBuild" Version="0.26.5" PrivateAssets="all" />
|
||||||
<!-- Make sure to target the lowest possible version of the compiler for wider support -->
|
<!-- Make sure to target the lowest possible version of the compiler for wider support -->
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.0.0" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.0.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.0.0" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.0.0" PrivateAssets="all" />
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class CommandMustBeAnnotatedAnalyzer : AnalyzerBase
|
public class CommandMustBeAnnotatedAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public CommandMustBeAnnotatedAnalyzer()
|
|
||||||
: base(
|
|
||||||
$"Commands must be annotated with `{SymbolNames.CliFxCommandAttribute}`",
|
$"Commands must be annotated with `{SymbolNames.CliFxCommandAttribute}`",
|
||||||
$"This type must be annotated with `{SymbolNames.CliFxCommandAttribute}` in order to be a valid command."
|
$"This type must be annotated with `{SymbolNames.CliFxCommandAttribute}` in order to be a valid command."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
ClassDeclarationSyntax classDeclaration,
|
ClassDeclarationSyntax classDeclaration,
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class CommandMustImplementInterfaceAnalyzer : AnalyzerBase
|
public class CommandMustImplementInterfaceAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public CommandMustImplementInterfaceAnalyzer()
|
|
||||||
: base(
|
|
||||||
$"Commands must implement `{SymbolNames.CliFxCommandInterface}` interface",
|
$"Commands must implement `{SymbolNames.CliFxCommandInterface}` interface",
|
||||||
$"This type must implement `{SymbolNames.CliFxCommandInterface}` interface in order to be a valid command."
|
$"This type must implement `{SymbolNames.CliFxCommandInterface}` interface in order to be a valid command."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
ClassDeclarationSyntax classDeclaration,
|
ClassDeclarationSyntax classDeclaration,
|
||||||
|
|||||||
@@ -5,36 +5,26 @@ using Microsoft.CodeAnalysis;
|
|||||||
|
|
||||||
namespace CliFx.Analyzers.ObjectModel;
|
namespace CliFx.Analyzers.ObjectModel;
|
||||||
|
|
||||||
internal partial class CommandOptionSymbol : ICommandMemberSymbol
|
internal partial class CommandOptionSymbol(
|
||||||
{
|
|
||||||
public IPropertySymbol Property { get; }
|
|
||||||
|
|
||||||
public string? Name { get; }
|
|
||||||
|
|
||||||
public char? ShortName { get; }
|
|
||||||
|
|
||||||
public bool? IsRequired { get; }
|
|
||||||
|
|
||||||
public ITypeSymbol? ConverterType { get; }
|
|
||||||
|
|
||||||
public IReadOnlyList<ITypeSymbol> ValidatorTypes { get; }
|
|
||||||
|
|
||||||
public CommandOptionSymbol(
|
|
||||||
IPropertySymbol property,
|
IPropertySymbol property,
|
||||||
string? name,
|
string? name,
|
||||||
char? shortName,
|
char? shortName,
|
||||||
bool? isRequired,
|
bool? isRequired,
|
||||||
ITypeSymbol? converterType,
|
ITypeSymbol? converterType,
|
||||||
IReadOnlyList<ITypeSymbol> validatorTypes
|
IReadOnlyList<ITypeSymbol> validatorTypes
|
||||||
)
|
) : ICommandMemberSymbol
|
||||||
{
|
{
|
||||||
Property = property;
|
public IPropertySymbol Property { get; } = property;
|
||||||
Name = name;
|
|
||||||
ShortName = shortName;
|
public string? Name { get; } = name;
|
||||||
IsRequired = isRequired;
|
|
||||||
ConverterType = converterType;
|
public char? ShortName { get; } = shortName;
|
||||||
ValidatorTypes = validatorTypes;
|
|
||||||
}
|
public bool? IsRequired { get; } = isRequired;
|
||||||
|
|
||||||
|
public ITypeSymbol? ConverterType { get; } = converterType;
|
||||||
|
|
||||||
|
public IReadOnlyList<ITypeSymbol> ValidatorTypes { get; } = validatorTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal partial class CommandOptionSymbol
|
internal partial class CommandOptionSymbol
|
||||||
|
|||||||
@@ -5,36 +5,26 @@ using Microsoft.CodeAnalysis;
|
|||||||
|
|
||||||
namespace CliFx.Analyzers.ObjectModel;
|
namespace CliFx.Analyzers.ObjectModel;
|
||||||
|
|
||||||
internal partial class CommandParameterSymbol : ICommandMemberSymbol
|
internal partial class CommandParameterSymbol(
|
||||||
{
|
|
||||||
public IPropertySymbol Property { get; }
|
|
||||||
|
|
||||||
public int Order { get; }
|
|
||||||
|
|
||||||
public string? Name { get; }
|
|
||||||
|
|
||||||
public bool? IsRequired { get; }
|
|
||||||
|
|
||||||
public ITypeSymbol? ConverterType { get; }
|
|
||||||
|
|
||||||
public IReadOnlyList<ITypeSymbol> ValidatorTypes { get; }
|
|
||||||
|
|
||||||
public CommandParameterSymbol(
|
|
||||||
IPropertySymbol property,
|
IPropertySymbol property,
|
||||||
int order,
|
int order,
|
||||||
string? name,
|
string? name,
|
||||||
bool? isRequired,
|
bool? isRequired,
|
||||||
ITypeSymbol? converterType,
|
ITypeSymbol? converterType,
|
||||||
IReadOnlyList<ITypeSymbol> validatorTypes
|
IReadOnlyList<ITypeSymbol> validatorTypes
|
||||||
)
|
) : ICommandMemberSymbol
|
||||||
{
|
{
|
||||||
Property = property;
|
public IPropertySymbol Property { get; } = property;
|
||||||
Order = order;
|
|
||||||
Name = name;
|
public int Order { get; } = order;
|
||||||
IsRequired = isRequired;
|
|
||||||
ConverterType = converterType;
|
public string? Name { get; } = name;
|
||||||
ValidatorTypes = validatorTypes;
|
|
||||||
}
|
public bool? IsRequired { get; } = isRequired;
|
||||||
|
|
||||||
|
public ITypeSymbol? ConverterType { get; } = converterType;
|
||||||
|
|
||||||
|
public IReadOnlyList<ITypeSymbol> ValidatorTypes { get; } = validatorTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal partial class CommandParameterSymbol
|
internal partial class CommandParameterSymbol
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustBeInsideCommandAnalyzer : AnalyzerBase
|
public class OptionMustBeInsideCommandAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustBeInsideCommandAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Options must be defined inside commands",
|
"Options must be defined inside commands",
|
||||||
$"This option must be defined inside a class that implements `{SymbolNames.CliFxCommandInterface}`."
|
$"This option must be defined inside a class that implements `{SymbolNames.CliFxCommandInterface}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustBeRequiredIfPropertyRequiredAnalyzer : AnalyzerBase
|
public class OptionMustBeRequiredIfPropertyRequiredAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustBeRequiredIfPropertyRequiredAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Options bound to required properties cannot be marked as non-required",
|
"Options bound to required properties cannot be marked as non-required",
|
||||||
"This option cannot be marked as non-required because it's bound to a required property."
|
"This option cannot be marked as non-required because it's bound to a required property."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustHaveNameOrShortNameAnalyzer : AnalyzerBase
|
public class OptionMustHaveNameOrShortNameAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustHaveNameOrShortNameAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Options must have either a name or short name specified",
|
"Options must have either a name or short name specified",
|
||||||
"This option must have either a name or short name specified."
|
"This option must have either a name or short name specified."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -9,16 +9,14 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustHaveUniqueNameAnalyzer : AnalyzerBase
|
public class OptionMustHaveUniqueNameAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustHaveUniqueNameAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Options must have unique names",
|
"Options must have unique names",
|
||||||
"This option's name must be unique within the command (comparison IS NOT case sensitive). "
|
"This option's name must be unique within the command (comparison IS NOT case sensitive). "
|
||||||
+ "Specified name: `{0}`. "
|
+ "Specified name: `{0}`. "
|
||||||
+ "Property bound to another option with the same name: `{1}`."
|
+ "Property bound to another option with the same name: `{1}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,16 +8,14 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustHaveUniqueShortNameAnalyzer : AnalyzerBase
|
public class OptionMustHaveUniqueShortNameAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustHaveUniqueShortNameAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Options must have unique short names",
|
"Options must have unique short names",
|
||||||
"This option's short name must be unique within the command (comparison IS case sensitive). "
|
"This option's short name must be unique within the command (comparison IS case sensitive). "
|
||||||
+ "Specified short name: `{0}` "
|
+ "Specified short name: `{0}` "
|
||||||
+ "Property bound to another option with the same short name: `{1}`."
|
+ "Property bound to another option with the same short name: `{1}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustHaveValidConverterAnalyzer : AnalyzerBase
|
public class OptionMustHaveValidConverterAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustHaveValidConverterAnalyzer()
|
|
||||||
: base(
|
|
||||||
$"Option converters must derive from `{SymbolNames.CliFxBindingConverterClass}`",
|
$"Option converters must derive from `{SymbolNames.CliFxBindingConverterClass}`",
|
||||||
$"Converter specified for this option must derive from a compatible `{SymbolNames.CliFxBindingConverterClass}`."
|
$"Converter specified for this option must derive from a compatible `{SymbolNames.CliFxBindingConverterClass}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -7,15 +7,13 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustHaveValidNameAnalyzer : AnalyzerBase
|
public class OptionMustHaveValidNameAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustHaveValidNameAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Options must have valid names",
|
"Options must have valid names",
|
||||||
"This option's name must be at least 2 characters long and must start with a letter. "
|
"This option's name must be at least 2 characters long and must start with a letter. "
|
||||||
+ "Specified name: `{0}`."
|
+ "Specified name: `{0}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -7,15 +7,13 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustHaveValidShortNameAnalyzer : AnalyzerBase
|
public class OptionMustHaveValidShortNameAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustHaveValidShortNameAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Option short names must be letter characters",
|
"Option short names must be letter characters",
|
||||||
"This option's short name must be a single letter character. "
|
"This option's short name must be a single letter character. "
|
||||||
+ "Specified short name: `{0}`."
|
+ "Specified short name: `{0}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class OptionMustHaveValidValidatorsAnalyzer : AnalyzerBase
|
public class OptionMustHaveValidValidatorsAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public OptionMustHaveValidValidatorsAnalyzer()
|
|
||||||
: base(
|
|
||||||
$"Option validators must derive from `{SymbolNames.CliFxBindingValidatorClass}`",
|
$"Option validators must derive from `{SymbolNames.CliFxBindingValidatorClass}`",
|
||||||
$"Each validator specified for this option must derive from a compatible `{SymbolNames.CliFxBindingValidatorClass}`."
|
$"Each validator specified for this option must derive from a compatible `{SymbolNames.CliFxBindingValidatorClass}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustBeInsideCommandAnalyzer : AnalyzerBase
|
public class ParameterMustBeInsideCommandAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustBeInsideCommandAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Parameters must be defined inside commands",
|
"Parameters must be defined inside commands",
|
||||||
$"This parameter must be defined inside a class that implements `{SymbolNames.CliFxCommandInterface}`."
|
$"This parameter must be defined inside a class that implements `{SymbolNames.CliFxCommandInterface}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,15 +8,13 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustBeLastIfNonRequiredAnalyzer : AnalyzerBase
|
public class ParameterMustBeLastIfNonRequiredAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustBeLastIfNonRequiredAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Parameters marked as non-required must be the last in order",
|
"Parameters marked as non-required must be the last in order",
|
||||||
"This parameter is non-required so it must be the last in order (its order must be highest within the command). "
|
"This parameter is non-required so it must be the last in order (its order must be highest within the command). "
|
||||||
+ "Property bound to another non-required parameter: `{0}`."
|
+ "Property bound to another non-required parameter: `{0}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,15 +8,13 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustBeLastIfNonScalarAnalyzer : AnalyzerBase
|
public class ParameterMustBeLastIfNonScalarAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustBeLastIfNonScalarAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Parameters of non-scalar types must be the last in order",
|
"Parameters of non-scalar types must be the last in order",
|
||||||
"This parameter has a non-scalar type so it must be the last in order (its order must be highest within the command). "
|
"This parameter has a non-scalar type so it must be the last in order (its order must be highest within the command). "
|
||||||
+ "Property bound to another non-scalar parameter: `{0}`."
|
+ "Property bound to another non-scalar parameter: `{0}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustBeRequiredIfPropertyRequiredAnalyzer : AnalyzerBase
|
public class ParameterMustBeRequiredIfPropertyRequiredAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustBeRequiredIfPropertyRequiredAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Parameters bound to required properties cannot be marked as non-required",
|
"Parameters bound to required properties cannot be marked as non-required",
|
||||||
"This parameter cannot be marked as non-required because it's bound to a required property."
|
"This parameter cannot be marked as non-required because it's bound to a required property."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,15 +8,13 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustBeSingleIfNonRequiredAnalyzer : AnalyzerBase
|
public class ParameterMustBeSingleIfNonRequiredAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustBeSingleIfNonRequiredAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Parameters marked as non-required are limited to one per command",
|
"Parameters marked as non-required are limited to one per command",
|
||||||
"This parameter is non-required so it must be the only such parameter in the command. "
|
"This parameter is non-required so it must be the only such parameter in the command. "
|
||||||
+ "Property bound to another non-required parameter: `{0}`."
|
+ "Property bound to another non-required parameter: `{0}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,15 +8,13 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustBeSingleIfNonScalarAnalyzer : AnalyzerBase
|
public class ParameterMustBeSingleIfNonScalarAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustBeSingleIfNonScalarAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Parameters of non-scalar types are limited to one per command",
|
"Parameters of non-scalar types are limited to one per command",
|
||||||
"This parameter has a non-scalar type so it must be the only such parameter in the command. "
|
"This parameter has a non-scalar type so it must be the only such parameter in the command. "
|
||||||
+ "Property bound to another non-scalar parameter: `{0}`."
|
+ "Property bound to another non-scalar parameter: `{0}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -9,16 +9,14 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustHaveUniqueNameAnalyzer : AnalyzerBase
|
public class ParameterMustHaveUniqueNameAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustHaveUniqueNameAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Parameters must have unique names",
|
"Parameters must have unique names",
|
||||||
"This parameter's name must be unique within the command (comparison IS NOT case sensitive). "
|
"This parameter's name must be unique within the command (comparison IS NOT case sensitive). "
|
||||||
+ "Specified name: `{0}`. "
|
+ "Specified name: `{0}`. "
|
||||||
+ "Property bound to another parameter with the same name: `{1}`."
|
+ "Property bound to another parameter with the same name: `{1}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,16 +8,14 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustHaveUniqueOrderAnalyzer : AnalyzerBase
|
public class ParameterMustHaveUniqueOrderAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustHaveUniqueOrderAnalyzer()
|
|
||||||
: base(
|
|
||||||
"Parameters must have unique order",
|
"Parameters must have unique order",
|
||||||
"This parameter's order must be unique within the command. "
|
"This parameter's order must be unique within the command. "
|
||||||
+ "Specified order: {0}. "
|
+ "Specified order: {0}. "
|
||||||
+ "Property bound to another parameter with the same order: `{1}`."
|
+ "Property bound to another parameter with the same order: `{1}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustHaveValidConverterAnalyzer : AnalyzerBase
|
public class ParameterMustHaveValidConverterAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustHaveValidConverterAnalyzer()
|
|
||||||
: base(
|
|
||||||
$"Parameter converters must derive from `{SymbolNames.CliFxBindingConverterClass}`",
|
$"Parameter converters must derive from `{SymbolNames.CliFxBindingConverterClass}`",
|
||||||
$"Converter specified for this parameter must derive from a compatible `{SymbolNames.CliFxBindingConverterClass}`."
|
$"Converter specified for this parameter must derive from a compatible `{SymbolNames.CliFxBindingConverterClass}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class ParameterMustHaveValidValidatorsAnalyzer : AnalyzerBase
|
public class ParameterMustHaveValidValidatorsAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public ParameterMustHaveValidValidatorsAnalyzer()
|
|
||||||
: base(
|
|
||||||
$"Parameter validators must derive from `{SymbolNames.CliFxBindingValidatorClass}`",
|
$"Parameter validators must derive from `{SymbolNames.CliFxBindingValidatorClass}`",
|
||||||
$"Each validator specified for this parameter must derive from a compatible `{SymbolNames.CliFxBindingValidatorClass}`."
|
$"Each validator specified for this parameter must derive from a compatible `{SymbolNames.CliFxBindingValidatorClass}`."
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private void Analyze(
|
private void Analyze(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
PropertyDeclarationSyntax propertyDeclaration,
|
PropertyDeclarationSyntax propertyDeclaration,
|
||||||
|
|||||||
@@ -9,15 +9,13 @@ using Microsoft.CodeAnalysis.Diagnostics;
|
|||||||
namespace CliFx.Analyzers;
|
namespace CliFx.Analyzers;
|
||||||
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||||
public class SystemConsoleShouldBeAvoidedAnalyzer : AnalyzerBase
|
public class SystemConsoleShouldBeAvoidedAnalyzer()
|
||||||
{
|
: AnalyzerBase(
|
||||||
public SystemConsoleShouldBeAvoidedAnalyzer()
|
|
||||||
: base(
|
|
||||||
$"Avoid calling `System.Console` where `{SymbolNames.CliFxConsoleInterface}` is available",
|
$"Avoid calling `System.Console` where `{SymbolNames.CliFxConsoleInterface}` is available",
|
||||||
$"Use the provided `{SymbolNames.CliFxConsoleInterface}` abstraction instead of `System.Console` to ensure that the command can be tested in isolation.",
|
$"Use the provided `{SymbolNames.CliFxConsoleInterface}` abstraction instead of `System.Console` to ensure that the command can be tested in isolation.",
|
||||||
DiagnosticSeverity.Warning
|
DiagnosticSeverity.Warning
|
||||||
) { }
|
)
|
||||||
|
{
|
||||||
private MemberAccessExpressionSyntax? TryGetSystemConsoleMemberAccess(
|
private MemberAccessExpressionSyntax? TryGetSystemConsoleMemberAccess(
|
||||||
SyntaxNodeAnalysisContext context,
|
SyntaxNodeAnalysisContext context,
|
||||||
SyntaxNode node
|
SyntaxNode node
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.10" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.11" />
|
||||||
<PackageReference Include="clipr" Version="1.6.1" />
|
<PackageReference Include="clipr" Version="1.6.1" />
|
||||||
<PackageReference Include="Cocona" Version="2.2.0" />
|
<PackageReference Include="Cocona" Version="2.2.0" />
|
||||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
<PackageReference Include="CSharpier.MsBuild" Version="0.26.5" PrivateAssets="all" />
|
||||||
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="4.1.0" />
|
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="4.1.0" />
|
||||||
<PackageReference Include="PowerArgs" Version="4.0.3" />
|
<PackageReference Include="PowerArgs" Version="4.0.3" />
|
||||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20574.7" />
|
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20574.7" />
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
<PackageReference Include="CSharpier.MsBuild" Version="0.26.5" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,8 @@ using CliFx.Infrastructure;
|
|||||||
namespace CliFx.Demo.Commands;
|
namespace CliFx.Demo.Commands;
|
||||||
|
|
||||||
[Command("book add", Description = "Adds a book to the library.")]
|
[Command("book add", Description = "Adds a book to the library.")]
|
||||||
public partial class BookAddCommand : ICommand
|
public partial class BookAddCommand(LibraryProvider libraryProvider) : ICommand
|
||||||
{
|
{
|
||||||
private readonly LibraryProvider _libraryProvider;
|
|
||||||
|
|
||||||
[CommandParameter(0, Name = "title", Description = "Book title.")]
|
[CommandParameter(0, Name = "title", Description = "Book title.")]
|
||||||
public required string Title { get; init; }
|
public required string Title { get; init; }
|
||||||
|
|
||||||
@@ -25,18 +23,13 @@ public partial class BookAddCommand : ICommand
|
|||||||
[CommandOption("isbn", 'n', Description = "Book ISBN.")]
|
[CommandOption("isbn", 'n', Description = "Book ISBN.")]
|
||||||
public Isbn Isbn { get; init; } = CreateRandomIsbn();
|
public Isbn Isbn { get; init; } = CreateRandomIsbn();
|
||||||
|
|
||||||
public BookAddCommand(LibraryProvider libraryProvider)
|
|
||||||
{
|
|
||||||
_libraryProvider = libraryProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask ExecuteAsync(IConsole console)
|
public ValueTask ExecuteAsync(IConsole console)
|
||||||
{
|
{
|
||||||
if (_libraryProvider.TryGetBook(Title) is not null)
|
if (libraryProvider.TryGetBook(Title) is not null)
|
||||||
throw new CommandException("Book already exists.", 10);
|
throw new CommandException("Book already exists.", 10);
|
||||||
|
|
||||||
var book = new Book(Title, Author, Published, Isbn);
|
var book = new Book(Title, Author, Published, Isbn);
|
||||||
_libraryProvider.AddBook(book);
|
libraryProvider.AddBook(book);
|
||||||
|
|
||||||
console.Output.WriteLine("Book added.");
|
console.Output.WriteLine("Book added.");
|
||||||
console.Output.WriteBook(book);
|
console.Output.WriteBook(book);
|
||||||
|
|||||||
@@ -8,21 +8,14 @@ using CliFx.Infrastructure;
|
|||||||
namespace CliFx.Demo.Commands;
|
namespace CliFx.Demo.Commands;
|
||||||
|
|
||||||
[Command("book", Description = "Retrieves a book from the library.")]
|
[Command("book", Description = "Retrieves a book from the library.")]
|
||||||
public class BookCommand : ICommand
|
public class BookCommand(LibraryProvider libraryProvider) : ICommand
|
||||||
{
|
{
|
||||||
private readonly LibraryProvider _libraryProvider;
|
|
||||||
|
|
||||||
[CommandParameter(0, Name = "title", Description = "Title of the book to retrieve.")]
|
[CommandParameter(0, Name = "title", Description = "Title of the book to retrieve.")]
|
||||||
public required string Title { get; init; }
|
public required string Title { get; init; }
|
||||||
|
|
||||||
public BookCommand(LibraryProvider libraryProvider)
|
|
||||||
{
|
|
||||||
_libraryProvider = libraryProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask ExecuteAsync(IConsole console)
|
public ValueTask ExecuteAsync(IConsole console)
|
||||||
{
|
{
|
||||||
var book = _libraryProvider.TryGetBook(Title);
|
var book = libraryProvider.TryGetBook(Title);
|
||||||
|
|
||||||
if (book is null)
|
if (book is null)
|
||||||
throw new CommandException("Book not found.", 10);
|
throw new CommandException("Book not found.", 10);
|
||||||
|
|||||||
@@ -7,18 +7,11 @@ using CliFx.Infrastructure;
|
|||||||
namespace CliFx.Demo.Commands;
|
namespace CliFx.Demo.Commands;
|
||||||
|
|
||||||
[Command("book list", Description = "Lists all books in the library.")]
|
[Command("book list", Description = "Lists all books in the library.")]
|
||||||
public class BookListCommand : ICommand
|
public class BookListCommand(LibraryProvider libraryProvider) : ICommand
|
||||||
{
|
{
|
||||||
private readonly LibraryProvider _libraryProvider;
|
|
||||||
|
|
||||||
public BookListCommand(LibraryProvider libraryProvider)
|
|
||||||
{
|
|
||||||
_libraryProvider = libraryProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask ExecuteAsync(IConsole console)
|
public ValueTask ExecuteAsync(IConsole console)
|
||||||
{
|
{
|
||||||
var library = _libraryProvider.GetLibrary();
|
var library = libraryProvider.GetLibrary();
|
||||||
|
|
||||||
for (var i = 0; i < library.Books.Count; i++)
|
for (var i = 0; i < library.Books.Count; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,26 +7,19 @@ using CliFx.Infrastructure;
|
|||||||
namespace CliFx.Demo.Commands;
|
namespace CliFx.Demo.Commands;
|
||||||
|
|
||||||
[Command("book remove", Description = "Removes a book from the library.")]
|
[Command("book remove", Description = "Removes a book from the library.")]
|
||||||
public class BookRemoveCommand : ICommand
|
public class BookRemoveCommand(LibraryProvider libraryProvider) : ICommand
|
||||||
{
|
{
|
||||||
private readonly LibraryProvider _libraryProvider;
|
|
||||||
|
|
||||||
[CommandParameter(0, Name = "title", Description = "Title of the book to remove.")]
|
[CommandParameter(0, Name = "title", Description = "Title of the book to remove.")]
|
||||||
public required string Title { get; init; }
|
public required string Title { get; init; }
|
||||||
|
|
||||||
public BookRemoveCommand(LibraryProvider libraryProvider)
|
|
||||||
{
|
|
||||||
_libraryProvider = libraryProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask ExecuteAsync(IConsole console)
|
public ValueTask ExecuteAsync(IConsole console)
|
||||||
{
|
{
|
||||||
var book = _libraryProvider.TryGetBook(Title);
|
var book = libraryProvider.TryGetBook(Title);
|
||||||
|
|
||||||
if (book is null)
|
if (book is null)
|
||||||
throw new CommandException("Book not found.", 10);
|
throw new CommandException("Book not found.", 10);
|
||||||
|
|
||||||
_libraryProvider.RemoveBook(book);
|
libraryProvider.RemoveBook(book);
|
||||||
|
|
||||||
console.Output.WriteLine($"Book {Title} removed.");
|
console.Output.WriteLine($"Book {Title} removed.");
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
<PackageReference Include="CSharpier.MsBuild" Version="0.26.5" PrivateAssets="all" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -8,11 +8,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class ApplicationSpecs : SpecsBase
|
public class ApplicationSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public ApplicationSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_create_an_application_with_the_default_configuration()
|
public async Task I_can_create_an_application_with_the_default_configuration()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,11 +12,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class CancellationSpecs : SpecsBase
|
public class CancellationSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public CancellationSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact(Timeout = 15000)]
|
[Fact(Timeout = 15000)]
|
||||||
public async Task I_can_configure_the_command_to_listen_to_the_interrupt_signal()
|
public async Task I_can_configure_the_command_to_listen_to_the_interrupt_signal()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,15 +12,15 @@
|
|||||||
<PackageReference Include="Basic.Reference.Assemblies.Net70" Version="1.4.5" />
|
<PackageReference Include="Basic.Reference.Assemblies.Net70" Version="1.4.5" />
|
||||||
<PackageReference Include="CliWrap" Version="3.6.4" />
|
<PackageReference Include="CliWrap" Version="3.6.4" />
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.0" PrivateAssets="all" />
|
<PackageReference Include="coverlet.collector" Version="6.0.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
<PackageReference Include="CSharpier.MsBuild" Version="0.26.5" PrivateAssets="all" />
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||||
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" PrivateAssets="all" />
|
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
<PackageReference Include="PolyShim" Version="1.8.0" PrivateAssets="all" />
|
<PackageReference Include="PolyShim" Version="1.8.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="xunit" Version="2.6.1" />
|
<PackageReference Include="xunit" Version="2.6.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" PrivateAssets="all" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.5" PrivateAssets="all" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -14,11 +14,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class ConsoleSpecs : SpecsBase
|
public class ConsoleSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public ConsoleSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact(Timeout = 15000)]
|
[Fact(Timeout = 15000)]
|
||||||
public async Task I_can_run_the_application_with_the_default_console_implementation_to_interact_with_the_system_console()
|
public async Task I_can_run_the_application_with_the_default_console_implementation_to_interact_with_the_system_console()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,11 +8,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class ConversionSpecs : SpecsBase
|
public class ConversionSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public ConversionSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_bind_a_parameter_or_an_option_to_a_string_property()
|
public async Task I_can_bind_a_parameter_or_an_option_to_a_string_property()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,11 +11,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class DirectivesSpecs : SpecsBase
|
public class DirectivesSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public DirectivesSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact(Timeout = 15000)]
|
[Fact(Timeout = 15000)]
|
||||||
public async Task I_can_use_the_debug_directive_to_make_the_application_wait_for_the_debugger_to_attach()
|
public async Task I_can_use_the_debug_directive_to_make_the_application_wait_for_the_debugger_to_attach()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,11 +12,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class EnvironmentSpecs : SpecsBase
|
public class EnvironmentSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public EnvironmentSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_configure_an_option_to_fall_back_to_an_environment_variable_if_the_user_does_not_provide_the_corresponding_argument()
|
public async Task I_can_configure_an_option_to_fall_back_to_an_environment_variable_if_the_user_does_not_provide_the_corresponding_argument()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class ErrorReportingSpecs : SpecsBase
|
public class ErrorReportingSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public ErrorReportingSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_throw_an_exception_in_a_command_to_report_an_error_with_a_stacktrace()
|
public async Task I_can_throw_an_exception_in_a_command_to_report_an_error_with_a_stacktrace()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class HelpTextSpecs : SpecsBase
|
public class HelpTextSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public HelpTextSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_request_the_help_text_by_running_the_application_without_arguments_if_the_default_command_is_not_defined()
|
public async Task I_can_request_the_help_text_by_running_the_application_without_arguments_if_the_default_command_is_not_defined()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class OptionBindingSpecs : SpecsBase
|
public class OptionBindingSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public OptionBindingSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_bind_an_option_to_a_property_and_get_the_value_from_the_corresponding_argument_by_name()
|
public async Task I_can_bind_an_option_to_a_property_and_get_the_value_from_the_corresponding_argument_by_name()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,11 +8,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class ParameterBindingSpecs : SpecsBase
|
public class ParameterBindingSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public ParameterBindingSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_bind_a_parameter_to_a_property_and_get_the_value_from_the_corresponding_argument()
|
public async Task I_can_bind_a_parameter_to_a_property_and_get_the_value_from_the_corresponding_argument()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,11 +8,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class RoutingSpecs : SpecsBase
|
public class RoutingSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public RoutingSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_configure_a_command_to_be_executed_by_default_when_the_user_does_not_specify_a_command_name()
|
public async Task I_can_configure_a_command_to_be_executed_by_default_when_the_user_does_not_specify_a_command_name()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public abstract class SpecsBase : IDisposable
|
public abstract class SpecsBase(ITestOutputHelper testOutput) : IDisposable
|
||||||
{
|
{
|
||||||
public ITestOutputHelper TestOutput { get; }
|
public ITestOutputHelper TestOutput { get; } = testOutput;
|
||||||
|
|
||||||
public FakeInMemoryConsole FakeConsole { get; } = new();
|
public FakeInMemoryConsole FakeConsole { get; } = new();
|
||||||
|
|
||||||
protected SpecsBase(ITestOutputHelper testOutput) => TestOutput = testOutput;
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
FakeConsole.DumpToTestOutput(TestOutput);
|
FakeConsole.DumpToTestOutput(TestOutput);
|
||||||
|
|||||||
@@ -10,11 +10,8 @@ using Xunit.Abstractions;
|
|||||||
|
|
||||||
namespace CliFx.Tests;
|
namespace CliFx.Tests;
|
||||||
|
|
||||||
public class TypeActivationSpecs : SpecsBase
|
public class TypeActivationSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
||||||
{
|
{
|
||||||
public TypeActivationSpecs(ITestOutputHelper testOutput)
|
|
||||||
: base(testOutput) { }
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_configure_the_application_to_use_the_default_type_activator_to_initialize_types_through_parameterless_constructors()
|
public async Task I_can_configure_the_application_to_use_the_default_type_activator_to_initialize_types_through_parameterless_constructors()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
<PackageReference Include="CSharpier.MsBuild" Version="0.26.5" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="PolyShim" Version="1.8.0" PrivateAssets="all" />
|
<PackageReference Include="PolyShim" Version="1.8.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
|
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
|
||||||
|
|||||||
@@ -12,22 +12,16 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx;
|
namespace CliFx;
|
||||||
|
|
||||||
internal class CommandBinder
|
internal class CommandBinder(ITypeActivator typeActivator)
|
||||||
{
|
{
|
||||||
private readonly ITypeActivator _typeActivator;
|
|
||||||
private readonly IFormatProvider _formatProvider = CultureInfo.InvariantCulture;
|
private readonly IFormatProvider _formatProvider = CultureInfo.InvariantCulture;
|
||||||
|
|
||||||
public CommandBinder(ITypeActivator typeActivator)
|
|
||||||
{
|
|
||||||
_typeActivator = typeActivator;
|
|
||||||
}
|
|
||||||
|
|
||||||
private object? ConvertSingle(IMemberSchema memberSchema, string? rawValue, Type targetType)
|
private object? ConvertSingle(IMemberSchema memberSchema, string? rawValue, Type targetType)
|
||||||
{
|
{
|
||||||
// Custom converter
|
// Custom converter
|
||||||
if (memberSchema.ConverterType is not null)
|
if (memberSchema.ConverterType is not null)
|
||||||
{
|
{
|
||||||
var converter = _typeActivator.CreateInstance<IBindingConverter>(
|
var converter = typeActivator.CreateInstance<IBindingConverter>(
|
||||||
memberSchema.ConverterType
|
memberSchema.ConverterType
|
||||||
);
|
);
|
||||||
return converter.Convert(rawValue);
|
return converter.Convert(rawValue);
|
||||||
@@ -213,7 +207,7 @@ internal class CommandBinder
|
|||||||
|
|
||||||
foreach (var validatorType in memberSchema.ValidatorTypes)
|
foreach (var validatorType in memberSchema.ValidatorTypes)
|
||||||
{
|
{
|
||||||
var validator = _typeActivator.CreateInstance<IBindingValidator>(validatorType);
|
var validator = typeActivator.CreateInstance<IBindingValidator>(validatorType);
|
||||||
var error = validator.Validate(convertedValue);
|
var error = validator.Validate(convertedValue);
|
||||||
|
|
||||||
if (error is not null)
|
if (error is not null)
|
||||||
|
|||||||
@@ -4,11 +4,9 @@ using CliFx.Input;
|
|||||||
|
|
||||||
namespace CliFx.Formatting;
|
namespace CliFx.Formatting;
|
||||||
|
|
||||||
internal class CommandInputConsoleFormatter : ConsoleFormatter
|
internal class CommandInputConsoleFormatter(ConsoleWriter consoleWriter)
|
||||||
|
: ConsoleFormatter(consoleWriter)
|
||||||
{
|
{
|
||||||
public CommandInputConsoleFormatter(ConsoleWriter consoleWriter)
|
|
||||||
: base(consoleWriter) { }
|
|
||||||
|
|
||||||
private void WriteCommandLineArguments(CommandInput commandInput)
|
private void WriteCommandLineArguments(CommandInput commandInput)
|
||||||
{
|
{
|
||||||
Write("Command-line:");
|
Write("Command-line:");
|
||||||
|
|||||||
@@ -3,50 +3,46 @@ using CliFx.Infrastructure;
|
|||||||
|
|
||||||
namespace CliFx.Formatting;
|
namespace CliFx.Formatting;
|
||||||
|
|
||||||
internal class ConsoleFormatter
|
internal class ConsoleFormatter(ConsoleWriter consoleWriter)
|
||||||
{
|
{
|
||||||
private readonly ConsoleWriter _consoleWriter;
|
|
||||||
|
|
||||||
private int _column;
|
private int _column;
|
||||||
private int _row;
|
private int _row;
|
||||||
|
|
||||||
public bool IsEmpty => _column == 0 && _row == 0;
|
public bool IsEmpty => _column == 0 && _row == 0;
|
||||||
|
|
||||||
public ConsoleFormatter(ConsoleWriter consoleWriter) => _consoleWriter = consoleWriter;
|
|
||||||
|
|
||||||
public void Write(string? value)
|
public void Write(string? value)
|
||||||
{
|
{
|
||||||
_consoleWriter.Write(value);
|
consoleWriter.Write(value);
|
||||||
_column += value?.Length ?? 0;
|
_column += value?.Length ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(char value)
|
public void Write(char value)
|
||||||
{
|
{
|
||||||
_consoleWriter.Write(value);
|
consoleWriter.Write(value);
|
||||||
_column++;
|
_column++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ConsoleColor foregroundColor, string? value)
|
public void Write(ConsoleColor foregroundColor, string? value)
|
||||||
{
|
{
|
||||||
using (_consoleWriter.Console.WithForegroundColor(foregroundColor))
|
using (consoleWriter.Console.WithForegroundColor(foregroundColor))
|
||||||
Write(value);
|
Write(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ConsoleColor foregroundColor, char value)
|
public void Write(ConsoleColor foregroundColor, char value)
|
||||||
{
|
{
|
||||||
using (_consoleWriter.Console.WithForegroundColor(foregroundColor))
|
using (consoleWriter.Console.WithForegroundColor(foregroundColor))
|
||||||
Write(value);
|
Write(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string? value)
|
public void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string? value)
|
||||||
{
|
{
|
||||||
using (_consoleWriter.Console.WithColors(foregroundColor, backgroundColor))
|
using (consoleWriter.Console.WithColors(foregroundColor, backgroundColor))
|
||||||
Write(value);
|
Write(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteLine()
|
public void WriteLine()
|
||||||
{
|
{
|
||||||
_consoleWriter.WriteLine();
|
consoleWriter.WriteLine();
|
||||||
_column = 0;
|
_column = 0;
|
||||||
_row++;
|
_row++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,9 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Formatting;
|
namespace CliFx.Formatting;
|
||||||
|
|
||||||
internal class ExceptionConsoleFormatter : ConsoleFormatter
|
internal class ExceptionConsoleFormatter(ConsoleWriter consoleWriter)
|
||||||
|
: ConsoleFormatter(consoleWriter)
|
||||||
{
|
{
|
||||||
public ExceptionConsoleFormatter(ConsoleWriter consoleWriter)
|
|
||||||
: base(consoleWriter) { }
|
|
||||||
|
|
||||||
private void WriteStackFrame(StackFrame stackFrame, int indentLevel)
|
private void WriteStackFrame(StackFrame stackFrame, int indentLevel)
|
||||||
{
|
{
|
||||||
WriteHorizontalMargin(2 + 4 * indentLevel);
|
WriteHorizontalMargin(2 + 4 * indentLevel);
|
||||||
|
|||||||
@@ -9,16 +9,9 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Formatting;
|
namespace CliFx.Formatting;
|
||||||
|
|
||||||
internal class HelpConsoleFormatter : ConsoleFormatter
|
internal class HelpConsoleFormatter(ConsoleWriter consoleWriter, HelpContext context)
|
||||||
|
: ConsoleFormatter(consoleWriter)
|
||||||
{
|
{
|
||||||
private readonly HelpContext _context;
|
|
||||||
|
|
||||||
public HelpConsoleFormatter(ConsoleWriter consoleWriter, HelpContext context)
|
|
||||||
: base(consoleWriter)
|
|
||||||
{
|
|
||||||
_context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteHeader(string text)
|
private void WriteHeader(string text)
|
||||||
{
|
{
|
||||||
Write(ConsoleColor.White, text.ToUpperInvariant());
|
Write(ConsoleColor.White, text.ToUpperInvariant());
|
||||||
@@ -27,13 +20,13 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
|
|
||||||
private void WriteCommandInvocation()
|
private void WriteCommandInvocation()
|
||||||
{
|
{
|
||||||
Write(_context.ApplicationMetadata.ExecutableName);
|
Write(context.ApplicationMetadata.ExecutableName);
|
||||||
|
|
||||||
// Command name
|
// Command name
|
||||||
if (!string.IsNullOrWhiteSpace(_context.CommandSchema.Name))
|
if (!string.IsNullOrWhiteSpace(context.CommandSchema.Name))
|
||||||
{
|
{
|
||||||
Write(' ');
|
Write(' ');
|
||||||
Write(ConsoleColor.Cyan, _context.CommandSchema.Name);
|
Write(ConsoleColor.Cyan, context.CommandSchema.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,16 +36,16 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
WriteVerticalMargin();
|
WriteVerticalMargin();
|
||||||
|
|
||||||
// Title and version
|
// Title and version
|
||||||
Write(ConsoleColor.White, _context.ApplicationMetadata.Title);
|
Write(ConsoleColor.White, context.ApplicationMetadata.Title);
|
||||||
Write(' ');
|
Write(' ');
|
||||||
Write(ConsoleColor.Yellow, _context.ApplicationMetadata.Version);
|
Write(ConsoleColor.Yellow, context.ApplicationMetadata.Version);
|
||||||
WriteLine();
|
WriteLine();
|
||||||
|
|
||||||
// Description
|
// Description
|
||||||
if (!string.IsNullOrWhiteSpace(_context.ApplicationMetadata.Description))
|
if (!string.IsNullOrWhiteSpace(context.ApplicationMetadata.Description))
|
||||||
{
|
{
|
||||||
WriteHorizontalMargin();
|
WriteHorizontalMargin();
|
||||||
Write(_context.ApplicationMetadata.Description);
|
Write(context.ApplicationMetadata.Description);
|
||||||
WriteLine();
|
WriteLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,7 +65,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
Write(' ');
|
Write(' ');
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
foreach (var parameter in _context.CommandSchema.Parameters.OrderBy(p => p.Order))
|
foreach (var parameter in context.CommandSchema.Parameters.OrderBy(p => p.Order))
|
||||||
{
|
{
|
||||||
Write(
|
Write(
|
||||||
ConsoleColor.DarkCyan,
|
ConsoleColor.DarkCyan,
|
||||||
@@ -82,7 +75,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Required options
|
// Required options
|
||||||
foreach (var option in _context.CommandSchema.Options.Where(o => o.IsRequired))
|
foreach (var option in context.CommandSchema.Options.Where(o => o.IsRequired))
|
||||||
{
|
{
|
||||||
Write(
|
Write(
|
||||||
ConsoleColor.Yellow,
|
ConsoleColor.Yellow,
|
||||||
@@ -97,7 +90,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder for non-required options
|
// Placeholder for non-required options
|
||||||
if (_context.CommandSchema.Options.Any(o => !o.IsRequired))
|
if (context.CommandSchema.Options.Any(o => !o.IsRequired))
|
||||||
{
|
{
|
||||||
Write(ConsoleColor.Yellow, "[options]");
|
Write(ConsoleColor.Yellow, "[options]");
|
||||||
}
|
}
|
||||||
@@ -106,9 +99,9 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Child command usage
|
// Child command usage
|
||||||
var childCommandSchemas = _context
|
var childCommandSchemas = context
|
||||||
.ApplicationSchema
|
.ApplicationSchema
|
||||||
.GetChildCommands(_context.CommandSchema.Name);
|
.GetChildCommands(context.CommandSchema.Name);
|
||||||
|
|
||||||
if (childCommandSchemas.Any())
|
if (childCommandSchemas.Any())
|
||||||
{
|
{
|
||||||
@@ -130,7 +123,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
|
|
||||||
private void WriteCommandDescription()
|
private void WriteCommandDescription()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(_context.CommandSchema.Description))
|
if (string.IsNullOrWhiteSpace(context.CommandSchema.Description))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!IsEmpty)
|
if (!IsEmpty)
|
||||||
@@ -140,13 +133,13 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
|
|
||||||
WriteHorizontalMargin();
|
WriteHorizontalMargin();
|
||||||
|
|
||||||
Write(_context.CommandSchema.Description);
|
Write(context.CommandSchema.Description);
|
||||||
WriteLine();
|
WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteCommandParameters()
|
private void WriteCommandParameters()
|
||||||
{
|
{
|
||||||
if (!_context.CommandSchema.Parameters.Any())
|
if (!context.CommandSchema.Parameters.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!IsEmpty)
|
if (!IsEmpty)
|
||||||
@@ -154,7 +147,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
|
|
||||||
WriteHeader("Parameters");
|
WriteHeader("Parameters");
|
||||||
|
|
||||||
foreach (var parameterSchema in _context.CommandSchema.Parameters.OrderBy(p => p.Order))
|
foreach (var parameterSchema in context.CommandSchema.Parameters.OrderBy(p => p.Order))
|
||||||
{
|
{
|
||||||
if (parameterSchema.IsRequired)
|
if (parameterSchema.IsRequired)
|
||||||
{
|
{
|
||||||
@@ -224,7 +217,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
WriteHeader("Options");
|
WriteHeader("Options");
|
||||||
|
|
||||||
foreach (
|
foreach (
|
||||||
var optionSchema in _context.CommandSchema.Options.OrderByDescending(o => o.IsRequired)
|
var optionSchema in context.CommandSchema.Options.OrderByDescending(o => o.IsRequired)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (optionSchema.IsRequired)
|
if (optionSchema.IsRequired)
|
||||||
@@ -314,7 +307,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
|
|
||||||
private void WriteDefaultValue(IMemberSchema schema)
|
private void WriteDefaultValue(IMemberSchema schema)
|
||||||
{
|
{
|
||||||
var defaultValue = _context.CommandDefaultValues.GetValueOrDefault(schema);
|
var defaultValue = context.CommandDefaultValues.GetValueOrDefault(schema);
|
||||||
if (defaultValue is not null)
|
if (defaultValue is not null)
|
||||||
{
|
{
|
||||||
// Non-Scalar
|
// Non-Scalar
|
||||||
@@ -365,9 +358,9 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
|
|
||||||
private void WriteCommandChildren()
|
private void WriteCommandChildren()
|
||||||
{
|
{
|
||||||
var childCommandSchemas = _context
|
var childCommandSchemas = context
|
||||||
.ApplicationSchema
|
.ApplicationSchema
|
||||||
.GetChildCommands(_context.CommandSchema.Name)
|
.GetChildCommands(context.CommandSchema.Name)
|
||||||
.OrderBy(a => a.Name, StringComparer.Ordinal)
|
.OrderBy(a => a.Name, StringComparer.Ordinal)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
@@ -386,7 +379,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
Write(
|
Write(
|
||||||
ConsoleColor.Cyan,
|
ConsoleColor.Cyan,
|
||||||
// Relative to current command
|
// Relative to current command
|
||||||
childCommandSchema.Name?.Substring(_context.CommandSchema.Name?.Length ?? 0).Trim()
|
childCommandSchema.Name?.Substring(context.CommandSchema.Name?.Length ?? 0).Trim()
|
||||||
);
|
);
|
||||||
|
|
||||||
WriteColumnMargin();
|
WriteColumnMargin();
|
||||||
@@ -399,7 +392,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Child commands of child command
|
// Child commands of child command
|
||||||
var grandChildCommandSchemas = _context
|
var grandChildCommandSchemas = context
|
||||||
.ApplicationSchema
|
.ApplicationSchema
|
||||||
.GetChildCommands(childCommandSchema.Name)
|
.GetChildCommands(childCommandSchema.Name)
|
||||||
.OrderBy(c => c.Name, StringComparer.Ordinal)
|
.OrderBy(c => c.Name, StringComparer.Ordinal)
|
||||||
@@ -426,7 +419,7 @@ internal class HelpConsoleFormatter : ConsoleFormatter
|
|||||||
// Relative to current command (not the parent)
|
// Relative to current command (not the parent)
|
||||||
grandChildCommandSchema
|
grandChildCommandSchema
|
||||||
.Name
|
.Name
|
||||||
?.Substring(_context.CommandSchema.Name?.Length ?? 0)
|
?.Substring(context.CommandSchema.Name?.Length ?? 0)
|
||||||
.Trim()
|
.Trim()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,26 +3,19 @@ using CliFx.Schema;
|
|||||||
|
|
||||||
namespace CliFx.Formatting;
|
namespace CliFx.Formatting;
|
||||||
|
|
||||||
internal class HelpContext
|
internal class HelpContext(
|
||||||
{
|
|
||||||
public ApplicationMetadata ApplicationMetadata { get; }
|
|
||||||
|
|
||||||
public ApplicationSchema ApplicationSchema { get; }
|
|
||||||
|
|
||||||
public CommandSchema CommandSchema { get; }
|
|
||||||
|
|
||||||
public IReadOnlyDictionary<IMemberSchema, object?> CommandDefaultValues { get; }
|
|
||||||
|
|
||||||
public HelpContext(
|
|
||||||
ApplicationMetadata applicationMetadata,
|
ApplicationMetadata applicationMetadata,
|
||||||
ApplicationSchema applicationSchema,
|
ApplicationSchema applicationSchema,
|
||||||
CommandSchema commandSchema,
|
CommandSchema commandSchema,
|
||||||
IReadOnlyDictionary<IMemberSchema, object?> commandDefaultValues
|
IReadOnlyDictionary<IMemberSchema, object?> commandDefaultValues
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ApplicationMetadata = applicationMetadata;
|
public ApplicationMetadata ApplicationMetadata { get; } = applicationMetadata;
|
||||||
ApplicationSchema = applicationSchema;
|
|
||||||
CommandSchema = commandSchema;
|
public ApplicationSchema ApplicationSchema { get; } = applicationSchema;
|
||||||
CommandDefaultValues = commandDefaultValues;
|
|
||||||
}
|
public CommandSchema CommandSchema { get; } = commandSchema;
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<IMemberSchema, object?> CommandDefaultValues { get; } =
|
||||||
|
commandDefaultValues;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,24 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Input;
|
namespace CliFx.Input;
|
||||||
|
|
||||||
internal partial class CommandInput
|
internal partial class CommandInput(
|
||||||
|
string? commandName,
|
||||||
|
IReadOnlyList<DirectiveInput> directives,
|
||||||
|
IReadOnlyList<ParameterInput> parameters,
|
||||||
|
IReadOnlyList<OptionInput> options,
|
||||||
|
IReadOnlyList<EnvironmentVariableInput> environmentVariables
|
||||||
|
)
|
||||||
{
|
{
|
||||||
public string? CommandName { get; }
|
public string? CommandName { get; } = commandName;
|
||||||
|
|
||||||
public IReadOnlyList<DirectiveInput> Directives { get; }
|
public IReadOnlyList<DirectiveInput> Directives { get; } = directives;
|
||||||
|
|
||||||
public IReadOnlyList<ParameterInput> Parameters { get; }
|
public IReadOnlyList<ParameterInput> Parameters { get; } = parameters;
|
||||||
|
|
||||||
public IReadOnlyList<OptionInput> Options { get; }
|
public IReadOnlyList<OptionInput> Options { get; } = options;
|
||||||
|
|
||||||
public IReadOnlyList<EnvironmentVariableInput> EnvironmentVariables { get; }
|
public IReadOnlyList<EnvironmentVariableInput> EnvironmentVariables { get; } =
|
||||||
|
environmentVariables;
|
||||||
|
|
||||||
public bool HasArguments =>
|
public bool HasArguments =>
|
||||||
!string.IsNullOrWhiteSpace(CommandName)
|
!string.IsNullOrWhiteSpace(CommandName)
|
||||||
@@ -30,21 +37,6 @@ internal partial class CommandInput
|
|||||||
public bool IsHelpOptionSpecified => Options.Any(o => o.IsHelpOption);
|
public bool IsHelpOptionSpecified => Options.Any(o => o.IsHelpOption);
|
||||||
|
|
||||||
public bool IsVersionOptionSpecified => Options.Any(o => o.IsVersionOption);
|
public bool IsVersionOptionSpecified => Options.Any(o => o.IsVersionOption);
|
||||||
|
|
||||||
public CommandInput(
|
|
||||||
string? commandName,
|
|
||||||
IReadOnlyList<DirectiveInput> directives,
|
|
||||||
IReadOnlyList<ParameterInput> parameters,
|
|
||||||
IReadOnlyList<OptionInput> options,
|
|
||||||
IReadOnlyList<EnvironmentVariableInput> environmentVariables
|
|
||||||
)
|
|
||||||
{
|
|
||||||
CommandName = commandName;
|
|
||||||
Directives = directives;
|
|
||||||
Parameters = parameters;
|
|
||||||
Options = options;
|
|
||||||
EnvironmentVariables = environmentVariables;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal partial class CommandInput
|
internal partial class CommandInput
|
||||||
|
|||||||
@@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
namespace CliFx.Input;
|
namespace CliFx.Input;
|
||||||
|
|
||||||
internal class DirectiveInput
|
internal class DirectiveInput(string name)
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; } = name;
|
||||||
|
|
||||||
public bool IsDebugDirective =>
|
public bool IsDebugDirective =>
|
||||||
string.Equals(Name, "debug", StringComparison.OrdinalIgnoreCase);
|
string.Equals(Name, "debug", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public bool IsPreviewDirective =>
|
public bool IsPreviewDirective =>
|
||||||
string.Equals(Name, "preview", StringComparison.OrdinalIgnoreCase);
|
string.Equals(Name, "preview", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public DirectiveInput(string name) => Name = name;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,11 @@ using System.IO;
|
|||||||
|
|
||||||
namespace CliFx.Input;
|
namespace CliFx.Input;
|
||||||
|
|
||||||
internal class EnvironmentVariableInput
|
internal class EnvironmentVariableInput(string name, string value)
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; } = name;
|
||||||
|
|
||||||
public string Value { get; }
|
public string Value { get; } = value;
|
||||||
|
|
||||||
public EnvironmentVariableInput(string name, string value)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<string> SplitValues() => Value.Split(Path.PathSeparator);
|
public IReadOnlyList<string> SplitValues() => Value.Split(Path.PathSeparator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,22 +3,16 @@ using CliFx.Schema;
|
|||||||
|
|
||||||
namespace CliFx.Input;
|
namespace CliFx.Input;
|
||||||
|
|
||||||
internal class OptionInput
|
internal class OptionInput(string identifier, IReadOnlyList<string> values)
|
||||||
{
|
{
|
||||||
public string Identifier { get; }
|
public string Identifier { get; } = identifier;
|
||||||
|
|
||||||
public IReadOnlyList<string> Values { get; }
|
public IReadOnlyList<string> Values { get; } = values;
|
||||||
|
|
||||||
public bool IsHelpOption => OptionSchema.HelpOption.MatchesIdentifier(Identifier);
|
public bool IsHelpOption => OptionSchema.HelpOption.MatchesIdentifier(Identifier);
|
||||||
|
|
||||||
public bool IsVersionOption => OptionSchema.VersionOption.MatchesIdentifier(Identifier);
|
public bool IsVersionOption => OptionSchema.VersionOption.MatchesIdentifier(Identifier);
|
||||||
|
|
||||||
public OptionInput(string identifier, IReadOnlyList<string> values)
|
|
||||||
{
|
|
||||||
Identifier = identifier;
|
|
||||||
Values = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetFormattedIdentifier() =>
|
public string GetFormattedIdentifier() =>
|
||||||
Identifier switch
|
Identifier switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
namespace CliFx.Input;
|
namespace CliFx.Input;
|
||||||
|
|
||||||
internal class ParameterInput
|
internal class ParameterInput(string value)
|
||||||
{
|
{
|
||||||
public string Value { get; }
|
public string Value { get; } = value;
|
||||||
|
|
||||||
public ParameterInput(string value) => Value = value;
|
|
||||||
|
|
||||||
public string GetFormattedIdentifier() => $"<{Value}>";
|
public string GetFormattedIdentifier() => $"<{Value}>";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,9 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Schema;
|
namespace CliFx.Schema;
|
||||||
|
|
||||||
internal partial class ApplicationSchema
|
internal partial class ApplicationSchema(IReadOnlyList<CommandSchema> commands)
|
||||||
{
|
{
|
||||||
public IReadOnlyList<CommandSchema> Commands { get; }
|
public IReadOnlyList<CommandSchema> Commands { get; } = commands;
|
||||||
|
|
||||||
public ApplicationSchema(IReadOnlyList<CommandSchema> commands)
|
|
||||||
{
|
|
||||||
Commands = commands;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<string> GetCommandNames() =>
|
public IReadOnlyList<string> GetCommandNames() =>
|
||||||
Commands.Select(c => c.Name).WhereNotNullOrWhiteSpace().ToArray();
|
Commands.Select(c => c.Name).WhereNotNullOrWhiteSpace().ToArray();
|
||||||
|
|||||||
@@ -5,18 +5,14 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Schema;
|
namespace CliFx.Schema;
|
||||||
|
|
||||||
internal class BindablePropertyDescriptor : IPropertyDescriptor
|
internal class BindablePropertyDescriptor(PropertyInfo property) : IPropertyDescriptor
|
||||||
{
|
{
|
||||||
private readonly PropertyInfo _property;
|
public Type Type => property.PropertyType;
|
||||||
|
|
||||||
public Type Type => _property.PropertyType;
|
public object? GetValue(ICommand commandInstance) => property.GetValue(commandInstance);
|
||||||
|
|
||||||
public BindablePropertyDescriptor(PropertyInfo property) => _property = property;
|
|
||||||
|
|
||||||
public object? GetValue(ICommand commandInstance) => _property.GetValue(commandInstance);
|
|
||||||
|
|
||||||
public void SetValue(ICommand commandInstance, object? value) =>
|
public void SetValue(ICommand commandInstance, object? value) =>
|
||||||
_property.SetValue(commandInstance, value);
|
property.SetValue(commandInstance, value);
|
||||||
|
|
||||||
public IReadOnlyList<object?> GetValidValues()
|
public IReadOnlyList<object?> GetValidValues()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,25 +8,7 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Schema;
|
namespace CliFx.Schema;
|
||||||
|
|
||||||
internal partial class CommandSchema
|
internal partial class CommandSchema(
|
||||||
{
|
|
||||||
public Type Type { get; }
|
|
||||||
|
|
||||||
public string? Name { get; }
|
|
||||||
|
|
||||||
public string? Description { get; }
|
|
||||||
|
|
||||||
public IReadOnlyList<ParameterSchema> Parameters { get; }
|
|
||||||
|
|
||||||
public IReadOnlyList<OptionSchema> Options { get; }
|
|
||||||
|
|
||||||
public bool IsDefault => string.IsNullOrWhiteSpace(Name);
|
|
||||||
|
|
||||||
public bool IsHelpOptionAvailable => Options.Contains(OptionSchema.HelpOption);
|
|
||||||
|
|
||||||
public bool IsVersionOptionAvailable => Options.Contains(OptionSchema.VersionOption);
|
|
||||||
|
|
||||||
public CommandSchema(
|
|
||||||
Type type,
|
Type type,
|
||||||
string? name,
|
string? name,
|
||||||
string? description,
|
string? description,
|
||||||
@@ -34,12 +16,21 @@ internal partial class CommandSchema
|
|||||||
IReadOnlyList<OptionSchema> options
|
IReadOnlyList<OptionSchema> options
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Type = type;
|
public Type Type { get; } = type;
|
||||||
Name = name;
|
|
||||||
Description = description;
|
public string? Name { get; } = name;
|
||||||
Parameters = parameters;
|
|
||||||
Options = options;
|
public string? Description { get; } = description;
|
||||||
}
|
|
||||||
|
public IReadOnlyList<ParameterSchema> Parameters { get; } = parameters;
|
||||||
|
|
||||||
|
public IReadOnlyList<OptionSchema> Options { get; } = options;
|
||||||
|
|
||||||
|
public bool IsDefault => string.IsNullOrWhiteSpace(Name);
|
||||||
|
|
||||||
|
public bool IsHelpOptionAvailable => Options.Contains(OptionSchema.HelpOption);
|
||||||
|
|
||||||
|
public bool IsVersionOptionAvailable => Options.Contains(OptionSchema.VersionOption);
|
||||||
|
|
||||||
public bool MatchesName(string? name) =>
|
public bool MatchesName(string? name) =>
|
||||||
!string.IsNullOrWhiteSpace(Name)
|
!string.IsNullOrWhiteSpace(Name)
|
||||||
|
|||||||
@@ -7,25 +7,7 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Schema;
|
namespace CliFx.Schema;
|
||||||
|
|
||||||
internal partial class OptionSchema : IMemberSchema
|
internal partial class OptionSchema(
|
||||||
{
|
|
||||||
public IPropertyDescriptor Property { get; }
|
|
||||||
|
|
||||||
public string? Name { get; }
|
|
||||||
|
|
||||||
public char? ShortName { get; }
|
|
||||||
|
|
||||||
public string? EnvironmentVariable { get; }
|
|
||||||
|
|
||||||
public bool IsRequired { get; }
|
|
||||||
|
|
||||||
public string? Description { get; }
|
|
||||||
|
|
||||||
public Type? ConverterType { get; }
|
|
||||||
|
|
||||||
public IReadOnlyList<Type> ValidatorTypes { get; }
|
|
||||||
|
|
||||||
public OptionSchema(
|
|
||||||
IPropertyDescriptor property,
|
IPropertyDescriptor property,
|
||||||
string? name,
|
string? name,
|
||||||
char? shortName,
|
char? shortName,
|
||||||
@@ -34,17 +16,23 @@ internal partial class OptionSchema : IMemberSchema
|
|||||||
string? description,
|
string? description,
|
||||||
Type? converterType,
|
Type? converterType,
|
||||||
IReadOnlyList<Type> validatorTypes
|
IReadOnlyList<Type> validatorTypes
|
||||||
)
|
) : IMemberSchema
|
||||||
{
|
{
|
||||||
Property = property;
|
public IPropertyDescriptor Property { get; } = property;
|
||||||
Name = name;
|
|
||||||
ShortName = shortName;
|
public string? Name { get; } = name;
|
||||||
EnvironmentVariable = environmentVariable;
|
|
||||||
IsRequired = isRequired;
|
public char? ShortName { get; } = shortName;
|
||||||
Description = description;
|
|
||||||
ConverterType = converterType;
|
public string? EnvironmentVariable { get; } = environmentVariable;
|
||||||
ValidatorTypes = validatorTypes;
|
|
||||||
}
|
public bool IsRequired { get; } = isRequired;
|
||||||
|
|
||||||
|
public string? Description { get; } = description;
|
||||||
|
|
||||||
|
public Type? ConverterType { get; } = converterType;
|
||||||
|
|
||||||
|
public IReadOnlyList<Type> ValidatorTypes { get; } = validatorTypes;
|
||||||
|
|
||||||
public bool MatchesName(string? name) =>
|
public bool MatchesName(string? name) =>
|
||||||
!string.IsNullOrWhiteSpace(Name)
|
!string.IsNullOrWhiteSpace(Name)
|
||||||
|
|||||||
@@ -6,23 +6,7 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Schema;
|
namespace CliFx.Schema;
|
||||||
|
|
||||||
internal partial class ParameterSchema : IMemberSchema
|
internal partial class ParameterSchema(
|
||||||
{
|
|
||||||
public IPropertyDescriptor Property { get; }
|
|
||||||
|
|
||||||
public int Order { get; }
|
|
||||||
|
|
||||||
public string Name { get; }
|
|
||||||
|
|
||||||
public bool IsRequired { get; }
|
|
||||||
|
|
||||||
public string? Description { get; }
|
|
||||||
|
|
||||||
public Type? ConverterType { get; }
|
|
||||||
|
|
||||||
public IReadOnlyList<Type> ValidatorTypes { get; }
|
|
||||||
|
|
||||||
public ParameterSchema(
|
|
||||||
IPropertyDescriptor property,
|
IPropertyDescriptor property,
|
||||||
int order,
|
int order,
|
||||||
string name,
|
string name,
|
||||||
@@ -30,16 +14,21 @@ internal partial class ParameterSchema : IMemberSchema
|
|||||||
string? description,
|
string? description,
|
||||||
Type? converterType,
|
Type? converterType,
|
||||||
IReadOnlyList<Type> validatorTypes
|
IReadOnlyList<Type> validatorTypes
|
||||||
)
|
) : IMemberSchema
|
||||||
{
|
{
|
||||||
Property = property;
|
public IPropertyDescriptor Property { get; } = property;
|
||||||
Order = order;
|
|
||||||
Name = name;
|
public int Order { get; } = order;
|
||||||
IsRequired = isRequired;
|
|
||||||
Description = description;
|
public string Name { get; } = name;
|
||||||
ConverterType = converterType;
|
|
||||||
ValidatorTypes = validatorTypes;
|
public bool IsRequired { get; } = isRequired;
|
||||||
}
|
|
||||||
|
public string? Description { get; } = description;
|
||||||
|
|
||||||
|
public Type? ConverterType { get; } = converterType;
|
||||||
|
|
||||||
|
public IReadOnlyList<Type> ValidatorTypes { get; } = validatorTypes;
|
||||||
|
|
||||||
public string GetFormattedIdentifier() => Property.IsScalar() ? $"<{Name}>" : $"<{Name}...>";
|
public string GetFormattedIdentifier() => Property.IsScalar() ? $"<{Name}>" : $"<{Name}...>";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,9 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace CliFx.Utils;
|
namespace CliFx.Utils;
|
||||||
|
|
||||||
internal partial class Disposable : IDisposable
|
internal partial class Disposable(Action dispose) : IDisposable
|
||||||
{
|
{
|
||||||
private readonly Action _dispose;
|
public void Dispose() => dispose();
|
||||||
|
|
||||||
public Disposable(Action dispose) => _dispose = dispose;
|
|
||||||
|
|
||||||
public void Dispose() => _dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal partial class Disposable
|
internal partial class Disposable
|
||||||
|
|||||||
@@ -10,65 +10,58 @@ namespace CliFx.Utils;
|
|||||||
// https://source.dot.net/#System.Console/ConsoleEncoding.cs,5eedd083a4a4f4a2
|
// https://source.dot.net/#System.Console/ConsoleEncoding.cs,5eedd083a4a4f4a2
|
||||||
// Majority of overrides are just proxy calls to avoid potentially more expensive base behavior.
|
// Majority of overrides are just proxy calls to avoid potentially more expensive base behavior.
|
||||||
// The important part is the GetPreamble() method that has been overriden to return an empty array.
|
// The important part is the GetPreamble() method that has been overriden to return an empty array.
|
||||||
internal class NoPreambleEncoding : Encoding
|
internal class NoPreambleEncoding(Encoding underlyingEncoding)
|
||||||
{
|
: Encoding(
|
||||||
private readonly Encoding _underlyingEncoding;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override string EncodingName => _underlyingEncoding.EncodingName;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override string BodyName => _underlyingEncoding.BodyName;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override int CodePage => _underlyingEncoding.CodePage;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override int WindowsCodePage => _underlyingEncoding.WindowsCodePage;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override string HeaderName => _underlyingEncoding.HeaderName;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override string WebName => _underlyingEncoding.WebName;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override bool IsBrowserDisplay => _underlyingEncoding.IsBrowserDisplay;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override bool IsBrowserSave => _underlyingEncoding.IsBrowserSave;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override bool IsSingleByte => _underlyingEncoding.IsSingleByte;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override bool IsMailNewsDisplay => _underlyingEncoding.IsMailNewsDisplay;
|
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public override bool IsMailNewsSave => _underlyingEncoding.IsMailNewsSave;
|
|
||||||
|
|
||||||
public NoPreambleEncoding(Encoding underlyingEncoding)
|
|
||||||
: base(
|
|
||||||
underlyingEncoding.CodePage,
|
underlyingEncoding.CodePage,
|
||||||
underlyingEncoding.EncoderFallback,
|
underlyingEncoding.EncoderFallback,
|
||||||
underlyingEncoding.DecoderFallback
|
underlyingEncoding.DecoderFallback
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_underlyingEncoding = underlyingEncoding;
|
[ExcludeFromCodeCoverage]
|
||||||
}
|
public override string EncodingName => underlyingEncoding.EncodingName;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override string BodyName => underlyingEncoding.BodyName;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override int CodePage => underlyingEncoding.CodePage;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override int WindowsCodePage => underlyingEncoding.WindowsCodePage;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override string HeaderName => underlyingEncoding.HeaderName;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override string WebName => underlyingEncoding.WebName;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override bool IsBrowserDisplay => underlyingEncoding.IsBrowserDisplay;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override bool IsBrowserSave => underlyingEncoding.IsBrowserSave;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override bool IsSingleByte => underlyingEncoding.IsSingleByte;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override bool IsMailNewsDisplay => underlyingEncoding.IsMailNewsDisplay;
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
public override bool IsMailNewsSave => underlyingEncoding.IsMailNewsSave;
|
||||||
|
|
||||||
// This is the only part that changes
|
// This is the only part that changes
|
||||||
public override byte[] GetPreamble() => Array.Empty<byte>();
|
public override byte[] GetPreamble() => Array.Empty<byte>();
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetByteCount(char[] chars, int index, int count) =>
|
public override int GetByteCount(char[] chars, int index, int count) =>
|
||||||
_underlyingEncoding.GetByteCount(chars, index, count);
|
underlyingEncoding.GetByteCount(chars, index, count);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetByteCount(char[] chars) => _underlyingEncoding.GetByteCount(chars);
|
public override int GetByteCount(char[] chars) => underlyingEncoding.GetByteCount(chars);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetByteCount(string s) => _underlyingEncoding.GetByteCount(s);
|
public override int GetByteCount(string s) => underlyingEncoding.GetByteCount(s);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetBytes(
|
public override int GetBytes(
|
||||||
@@ -77,14 +70,14 @@ internal class NoPreambleEncoding : Encoding
|
|||||||
int charCount,
|
int charCount,
|
||||||
byte[] bytes,
|
byte[] bytes,
|
||||||
int byteIndex
|
int byteIndex
|
||||||
) => _underlyingEncoding.GetBytes(chars, charIndex, charCount, bytes, byteIndex);
|
) => underlyingEncoding.GetBytes(chars, charIndex, charCount, bytes, byteIndex);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override byte[] GetBytes(char[] chars, int index, int count) =>
|
public override byte[] GetBytes(char[] chars, int index, int count) =>
|
||||||
_underlyingEncoding.GetBytes(chars, index, count);
|
underlyingEncoding.GetBytes(chars, index, count);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override byte[] GetBytes(char[] chars) => _underlyingEncoding.GetBytes(chars);
|
public override byte[] GetBytes(char[] chars) => underlyingEncoding.GetBytes(chars);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetBytes(
|
public override int GetBytes(
|
||||||
@@ -93,17 +86,17 @@ internal class NoPreambleEncoding : Encoding
|
|||||||
int charCount,
|
int charCount,
|
||||||
byte[] bytes,
|
byte[] bytes,
|
||||||
int byteIndex
|
int byteIndex
|
||||||
) => _underlyingEncoding.GetBytes(s, charIndex, charCount, bytes, byteIndex);
|
) => underlyingEncoding.GetBytes(s, charIndex, charCount, bytes, byteIndex);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override byte[] GetBytes(string s) => _underlyingEncoding.GetBytes(s);
|
public override byte[] GetBytes(string s) => underlyingEncoding.GetBytes(s);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetCharCount(byte[] bytes, int index, int count) =>
|
public override int GetCharCount(byte[] bytes, int index, int count) =>
|
||||||
_underlyingEncoding.GetCharCount(bytes, index, count);
|
underlyingEncoding.GetCharCount(bytes, index, count);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetCharCount(byte[] bytes) => _underlyingEncoding.GetCharCount(bytes);
|
public override int GetCharCount(byte[] bytes) => underlyingEncoding.GetCharCount(bytes);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetChars(
|
public override int GetChars(
|
||||||
@@ -112,39 +105,39 @@ internal class NoPreambleEncoding : Encoding
|
|||||||
int byteCount,
|
int byteCount,
|
||||||
char[] chars,
|
char[] chars,
|
||||||
int charIndex
|
int charIndex
|
||||||
) => _underlyingEncoding.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
|
) => underlyingEncoding.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override char[] GetChars(byte[] bytes) => _underlyingEncoding.GetChars(bytes);
|
public override char[] GetChars(byte[] bytes) => underlyingEncoding.GetChars(bytes);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override char[] GetChars(byte[] bytes, int index, int count) =>
|
public override char[] GetChars(byte[] bytes, int index, int count) =>
|
||||||
_underlyingEncoding.GetChars(bytes, index, count);
|
underlyingEncoding.GetChars(bytes, index, count);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override string GetString(byte[] bytes) => _underlyingEncoding.GetString(bytes);
|
public override string GetString(byte[] bytes) => underlyingEncoding.GetString(bytes);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override string GetString(byte[] bytes, int index, int count) =>
|
public override string GetString(byte[] bytes, int index, int count) =>
|
||||||
_underlyingEncoding.GetString(bytes, index, count);
|
underlyingEncoding.GetString(bytes, index, count);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetMaxByteCount(int charCount) =>
|
public override int GetMaxByteCount(int charCount) =>
|
||||||
_underlyingEncoding.GetMaxByteCount(charCount);
|
underlyingEncoding.GetMaxByteCount(charCount);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override int GetMaxCharCount(int byteCount) =>
|
public override int GetMaxCharCount(int byteCount) =>
|
||||||
_underlyingEncoding.GetMaxCharCount(byteCount);
|
underlyingEncoding.GetMaxCharCount(byteCount);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override bool IsAlwaysNormalized(NormalizationForm form) =>
|
public override bool IsAlwaysNormalized(NormalizationForm form) =>
|
||||||
_underlyingEncoding.IsAlwaysNormalized(form);
|
underlyingEncoding.IsAlwaysNormalized(form);
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override Encoder GetEncoder() => _underlyingEncoding.GetEncoder();
|
public override Encoder GetEncoder() => underlyingEncoding.GetEncoder();
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override Decoder GetDecoder() => _underlyingEncoding.GetDecoder();
|
public override Decoder GetDecoder() => underlyingEncoding.GetDecoder();
|
||||||
|
|
||||||
[ExcludeFromCodeCoverage]
|
[ExcludeFromCodeCoverage]
|
||||||
public override object Clone() => new NoPreambleEncoding((Encoding)base.Clone());
|
public override object Clone() => new NoPreambleEncoding((Encoding)base.Clone());
|
||||||
|
|||||||
@@ -6,32 +6,14 @@ using CliFx.Utils.Extensions;
|
|||||||
|
|
||||||
namespace CliFx.Utils;
|
namespace CliFx.Utils;
|
||||||
|
|
||||||
internal class StackFrameParameter
|
internal class StackFrameParameter(string type, string? name)
|
||||||
{
|
{
|
||||||
public string Type { get; }
|
public string Type { get; } = type;
|
||||||
|
|
||||||
public string? Name { get; }
|
public string? Name { get; } = name;
|
||||||
|
|
||||||
public StackFrameParameter(string type, string? name)
|
|
||||||
{
|
|
||||||
Type = type;
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal partial class StackFrame
|
internal partial class StackFrame(
|
||||||
{
|
|
||||||
public string ParentType { get; }
|
|
||||||
|
|
||||||
public string MethodName { get; }
|
|
||||||
|
|
||||||
public IReadOnlyList<StackFrameParameter> Parameters { get; }
|
|
||||||
|
|
||||||
public string? FilePath { get; }
|
|
||||||
|
|
||||||
public string? LineNumber { get; }
|
|
||||||
|
|
||||||
public StackFrame(
|
|
||||||
string parentType,
|
string parentType,
|
||||||
string methodName,
|
string methodName,
|
||||||
IReadOnlyList<StackFrameParameter> parameters,
|
IReadOnlyList<StackFrameParameter> parameters,
|
||||||
@@ -39,12 +21,15 @@ internal partial class StackFrame
|
|||||||
string? lineNumber
|
string? lineNumber
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ParentType = parentType;
|
public string ParentType { get; } = parentType;
|
||||||
MethodName = methodName;
|
|
||||||
Parameters = parameters;
|
public string MethodName { get; } = methodName;
|
||||||
FilePath = filePath;
|
|
||||||
LineNumber = lineNumber;
|
public IReadOnlyList<StackFrameParameter> Parameters { get; } = parameters;
|
||||||
}
|
|
||||||
|
public string? FilePath { get; } = filePath;
|
||||||
|
|
||||||
|
public string? LineNumber { get; } = lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal partial class StackFrame
|
internal partial class StackFrame
|
||||||
|
|||||||
Reference in New Issue
Block a user