Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Swashbuckle.AspNetCore.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<Project Path="test/Swashbuckle.AspNetCore.TestSupport/Swashbuckle.AspNetCore.TestSupport.csproj" />
</Folder>
<Folder Name="/test/WebSites/">
<Project Path="test/WebSites/Authorization/Authorization.csproj" />
<Project Path="test/WebSites/Basic/Basic.csproj" />
<Project Path="test/WebSites/CliExample/CliExample.csproj" />
<Project Path="test/WebSites/CliExampleWithFactory/CliExampleWithFactory.csproj" />
Expand Down
10 changes: 5 additions & 5 deletions src/Swashbuckle.AspNetCore.Cli/CommandRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ internal class CommandRunner(string commandName, string commandDescription, Text
{
private readonly Dictionary<string, string> _argumentDescriptors = [];
private readonly Dictionary<string, OptionDescriptor> _optionDescriptors = [];
private Func<IDictionary<string, string>, int> _runFunc = (_) => 1;
private Func<IDictionary<string, string>, Task<int>> _runFunc = (_) => Task.FromResult(1);
private readonly List<CommandRunner> _subRunners = [];
private readonly TextWriter _output = output;

Expand All @@ -27,7 +27,7 @@ public void Option(string name, string description, bool isFlag = false)
_optionDescriptors.Add(name, new OptionDescriptor { Description = description, IsFlag = isFlag });
}

public void OnRun(Func<IDictionary<string, string>, int> runFunc)
public void OnRun(Func<IDictionary<string, string>, Task<int>> runFunc)
{
_runFunc = runFunc;
}
Expand All @@ -39,12 +39,12 @@ public void SubCommand(string name, string description, Action<CommandRunner> co
_subRunners.Add(runner);
}

public int Run(IEnumerable<string> args)
public async Task<int> RunAsync(IEnumerable<string> args)
{
if (args.Any())
{
var subRunner = _subRunners.FirstOrDefault(r => r.CommandName.Split(' ').Last() == args.First());
if (subRunner != null) return subRunner.Run(args.Skip(1));
if (subRunner != null) return await subRunner.RunAsync(args.Skip(1));
}

if (_subRunners.Count != 0 || !TryParseArgs(args, out IDictionary<string, string> namedArgs))
Expand All @@ -53,7 +53,7 @@ public int Run(IEnumerable<string> args)
return 1;
}

return _runFunc(namedArgs);
return await _runFunc(namedArgs);
}

private bool TryParseArgs(IEnumerable<string> args, out IDictionary<string, string> namedArgs)
Expand Down
31 changes: 17 additions & 14 deletions src/Swashbuckle.AspNetCore.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal class Program
{
private const string OpenApiVersionOption = "--openapiversion";

public static int Main(string[] args)
public static async Task<int> Main(string[] args)
{
// Helper to simplify command line parsing etc.
var runner = new CommandRunner("dotnet swagger", "Swashbuckle (Swagger) Command Line Tools", Console.Out);
Expand Down Expand Up @@ -45,7 +45,7 @@ public static int Main(string[] args)
using var child = Process.Start("dotnet", subProcessCommandLine);

child.WaitForExit();
return child.ExitCode;
return Task.FromResult(child.ExitCode);
});
});

Expand All @@ -60,14 +60,16 @@ public static int Main(string[] args)
c.Option(OpenApiVersionOption, "");
c.Option("--yaml", "", true);

