Skip to content

Commit

Permalink
Load controlles and types via command line (NSwagStudio), #953
Browse files Browse the repository at this point in the history
  • Loading branch information
RicoSuter committed Sep 19, 2017
1 parent 3ef7726 commit 55784ba
Show file tree
Hide file tree
Showing 20 changed files with 351 additions and 104 deletions.
2 changes: 2 additions & 0 deletions src/NSwag.AssemblyLoader/NSwag.AssemblyLoader.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
<Compile Include="..\NSwag.AssemblyLoaderCore\Commands\AssemblyTypeToSwaggerCommand.cs" Link="Commands\AssemblyTypeToSwaggerCommand.cs" />
<Compile Include="..\NSwag.AssemblyLoaderCore\Commands\Documents\CreateDocumentCommand.cs" Link="Commands\Documents\CreateDocumentCommand.cs" />
<Compile Include="..\NSwag.AssemblyLoaderCore\Commands\Documents\ExecuteDocumentCommand.cs" Link="Commands\Documents\ExecuteDocumentCommand.cs" />
<Compile Include="..\NSwag.AssemblyLoaderCore\Commands\ListTypesCommand.cs" Link="Commands\ListTypesCommand.cs" />
<Compile Include="..\NSwag.AssemblyLoaderCore\Commands\ListWebApiControllersCommand.cs" Link="Commands\ListWebApiControllersCommand.cs" />
<Compile Include="..\NSwag.AssemblyLoaderCore\Commands\WebApiToSwaggerCommand.cs" Link="Commands\WebApiToSwaggerCommand.cs" />
<Compile Include="..\NSwag.AssemblyLoaderCore\Infrastructure\AssemblyLoader.cs" Link="Infrastructure\AssemblyLoader.cs" />
<Compile Include="..\NSwag.AssemblyLoaderCore\NSwagDocument.cs" Link="NSwagDocument.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// <author>Rico Suter, [email protected]</author>
//-----------------------------------------------------------------------

using NSwag.Commands;
using System.Threading.Tasks;
using NSwag.SwaggerGeneration;

namespace NSwag.Commands
Expand All @@ -15,12 +15,11 @@ namespace NSwag.Commands
/// <seealso cref="NSwag.Commands.AssemblyTypeToSwaggerCommandBase" />
public class AssemblyTypeToSwaggerCommand : AssemblyTypeToSwaggerCommandBase
{

/// <summary>Creates a new generator instance.</summary>
/// <returns>The generator.</returns>
protected override AssemblyTypeToSwaggerGeneratorBase CreateGenerator()
protected override Task<AssemblyTypeToSwaggerGeneratorBase> CreateGeneratorAsync()
{
return new AssemblyTypeToSwaggerGenerator(Settings);
return Task.FromResult<AssemblyTypeToSwaggerGeneratorBase>(new AssemblyTypeToSwaggerGenerator(Settings));
}
}
}
40 changes: 40 additions & 0 deletions src/NSwag.AssemblyLoaderCore/Commands/ListTypesCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//-----------------------------------------------------------------------
// <copyright file="ListTypesCommand.cs" company="NSwag">
// Copyright (c) Rico Suter. All rights reserved.
// </copyright>
// <license>https://github.com/NSwag/NSwag/blob/master/LICENSE.md</license>
// <author>Rico Suter, [email protected]</author>
//-----------------------------------------------------------------------

using System;
using System.Threading.Tasks;
using NSwag.SwaggerGeneration;

