| File: GetOpenApiReferenceMetadata.cs | Web Access |
| Project: src\aspnetcore\src\Tools\Extensions.ApiDescription.Client\src\Microsoft.Extensions.ApiDescription.Client.csproj (Microsoft.Extensions.ApiDescription.Client) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.IO; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace Microsoft.Extensions.ApiDescription.Client; /// <summary> /// Adds or corrects ClassName, FirstForGenerator, Namespace, and OutputPath metadata in OpenApiReference items. /// Also stores final metadata as SerializedMetadata. /// </summary> public class GetOpenApiReferenceMetadata : Task { private const string TypeScriptLanguageName = "TypeScript"; /// <summary> /// Extension to use in default OutputPath metadata value. Ignored when generating TypeScript. /// </summary> [Required] public string Extension { get; set; } /// <summary> /// Default Namespace metadata value. /// </summary> [Required] public string Namespace { get; set; } /// <summary> /// Default directory for OutputPath values. /// </summary> public string OutputDirectory { get; set; } /// <summary> /// The OpenApiReference items to update. /// </summary> [Required] public ITaskItem[] Inputs { get; set; } /// <summary> /// The updated OpenApiReference items. Will include ClassName, Namespace and OutputPath metadata. /// </summary> [Output] public ITaskItem[] Outputs { get; set; } /// <inheritdoc /> public override bool Execute() { var outputs = new List<ITaskItem>(Inputs.Length); var codeGenerators = new HashSet<string>(); var destinations = new HashSet<string>(); foreach (var item in Inputs) { var codeGenerator = item.GetMetadata("CodeGenerator"); if (string.IsNullOrEmpty(codeGenerator)) { // This case occurs when user overrides the required metadata with an empty string. var type = string.IsNullOrEmpty(item.GetMetadata("SourceProject")) ? "OpenApiReference" : "OpenApiProjectReference"; Log.LogError(Resources.FormatInvalidEmptyMetadataValue("CodeGenerator", type, item.ItemSpec)); continue; } var newItem = new TaskItem(item); outputs.Add(newItem); if (codeGenerators.Add(codeGenerator)) { newItem.SetMetadata("FirstForGenerator", "true"); } else { newItem.SetMetadata("FirstForGenerator", "false"); } var outputPath = item.GetMetadata("OutputPath"); if (string.IsNullOrEmpty(outputPath)) { // No need to further sanitize this path because the file must exist. var filename = item.GetMetadata("Filename"); var isTypeScript = codeGenerator.EndsWith( TypeScriptLanguageName, StringComparison.OrdinalIgnoreCase); outputPath = $"{filename}Client{(isTypeScript ? ".ts" : Extension)}"; } // Place output file in correct directory (relative to project directory). if (!Path.IsPathRooted(outputPath) && !string.IsNullOrEmpty(OutputDirectory)) { outputPath = Path.Combine(OutputDirectory, outputPath); } if (!destinations.Add(outputPath)) { // This case may occur when user is experimenting e.g. with multiple code generators or options. // May also occur when user accidentally duplicates OutputPath metadata. Log.LogError(Resources.FormatDuplicateFileOutputPaths(outputPath)); continue; } MetadataSerializer.SetMetadata(newItem, "OutputPath", outputPath); var className = item.GetMetadata("ClassName"); if (string.IsNullOrEmpty(className)) { var outputFilename = Path.GetFileNameWithoutExtension(outputPath); className = CSharpIdentifier.SanitizeIdentifier(outputFilename); MetadataSerializer.SetMetadata(newItem, "ClassName", className); } var @namespace = item.GetMetadata("Namespace"); if (string.IsNullOrEmpty(@namespace)) { MetadataSerializer.SetMetadata(newItem, "Namespace", Namespace); } // Add metadata which may be used as a property and passed to an inner build. newItem.RemoveMetadata("SerializedMetadata"); newItem.SetMetadata("SerializedMetadata", MetadataSerializer.SerializeMetadata(newItem)); } Outputs = outputs.ToArray(); return !Log.HasLoggedErrors; } }