Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added Nullability markup for some classes #1705

Closed
wants to merge 3 commits into from
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 @@
/// <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 @@
/// <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 @@
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 @@
/// <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 @@
/// <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 @@
/// <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,14 +457,14 @@
// 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)
{
tag.Reference = reference;
return tag;
}
}

Check notice

Code scanning / CodeQL

Missed opportunity to use Where Note

This foreach loop
implicitly filters its target sequence
- consider filtering the sequence explicitly using '.Where(...)'.

return null;
}
Expand All @@ -477,34 +479,34 @@
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 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
Loading