Skip to content

Commit 2e0b42d

Browse files
committed
fix: resolve PR feedback
1 parent cd4de69 commit 2e0b42d

23 files changed

+170
-164
lines changed

src/Microsoft.OpenApi.Hidi/OpenApiService.cs

Lines changed: 79 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
9494
// Load OpenAPI document
9595
var document = await GetOpenApiAsync(options, openApiFormat.GetDisplayName(), logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false);
9696

97-
if (options.FilterOptions != null)
97+
if (options.FilterOptions != null && document is not null)
9898
{
9999
document = ApplyFilters(options, logger, apiDependency, postmanCollection, document);
100100
}
@@ -107,7 +107,11 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
107107
var walker = new OpenApiWalker(powerShellFormatter);
108108
walker.Walk(document);
109109
}
110-
await WriteOpenApiAsync(options, openApiFormat, openApiVersion, document, logger, cancellationToken).ConfigureAwait(false);
110+
if (document is not null)
111+
{
112+
// Write the OpenAPI document to the output file
113+
await WriteOpenApiAsync(options, openApiFormat, openApiVersion, document, logger, cancellationToken).ConfigureAwait(false);
114+
}
111115
}
112116
catch (TaskCanceledException)
113117
{
@@ -149,7 +153,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
149153
return apiDependency;
150154
}
151155

152-
private static OpenApiDocument? ApplyFilters(HidiOptions options, ILogger logger, ApiDependency? apiDependency, JsonDocument? postmanCollection, OpenApiDocument? document)
156+
private static OpenApiDocument ApplyFilters(HidiOptions options, ILogger logger, ApiDependency? apiDependency, JsonDocument? postmanCollection, OpenApiDocument document)
153157
{
154158
Dictionary<string, List<string>> requestUrls;
155159
if (apiDependency != null)
@@ -172,7 +176,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
172176
options.FilterOptions.FilterByTags,
173177
requestUrls,
174178
document,
175-
logger);
179+
logger);
176180
if (predicate != null)
177181
{
178182
var stopwatch = new Stopwatch();
@@ -185,7 +189,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
185189
return document;
186190
}
187191