namespace NSwag.Commands
{
/// <summary>The generator.</summary>
/// <seealso cref="NSwag.Commands.WebApiToSwaggerCommandBase" />
public class ListTypesCommand : ListTypesCommandBase
{
/// <summary>Creates a new generator instance.</summary>
/// <returns>The generator.</returns>
/// <summary>Creates a new generator instance.</summary>
/// <returns>The generator.</returns>
/// <exception cref="InvalidOperationException">Configuraiton file does not contain AssemblyTypeToSwagger settings.</exception>
protected override async Task<AssemblyTypeToSwaggerGeneratorBase> CreateGeneratorAsync()
{
if (!string.IsNullOrEmpty(File))
{
var document = await NSwagDocument.LoadAsync(File);

var settings = document.SwaggerGenerators?.AssemblyTypeToSwaggerCommand?.Settings;
if (settings == null)
throw new InvalidOperationException("Configuraiton file does not contain AssemblyTypeToSwagger settings.");

return new AssemblyTypeToSwaggerGenerator(settings);
}
else
return new AssemblyTypeToSwaggerGenerator(Settings);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//-----------------------------------------------------------------------
// <copyright file="ListWebApiControllersCommand.cs" company="NSwag">
// Copyright (c) Rico Suter. All rights reserved.
// </copyright>
// <license>https://github.com/NSwag/NSwag/blob/master/LICENSE.md</license>
// <author>Rico Suter, [email protected]</author>
//-----------------------------------------------------------------------

using System;
using System.Threading.Tasks;
using NSwag.SwaggerGeneration.WebApi;

namespace NSwag.Commands
{
/// <summary>The generator.</summary>
/// <seealso cref="NSwag.Commands.WebApiToSwaggerCommandBase" />
public class ListWebApiControllersCommand : ListWebApiControllersCommandBase
{
/// <summary>Creates a new generator instance.</summary>
/// <returns>The generator.</returns>
/// <summary>Creates a new generator instance.</summary>
/// <returns>The generator.</returns>
/// <exception cref="InvalidOperationException">Configuraiton file does not contain WebApiToSwagger settings.</exception>
protected override async Task<WebApiAssemblyToSwaggerGeneratorBase> CreateGeneratorAsync()
{
if (!string.IsNullOrEmpty(File))
{
var document = await NSwagDocument.LoadAsync(File);

var settings = document.SwaggerGenerators?.WebApiToSwaggerCommand?.Settings;
if (settings == null)
throw new InvalidOperationException("Configuraiton file does not contain WebApiToSwagger settings.");

return new WebApiAssemblyToSwaggerGenerator(settings);
}
else
return new WebApiAssemblyToSwaggerGenerator(Settings);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@
// <author>Rico Suter, [email protected]</author>
//-----------------------------------------------------------------------

using NSwag.Commands;
using System.Threading.Tasks;
using NSwag.SwaggerGeneration.WebApi;

namespace NSwag.Commands
{
/// <summary></summary>
/// <summary>The generator.</summary>
/// <seealso cref="NSwag.Commands.WebApiToSwaggerCommandBase" />
public class WebApiToSwaggerCommand : WebApiToSwaggerCommandBase
{
/// <summary>Creates a new generator instance.</summary>
/// <returns>The generator.</returns>
protected override WebApiAssemblyToSwaggerGeneratorBase CreateGenerator()
protected override Task<WebApiAssemblyToSwaggerGeneratorBase> CreateGeneratorAsync()
{
return new WebApiAssemblyToSwaggerGenerator(Settings);
return Task.FromResult<WebApiAssemblyToSwaggerGeneratorBase>(new WebApiAssemblyToSwaggerGenerator(Settings));
}
}
}
66 changes: 59 additions & 7 deletions src/NSwag.AssemblyLoaderCore/NSwagDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ public async Task<SwaggerDocumentExecutionResult> ExecuteCommandLineAsync(bool r
return await ExecuteAsync();

var baseFilename = System.IO.Path.GetTempPath() + "nswag_document_" + Guid.NewGuid();
var configFilename = baseFilename + "_config.json";
var swaggerFilename = baseFilename + "_swagger.json";
var filenames = new List<string>();

Expand All @@ -95,10 +94,12 @@ public async Task<SwaggerDocumentExecutionResult> ExecuteCommandLineAsync(bool r
}
}

var configFilename = baseFilename + "_config.json";
File.WriteAllText(configFilename, clone.ToJson());
try
{
var output = await StartCommandLineProcessAsync(configFilename);
var command = "run \"" + configFilename + "\"";
var output = await StartCommandLineProcessAsync(command);
return clone.ProcessExecutionResult(output, baseFilename, redirectOutput);
}
finally
Expand All @@ -111,6 +112,48 @@ public async Task<SwaggerDocumentExecutionResult> ExecuteCommandLineAsync(bool r
});
}

/// <summary>Gets the available controller types by calling the command line.</summary>
/// <returns>The controller names.</returns>
public async Task<string[]> GetControllersFromCommandLineAsync()
{
return await Task.Run(async () =>
{
var baseFilename = System.IO.Path.GetTempPath() + "nswag_document_" + Guid.NewGuid();
var configFilename = baseFilename + "_config.json";
File.WriteAllText(configFilename, ToJson());
try
{
var command = "list-controllers /file:\"" + configFilename + "\"";
return GetListFromCommandLineOutput(await StartCommandLineProcessAsync(command));
}
finally
{
DeleteFileIfExists(configFilename);
}
});
}

/// <summary>Gets the available controller types by calling the command line.</summary>
/// <returns>The controller names.</returns>
public async Task<string[]> GetTypesFromCommandLineAsync()
{
return await Task.Run(async () =>
{
var baseFilename = System.IO.Path.GetTempPath() + "nswag_document_" + Guid.NewGuid();
var configFilename = baseFilename + "_config.json";
File.WriteAllText(configFilename, ToJson());
try
{
var command = "list-types /file:\"" + configFilename + "\"";
return GetListFromCommandLineOutput(await StartCommandLineProcessAsync(command));
}
finally
{
DeleteFileIfExists(configFilename);
}
});
}

/// <summary>Converts to absolute path.</summary>
/// <param name="pathToConvert">The path to convert.</param>
/// <returns>The absolute path.</returns>
Expand All @@ -131,6 +174,15 @@ protected override string ConvertToRelativePath(string pathToConvert)
return pathToConvert?.Replace("\\", "/");
}

private string[] GetListFromCommandLineOutput(string output)
{
return output.Replace("\r\n", "\n")
.Split(new string[] { "\n\n" }, StringSplitOptions.None)[1]
.Split('\n')
.Where(t => !string.IsNullOrEmpty(t))
.ToArray();
}

private SwaggerDocumentExecutionResult ProcessExecutionResult(string output, string baseFilename, bool redirectOutput)
{
var swaggerOutput = ReadFileIfExists(SelectedSwaggerGenerator.OutputFilePath);
Expand All @@ -148,9 +200,9 @@ private SwaggerDocumentExecutionResult ProcessExecutionResult(string output, str
return result;
}

private async Task<string> StartCommandLineProcessAsync(string configFilename)
private async Task<string> StartCommandLineProcessAsync(string command)
{
var processStart = new ProcessStartInfo(GetProgramName(), GetArgumentsPrefix() + "run \"" + configFilename + "\"");
var processStart = new ProcessStartInfo(GetProgramName(), GetArgumentsPrefix() + command);
processStart.RedirectStandardOutput = true;
processStart.RedirectStandardError = true;
processStart.UseShellExecute = false;
Expand All @@ -177,11 +229,11 @@ private string GetDocumentDirectory()

private string GetArgumentsPrefix()
{
if (Runtime == Runtime.Core10)
if (Runtime == Runtime.NetCore10)
return "\"" + System.IO.Path.Combine(RootBinaryDirectory, "netcoreapp1.0/dotnet-nswag.dll") + "\" ";
else if (Runtime == Runtime.Core11)
else if (Runtime == Runtime.NetCore11)
return "\"" + System.IO.Path.Combine(RootBinaryDirectory, "netcoreapp1.1/dotnet-nswag.dll") + "\" ";
else if (Runtime == Runtime.Core20)
else if (Runtime == Runtime.NetCore20)
return "\"" + System.IO.Path.Combine(RootBinaryDirectory, "netcoreapp2.0/dotnet-nswag.dll") + "\" ";
else
return "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public WebApiAssemblyToSwaggerGenerator(WebApiAssemblyToSwaggerGeneratorSettings
/// <exception cref="FileNotFoundException">The assembly could not be found.</exception>
/// <exception cref="FileNotFoundException">The assembly config file could not be found..</exception>
/// <exception cref="InvalidOperationException">No assembly paths have been provided.</exception>
public override string[] GetControllerClasses()
public override string[] GetExportedControllerClassNames()
{
if (Settings.AssemblyPaths == null || Settings.AssemblyPaths.Length == 0)
throw new InvalidOperationException("No assembly paths have been provided.");
Expand Down
37 changes: 37 additions & 0 deletions src/NSwag.Commands/Commands/AssemblyOutputCommandBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Threading.Tasks;
using NConsole;
using Newtonsoft.Json;
using NSwag.Commands.Base;
using NSwag.SwaggerGeneration;

namespace NSwag.Commands
{
public abstract class AssemblyOutputCommandBase : OutputCommandBase
{
public AssemblyOutputCommandBase()
{
Settings = new AssemblyTypeToSwaggerGeneratorSettings();
}

[JsonIgnore]
public AssemblyTypeToSwaggerGeneratorSettings Settings { get; set; }

[Argument(Name = "AssemblyConfig", IsRequired = false, Description = "The path to the assembly App.config or Web.config (optional).")]
public string AssemblyConfig
{
get { return Settings.AssemblyConfig; }
set { Settings.AssemblyConfig = value; }
}

[Argument(Name = "ReferencePaths", IsRequired = false, Description = "The paths to search for referenced assembly files (comma separated).")]
public string[] ReferencePaths
{
get { return Settings.ReferencePaths; }
set { Settings.ReferencePaths = value; }
}

/// <summary>Creates a new generator instance.</summary>
/// <returns>The generator.</returns>
protected abstract Task<AssemblyTypeToSwaggerGeneratorBase> CreateGeneratorAsync();
}
}
33 changes: 4 additions & 29 deletions src/NSwag.Commands/Commands/AssemblyTypeToSwaggerCommandBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,21 @@

using System.Threading.Tasks;
using NConsole;
using Newtonsoft.Json;
using NJsonSchema;
using NSwag.Commands.Base;
using NSwag.SwaggerGeneration;

#pragma warning disable 1591

namespace NSwag.Commands
{
[Command(Name = "types2swagger")]
public abstract class AssemblyTypeToSwaggerCommandBase : OutputCommandBase
public abstract class AssemblyTypeToSwaggerCommandBase : AssemblyOutputCommandBase
{
public AssemblyTypeToSwaggerCommandBase()
{
Settings = new AssemblyTypeToSwaggerGeneratorSettings();
ClassNames = new string[] { };
}

[JsonIgnore]
public AssemblyTypeToSwaggerGeneratorSettings Settings { get; set; }

[Argument(Name = "Assembly", Description = "The path to the Web API .NET assembly.")]
[Argument(Name = "Assembly", IsRequired = true, Description = "The path to the Web API .NET assembly.")]
public string AssemblyPath
{
get { return Settings.AssemblyPath; }
Expand All @@ -39,20 +32,6 @@ public string AssemblyPath
[Argument(Name = "ClassNames", Description = "The class names.")]
public string[] ClassNames { get; set; }

[Argument(Name = "AssemblyConfig", IsRequired = false, Description = "The path to the assembly App.config or Web.config (optional).")]
public string AssemblyConfig
{
get { return Settings.AssemblyConfig; }
set { Settings.AssemblyConfig = value; }
}

[Argument(Name = "ReferencePaths", IsRequired = false, Description = "The paths to search for referenced assembly files.")]
public string[] ReferencePaths
{
get { return Settings.ReferencePaths; }
set { Settings.ReferencePaths = value; }
}

[Argument(Name = "DefaultPropertyNameHandling", IsRequired = false, Description = "The default property name handling ('Default' or 'CamelCase').")]
public PropertyNameHandling DefaultPropertyNameHandling
{
Expand Down Expand Up @@ -99,20 +78,16 @@ public override async Task<object> RunAsync(CommandLineProcessor processor, ICon
{
var document = await RunAsync();
await TryWriteFileOutputAsync(host, () => document.ToJson()).ConfigureAwait(false);
return document;
return document;
}

public async Task<SwaggerDocument> RunAsync()
{
return await Task.Run(async () =>
{
var generator = CreateGenerator();
var generator = await CreateGeneratorAsync();
return await generator.GenerateAsync(ClassNames).ConfigureAwait(false);
});
}

/// <summary>Creates a new generator instance.</summary>
/// <returns>The generator.</returns>
protected abstract AssemblyTypeToSwaggerGeneratorBase CreateGenerator();
}
}
Loading

0 comments on commit 55784ba

Please sign in to comment.