c.OnRun((namedArgs) =>
c.OnRun(async (namedArgs) =>
{
SetupAndRetrieveSwaggerProviderAndOptions(namedArgs, out var swaggerProvider, out var swaggerOptions);
SetupAndRetrieveSwaggerProviderAndOptions(namedArgs, out var asyncSwaggerProvider, out var swaggerProvider, out var swaggerOptions);
var swaggerDocumentSerializer = swaggerOptions?.Value?.CustomDocumentSerializer;
var swagger = swaggerProvider.GetSwagger(
namedArgs["swaggerdoc"],
namedArgs.TryGetValue("--host", out var arg) ? arg : null,
namedArgs.TryGetValue("--basepath", out var namedArg) ? namedArg : null);

var host = namedArgs.TryGetValue("--host", out var arg) ? arg : null;
var basePath = namedArgs.TryGetValue("--basepath", out var namedArg) ? namedArg : null;
var swagger = asyncSwaggerProvider != null
? await asyncSwaggerProvider.GetSwaggerAsync(namedArgs["swaggerdoc"], host, basePath)
: swaggerProvider.GetSwagger(namedArgs["swaggerdoc"], host, basePath);
Comment thread
martincostello marked this conversation as resolved.

// 4) Serialize to specified output location or stdout
var outputPath = namedArgs.TryGetValue("--output", out var arg1)
Expand Down Expand Up @@ -139,7 +141,7 @@ public static int Main(string[] args)
using var child = Process.Start("dotnet", subProcessCommandLine);

child.WaitForExit();
return child.ExitCode;
return Task.FromResult(child.ExitCode);
});
});

Expand All @@ -150,7 +152,7 @@ public static int Main(string[] args)
c.Option("--output", "");
c.OnRun((namedArgs) =>
{
SetupAndRetrieveSwaggerProviderAndOptions(namedArgs, out var swaggerProvider, out var swaggerOptions);
SetupAndRetrieveSwaggerProviderAndOptions(namedArgs, out _, out var swaggerProvider, out var swaggerOptions);
IList<string> docNames = [];

string outputPath = namedArgs.TryGetValue("--output", out var arg1)
Expand All @@ -172,7 +174,7 @@ public static int Main(string[] args)
if (swaggerProvider is not ISwaggerDocumentMetadataProvider docMetaProvider)
{
writer.WriteLine($"The registered {nameof(ISwaggerProvider)} instance does not implement {nameof(ISwaggerDocumentMetadataProvider)}; unable to list the Swagger document names.");
return -1;
return Task.FromResult(-1);
}

docNames = docMetaProvider.GetDocumentNames();
Expand All @@ -182,14 +184,14 @@ public static int Main(string[] args)
writer.WriteLine($"\"{name}\"");
}

return 0;
return Task.FromResult(0);
});
});

return runner.Run(args);
return await runner.RunAsync(args);
}

private static void SetupAndRetrieveSwaggerProviderAndOptions(IDictionary<string, string> namedArgs, out ISwaggerProvider swaggerProvider, out IOptions<SwaggerOptions> swaggerOptions)
private static void SetupAndRetrieveSwaggerProviderAndOptions(IDictionary<string, string> namedArgs, out IAsyncSwaggerProvider asyncSwaggerProvider, out ISwaggerProvider swaggerProvider, out IOptions<SwaggerOptions> swaggerOptions)
{
// 1) Configure host with provided startupassembly
var startupAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(
Expand All @@ -199,6 +201,7 @@ private static void SetupAndRetrieveSwaggerProviderAndOptions(IDictionary<string
var serviceProvider = GetServiceProvider(startupAssembly);

// 3) Retrieve Swagger via configured provider
asyncSwaggerProvider = serviceProvider.GetService<IAsyncSwaggerProvider>();
swaggerProvider = serviceProvider.GetRequiredService<ISwaggerProvider>();
swaggerOptions = serviceProvider.GetService<IOptions<SwaggerOptions>>();
}
Expand Down
22 changes: 11 additions & 11 deletions test/Swashbuckle.AspNetCore.Cli.Test/CommandRunnerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Swashbuckle.AspNetCore.Cli.Test;
public static class CommandRunnerTests
{
[Fact]
public static void Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredMetadata()
public static async Task Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredMetadata()
{
var receivedValues = new List<string>();
var subject = new CommandRunner("test", "a test", new StringWriter());
Expand All @@ -18,7 +18,7 @@ public static void Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredM
receivedValues.Add(namedArgs["--opt1"]);
receivedValues.Add(namedArgs["--opt2"]);
receivedValues.Add(namedArgs["arg1"]);
return 2;
return Task.FromResult(2);
});
});
subject.SubCommand("cmd2", "", c => {
Expand All @@ -30,42 +30,42 @@ public static void Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredM
receivedValues.Add(namedArgs["--opt1"]);
receivedValues.Add(namedArgs["--opt2"]);
receivedValues.Add(namedArgs["arg1"]);
return 3;
return Task.FromResult(3);
});
});

