Rewrite dotnet-getdocument and GetDocument.Insider to retrieve all documents in one go (#10667)
- #8242 1 of 2 - save a cache file listing all retrieved documents - remove .NET Core App 2.0 support - remove ServiceProjectReferenceMetadata.targets, related `Project` class, and searches for a project - tools will run within a project and get needed information from project on command line - roll framework forward in both tools to expand their applicability when using .NET Core - use Microsoft.Extensions.HostFactoryResolver.Sources (part of #4923) - remove Microsoft.AspNetCore.Hosting.Abstractions dependency nits: - refactor methods in `GetDocumentCommandWorker` - reorder option addition for consistency and to place `--help` at the top of help output - consolidate information about method signatures at top of `GetDocumentCommandWorker` - consolidate `try` / `catch` blocks in `GetDocumentCommandWorker` - shorten the lifespan of a `Task` - ensure GetDocument.Insider exit codes are unique - make a few more `string`s `const` - fold a few expressions over fewer lines
This commit is contained in:
parent
91e6839c8d
commit
4c8ca0b080
|
|
@ -32,7 +32,6 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
{
|
||||
}
|
||||
|
||||
protected virtual int Execute()
|
||||
=> 0;
|
||||
protected virtual int Execute() => 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
#if NETCOREAPP2_0
|
||||
#if NETCOREAPP2_1
|
||||
using System.Runtime.Loader;
|
||||
#endif
|
||||
using Microsoft.DotNet.Cli.CommandLine;
|
||||
|
|
@ -14,45 +14,30 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
{
|
||||
internal class GetDocumentCommand : ProjectCommandBase
|
||||
{
|
||||
internal const string FallbackDocumentName = "v1";
|
||||
internal const string FallbackMethod = "GenerateAsync";
|
||||
internal const string FallbackService = "Microsoft.Extensions.ApiDescription.IDocumentProvider";
|
||||
|
||||
private CommandOption _documentName;
|
||||
private CommandOption _method;
|
||||
private CommandOption _fileListPath;
|
||||
private CommandOption _output;
|
||||
private CommandOption _service;
|
||||
|
||||
public override void Configure(CommandLineApplication command)
|
||||
{
|
||||
base.Configure(command);
|
||||
|
||||
_documentName = command.Option(
|
||||
"--documentName <Name>",
|
||||
Resources.FormatDocumentDescription(FallbackDocumentName));
|
||||
_method = command.Option("--method <Name>", Resources.FormatMethodDescription(FallbackMethod));
|
||||
_output = command.Option("--output <Path>", Resources.OutputDescription);
|
||||
_service = command.Option("--service <QualifiedName>", Resources.FormatServiceDescription(FallbackService));
|
||||
_fileListPath = command.Option("--file-list <Path>", Resources.FileListDescription);
|
||||
_output = command.Option("--output <Directory>", Resources.OutputDescription);
|
||||
}
|
||||
|
||||
protected override void Validate()
|
||||
{
|
||||
base.Validate();
|
||||
|
||||
if (!_fileListPath.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(_fileListPath.LongName));
|
||||
}
|
||||
|
||||
if (!_output.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(_output.LongName));
|
||||
}
|
||||
|
||||
if (_method.HasValue() && !_service.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(_service.LongName));
|
||||
}
|
||||
|
||||
if (_service.HasValue() && !_method.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(_method.LongName));
|
||||
}
|
||||
}
|
||||
|
||||
protected override int Execute()
|
||||
|
|
@ -79,7 +64,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
}
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_0
|
||||
#if NETCOREAPP2_1
|
||||
AssemblyLoadContext.Default.Resolving += (loadContext, assemblyName) =>
|
||||
{
|
||||
var name = assemblyName.Name;
|
||||
|
|
@ -125,7 +110,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
return Assembly.LoadFile(assemblyPath);
|
||||
};
|
||||
#else
|
||||
#error target frameworks need to be updated.
|
||||
#error Target frameworks need to be updated.
|
||||
#endif
|
||||
|
||||
// Now safe to reference the application's code.
|
||||
|
|
@ -135,12 +120,10 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
var context = new GetDocumentCommandContext
|
||||
{
|
||||
AssemblyPath = assemblyPath,
|
||||
AssemblyDirectory = Path.GetDirectoryName(assemblyPath),
|
||||
AssemblyName = Path.GetFileNameWithoutExtension(assemblyPath),
|
||||
DocumentName = _documentName.Value(),
|
||||
Method = _method.Value(),
|
||||
OutputPath = _output.Value(),
|
||||
Service = _service.Value(),
|
||||
FileListPath = _fileListPath.Value(),
|
||||
OutputDirectory = _output.Value(),
|
||||
ProjectName = ProjectName.Value(),
|
||||
};
|
||||
|
||||
return GetDocumentCommandWorker.Process(context);
|
||||
|
|
@ -148,7 +131,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine(ex.ToString());
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
[Serializable]
|
||||
public class GetDocumentCommandContext
|
||||
{
|
||||
public string AssemblyDirectory { get; set; }
|
||||
|
||||
public string AssemblyName { get; set; }
|
||||
|
||||
public string AssemblyPath { get; set; }
|
||||
|
||||
public string DocumentName { get; set; }
|
||||
public string FileListPath { get; set; }
|
||||
|
||||
public string Method { get; set; }
|
||||
public string OutputDirectory { get; set; }
|
||||
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
public string Service { get; set; }
|
||||
public string ProjectName { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,36 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
||||
{
|
||||
internal class GetDocumentCommandWorker
|
||||
{
|
||||
private const string DefaultDocumentName = "v1";
|
||||
private const string DocumentService = "Microsoft.Extensions.ApiDescriptions.IDocumentProvider";
|
||||
private const string DotString = ".";
|
||||
private const string InvalidFilenameString = "..";
|
||||
private const string JsonExtension = ".json";
|
||||
private const string UnderscoreString = "_";
|
||||
private static readonly char[] InvalidFilenameCharacters = Path.GetInvalidFileNameChars();
|
||||
private static readonly Encoding UTF8EncodingWithoutBOM
|
||||
= new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
|
||||
|
||||
private const string GetDocumentsMethodName = "GetDocumentNames";
|
||||
private static readonly object[] GetDocumentsArguments = Array.Empty<object>();
|
||||
private static readonly Type[] GetDocumentsParameterTypes = Type.EmptyTypes;
|
||||
private static readonly Type GetDocumentsReturnType = typeof(IEnumerable<string>);
|
||||
|
||||
private const string GenerateMethodName = "GenerateAsync";
|
||||
private static readonly Type[] GenerateMethodParameterTypes = new[] { typeof(string), typeof(TextWriter) };
|
||||
private static readonly Type GenerateMethodReturnType = typeof(Task);
|
||||
|
||||
public static int Process(GetDocumentCommandContext context)
|
||||
{
|
||||
var assemblyName = new AssemblyName(context.AssemblyName);
|
||||
|
|
@ -19,203 +40,251 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
if (entryPointType == null)
|
||||
{
|
||||
Reporter.WriteError(Resources.FormatMissingEntryPoint(context.AssemblyPath));
|
||||
return 2;
|
||||
}
|
||||
|
||||
var services = GetServices(entryPointType, context.AssemblyPath, context.AssemblyName);
|
||||
if (services == null)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
var success = TryProcess(context, services);
|
||||
if (!success)
|
||||
try
|
||||
{
|
||||
// As part of the aspnet/Mvc#8425 fix, return 4 here.
|
||||
return 0;
|
||||
var serviceFactory = HostFactoryResolver.ResolveServiceProviderFactory(assembly);
|
||||
if (serviceFactory == null)
|
||||
{
|
||||
Reporter.WriteError(Resources.FormatMethodsNotFound(
|
||||
HostFactoryResolver.BuildWebHost,
|
||||
HostFactoryResolver.CreateHostBuilder,
|
||||
HostFactoryResolver.CreateWebHostBuilder,
|
||||
entryPointType));
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
var services = serviceFactory(Array.Empty<string>());
|
||||
if (services == null)
|
||||
{
|
||||
Reporter.WriteError(Resources.FormatServiceProviderNotFound(
|
||||
typeof(IServiceProvider),
|
||||
HostFactoryResolver.BuildWebHost,
|
||||
HostFactoryResolver.CreateHostBuilder,
|
||||
HostFactoryResolver.CreateWebHostBuilder,
|
||||
entryPointType));
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
var success = GetDocuments(context, services);
|
||||
if (!success)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Reporter.WriteError(ex.ToString());
|
||||
return 7;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static bool TryProcess(GetDocumentCommandContext context, IServiceProvider services)
|
||||
private static bool GetDocuments(GetDocumentCommandContext context, IServiceProvider services)
|
||||
{
|
||||
var documentName = string.IsNullOrEmpty(context.DocumentName) ?
|
||||
GetDocumentCommand.FallbackDocumentName :
|
||||
context.DocumentName;
|
||||
var methodName = string.IsNullOrEmpty(context.Method) ?
|
||||
GetDocumentCommand.FallbackMethod :
|
||||
context.Method;
|
||||
var serviceName = string.IsNullOrEmpty(context.Service) ?
|
||||
GetDocumentCommand.FallbackService :
|
||||
context.Service;
|
||||
Type serviceType = null;
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
serviceType = assembly.GetType(DocumentService, throwOnError: false);
|
||||
if (serviceType != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reporter.WriteInformation(Resources.FormatUsingDocument(documentName));
|
||||
Reporter.WriteInformation(Resources.FormatUsingMethod(methodName));
|
||||
Reporter.WriteInformation(Resources.FormatUsingService(serviceName));
|
||||
if (serviceType == null)
|
||||
{
|
||||
Reporter.WriteError(Resources.FormatServiceTypeNotFound(DocumentService));
|
||||
return false;
|
||||
}
|
||||
|
||||
var getDocumentsMethod = GetMethod(
|
||||
GetDocumentsMethodName,
|
||||
serviceType,
|
||||
GetDocumentsParameterTypes,
|
||||
GetDocumentsReturnType);
|
||||
if (getDocumentsMethod == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var generateMethod = GetMethod(
|
||||
GenerateMethodName,
|
||||
serviceType,
|
||||
GenerateMethodParameterTypes,
|
||||
GenerateMethodReturnType);
|
||||
if (generateMethod == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var service = services.GetService(serviceType);
|
||||
if (service == null)
|
||||
{
|
||||
Reporter.WriteError(Resources.FormatServiceNotFound(DocumentService));
|
||||
return false;
|
||||
}
|
||||
|
||||
var documentNames = (IEnumerable<string>)InvokeMethod(getDocumentsMethod, service, GetDocumentsArguments);
|
||||
if (documentNames == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write out the documents.
|
||||
Directory.CreateDirectory(context.OutputDirectory);
|
||||
var filePathList = new List<string>();
|
||||
foreach (var documentName in documentNames)
|
||||
{
|
||||
var filePath = GetDocument(
|
||||
documentName,
|
||||
context.ProjectName,
|
||||
context.OutputDirectory,
|
||||
generateMethod,
|
||||
service);
|
||||
if (filePath == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
filePathList.Add(filePath);
|
||||
}
|
||||
|
||||
// Write out the cache file.
|
||||
var stream = File.Create(context.FileListPath);
|
||||
using var writer = new StreamWriter(stream);
|
||||
writer.WriteLine(string.Join(Environment.NewLine, filePathList));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string GetDocument(
|
||||
string documentName,
|
||||
string projectName,
|
||||
string outputDirectory,
|
||||
MethodInfo generateMethod,
|
||||
object service)
|
||||
{
|
||||
Reporter.WriteInformation(Resources.FormatGeneratingDocument(documentName));
|
||||
|
||||
using var stream = new MemoryStream();
|
||||
using (var writer = new StreamWriter(stream, UTF8EncodingWithoutBOM, bufferSize: 1024, leaveOpen: true))
|
||||
{
|
||||
var arguments = new object[] { documentName, writer };
|
||||
using var resultTask = (Task)InvokeMethod(generateMethod, service, arguments);
|
||||
if (resultTask == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var finished = resultTask.Wait(TimeSpan.FromMinutes(1));
|
||||
if (!finished)
|
||||
{
|
||||
Reporter.WriteError(Resources.FormatMethodTimedOut(GenerateMethodName, DocumentService, 1));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (stream.Length == 0L)
|
||||
{
|
||||
Reporter.WriteError(
|
||||
Resources.FormatMethodWroteNoContent(GenerateMethodName, DocumentService, documentName));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var filePath = GetDocumentPath(documentName, projectName, outputDirectory);
|
||||
Reporter.WriteInformation(Resources.FormatWritingDocument(documentName, filePath));
|
||||
try
|
||||
{
|
||||
Type serviceType = null;
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
serviceType = assembly.GetType(serviceName, throwOnError: false);
|
||||
if (serviceType != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// As part of the aspnet/Mvc#8425 fix, make all warnings in this method errors unless the file already
|
||||
// exists.
|
||||
if (serviceType == null)
|
||||
{
|
||||
Reporter.WriteWarning(Resources.FormatServiceTypeNotFound(serviceName));
|
||||
return false;
|
||||
}
|
||||
|
||||
var method = serviceType.GetMethod(methodName, new[] { typeof(string), typeof(TextWriter) });
|
||||
if (method == null)
|
||||
{
|
||||
Reporter.WriteWarning(Resources.FormatMethodNotFound(methodName, serviceName));
|
||||
return false;
|
||||
}
|
||||
else if (!typeof(Task).IsAssignableFrom(method.ReturnType))
|
||||
{
|
||||
Reporter.WriteWarning(Resources.FormatMethodReturnTypeUnsupported(
|
||||
methodName,
|
||||
serviceName,
|
||||
method.ReturnType,
|
||||
typeof(Task)));
|
||||
return false;
|
||||
}
|
||||
|
||||
var service = services.GetService(serviceType);
|
||||
if (service == null)
|
||||
{
|
||||
Reporter.WriteWarning(Resources.FormatServiceNotFound(serviceName));
|
||||
return false;
|
||||
}
|
||||
stream.Position = 0L;
|
||||
|
||||
// Create the output FileStream last to avoid corrupting an existing file or writing partial data.
|
||||
var stream = new MemoryStream();
|
||||
using (var writer = new StreamWriter(stream))
|
||||
{
|
||||
var resultTask = (Task)method.Invoke(service, new object[] { documentName, writer });
|
||||
if (resultTask == null)
|
||||
{
|
||||
Reporter.WriteWarning(
|
||||
Resources.FormatMethodReturnedNull(methodName, serviceName, nameof(Task)));
|
||||
return false;
|
||||
}
|
||||
|
||||
var finishedIndex = Task.WaitAny(resultTask, Task.Delay(TimeSpan.FromMinutes(1)));
|
||||
if (finishedIndex != 0)
|
||||
{
|
||||
Reporter.WriteWarning(Resources.FormatMethodTimedOut(methodName, serviceName, 1));
|
||||
return false;
|
||||
}
|
||||
|
||||
writer.Flush();
|
||||
if (stream.Length > 0L)
|
||||
{
|
||||
stream.Position = 0L;
|
||||
using (var outStream = File.Create(context.OutputPath))
|
||||
{
|
||||
stream.CopyTo(outStream);
|
||||
outStream.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
using var outStream = File.Create(filePath);
|
||||
stream.CopyTo(outStream);
|
||||
}
|
||||
catch (AggregateException ex) when (ex.InnerException != null)
|
||||
catch
|
||||
{
|
||||
foreach (var innerException in ex.Flatten().InnerExceptions)
|
||||
{
|
||||
Reporter.WriteWarning(FormatException(innerException));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Reporter.WriteWarning(FormatException(ex));
|
||||
File.Delete(filePath);
|
||||
throw;
|
||||
}
|
||||
|
||||
File.Delete(context.OutputPath);
|
||||
|
||||
return false;
|
||||
return filePath;
|
||||
}
|
||||
|
||||
// TODO: Use Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Sources once we have dev feed available.
|
||||
private static IServiceProvider GetServices(Type entryPointType, string assemblyPath, string assemblyName)
|
||||
private static string GetDocumentPath(string documentName, string projectName, string outputDirectory)
|
||||
{
|
||||
var args = new[] { Array.Empty<string>() };
|
||||
var methodInfo = entryPointType.GetMethod("BuildWebHost");
|
||||
if (methodInfo != null)
|
||||
string path;
|
||||
if (string.Equals(DefaultDocumentName, documentName, StringComparison.Ordinal))
|
||||
{
|
||||
// BuildWebHost (old style has highest priority)
|
||||
var parameters = methodInfo.GetParameters();
|
||||
if (!methodInfo.IsStatic ||
|
||||
parameters.Length != 1 ||
|
||||
typeof(string[]) != parameters[0].ParameterType ||
|
||||
typeof(IWebHost) != methodInfo.ReturnType)
|
||||
{
|
||||
Reporter.WriteError(
|
||||
"BuildWebHost method found in {assemblyPath} does not have expected signature.");
|
||||
// Leave default document name out of the filename.
|
||||
path = projectName + JsonExtension;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sanitize the document name because it may contain almost any character, including illegal filename
|
||||
// characters such as '/' and '?' and the string "..". Do not treat slashes as folder separators.
|
||||
var sanitizedDocumentName = string.Join(
|
||||
UnderscoreString,
|
||||
documentName.Split(InvalidFilenameCharacters));
|
||||
|
||||
return null;
|
||||
while (sanitizedDocumentName.Contains(InvalidFilenameString))
|
||||
{
|
||||
sanitizedDocumentName = sanitizedDocumentName.Replace(InvalidFilenameString, DotString);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var webHost = (IWebHost)methodInfo.Invoke(obj: null, parameters: args);
|
||||
|
||||
return webHost.Services;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Reporter.WriteError($"BuildWebHost method threw: {FormatException(ex)}");
|
||||
|
||||
return null;
|
||||
}
|
||||
path = $"{projectName}_{documentName}{JsonExtension}";
|
||||
}
|
||||
|
||||
if ((methodInfo = entryPointType.GetMethod("CreateWebHostBuilder")) != null)
|
||||
if (!string.IsNullOrEmpty(outputDirectory))
|
||||
{
|
||||
// CreateWebHostBuilder
|
||||
var parameters = methodInfo.GetParameters();
|
||||
if (!methodInfo.IsStatic ||
|
||||
parameters.Length != 1 ||
|
||||
typeof(string[]) != parameters[0].ParameterType ||
|
||||
typeof(IWebHostBuilder) != methodInfo.ReturnType)
|
||||
{
|
||||
Reporter.WriteError(
|
||||
"CreateWebHostBuilder method found in {assemblyPath} does not have expected signature.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var builder = (IWebHostBuilder)methodInfo.Invoke(obj: null, parameters: args);
|
||||
|
||||
return builder.Build().Services;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Reporter.WriteError($"CreateWebHostBuilder method threw: {FormatException(ex)}");
|
||||
|
||||
return null;
|
||||
}
|
||||
path = Path.Combine(outputDirectory, path);
|
||||
}
|
||||
|
||||
return null;
|
||||
return path;
|
||||
}
|
||||
|
||||
private static string FormatException(Exception exception)
|
||||
private static MethodInfo GetMethod(string methodName, Type type, Type[] parameterTypes, Type returnType)
|
||||
{
|
||||
return $"{exception.GetType().FullName}: {exception.Message}";
|
||||
var method = type.GetMethod(methodName, parameterTypes);
|
||||
if (method == null)
|
||||
{
|
||||
Reporter.WriteError(Resources.FormatMethodNotFound(methodName, type));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (method.IsStatic)
|
||||
{
|
||||
Reporter.WriteError(Resources.FormatMethodIsStatic(methodName, type));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!returnType.IsAssignableFrom(method.ReturnType))
|
||||
{
|
||||
Reporter.WriteError(
|
||||
Resources.FormatMethodReturnTypeUnsupported(methodName, type, method.ReturnType, returnType));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
private static object InvokeMethod(MethodInfo method, object instance, object[] arguments)
|
||||
{
|
||||
var result = method.Invoke(instance, arguments);
|
||||
if (result == null)
|
||||
{
|
||||
Reporter.WriteError(
|
||||
Resources.FormatMethodReturnedNull(method.Name, method.DeclaringType, method.ReturnType));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
{
|
||||
public override void Configure(CommandLineApplication command)
|
||||
{
|
||||
base.Configure(command);
|
||||
|
||||
command.HelpOption("-h|--help");
|
||||
command.VersionOption("--version", ProductInfo.GetVersion);
|
||||
base.Configure(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,16 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
{
|
||||
public CommandOption AssemblyPath { get; private set; }
|
||||
|
||||
public CommandOption ProjectName { get; private set; }
|
||||
|
||||
public CommandOption ToolsDirectory { get; private set; }
|
||||
|
||||
public override void Configure(CommandLineApplication command)
|
||||
{
|
||||
base.Configure(command);
|
||||
|
||||
AssemblyPath = command.Option("-a|--assembly <PATH>", Resources.AssemblyDescription);
|
||||
AssemblyPath = command.Option("--assembly <PATH>", Resources.AssemblyDescription);
|
||||
ProjectName = command.Option("--project <Name>", Resources.ProjectDescription);
|
||||
ToolsDirectory = command.Option("--tools-directory <PATH>", Resources.ToolsDirectoryDescription);
|
||||
}
|
||||
|
||||
|
|
@ -28,6 +31,11 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
throw new CommandException(Resources.FormatMissingOption(AssemblyPath.LongName));
|
||||
}
|
||||
|
||||
if (!ProjectName.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(ProjectName.LongName));
|
||||
}
|
||||
|
||||
if (!ToolsDirectory.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(ToolsDirectory.LongName));
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<IsPackable>false</IsPackable>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Microsoft.Extensions.ApiDescription.Tool</RootNamespace>
|
||||
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
|
||||
<VerifyVersion>false</VerifyVersion>
|
||||
<VersionPrefix>$(ExperimentalVersionPrefix)</VersionPrefix>
|
||||
<VersionSuffix>$(ExperimentalVersionSuffix)</VersionSuffix>
|
||||
|
|
@ -17,10 +17,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Hard-coded to 2.0 because this project currently targets netcoreapp2.0 -->
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.0.0">
|
||||
<AllowExplicitReference>true</AllowExplicitReference>
|
||||
</PackageReference>
|
||||
<Reference Include="Microsoft.Extensions.HostFactoryResolver.Sources" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="BuildX86" AfterTargets="Build" Condition=" '$(TargetFramework)' == 'net461' And '$(Platform)' != 'x86' ">
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
Console.OutputEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
var app = new CommandLineApplication(throwOnUnexpectedArg: false)
|
||||
var app = new CommandLineApplication()
|
||||
{
|
||||
Name = "GetDocument.Insider"
|
||||
FullName = Resources.CommandFullName,
|
||||
Name = Resources.CommandFullName,
|
||||
};
|
||||
|
||||
new GetDocumentCommand().Configure(app);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
= new ResourceManager("Microsoft.Extensions.ApiDescription.Tool.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// The assembly to use.
|
||||
/// The assembly path to use. Required.
|
||||
/// </summary>
|
||||
internal static string AssemblyDescription
|
||||
{
|
||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The assembly to use.
|
||||
/// The assembly path to use. Required.
|
||||
/// </summary>
|
||||
internal static string FormatAssemblyDescription()
|
||||
=> GetString("AssemblyDescription");
|
||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
=> string.Format(CultureInfo.CurrentCulture, GetString("MissingOption"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Do not colorize output.
|
||||
/// Do not colorize console output.
|
||||
/// </summary>
|
||||
internal static string NoColorDescription
|
||||
{
|
||||
|
|
@ -47,13 +47,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do not colorize output.
|
||||
/// Do not colorize console output.
|
||||
/// </summary>
|
||||
internal static string FormatNoColorDescription()
|
||||
=> GetString("NoColorDescription");
|
||||
|
||||
/// <summary>
|
||||
/// The file to write the result to.
|
||||
/// The directory where the document files should be written. Required.
|
||||
/// </summary>
|
||||
internal static string OutputDescription
|
||||
{
|
||||
|
|
@ -61,7 +61,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The file to write the result to.
|
||||
/// The directory where the document files should be written. Required.
|
||||
/// </summary>
|
||||
internal static string FormatOutputDescription()
|
||||
=> GetString("OutputDescription");
|
||||
|
|
@ -81,7 +81,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
=> GetString("PrefixDescription");
|
||||
|
||||
/// <summary>
|
||||
/// Show verbose output.
|
||||
/// Show verbose console output.
|
||||
/// </summary>
|
||||
internal static string VerboseDescription
|
||||
{
|
||||
|
|
@ -89,13 +89,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show verbose output.
|
||||
/// Show verbose console output.
|
||||
/// </summary>
|
||||
internal static string FormatVerboseDescription()
|
||||
=> GetString("VerboseDescription");
|
||||
|
||||
/// <summary>
|
||||
/// Location from which inside man was copied (in the .NET Framework case) or loaded.
|
||||
/// Location from which inside man was copied (in the .NET Framework case) or loaded. Required.
|
||||
/// </summary>
|
||||
internal static string ToolsDirectoryDescription
|
||||
{
|
||||
|
|
@ -103,108 +103,24 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Location from which inside man was copied (in the .NET Framework case) or loaded.
|
||||
/// Location from which inside man was copied (in the .NET Framework case) or loaded. Required.
|
||||
/// </summary>
|
||||
internal static string FormatToolsDirectoryDescription()
|
||||
=> GetString("ToolsDirectoryDescription");
|
||||
|
||||
/// <summary>
|
||||
/// The name of the method to invoke on the '--service' instance. Default value '{0}'.
|
||||
/// Generating document named '{0}'.
|
||||
/// </summary>
|
||||
internal static string MethodDescription
|
||||
internal static string GeneratingDocument
|
||||
{
|
||||
get => GetString("MethodDescription");
|
||||
get => GetString("GeneratingDocument");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the method to invoke on the '--service' instance. Default value '{0}'.
|
||||
/// Generating document named '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatMethodDescription(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodDescription"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// The qualified name of the service type to retrieve from dependency injection. Default value '{0}'.
|
||||
/// </summary>
|
||||
internal static string ServiceDescription
|
||||
{
|
||||
get => GetString("ServiceDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The qualified name of the service type to retrieve from dependency injection. Default value '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatServiceDescription(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("ServiceDescription"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// The name of the document to pass to the '--method' method. Default value '{0}'.
|
||||
/// </summary>
|
||||
internal static string DocumentDescription
|
||||
{
|
||||
get => GetString("DocumentDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the document to pass to the '--method' method. Default value '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatDocumentDescription(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("DocumentDescription"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Using document name '{0}'.
|
||||
/// </summary>
|
||||
internal static string UsingDocument
|
||||
{
|
||||
get => GetString("UsingDocument");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Using document name '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatUsingDocument(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("UsingDocument"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Using method '{0}'.
|
||||
/// </summary>
|
||||
internal static string UsingMethod
|
||||
{
|
||||
get => GetString("UsingMethod");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Using method '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatUsingMethod(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("UsingMethod"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Using service '{0}'.
|
||||
/// </summary>
|
||||
internal static string UsingService
|
||||
{
|
||||
get => GetString("UsingService");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Using service '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatUsingService(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("UsingService"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of service '{1}' failed to generate document '{2}'.
|
||||
/// </summary>
|
||||
internal static string MethodInvocationFailed
|
||||
{
|
||||
get => GetString("MethodInvocationFailed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of service '{1}' failed to generate document '{2}'.
|
||||
/// </summary>
|
||||
internal static string FormatMethodInvocationFailed(object p0, object p1, object p2)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodInvocationFailed"), p0, p1, p2);
|
||||
internal static string FormatGeneratingDocument(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("GeneratingDocument"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Assembly '{0}' does not contain an entry point.
|
||||
|
|
@ -235,7 +151,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
=> string.Format(CultureInfo.CurrentCulture, GetString("ServiceTypeNotFound"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Unable to find method named '{0}' in '{1}' implementation.
|
||||
/// Method '{0}' not found in type '{1}' with expected signature.
|
||||
/// </summary>
|
||||
internal static string MethodNotFound
|
||||
{
|
||||
|
|
@ -243,13 +159,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unable to find method named '{0}' in '{1}' implementation.
|
||||
/// Method '{0}' not found in type '{1}' with expected signature.
|
||||
/// </summary>
|
||||
internal static string FormatMethodNotFound(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodNotFound"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// Unable to find service of type '{0}' in dependency injection container.
|
||||
/// Unable to find service type '{0}' in dependency injection container.
|
||||
/// </summary>
|
||||
internal static string ServiceNotFound
|
||||
{
|
||||
|
|
@ -257,13 +173,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unable to find service of type '{0}' in dependency injection container.
|
||||
/// Unable to find service type '{0}' in dependency injection container.
|
||||
/// </summary>
|
||||
internal static string FormatServiceNotFound(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("ServiceNotFound"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of service '{1}' returned null. Must return a non-null '{2}'.
|
||||
/// Method '{0}' of type '{1}' returned null. Must return a non-null '{2}'.
|
||||
/// </summary>
|
||||
internal static string MethodReturnedNull
|
||||
{
|
||||
|
|
@ -271,13 +187,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of service '{1}' returned null. Must return a non-null '{2}'.
|
||||
/// Method '{0}' of type '{1}' returned null. Must return a non-null '{2}'.
|
||||
/// </summary>
|
||||
internal static string FormatMethodReturnedNull(object p0, object p1, object p2)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodReturnedNull"), p0, p1, p2);
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of service '{1}' has unsupported return type '{2}'. Must return a '{3}'.
|
||||
/// Method '{0}' of type '{1}' has unsupported return type '{2}'. Must return '{3}'.
|
||||
/// </summary>
|
||||
internal static string MethodReturnTypeUnsupported
|
||||
{
|
||||
|
|
@ -285,13 +201,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of service '{1}' has unsupported return type '{2}'. Must return a '{3}'.
|
||||
/// Method '{0}' of type '{1}' has unsupported return type '{2}'. Must return '{3}'.
|
||||
/// </summary>
|
||||
internal static string FormatMethodReturnTypeUnsupported(object p0, object p1, object p2, object p3)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodReturnTypeUnsupported"), p0, p1, p2, p3);
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of service '{1}' timed out. Must complete execution within {2} minute.
|
||||
/// Method '{0}' of type '{1}' timed out. Must complete execution within {2} minute.
|
||||
/// </summary>
|
||||
internal static string MethodTimedOut
|
||||
{
|
||||
|
|
@ -299,11 +215,123 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of service '{1}' timed out. Must complete execution within {2} minute.
|
||||
/// Method '{0}' of type '{1}' timed out. Must complete execution within {2} minute.
|
||||
/// </summary>
|
||||
internal static string FormatMethodTimedOut(object p0, object p1, object p2)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodTimedOut"), p0, p1, p2);
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of type '{1}' is static. Must be an instance method.
|
||||
/// </summary>
|
||||
internal static string MethodIsStatic
|
||||
{
|
||||
get => GetString("MethodIsStatic");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of type '{1}' is static. Must be an instance method.
|
||||
/// </summary>
|
||||
internal static string FormatMethodIsStatic(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodIsStatic"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// No method '{0}', '{1}' or '{2}' found in type '{3}' with expected signatures.
|
||||
/// </summary>
|
||||
internal static string MethodsNotFound
|
||||
{
|
||||
get => GetString("MethodsNotFound");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No method '{0}', '{1}' or '{2}' found in type '{3}' with expected signatures.
|
||||
/// </summary>
|
||||
internal static string FormatMethodsNotFound(object p0, object p1, object p2, object p3)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodsNotFound"), p0, p1, p2, p3);
|
||||
|
||||
/// <summary>
|
||||
/// Writing document named '{0}' to '{1}'.
|
||||
/// </summary>
|
||||
internal static string WritingDocument
|
||||
{
|
||||
get => GetString("WritingDocument");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writing document named '{0}' to '{1}'.
|
||||
/// </summary>
|
||||
internal static string FormatWritingDocument(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("WritingDocument"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of type '{1}' wrote no content for document named '{2}'.
|
||||
/// </summary>
|
||||
internal static string MethodWroteNoContent
|
||||
{
|
||||
get => GetString("MethodWroteNoContent");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method '{0}' of type '{1}' wrote no content for document named '{2}'.
|
||||
/// </summary>
|
||||
internal static string FormatMethodWroteNoContent(object p0, object p1, object p2)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MethodWroteNoContent"), p0, p1, p2);
|
||||
|
||||
/// <summary>
|
||||
/// GetDocument.Insider
|
||||
/// </summary>
|
||||
internal static string CommandFullName
|
||||
{
|
||||
get => GetString("CommandFullName");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetDocument.Insider
|
||||
/// </summary>
|
||||
internal static string FormatCommandFullName()
|
||||
=> GetString("CommandFullName");
|
||||
|
||||
/// <summary>
|
||||
/// The path where the list of document files should be written. Required.
|
||||
/// </summary>
|
||||
internal static string FileListDescription
|
||||
{
|
||||
get => GetString("FileListDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The path where the list of document files should be written. Required.
|
||||
/// </summary>
|
||||
internal static string FormatFileListDescription()
|
||||
=> GetString("FileListDescription");
|
||||
|
||||
/// <summary>
|
||||
/// The project name to use. Required.
|
||||
/// </summary>
|
||||
internal static string ProjectDescription
|
||||
{
|
||||
get => GetString("ProjectDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The project name to use. Required.
|
||||
/// </summary>
|
||||
internal static string FormatProjectDescription()
|
||||
=> GetString("ProjectDescription");
|
||||
|
||||
/// <summary>
|
||||
/// Unable to resolve a non-null '{0}' implementation using method '{1}', '{2}' or '{3}' of type '{4}'.
|
||||
/// </summary>
|
||||
internal static string ServiceProviderNotFound
|
||||
{
|
||||
get => GetString("ServiceProviderNotFound");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unable to resolve a non-null '{0}' implementation using method '{1}', '{2}' or '{3}' of type '{4}'.
|
||||
/// </summary>
|
||||
internal static string FormatServiceProviderNotFound(object p0, object p1, object p2, object p3, object p4)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("ServiceProviderNotFound"), p0, p1, p2, p3, p4);
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -118,46 +118,28 @@
|
|||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AssemblyDescription" xml:space="preserve">
|
||||
<value>The assembly to use.</value>
|
||||
<value>The assembly path to use. Required.</value>
|
||||
</data>
|
||||
<data name="MissingOption" xml:space="preserve">
|
||||
<value>Missing required option '--{0}'.</value>
|
||||
</data>
|
||||
<data name="NoColorDescription" xml:space="preserve">
|
||||
<value>Do not colorize output.</value>
|
||||
<value>Do not colorize console output.</value>
|
||||
</data>
|
||||
<data name="OutputDescription" xml:space="preserve">
|
||||
<value>The file to write the result to.</value>
|
||||
<value>The directory where the document files should be written. Required.</value>
|
||||
</data>
|
||||
<data name="PrefixDescription" xml:space="preserve">
|
||||
<value>Prefix console output with logging level.</value>
|
||||
</data>
|
||||
<data name="VerboseDescription" xml:space="preserve">
|
||||
<value>Show verbose output.</value>
|
||||
<value>Show verbose console output.</value>
|
||||
</data>
|
||||
<data name="ToolsDirectoryDescription" xml:space="preserve">
|
||||
<value>Location from which inside man was copied (in the .NET Framework case) or loaded.</value>
|
||||
<value>Location from which inside man was copied (in the .NET Framework case) or loaded. Required.</value>
|
||||
</data>
|
||||
<data name="MethodDescription" xml:space="preserve">
|
||||
<value>The name of the method to invoke on the '--service' instance. Default value '{0}'.</value>
|
||||
</data>
|
||||
<data name="ServiceDescription" xml:space="preserve">
|
||||
<value>The qualified name of the service type to retrieve from dependency injection. Default value '{0}'.</value>
|
||||
</data>
|
||||
<data name="DocumentDescription" xml:space="preserve">
|
||||
<value>The name of the document to pass to the '--method' method. Default value '{0}'.</value>
|
||||
</data>
|
||||
<data name="UsingDocument" xml:space="preserve">
|
||||
<value>Using document name '{0}'.</value>
|
||||
</data>
|
||||
<data name="UsingMethod" xml:space="preserve">
|
||||
<value>Using method '{0}'.</value>
|
||||
</data>
|
||||
<data name="UsingService" xml:space="preserve">
|
||||
<value>Using service '{0}'.</value>
|
||||
</data>
|
||||
<data name="MethodInvocationFailed" xml:space="preserve">
|
||||
<value>Method '{0}' of service '{1}' failed to generate document '{2}'.</value>
|
||||
<data name="GeneratingDocument" xml:space="preserve">
|
||||
<value>Generating document named '{0}'.</value>
|
||||
</data>
|
||||
<data name="MissingEntryPoint" xml:space="preserve">
|
||||
<value>Assembly '{0}' does not contain an entry point.</value>
|
||||
|
|
@ -166,18 +148,42 @@
|
|||
<value>Unable to find service type '{0}' in loaded assemblies.</value>
|
||||
</data>
|
||||
<data name="MethodNotFound" xml:space="preserve">
|
||||
<value>Unable to find method named '{0}' in '{1}' implementation.</value>
|
||||
<value>Method '{0}' not found in type '{1}' with expected signature.</value>
|
||||
</data>
|
||||
<data name="ServiceNotFound" xml:space="preserve">
|
||||
<value>Unable to find service of type '{0}' in dependency injection container.</value>
|
||||
<value>Unable to find service type '{0}' in dependency injection container.</value>
|
||||
</data>
|
||||
<data name="MethodReturnedNull" xml:space="preserve">
|
||||
<value>Method '{0}' of service '{1}' returned null. Must return a non-null '{2}'.</value>
|
||||
<value>Method '{0}' of type '{1}' returned null. Must return a non-null '{2}'.</value>
|
||||
</data>
|
||||
<data name="MethodReturnTypeUnsupported" xml:space="preserve">
|
||||
<value>Method '{0}' of service '{1}' has unsupported return type '{2}'. Must return a '{3}'.</value>
|
||||
<value>Method '{0}' of type '{1}' has unsupported return type '{2}'. Must return '{3}'.</value>
|
||||
</data>
|
||||
<data name="MethodTimedOut" xml:space="preserve">
|
||||
<value>Method '{0}' of service '{1}' timed out. Must complete execution within {2} minute.</value>
|
||||
<value>Method '{0}' of type '{1}' timed out. Must complete execution within {2} minute.</value>
|
||||
</data>
|
||||
<data name="MethodIsStatic" xml:space="preserve">
|
||||
<value>Method '{0}' of type '{1}' is static. Must be an instance method.</value>
|
||||
</data>
|
||||
<data name="MethodsNotFound" xml:space="preserve">
|
||||
<value>No method '{0}', '{1}' or '{2}' found in type '{3}' with expected signatures.</value>
|
||||
</data>
|
||||
<data name="WritingDocument" xml:space="preserve">
|
||||
<value>Writing document named '{0}' to '{1}'.</value>
|
||||
</data>
|
||||
<data name="MethodWroteNoContent" xml:space="preserve">
|
||||
<value>Method '{0}' of type '{1}' wrote no content for document named '{2}'.</value>
|
||||
</data>
|
||||
<data name="CommandFullName" xml:space="preserve">
|
||||
<value>GetDocument.Insider</value>
|
||||
</data>
|
||||
<data name="FileListDescription" xml:space="preserve">
|
||||
<value>The path where the list of document files should be written. Required.</value>
|
||||
</data>
|
||||
<data name="ProjectDescription" xml:space="preserve">
|
||||
<value>The project name to use. Required.</value>
|
||||
</data>
|
||||
<data name="ServiceProviderNotFound" xml:space="preserve">
|
||||
<value>Unable to resolve a non-null '{0}' implementation using method '{1}', '{2}' or '{3}' of type '{4}'.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"applyPatches": true,
|
||||
"rollForwardOnNoCandidateFx": 2
|
||||
}
|
||||
|
|
@ -16,155 +16,123 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
{
|
||||
private const string InsideManName = "GetDocument.Insider";
|
||||
|
||||
private readonly ProjectOptions _projectOptions = new ProjectOptions();
|
||||
private IList<string> _args;
|
||||
private CommandOption _configuration;
|
||||
private CommandOption _output;
|
||||
private CommandOption _project;
|
||||
private CommandOption _projectExtensionsPath;
|
||||
private CommandOption _runtime;
|
||||
private CommandOption _targetFramework;
|
||||
|
||||
public override void Configure(CommandLineApplication command)
|
||||
{
|
||||
var options = new ProjectOptions();
|
||||
options.Configure(command);
|
||||
|
||||
_configuration = options.Configuration;
|
||||
_project = options.Project;
|
||||
_projectExtensionsPath = options.ProjectExtensionsPath;
|
||||
_runtime = options.Runtime;
|
||||
_targetFramework = options.TargetFramework;
|
||||
|
||||
_output = command.Option("--output <Path>", Resources.OutputDescription);
|
||||
command.VersionOption("--version", ProductInfo.GetVersion);
|
||||
_args = command.RemainingArguments;
|
||||
|
||||
base.Configure(command);
|
||||
|
||||
_projectOptions.Configure(command);
|
||||
_args = command.RemainingArguments;
|
||||
}
|
||||
|
||||
protected override void Validate()
|
||||
{
|
||||
base.Validate();
|
||||
_projectOptions.Validate();
|
||||
}
|
||||
|
||||
protected override int Execute()
|
||||
{
|
||||
var projectFile = FindProjects(
|
||||
_project.Value(),
|
||||
Resources.NoProject,
|
||||
Resources.MultipleProjects);
|
||||
Reporter.WriteVerbose(Resources.FormatUsingProject(projectFile));
|
||||
|
||||
var project = Project.FromFile(
|
||||
projectFile,
|
||||
_projectExtensionsPath.Value(),
|
||||
_targetFramework.Value(),
|
||||
_configuration.Value(),
|
||||
_runtime.Value());
|
||||
if (!File.Exists(project.TargetPath))
|
||||
{
|
||||
throw new CommandException(Resources.MustBuild);
|
||||
}
|
||||
|
||||
var thisPath = Path.GetFullPath(Path.GetDirectoryName(typeof(InvokeCommand).Assembly.Location));
|
||||
|
||||
var projectName = _projectOptions.ProjectName.Value();
|
||||
var assemblyPath = _projectOptions.AssemblyPath.Value();
|
||||
var targetDirectory = Path.GetDirectoryName(assemblyPath);
|
||||
|
||||
string executable = null;
|
||||
var cleanupExecutable = false;
|
||||
try
|
||||
{
|
||||
string toolsDirectory;
|
||||
var args = new List<string>();
|
||||
var targetFramework = new FrameworkName(project.TargetFrameworkMoniker);
|
||||
var targetFramework = new FrameworkName(_projectOptions.TargetFramework.Value());
|
||||
switch (targetFramework.Identifier)
|
||||
{
|
||||
case ".NETFramework":
|
||||
cleanupExecutable = true;
|
||||
executable = Path.Combine(project.OutputPath, InsideManName + ".exe");
|
||||
toolsDirectory = Path.Combine(
|
||||
thisPath,
|
||||
project.PlatformTarget == "x86" ? "net461-x86" : "net461");
|
||||
_projectOptions.Platform.Value() == "x86" ? "net461-x86" : "net461");
|
||||
|
||||
var executableSource = Path.Combine(toolsDirectory, InsideManName + ".exe");
|
||||
executable = Path.Combine(targetDirectory, InsideManName + ".exe");
|
||||
File.Copy(executableSource, executable, overwrite: true);
|
||||
|
||||
if (!string.IsNullOrEmpty(project.ConfigPath))
|
||||
var configPath = assemblyPath + ".config";
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
File.Copy(project.ConfigPath, executable + ".config", overwrite: true);
|
||||
File.Copy(configPath, executable + ".config", overwrite: true);
|
||||
}
|
||||
break;
|
||||
|
||||
case ".NETCoreApp":
|
||||
executable = "dotnet";
|
||||
toolsDirectory = Path.Combine(thisPath, "netcoreapp2.0");
|
||||
|
||||
if (targetFramework.Version < new Version(2, 0))
|
||||
if (targetFramework.Version < new Version(2, 1))
|
||||
{
|
||||
throw new CommandException(
|
||||
Resources.FormatNETCoreApp1Project(project.ProjectName, targetFramework.Version));
|
||||
throw new CommandException(Resources.FormatOldNETCoreAppProject(
|
||||
projectName,
|
||||
targetFramework.Version));
|
||||
}
|
||||
|
||||
executable = "dotnet";
|
||||
toolsDirectory = Path.Combine(thisPath, "netcoreapp2.1");
|
||||
|
||||
args.Add("exec");
|
||||
args.Add("--depsFile");
|
||||
args.Add(project.ProjectDepsFilePath);
|
||||
args.Add(Path.ChangeExtension(assemblyPath, ".deps.json"));
|
||||
|
||||
if (!string.IsNullOrEmpty(project.ProjectAssetsFile))
|
||||
var projectAssetsFile = _projectOptions.AssetsFile.Value();
|
||||
if (!string.IsNullOrEmpty(projectAssetsFile) && File.Exists(projectAssetsFile))
|
||||
{
|
||||
using (var reader = new JsonTextReader(File.OpenText(project.ProjectAssetsFile)))
|
||||
{
|
||||
var projectAssets = JToken.ReadFrom(reader);
|
||||
var packageFolders = projectAssets["packageFolders"]
|
||||
.Children<JProperty>()
|
||||
.Select(p => p.Name);
|
||||
using var reader = new JsonTextReader(File.OpenText(projectAssetsFile));
|
||||
var projectAssets = JToken.ReadFrom(reader);
|
||||
var packageFolders = projectAssets["packageFolders"]
|
||||
.Children<JProperty>()
|
||||
.Select(p => p.Name);
|
||||
|
||||
foreach (var packageFolder in packageFolders)
|
||||
{
|
||||
args.Add("--additionalProbingPath");
|
||||
args.Add(packageFolder.TrimEnd(Path.DirectorySeparatorChar));
|
||||
}
|
||||
foreach (var packageFolder in packageFolders)
|
||||
{
|
||||
args.Add("--additionalProbingPath");
|
||||
args.Add(packageFolder.TrimEnd(Path.DirectorySeparatorChar));
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(project.ProjectRuntimeConfigFilePath))
|
||||
var runtimeConfigPath = Path.ChangeExtension(assemblyPath, ".runtimeconfig.json");
|
||||
if (File.Exists(runtimeConfigPath))
|
||||
{
|
||||
args.Add("--runtimeConfig");
|
||||
args.Add(project.ProjectRuntimeConfigFilePath);
|
||||
args.Add(runtimeConfigPath);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(project.RuntimeFrameworkVersion))
|
||||
else
|
||||
{
|
||||
args.Add("--fx-version");
|
||||
args.Add(project.RuntimeFrameworkVersion);
|
||||
var runtimeFrameworkVersion = _projectOptions.RuntimeFrameworkVersion.Value();
|
||||
if (!string.IsNullOrEmpty(runtimeFrameworkVersion))
|
||||
{
|
||||
args.Add("--fx-version");
|
||||
args.Add(runtimeFrameworkVersion);
|
||||
}
|
||||
}
|
||||
|
||||
args.Add(Path.Combine(toolsDirectory, InsideManName + ".dll"));
|
||||
break;
|
||||
|
||||
case ".NETStandard":
|
||||
throw new CommandException(Resources.FormatNETStandardProject(project.ProjectName));
|
||||
throw new CommandException(Resources.FormatNETStandardProject(projectName));
|
||||
|
||||
default:
|
||||
throw new CommandException(
|
||||
Resources.FormatUnsupportedFramework(project.ProjectName, targetFramework.Identifier));
|
||||
Resources.FormatUnsupportedFramework(projectName, targetFramework.Identifier));
|
||||
}
|
||||
|
||||
args.AddRange(_args);
|
||||
args.Add("--assembly");
|
||||
args.Add(project.TargetPath);
|
||||
args.Add(assemblyPath);
|
||||
args.Add("--project");
|
||||
args.Add(projectName);
|
||||
args.Add("--tools-directory");
|
||||
args.Add(toolsDirectory);
|
||||
|
||||
if (!(args.Contains("--method") || string.IsNullOrEmpty(project.DefaultMethod)))
|
||||
{
|
||||
args.Add("--method");
|
||||
args.Add(project.DefaultMethod);
|
||||
}
|
||||
|
||||
if (!(args.Contains("--service") || string.IsNullOrEmpty(project.DefaultService)))
|
||||
{
|
||||
args.Add("--service");
|
||||
args.Add(project.DefaultService);
|
||||
}
|
||||
|
||||
if (_output.HasValue())
|
||||
{
|
||||
args.Add("--output");
|
||||
args.Add(Path.GetFullPath(_output.Value()));
|
||||
}
|
||||
|
||||
if (Reporter.IsVerbose)
|
||||
{
|
||||
args.Add("--verbose");
|
||||
|
|
@ -180,7 +148,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
args.Add("--prefix-output");
|
||||
}
|
||||
|
||||
return Exe.Run(executable, args, project.ProjectDirectory);
|
||||
return Exe.Run(executable, args);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -205,44 +173,5 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string FindProjects(
|
||||
string path,
|
||||
string errorWhenNoProject,
|
||||
string errorWhenMultipleProjects)
|
||||
{
|
||||
var specified = true;
|
||||
if (path == null)
|
||||
{
|
||||
specified = false;
|
||||
path = Directory.GetCurrentDirectory();
|
||||
}
|
||||
else if (!Directory.Exists(path)) // It's not a directory
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
var projectFiles = Directory
|
||||
.EnumerateFiles(path, "*.*proj", SearchOption.TopDirectoryOnly)
|
||||
.Where(f => !string.Equals(Path.GetExtension(f), ".xproj", StringComparison.OrdinalIgnoreCase))
|
||||
.Take(2)
|
||||
.ToList();
|
||||
if (projectFiles.Count == 0)
|
||||
{
|
||||
throw new CommandException(
|
||||
specified
|
||||
? Resources.FormatNoProjectInDirectory(path)
|
||||
: errorWhenNoProject);
|
||||
}
|
||||
if (projectFiles.Count != 1)
|
||||
{
|
||||
throw new CommandException(
|
||||
specified
|
||||
? Resources.FormatMultipleProjectsInDirectory(path)
|
||||
: errorWhenMultipleProjects);
|
||||
}
|
||||
|
||||
return projectFiles[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,37 +79,37 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
|
||||
builder.Append("\"");
|
||||
|
||||
var pendingBackslashs = 0;
|
||||
var pendingBackslashes = 0;
|
||||
for (var j = 0; j < args[i].Length; j++)
|
||||
{
|
||||
switch (args[i][j])
|
||||
{
|
||||
case '\"':
|
||||
if (pendingBackslashs != 0)
|
||||
if (pendingBackslashes != 0)
|
||||
{
|
||||
builder.Append('\\', pendingBackslashs * 2);
|
||||
pendingBackslashs = 0;
|
||||
builder.Append('\\', pendingBackslashes * 2);
|
||||
pendingBackslashes = 0;
|
||||
}
|
||||
builder.Append("\\\"");
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
pendingBackslashs++;
|
||||
pendingBackslashes++;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (pendingBackslashs != 0)
|
||||
if (pendingBackslashes != 0)
|
||||
{
|
||||
if (pendingBackslashs == 1)
|
||||
if (pendingBackslashes == 1)
|
||||
{
|
||||
builder.Append("\\");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append('\\', pendingBackslashs * 2);
|
||||
builder.Append('\\', pendingBackslashes * 2);
|
||||
}
|
||||
|
||||
pendingBackslashs = 0;
|
||||
pendingBackslashes = 0;
|
||||
}
|
||||
|
||||
builder.Append(args[i][j]);
|
||||
|
|
@ -117,9 +117,9 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
}
|
||||
|
||||
if (pendingBackslashs != 0)
|
||||
if (pendingBackslashes != 0)
|
||||
{
|
||||
builder.Append('\\', pendingBackslashs * 2);
|
||||
builder.Append('\\', pendingBackslashes * 2);
|
||||
}
|
||||
|
||||
builder.Append("\"");
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
var app = new CommandLineApplication(throwOnUnexpectedArg: false)
|
||||
{
|
||||
FullName = Resources.CommandFullName,
|
||||
Name = Resources.CommandFullName,
|
||||
};
|
||||
|
||||
new InvokeCommand().Configure(app);
|
||||
|
|
|
|||
|
|
@ -1,252 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using IODirectory = System.IO.Directory;
|
||||
|
||||
namespace Microsoft.Extensions.ApiDescription.Tool
|
||||
{
|
||||
internal class Project
|
||||
{
|
||||
private const string ResourceFilename = "ServiceProjectReferenceMetadata.targets";
|
||||
private const string MSBuildResourceName = "Microsoft.Extensions.ApiDescription.Tool." + ResourceFilename;
|
||||
|
||||
private Project()
|
||||
{
|
||||
}
|
||||
|
||||
public string AssemblyName { get; private set; }
|
||||
|
||||
public string ConfigPath { get; private set; }
|
||||
|
||||
public string Configuration { get; private set; }
|
||||
|
||||
public string DefaultDocumentName { get; private set; }
|
||||
|
||||
public string DefaultMethod { get; private set; }
|
||||
|
||||
public string DefaultService { get; private set; }
|
||||
|
||||
public string OutputPath { get; private set; }
|
||||
|
||||
public string Platform { get; private set; }
|
||||
|
||||
public string PlatformTarget { get; private set; }
|
||||
|
||||
public string ProjectAssetsFile { get; private set; }
|
||||
|
||||
public string ProjectDepsFilePath { get; private set; }
|
||||
|
||||
public string ProjectDirectory { get; private set; }
|
||||
|
||||
public string ProjectExtensionsPath { get; private set; }
|
||||
|
||||
public string ProjectName { get; private set; }
|
||||
|
||||
public string ProjectRuntimeConfigFilePath { get; private set; }
|
||||
|
||||
public string RuntimeFrameworkVersion { get; private set; }
|
||||
|
||||
public string RuntimeIdentifier { get; private set; }
|
||||
|
||||
public string TargetFramework { get; private set; }
|
||||
|
||||
public string TargetFrameworkMoniker { get; private set; }
|
||||
|
||||
public string TargetPath { get; private set; }
|
||||
|
||||
public static Project FromFile(
|
||||
string projectFile,
|
||||
string buildExtensionsDirectory,
|
||||
string framework = null,
|
||||
string configuration = null,
|
||||
string runtime = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(projectFile))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectFile));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(buildExtensionsDirectory))
|
||||
{
|
||||
buildExtensionsDirectory = Path.Combine(Path.GetDirectoryName(projectFile), "obj");
|
||||
}
|
||||
|
||||
IODirectory.CreateDirectory(buildExtensionsDirectory);
|
||||
|
||||
var assembly = typeof(Project).Assembly;
|
||||
var targetsPath = Path.Combine(
|
||||
buildExtensionsDirectory,
|
||||
$"{Path.GetFileName(projectFile)}.{ResourceFilename}");
|
||||
using (var input = assembly.GetManifestResourceStream(MSBuildResourceName))
|
||||
{
|
||||
using (var output = File.OpenWrite(targetsPath))
|
||||
{
|
||||
// NB: Copy always in case it changes
|
||||
Reporter.WriteVerbose(Resources.FormatWritingFile(targetsPath));
|
||||
input.CopyTo(output);
|
||||
|
||||
output.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
IDictionary<string, string> metadata;
|
||||
var metadataPath = Path.GetTempFileName();
|
||||
try
|
||||
{
|
||||
var args = new List<string>
|
||||
{
|
||||
"msbuild",
|
||||
"/target:WriteServiceProjectReferenceMetadata",
|
||||
"/verbosity:quiet",
|
||||
"/nologo",
|
||||
"/nodeReuse:false",
|
||||
$"/property:ServiceProjectReferenceMetadataPath={metadataPath}",
|
||||
projectFile,
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(framework))
|
||||
{
|
||||
args.Add($"/property:TargetFramework={framework}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(configuration))
|
||||
{
|
||||
args.Add($"/property:Configuration={configuration}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(runtime))
|
||||
{
|
||||
args.Add($"/property:RuntimeIdentifier={runtime}");
|
||||
}
|
||||
|
||||
var exitCode = Exe.Run("dotnet", args);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
throw new CommandException(Resources.GetMetadataFailed);
|
||||
}
|
||||
|
||||
metadata = File
|
||||
.ReadLines(metadataPath)
|
||||
.Select(l => l.Split(new[] { ':' }, 2))
|
||||
.ToDictionary(s => s[0], s => s[1].TrimStart());
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ignore errors about in-use files. Should still be marked for delete after process cleanup.
|
||||
try
|
||||
{
|
||||
File.Delete(metadataPath);
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(targetsPath);
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
var project = new Project
|
||||
{
|
||||
DefaultDocumentName = metadata[nameof(DefaultDocumentName)],
|
||||
DefaultMethod = metadata[nameof(DefaultMethod)],
|
||||
DefaultService = metadata[nameof(DefaultService)],
|
||||
|
||||
AssemblyName = metadata[nameof(AssemblyName)],
|
||||
Configuration = metadata[nameof(Configuration)],
|
||||
OutputPath = metadata[nameof(OutputPath)],
|
||||
Platform = metadata[nameof(Platform)],
|
||||
PlatformTarget = metadata[nameof(PlatformTarget)] ?? metadata[nameof(Platform)],
|
||||
ProjectAssetsFile = metadata[nameof(ProjectAssetsFile)],
|
||||
ProjectDepsFilePath = metadata[nameof(ProjectDepsFilePath)],
|
||||
ProjectDirectory = metadata[nameof(ProjectDirectory)],
|
||||
ProjectExtensionsPath = metadata[nameof(ProjectExtensionsPath)],
|
||||
ProjectName = metadata[nameof(ProjectName)],
|
||||
ProjectRuntimeConfigFilePath = metadata[nameof(ProjectRuntimeConfigFilePath)],
|
||||
RuntimeFrameworkVersion = metadata[nameof(RuntimeFrameworkVersion)],
|
||||
RuntimeIdentifier = metadata[nameof(RuntimeIdentifier)],
|
||||
TargetFramework = metadata[nameof(TargetFramework)],
|
||||
TargetFrameworkMoniker = metadata[nameof(TargetFrameworkMoniker)],
|
||||
TargetPath = metadata[nameof(TargetPath)],
|
||||
};
|
||||
|
||||
if (string.IsNullOrEmpty(project.OutputPath))
|
||||
{
|
||||
throw new CommandException(
|
||||
Resources.FormatGetMetadataValueFailed(nameof(OutputPath), nameof(OutputPath)));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(project.ProjectDirectory))
|
||||
{
|
||||
throw new CommandException(
|
||||
Resources.FormatGetMetadataValueFailed(nameof(ProjectDirectory), "MSBuildProjectDirectory"));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(project.TargetPath))
|
||||
{
|
||||
throw new CommandException(
|
||||
Resources.FormatGetMetadataValueFailed(nameof(TargetPath), nameof(TargetPath)));
|
||||
}
|
||||
|
||||
if (!Path.IsPathRooted(project.ProjectDirectory))
|
||||
{
|
||||
project.OutputPath = Path.GetFullPath(
|
||||
Path.Combine(IODirectory.GetCurrentDirectory(), project.ProjectDirectory));
|
||||
}
|
||||
|
||||
if (!Path.IsPathRooted(project.OutputPath))
|
||||
{
|
||||
project.OutputPath = Path.GetFullPath(Path.Combine(project.ProjectDirectory, project.OutputPath));
|
||||
}
|
||||
|
||||
if (!Path.IsPathRooted(project.ProjectExtensionsPath))
|
||||
{
|
||||
project.ProjectExtensionsPath = Path.GetFullPath(
|
||||
Path.Combine(project.ProjectDirectory, project.ProjectExtensionsPath));
|
||||
}
|
||||
|
||||
if (!Path.IsPathRooted(project.TargetPath))
|
||||
{
|
||||
project.TargetPath = Path.GetFullPath(Path.Combine(project.OutputPath, project.TargetPath));
|
||||
}
|
||||
|
||||
// Some document generation tools support non-ASP.NET Core projects. Any of the remaining properties may
|
||||
// thus be null empty.
|
||||
var configPath = $"{project.TargetPath}.config";
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
project.ConfigPath = configPath;
|
||||
}
|
||||
|
||||
if (!(string.IsNullOrEmpty(project.ProjectAssetsFile) || Path.IsPathRooted(project.ProjectAssetsFile)))
|
||||
{
|
||||
project.ProjectAssetsFile = Path.GetFullPath(
|
||||
Path.Combine(project.ProjectDirectory, project.ProjectAssetsFile));
|
||||
}
|
||||
|
||||
if (!(string.IsNullOrEmpty(project.ProjectDepsFilePath) || Path.IsPathRooted(project.ProjectDepsFilePath)))
|
||||
{
|
||||
project.ProjectDepsFilePath = Path.GetFullPath(
|
||||
Path.Combine(project.ProjectDirectory, project.ProjectDepsFilePath));
|
||||
}
|
||||
|
||||
if (!(string.IsNullOrEmpty(project.ProjectRuntimeConfigFilePath) ||
|
||||
Path.IsPathRooted(project.ProjectRuntimeConfigFilePath)))
|
||||
{
|
||||
project.ProjectRuntimeConfigFilePath = Path.GetFullPath(
|
||||
Path.Combine(project.OutputPath, project.ProjectRuntimeConfigFilePath));
|
||||
}
|
||||
|
||||
return project;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,25 +7,44 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
{
|
||||
internal class ProjectOptions
|
||||
{
|
||||
public CommandOption Configuration { get; private set; }
|
||||
public CommandOption AssemblyPath { get; private set; }
|
||||
|
||||
public CommandOption Project { get; private set; }
|
||||
public CommandOption AssetsFile { get; private set; }
|
||||
|
||||
public CommandOption ProjectExtensionsPath { get; private set; }
|
||||
public CommandOption Platform { get; private set; }
|
||||
|
||||
public CommandOption Runtime { get; private set; }
|
||||
public CommandOption ProjectName { get; private set; }
|
||||
|
||||
public CommandOption RuntimeFrameworkVersion { get; private set; }
|
||||
|
||||
public CommandOption TargetFramework { get; private set; }
|
||||
|
||||
public void Configure(CommandLineApplication command)
|
||||
{
|
||||
Configuration = command.Option("--configuration <CONFIGURATION>", Resources.ConfigurationDescription);
|
||||
Project = command.Option("-p|--project <PROJECT>", Resources.ProjectDescription);
|
||||
ProjectExtensionsPath = command.Option(
|
||||
"--projectExtensionsPath <PATH>",
|
||||
Resources.ProjectExtensionsPathDescription);
|
||||
Runtime = command.Option("--runtime <RUNTIME_IDENTIFIER>", Resources.RuntimeDescription);
|
||||
AssemblyPath = command.Option("--assembly <Path>", Resources.AssemblyDescription);
|
||||
AssetsFile = command.Option("--assets-file <Path>", Resources.AssetsFileDescription);
|
||||
TargetFramework = command.Option("--framework <FRAMEWORK>", Resources.TargetFrameworkDescription);
|
||||
Platform = command.Option("--platform <Target>", Resources.PlatformDescription);
|
||||
ProjectName = command.Option("--project <Name>", Resources.ProjectDescription);
|
||||
RuntimeFrameworkVersion = command.Option("--runtime <RUNTIME_IDENTIFIER>", Resources.RuntimeDescription);
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
if (!AssemblyPath.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(AssemblyPath.LongName));
|
||||
}
|
||||
|
||||
if (!ProjectName.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(ProjectName.LongName));
|
||||
}
|
||||
|
||||
if (!TargetFramework.HasValue())
|
||||
{
|
||||
throw new CommandException(Resources.FormatMissingOption(TargetFramework.LongName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,20 +10,6 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.Extensions.ApiDescription.Tool.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// The configuration to use.
|
||||
/// </summary>
|
||||
internal static string ConfigurationDescription
|
||||
{
|
||||
get => GetString("ConfigurationDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The configuration to use.
|
||||
/// </summary>
|
||||
internal static string FormatConfigurationDescription()
|
||||
=> GetString("ConfigurationDescription");
|
||||
|
||||
/// <summary>
|
||||
/// dotnet-getdocument
|
||||
/// </summary>
|
||||
|
|
@ -39,7 +25,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
=> GetString("CommandFullName");
|
||||
|
||||
/// <summary>
|
||||
/// The target framework.
|
||||
/// The target framework to use. Required.
|
||||
/// </summary>
|
||||
internal static string TargetFrameworkDescription
|
||||
{
|
||||
|
|
@ -47,69 +33,27 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The target framework.
|
||||
/// The target framework to use. Required.
|
||||
/// </summary>
|
||||
internal static string FormatTargetFrameworkDescription()
|
||||
=> GetString("TargetFrameworkDescription");
|
||||
|
||||
/// <summary>
|
||||
/// Unable to retrieve project metadata. If you are using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, use the --projectExtensionsPath option.
|
||||
/// Project '{0}' targets framework '.NETCoreApp' version '{1}'. This version of the dotnet-getdocument tool only supports version 2.1 or higher.
|
||||
/// </summary>
|
||||
internal static string GetMetadataFailed
|
||||
internal static string OldNETCoreAppProject
|
||||
{
|
||||
get => GetString("GetMetadataFailed");
|
||||
get => GetString("OldNETCoreAppProject");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unable to retrieve project metadata. If you are using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, use the --projectExtensionsPath option.
|
||||
/// Project '{0}' targets framework '.NETCoreApp' version '{1}'. This version of the dotnet-getdocument tool only supports version 2.1 or higher.
|
||||
/// </summary>
|
||||
internal static string FormatGetMetadataFailed()
|
||||
=> GetString("GetMetadataFailed");
|
||||
internal static string FormatOldNETCoreAppProject(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("OldNETCoreAppProject"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// More than one project was found in the current working directory. Use the --project option.
|
||||
/// </summary>
|
||||
internal static string MultipleProjects
|
||||
{
|
||||
get => GetString("MultipleProjects");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// More than one project was found in the current working directory. Use the --project option.
|
||||
/// </summary>
|
||||
internal static string FormatMultipleProjects()
|
||||
=> GetString("MultipleProjects");
|
||||
|
||||
/// <summary>
|
||||
/// More than one project was found in directory '{0}'. Specify one using its file name.
|
||||
/// </summary>
|
||||
internal static string MultipleProjectsInDirectory
|
||||
{
|
||||
get => GetString("MultipleProjectsInDirectory");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// More than one project was found in directory '{0}'. Specify one using its file name.
|
||||
/// </summary>
|
||||
internal static string FormatMultipleProjectsInDirectory(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MultipleProjectsInDirectory"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Project '{0}' targets framework '.NETCoreApp' version '{1}'. This version of the dotnet-getdocument tool only supports version 2.0 or higher.
|
||||
/// </summary>
|
||||
internal static string NETCoreApp1Project
|
||||
{
|
||||
get => GetString("NETCoreApp1Project");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Project '{0}' targets framework '.NETCoreApp' version '{1}'. This version of the dotnet-getdocument tool only supports version 2.0 or higher.
|
||||
/// </summary>
|
||||
internal static string FormatNETCoreApp1Project(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("NETCoreApp1Project"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// Project '{0}' targets framework '.NETStandard'. There is no runtime associated with this framework, and projects targeting it cannot be executed directly. To use the dotnet-getdocument tool with this project, add an executable project targeting .NET Core or .NET Framework that references this project and specify it using the --project option; or, update this project to target .NET Core and / or .NET Framework.
|
||||
/// Project '{0}' targets framework '.NETStandard'. There is no runtime associated with this framework and projects targeting it cannot be executed directly. To use the dotnet-getdocument tool with this project, update this project to target .NET Core and / or .NET Framework.
|
||||
/// </summary>
|
||||
internal static string NETStandardProject
|
||||
{
|
||||
|
|
@ -117,13 +61,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Project '{0}' targets framework '.NETStandard'. There is no runtime associated with this framework, and projects targeting it cannot be executed directly. To use the dotnet-getdocument tool with this project, add an executable project targeting .NET Core or .NET Framework that references this project and specify it using the --project option; or, update this project to target .NET Core and / or .NET Framework.
|
||||
/// Project '{0}' targets framework '.NETStandard'. There is no runtime associated with this framework and projects targeting it cannot be executed directly. To use the dotnet-getdocument tool with this project, update this project to target .NET Core and / or .NET Framework.
|
||||
/// </summary>
|
||||
internal static string FormatNETStandardProject(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("NETStandardProject"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Do not colorize output.
|
||||
/// Do not colorize console output.
|
||||
/// </summary>
|
||||
internal static string NoColorDescription
|
||||
{
|
||||
|
|
@ -131,41 +75,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do not colorize output.
|
||||
/// Do not colorize console output.
|
||||
/// </summary>
|
||||
internal static string FormatNoColorDescription()
|
||||
=> GetString("NoColorDescription");
|
||||
|
||||
/// <summary>
|
||||
/// No project was found. Change the current working directory or use the --project option.
|
||||
/// </summary>
|
||||
internal static string NoProject
|
||||
{
|
||||
get => GetString("NoProject");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No project was found. Change the current working directory or use the --project option.
|
||||
/// </summary>
|
||||
internal static string FormatNoProject()
|
||||
=> GetString("NoProject");
|
||||
|
||||
/// <summary>
|
||||
/// No project was found in directory '{0}'.
|
||||
/// </summary>
|
||||
internal static string NoProjectInDirectory
|
||||
{
|
||||
get => GetString("NoProjectInDirectory");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No project was found in directory '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatNoProjectInDirectory(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("NoProjectInDirectory"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Prefix output with level.
|
||||
/// Prefix console output with logging level.
|
||||
/// </summary>
|
||||
internal static string PrefixDescription
|
||||
{
|
||||
|
|
@ -173,13 +89,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prefix output with level.
|
||||
/// Prefix console output with logging level.
|
||||
/// </summary>
|
||||
internal static string FormatPrefixDescription()
|
||||
=> GetString("PrefixDescription");
|
||||
|
||||
/// <summary>
|
||||
/// The project to use.
|
||||
/// The project name. Required.
|
||||
/// </summary>
|
||||
internal static string ProjectDescription
|
||||
{
|
||||
|
|
@ -187,25 +103,11 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The project to use.
|
||||
/// The project name. Required.
|
||||
/// </summary>
|
||||
internal static string FormatProjectDescription()
|
||||
=> GetString("ProjectDescription");
|
||||
|
||||
/// <summary>
|
||||
/// The MSBuild project extensions path. Defaults to "obj".
|
||||
/// </summary>
|
||||
internal static string ProjectExtensionsPathDescription
|
||||
{
|
||||
get => GetString("ProjectExtensionsPathDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The MSBuild project extensions path. Defaults to "obj".
|
||||
/// </summary>
|
||||
internal static string FormatProjectExtensionsPathDescription()
|
||||
=> GetString("ProjectExtensionsPathDescription");
|
||||
|
||||
/// <summary>
|
||||
/// The runtime identifier to use.
|
||||
/// </summary>
|
||||
|
|
@ -234,20 +136,6 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
internal static string FormatUnsupportedFramework(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("UnsupportedFramework"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// Using project '{0}'.
|
||||
/// </summary>
|
||||
internal static string UsingProject
|
||||
{
|
||||
get => GetString("UsingProject");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Using project '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatUsingProject(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("UsingProject"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Show verbose output.
|
||||
/// </summary>
|
||||
|
|
@ -263,60 +151,60 @@ namespace Microsoft.Extensions.ApiDescription.Tool
|
|||
=> GetString("VerboseDescription");
|
||||
|
||||
/// <summary>
|
||||
/// Writing '{0}'...
|
||||
/// The project assets file to use.
|
||||
/// </summary>
|
||||
internal static string WritingFile
|
||||
internal static string AssetsFileDescription
|
||||
{
|
||||
get => GetString("WritingFile");
|
||||
get => GetString("AssetsFileDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writing '{0}'...
|
||||
/// The project assets file to use.
|
||||
/// </summary>
|
||||
internal static string FormatWritingFile(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("WritingFile"), p0);
|
||||
internal static string FormatAssetsFileDescription()
|
||||
=> GetString("AssetsFileDescription");
|
||||
|
||||
/// <summary>
|
||||
/// Project output not found. Project must be up-to-date when using this tool.
|
||||
/// Missing required option '--{0}'.
|
||||
/// </summary>
|
||||
internal static string MustBuild
|
||||
internal static string MissingOption
|
||||
{
|
||||
get => GetString("MustBuild");
|
||||
get => GetString("MissingOption");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Project output not found. Project must be up-to-date when using this tool.
|
||||
/// Missing required option '--{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatMustBuild()
|
||||
=> GetString("MustBuild");
|
||||
internal static string FormatMissingOption(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MissingOption"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// The file to write the result to.
|
||||
/// The platform to use.
|
||||
/// </summary>
|
||||
internal static string OutputDescription
|
||||
internal static string PlatformDescription
|
||||
{
|
||||
get => GetString("OutputDescription");
|
||||
get => GetString("PlatformDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The file to write the result to.
|
||||
/// The platform to use.
|
||||
/// </summary>
|
||||
internal static string FormatOutputDescription()
|
||||
=> GetString("OutputDescription");
|
||||
internal static string FormatPlatformDescription()
|
||||
=> GetString("PlatformDescription");
|
||||
|
||||
/// <summary>
|
||||
/// Unable to retrieve '{0}' project metadata. Ensure '$({1})' is set.
|
||||
/// The assembly path to use. Required.
|
||||
/// </summary>
|
||||
internal static string GetMetadataValueFailed
|
||||
internal static string AssemblyDescription
|
||||
{
|
||||
get => GetString("GetMetadataValueFailed");
|
||||
get => GetString("AssemblyDescription");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unable to retrieve '{0}' project metadata. Ensure '$({1})' is set.
|
||||
/// The assembly path to use. Required.
|
||||
/// </summary>
|
||||
internal static string FormatGetMetadataValueFailed(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("GetMetadataValueFailed"), p0, p1);
|
||||
internal static string FormatAssemblyDescription()
|
||||
=> GetString("AssemblyDescription");
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -117,47 +117,26 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ConfigurationDescription" xml:space="preserve">
|
||||
<value>The configuration to use.</value>
|
||||
</data>
|
||||
<data name="CommandFullName" xml:space="preserve">
|
||||
<value>dotnet-getdocument</value>
|
||||
</data>
|
||||
<data name="TargetFrameworkDescription" xml:space="preserve">
|
||||
<value>The target framework.</value>
|
||||
<value>The target framework to use. Required.</value>
|
||||
</data>
|
||||
<data name="GetMetadataFailed" xml:space="preserve">
|
||||
<value>Unable to retrieve project metadata. If you are using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, use the --projectExtensionsPath option.</value>
|
||||
</data>
|
||||
<data name="MultipleProjects" xml:space="preserve">
|
||||
<value>More than one project was found in the current working directory. Use the --project option.</value>
|
||||
</data>
|
||||
<data name="MultipleProjectsInDirectory" xml:space="preserve">
|
||||
<value>More than one project was found in directory '{0}'. Specify one using its file name.</value>
|
||||
</data>
|
||||
<data name="NETCoreApp1Project" xml:space="preserve">
|
||||
<value>Project '{0}' targets framework '.NETCoreApp' version '{1}'. This version of the dotnet-getdocument tool only supports version 2.0 or higher.</value>
|
||||
<data name="OldNETCoreAppProject" xml:space="preserve">
|
||||
<value>Project '{0}' targets framework '.NETCoreApp' version '{1}'. This version of the dotnet-getdocument tool only supports version 2.1 or higher.</value>
|
||||
</data>
|
||||
<data name="NETStandardProject" xml:space="preserve">
|
||||
<value>Project '{0}' targets framework '.NETStandard'. There is no runtime associated with this framework, and projects targeting it cannot be executed directly. To use the dotnet-getdocument tool with this project, add an executable project targeting .NET Core or .NET Framework that references this project and specify it using the --project option; or, update this project to target .NET Core and / or .NET Framework.</value>
|
||||
<value>Project '{0}' targets framework '.NETStandard'. There is no runtime associated with this framework and projects targeting it cannot be executed directly. To use the dotnet-getdocument tool with this project, update this project to target .NET Core and / or .NET Framework.</value>
|
||||
</data>
|
||||
<data name="NoColorDescription" xml:space="preserve">
|
||||
<value>Do not colorize output.</value>
|
||||
</data>
|
||||
<data name="NoProject" xml:space="preserve">
|
||||
<value>No project was found. Change the current working directory or use the --project option.</value>
|
||||
</data>
|
||||
<data name="NoProjectInDirectory" xml:space="preserve">
|
||||
<value>No project was found in directory '{0}'.</value>
|
||||
<value>Do not colorize console output.</value>
|
||||
</data>
|
||||
<data name="PrefixDescription" xml:space="preserve">
|
||||
<value>Prefix output with level.</value>
|
||||
<value>Prefix console output with logging level.</value>
|
||||
</data>
|
||||
<data name="ProjectDescription" xml:space="preserve">
|
||||
<value>The project to use.</value>
|
||||
</data>
|
||||
<data name="ProjectExtensionsPathDescription" xml:space="preserve">
|
||||
<value>The MSBuild project extensions path. Defaults to "obj".</value>
|
||||
<value>The project name. Required.</value>
|
||||
</data>
|
||||
<data name="RuntimeDescription" xml:space="preserve">
|
||||
<value>The runtime identifier to use.</value>
|
||||
|
|
@ -165,22 +144,19 @@
|
|||
<data name="UnsupportedFramework" xml:space="preserve">
|
||||
<value>Project '{0}' targets framework '{1}'. The dotnet-getdocument tool does not support this framework.</value>
|
||||
</data>
|
||||
<data name="UsingProject" xml:space="preserve">
|
||||
<value>Using project '{0}'.</value>
|
||||
</data>
|
||||
<data name="VerboseDescription" xml:space="preserve">
|
||||
<value>Show verbose output.</value>
|
||||
</data>
|
||||
<data name="WritingFile" xml:space="preserve">
|
||||
<value>Writing '{0}'...</value>
|
||||
<data name="AssetsFileDescription" xml:space="preserve">
|
||||
<value>The project assets file to use.</value>
|
||||
</data>
|
||||
<data name="MustBuild" xml:space="preserve">
|
||||
<value>Project output not found. Project must be up-to-date when using this tool.</value>
|
||||
<data name="MissingOption" xml:space="preserve">
|
||||
<value>Missing required option '--{0}'.</value>
|
||||
</data>
|
||||
<data name="OutputDescription" xml:space="preserve">
|
||||
<value>The file to write the result to.</value>
|
||||
<data name="PlatformDescription" xml:space="preserve">
|
||||
<value>The platform to use.</value>
|
||||
</data>
|
||||
<data name="GetMetadataValueFailed" xml:space="preserve">
|
||||
<value>Unable to retrieve '{0}' project metadata. Ensure '$({1})' is set.</value>
|
||||
<data name="AssemblyDescription" xml:space="preserve">
|
||||
<value>The assembly path to use. Required.</value>
|
||||
</data>
|
||||
</root>
|
||||
</root>
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- Collect properties only in inner build. Execute unconditionally before WriteServiceProjectReferenceMetadata. -->
|
||||
<Target Name="GetServiceProjectReferenceMetadata"
|
||||
BeforeTargets="WriteServiceProjectReferenceMetadata"
|
||||
Condition="'$(TargetFramework)' != ''"
|
||||
Returns="@(ServiceProjectReferenceMetadata)">
|
||||
<ItemGroup Condition="'$(TargetFramework)' != ''">
|
||||
<ServiceProjectReferenceMetadata Include="DefaultDocumentName: $(DefaultServiceProjectDocumentName)" />
|
||||
<ServiceProjectReferenceMetadata Include="DefaultMethod: $(DefaultServiceProjectMethod)" />
|
||||
<ServiceProjectReferenceMetadata Include="DefaultService: $(DefaultServiceProjectService)" />
|
||||
|
||||
<ServiceProjectReferenceMetadata Include="AssemblyName: $(AssemblyName)" />
|
||||
<ServiceProjectReferenceMetadata Include="Configuration: $(Configuration)" />
|
||||
<ServiceProjectReferenceMetadata Include="OutputPath: $(OutputPath)" />
|
||||
<ServiceProjectReferenceMetadata Include="Platform: $(Platform)" />
|
||||
<ServiceProjectReferenceMetadata Include="PlatformTarget: $(PlatformTarget)" />
|
||||
<ServiceProjectReferenceMetadata Include="ProjectAssetsFile: $(ProjectAssetsFile)" />
|
||||
<ServiceProjectReferenceMetadata Include="ProjectDepsFilePath: $(ProjectDepsFilePath)" />
|
||||
<ServiceProjectReferenceMetadata Include="ProjectDirectory: $(MSBuildProjectDirectory)" />
|
||||
<ServiceProjectReferenceMetadata Include="ProjectExtensionsPath: $(MSBuildProjectExtensionsPath)" />
|
||||
<ServiceProjectReferenceMetadata Include="ProjectName: $(MSBuildProjectName)" />
|
||||
<ServiceProjectReferenceMetadata Include="ProjectRuntimeConfigFilePath: $(ProjectRuntimeConfigFilePath)" />
|
||||
<ServiceProjectReferenceMetadata Include="RuntimeFrameworkVersion: $(RuntimeFrameworkVersion)" />
|
||||
<ServiceProjectReferenceMetadata Include="RuntimeIdentifier: $(RuntimeIdentifier)" />
|
||||
<ServiceProjectReferenceMetadata Include="TargetFramework: $(TargetFramework)" />
|
||||
<ServiceProjectReferenceMetadata Include="TargetFrameworkMoniker: $(TargetFrameworkMoniker)" />
|
||||
<ServiceProjectReferenceMetadata Include="TargetPath: $(TargetPath)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!-- Write information only in inner build. -->
|
||||
<Target Name="WriteServiceProjectReferenceMetadata" Returns="@(ServiceProjectReferenceMetadata)">
|
||||
<MSBuild Condition="'$(TargetFramework)' == ''"
|
||||
Projects="$(MSBuildProjectFile)"
|
||||
Targets="WriteServiceProjectReferenceMetadata"
|
||||
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0]);ServiceProjectReferenceMetadataFile=$(ServiceProjectReferenceMetadataFile)" />
|
||||
|
||||
<WriteLinesToFile Condition="'$(TargetFramework)' != ''"
|
||||
File="$(ServiceProjectReferenceMetadataPath)"
|
||||
Lines="@(ServiceProjectReferenceMetadata)" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -22,8 +22,6 @@
|
|||
<Compile Include="../../GetDocumentInsider/src/ProductInfo.cs" />
|
||||
<Compile Include="../../GetDocumentInsider/src/Reporter.cs" />
|
||||
|
||||
<EmbeddedResource Include="ServiceProjectReferenceMetadata.targets" />
|
||||
|
||||
<Reference Include="Newtonsoft.Json" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"applyPatches": true,
|
||||
"rollForwardOnNoCandidateFx": 2
|
||||
}
|
||||
Loading…
Reference in New Issue