188-
private static async Task WriteOpenApiAsync(HidiOptions options, OpenApiFormat openApiFormat, OpenApiSpecVersion openApiVersion, OpenApiDocument? document, ILogger logger, CancellationToken cancellationToken)
192+
private static async Task WriteOpenApiAsync(HidiOptions options, OpenApiFormat openApiFormat, OpenApiSpecVersion openApiVersion, OpenApiDocument document, ILogger logger, CancellationToken cancellationToken)
189193
{
190194
using (logger.BeginScope("Output"))
191195
{
@@ -210,10 +214,8 @@ private static async Task WriteOpenApiAsync(HidiOptions options, OpenApiFormat o
210214

211215
var stopwatch = new Stopwatch();
212216
stopwatch.Start();
213-
if (document is not null)
214-
{
215-
await document.SerializeAsync(writer, openApiVersion, cancellationToken).ConfigureAwait(false);
216-
}
217+
218+
await document.SerializeAsync(writer, openApiVersion, cancellationToken).ConfigureAwait(false);
217219
stopwatch.Stop();
218220

219221
logger.LogTrace("Finished serializing in {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
@@ -259,7 +261,7 @@ private static async Task WriteOpenApiAsync(HidiOptions options, OpenApiFormat o
259261
return document;
260262
}
261263

262-
private static Func<string, OperationType?, OpenApiOperation, bool>? FilterOpenApiDocument(string? filterByOperationIds, string? filterByTags, Dictionary<string, List<string>> requestUrls, OpenApiDocument? document, ILogger logger)
264+
private static Func<string, OperationType?, OpenApiOperation, bool>? FilterOpenApiDocument(string? filterByOperationIds, string? filterByTags, Dictionary<string, List<string>> requestUrls, OpenApiDocument document, ILogger logger)
263265
{
264266
Func<string, OperationType?, OpenApiOperation, bool>? predicate = null;
265267

@@ -587,52 +589,54 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl
587589

588590
var openApiFormat = options.OpenApiFormat ?? (!string.IsNullOrEmpty(options.OpenApi) ? GetOpenApiFormat(options.OpenApi, logger) : OpenApiFormat.Yaml);
589591
var document = await GetOpenApiAsync(options, openApiFormat.GetDisplayName(), logger, null, cancellationToken).ConfigureAwait(false);
590-
591-
using (logger.BeginScope("Creating diagram"))
592+
if (document is not null)
592593
{
593-
// If output is null, create a HTML file in the user's temporary directory
594-
var sourceUrl = (string.IsNullOrEmpty(options.OpenApi), string.IsNullOrEmpty(options.Csdl)) switch {
595-
(false, _) => options.OpenApi!,
596-
(_, false) => options.Csdl!,
597-
_ => throw new InvalidOperationException("No input file path or URL provided")
598-
};
599-
if (options.Output == null)
594+
using (logger.BeginScope("Creating diagram"))
600595
{
601-
var tempPath = Path.GetTempPath() + "/hidi/";
602-
if (!File.Exists(tempPath))
596+
// If output is null, create a HTML file in the user's temporary directory
597+
var sourceUrl = (string.IsNullOrEmpty(options.OpenApi), string.IsNullOrEmpty(options.Csdl)) switch
603598
{
604-
Directory.CreateDirectory(tempPath);
605-
}
606-
607-
var fileName = Path.GetRandomFileName();
608-
609-
var output = new FileInfo(Path.Combine(tempPath, fileName + ".html"));
610-
using (var file = new FileStream(output.FullName, FileMode.Create))
599+
(false, _) => options.OpenApi!,
600+
(_, false) => options.Csdl!,
601+
_ => throw new InvalidOperationException("No input file path or URL provided")
602+
};
603+
if (options.Output == null)
611604
{
612-
using var writer = new StreamWriter(file);
613-
WriteTreeDocumentAsHtml(sourceUrl, document, writer);
605+
var tempPath = Path.GetTempPath() + "/hidi/";
606+
if (!File.Exists(tempPath))
607+
{
608+
Directory.CreateDirectory(tempPath);
609+
}
610+
611+
var fileName = Path.GetRandomFileName();
612+
613+
var output = new FileInfo(Path.Combine(tempPath, fileName + ".html"));
614+
using (var file = new FileStream(output.FullName, FileMode.Create))
615+
{
616+
using var writer = new StreamWriter(file);
617+
WriteTreeDocumentAsHtml(sourceUrl, document, writer);
618+
}
619+
logger.LogTrace("Created Html document with diagram ");
620+
621+
// Launch a browser to display the output html file
622+
using var process = new Process();
623+
process.StartInfo.FileName = output.FullName;
624+
process.StartInfo.UseShellExecute = true;
625+
process.Start();
626+
627+
return output.FullName;
614628
}
615-
logger.LogTrace("Created Html document with diagram ");
616-
617-
// Launch a browser to display the output html file
618-
using var process = new Process();
619-
process.StartInfo.FileName = output.FullName;
620-
process.StartInfo.UseShellExecute = true;
621-
process.Start();
622-
623-
return output.FullName;
624-
}
625-
else // Write diagram as Markdown document to output file
626-
{
627-
using (var file = new FileStream(options.Output.FullName, FileMode.Create))
629+
else // Write diagram as Markdown document to output file
628630
{
631+
using var file = new FileStream(options.Output.FullName, FileMode.Create);
629632
using var writer = new StreamWriter(file);
630633
WriteTreeDocumentAsMarkdown(sourceUrl, document, writer);
634+
635+
logger.LogTrace("Created markdown document with diagram ");
636+
return options.Output.FullName;
631637
}
632-
logger.LogTrace("Created markdown document with diagram ");
633-
return options.Output.FullName;
634638
}
635-
}
639+
}
636640
}
637641
catch (TaskCanceledException)
638642
{
@@ -660,11 +664,11 @@ private static void LogErrors(ILogger logger, ReadResult result)
660664
}
661665
}
662666

663-
internal static void WriteTreeDocumentAsMarkdown(string openapiUrl, OpenApiDocument? document, StreamWriter writer)
667+
internal static void WriteTreeDocumentAsMarkdown(string openapiUrl, OpenApiDocument document, StreamWriter writer)
664668
{
665669
var rootNode = OpenApiUrlTreeNode.Create(document, "main");
666670

667-
writer.WriteLine("# " + document?.Info.Title);
671+
writer.WriteLine("# " + document.Info.Title);
668672
writer.WriteLine();
669673
writer.WriteLine("API Description: " + openapiUrl);
670674

@@ -681,7 +685,7 @@ internal static void WriteTreeDocumentAsMarkdown(string openapiUrl, OpenApiDocum
681685
writer.WriteLine("```");
682686
}
683687

684-
internal static void WriteTreeDocumentAsHtml(string sourceUrl, OpenApiDocument? document, StreamWriter writer, bool asHtmlFile = false)
688+
internal static void WriteTreeDocumentAsHtml(string sourceUrl, OpenApiDocument document, StreamWriter writer, bool asHtmlFile = false)
685689
{
686690
var rootNode = OpenApiUrlTreeNode.Create(document, "main");
687691

@@ -754,7 +758,7 @@ internal static async Task PluginManifestAsync(HidiOptions options, ILogger logg
754758

755759
cancellationToken.ThrowIfCancellationRequested();
756760

757-
if (options.FilterOptions != null)
761+
if (options.FilterOptions != null && document is not null)
758762
{
759763
document = ApplyFilters(options, logger, apiDependency, null, document);
760764
}
@@ -768,28 +772,31 @@ internal static async Task PluginManifestAsync(HidiOptions options, ILogger logg
768772
// Write OpenAPI to Output folder
769773
options.Output = new(Path.Combine(options.OutputFolder, "openapi.json"));
770774
options.TerseOutput = true;
771-
await WriteOpenApiAsync(options, OpenApiFormat.Json, OpenApiSpecVersion.OpenApi3_1, document, logger, cancellationToken).ConfigureAwait(false);
772-
773-
// Create OpenAIPluginManifest from ApiDependency and OpenAPI document
774-
var manifest = new OpenAIPluginManifest(document?.Info.Title ?? "Title",
775-
document?.Info.Title ?? "Title",
776-
"https://go.microsoft.com/fwlink/?LinkID=288890",
777-
document?.Info?.Contact?.Email ?? "placeholder@contoso.com",
778-
document?.Info?.License?.Url?.ToString() ?? "https://placeholderlicenseurl.com")
779-
{
780-
DescriptionForHuman = document?.Info.Description ?? "Description placeholder",
781-
Api = new("openapi", "./openapi.json"),
782-
Auth = new ManifestNoAuth(),
783-
};
784-
manifest.NameForModel = manifest.NameForHuman;
785-
manifest.DescriptionForModel = manifest.DescriptionForHuman;
786-
787-
// Write OpenAIPluginManifest to Output folder
788-
var manifestFile = new FileInfo(Path.Combine(options.OutputFolder, "ai-plugin.json"));
789-
using var file = new FileStream(manifestFile.FullName, FileMode.Create);
790-
using var jsonWriter = new Utf8JsonWriter(file, new() { Indented = true });
791-
manifest.Write(jsonWriter);
792-
await jsonWriter.FlushAsync(cancellationToken).ConfigureAwait(false);
775+
if (document is not null)
776+
{
777+
await WriteOpenApiAsync(options, OpenApiFormat.Json, OpenApiSpecVersion.OpenApi3_1, document, logger, cancellationToken).ConfigureAwait(false);
778+
779+
// Create OpenAIPluginManifest from ApiDependency and OpenAPI document
780+
var manifest = new OpenAIPluginManifest(document.Info.Title ?? "Title",
781+
document.Info.Title ?? "Title",
782+
"https://go.microsoft.com/fwlink/?LinkID=288890",
783+
document.Info?.Contact?.Email ?? "placeholder@contoso.com",
784+
document.Info?.License?.Url?.ToString() ?? "https://placeholderlicenseurl.com")
785+
{
786+
DescriptionForHuman = document.Info?.Description ?? "Description placeholder",
787+
Api = new("openapi", "./openapi.json"),
788+
Auth = new ManifestNoAuth(),
789+
};
790+
manifest.NameForModel = manifest.NameForHuman;
791+
manifest.DescriptionForModel = manifest.DescriptionForHuman;
792+
793+
// Write OpenAIPluginManifest to Output folder
794+
var manifestFile = new FileInfo(Path.Combine(options.OutputFolder, "ai-plugin.json"));
795+
using var file = new FileStream(manifestFile.FullName, FileMode.Create);
796+
using var jsonWriter = new Utf8JsonWriter(file, new() { Indented = true });
797+
manifest.Write(jsonWriter);
798+
await jsonWriter.FlushAsync(cancellationToken).ConfigureAwait(false);
799+
}
793800
}
794801
}
795802
}

src/Microsoft.OpenApi/Extensions/OpenApiElementExtensions.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,7 @@ public static class OpenApiElementExtensions
2323
/// <returns>An IEnumerable of errors. This function will never return null.</returns>
2424
public static IEnumerable<OpenApiError> Validate(this IOpenApiElement element, ValidationRuleSet ruleSet)
2525
{
26-
var validator = new OpenApiValidator(ruleSet);
27-
28-
if (element is OpenApiDocument doc)
29-
{
30-
validator.HostDocument = doc;
31-
}
32-
26+
var validator = new OpenApiValidator(ruleSet);
3327
var walker = new OpenApiWalker(validator);
3428
walker.Walk(element);
3529
return validator.Errors.Cast<OpenApiError>().Union(validator.Warnings);

src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,20 @@ public static IOpenApiReferenceable ResolveReference(this IOpenApiReferenceable
3232
var mapKey = pointer.Tokens.ElementAtOrDefault(1);
3333
try
3434
{
35-
if (element is OpenApiHeader header)
35+
if (propertyName is not null && mapKey is not null)
3636
{
37-
return ResolveReferenceOnHeaderElement(header, propertyName, mapKey, pointer);
38-
}
39-
if (element is OpenApiParameter parameter)
40-
{
41-
return ResolveReferenceOnParameterElement(parameter, propertyName, mapKey, pointer);
42-
}
43-
if (element is OpenApiResponse response)
44-
{
45-
return ResolveReferenceOnResponseElement(response, propertyName, mapKey, pointer);
37+
if (element is OpenApiHeader header)
38+
{
39+
return ResolveReferenceOnHeaderElement(header, propertyName, mapKey, pointer);
40+
}
41+
if (element is OpenApiParameter parameter)
42+
{
43+
return ResolveReferenceOnParameterElement(parameter, propertyName, mapKey, pointer);
44+
}
45+
if (element is OpenApiResponse response)
46+
{
47+
return ResolveReferenceOnResponseElement(response, propertyName, mapKey, pointer);
48+
}
4649
}
4750
}
4851
catch (KeyNotFoundException)
@@ -54,12 +57,12 @@ public static IOpenApiReferenceable ResolveReference(this IOpenApiReferenceable
5457

5558
private static IOpenApiReferenceable ResolveReferenceOnHeaderElement(
5659
OpenApiHeader headerElement,
57-
string? propertyName,
58-
string? mapKey,
60+
string propertyName,
61+
string mapKey,
5962
JsonPointer pointer)
6063
{
6164
if (OpenApiConstants.Examples.Equals(propertyName, StringComparison.Ordinal) &&
62-
!string.IsNullOrEmpty(mapKey) && mapKey is not null &&
65+
!string.IsNullOrEmpty(mapKey) &&
6366
headerElement?.Examples != null &&
6467
headerElement.Examples.TryGetValue(mapKey, out var exampleElement) &&
6568
exampleElement is IOpenApiReferenceable referenceable)
@@ -71,12 +74,12 @@ private static IOpenApiReferenceable ResolveReferenceOnHeaderElement(
7174

7275
private static IOpenApiReferenceable ResolveReferenceOnParameterElement(
7376
OpenApiParameter parameterElement,
74-
string? propertyName,
75-
string? mapKey,
77+
string propertyName,
78+
string mapKey,
7679
JsonPointer pointer)
7780
{
7881
if (OpenApiConstants.Examples.Equals(propertyName, StringComparison.Ordinal) &&
79-
!string.IsNullOrEmpty(mapKey) && mapKey is not null &&
82+
!string.IsNullOrEmpty(mapKey) &&
8083
parameterElement?.Examples != null &&
8184
parameterElement.Examples.TryGetValue(mapKey, out var exampleElement) &&
8285
exampleElement is IOpenApiReferenceable referenceable)
@@ -88,11 +91,11 @@ private static IOpenApiReferenceable ResolveReferenceOnParameterElement(
8891

8992
private static IOpenApiReferenceable ResolveReferenceOnResponseElement(
9093
OpenApiResponse responseElement,
91-
string? propertyName,
92-
string? mapKey,
94+
string propertyName,
95+
string mapKey,
9396
JsonPointer pointer)
9497
{
95-
if (!string.IsNullOrEmpty(mapKey) && mapKey is not null)
98+
if (!string.IsNullOrEmpty(mapKey))
9699
{
97100
if (OpenApiConstants.Headers.Equals(propertyName, StringComparison.Ordinal) &&
98101
responseElement?.Headers != null &&

0 commit comments

Comments
 (0)