Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public override void Visit(OpenApiSchema schema)

public override void Visit(OpenApiPathItem pathItem)
{
if (pathItem.Operations.TryGetValue(OperationType.Put, out var value))
if (pathItem.Operations.TryGetValue(OperationType.Put, out var value) &&
value.OperationId != null)
{
var operationId = value.OperationId;
pathItem.Operations[OperationType.Put].OperationId = ResolvePutOperationId(operationId);
Expand All @@ -67,14 +68,14 @@ public override void Visit(OpenApiOperation operation)
throw new ArgumentException($"OperationId is required {PathString}", nameof(operation));

var operationId = operation.OperationId;
var operationTypeExtension = operation.Extensions.GetExtension("x-ms-docs-operation-type");
var operationTypeExtension = operation.Extensions?.GetExtension("x-ms-docs-operation-type");
if (operationTypeExtension.IsEquals("function"))
operation.Parameters = ResolveFunctionParameters(operation.Parameters);
operation.Parameters = ResolveFunctionParameters(operation.Parameters ?? new List<OpenApiParameter>());

// Order matters. Resolve operationId.
operationId = RemoveHashSuffix(operationId);
if (operationTypeExtension.IsEquals("action") || operationTypeExtension.IsEquals("function"))
operationId = RemoveKeyTypeSegment(operationId, operation.Parameters);
operationId = RemoveKeyTypeSegment(operationId, operation.Parameters ?? new List<OpenApiParameter>());
operationId = SingularizeAndDeduplicateOperationId(operationId.SplitByChar('.'));
operationId = ResolveODataCastOperationId(operationId);
operationId = ResolveByRefOperationId(operationId);
Expand Down
12 changes: 6 additions & 6 deletions src/Microsoft.OpenApi.Hidi/OpenApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ private static OpenApiDocument ApplyFilters(HidiOptions options, ILogger logger,
stopwatch.Start();
document = OpenApiFilterService.CreateFilteredDocument(document, predicate);
stopwatch.Stop();
logger.LogTrace("{Timestamp}ms: Creating filtered OpenApi document with {Paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count);
logger.LogTrace("{Timestamp}ms: Creating filtered OpenApi document with {Paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths?.Count);
}

return document;
Expand Down Expand Up @@ -235,7 +235,7 @@ private static async Task<OpenApiDocument> GetOpenApi(HidiOptions options, ILogg

document = await ConvertCsdlToOpenApi(filteredStream ?? stream, metadataVersion, options.SettingsConfig, cancellationToken).ConfigureAwait(false);
stopwatch.Stop();
logger.LogTrace("{Timestamp}ms: Generated OpenAPI with {Paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count);
logger.LogTrace("{Timestamp}ms: Generated OpenAPI with {Paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths?.Count);
}
}
else if (!string.IsNullOrEmpty(options.OpenApi))
Expand Down Expand Up @@ -649,7 +649,7 @@ internal static void WriteTreeDocumentAsMarkdown(string openapiUrl, OpenApiDocum
{
var rootNode = OpenApiUrlTreeNode.Create(document, "main");

writer.WriteLine("# " + document.Info.Title);
writer.WriteLine("# " + document.Info?.Title);
writer.WriteLine();
writer.WriteLine("API Description: " + openapiUrl);

Expand Down Expand Up @@ -685,7 +685,7 @@ internal static void WriteTreeDocumentAsHtml(string sourceUrl, OpenApiDocument d
</style>
<body>
""");
writer.WriteLine("<h1>" + document.Info.Title + "</h1>");
writer.WriteLine("<h1>" + document.Info?.Title + "</h1>");
writer.WriteLine();
writer.WriteLine($"<h3> API Description: <a href='{sourceUrl}'>{sourceUrl}</a></h3>");

Expand Down Expand Up @@ -755,8 +755,8 @@ internal static async Task PluginManifest(HidiOptions options, ILogger logger, C
// Create OpenAIPluginManifest from ApiDependency and OpenAPI document
var manifest = new OpenAIPluginManifest
{
NameForHuman = document.Info.Title,
DescriptionForHuman = document.Info.Description,
NameForHuman = document.Info?.Title,
DescriptionForHuman = document.Info?.Description,
Api = new()
{
Type = "openapi",
Expand Down
24 changes: 13 additions & 11 deletions src/Microsoft.OpenApi/Models/OpenApiComponents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Writers;

#nullable enable

namespace Microsoft.OpenApi.Models
{
/// <summary>
Expand All @@ -16,55 +18,55 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible
/// <summary>
/// An object to hold reusable <see cref="OpenApiSchema"/> Objects.
/// </summary>
public IDictionary<string, OpenApiSchema> Schemas { get; set; } = new Dictionary<string, OpenApiSchema>();
public IDictionary<string, OpenApiSchema>? Schemas { get; set; } = new Dictionary<string, OpenApiSchema>();

/// <summary>
/// An object to hold reusable <see cref="OpenApiResponse"/> Objects.
/// </summary>
public IDictionary<string, OpenApiResponse> Responses { get; set; } = new Dictionary<string, OpenApiResponse>();
public IDictionary<string, OpenApiResponse>? Responses { get; set; } = new Dictionary<string, OpenApiResponse>();

/// <summary>
/// An object to hold reusable <see cref="OpenApiParameter"/> Objects.
/// </summary>
public IDictionary<string, OpenApiParameter> Parameters { get; set; } =
public IDictionary<string, OpenApiParameter>? Parameters { get; set; } =
new Dictionary<string, OpenApiParameter>();

/// <summary>
/// An object to hold reusable <see cref="OpenApiExample"/> Objects.
/// </summary>
public IDictionary<string, OpenApiExample> Examples { get; set; } = new Dictionary<string, OpenApiExample>();
public IDictionary<string, OpenApiExample>? Examples { get; set; } = new Dictionary<string, OpenApiExample>();

/// <summary>
/// An object to hold reusable <see cref="OpenApiRequestBody"/> Objects.
/// </summary>
public IDictionary<string, OpenApiRequestBody> RequestBodies { get; set; } =
public IDictionary<string, OpenApiRequestBody>? RequestBodies { get; set; } =
new Dictionary<string, OpenApiRequestBody>();

/// <summary>
/// An object to hold reusable <see cref="OpenApiHeader"/> Objects.
/// </summary>
public IDictionary<string, OpenApiHeader> Headers { get; set; } = new Dictionary<string, OpenApiHeader>();
public IDictionary<string, OpenApiHeader>? Headers { get; set; } = new Dictionary<string, OpenApiHeader>();

/// <summary>
/// An object to hold reusable <see cref="OpenApiSecurityScheme"/> Objects.
/// </summary>
public IDictionary<string, OpenApiSecurityScheme> SecuritySchemes { get; set; } =
public IDictionary<string, OpenApiSecurityScheme>? SecuritySchemes { get; set; } =
new Dictionary<string, OpenApiSecurityScheme>();

/// <summary>
/// An object to hold reusable <see cref="OpenApiLink"/> Objects.
/// </summary>
public IDictionary<string, OpenApiLink> Links { get; set; } = new Dictionary<string, OpenApiLink>();
public IDictionary<string, OpenApiLink>? Links { get; set; } = new Dictionary<string, OpenApiLink>();

/// <summary>
/// An object to hold reusable <see cref="OpenApiCallback"/> Objects.
/// </summary>
public IDictionary<string, OpenApiCallback> Callbacks { get; set; } = new Dictionary<string, OpenApiCallback>();
public IDictionary<string, OpenApiCallback>? Callbacks { get; set; } = new Dictionary<string, OpenApiCallback>();

/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();

/// <summary>
/// Parameter-less constructor
Expand All @@ -74,7 +76,7 @@ public OpenApiComponents() { }
/// <summary>
/// Initializes a copy of an <see cref="OpenApiComponents"/> object
/// </summary>
public OpenApiComponents(OpenApiComponents components)
public OpenApiComponents(OpenApiComponents? components)
{
Schemas = components?.Schemas != null ? new Dictionary<string, OpenApiSchema>(components.Schemas) : null;
Responses = components?.Responses != null ? new Dictionary<string, OpenApiResponse>(components.Responses) : null;
Expand Down
56 changes: 29 additions & 27 deletions src/Microsoft.OpenApi/Models/OpenApiDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
using Microsoft.OpenApi.Services;
using Microsoft.OpenApi.Writers;

#nullable enable

namespace Microsoft.OpenApi.Models
{
/// <summary>
Expand All @@ -22,48 +24,48 @@ public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible
/// <summary>
/// Related workspace containing OpenApiDocuments that are referenced in this document
/// </summary>
public OpenApiWorkspace Workspace { get; set; }
public OpenApiWorkspace? Workspace { get; set; }

/// <summary>
/// REQUIRED. Provides metadata about the API. The metadata MAY be used by tooling as required.
/// </summary>
public OpenApiInfo Info { get; set; }
public OpenApiInfo? Info { get; set; }

/// <summary>
/// An array of Server Objects, which provide connectivity information to a target server.
/// </summary>
public IList<OpenApiServer> Servers { get; set; } = new List<OpenApiServer>();
public IList<OpenApiServer>? Servers { get; set; } = new List<OpenApiServer>();

/// <summary>
/// REQUIRED. The available paths and operations for the API.
/// </summary>
public OpenApiPaths Paths { get; set; }
public OpenApiPaths? Paths { get; set; }

/// <summary>
/// An element to hold various schemas for the specification.
/// </summary>
public OpenApiComponents Components { get; set; }
public OpenApiComponents? Components { get; set; }

/// <summary>
/// A declaration of which security mechanisms can be used across the API.
/// </summary>
public IList<OpenApiSecurityRequirement> SecurityRequirements { get; set; } =
public IList<OpenApiSecurityRequirement>? SecurityRequirements { get; set; } =
new List<OpenApiSecurityRequirement>();

/// <summary>
/// A list of tags used by the specification with additional metadata.
/// </summary>
public IList<OpenApiTag> Tags { get; set; } = new List<OpenApiTag>();
public IList<OpenApiTag>? Tags { get; set; } = new List<OpenApiTag>();

/// <summary>
/// Additional external documentation.
/// </summary>
public OpenApiExternalDocs ExternalDocs { get; set; }
public OpenApiExternalDocs? ExternalDocs { get; set; }

/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();

/// <summary>
/// The unique hash code of the generated OpenAPI document
Expand All @@ -78,7 +80,7 @@ public OpenApiDocument() {}
/// <summary>
/// Initializes a copy of an an <see cref="OpenApiDocument"/> object
/// </summary>
public OpenApiDocument(OpenApiDocument document)
public OpenApiDocument(OpenApiDocument? document)
{
Workspace = document?.Workspace != null ? new(document?.Workspace) : null;
Info = document?.Info != null ? new(document?.Info) : null;
Expand Down Expand Up @@ -289,7 +291,7 @@ private static string ParseServerUrl(OpenApiServer server)
return parsedUrl;
}

private static void WriteHostInfoV2(IOpenApiWriter writer, IList<OpenApiServer> servers)
private static void WriteHostInfoV2(IOpenApiWriter writer, IList<OpenApiServer>? servers)
{
if (servers == null || !servers.Any())
{
Expand Down Expand Up @@ -373,7 +375,7 @@ public IEnumerable<OpenApiError> ResolveReferences()
/// <summary>
/// Load the referenced <see cref="IOpenApiReferenceable"/> object from a <see cref="OpenApiReference"/> object
/// </summary>
internal T ResolveReferenceTo<T>(OpenApiReference reference) where T : class, IOpenApiReferenceable
internal T? ResolveReferenceTo<T>(OpenApiReference reference) where T : class, IOpenApiReferenceable
{
if (reference.IsExternal)
{
Expand All @@ -388,7 +390,7 @@ internal T ResolveReferenceTo<T>(OpenApiReference reference) where T : class, IO
/// <summary>
/// Load the referenced <see cref="IOpenApiReferenceable"/> object from a <see cref="OpenApiReference"/> object
/// </summary>
public IOpenApiReferenceable ResolveReference(OpenApiReference reference)
public IOpenApiReferenceable? ResolveReference(OpenApiReference reference)
{
return ResolveReference(reference, false);
}
Expand Down Expand Up @@ -430,7 +432,7 @@ private static string ConvertByteArrayToString(byte[] hash)
/// <summary>
/// Load the referenced <see cref="IOpenApiReferenceable"/> object from a <see cref="OpenApiReference"/> object
/// </summary>
internal IOpenApiReferenceable ResolveReference(OpenApiReference reference, bool useExternal)
internal IOpenApiReferenceable? ResolveReference(OpenApiReference? reference, bool useExternal)
{
if (reference == null)
{
Expand All @@ -455,7 +457,7 @@ internal IOpenApiReferenceable ResolveReference(OpenApiReference reference, bool
// Special case for Tag
if (reference.Type == ReferenceType.Tag)
{
foreach (var tag in this.Tags)
foreach (var tag in this.Tags ?? Enumerable.Empty<OpenApiTag>())
{
if (tag.Name == reference.Id)
{
Expand All @@ -477,34 +479,34 @@ internal IOpenApiReferenceable ResolveReference(OpenApiReference reference, bool
switch (reference.Type)
{
case ReferenceType.Schema:
return this.Components.Schemas[reference.Id];
return this.Components.Schemas?[reference.Id];

case ReferenceType.Response:
return this.Components.Responses[reference.Id];
return this.Components.Responses?[reference.Id];

case ReferenceType.Parameter:
return this.Components.Parameters[reference.Id];
return this.Components.Parameters?[reference.Id];

case ReferenceType.Example:
return this.Components.Examples[reference.Id];
return this.Components.Examples?[reference.Id];

case ReferenceType.RequestBody:
return this.Components.RequestBodies[reference.Id];
return this.Components.RequestBodies?[reference.Id];

case ReferenceType.Header:
return this.Components.Headers[reference.Id];
return this.Components.Headers?[reference.Id];

case ReferenceType.SecurityScheme:
return this.Components.SecuritySchemes[reference.Id];
return this.Components.SecuritySchemes?[reference.Id];

case ReferenceType.Link:
return this.Components.Links[reference.Id];
return this.Components.Links?[reference.Id];

case ReferenceType.Callback:
return this.Components.Callbacks[reference.Id];
return this.Components.Callbacks?[reference.Id];

case ReferenceType.Path:
return this.Paths[reference.Id];
return this.Paths?[reference.Id];

default:
throw new OpenApiException(Properties.SRResource.InvalidReferenceType);
Expand All @@ -519,9 +521,9 @@ internal IOpenApiReferenceable ResolveReference(OpenApiReference reference, bool

internal class FindSchemaReferences : OpenApiVisitorBase
{
private Dictionary<string, OpenApiSchema> Schemas;
private Dictionary<string, OpenApiSchema> Schemas = new Dictionary<string, OpenApiSchema>();

public static void ResolveSchemas(OpenApiComponents components, Dictionary<string, OpenApiSchema> schemas )
public static void ResolveSchemas(OpenApiComponents? components, Dictionary<string, OpenApiSchema> schemas )
{
var visitor = new FindSchemaReferences();
visitor.Schemas = schemas;
Expand Down
Loading