Upstream Tyrrrz/CliFx state of the touched files before 72b7d869fc
This commit is contained in:
1 parent
8f11b8ff38
commit
50964082ba
6 files changed
+3
-132
No files matched your search
@@ -3,7 +3,6 @@ using System.Linq;
|
|||||||
using CliFx.Generators.Utils;
|
using CliFx.Generators.Utils;
|
||||||
using CliFx.Generators.Utils.Extensions;
|
using CliFx.Generators.Utils.Extensions;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using PowerKit.Extensions;
|
|
||||||
|
|
||||||
namespace CliFx.Generators.Binding;
|
namespace CliFx.Generators.Binding;
|
||||||
|
|
||||||
@@ -11,7 +10,6 @@ internal partial record CommandSymbol(
|
|||||||
INamedTypeSymbol Type,
|
INamedTypeSymbol Type,
|
||||||
string? Name,
|
string? Name,
|
||||||
string? Description,
|
string? Description,
|
||||||
IReadOnlyList<string> Examples,
|
|
||||||
IReadOnlyList<CommandInputSymbol> Inputs
|
IReadOnlyList<CommandInputSymbol> Inputs
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -73,19 +71,10 @@ internal partial record CommandSymbol
|
|||||||
attribute?.NamedArguments.FirstOrDefault(a => a.Key == "Description").Value.Value
|
attribute?.NamedArguments.FirstOrDefault(a => a.Key == "Description").Value.Value
|
||||||
as string;
|
as string;
|
||||||
|
|
||||||
var examples =
|
|
||||||
attribute
|
|
||||||
?.NamedArguments.Where(a => a.Key == "Examples")
|
|
||||||
.SelectMany(a => a.Value.Values)
|
|
||||||
.Select(v => v.Value as string)
|
|
||||||
.WhereNotNull()
|
|
||||||
.ToArray()
|
|
||||||
?? [];
|
|
||||||
|
|
||||||
var properties = type.GetProperties().ToArray();
|
var properties = type.GetProperties().ToArray();
|
||||||
var parameters = CommandParameterSymbol.Resolve(properties, diagnostics);
|
var parameters = CommandParameterSymbol.Resolve(properties, diagnostics);
|
||||||
var options = CommandOptionSymbol.Resolve(properties, diagnostics);
|
var options = CommandOptionSymbol.Resolve(properties, diagnostics);
|
||||||
|
|
||||||
return new CommandSymbol(type, name, description, examples, [.. parameters, .. options]);
|
return new CommandSymbol(type, name, description, [.. parameters, .. options]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,17 +31,6 @@ internal static class CommandDescriptor
|
|||||||
""";
|
""";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string EmitExamples(IReadOnlyList<string> examples)
|
|
||||||
{
|
|
||||||
if (examples.Count == 0)
|
|
||||||
return "global::System.Array.Empty<string>()";
|
|
||||||
|
|
||||||
// lang=csharp
|
|
||||||
return $$"""
|
|
||||||
new[] { {{string.Join(", ", examples.Select(CSharp.Encode))}} }
|
|
||||||
""";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string? TryEmitDefaultScalarConverter(ITypeSymbol type)
|
private static string? TryEmitDefaultScalarConverter(ITypeSymbol type)
|
||||||
{
|
{
|
||||||
// Object
|
// Object
|
||||||
@@ -533,7 +522,6 @@ internal static class CommandDescriptor
|
|||||||
new global::CliFx.Binding.CommandDescriptor<{{command.Type.GetGloballyQualifiedName()}}>(
|
new global::CliFx.Binding.CommandDescriptor<{{command.Type.GetGloballyQualifiedName()}}>(
|
||||||
{{CSharp.Encode(command.Name)}},
|
{{CSharp.Encode(command.Name)}},
|
||||||
{{CSharp.Encode(command.Description)}},
|
{{CSharp.Encode(command.Description)}},
|
||||||
{{EmitExamples(command.Examples)}},
|
|
||||||
new global::CliFx.Binding.CommandInputDescriptor[]
|
new global::CliFx.Binding.CommandInputDescriptor[]
|
||||||
{
|
{
|
||||||
{{string.Join(",", command.Inputs
|
{{string.Join(",", command.Inputs
|
||||||
|
|||||||
@@ -381,81 +381,6 @@ public class HelpSpecs(ITestOutputHelper testOutput) : SpecsBase(testOutput)
|
|||||||
.ContainAllInOrder("USAGE", "--foo <value>", "--baz <values...>", "[options]");
|
.ContainAllInOrder("USAGE", "--foo <value>", "--baz <values...>", "[options]");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task I_can_request_help_to_see_the_usage_examples_of_a_command()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var application = new CommandLineApplicationBuilder()
|
|
||||||
.AddCommands(
|
|
||||||
CommandCompiler.Compile(
|
|
||||||
// lang=csharp
|
|
||||||
"""
|
|
||||||
[Command("foo", Examples = new[] { "--bar 42", "-b 42" })]
|
|
||||||
public partial class Command : ICommand
|
|
||||||
{
|
|
||||||
[CommandOption("bar", 'b')]
|
|
||||||
public int Bar { get; set; }
|
|
||||||
|
|
||||||
public ValueTask ExecuteAsync(IConsole console) => default;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.UseConsole(FakeConsole)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var exitCode = await application.RunAsync(
|
|
||||||
["foo", "--help"],
|
|
||||||
new Dictionary<string, string>()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
exitCode.Should().Be(0);
|
|
||||||
|
|
||||||
var stdOut = FakeConsole.ReadOutputString();
|
|
||||||
stdOut
|
|
||||||
.Should()
|
|
||||||
.ContainAllInOrder("USAGE", "foo [options]", "foo --bar 42", "foo -b 42", "OPTIONS");
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task I_do_not_see_any_usage_examples_if_the_command_does_not_define_any()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var application = new CommandLineApplicationBuilder()
|
|
||||||
.AddCommands(
|
|
||||||
CommandCompiler.Compile(
|
|
||||||
// lang=csharp
|
|
||||||
"""
|
|
||||||
[Command("foo")]
|
|
||||||
public partial class Command : ICommand
|
|
||||||
{
|
|
||||||
[CommandOption("bar", 'b')]
|
|
||||||
public int Bar { get; set; }
|
|
||||||
|
|
||||||
public ValueTask ExecuteAsync(IConsole console) => default;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.UseConsole(FakeConsole)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var exitCode = await application.RunAsync(
|
|
||||||
["foo", "--help"],
|
|
||||||
new Dictionary<string, string>()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
exitCode.Should().Be(0);
|
|
||||||
|
|
||||||
var stdOut = FakeConsole.ReadOutputString();
|
|
||||||
stdOut.Should().Contain("foo [options]");
|
|
||||||
stdOut.Should().NotContain("foo --bar 42");
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task I_can_request_help_to_see_the_list_of_all_inputs()
|
public async Task I_can_request_help_to_see_the_list_of_all_inputs()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,14 +29,4 @@ public class CommandAttribute(string? name) : Attribute
|
|||||||
/// Used for display purposes in the help text.
|
/// Used for display purposes in the help text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Usage examples of the command.
|
|
||||||
/// Used for display purposes in the help text.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Each example contains only what comes after the command name; the name itself
|
|
||||||
/// is prepended when the help text is rendered.
|
|
||||||
/// </remarks>
|
|
||||||
public string[] Examples { get; set; } = [];
|
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,6 @@ public class CommandDescriptor(
|
|||||||
Type type,
|
Type type,
|
||||||
string? name,
|
string? name,
|
||||||
string? description,
|
string? description,
|
||||||
IReadOnlyList<string> examples,
|
|
||||||
IReadOnlyList<CommandInputDescriptor> inputs
|
IReadOnlyList<CommandInputDescriptor> inputs
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -31,9 +30,6 @@ public class CommandDescriptor(
|
|||||||
/// <inheritdoc cref="CommandAttribute.Description" />
|
/// <inheritdoc cref="CommandAttribute.Description" />
|
||||||
public string? Description { get; } = description;
|
public string? Description { get; } = description;
|
||||||
|
|
||||||
/// <inheritdoc cref="CommandAttribute.Examples" />
|
|
||||||
public IReadOnlyList<string> Examples { get; } = examples;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inputs (parameters and options) of the command;
|
/// Inputs (parameters and options) of the command;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -61,10 +57,6 @@ public class CommandDescriptor(
|
|||||||
public class CommandDescriptor<
|
public class CommandDescriptor<
|
||||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
|
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
|
||||||
TCommand
|
TCommand
|
||||||
>(
|
>(string? name, string? description, IReadOnlyList<CommandInputDescriptor> inputs)
|
||||||
string? name,
|
: CommandDescriptor(typeof(TCommand), name, description, inputs)
|
||||||
string? description,
|
|
||||||
IReadOnlyList<string> examples,
|
|
||||||
IReadOnlyList<CommandInputDescriptor> inputs
|
|
||||||
) : CommandDescriptor(typeof(TCommand), name, description, examples, inputs)
|
|
||||||
where TCommand : ICommand;
|
where TCommand : ICommand;
|
||||||
@@ -73,19 +73,6 @@ internal class HelpWriter(HelpContext context, ConsoleWriter consoleWriter)
|
|||||||
WriteLine();
|
WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Examples
|
|
||||||
foreach (var example in context.Command.Examples)
|
|
||||||
{
|
|
||||||
WriteHorizontalMargin();
|
|
||||||
|
|
||||||
WriteCommandInvocation();
|
|
||||||
Write(' ');
|
|
||||||
|
|
||||||
Write(example);
|
|
||||||
|
|
||||||
WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Child commands
|
// Child commands
|
||||||
if (context.Root.GetChildCommands(context.Command.Name).Any())
|
if (context.Root.GetChildCommands(context.Command.Name).Any())
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user