var cmd1ExitCode = subject.Run(["cmd1", "--opt1", "foo", "--opt2", "bar"]);
var cmd2ExitCode = subject.Run(["cmd2", "--opt1", "blah", "--opt2", "dblah"]);
var cmd1ExitCode = await subject.RunAsync(["cmd1", "--opt1", "foo", "--opt2", "bar"]);
var cmd2ExitCode = await subject.RunAsync(["cmd2", "--opt1", "blah", "--opt2", "dblah"]);

Assert.Equal(2, cmd1ExitCode);
Assert.Equal(3, cmd2ExitCode);
Assert.Equal(["foo", null, "bar", "blah", null, "dblah"], [.. receivedValues]);
}

[Fact]
public static void Run_PrintsAvailableCommands_WhenUnexpectedCommandIsProvided()
public static async Task Run_PrintsAvailableCommands_WhenUnexpectedCommandIsProvided()
{
var output = new StringWriter();
var subject = new CommandRunner("test", "a test", output);
subject.SubCommand("cmd", "does something", c => {
});

var exitCode = subject.Run(["foo"]);
var exitCode = await subject.RunAsync(["foo"]);

Assert.StartsWith("a test", output.ToString());
Assert.Contains("Commands:", output.ToString());
Assert.Contains("cmd: does something", output.ToString());
}

[Fact]
public static void Run_PrintsAvailableCommands_WhenHelpOptionIsProvided()
public static async Task Run_PrintsAvailableCommands_WhenHelpOptionIsProvided()
{
var output = new StringWriter();
var subject = new CommandRunner("test", "a test", output);
subject.SubCommand("cmd", "does something", c => {
});

var exitCode = subject.Run(["--help"]);
var exitCode = await subject.RunAsync(["--help"]);

Assert.StartsWith("a test", output.ToString());
Assert.Contains("Commands:", output.ToString());
Expand All @@ -81,7 +81,7 @@ public static void Run_PrintsAvailableCommands_WhenHelpOptionIsProvided()
[InlineData(new string[0], new[] { "arg1" }, new[] { "cmd", "--opt1" }, true)]
[InlineData(new string[0], new[] { "arg1" }, new[] { "cmd", "foo", "bar" }, true)]
[InlineData(new string[0], new[] { "arg1" }, new[] { "cmd", "foo" }, false)]
public static void Run_PrintsCommandUsage_WhenUnexpectedArgumentsAreProvided(
public static async Task Run_PrintsCommandUsage_WhenUnexpectedArgumentsAreProvided(
string[] optionNames,
string[] argNames,
string[] providedArgs,
Expand All @@ -97,7 +97,7 @@ public static void Run_PrintsCommandUsage_WhenUnexpectedArgumentsAreProvided(
c.Argument(name, "");
});

subject.Run(providedArgs);
await subject.RunAsync(providedArgs);

if (shouldPrintUsage)
Assert.StartsWith("Usage: test cmd", output.ToString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

<ItemGroup>
<ProjectReference Include="..\Swashbuckle.AspNetCore.TestSupport\Swashbuckle.AspNetCore.TestSupport.csproj" />
<ProjectReference Include="..\WebSites\Authorization\Authorization.csproj" />
<ProjectReference Include="..\WebSites\Basic\Basic.csproj" />
<ProjectReference Include="..\WebSites\CustomDocumentSerializer\CustomDocumentSerializer.csproj" />
<ProjectReference Include="..\WebSites\MinimalAppWithHostedServices\MinimalAppWithHostedServices.csproj" />
Expand Down
Loading
Loading