diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 6686bba75..968286c19 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -8,6 +8,9 @@ trigger: - main - dev - support/v1 + tags: + include: + - 'v*' pr: branches: include: @@ -194,7 +197,7 @@ extends: content: '*.nupkg' - stage: deploy - condition: and(or(contains(variables['build.sourceBranch'], 'refs/heads/main'),contains(variables['build.sourceBranch'], 'refs/heads/support/v1')), succeeded()) + condition: and(contains(variables['build.sourceBranch'], 'refs/tags/v'), succeeded()) dependsOn: build jobs: - deployment: deploy_hidi @@ -305,18 +308,10 @@ extends: condition: succeededOrFailed() inputs: gitHubConnection: 'Github-MaggieKimani1' - action: create + action: edit tagSource: userSpecifiedTag - tag: '$(artifactVersion)' - title: '$(artifactVersion)' + tag: 'v$(artifactVersion)' releaseNotesSource: inline assets: '$(Pipeline.Workspace)\**\*.exe' - changeLogType: issueBased - changeLogLabels: '[ - { "label" : "feature-work", "feature", "displayName" : "New Features", "state" : "closed" }, - { "label" : "enhancement", "V2-Enhancement", "displayName" : "Enhancements", "state" : "closed" }, - { "label" : "bug", "bug-fix", "displayName" : "Bugs", "state" : "closed" }, - { "label" : "documentation", "doc", "displayName" : "Documentation", "state" : "closed"}, - { "label" : "dependencies", "displayName" : "Package Updates", "state" : "closed" } - ]' + addChangeLog: false diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml index 2425160a4..a4d9608c6 100644 --- a/.config/1espt/PipelineAutobaseliningConfig.yml +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -13,3 +13,10 @@ pipelines: lastModifiedDate: 2024-09-13 armory: lastModifiedDate: 2024-09-13 + binary: + credscan: + lastModifiedDate: 2025-01-27 + binskim: + lastModifiedDate: 2025-01-27 + spotbugs: + lastModifiedDate: 2025-01-27 diff --git a/.github/release-please.yml b/.github/release-please.yml new file mode 100644 index 000000000..c821fc166 --- /dev/null +++ b/.github/release-please.yml @@ -0,0 +1,7 @@ +manifest: true +primaryBranch: main +handleGHRelease: true +branches: + - branch: support/v1 + manifest: true + handleGHRelease: true \ No newline at end of file diff --git a/.github/workflows/auto-merge-dependabot.yml b/.github/workflows/auto-merge-dependabot.yml index 3d9334e96..df4b487a7 100644 --- a/.github/workflows/auto-merge-dependabot.yml +++ b/.github/workflows/auto-merge-dependabot.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v2.2.0 + uses: dependabot/fetch-metadata@v2.3.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b4f6003dc..93c8f3e87 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,13 +30,13 @@ jobs: id: getversion - name: Push to registry - Nightly if: ${{ github.ref == 'refs/heads/dev' }} - uses: docker/build-push-action@v6.12.0 + uses: docker/build-push-action@v6.13.0 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly - name: Push to registry - Release if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/support/v1' }} - uses: docker/build-push-action@v6.12.0 + uses: docker/build-push-action@v6.13.0 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.getversion.outputs.version }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 000000000..38714b6bd --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "2.0.0-preview5" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..52e80a16a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..a08924c7b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,52 @@ +# Contributing to OpenAPI.net + +OpenAPI.net is a mono-repo containing source code for the following packages: + +## Libraries + +| Library | NuGet Release | +|----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Microsoft.OpenAPI](./src/Microsoft.OpenAPI/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI/) | +| [Microsoft.OpenAPI.Readers](./src/Microsoft.OpenAPI.Readers/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI.Readers?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI.Readers/) | +| [Microsoft.OpenAPI.Hidi](./src/Microsoft.OpenAPI.Hidi/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI.Hidi?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI.Hidi/) | + +OpenAPI.net is open to contributions. There are a couple of different recommended paths to get contributions into the released version of this library. + +__NOTE__ A signed a contribution license agreement is required for all contributions, and is checked automatically on new pull requests. Please read and sign [the agreement](https://cla.microsoft.com/) before starting any work for this repository. + +## File issues + +The best way to get started with a contribution is to start a dialog with the owners of this repository. Sometimes features will be under development or out of scope for this SDK and it's best to check before starting work on contribution. Discussions on bugs and potential fixes could point you to the write change to make. + +## Submit pull requests for bug fixes and features + +Feel free to submit a pull request with a linked issue against the __main__ branch. The main branch will be updated frequently. +## Commit message format + +To support our automated release process, pull requests are required to follow the [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/) +format. +Each commit message consists of a __header__, an optional __body__ and an optional __footer__. The header is the first line of the commit and +MUST have a __type__ (see below for a list of types) and a __description__. An optional __scope__ can be added to the header to give extra context. + +``` +[optional scope]: + + + + +``` + +The recommended commit types used are: + +- __feat__ for feature updates (increments the _minor_ version) +- __fix__ for bug fixes (increments the _patch_ version) +- __perf__ for performance related changes e.g. optimizing an algorithm +- __refactor__ for code refactoring changes +- __test__ for test suite updates e.g. adding a test or fixing a test +- __style__ for changes that don't affect the meaning of code. e.g. formatting changes +- __docs__ for documentation updates e.g. ReadMe update or code documentation updates +- __build__ for build system changes (gradle updates, external dependency updates) +- __ci__ for CI configuration file changes e.g. updating a pipeline +- __chore__ for miscallaneous non-sdk changesin the repo e.g. removing an unused file + +Adding an exclamation mark after the commit type (`feat!`) or footer with the prefix __BREAKING CHANGE:__ will cause an increment of the _major_ version. \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 4fbb218f9..1b2409cb0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,6 +12,7 @@ https://github.com/Microsoft/OpenAPI.NET © Microsoft Corporation. All rights reserved. OpenAPI .NET + 2.0.0-preview5 diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 000000000..e6d1fb148 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,33 @@ +{ + "bootstrap-sha": "8943e2ad40babb0204dedb11ad6f9273adf9cd53", + "exclude-paths": [ + ".azure-pipelines", + ".github", + ".idea", + ".vs", + ".vscode" + ], + "release-type": "simple", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-component-in-tag": false, + "include-v-in-tag": true, + "draft": false, + "prerelease": true, + "versioning": "prerelease", + "prerelease-type": "preview", + "packages": { + ".": { + "package-name": "Microsoft.OpenApi", + "changelog-path": "CHANGELOG.md", + "extra-files": [ + { + "type": "xml", + "path": "Directory.Build.props", + "xpath": "//Project/PropertyGroup/Version" + } + ] + } + }, + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" +} \ No newline at end of file diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index c2bbc97d0..df632b78a 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -7,6 +7,7 @@ using Humanizer.Inflections; using Microsoft.OpenApi.Hidi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; namespace Microsoft.OpenApi.Hidi.Formatters @@ -15,7 +16,7 @@ internal class PowerShellFormatter : OpenApiVisitorBase { private const string DefaultPutPrefix = ".Update"; private const string PowerShellPutPrefix = ".Set"; - private readonly Stack _schemaLoop = new(); + private readonly Stack _schemaLoop = new(); private static readonly Regex s_oDataCastRegex = new("(.*(?<=[a-z]))\\.(As(?=[A-Z]).*)", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); private static readonly Regex s_hashSuffixRegex = new(@"^[^-]+", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); private static readonly Regex s_oDataRefRegex = new("(?<=[a-z])Ref(?=[A-Z])", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); @@ -41,7 +42,7 @@ static PowerShellFormatter() // 5. Fix anyOf and oneOf schema. // 6. Add AdditionalProperties to object schemas. - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { AddAdditionalPropertiesToSchema(schema); ResolveAnyOfSchema(schema); @@ -50,7 +51,7 @@ public override void Visit(OpenApiSchema schema) base.Visit(schema); } - public override void Visit(OpenApiPathItem pathItem) + public override void Visit(IOpenApiPathItem pathItem) { if (pathItem.Operations.TryGetValue(OperationType.Put, out var value) && value.OperationId != null) @@ -69,24 +70,24 @@ public override void Visit(OpenApiOperation operation) var operationId = operation.OperationId; var operationTypeExtension = operation.Extensions?.GetExtension("x-ms-docs-operation-type"); - if (operationTypeExtension.IsEquals("function")) - operation.Parameters = ResolveFunctionParameters(operation.Parameters ?? new List()); + if (operationTypeExtension.IsEquals("function") && operation.Parameters is { Count :> 0}) + ResolveFunctionParameters(operation.Parameters); // Order matters. Resolve operationId. operationId = RemoveHashSuffix(operationId); if (operationTypeExtension.IsEquals("action") || operationTypeExtension.IsEquals("function")) - operationId = RemoveKeyTypeSegment(operationId, operation.Parameters ?? new List()); + operationId = RemoveKeyTypeSegment(operationId, operation.Parameters ?? new List()); operationId = SingularizeAndDeduplicateOperationId(operationId.SplitByChar('.')); operationId = ResolveODataCastOperationId(operationId); operationId = ResolveByRefOperationId(operationId); // Verb segment resolution should always be last. user.get -> user_Get - operationId = ResolveVerbSegmentInOpertationId(operationId); + operationId = ResolveVerbSegmentInOperationId(operationId); operation.OperationId = operationId; base.Visit(operation); } - private static string ResolveVerbSegmentInOpertationId(string operationId) + private static string ResolveVerbSegmentInOperationId(string operationId) { var charPos = operationId.LastIndexOf('.', operationId.Length - 1); if (operationId.Contains('_', StringComparison.OrdinalIgnoreCase) || charPos < 0) @@ -143,7 +144,7 @@ private static string RemoveHashSuffix(string operationId) return s_hashSuffixRegex.Match(operationId).Value; } - private static string RemoveKeyTypeSegment(string operationId, IList parameters) + private static string RemoveKeyTypeSegment(string operationId, IList parameters) { var segments = operationId.SplitByChar('.'); foreach (var parameter in parameters) @@ -157,30 +158,29 @@ private static string RemoveKeyTypeSegment(string operationId, IList ResolveFunctionParameters(IList parameters) + private static void ResolveFunctionParameters(IList parameters) { - foreach (var parameter in parameters.Where(static p => p.Content?.Any() ?? false)) + foreach (var parameter in parameters.OfType().Where(static p => p.Content?.Any() ?? false)) { // Replace content with a schema object of type array // for structured or collection-valued function parameters parameter.Content = null; - parameter.Schema = new() + parameter.Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } }; } - return parameters; } - private void AddAdditionalPropertiesToSchema(OpenApiSchema schema) + private void AddAdditionalPropertiesToSchema(IOpenApiSchema schema) { - if (schema != null && !_schemaLoop.Contains(schema) && schema.Type.Equals(JsonSchemaType.Object)) + if (schema is OpenApiSchema openApiSchema && !_schemaLoop.Contains(schema) && schema.Type.Equals(JsonSchemaType.Object)) { - schema.AdditionalProperties = new() { Type = JsonSchemaType.Object }; + openApiSchema.AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Object }; /* Because 'additionalProperties' are now being walked, * we need a way to keep track of visited schemas to avoid @@ -190,39 +190,29 @@ private void AddAdditionalPropertiesToSchema(OpenApiSchema schema) } } - private static void ResolveOneOfSchema(OpenApiSchema schema) + private static void ResolveOneOfSchema(IOpenApiSchema schema) { - if (schema.OneOf?.FirstOrDefault() is { } newSchema) + if (schema is OpenApiSchema openApiSchema && schema.OneOf?.FirstOrDefault() is OpenApiSchema newSchema) { - schema.OneOf = null; - FlattenSchema(schema, newSchema); + openApiSchema.OneOf = null; + FlattenSchema(openApiSchema, newSchema); } } - private static void ResolveAnyOfSchema(OpenApiSchema schema) + private static void ResolveAnyOfSchema(IOpenApiSchema schema) { - if (schema.AnyOf?.FirstOrDefault() is { } newSchema) + if (schema is OpenApiSchema openApiSchema && schema.AnyOf?.FirstOrDefault() is OpenApiSchema newSchema) { - schema.AnyOf = null; - FlattenSchema(schema, newSchema); + openApiSchema.AnyOf = null; + FlattenSchema(openApiSchema, newSchema); } } private static void FlattenSchema(OpenApiSchema schema, OpenApiSchema newSchema) { - if (newSchema != null) - { - if (newSchema.Reference != null) - { - schema.Reference = newSchema.Reference; - schema.UnresolvedReference = true; - } - else - { - // Copies schema properties based on https://github.com/microsoft/OpenAPI.NET.OData/pull/264. - CopySchema(schema, newSchema); - } - } + if (newSchema is null) return; + // Copies schema properties based on https://github.com/microsoft/OpenAPI.NET.OData/pull/264. + CopySchema(schema, newSchema); } private static void CopySchema(OpenApiSchema schema, OpenApiSchema newSchema) @@ -253,7 +243,6 @@ private static void CopySchema(OpenApiSchema schema, OpenApiSchema newSchema) schema.Enum ??= newSchema.Enum; schema.ReadOnly = !schema.ReadOnly ? newSchema.ReadOnly : schema.ReadOnly; schema.WriteOnly = !schema.WriteOnly ? newSchema.WriteOnly : schema.WriteOnly; - schema.Nullable = !schema.Nullable ? newSchema.Nullable : schema.Nullable; schema.Deprecated = !schema.Deprecated ? newSchema.Deprecated : schema.Deprecated; } } diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 1e13eb157..b4bfa6189 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -9,7 +9,6 @@ enable hidi ./../../artifacts - 2.0.0-preview5 OpenAPI.NET CLI tool for slicing OpenAPI documents true diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index c7bf1a558..c757f4031 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -254,7 +254,7 @@ private static async Task GetOpenApiAsync(HidiOptions options, else if (!string.IsNullOrEmpty(options.OpenApi)) { stream = await GetStreamAsync(options.OpenApi, logger, cancellationToken).ConfigureAwait(false); - var result = await ParseOpenApiAsync(options.OpenApi, format, options.InlineExternal, logger, stream, cancellationToken).ConfigureAwait(false); + var result = await ParseOpenApiAsync(options.OpenApi, options.InlineExternal, logger, stream, cancellationToken).ConfigureAwait(false); document = result.Document; } else throw new InvalidOperationException("No input file path or URL provided"); @@ -351,8 +351,7 @@ private static MemoryStream ApplyFilterToCsdl(Stream csdlStream, string entitySe try { using var stream = await GetStreamAsync(openApi, logger, cancellationToken).ConfigureAwait(false); - var openApiFormat = !string.IsNullOrEmpty(openApi) ? GetOpenApiFormat(openApi, logger) : OpenApiFormat.Yaml; - result = await ParseOpenApiAsync(openApi, openApiFormat.GetDisplayName(),false, logger, stream, cancellationToken).ConfigureAwait(false); + result = await ParseOpenApiAsync(openApi, false, logger, stream, cancellationToken).ConfigureAwait(false); using (logger.BeginScope("Calculating statistics")) { @@ -380,7 +379,7 @@ private static MemoryStream ApplyFilterToCsdl(Stream csdlStream, string entitySe return result.Diagnostic.Errors.Count == 0; } - private static async Task ParseOpenApiAsync(string openApiFile, string format, bool inlineExternal, ILogger logger, Stream stream, CancellationToken cancellationToken = default) + private static async Task ParseOpenApiAsync(string openApiFile, bool inlineExternal, ILogger logger, Stream stream, CancellationToken cancellationToken = default) { ReadResult result; var stopwatch = Stopwatch.StartNew(); @@ -396,7 +395,7 @@ private static async Task ParseOpenApiAsync(string openApiFile, stri new Uri("file://" + new FileInfo(openApiFile).DirectoryName + Path.DirectorySeparatorChar) }; - result = await OpenApiDocument.LoadAsync(stream, format, settings, cancellationToken).ConfigureAwait(false); + result = await OpenApiDocument.LoadAsync(stream, settings: settings, cancellationToken: cancellationToken).ConfigureAwait(false); logger.LogTrace("{Timestamp}ms: Completed parsing.", stopwatch.ElapsedMilliseconds); diff --git a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs index d1f6f7f64..d157a6c42 100644 --- a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; namespace Microsoft.OpenApi.Hidi @@ -12,35 +13,35 @@ internal class StatsVisitor : OpenApiVisitorBase { public int ParameterCount { get; set; } - public override void Visit(OpenApiParameter parameter) + public override void Visit(IOpenApiParameter parameter) { ParameterCount++; } public int SchemaCount { get; set; } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { SchemaCount++; } public int HeaderCount { get; set; } - public override void Visit(IDictionary headers) + public override void Visit(IDictionary headers) { HeaderCount++; } public int PathItemCount { get; set; } - public override void Visit(OpenApiPathItem pathItem) + public override void Visit(IOpenApiPathItem pathItem) { PathItemCount++; } public int RequestBodyCount { get; set; } - public override void Visit(OpenApiRequestBody requestBody) + public override void Visit(IOpenApiRequestBody requestBody) { RequestBodyCount++; } @@ -61,14 +62,14 @@ public override void Visit(OpenApiOperation operation) public int LinkCount { get; set; } - public override void Visit(OpenApiLink link) + public override void Visit(IOpenApiLink link) { LinkCount++; } public int CallbackCount { get; set; } - public override void Visit(OpenApiCallback callback) + public override void Visit(IOpenApiCallback callback) { CallbackCount++; } diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj index 624fe822f..13c50aefd 100644 --- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj +++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj @@ -4,7 +4,6 @@ latest true - 2.0.0-preview5 OpenAPI.NET Readers for JSON and YAML documents true true diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 2f1ce2b37..353435bc8 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -77,9 +77,9 @@ public ReadResult Read(MemoryStream input, } /// - public static ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null) + public static ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings) { - return _jsonReader.Read(jsonNode, settings, OpenApiConstants.Yaml); + return _jsonReader.Read(jsonNode, settings); } /// diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs index 7eee12251..34a44c026 100644 --- a/src/Microsoft.OpenApi.Workbench/MainModel.cs +++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs @@ -219,7 +219,7 @@ internal async Task ParseDocumentAsync() { if (!string.IsNullOrWhiteSpace(_inputFile)) { - stream = _inputFile.StartsWith("http") ? await _httpClient.GetStreamAsync(_inputFile) + stream = _inputFile.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? await _httpClient.GetStreamAsync(_inputFile) : new FileStream(_inputFile, FileMode.Open); } else @@ -241,7 +241,7 @@ internal async Task ParseDocumentAsync() }; if (ResolveExternal && !string.IsNullOrWhiteSpace(_inputFile)) { - settings.BaseUrl = _inputFile.StartsWith("http") ? new(_inputFile) + settings.BaseUrl = _inputFile.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? new(_inputFile) : new("file://" + Path.GetDirectoryName(_inputFile) + "/"); } diff --git a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs index fafbc8188..85dc824a4 100644 --- a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; namespace Microsoft.OpenApi.Workbench @@ -12,35 +13,35 @@ internal class StatsVisitor : OpenApiVisitorBase { public int ParameterCount { get; set; } - public override void Visit(OpenApiParameter parameter) + public override void Visit(IOpenApiParameter parameter) { ParameterCount++; } public int SchemaCount { get; set; } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { SchemaCount++; } public int HeaderCount { get; set; } - public override void Visit(IDictionary headers) + public override void Visit(IDictionary headers) { HeaderCount++; } public int PathItemCount { get; set; } - public override void Visit(OpenApiPathItem pathItem) + public override void Visit(IOpenApiPathItem pathItem) { PathItemCount++; } public int RequestBodyCount { get; set; } - public override void Visit(OpenApiRequestBody requestBody) + public override void Visit(IOpenApiRequestBody requestBody) { RequestBodyCount++; } @@ -61,14 +62,14 @@ public override void Visit(OpenApiOperation operation) public int LinkCount { get; set; } - public override void Visit(OpenApiLink link) + public override void Visit(IOpenApiLink link) { LinkCount++; } public int CallbackCount { get; set; } - public override void Visit(OpenApiCallback callback) + public override void Visit(IOpenApiCallback callback) { CallbackCount++; } diff --git a/src/Microsoft.OpenApi/Expressions/RuntimeExpression.cs b/src/Microsoft.OpenApi/Expressions/RuntimeExpression.cs index 25792257e..69aecfd37 100644 --- a/src/Microsoft.OpenApi/Expressions/RuntimeExpression.cs +++ b/src/Microsoft.OpenApi/Expressions/RuntimeExpression.cs @@ -31,31 +31,31 @@ public static RuntimeExpression Build(string expression) { Utils.CheckArgumentNullOrEmpty(expression); - if (!expression.StartsWith(Prefix)) + if (!expression.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase)) { return new CompositeExpression(expression); } // $url - if (expression == UrlExpression.Url) + if (expression.Equals(UrlExpression.Url, StringComparison.Ordinal)) { return new UrlExpression(); } // $method - if (expression == MethodExpression.Method) + if (expression.Equals(MethodExpression.Method, StringComparison.Ordinal)) { return new MethodExpression(); } // $statusCode - if (expression == StatusCodeExpression.StatusCode) + if (expression.Equals(StatusCodeExpression.StatusCode, StringComparison.Ordinal)) { return new StatusCodeExpression(); } // $request. - if (expression.StartsWith(RequestExpression.Request)) + if (expression.StartsWith(RequestExpression.Request, StringComparison.Ordinal)) { var subString = expression.Substring(RequestExpression.Request.Length); var source = SourceExpression.Build(subString); @@ -63,7 +63,7 @@ public static RuntimeExpression Build(string expression) } // $response. - if (expression.StartsWith(ResponseExpression.Response)) + if (expression.StartsWith(ResponseExpression.Response, StringComparison.Ordinal)) { var subString = expression.Substring(ResponseExpression.Response.Length); var source = SourceExpression.Build(subString); diff --git a/src/Microsoft.OpenApi/Expressions/SourceExpression.cs b/src/Microsoft.OpenApi/Expressions/SourceExpression.cs index 8504a1e89..76a22f97d 100644 --- a/src/Microsoft.OpenApi/Expressions/SourceExpression.cs +++ b/src/Microsoft.OpenApi/Expressions/SourceExpression.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Properties; @@ -37,19 +38,19 @@ protected SourceExpression(string value) var expressions = expression.Split('.'); if (expressions.Length == 2) { - if (expression.StartsWith(HeaderExpression.Header)) + if (expression.StartsWith(HeaderExpression.Header, StringComparison.Ordinal)) { // header. return new HeaderExpression(expressions[1]); } - if (expression.StartsWith(QueryExpression.Query)) + if (expression.StartsWith(QueryExpression.Query, StringComparison.Ordinal)) { // query. return new QueryExpression(expressions[1]); } - if (expression.StartsWith(PathExpression.Path)) + if (expression.StartsWith(PathExpression.Path, StringComparison.Ordinal)) { // path. return new PathExpression(expressions[1]); @@ -57,7 +58,7 @@ protected SourceExpression(string value) } // body - if (expression.StartsWith(BodyExpression.Body)) + if (expression.StartsWith(BodyExpression.Body, StringComparison.Ordinal)) { var subString = expression.Substring(BodyExpression.Body.Length); if (string.IsNullOrEmpty(subString)) diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs index d6522ead3..c8c3b2a48 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; @@ -26,7 +27,7 @@ public static void AddExtension(this T element, string name, IOpenApiExtensio Utils.CheckArgumentNull(element); Utils.CheckArgumentNullOrEmpty(name); - if (!name.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix)) + if (!name.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase)) { throw new OpenApiException(string.Format(SRResource.ExtensionFieldNameMustBeginWithXDash, name)); } diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs index aca76f979..da51f3b55 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Exceptions; @@ -13,7 +14,7 @@ namespace Microsoft.OpenApi.Extensions /// /// Extension methods for resolving references on elements. /// - public static class OpenApiReferencableExtensions + public static class OpenApiReferenceableExtensions { /// /// Resolves a JSON Pointer with respect to an element, returning the referenced element. @@ -57,13 +58,15 @@ private static IOpenApiReferenceable ResolveReferenceOnHeaderElement( string mapKey, JsonPointer pointer) { - switch (propertyName) + if (OpenApiConstants.Examples.Equals(propertyName, StringComparison.Ordinal) && + !string.IsNullOrEmpty(mapKey) && + headerElement?.Examples != null && + headerElement.Examples.TryGetValue(mapKey, out var exampleElement) && + exampleElement is IOpenApiReferenceable referenceable) { - case OpenApiConstants.Examples when mapKey != null: - return headerElement.Examples[mapKey]; - default: - throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer)); + return referenceable; } + throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer)); } private static IOpenApiReferenceable ResolveReferenceOnParameterElement( @@ -72,13 +75,15 @@ private static IOpenApiReferenceable ResolveReferenceOnParameterElement( string mapKey, JsonPointer pointer) { - switch (propertyName) + if (OpenApiConstants.Examples.Equals(propertyName, StringComparison.Ordinal) && + !string.IsNullOrEmpty(mapKey) && + parameterElement?.Examples != null && + parameterElement.Examples.TryGetValue(mapKey, out var exampleElement) && + exampleElement is IOpenApiReferenceable referenceable) { - case OpenApiConstants.Examples when mapKey != null: - return parameterElement.Examples[mapKey]; - default: - throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer)); + return referenceable; } + throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer)); } private static IOpenApiReferenceable ResolveReferenceOnResponseElement( @@ -87,15 +92,24 @@ private static IOpenApiReferenceable ResolveReferenceOnResponseElement( string mapKey, JsonPointer pointer) { - switch (propertyName) + if (!string.IsNullOrEmpty(mapKey)) { - case OpenApiConstants.Headers when mapKey != null: - return responseElement.Headers[mapKey]; - case OpenApiConstants.Links when mapKey != null: - return responseElement.Links[mapKey]; - default: - throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer)); + if (OpenApiConstants.Headers.Equals(propertyName, StringComparison.Ordinal) && + responseElement?.Headers != null && + responseElement.Headers.TryGetValue(mapKey, out var headerElement) && + headerElement is IOpenApiReferenceable referenceable) + { + return referenceable; + } + if (OpenApiConstants.Links.Equals(propertyName, StringComparison.Ordinal) && + responseElement?.Links != null && + responseElement.Links.TryGetValue(mapKey, out var linkElement) && + linkElement is IOpenApiReferenceable referenceable2) + { + return referenceable2; + } } + throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer)); } } } diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs index e47eff496..eea41be49 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs @@ -87,19 +87,19 @@ public static JsonSchemaType ToJsonSchemaType(this string identifier) [typeof(char)] = () => new() { Type = JsonSchemaType.String }, // Nullable types - [typeof(bool?)] = () => new() { Type = JsonSchemaType.Boolean, Nullable = true }, - [typeof(byte?)] = () => new() { Type = JsonSchemaType.String, Format = "byte", Nullable = true }, - [typeof(int?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true }, - [typeof(uint?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true }, - [typeof(long?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true }, - [typeof(ulong?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true }, - [typeof(float?)] = () => new() { Type = JsonSchemaType.Number, Format = "float", Nullable = true }, - [typeof(double?)] = () => new() { Type = JsonSchemaType.Number, Format = "double", Nullable = true }, - [typeof(decimal?)] = () => new() { Type = JsonSchemaType.Number, Format = "double", Nullable = true }, - [typeof(DateTime?)] = () => new() { Type = JsonSchemaType.String, Format = "date-time", Nullable = true }, - [typeof(DateTimeOffset?)] = () => new() { Type = JsonSchemaType.String, Format = "date-time", Nullable = true }, - [typeof(Guid?)] = () => new() { Type = JsonSchemaType.String, Format = "uuid", Nullable = true }, - [typeof(char?)] = () => new() { Type = JsonSchemaType.String, Nullable = true }, + [typeof(bool?)] = () => new() { Type = JsonSchemaType.Boolean | JsonSchemaType.Null }, + [typeof(byte?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "byte" }, + [typeof(int?)] = () => new() { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32" }, + [typeof(uint?)] = () => new() { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32" }, + [typeof(long?)] = () => new() { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int64" }, + [typeof(ulong?)] = () => new() { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int64" }, + [typeof(float?)] = () => new() { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "float" }, + [typeof(double?)] = () => new() { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" }, + [typeof(decimal?)] = () => new() { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" }, + [typeof(DateTime?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "date-time" }, + [typeof(DateTimeOffset?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "date-time" }, + [typeof(Guid?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "uuid" }, + [typeof(char?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null }, [typeof(Uri)] = () => new() { Type = JsonSchemaType.String, Format = "uri" }, // Uri is treated as simple string [typeof(string)] = () => new() { Type = JsonSchemaType.String }, @@ -153,37 +153,37 @@ public static Type MapOpenApiPrimitiveTypeToSimpleType(this OpenApiSchema schema throw new ArgumentNullException(nameof(schema)); } - var type = (schema.Type.ToIdentifier(), schema.Format?.ToLowerInvariant(), schema.Nullable) switch + var type = ((schema.Type & ~JsonSchemaType.Null).ToIdentifier(), schema.Format?.ToLowerInvariant(), schema.Type & JsonSchemaType.Null) switch { - ("boolean", null, false) => typeof(bool), + ("integer" or "number", "int32", JsonSchemaType.Null) => typeof(int?), + ("integer" or "number", "int64", JsonSchemaType.Null) => typeof(long?), + ("integer", null, JsonSchemaType.Null) => typeof(long?), + ("number", "float", JsonSchemaType.Null) => typeof(float?), + ("number", "double", JsonSchemaType.Null) => typeof(double?), + ("number", null, JsonSchemaType.Null) => typeof(double?), + ("number", "decimal", JsonSchemaType.Null) => typeof(decimal?), + ("string", "byte", JsonSchemaType.Null) => typeof(byte?), + ("string", "date-time", JsonSchemaType.Null) => typeof(DateTimeOffset?), + ("string", "uuid", JsonSchemaType.Null) => typeof(Guid?), + ("string", "char", JsonSchemaType.Null) => typeof(char?), + ("boolean", null, JsonSchemaType.Null) => typeof(bool?), + ("boolean", null, _) => typeof(bool), // integer is technically not valid with format, but we must provide some compatibility - ("integer" or "number", "int32", false) => typeof(int), - ("integer" or "number", "int64", false) => typeof(long), - ("integer", null, false) => typeof(long), - ("number", "float", false) => typeof(float), - ("number", "double", false) => typeof(double), - ("number", "decimal", false) => typeof(decimal), - ("number", null, false) => typeof(double), - ("string", "byte", false) => typeof(byte), - ("string", "date-time", false) => typeof(DateTimeOffset), - ("string", "uuid", false) => typeof(Guid), - ("string", "duration", false) => typeof(TimeSpan), - ("string", "char", false) => typeof(char), - ("string", null, false) => typeof(string), - ("object", null, false) => typeof(object), - ("string", "uri", false) => typeof(Uri), - ("integer" or "number", "int32", true) => typeof(int?), - ("integer" or "number", "int64", true) => typeof(long?), - ("integer", null, true) => typeof(long?), - ("number", "float", true) => typeof(float?), - ("number", "double", true) => typeof(double?), - ("number", null, true) => typeof(double?), - ("number", "decimal", true) => typeof(decimal?), - ("string", "byte", true) => typeof(byte?), - ("string", "date-time", true) => typeof(DateTimeOffset?), - ("string", "uuid", true) => typeof(Guid?), - ("string", "char", true) => typeof(char?), - ("boolean", null, true) => typeof(bool?), + ("integer" or "number", "int32", _) => typeof(int), + ("integer" or "number", "int64", _) => typeof(long), + ("integer", null, _) => typeof(long), + ("number", "float", _) => typeof(float), + ("number", "double", _) => typeof(double), + ("number", "decimal", _) => typeof(decimal), + ("number", null, _) => typeof(double), + ("string", "byte", _) => typeof(byte), + ("string", "date-time", _) => typeof(DateTimeOffset), + ("string", "uuid", _) => typeof(Guid), + ("string", "duration", _) => typeof(TimeSpan), + ("string", "char", _) => typeof(char), + ("string", null, _) => typeof(string), + ("object", null, _) => typeof(object), + ("string", "uri", _) => typeof(Uri), _ => typeof(string), }; diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs new file mode 100644 index 000000000..367c84a96 --- /dev/null +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Microsoft.OpenApi.Interfaces; + +/// +/// Represents an Extensible Open API element elements can be rad from. +/// +public interface IOpenApiReadOnlyExtensible +{ + /// + /// Specification extensions. + /// + IDictionary Extensions { get; } + +} diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceHolder.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceHolder.cs new file mode 100644 index 000000000..8883a90f5 --- /dev/null +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceHolder.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.OpenApi.Models; + +namespace Microsoft.OpenApi.Interfaces +{ + /// + /// A generic interface for OpenApiReferenceable objects that have a target. + /// + /// The type of the target being referenced + /// The type of the interface implemented by both the target and the reference type + public interface IOpenApiReferenceHolder : IOpenApiReferenceHolder where T : IOpenApiReferenceable, V + { + /// + /// Gets the resolved target object. + /// + T Target { get; } + /// + /// Copy the reference as a target element with overrides. + /// + V CopyReferenceAsTargetElementWithOverrides(V source); + } + /// + /// A generic interface for OpenApiReferenceable objects that have a target. + /// + public interface IOpenApiReferenceHolder : IOpenApiSerializable + { + /// + /// Indicates if object is populated with data or is just a reference to the data + /// + bool UnresolvedReference { get; } + + /// + /// Reference object. + /// + OpenApiReference Reference { get; init; } + } +} diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs index 43088bf6b..38e888dc8 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using Microsoft.OpenApi.Models; - namespace Microsoft.OpenApi.Interfaces { /// @@ -10,14 +8,5 @@ namespace Microsoft.OpenApi.Interfaces /// public interface IOpenApiReferenceable : IOpenApiSerializable { - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - bool UnresolvedReference { get; set; } - - /// - /// Reference object. - /// - OpenApiReference Reference { get; set; } } } diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceableWithTarget.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceableWithTarget.cs deleted file mode 100644 index fc4c1daed..000000000 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceableWithTarget.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -namespace Microsoft.OpenApi.Interfaces -{ - /// - /// A generic interface for OpenApiReferenceable objects that have a target. - /// - /// - public interface IOpenApiReferenceableWithTarget : IOpenApiReferenceable - { - /// - /// Gets the resolved target object. - /// - T Target { get; } - } -} diff --git a/src/Microsoft.OpenApi/Interfaces/IShallowCopyable.cs b/src/Microsoft.OpenApi/Interfaces/IShallowCopyable.cs new file mode 100644 index 000000000..c1327bf0f --- /dev/null +++ b/src/Microsoft.OpenApi/Interfaces/IShallowCopyable.cs @@ -0,0 +1,12 @@ +namespace Microsoft.OpenApi.Interfaces; +/// +/// Interface for shallow copyable objects. +/// +/// The type of the resulting object +public interface IShallowCopyable +{ + /// + /// Create a shallow copy of the current instance. + /// + T CreateShallowCopy(); +} diff --git a/src/Microsoft.OpenApi/IsExternalInit.cs b/src/Microsoft.OpenApi/IsExternalInit.cs new file mode 100644 index 000000000..9c8e2ad1a --- /dev/null +++ b/src/Microsoft.OpenApi/IsExternalInit.cs @@ -0,0 +1,13 @@ +//TODO remove this if we ever remove the netstandard2.0 target +#if !NET5_0_OR_GREATER +namespace System.Runtime.CompilerServices { + using System.ComponentModel; + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit { + } +} +#endif diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index 46cb80f08..6a402478f 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -3,7 +3,6 @@ netstandard2.0;net8.0 Latest true - 2.0.0-preview5 .NET models with JSON and YAML writers for OpenAPI specification true true diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiCallback.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiCallback.cs new file mode 100644 index 000000000..a8a818d33 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiCallback.cs @@ -0,0 +1,18 @@ + +using System.Collections.Generic; +using Microsoft.OpenApi.Expressions; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the callback object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiCallback : IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// A Path Item Object used to define a callback request and expected responses. + /// + public Dictionary PathItems { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs new file mode 100644 index 000000000..3deee3d3c --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs @@ -0,0 +1,27 @@ +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Describes an element that has a description. +/// +public interface IOpenApiDescribedElement : IOpenApiElement +{ + /// + /// Long description for the example. + /// CommonMark syntax MAY be used for rich text representation. + /// + public string Description { get; set; } +} + +/// +/// Describes an element that has a description. +/// +public interface IOpenApiReadOnlyDescribedElement : IOpenApiElement +{ + /// + /// Long description for the example. + /// CommonMark syntax MAY be used for rich text representation. + /// + public string Description { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs new file mode 100644 index 000000000..ece8b48ad --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the example object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiExample : IOpenApiDescribedElement, IOpenApiSummarizedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// Embedded literal example. The value field and externalValue field are mutually + /// exclusive. To represent examples of media types that cannot naturally represented + /// in JSON or YAML, use a string value to contain the example, escaping where necessary. + /// + public JsonNode Value { get; } + + /// + /// A URL that points to the literal example. + /// This provides the capability to reference examples that cannot easily be + /// included in JSON or YAML documents. + /// The value field and externalValue field are mutually exclusive. + /// + public string ExternalValue { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs new file mode 100644 index 000000000..35b6cdfe9 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs @@ -0,0 +1,65 @@ + +using System.Collections.Generic; +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the headers object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// Determines whether this header is mandatory. + /// + public bool Required { get; } + + /// + /// Specifies that a header is deprecated and SHOULD be transitioned out of usage. + /// + public bool Deprecated { get; } + + /// + /// Sets the ability to pass empty-valued headers. + /// + public bool AllowEmptyValue { get; } + + /// + /// Describes how the header value will be serialized depending on the type of the header value. + /// + public ParameterStyle? Style { get; } + + /// + /// When this is true, header values of type array or object generate separate parameters + /// for each value of the array or key-value pair of the map. + /// + public bool Explode { get; } + + /// + /// Determines whether the header value SHOULD allow reserved characters, as defined by RFC3986. + /// + public bool AllowReserved { get; } + + /// + /// The schema defining the type used for the request body. + /// + public IOpenApiSchema Schema { get; } + + /// + /// Example of the media type. + /// + public JsonNode Example { get; } + + /// + /// Examples of the media type. + /// + public IDictionary Examples { get; } + + /// + /// A map containing the representations for the header. + /// + public IDictionary Content { get; } + +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiLink.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiLink.cs new file mode 100644 index 000000000..66e8b5e3b --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiLink.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the link object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiLink : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// A relative or absolute reference to an OAS operation. + /// This field is mutually exclusive of the operationId field, and MUST point to an Operation Object. + /// + public string OperationRef { get; } + + /// + /// The name of an existing, resolvable OAS operation, as defined with a unique operationId. + /// This field is mutually exclusive of the operationRef field. + /// + public string OperationId { get; } + + /// + /// A map representing parameters to pass to an operation as specified with operationId or identified via operationRef. + /// + public IDictionary Parameters { get; } + + /// + /// A literal value or {expression} to use as a request body when calling the target operation. + /// + public RuntimeExpressionAnyWrapper RequestBody { get; } + /// + /// A server object to be used by the target operation. + /// + public OpenApiServer Server { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs new file mode 100644 index 000000000..465078e43 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the parameter object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// REQUIRED. The name of the parameter. Parameter names are case sensitive. + /// If in is "path", the name field MUST correspond to the associated path segment from the path field in the Paths Object. + /// If in is "header" and the name field is "Accept", "Content-Type" or "Authorization", the parameter definition SHALL be ignored. + /// For all other cases, the name corresponds to the parameter name used by the in property. + /// + public string Name { get; } + + /// + /// REQUIRED. The location of the parameter. + /// Possible values are "query", "header", "path" or "cookie". + /// + public ParameterLocation? In { get; } + + /// + /// Determines whether this parameter is mandatory. + /// If the parameter location is "path", this property is REQUIRED and its value MUST be true. + /// Otherwise, the property MAY be included and its default value is false. + /// + public bool Required { get; } + + /// + /// Specifies that a parameter is deprecated and SHOULD be transitioned out of usage. + /// + public bool Deprecated { get; } + + /// + /// Sets the ability to pass empty-valued parameters. + /// This is valid only for query parameters and allows sending a parameter with an empty value. + /// Default value is false. + /// If style is used, and if behavior is n/a (cannot be serialized), + /// the value of allowEmptyValue SHALL be ignored. + /// + public bool AllowEmptyValue { get; } + + /// + /// Describes how the parameter value will be serialized depending on the type of the parameter value. + /// Default values (based on value of in): for query - form; for path - simple; for header - simple; + /// for cookie - form. + /// + public ParameterStyle? Style { get; } + + /// + /// When this is true, parameter values of type array or object generate separate parameters + /// for each value of the array or key-value pair of the map. + /// For other types of parameters this property has no effect. + /// When style is form, the default value is true. + /// For all other styles, the default value is false. + /// + public bool Explode { get; } + + /// + /// Determines whether the parameter value SHOULD allow reserved characters, + /// as defined by RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding. + /// This property only applies to parameters with an in value of query. + /// The default value is false. + /// + public bool AllowReserved { get; } + + /// + /// The schema defining the type used for the parameter. + /// + public IOpenApiSchema Schema { get; } + + /// + /// Examples of the media type. Each example SHOULD contain a value + /// in the correct format as specified in the parameter encoding. + /// The examples object is mutually exclusive of the example object. + /// Furthermore, if referencing a schema which contains an example, + /// the examples value SHALL override the example provided by the schema. + /// + public IDictionary Examples { get; } + + /// + /// Example of the media type. The example SHOULD match the specified schema and encoding properties + /// if present. The example object is mutually exclusive of the examples object. + /// Furthermore, if referencing a schema which contains an example, + /// the example value SHALL override the example provided by the schema. + /// To represent examples of media types that cannot naturally be represented in JSON or YAML, + /// a string value can contain the example with escaping where necessary. + /// + public JsonNode Example { get; } + + /// + /// A map containing the representations for the parameter. + /// The key is the media type and the value describes it. + /// The map MUST only contain one entry. + /// For more complex scenarios, the content property can define the media type and schema of the parameter. + /// A parameter MUST contain either a schema property, or a content property, but not both. + /// When example or examples are provided in conjunction with the schema object, + /// the example MUST follow the prescribed serialization strategy for the parameter. + /// + public IDictionary Content { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiPathItem.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiPathItem.cs new file mode 100644 index 000000000..bbc316a14 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiPathItem.cs @@ -0,0 +1,28 @@ + +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the path item object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiPathItem : IOpenApiDescribedElement, IOpenApiSummarizedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// Gets the definition of operations on this path. + /// + public IDictionary Operations { get; } + + /// + /// An alternative server array to service all operations in this path. + /// + public IList Servers { get; } + + /// + /// A list of parameters that are applicable for all the operations described under this path. + /// These parameters can be overridden at the operation level, but cannot be removed there. + /// + public IList Parameters { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs new file mode 100644 index 000000000..84afff156 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the request body object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// Determines if the request body is required in the request. Defaults to false. + /// + public bool Required { get; } + + /// + /// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it. + /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* + /// + public IDictionary Content { get; } + /// + /// Converts the request body to a body parameter in preparation for a v2 serialization. + /// + /// The writer to use to read settings from. + /// The converted OpenAPI parameter + IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer); + /// + /// Converts the request body to a set of form data parameters in preparation for a v2 serialization. + /// + /// The writer to use to read settings from + /// The converted OpenAPI parameters + IEnumerable ConvertToFormDataParameters(IOpenApiWriter writer); +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs new file mode 100644 index 000000000..3df66eec0 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the response object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// Maps a header name to its definition. + /// + public IDictionary Headers { get; } + + /// + /// A map containing descriptions of potential response payloads. + /// The key is a media type or media type range and the value describes it. + /// + public IDictionary Content { get; } + + /// + /// A map of operations links that can be followed from the response. + /// The key of the map is a short name for the link, + /// following the naming constraints of the names for Component Objects. + /// + public IDictionary Links { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs new file mode 100644 index 000000000..9ff8e8389 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs @@ -0,0 +1,302 @@ +using System.Collections.Generic; +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the schema object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiSchema : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + + /// + /// Follow JSON Schema definition. Short text providing information about the data. + /// + public string Title { get; } + + /// + /// $schema, a JSON Schema dialect identifier. Value must be a URI + /// + public string Schema { get; } + + /// + /// $id - Identifies a schema resource with its canonical URI. + /// + public string Id { get; } + + /// + /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema. + /// + public string Comment { get; } + + /// + /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema. + /// + public IDictionary Vocabulary { get; } + + /// + /// $dynamicRef - an applicator that allows for deferring the full resolution until runtime, at which point it is resolved each time it is encountered while evaluating an instance + /// + public string DynamicRef { get; } + + /// + /// $dynamicAnchor - used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing. + /// + public string DynamicAnchor { get; } + + /// + /// $defs - reserves a location for schema authors to inline re-usable JSON Schemas into a more general schema. + /// The keyword does not directly affect the validation result + /// + public IDictionary Definitions { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? V31ExclusiveMaximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? V31ExclusiveMinimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool UnEvaluatedProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value MUST be a string in V2 and V3. + /// + public JsonSchemaType? Type { get; } + + /// + /// Follow JSON Schema definition: https://json-schema.org/draft/2020-12/json-schema-validation + /// + public string Const { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// While relying on JSON Schema's defined formats, + /// the OAS offers a few additional predefined formats. + /// + public string Format { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? Maximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? ExclusiveMaximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? Minimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? ExclusiveMinimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxLength { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinLength { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect + /// + public string Pattern { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? MultipleOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. + /// Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. + /// For example, if type is string, then default can be "foo" but cannot be 1. + /// + public JsonNode Default { get; } + + /// + /// Relevant only for Schema "properties" definitions. Declares the property as "read only". + /// This means that it MAY be sent as part of a response but SHOULD NOT be sent as part of the request. + /// If the property is marked as readOnly being true and is in the required list, + /// the required will take effect on the response only. + /// A property MUST NOT be marked as both readOnly and writeOnly being true. + /// Default value is false. + /// + public bool ReadOnly { get; } + + /// + /// Relevant only for Schema "properties" definitions. Declares the property as "write only". + /// Therefore, it MAY be sent as part of a request but SHOULD NOT be sent as part of the response. + /// If the property is marked as writeOnly being true and is in the required list, + /// the required will take effect on the request only. + /// A property MUST NOT be marked as both readOnly and writeOnly being true. + /// Default value is false. + /// + public bool WriteOnly { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList AllOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList OneOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList AnyOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IOpenApiSchema Not { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public ISet Required { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value MUST be an object and not an array. Inline or referenced schema MUST be of a Schema Object + /// and not a standard JSON Schema. items MUST be present if the type is array. + /// + public IOpenApiSchema Items { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? UniqueItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Property definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced). + /// + public IDictionary Properties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// PatternProperty definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced) + /// Each property name of this object SHOULD be a valid regular expression according to the ECMA 262 r + /// egular expression dialect. Each property value of this object MUST be an object, and each object MUST + /// be a valid Schema Object not a standard JSON Schema. + /// + public IDictionary PatternProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinProperties { get; } + + /// + /// Indicates if the schema can contain properties other than those defined by the properties map. + /// + public bool AdditionalPropertiesAllowed { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value can be boolean or object. Inline or referenced schema + /// MUST be of a Schema Object and not a standard JSON Schema. + /// + public IOpenApiSchema AdditionalProperties { get; } + + /// + /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate + /// between other schemas which may satisfy the payload description. + /// + public OpenApiDiscriminator Discriminator { get; } + + /// + /// A free-form property to include an example of an instance for this schema. + /// To represent examples that cannot be naturally represented in JSON or YAML, + /// a string value can be used to contain the example with escaping where necessary. + /// + public JsonNode Example { get; } + + /// + /// A free-form property to include examples of an instance for this schema. + /// To represent examples that cannot be naturally represented in JSON or YAML, + /// a list of values can be used to contain the examples with escaping where necessary. + /// + public IList Examples { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public IList Enum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool UnevaluatedProperties { get; } + + /// + /// Additional external documentation for this schema. + /// + public OpenApiExternalDocs ExternalDocs { get; } + + /// + /// Specifies that a schema is deprecated and SHOULD be transitioned out of usage. + /// Default value is false. + /// + public bool Deprecated { get; } + + /// + /// This MAY be used only on properties schemas. It has no effect on root schemas. + /// Adds additional metadata to describe the XML representation of this property. + /// + public OpenApiXml Xml { get; } + + /// + /// This object stores any unrecognized keywords found in the schema. + /// + public IDictionary UnrecognizedKeywords { get; } + + /// + /// Any annotation to attach to the schema to be used by the application. + /// Annotations are NOT (de)serialized with the schema and can be used for custom properties. + /// + public IDictionary Annotations { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSecurityScheme.cs new file mode 100644 index 000000000..9580a3dad --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSecurityScheme.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the security scheme object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiSecurityScheme : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// REQUIRED. The type of the security scheme. Valid values are "apiKey", "http", "oauth2", "openIdConnect". + /// + public SecuritySchemeType? Type { get; } + + /// + /// REQUIRED. The name of the header, query or cookie parameter to be used. + /// + public string Name { get; } + + /// + /// REQUIRED. The location of the API key. Valid values are "query", "header" or "cookie". + /// + public ParameterLocation? In { get; } + + /// + /// REQUIRED. The name of the HTTP Authorization scheme to be used + /// in the Authorization header as defined in RFC7235. + /// + public string Scheme { get; } + + /// + /// A hint to the client to identify how the bearer token is formatted. + /// Bearer tokens are usually generated by an authorization server, + /// so this information is primarily for documentation purposes. + /// + public string BearerFormat { get; } + + /// + /// REQUIRED. An object containing configuration information for the flow types supported. + /// + public OpenApiOAuthFlows Flows { get; } + + /// + /// REQUIRED. OpenId Connect URL to discover OAuth2 configuration values. + /// + public Uri OpenIdConnectUrl { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSummarizedElement.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSummarizedElement.cs new file mode 100644 index 000000000..3273b03f5 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSummarizedElement.cs @@ -0,0 +1,13 @@ +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; +/// +/// Describes an element that has a summary. +/// +public interface IOpenApiSummarizedElement : IOpenApiElement +{ + /// + /// Short description for the example. + /// + public string Summary { get; set; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiTag.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiTag.cs new file mode 100644 index 000000000..c2a6d8523 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiTag.cs @@ -0,0 +1,20 @@ +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the path item object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiTag : IOpenApiSerializable, IOpenApiReadOnlyExtensible, IOpenApiReadOnlyDescribedElement, IShallowCopyable +{ + /// + /// The name of the tag. + /// + public string Name { get; } + + /// + /// Additional external documentation for this tag. + /// + public OpenApiExternalDocs ExternalDocs { get; } +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs index f538d90c0..96f5c5cf4 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Expressions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -12,28 +13,17 @@ namespace Microsoft.OpenApi.Models /// /// Callback Object: A map of possible out-of band callbacks related to the parent operation. /// - public class OpenApiCallback : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiCallback : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiCallback { - /// - /// A Path Item Object used to define a callback request and expected responses. - /// - public virtual Dictionary PathItems { get; set; } - = new(); - - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public virtual bool UnresolvedReference { get; set; } + /// + public Dictionary PathItems { get; set; } + = []; - /// - /// Reference pointer. - /// - public OpenApiReference Reference { get; set; } /// /// This object MAY be extended with Specification Extensions. /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameter-less constructor @@ -43,20 +33,19 @@ public OpenApiCallback() { } /// /// Initializes a copy of an object /// - public OpenApiCallback(OpenApiCallback callback) + internal OpenApiCallback(IOpenApiCallback callback) { + Utils.CheckArgumentNull(callback); PathItems = callback?.PathItems != null ? new(callback?.PathItems) : null; - UnresolvedReference = callback?.UnresolvedReference ?? UnresolvedReference; - Reference = callback?.Reference != null ? new(callback?.Reference) : null; Extensions = callback?.Extensions != null ? new Dictionary(callback.Extensions) : null; } /// - /// Add a into the . + /// Add a into the . /// /// The runtime expression. /// The path item. - public void AddPathItem(RuntimeExpression expression, OpenApiPathItem pathItem) + public void AddPathItem(RuntimeExpression expression, IOpenApiPathItem pathItem) { Utils.CheckArgumentNull(expression); Utils.CheckArgumentNull(pathItem); @@ -71,7 +60,7 @@ public void AddPathItem(RuntimeExpression expression, OpenApiPathItem pathItem) /// /// /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } @@ -79,7 +68,7 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } @@ -110,5 +99,11 @@ public void SerializeAsV2(IOpenApiWriter writer) { // Callback object does not exist in V2. } + + /// + public IOpenApiCallback CreateShallowCopy() + { + return new OpenApiCallback(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index 5b43b5187..250254212 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; @@ -17,62 +18,62 @@ namespace Microsoft.OpenApi.Models public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible { /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public IDictionary? Schemas { get; set; } = new Dictionary(); + public IDictionary? Schemas { get; set; } = new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public virtual IDictionary? Responses { get; set; } = new Dictionary(); + public IDictionary? Responses { get; set; } = new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public virtual IDictionary? Parameters { get; set; } = - new Dictionary(); + public IDictionary? Parameters { get; set; } = + new Dictionary(); /// /// An object to hold reusable Objects. /// - public virtual IDictionary? Examples { get; set; } = new Dictionary(); + public IDictionary? Examples { get; set; } = new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public virtual IDictionary? RequestBodies { get; set; } = - new Dictionary(); + public IDictionary? RequestBodies { get; set; } = + new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public virtual IDictionary? Headers { get; set; } = new Dictionary(); + public IDictionary? Headers { get; set; } = new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public virtual IDictionary? SecuritySchemes { get; set; } = - new Dictionary(); + public IDictionary? SecuritySchemes { get; set; } = + new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public virtual IDictionary? Links { get; set; } = new Dictionary(); + public IDictionary? Links { get; set; } = new Dictionary(); /// /// An object to hold reusable Objects. /// - public virtual IDictionary? Callbacks { get; set; } = new Dictionary(); + public IDictionary? Callbacks { get; set; } = new Dictionary(); /// - /// An object to hold reusable Object. + /// An object to hold reusable Object. /// - public virtual IDictionary? PathItems { get; set; } = new Dictionary(); + public IDictionary? PathItems { get; set; } = new Dictionary(); /// /// This object MAY be extended with Specification Extensions. /// - public virtual IDictionary? Extensions { get; set; } = new Dictionary(); + public IDictionary? Extensions { get; set; } = new Dictionary(); /// /// Parameter-less constructor @@ -84,16 +85,16 @@ public OpenApiComponents() { } /// public OpenApiComponents(OpenApiComponents? components) { - Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null; - Responses = components?.Responses != null ? new Dictionary(components.Responses) : null; - Parameters = components?.Parameters != null ? new Dictionary(components.Parameters) : null; - Examples = components?.Examples != null ? new Dictionary(components.Examples) : null; - RequestBodies = components?.RequestBodies != null ? new Dictionary(components.RequestBodies) : null; - Headers = components?.Headers != null ? new Dictionary(components.Headers) : null; - SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary(components.SecuritySchemes) : null; - Links = components?.Links != null ? new Dictionary(components.Links) : null; - Callbacks = components?.Callbacks != null ? new Dictionary(components.Callbacks) : null; - PathItems = components?.PathItems != null ? new Dictionary(components.PathItems) : null; + Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null; + Responses = components?.Responses != null ? new Dictionary(components.Responses) : null; + Parameters = components?.Parameters != null ? new Dictionary(components.Parameters) : null; + Examples = components?.Examples != null ? new Dictionary(components.Examples) : null; + RequestBodies = components?.RequestBodies != null ? new Dictionary(components.RequestBodies) : null; + Headers = components?.Headers != null ? new Dictionary(components.Headers) : null; + SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary(components.SecuritySchemes) : null; + Links = components?.Links != null ? new Dictionary(components.Links) : null; + Callbacks = components?.Callbacks != null ? new Dictionary(components.Callbacks) : null; + PathItems = components?.PathItems != null ? new Dictionary(components.PathItems) : null; Extensions = components?.Extensions != null ? new Dictionary(components.Extensions) : null; } @@ -160,7 +161,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// Serialize . /// private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, - Action callback, Action action) + Action callback, Action action) { // Serialize each referenceable object as full object without reference if the reference in the object points to itself. // If the reference exists but points to other objects, the object is serialized to just that reference. diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 1ce80f092..7820a6f8e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Services; @@ -25,6 +26,13 @@ namespace Microsoft.OpenApi.Models /// public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenApiAnnotatable { + /// + /// Register components in the document to the workspace + /// + public void RegisterComponents() + { + Workspace?.RegisterComponents(this); + } /// /// Related workspace containing components that are referenced in a document /// @@ -55,7 +63,7 @@ public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenAp /// A map of requests initiated other than by an API call, for example by an out of band registration. /// The key name is a unique string to refer to each webhook, while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider and the expected responses /// - public IDictionary? Webhooks { get; set; } = new Dictionary(); + public IDictionary? Webhooks { get; set; } = new Dictionary(); /// /// An element to hold various schemas for the specification. @@ -112,7 +120,7 @@ public OpenApiDocument(OpenApiDocument? document) JsonSchemaDialect = document?.JsonSchemaDialect ?? JsonSchemaDialect; Servers = document?.Servers != null ? new List(document.Servers) : null; Paths = document?.Paths != null ? new(document?.Paths) : new OpenApiPaths(); - Webhooks = document?.Webhooks != null ? new Dictionary(document.Webhooks) : null; + Webhooks = document?.Webhooks != null ? new Dictionary(document.Webhooks) : null; Components = document?.Components != null ? new(document?.Components) : null; SecurityRequirements = document?.SecurityRequirements != null ? new List(document.SecurityRequirements) : null; Tags = document?.Tags != null ? new List(document.Tags) : null; @@ -238,10 +246,10 @@ public void SerializeAsV2(IOpenApiWriter writer) { var loops = writer.GetSettings().LoopDetector.Loops; - if (loops.TryGetValue(typeof(OpenApiSchema), out var schemas)) + if (loops.TryGetValue(typeof(IOpenApiSchema), out var schemas)) { - var openApiSchemas = schemas.Cast().Distinct().ToList() - .ToDictionary(k => k.Reference.Id); + var openApiSchemas = schemas.Cast().Distinct().OfType() + .ToDictionary(k => k.Reference.Id, v => v); foreach (var schema in openApiSchemas.Values.ToList()) { @@ -276,14 +284,14 @@ public void SerializeAsV2(IOpenApiWriter writer) // parameters var parameters = Components?.Parameters != null - ? new Dictionary(Components.Parameters) - : new Dictionary(); + ? new Dictionary(Components.Parameters) + : []; if (Components?.RequestBodies != null) { foreach (var requestBody in Components.RequestBodies.Where(b => !parameters.ContainsKey(b.Key))) { - parameters.Add(requestBody.Key, requestBody.Value.ConvertToBodyParameter()); + parameters.Add(requestBody.Key, requestBody.Value.ConvertToBodyParameter(writer)); } } writer.WriteOptionalMap( @@ -388,7 +396,7 @@ private static void WriteHostInfoV2(IOpenApiWriter writer, IList? else { var relativeUrl = firstServerUrl.OriginalString; - if (relativeUrl.StartsWith("//")) + if (relativeUrl.StartsWith("//", StringComparison.OrdinalIgnoreCase)) { var pathPosition = relativeUrl.IndexOf('/', 3); writer.WriteProperty(OpenApiConstants.Host, relativeUrl.Substring(0, pathPosition)); @@ -586,44 +594,44 @@ public bool AddComponent(string id, T componentToRegister) Components ??= new(); switch (componentToRegister) { - case OpenApiSchema openApiSchema: - Components.Schemas ??= new Dictionary(); + case IOpenApiSchema openApiSchema: + Components.Schemas ??= new Dictionary(); Components.Schemas.Add(id, openApiSchema); break; - case OpenApiParameter openApiParameter: - Components.Parameters ??= new Dictionary(); + case IOpenApiParameter openApiParameter: + Components.Parameters ??= new Dictionary(); Components.Parameters.Add(id, openApiParameter); break; - case OpenApiResponse openApiResponse: - Components.Responses ??= new Dictionary(); + case IOpenApiResponse openApiResponse: + Components.Responses ??= new Dictionary(); Components.Responses.Add(id, openApiResponse); break; - case OpenApiRequestBody openApiRequestBody: - Components.RequestBodies ??= new Dictionary(); + case IOpenApiRequestBody openApiRequestBody: + Components.RequestBodies ??= new Dictionary(); Components.RequestBodies.Add(id, openApiRequestBody); break; - case OpenApiLink openApiLink: - Components.Links ??= new Dictionary(); + case IOpenApiLink openApiLink: + Components.Links ??= new Dictionary(); Components.Links.Add(id, openApiLink); break; - case OpenApiCallback openApiCallback: - Components.Callbacks ??= new Dictionary(); + case IOpenApiCallback openApiCallback: + Components.Callbacks ??= new Dictionary(); Components.Callbacks.Add(id, openApiCallback); break; - case OpenApiPathItem openApiPathItem: - Components.PathItems ??= new Dictionary(); + case IOpenApiPathItem openApiPathItem: + Components.PathItems ??= new Dictionary(); Components.PathItems.Add(id, openApiPathItem); break; - case OpenApiExample openApiExample: - Components.Examples ??= new Dictionary(); + case IOpenApiExample openApiExample: + Components.Examples ??= new Dictionary(); Components.Examples.Add(id, openApiExample); break; - case OpenApiHeader openApiHeader: - Components.Headers ??= new Dictionary(); + case IOpenApiHeader openApiHeader: + Components.Headers ??= new Dictionary(); Components.Headers.Add(id, openApiHeader); break; - case OpenApiSecurityScheme openApiSecurityScheme: - Components.SecuritySchemes ??= new Dictionary(); + case IOpenApiSecurityScheme openApiSecurityScheme: + Components.SecuritySchemes ??= new Dictionary(); Components.SecuritySchemes.Add(id, openApiSecurityScheme); break; default: @@ -635,9 +643,9 @@ public bool AddComponent(string id, T componentToRegister) internal class FindSchemaReferences : OpenApiVisitorBase { - private Dictionary Schemas = new(); + private Dictionary Schemas = new(StringComparer.Ordinal); - public static void ResolveSchemas(OpenApiComponents? components, Dictionary schemas) + public static void ResolveSchemas(OpenApiComponents? components, Dictionary schemas) { var visitor = new FindSchemaReferences(); visitor.Schemas = schemas; @@ -645,11 +653,12 @@ public static void ResolveSchemas(OpenApiComponents? components, Dictionary + public override void Visit(IOpenApiReferenceHolder referenceHolder) { - switch (referenceable) + switch (referenceHolder) { - case OpenApiSchema schema: + case OpenApiSchemaReference schema: if (!Schemas.ContainsKey(schema.Reference.Id)) { Schemas.Add(schema.Reference.Id, schema); @@ -659,15 +668,15 @@ public override void Visit(IOpenApiReferenceable referenceable) default: break; } - base.Visit(referenceable); + base.Visit(referenceHolder); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { // This is needed to handle schemas used in Responses in components - if (schema.Reference != null && !Schemas.ContainsKey(schema.Reference.Id)) + if (schema is OpenApiSchemaReference {Reference: not null} schemaReference && !Schemas.ContainsKey(schemaReference.Reference.Id)) { - Schemas.Add(schema.Reference.Id, schema); + Schemas.Add(schemaReference.Reference.Id, schema); } base.Visit(schema); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs b/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs index 9ab0e7468..bb8bfab17 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -24,7 +25,7 @@ public class OpenApiEncoding : IOpenApiSerializable, IOpenApiExtensible /// /// A map allowing additional information to be provided as headers. /// - public IDictionary Headers { get; set; } = new Dictionary(); + public IDictionary Headers { get; set; } = new Dictionary(); /// /// Describes how a specific property value will be serialized depending on its type. @@ -64,7 +65,7 @@ public OpenApiEncoding() { } public OpenApiEncoding(OpenApiEncoding encoding) { ContentType = encoding?.ContentType ?? ContentType; - Headers = encoding?.Headers != null ? new Dictionary(encoding.Headers) : null; + Headers = encoding?.Headers != null ? new Dictionary(encoding.Headers) : null; Style = encoding?.Style ?? Style; Explode = encoding?.Explode ?? Explode; AllowReserved = encoding?.AllowReserved ?? AllowReserved; diff --git a/src/Microsoft.OpenApi/Models/OpenApiExample.cs b/src/Microsoft.OpenApi/Models/OpenApiExample.cs index 1fc7ca900..bdfd42f4e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExample.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExample.cs @@ -5,6 +5,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -12,48 +13,22 @@ namespace Microsoft.OpenApi.Models /// /// Example Object. /// - public class OpenApiExample : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiExample : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiExample { - /// - /// Short description for the example. - /// - public virtual string Summary { get; set; } + /// + public string Summary { get; set; } - /// - /// Long description for the example. - /// CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } - - /// - /// Embedded literal example. The value field and externalValue field are mutually - /// exclusive. To represent examples of media types that cannot naturally represented - /// in JSON or YAML, use a string value to contain the example, escaping where necessary. - /// - public virtual JsonNode Value { get; set; } + /// + public string Description { get; set; } - /// - /// A URL that points to the literal example. - /// This provides the capability to reference examples that cannot easily be - /// included in JSON or YAML documents. - /// The value field and externalValue field are mutually exclusive. - /// - public virtual string ExternalValue { get; set; } + /// + public string ExternalValue { get; set; } - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public JsonNode Value { get; set; } - /// - /// Reference object. - /// - public virtual OpenApiReference Reference { get; set; } - - /// - /// Indicates object is a placeholder reference to an actual object and does not contain valid data. - /// - public virtual bool UnresolvedReference { get; set; } = false; + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameter-less constructor @@ -63,41 +38,30 @@ public OpenApiExample() { } /// /// Initializes a copy of object /// - public OpenApiExample(OpenApiExample example) + /// The object + internal OpenApiExample(IOpenApiExample example) { - Summary = example?.Summary ?? Summary; - Description = example?.Description ?? Description; - Value = example?.Value != null ? JsonNodeCloneHelper.Clone(example.Value) : null; - ExternalValue = example?.ExternalValue ?? ExternalValue; - Extensions = example?.Extensions != null ? new Dictionary(example.Extensions) : null; - Reference = example?.Reference != null ? new(example.Reference) : null; - UnresolvedReference = example?.UnresolvedReference ?? UnresolvedReference; + Utils.CheckArgumentNull(example); + Summary = example.Summary ?? Summary; + Description = example.Description ?? Description; + Value = example.Value != null ? JsonNodeCloneHelper.Clone(example.Value) : null; + ExternalValue = example.ExternalValue ?? ExternalValue; + Extensions = example.Extensions != null ? new Dictionary(example.Extensions) : null; } - /// - /// Serialize to Open Api v3.1 - /// - /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + /// + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1); } - /// - /// Serialize to Open Api v3.0 - /// - /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + /// + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0); } - /// - /// Writes out existing examples in a mediatype object - /// - /// - /// - public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version) + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version) { Utils.CheckArgumentNull(writer); @@ -121,14 +85,16 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version) writer.WriteEndObject(); } - /// - /// Serialize to Open Api v2.0 - /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + /// + public void SerializeAsV2(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi2_0); + } + + /// + public IOpenApiExample CreateShallowCopy() { - // Example object of this form does not exist in V2. - // V2 Example object requires knowledge of media type and exists only - // in Response object, so it will be serialized as a part of the Response object. + return new OpenApiExample(this); } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index 268878b1b..dd7a0ec84 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -7,6 +7,8 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -15,84 +17,43 @@ namespace Microsoft.OpenApi.Models /// Header Object. /// The Header Object follows the structure of the Parameter Object. /// - public class OpenApiHeader : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiHeader : IOpenApiHeader, IOpenApiReferenceable, IOpenApiExtensible { - private OpenApiSchema _schema; + /// + public string Description { get; set; } - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public virtual bool UnresolvedReference { get; set; } + /// + public bool Required { get; set; } - /// - /// Reference pointer. - /// - public OpenApiReference Reference { get; set; } + /// + public bool Deprecated { get; set; } - /// - /// A brief description of the header. - /// - public virtual string Description { get; set; } + /// + public bool AllowEmptyValue { get; set; } - /// - /// Determines whether this header is mandatory. - /// - public virtual bool Required { get; set; } + /// + public ParameterStyle? Style { get; set; } - /// - /// Specifies that a header is deprecated and SHOULD be transitioned out of usage. - /// - public virtual bool Deprecated { get; set; } + /// + public bool Explode { get; set; } - /// - /// Sets the ability to pass empty-valued headers. - /// - public virtual bool AllowEmptyValue { get; set; } + /// + public bool AllowReserved { get; set; } - /// - /// Describes how the header value will be serialized depending on the type of the header value. - /// - public virtual ParameterStyle? Style { get; set; } + /// + public IOpenApiSchema Schema { get; set; } - /// - /// When this is true, header values of type array or object generate separate parameters - /// for each value of the array or key-value pair of the map. - /// - public virtual bool Explode { get; set; } + /// + public JsonNode Example { get; set; } - /// - /// Determines whether the header value SHOULD allow reserved characters, as defined by RFC3986. - /// - public virtual bool AllowReserved { get; set; } + /// + public IDictionary Examples { get; set; } = new Dictionary(); - /// - /// The schema defining the type used for the request body. - /// - public virtual OpenApiSchema Schema - { - get => _schema; - set => _schema = value; - } + /// + public IDictionary Content { get; set; } = new Dictionary(); - /// - /// Example of the media type. - /// - public virtual JsonNode Example { get; set; } - - /// - /// Examples of the media type. - /// - public virtual IDictionary Examples { get; set; } = new Dictionary(); - - /// - /// A map containing the representations for the header. - /// - public virtual IDictionary Content { get; set; } = new Dictionary(); - - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameter-less constructor @@ -102,28 +63,27 @@ public OpenApiHeader() { } /// /// Initializes a copy of an object /// - public OpenApiHeader(OpenApiHeader header) + internal OpenApiHeader(IOpenApiHeader header) { - UnresolvedReference = header?.UnresolvedReference ?? UnresolvedReference; - Reference = header?.Reference != null ? new(header?.Reference) : null; - Description = header?.Description ?? Description; - Required = header?.Required ?? Required; - Deprecated = header?.Deprecated ?? Deprecated; - AllowEmptyValue = header?.AllowEmptyValue ?? AllowEmptyValue; - Style = header?.Style ?? Style; - Explode = header?.Explode ?? Explode; - AllowReserved = header?.AllowReserved ?? AllowReserved; - _schema = header?.Schema != null ? new(header.Schema) : null; - Example = header?.Example != null ? JsonNodeCloneHelper.Clone(header.Example) : null; - Examples = header?.Examples != null ? new Dictionary(header.Examples) : null; - Content = header?.Content != null ? new Dictionary(header.Content) : null; - Extensions = header?.Extensions != null ? new Dictionary(header.Extensions) : null; + Utils.CheckArgumentNull(header); + Description = header.Description ?? Description; + Required = header.Required; + Deprecated = header.Deprecated; + AllowEmptyValue = header.AllowEmptyValue; + Style = header.Style ?? Style; + Explode = header.Explode; + AllowReserved = header.AllowReserved; + Schema = header.Schema.CreateShallowCopy(); + Example = header.Example != null ? JsonNodeCloneHelper.Clone(header.Example) : null; + Examples = header.Examples != null ? new Dictionary(header.Examples) : null; + Content = header.Content != null ? new Dictionary(header.Content) : null; + Extensions = header.Extensions != null ? new Dictionary(header.Extensions) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV31(writer)); } @@ -131,12 +91,12 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -185,7 +145,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio /// /// Serialize to OpenAPI V2 document without using reference. /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); @@ -213,7 +173,12 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // schema - Schema.WriteAsItemsProperties(writer); + var targetSchema = Schema switch { + OpenApiSchemaReference schemaReference => schemaReference.Target, + OpenApiSchema schema => schema, + _ => null, + }; + targetSchema?.WriteAsItemsProperties(writer); // example writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, s) => w.WriteAny(s)); @@ -223,5 +188,11 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) writer.WriteEndObject(); } + + /// + public IOpenApiHeader CreateShallowCopy() + { + return new OpenApiHeader(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiLink.cs b/src/Microsoft.OpenApi/Models/OpenApiLink.cs index 715826c67..09883b4a2 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLink.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLink.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -11,55 +12,28 @@ namespace Microsoft.OpenApi.Models /// /// Link Object. /// - public class OpenApiLink : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiLink : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiLink { - /// - /// A relative or absolute reference to an OAS operation. - /// This field is mutually exclusive of the operationId field, and MUST point to an Operation Object. - /// - public virtual string OperationRef { get; set; } + /// + public string OperationRef { get; set; } - /// - /// The name of an existing, resolvable OAS operation, as defined with a unique operationId. - /// This field is mutually exclusive of the operationRef field. - /// - public virtual string OperationId { get; set; } + /// + public string OperationId { get; set; } - /// - /// A map representing parameters to pass to an operation as specified with operationId or identified via operationRef. - /// - public virtual Dictionary Parameters { get; set; } = - new(); + /// + public IDictionary Parameters { get; set; } = new Dictionary(); - /// - /// A literal value or {expression} to use as a request body when calling the target operation. - /// - public virtual RuntimeExpressionAnyWrapper RequestBody { get; set; } + /// + public RuntimeExpressionAnyWrapper RequestBody { get; set; } - /// - /// A description of the link. - /// - public virtual string Description { get; set; } + /// + public string Description { get; set; } - /// - /// A server object to be used by the target operation. - /// - public virtual OpenApiServer Server { get; set; } + /// + public OpenApiServer Server { get; set; } - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); - - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public virtual bool UnresolvedReference { get; set; } - - /// - /// Reference pointer. - /// - public OpenApiReference Reference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameterless constructor @@ -69,36 +43,31 @@ public OpenApiLink() { } /// /// Initializes a copy of an object /// - public OpenApiLink(OpenApiLink link) + internal OpenApiLink(IOpenApiLink link) { - OperationRef = link?.OperationRef ?? OperationRef; - OperationId = link?.OperationId ?? OperationId; - Parameters = link?.Parameters != null ? new(link?.Parameters) : null; - RequestBody = link?.RequestBody != null ? new(link?.RequestBody) : null; - Description = link?.Description ?? Description; - Server = link?.Server != null ? new(link?.Server) : null; - Extensions = link?.Extensions != null ? new Dictionary(link.Extensions) : null; - UnresolvedReference = link?.UnresolvedReference ?? UnresolvedReference; - Reference = link?.Reference != null ? new(link?.Reference) : null; + Utils.CheckArgumentNull(link); + OperationRef = link.OperationRef ?? OperationRef; + OperationId = link.OperationId ?? OperationId; + Parameters = link.Parameters != null ? new Dictionary(link.Parameters) : null; + RequestBody = link.RequestBody != null ? new(link.RequestBody) : null; + Description = link.Description ?? Description; + Server = link.Server != null ? new(link.Server) : null; + Extensions = link.Extensions != null ? new Dictionary(link.Extensions) : null; } - /// - /// Serialize to Open Api v3.1 - /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + /// + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); } - /// - /// Serialize to Open Api v3.0 - /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + /// + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, Action callback) + internal void SerializeInternal(IOpenApiWriter writer, Action callback) { Utils.CheckArgumentNull(writer); @@ -128,12 +97,16 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, Action - /// Serialize to Open Api v2.0 - /// + /// public void SerializeAsV2(IOpenApiWriter writer) { // Link object does not exist in V2. } + + /// + public IOpenApiLink CreateShallowCopy() + { + return new OpenApiLink(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 671a0dcfc..7ba469bc6 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -7,6 +7,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; #nullable enable @@ -18,16 +19,10 @@ namespace Microsoft.OpenApi.Models /// public class OpenApiMediaType : IOpenApiSerializable, IOpenApiExtensible { - private OpenApiSchema? _schema; - /// /// The schema defining the type used for the request body. /// - public virtual OpenApiSchema? Schema - { - get => _schema; - set => _schema = value; - } + public IOpenApiSchema? Schema { get; set; } /// /// Example of the media type. @@ -39,7 +34,7 @@ public virtual OpenApiSchema? Schema /// Examples of the media type. /// Each example object SHOULD match the media type and specified schema if present. /// - public IDictionary? Examples { get; set; } = new Dictionary(); + public IDictionary? Examples { get; set; } = new Dictionary(); /// /// A map between a property name and its encoding information. @@ -64,9 +59,9 @@ public OpenApiMediaType() { } /// public OpenApiMediaType(OpenApiMediaType? mediaType) { - _schema = mediaType?.Schema != null ? new(mediaType.Schema) : null; + Schema = mediaType?.Schema?.CreateShallowCopy(); Example = mediaType?.Example != null ? JsonNodeCloneHelper.Clone(mediaType.Example) : null; - Examples = mediaType?.Examples != null ? new Dictionary(mediaType.Examples) : null; + Examples = mediaType?.Examples != null ? new Dictionary(mediaType.Examples) : null; Encoding = mediaType?.Encoding != null ? new Dictionary(mediaType.Encoding) : null; Extensions = mediaType?.Extensions != null ? new Dictionary(mediaType.Extensions) : null; } @@ -93,7 +88,7 @@ public void SerializeAsV3(IOpenApiWriter writer) private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); writer.WriteStartObject(); @@ -126,7 +121,7 @@ public void SerializeAsV2(IOpenApiWriter writer) // Media type does not exist in V2. } - private static void SerializeExamples(IOpenApiWriter writer, IDictionary examples) + private static void SerializeExamples(IOpenApiWriter writer, IDictionary examples) { /* Special case for writing out empty arrays as valid response examples * Check if there is any example with an empty array as its value and set the flag `hasEmptyArray` to true diff --git a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs index efd586e80..3acbd05ab 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; @@ -57,7 +58,7 @@ public class OpenApiOperation : IOpenApiSerializable, IOpenApiExtensible, IOpenA /// The list MUST NOT include duplicated parameters. A unique parameter is defined by a combination of a name and location. /// The list can use the Reference Object to link to parameters that are defined at the OpenAPI Object's components/parameters. /// - public IList? Parameters { get; set; } = new List(); + public IList? Parameters { get; set; } = []; /// /// The request body applicable for this operation. @@ -65,7 +66,7 @@ public class OpenApiOperation : IOpenApiSerializable, IOpenApiExtensible, IOpenA /// has explicitly defined semantics for request bodies. /// In other cases where the HTTP spec is vague, requestBody SHALL be ignored by consumers. /// - public OpenApiRequestBody? RequestBody { get; set; } + public IOpenApiRequestBody? RequestBody { get; set; } /// /// REQUIRED. The list of possible responses as they are returned from executing this operation. @@ -80,7 +81,7 @@ public class OpenApiOperation : IOpenApiSerializable, IOpenApiExtensible, IOpenA /// The key value used to identify the callback object is an expression, evaluated at runtime, /// that identifies a URL to use for the callback operation. /// - public IDictionary? Callbacks { get; set; } = new Dictionary(); + public IDictionary? Callbacks { get; set; } = new Dictionary(); /// /// Declares this operation to be deprecated. Consumers SHOULD refrain from usage of the declared operation. @@ -119,22 +120,23 @@ public OpenApiOperation() { } /// /// Initializes a copy of an object /// - public OpenApiOperation(OpenApiOperation? operation) + public OpenApiOperation(OpenApiOperation operation) { - Tags = operation?.Tags != null ? new List(operation.Tags) : null; - Summary = operation?.Summary ?? Summary; - Description = operation?.Description ?? Description; - ExternalDocs = operation?.ExternalDocs != null ? new(operation?.ExternalDocs) : null; - OperationId = operation?.OperationId ?? OperationId; - Parameters = operation?.Parameters != null ? new List(operation.Parameters) : null; - RequestBody = operation?.RequestBody != null ? new(operation?.RequestBody) : null; - Responses = operation?.Responses != null ? new(operation?.Responses) : null; - Callbacks = operation?.Callbacks != null ? new Dictionary(operation.Callbacks) : null; - Deprecated = operation?.Deprecated ?? Deprecated; - Security = operation?.Security != null ? new List(operation.Security) : null; - Servers = operation?.Servers != null ? new List(operation.Servers) : null; - Extensions = operation?.Extensions != null ? new Dictionary(operation.Extensions) : null; - Annotations = operation?.Annotations != null ? new Dictionary(operation.Annotations) : null; + Utils.CheckArgumentNull(operation); + Tags = operation.Tags != null ? new List(operation.Tags) : null; + Summary = operation.Summary ?? Summary; + Description = operation.Description ?? Description; + ExternalDocs = operation.ExternalDocs != null ? new(operation.ExternalDocs) : null; + OperationId = operation.OperationId ?? OperationId; + Parameters = operation.Parameters != null ? new List(operation.Parameters) : null; + RequestBody = operation.RequestBody?.CreateShallowCopy(); + Responses = operation.Responses != null ? new(operation.Responses) : null; + Callbacks = operation.Callbacks != null ? new Dictionary(operation.Callbacks) : null; + Deprecated = operation.Deprecated; + Security = operation.Security != null ? new List(operation.Security) : null; + Servers = operation.Servers != null ? new List(operation.Servers) : null; + Extensions = operation.Extensions != null ? new Dictionary(operation.Extensions) : null; + Annotations = operation.Annotations != null ? new Dictionary(operation.Annotations) : null; } /// @@ -158,7 +160,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); writer.WriteStartObject(); @@ -212,7 +214,7 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version /// public void SerializeAsV2(IOpenApiWriter writer) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); writer.WriteStartObject(); @@ -234,15 +236,7 @@ public void SerializeAsV2(IOpenApiWriter writer) // operationId writer.WriteProperty(OpenApiConstants.OperationId, OperationId); - List parameters; - if (Parameters == null) - { - parameters = []; - } - else - { - parameters = [.. Parameters]; - } + List parameters = Parameters is null ? new() : new(Parameters); if (RequestBody != null) { @@ -254,17 +248,17 @@ public void SerializeAsV2(IOpenApiWriter writer) if (consumes.Contains("application/x-www-form-urlencoded") || consumes.Contains("multipart/form-data")) { - parameters.AddRange(RequestBody.ConvertToFormDataParameters()); + parameters.AddRange(RequestBody.ConvertToFormDataParameters(writer)); } else { - parameters.Add(RequestBody.ConvertToBodyParameter()); + parameters.Add(RequestBody.ConvertToBodyParameter(writer)); } } - else if (RequestBody.Reference != null && RequestBody.Reference.HostDocument is {} hostDocument) + else if (RequestBody is OpenApiRequestBodyReference requestBodyReference) { parameters.Add( - new OpenApiParameterReference(RequestBody.Reference.Id, hostDocument)); + new OpenApiParameterReference(requestBodyReference.Reference.Id, requestBodyReference.Reference.HostDocument)); } if (consumes.Count > 0) @@ -284,10 +278,7 @@ public void SerializeAsV2(IOpenApiWriter writer) var produces = Responses .Where(static r => r.Value.Content != null) .SelectMany(static r => r.Value.Content?.Keys ?? []) - .Concat( - Responses - .Where(static r => r.Value.Reference is {HostDocument: not null}) - .SelectMany(static r => r.Value.Content?.Keys ?? [])) + .Where(static m => !string.IsNullOrEmpty(m)) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index bdaba739e..0f1d7c03a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -8,6 +8,8 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -15,138 +17,60 @@ namespace Microsoft.OpenApi.Models /// /// Parameter Object. /// - public class OpenApiParameter : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiParameter : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiParameter { private bool? _explode; private ParameterStyle? _style; - private OpenApiSchema _schema; - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public virtual bool UnresolvedReference { get; set; } + /// + public string Name { get; set; } - /// - /// Reference object. - /// - public OpenApiReference Reference { get; set; } + /// + public ParameterLocation? In { get; set; } - /// - /// REQUIRED. The name of the parameter. Parameter names are case sensitive. - /// If in is "path", the name field MUST correspond to the associated path segment from the path field in the Paths Object. - /// If in is "header" and the name field is "Accept", "Content-Type" or "Authorization", the parameter definition SHALL be ignored. - /// For all other cases, the name corresponds to the parameter name used by the in property. - /// - public virtual string Name { get; set; } - - /// - /// REQUIRED. The location of the parameter. - /// Possible values are "query", "header", "path" or "cookie". - /// - public virtual ParameterLocation? In { get; set; } - - /// - /// A brief description of the parameter. This could contain examples of use. - /// CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } + /// + public string Description { get; set; } - /// - /// Determines whether this parameter is mandatory. - /// If the parameter location is "path", this property is REQUIRED and its value MUST be true. - /// Otherwise, the property MAY be included and its default value is false. - /// - public virtual bool Required { get; set; } + /// + public bool Required { get; set; } - /// - /// Specifies that a parameter is deprecated and SHOULD be transitioned out of usage. - /// - public virtual bool Deprecated { get; set; } = false; + /// + public bool Deprecated { get; set; } - /// - /// Sets the ability to pass empty-valued parameters. - /// This is valid only for query parameters and allows sending a parameter with an empty value. - /// Default value is false. - /// If style is used, and if behavior is n/a (cannot be serialized), - /// the value of allowEmptyValue SHALL be ignored. - /// - public virtual bool AllowEmptyValue { get; set; } = false; + /// + public bool AllowEmptyValue { get; set; } - /// - /// Describes how the parameter value will be serialized depending on the type of the parameter value. - /// Default values (based on value of in): for query - form; for path - simple; for header - simple; - /// for cookie - form. - /// - public virtual ParameterStyle? Style + /// + public ParameterStyle? Style { get => _style ?? GetDefaultStyleValue(); set => _style = value; } - /// - /// When this is true, parameter values of type array or object generate separate parameters - /// for each value of the array or key-value pair of the map. - /// For other types of parameters this property has no effect. - /// When style is form, the default value is true. - /// For all other styles, the default value is false. - /// - public virtual bool Explode + /// + public bool Explode { get => _explode ?? Style == ParameterStyle.Form; set => _explode = value; } - /// - /// Determines whether the parameter value SHOULD allow reserved characters, - /// as defined by RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding. - /// This property only applies to parameters with an in value of query. - /// The default value is false. - /// - public virtual bool AllowReserved { get; set; } + /// + public bool AllowReserved { get; set; } - /// - /// The schema defining the type used for the parameter. - /// - public virtual OpenApiSchema Schema - { - get => _schema; - set => _schema = value; - } + /// + public IOpenApiSchema Schema { get; set; } - /// - /// Examples of the media type. Each example SHOULD contain a value - /// in the correct format as specified in the parameter encoding. - /// The examples object is mutually exclusive of the example object. - /// Furthermore, if referencing a schema which contains an example, - /// the examples value SHALL override the example provided by the schema. - /// - public virtual IDictionary Examples { get; set; } = new Dictionary(); + /// + public IDictionary Examples { get; set; } = new Dictionary(); - /// - /// Example of the media type. The example SHOULD match the specified schema and encoding properties - /// if present. The example object is mutually exclusive of the examples object. - /// Furthermore, if referencing a schema which contains an example, - /// the example value SHALL override the example provided by the schema. - /// To represent examples of media types that cannot naturally be represented in JSON or YAML, - /// a string value can contain the example with escaping where necessary. - /// - public virtual JsonNode Example { get; set; } + /// + public JsonNode Example { get; set; } - /// - /// A map containing the representations for the parameter. - /// The key is the media type and the value describes it. - /// The map MUST only contain one entry. - /// For more complex scenarios, the content property can define the media type and schema of the parameter. - /// A parameter MUST contain either a schema property, or a content property, but not both. - /// When example or examples are provided in conjunction with the schema object, - /// the example MUST follow the prescribed serialization strategy for the parameter. - /// - public virtual IDictionary Content { get; set; } = new Dictionary(); + /// + public IDictionary Content { get; set; } = new Dictionary(); - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// A parameterless constructor @@ -156,43 +80,38 @@ public OpenApiParameter() { } /// /// Initializes a clone instance of object /// - public OpenApiParameter(OpenApiParameter parameter) + internal OpenApiParameter(IOpenApiParameter parameter) { - UnresolvedReference = parameter?.UnresolvedReference ?? UnresolvedReference; - Reference = parameter?.Reference != null ? new(parameter?.Reference) : null; - Name = parameter?.Name ?? Name; - In = parameter?.In ?? In; - Description = parameter?.Description ?? Description; - Required = parameter?.Required ?? Required; - Style = parameter?.Style ?? Style; - Explode = parameter?.Explode ?? Explode; - AllowReserved = parameter?.AllowReserved ?? AllowReserved; - _schema = parameter?.Schema != null ? new(parameter.Schema) : null; - Examples = parameter?.Examples != null ? new Dictionary(parameter.Examples) : null; - Example = parameter?.Example != null ? JsonNodeCloneHelper.Clone(parameter.Example) : null; - Content = parameter?.Content != null ? new Dictionary(parameter.Content) : null; - Extensions = parameter?.Extensions != null ? new Dictionary(parameter.Extensions) : null; - AllowEmptyValue = parameter?.AllowEmptyValue ?? AllowEmptyValue; - Deprecated = parameter?.Deprecated ?? Deprecated; + Utils.CheckArgumentNull(parameter); + Name = parameter.Name ?? Name; + In = parameter.In ?? In; + Description = parameter.Description ?? Description; + Required = parameter.Required; + Style = parameter.Style ?? Style; + Explode = parameter.Explode; + AllowReserved = parameter.AllowReserved; + Schema = parameter.Schema.CreateShallowCopy(); + Examples = parameter.Examples != null ? new Dictionary(parameter.Examples) : null; + Example = parameter.Example != null ? JsonNodeCloneHelper.Clone(parameter.Example) : null; + Content = parameter.Content != null ? new Dictionary(parameter.Content) : null; + Extensions = parameter.Extensions != null ? new Dictionary(parameter.Extensions) : null; + AllowEmptyValue = parameter.AllowEmptyValue; + Deprecated = parameter.Deprecated; } - /// - /// Serialize to Open Api v3.1 - /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + /// + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } - /// - /// Serialize to Open Api v3.0 - /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + /// + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -218,13 +137,13 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio writer.WriteProperty(OpenApiConstants.AllowEmptyValue, AllowEmptyValue, false); // style - if (_style.HasValue) + if (Style.HasValue && Style != GetDefaultStyleValue()) { - writer.WriteProperty(OpenApiConstants.Style, _style.Value.GetDisplayName()); + writer.WriteProperty(OpenApiConstants.Style, Style.Value.GetDisplayName()); } // explode - writer.WriteProperty(OpenApiConstants.Explode, _explode, _style is ParameterStyle.Form); + writer.WriteProperty(OpenApiConstants.Explode, _explode, Style is ParameterStyle.Form); // allowReserved writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); @@ -247,10 +166,8 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio writer.WriteEndObject(); } - /// - /// Serialize to OpenAPI V2 document without using reference. - /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + /// + public void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); @@ -291,7 +208,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) } // In V2 parameter's type can't be a reference to a custom object schema or can't be of type object // So in that case map the type as string. - else if (Schema?.UnresolvedReference == true || Schema?.Type == JsonSchemaType.Object) + else if (Schema is OpenApiSchemaReference { UnresolvedReference: true } || (Schema?.Type & JsonSchemaType.Object) == JsonSchemaType.Object) { writer.WriteProperty(OpenApiConstants.Type, "string"); } @@ -314,9 +231,14 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) // uniqueItems // enum // multipleOf - if (Schema != null) + var targetSchema = Schema switch { + OpenApiSchemaReference schemaReference => schemaReference.Target, + OpenApiSchema schema => schema, + _ => null, + }; + if (targetSchema is not null) { - Schema.WriteAsItemsProperties(writer); + targetSchema.WriteAsItemsProperties(writer); var extensions = Schema.Extensions; if (extensions != null) { @@ -358,7 +280,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) foreach (var example in Examples) { writer.WritePropertyName(example.Key); - example.Value.SerializeInternal(writer, OpenApiSpecVersion.OpenApi2_0); + example.Value.SerializeAsV2(writer); } writer.WriteEndObject(); } @@ -371,7 +293,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) internal virtual ParameterStyle? GetDefaultStyleValue() { - Style = In switch + return In switch { ParameterLocation.Query => ParameterStyle.Form, ParameterLocation.Header => ParameterStyle.Simple, @@ -379,8 +301,12 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) ParameterLocation.Cookie => ParameterStyle.Form, _ => (ParameterStyle?)ParameterStyle.Simple, }; + } - return Style; + /// + public IOpenApiParameter CreateShallowCopy() + { + return new OpenApiParameter(this); } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs index ea7d628ea..f3baa5743 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -12,49 +13,26 @@ namespace Microsoft.OpenApi.Models /// /// Path Item Object: to describe the operations available on a single path. /// - public class OpenApiPathItem : IOpenApiExtensible, IOpenApiReferenceable + public class OpenApiPathItem : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiPathItem { - /// - /// An optional, string summary, intended to apply to all operations in this path. - /// - public virtual string Summary { get; set; } + /// + public string Summary { get; set; } - /// - /// An optional, string description, intended to apply to all operations in this path. - /// - public virtual string Description { get; set; } + /// + public string Description { get; set; } - /// - /// Gets the definition of operations on this path. - /// - public virtual IDictionary Operations { get; set; } + /// + public IDictionary Operations { get; set; } = new Dictionary(); - /// - /// An alternative server array to service all operations in this path. - /// - public virtual IList Servers { get; set; } = new List(); + /// + public IList Servers { get; set; } = []; - /// - /// A list of parameters that are applicable for all the operations described under this path. - /// These parameters can be overridden at the operation level, but cannot be removed there. - /// - public virtual IList Parameters { get; set; } = new List(); + /// + public IList Parameters { get; set; } = []; - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); - - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public bool UnresolvedReference { get; set; } - - /// - /// Reference object. - /// - public OpenApiReference Reference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Add one operation into this path item. @@ -74,22 +52,21 @@ public OpenApiPathItem() { } /// /// Initializes a clone of an object /// - public OpenApiPathItem(OpenApiPathItem pathItem) + internal OpenApiPathItem(IOpenApiPathItem pathItem) { - Summary = pathItem?.Summary ?? Summary; - Description = pathItem?.Description ?? Description; - Operations = pathItem?.Operations != null ? new Dictionary(pathItem.Operations) : null; - Servers = pathItem?.Servers != null ? new List(pathItem.Servers) : null; - Parameters = pathItem?.Parameters != null ? new List(pathItem.Parameters) : null; - Extensions = pathItem?.Extensions != null ? new Dictionary(pathItem.Extensions) : null; - UnresolvedReference = pathItem?.UnresolvedReference ?? UnresolvedReference; - Reference = pathItem?.Reference != null ? new(pathItem?.Reference) : null; + Utils.CheckArgumentNull(pathItem); + Summary = pathItem.Summary ?? Summary; + Description = pathItem.Description ?? Description; + Operations = pathItem.Operations != null ? new Dictionary(pathItem.Operations) : null; + Servers = pathItem.Servers != null ? new List(pathItem.Servers) : null; + Parameters = pathItem.Parameters != null ? new List(pathItem.Parameters) : null; + Extensions = pathItem.Extensions != null ? new Dictionary(pathItem.Extensions) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } @@ -97,7 +74,7 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } @@ -174,5 +151,11 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio writer.WriteEndObject(); } + + /// + public IOpenApiPathItem CreateShallowCopy() + { + return new OpenApiPathItem(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs index f3a89460a..a15fed843 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs @@ -1,12 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using Microsoft.OpenApi.Models.Interfaces; + namespace Microsoft.OpenApi.Models { /// /// Paths object. /// - public class OpenApiPaths : OpenApiExtensibleDictionary + public class OpenApiPaths : OpenApiExtensibleDictionary { /// /// Parameterless constructor diff --git a/src/Microsoft.OpenApi/Models/OpenApiReference.cs b/src/Microsoft.OpenApi/Models/OpenApiReference.cs index 8a1ae4a43..43d307fad 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiReference.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiReference.cs @@ -4,6 +4,7 @@ using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -11,7 +12,7 @@ namespace Microsoft.OpenApi.Models /// /// A simple object to allow referencing other components in the specification, internally and externally. /// - public class OpenApiReference : IOpenApiSerializable + public class OpenApiReference : IOpenApiSerializable, IOpenApiDescribedElement, IOpenApiSummarizedElement { /// /// A short summary which by default SHOULD override that of the referenced component. @@ -32,13 +33,13 @@ public class OpenApiReference : IOpenApiSerializable /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public string ExternalResource { get; set; } + public string ExternalResource { get; init; } /// /// The element type referenced. /// /// This must be present if is not present. - public ReferenceType? Type { get; set; } + public ReferenceType? Type { get; init; } /// /// The identifier of the reusable component of one particular ReferenceType. @@ -47,7 +48,7 @@ public class OpenApiReference : IOpenApiSerializable /// If ExternalResource is not present, this is the name of the component without the reference type name. /// For example, if the reference is '#/components/schemas/componentName', the Id is 'componentName'. /// - public string Id { get; set; } + public string Id { get; init; } /// /// Gets a flag indicating whether this reference is an external reference. @@ -62,12 +63,13 @@ public class OpenApiReference : IOpenApiSerializable /// /// Gets a flag indicating whether a file is a valid OpenAPI document or a fragment /// - public bool IsFragment = false; + public bool IsFragment { get; init; } + private OpenApiDocument hostDocument; /// /// The OpenApiDocument that is hosting the OpenApiReference instance. This is used to enable dereferencing the reference. /// - public OpenApiDocument HostDocument { get; set; } + public OpenApiDocument HostDocument { get => hostDocument; init => hostDocument = value; } /// /// Gets the full reference string for v3.0. @@ -95,7 +97,7 @@ public string ReferenceV3 { return Id; } - if (Id.StartsWith("http")) + if (Id.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { return Id; } @@ -145,12 +147,13 @@ public OpenApiReference() { } /// public OpenApiReference(OpenApiReference reference) { - Summary = reference?.Summary; - Description = reference?.Description; - ExternalResource = reference?.ExternalResource; - Type = reference?.Type; - Id = reference?.Id; - HostDocument = new(reference?.HostDocument); + Utils.CheckArgumentNull(reference); + Summary = reference.Summary; + Description = reference.Description; + ExternalResource = reference.ExternalResource; + Type = reference.Type; + Id = reference.Id; + HostDocument = reference.HostDocument; } /// @@ -158,11 +161,12 @@ public OpenApiReference(OpenApiReference reference) /// public void SerializeAsV31(IOpenApiWriter writer) { - // summary and description are in 3.1 but not in 3.0 - writer.WriteProperty(OpenApiConstants.Summary, Summary); - writer.WriteProperty(OpenApiConstants.Description, Description); - - SerializeInternal(writer); + SerializeInternal(writer, w => + { + // summary and description are in 3.1 but not in 3.0 + w.WriteProperty(OpenApiConstants.Summary, Summary); + w.WriteProperty(OpenApiConstants.Description, Description); + }); } /// @@ -176,7 +180,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// /// Serialize /// - private void SerializeInternal(IOpenApiWriter writer) + private void SerializeInternal(IOpenApiWriter writer, Action callback = null) { Utils.CheckArgumentNull(writer); @@ -188,6 +192,10 @@ private void SerializeInternal(IOpenApiWriter writer) } writer.WriteStartObject(); + if (callback is not null) + { + callback(writer); + } // $ref writer.WriteProperty(OpenApiConstants.DollarRef, ReferenceV3); @@ -200,7 +208,7 @@ private void SerializeInternal(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); if (Type == ReferenceType.Tag) { @@ -233,7 +241,7 @@ private string GetExternalReferenceV3() return ExternalResource + "#" + Id; } - if (Id.StartsWith("http")) + if (Id.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { return Id; } @@ -271,5 +279,16 @@ private string GetReferenceTypeNameAsV2(ReferenceType type) // to indicate that the reference is not pointing to any object. }; } + + /// + /// Sets the host document after deserialization or before serialization. + /// This method is internal on purpose to avoid consumers mutating the host document. + /// + /// Host document to set if none is present + internal void EnsureHostDocumentIsSet(OpenApiDocument currentDocument) + { + Utils.CheckArgumentNull(currentDocument); + hostDocument ??= currentDocument; + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index 037e7d92c..95f86dba3 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -7,6 +7,8 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -14,39 +16,19 @@ namespace Microsoft.OpenApi.Models /// /// Request Body Object /// - public class OpenApiRequestBody : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiRequestBody : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiRequestBody { - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public bool UnresolvedReference { get; set; } + /// + public string Description { get; set; } - /// - /// Reference object. - /// - public OpenApiReference Reference { get; set; } + /// + public bool Required { get; set; } - /// - /// A brief description of the request body. This could contain examples of use. - /// CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } + /// + public IDictionary Content { get; set; } = new Dictionary(); - /// - /// Determines if the request body is required in the request. Defaults to false. - /// - public virtual bool Required { get; set; } - - /// - /// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it. - /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* - /// - public virtual IDictionary Content { get; set; } = new Dictionary(); - - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameter-less constructor @@ -54,22 +36,21 @@ public class OpenApiRequestBody : IOpenApiReferenceable, IOpenApiExtensible public OpenApiRequestBody() { } /// - /// Initializes a copy instance of an object + /// Initializes a copy instance of an object /// - public OpenApiRequestBody(OpenApiRequestBody requestBody) + internal OpenApiRequestBody(IOpenApiRequestBody requestBody) { - UnresolvedReference = requestBody?.UnresolvedReference ?? UnresolvedReference; - Reference = requestBody?.Reference != null ? new(requestBody?.Reference) : null; - Description = requestBody?.Description ?? Description; - Required = requestBody?.Required ?? Required; - Content = requestBody?.Content != null ? new Dictionary(requestBody.Content) : null; - Extensions = requestBody?.Extensions != null ? new Dictionary(requestBody.Extensions) : null; + Utils.CheckArgumentNull(requestBody); + Description = requestBody.Description ?? Description; + Required = requestBody.Required; + Content = requestBody.Content != null ? new Dictionary(requestBody.Content) : null; + Extensions = requestBody.Extensions != null ? new Dictionary(requestBody.Extensions) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } @@ -77,12 +58,12 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -112,7 +93,8 @@ public void SerializeAsV2(IOpenApiWriter writer) // RequestBody object does not exist in V2. } - internal OpenApiBodyParameter ConvertToBodyParameter() + /// + public IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) { var bodyParameter = new OpenApiBodyParameter { @@ -134,30 +116,45 @@ internal OpenApiBodyParameter ConvertToBodyParameter() return bodyParameter; } - internal IEnumerable ConvertToFormDataParameters() + /// + public IEnumerable ConvertToFormDataParameters(IOpenApiWriter writer) { if (Content == null || !Content.Any()) yield break; foreach (var property in Content.First().Value.Schema.Properties) { - var paramSchema = property.Value; - if ("string".Equals(paramSchema.Type.ToIdentifier(), StringComparison.OrdinalIgnoreCase) + var paramSchema = property.Value.CreateShallowCopy(); + if ((paramSchema.Type & JsonSchemaType.String) == JsonSchemaType.String && ("binary".Equals(paramSchema.Format, StringComparison.OrdinalIgnoreCase) || "base64".Equals(paramSchema.Format, StringComparison.OrdinalIgnoreCase))) { - paramSchema.Type = "file".ToJsonSchemaType(); - paramSchema.Format = null; + var updatedSchema = paramSchema switch { + OpenApiSchema s => s, // we already have a copy + // we have a copy of a reference but don't want to mutate the source schema + // TODO might need recursive resolution of references here + OpenApiSchemaReference r => (OpenApiSchema)r.Target.CreateShallowCopy(), + _ => throw new InvalidOperationException("Unexpected schema type") + }; + updatedSchema.Type = "file".ToJsonSchemaType(); + updatedSchema.Format = null; + paramSchema = updatedSchema; } - yield return new() + yield return new OpenApiFormDataParameter() { - Description = property.Value.Description, + Description = paramSchema.Description, Name = property.Key, - Schema = property.Value, + Schema = paramSchema, Examples = Content.Values.FirstOrDefault()?.Examples, Required = Content.First().Value.Schema.Required?.Contains(property.Key) ?? false }; } } + + /// + public IOpenApiRequestBody CreateShallowCopy() + { + return new OpenApiRequestBody(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index 2fab33fd5..0ec6cbb84 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -12,45 +13,22 @@ namespace Microsoft.OpenApi.Models /// /// Response object. /// - public class OpenApiResponse : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiResponse : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiResponse { - /// - /// REQUIRED. A short description of the response. - /// - public virtual string Description { get; set; } + /// + public string Description { get; set; } - /// - /// Maps a header name to its definition. - /// - public virtual IDictionary Headers { get; set; } = new Dictionary(); + /// + public IDictionary Headers { get; set; } = new Dictionary(); - /// - /// A map containing descriptions of potential response payloads. - /// The key is a media type or media type range and the value describes it. - /// - public virtual IDictionary Content { get; set; } = new Dictionary(); + /// + public IDictionary Content { get; set; } = new Dictionary(); - /// - /// A map of operations links that can be followed from the response. - /// The key of the map is a short name for the link, - /// following the naming constraints of the names for Component Objects. - /// - public virtual IDictionary Links { get; set; } = new Dictionary(); + /// + public IDictionary Links { get; set; } = new Dictionary(); - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); - - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public bool UnresolvedReference { get; set; } - - /// - /// Reference pointer. - /// - public OpenApiReference Reference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameterless constructor @@ -58,23 +36,22 @@ public class OpenApiResponse : IOpenApiReferenceable, IOpenApiExtensible public OpenApiResponse() { } /// - /// Initializes a copy of object + /// Initializes a copy of object /// - public OpenApiResponse(OpenApiResponse response) + internal OpenApiResponse(IOpenApiResponse response) { - Description = response?.Description ?? Description; - Headers = response?.Headers != null ? new Dictionary(response.Headers) : null; - Content = response?.Content != null ? new Dictionary(response.Content) : null; - Links = response?.Links != null ? new Dictionary(response.Links) : null; - Extensions = response?.Extensions != null ? new Dictionary(response.Extensions) : null; - UnresolvedReference = response?.UnresolvedReference ?? UnresolvedReference; - Reference = response?.Reference != null ? new(response?.Reference) : null; + Utils.CheckArgumentNull(response); + Description = response.Description ?? Description; + Headers = response.Headers != null ? new Dictionary(response.Headers) : null; + Content = response.Content != null ? new Dictionary(response.Content) : null; + Links = response.Links != null ? new Dictionary(response.Links) : null; + Extensions = response.Extensions != null ? new Dictionary(response.Extensions) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } @@ -82,12 +59,12 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0. /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -115,7 +92,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio /// /// Serialize to OpenAPI V2 document without using reference. /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); @@ -162,7 +139,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) .SelectMany(mediaTypePair => mediaTypePair.Value.Examples)) { writer.WritePropertyName(example.Key); - example.Value.SerializeInternal(writer, OpenApiSpecVersion.OpenApi2_0); + example.Value.SerializeAsV2(writer); } writer.WriteEndObject(); @@ -187,5 +164,11 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) writer.WriteEndObject(); } + + /// + public IOpenApiResponse CreateShallowCopy() + { + return new OpenApiResponse(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponses.cs b/src/Microsoft.OpenApi/Models/OpenApiResponses.cs index 8880c244f..855ac6834 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponses.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponses.cs @@ -1,12 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using Microsoft.OpenApi.Models.Interfaces; + namespace Microsoft.OpenApi.Models { /// /// Responses object. /// - public class OpenApiResponses : OpenApiExtensibleDictionary + public class OpenApiResponses : OpenApiExtensibleDictionary { /// /// Parameterless constructor diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index d2ffa88ed..e69340641 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -4,10 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Text.Json.Nodes; +using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -15,316 +18,160 @@ namespace Microsoft.OpenApi.Models /// /// The Schema Object allows the definition of input and output data types. /// - public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiReferenceable + public class OpenApiSchema : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiSchema { - /// - /// Follow JSON Schema definition. Short text providing information about the data. - /// - public virtual string Title { get; set; } - - /// - /// $schema, a JSON Schema dialect identifier. Value must be a URI - /// - public virtual string Schema { get; set; } - - /// - /// $id - Identifies a schema resource with its canonical URI. - /// - public virtual string Id { get; set; } - - /// - /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema. - /// - public virtual string Comment { get; set; } + /// + public string Title { get; set; } - /// - /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema. - /// - public virtual IDictionary Vocabulary { get; set; } + /// + public string Schema { get; set; } - /// - /// $dynamicRef - an applicator that allows for deferring the full resolution until runtime, at which point it is resolved each time it is encountered while evaluating an instance - /// - public virtual string DynamicRef { get; set; } + /// + public string Id { get; set; } - /// - /// $dynamicAnchor - used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing. - /// - public virtual string DynamicAnchor { get; set; } + /// + public string Comment { get; set; } - /// - /// $defs - reserves a location for schema authors to inline re-usable JSON Schemas into a more general schema. - /// The keyword does not directly affect the validation result - /// - public virtual IDictionary Definitions { get; set; } + /// + public IDictionary Vocabulary { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? V31ExclusiveMaximum { get; set; } + /// + public string DynamicRef { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? V31ExclusiveMinimum { get; set; } + /// + public string DynamicAnchor { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool UnEvaluatedProperties { get; set; } + /// + public IDictionary Definitions { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value MUST be a string in V2 and V3. - /// - public virtual JsonSchemaType? Type { get; set; } + /// + public decimal? V31ExclusiveMaximum { get; set; } - /// - /// Follow JSON Schema definition: https://json-schema.org/draft/2020-12/json-schema-validation - /// - public virtual string Const { get; set; } + /// + public decimal? V31ExclusiveMinimum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// While relying on JSON Schema's defined formats, - /// the OAS offers a few additional predefined formats. - /// - public virtual string Format { get; set; } + /// + public bool UnEvaluatedProperties { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } + /// + public JsonSchemaType? Type { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? Maximum { get; set; } + /// + public string Const { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? ExclusiveMaximum { get; set; } + /// + public string Format { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? Minimum { get; set; } + /// + public string Description { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? ExclusiveMinimum { get; set; } + /// + public decimal? Maximum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxLength { get; set; } + /// + public bool? ExclusiveMaximum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinLength { get; set; } + /// + public decimal? Minimum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect - /// - public virtual string Pattern { get; set; } + /// + public bool? ExclusiveMinimum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? MultipleOf { get; set; } + /// + public int? MaxLength { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. - /// Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. - /// For example, if type is string, then default can be "foo" but cannot be 1. - /// - public virtual JsonNode Default { get; set; } + /// + public int? MinLength { get; set; } - /// - /// Relevant only for Schema "properties" definitions. Declares the property as "read only". - /// This means that it MAY be sent as part of a response but SHOULD NOT be sent as part of the request. - /// If the property is marked as readOnly being true and is in the required list, - /// the required will take effect on the response only. - /// A property MUST NOT be marked as both readOnly and writeOnly being true. - /// Default value is false. - /// - public virtual bool ReadOnly { get; set; } + /// + public string Pattern { get; set; } - /// - /// Relevant only for Schema "properties" definitions. Declares the property as "write only". - /// Therefore, it MAY be sent as part of a request but SHOULD NOT be sent as part of the response. - /// If the property is marked as writeOnly being true and is in the required list, - /// the required will take effect on the request only. - /// A property MUST NOT be marked as both readOnly and writeOnly being true. - /// Default value is false. - /// - public virtual bool WriteOnly { get; set; } + /// + public decimal? MultipleOf { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList AllOf { get; set; } = new List(); + /// + public JsonNode Default { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList OneOf { get; set; } = new List(); + /// + public bool ReadOnly { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList AnyOf { get; set; } = new List(); + /// + public bool WriteOnly { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual OpenApiSchema Not { get; set; } + /// + public IList AllOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual ISet Required { get; set; } = new HashSet(); + /// + public IList OneOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value MUST be an object and not an array. Inline or referenced schema MUST be of a Schema Object - /// and not a standard JSON Schema. items MUST be present if the type is array. - /// - public virtual OpenApiSchema Items { get; set; } + /// + public IList AnyOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxItems { get; set; } + /// + public IOpenApiSchema Not { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinItems { get; set; } + /// + public ISet Required { get; set; } = new HashSet(); - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? UniqueItems { get; set; } + /// + public IOpenApiSchema Items { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Property definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced). - /// - public virtual IDictionary Properties { get; set; } = new Dictionary(); + /// + public int? MaxItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// PatternProperty definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced) - /// Each property name of this object SHOULD be a valid regular expression according to the ECMA 262 r - /// egular expression dialect. Each property value of this object MUST be an object, and each object MUST - /// be a valid Schema Object not a standard JSON Schema. - /// - public virtual IDictionary PatternProperties { get; set; } = new Dictionary(); + /// + public int? MinItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxProperties { get; set; } + /// + public bool? UniqueItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinProperties { get; set; } + /// + public IDictionary Properties { get; set; } = new Dictionary(StringComparer.Ordinal); - /// - /// Indicates if the schema can contain properties other than those defined by the properties map. - /// - public virtual bool AdditionalPropertiesAllowed { get; set; } = true; + /// + public IDictionary PatternProperties { get; set; } = new Dictionary(StringComparer.Ordinal); - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value can be boolean or object. Inline or referenced schema - /// MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual OpenApiSchema AdditionalProperties { get; set; } + /// + public int? MaxProperties { get; set; } - /// - /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate - /// between other schemas which may satisfy the payload description. - /// - public virtual OpenApiDiscriminator Discriminator { get; set; } + /// + public int? MinProperties { get; set; } - /// - /// A free-form property to include an example of an instance for this schema. - /// To represent examples that cannot be naturally represented in JSON or YAML, - /// a string value can be used to contain the example with escaping where necessary. - /// - public virtual JsonNode Example { get; set; } + /// + public bool AdditionalPropertiesAllowed { get; set; } = true; - /// - /// A free-form property to include examples of an instance for this schema. - /// To represent examples that cannot be naturally represented in JSON or YAML, - /// a list of values can be used to contain the examples with escaping where necessary. - /// - public virtual IList Examples { get; set; } + /// + public IOpenApiSchema AdditionalProperties { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual IList Enum { get; set; } = new List(); + /// + public OpenApiDiscriminator Discriminator { get; set; } - /// - /// Allows sending a null value for the defined schema. Default value is false. - /// - public virtual bool Nullable { get; set; } + /// + public JsonNode Example { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool UnevaluatedProperties { get; set;} + /// + public IList Examples { get; set; } - /// - /// Additional external documentation for this schema. - /// - public virtual OpenApiExternalDocs ExternalDocs { get; set; } + /// + public IList Enum { get; set; } = new List(); - /// - /// Specifies that a schema is deprecated and SHOULD be transitioned out of usage. - /// Default value is false. - /// - public virtual bool Deprecated { get; set; } + /// + public bool UnevaluatedProperties { get; set;} - /// - /// This MAY be used only on properties schemas. It has no effect on root schemas. - /// Adds additional metadata to describe the XML representation of this property. - /// - public virtual OpenApiXml Xml { get; set; } + /// + public OpenApiExternalDocs ExternalDocs { get; set; } - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public bool Deprecated { get; set; } - /// - /// This object stores any unrecognized keywords found in the schema. - /// - public virtual IDictionary UnrecognizedKeywords { get; set; } = new Dictionary(); + /// + public OpenApiXml Xml { get; set; } - /// - /// Indicates object is a placeholder reference to an actual object and does not contain valid data. - /// - public virtual bool UnresolvedReference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); - /// - /// Reference object. - /// - public virtual OpenApiReference Reference { get; set; } + /// + public IDictionary UnrecognizedKeywords { get; set; } = new Dictionary(); /// public IDictionary Annotations { get; set; } @@ -335,85 +182,78 @@ public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiRe public OpenApiSchema() { } /// - /// Initializes a copy of object + /// Initializes a copy of object /// - public OpenApiSchema(OpenApiSchema schema) + /// The schema object to copy from. + internal OpenApiSchema(IOpenApiSchema schema) { - Title = schema?.Title ?? Title; - Id = schema?.Id ?? Id; - Const = schema?.Const ?? Const; - Schema = schema?.Schema ?? Schema; - Comment = schema?.Comment ?? Comment; - Vocabulary = schema?.Vocabulary != null ? new Dictionary(schema.Vocabulary) : null; - DynamicAnchor = schema?.DynamicAnchor ?? DynamicAnchor; - DynamicRef = schema?.DynamicRef ?? DynamicRef; - Definitions = schema?.Definitions != null ? new Dictionary(schema.Definitions) : null; - UnevaluatedProperties = schema?.UnevaluatedProperties ?? UnevaluatedProperties; - V31ExclusiveMaximum = schema?.V31ExclusiveMaximum ?? V31ExclusiveMaximum; - V31ExclusiveMinimum = schema?.V31ExclusiveMinimum ?? V31ExclusiveMinimum; - Type = schema?.Type ?? Type; - Format = schema?.Format ?? Format; - Description = schema?.Description ?? Description; - Maximum = schema?.Maximum ?? Maximum; - ExclusiveMaximum = schema?.ExclusiveMaximum ?? ExclusiveMaximum; - Minimum = schema?.Minimum ?? Minimum; - ExclusiveMinimum = schema?.ExclusiveMinimum ?? ExclusiveMinimum; - MaxLength = schema?.MaxLength ?? MaxLength; - MinLength = schema?.MinLength ?? MinLength; - Pattern = schema?.Pattern ?? Pattern; - MultipleOf = schema?.MultipleOf ?? MultipleOf; - Default = schema?.Default != null ? JsonNodeCloneHelper.Clone(schema?.Default) : null; - ReadOnly = schema?.ReadOnly ?? ReadOnly; - WriteOnly = schema?.WriteOnly ?? WriteOnly; - AllOf = schema?.AllOf != null ? new List(schema.AllOf) : null; - OneOf = schema?.OneOf != null ? new List(schema.OneOf) : null; - AnyOf = schema?.AnyOf != null ? new List(schema.AnyOf) : null; - Not = schema?.Not != null ? new(schema?.Not) : null; - Required = schema?.Required != null ? new HashSet(schema.Required) : null; - Items = schema?.Items != null ? new(schema?.Items) : null; - MaxItems = schema?.MaxItems ?? MaxItems; - MinItems = schema?.MinItems ?? MinItems; - UniqueItems = schema?.UniqueItems ?? UniqueItems; - Properties = schema?.Properties != null ? new Dictionary(schema.Properties) : null; - PatternProperties = schema?.PatternProperties != null ? new Dictionary(schema.PatternProperties) : null; - MaxProperties = schema?.MaxProperties ?? MaxProperties; - MinProperties = schema?.MinProperties ?? MinProperties; - AdditionalPropertiesAllowed = schema?.AdditionalPropertiesAllowed ?? AdditionalPropertiesAllowed; - AdditionalProperties = schema?.AdditionalProperties != null ? new(schema?.AdditionalProperties) : null; - Discriminator = schema?.Discriminator != null ? new(schema?.Discriminator) : null; - Example = schema?.Example != null ? JsonNodeCloneHelper.Clone(schema?.Example) : null; - Examples = schema?.Examples != null ? new List(schema.Examples) : null; - Enum = schema?.Enum != null ? new List(schema.Enum) : null; - Nullable = schema?.Nullable ?? Nullable; - ExternalDocs = schema?.ExternalDocs != null ? new(schema?.ExternalDocs) : null; - Deprecated = schema?.Deprecated ?? Deprecated; - Xml = schema?.Xml != null ? new(schema?.Xml) : null; - Extensions = schema?.Extensions != null ? new Dictionary(schema.Extensions) : null; - UnresolvedReference = schema?.UnresolvedReference ?? UnresolvedReference; - Reference = schema?.Reference != null ? new(schema?.Reference) : null; - Annotations = schema?.Annotations != null ? new Dictionary(schema?.Annotations) : null; - UnrecognizedKeywords = schema?.UnrecognizedKeywords != null ? new Dictionary(schema?.UnrecognizedKeywords) : null; + Utils.CheckArgumentNull(schema); + Title = schema.Title ?? Title; + Id = schema.Id ?? Id; + Const = schema.Const ?? Const; + Schema = schema.Schema ?? Schema; + Comment = schema.Comment ?? Comment; + Vocabulary = schema.Vocabulary != null ? new Dictionary(schema.Vocabulary) : null; + DynamicAnchor = schema.DynamicAnchor ?? DynamicAnchor; + DynamicRef = schema.DynamicRef ?? DynamicRef; + Definitions = schema.Definitions != null ? new Dictionary(schema.Definitions) : null; + UnevaluatedProperties = schema.UnevaluatedProperties; + V31ExclusiveMaximum = schema.V31ExclusiveMaximum ?? V31ExclusiveMaximum; + V31ExclusiveMinimum = schema.V31ExclusiveMinimum ?? V31ExclusiveMinimum; + Type = schema.Type ?? Type; + Format = schema.Format ?? Format; + Description = schema.Description ?? Description; + Maximum = schema.Maximum ?? Maximum; + ExclusiveMaximum = schema.ExclusiveMaximum ?? ExclusiveMaximum; + Minimum = schema.Minimum ?? Minimum; + ExclusiveMinimum = schema.ExclusiveMinimum ?? ExclusiveMinimum; + MaxLength = schema.MaxLength ?? MaxLength; + MinLength = schema.MinLength ?? MinLength; + Pattern = schema.Pattern ?? Pattern; + MultipleOf = schema.MultipleOf ?? MultipleOf; + Default = schema.Default != null ? JsonNodeCloneHelper.Clone(schema.Default) : null; + ReadOnly = schema.ReadOnly; + WriteOnly = schema.WriteOnly; + AllOf = schema.AllOf != null ? new List(schema.AllOf) : null; + OneOf = schema.OneOf != null ? new List(schema.OneOf) : null; + AnyOf = schema.AnyOf != null ? new List(schema.AnyOf) : null; + Not = schema.Not?.CreateShallowCopy(); + Required = schema.Required != null ? new HashSet(schema.Required) : null; + Items = schema.Items?.CreateShallowCopy(); + MaxItems = schema.MaxItems ?? MaxItems; + MinItems = schema.MinItems ?? MinItems; + UniqueItems = schema.UniqueItems ?? UniqueItems; + Properties = schema.Properties != null ? new Dictionary(schema.Properties) : null; + PatternProperties = schema.PatternProperties != null ? new Dictionary(schema.PatternProperties) : null; + MaxProperties = schema.MaxProperties ?? MaxProperties; + MinProperties = schema.MinProperties ?? MinProperties; + AdditionalPropertiesAllowed = schema.AdditionalPropertiesAllowed; + AdditionalProperties = schema.AdditionalProperties?.CreateShallowCopy(); + Discriminator = schema.Discriminator != null ? new(schema.Discriminator) : null; + Example = schema.Example != null ? JsonNodeCloneHelper.Clone(schema.Example) : null; + Examples = schema.Examples != null ? new List(schema.Examples) : null; + Enum = schema.Enum != null ? new List(schema.Enum) : null; + ExternalDocs = schema.ExternalDocs != null ? new(schema.ExternalDocs) : null; + Deprecated = schema.Deprecated; + Xml = schema.Xml != null ? new(schema.Xml) : null; + Extensions = schema.Extensions != null ? new Dictionary(schema.Extensions) : null; + Annotations = schema.Annotations != null ? new Dictionary(schema.Annotations) : null; + UnrecognizedKeywords = schema.UnrecognizedKeywords != null ? new Dictionary(schema.UnrecognizedKeywords) : null; } - /// - /// Serialize to Open Api v3.1 - /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + /// + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } - /// - /// Serialize to Open Api v3.0 - /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + /// + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } -/// - - public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { writer.WriteStartObject(); @@ -514,12 +354,6 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, // default writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d)); - // nullable - if (version is OpenApiSpecVersion.OpenApi3_0) - { - writer.WriteProperty(OpenApiConstants.Nullable, Nullable, false); - } - // discriminator writer.WriteOptionalObject(OpenApiConstants.Discriminator, Discriminator, callback); @@ -553,9 +387,8 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, writer.WriteEndObject(); } -/// - - public virtual void SerializeAsV2(IOpenApiWriter writer) + /// + public void SerializeAsV2(IOpenApiWriter writer) { SerializeAsV2(writer: writer, parentRequiredProperties: new HashSet(), propertyName: null); } @@ -583,14 +416,7 @@ internal void WriteAsItemsProperties(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Type, Type.ToIdentifier()); // format - if (string.IsNullOrEmpty(Format)) - { - Format = AllOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ?? - AnyOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ?? - OneOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format; - } - - writer.WriteProperty(OpenApiConstants.Format, Format); + WriteFormatProperty(writer); // items writer.WriteOptionalObject(OpenApiConstants.Items, Items, (w, s) => s.SerializeAsV2(w)); @@ -643,6 +469,19 @@ internal void WriteAsItemsProperties(IOpenApiWriter writer) writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi2_0); } + private void WriteFormatProperty(IOpenApiWriter writer) + { + var formatToWrite = Format; + if (string.IsNullOrEmpty(formatToWrite)) + { + formatToWrite = AllOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ?? + AnyOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ?? + OneOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format; + } + + writer.WriteProperty(OpenApiConstants.Format, formatToWrite); + } + /// /// Serialize to Open Api v2.0 and handles not marking the provided property /// as readonly if its included in the provided list of required properties of parent schema. @@ -650,7 +489,7 @@ internal void WriteAsItemsProperties(IOpenApiWriter writer) /// The open api writer. /// The list of required properties in parent schema. /// The property name that will be serialized. - internal virtual void SerializeAsV2( + private void SerializeAsV2( IOpenApiWriter writer, ISet parentRequiredProperties, string propertyName) @@ -666,14 +505,7 @@ internal virtual void SerializeAsV2( writer.WriteProperty(OpenApiConstants.Description, Description); // format - if (string.IsNullOrEmpty(Format)) - { - Format = AllOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ?? - AnyOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ?? - OneOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format; - } - - writer.WriteProperty(OpenApiConstants.Format, Format); + WriteFormatProperty(writer); // title writer.WriteProperty(OpenApiConstants.Title, Title); @@ -748,7 +580,12 @@ internal virtual void SerializeAsV2( // properties writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, (w, key, s) => - s.SerializeAsV2(w, Required, key)); + { + if (s is OpenApiSchema oais) + oais.SerializeAsV2(w, Required, key); + else + s.SerializeAsV2(w); + }); // additionalProperties if (AdditionalPropertiesAllowed) @@ -791,20 +628,38 @@ internal virtual void SerializeAsV2( private void SerializeTypeProperty(JsonSchemaType? type, IOpenApiWriter writer, OpenApiSpecVersion version) { + // check whether nullable is true for upcasting purposes + var isNullable = (Type.HasValue && Type.Value.HasFlag(JsonSchemaType.Null)) || + Extensions is not null && + Extensions.TryGetValue(OpenApiConstants.NullableExtension, out var nullExtRawValue) && + nullExtRawValue is OpenApiAny { Node: JsonNode jsonNode} && + jsonNode.GetValueKind() is JsonValueKind.True; if (type is null) { - return; - } - if (!HasMultipleTypes(type.Value)) - { - // check whether nullable is true for upcasting purposes - if (version is OpenApiSpecVersion.OpenApi3_1 && (Nullable || Extensions.ContainsKey(OpenApiConstants.NullableExtension))) + if (version is OpenApiSpecVersion.OpenApi3_0 && isNullable) { - UpCastSchemaTypeToV31(type, writer); + writer.WriteProperty(OpenApiConstants.Nullable, true); } - else + } + else if (!HasMultipleTypes(type.Value)) + { + + switch (version) { - writer.WriteProperty(OpenApiConstants.Type, type.Value.ToIdentifier()); + case OpenApiSpecVersion.OpenApi3_1 when isNullable: + UpCastSchemaTypeToV31(type.Value, writer); + break; + case OpenApiSpecVersion.OpenApi3_0 when isNullable && type.Value == JsonSchemaType.Null: + writer.WriteProperty(OpenApiConstants.Nullable, true); + writer.WriteProperty(OpenApiConstants.Type, JsonSchemaType.Object.ToIdentifier()); + break; + case OpenApiSpecVersion.OpenApi3_0 when isNullable && type.Value != JsonSchemaType.Null: + writer.WriteProperty(OpenApiConstants.Nullable, true); + writer.WriteProperty(OpenApiConstants.Type, type.Value.ToIdentifier()); + break; + default: + writer.WriteProperty(OpenApiConstants.Type, type.Value.ToIdentifier()); + break; } } else @@ -836,14 +691,21 @@ private static bool HasMultipleTypes(JsonSchemaType schemaType) schemaTypeNumeric != (int)JsonSchemaType.Null; } - private void UpCastSchemaTypeToV31(JsonSchemaType? type, IOpenApiWriter writer) + private static void UpCastSchemaTypeToV31(JsonSchemaType type, IOpenApiWriter writer) { // create a new array and insert the type and "null" as values - Type = type | JsonSchemaType.Null; - var list = (from JsonSchemaType? flag in jsonSchemaTypeValues// Check if the flag is set in 'type' using a bitwise AND operation - where Type.Value.HasFlag(flag) + var temporaryType = type | JsonSchemaType.Null; + var list = (from JsonSchemaType flag in jsonSchemaTypeValues// Check if the flag is set in 'type' using a bitwise AND operation + where temporaryType.HasFlag(flag) select flag.ToIdentifier()).ToList(); - writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s)); + if (list.Count > 1) + { + writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s)); + } + else + { + writer.WriteProperty(OpenApiConstants.Type, list[0]); + } } #if NET5_0_OR_GREATER @@ -864,9 +726,9 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType schemaType, IOpenApiWriter ? OpenApiConstants.NullableExtension : OpenApiConstants.Nullable; - if (!HasMultipleTypes(schemaType ^ JsonSchemaType.Null) && (schemaType & JsonSchemaType.Null) == JsonSchemaType.Null) // checks for two values and one is null + if (!HasMultipleTypes(schemaType & ~JsonSchemaType.Null) && (schemaType & JsonSchemaType.Null) == JsonSchemaType.Null) // checks for two values and one is null { - foreach (JsonSchemaType? flag in jsonSchemaTypeValues) + foreach (JsonSchemaType flag in jsonSchemaTypeValues) { // Skip if the flag is not set or if it's the Null flag if (schemaType.HasFlag(flag) && flag != JsonSchemaType.Null) @@ -875,10 +737,7 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType schemaType, IOpenApiWriter writer.WriteProperty(OpenApiConstants.Type, flag.ToIdentifier()); } } - if (!Nullable) - { - writer.WriteProperty(nullableProp, true); - } + writer.WriteProperty(nullableProp, true); } else if (!HasMultipleTypes(schemaType)) { @@ -892,5 +751,11 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType schemaType, IOpenApiWriter } } } + + /// + public IOpenApiSchema CreateShallowCopy() + { + return new OpenApiSchema(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs index 428d0649e..193d648df 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs @@ -3,7 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -16,7 +19,7 @@ namespace Microsoft.OpenApi.Models /// then the value is a list of scope names required for the execution. /// For other security scheme types, the array MUST be empty. /// - public class OpenApiSecurityRequirement : Dictionary>, + public class OpenApiSecurityRequirement : Dictionary>, IOpenApiSerializable { /// @@ -34,7 +37,7 @@ public OpenApiSecurityRequirement() /// public void SerializeAsV31(IOpenApiWriter writer) { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); + SerializeInternal(writer, (w, s) => w.WritePropertyName(s.Reference.ReferenceV3)); } /// @@ -42,32 +45,28 @@ public void SerializeAsV31(IOpenApiWriter writer) /// public void SerializeAsV3(IOpenApiWriter writer) { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); + SerializeInternal(writer, (w, s) => w.WritePropertyName(s.Reference.ReferenceV3)); } /// /// Serialize /// - private void SerializeInternal(IOpenApiWriter writer, Action callback) + private void SerializeInternal(IOpenApiWriter writer, Action callback) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); writer.WriteStartObject(); - foreach (var securitySchemeAndScopesValuePair in this) + // Reaching this point means the reference to a specific OpenApiSecurityScheme fails. + // We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what + // string to output. + + foreach (var securitySchemeAndScopesValuePair in this.Where(static p => p.Key?.Target is not null)) { var securityScheme = securitySchemeAndScopesValuePair.Key; var scopes = securitySchemeAndScopesValuePair.Value; - if (securityScheme.Reference == null) - { - // Reaching this point means the reference to a specific OpenApiSecurityScheme fails. - // We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what - // string to output. - continue; - } - - writer.WritePropertyName(securityScheme.Reference.ReferenceV3); + callback(writer, securityScheme); writer.WriteStartArray(); @@ -87,48 +86,19 @@ private void SerializeInternal(IOpenApiWriter writer, Action public void SerializeAsV2(IOpenApiWriter writer) { - Utils.CheckArgumentNull(writer);; - - writer.WriteStartObject(); - - foreach (var securitySchemeAndScopesValuePair in this) - { - var securityScheme = securitySchemeAndScopesValuePair.Key; - var scopes = securitySchemeAndScopesValuePair.Value; - - if (securityScheme.Reference == null) - { - // Reaching this point means the reference to a specific OpenApiSecurityScheme fails. - // We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what - // string to output. - continue; - } - - securityScheme.SerializeAsV2(writer); - - writer.WriteStartArray(); - - foreach (var scope in scopes) - { - writer.WriteValue(scope); - } - - writer.WriteEndArray(); - } - - writer.WriteEndObject(); + SerializeInternal(writer, (w, s) => s.SerializeAsV2(w)); } /// /// Comparer for OpenApiSecurityScheme that only considers the Id in the Reference /// (i.e. the string that will actually be displayed in the written document) /// - private class OpenApiSecuritySchemeReferenceEqualityComparer : IEqualityComparer + private sealed class OpenApiSecuritySchemeReferenceEqualityComparer : IEqualityComparer { /// /// Determines whether the specified objects are equal. /// - public bool Equals(OpenApiSecurityScheme x, OpenApiSecurityScheme y) + public bool Equals(OpenApiSecuritySchemeReference x, OpenApiSecuritySchemeReference y) { if (x == null && y == null) { @@ -140,20 +110,19 @@ public bool Equals(OpenApiSecurityScheme x, OpenApiSecurityScheme y) return false; } - if (x.Reference == null || y.Reference == null) - { - return false; - } - - return x.Reference.Id == y.Reference.Id; + return GetHashCode(x) == GetHashCode(y); } /// /// Returns a hash code for the specified object. /// - public int GetHashCode(OpenApiSecurityScheme obj) + public int GetHashCode(OpenApiSecuritySchemeReference obj) { - return obj?.Reference?.Id == null ? 0 : obj.Reference.Id.GetHashCode(); + if (obj is null) + { + return 0; + } + return string.IsNullOrEmpty(obj?.Reference?.Id) ? 0 : obj.Reference.Id.GetHashCode(); } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs index d9227be25..dddbbffec 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -12,65 +13,34 @@ namespace Microsoft.OpenApi.Models /// /// Security Scheme Object. /// - public class OpenApiSecurityScheme : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiSecurityScheme : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSecurityScheme { - /// - /// REQUIRED. The type of the security scheme. Valid values are "apiKey", "http", "oauth2", "openIdConnect". - /// - public virtual SecuritySchemeType? Type { get; set; } + /// + public SecuritySchemeType? Type { get; set; } - /// - /// A short description for security scheme. CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } + /// + public string Description { get; set; } - /// - /// REQUIRED. The name of the header, query or cookie parameter to be used. - /// - public virtual string Name { get; set; } + /// + public string Name { get; set; } - /// - /// REQUIRED. The location of the API key. Valid values are "query", "header" or "cookie". - /// - public virtual ParameterLocation? In { get; set; } + /// + public ParameterLocation? In { get; set; } - /// - /// REQUIRED. The name of the HTTP Authorization scheme to be used - /// in the Authorization header as defined in RFC7235. - /// - public virtual string Scheme { get; set; } + /// + public string Scheme { get; set; } - /// - /// A hint to the client to identify how the bearer token is formatted. - /// Bearer tokens are usually generated by an authorization server, - /// so this information is primarily for documentation purposes. - /// - public virtual string BearerFormat { get; set; } + /// + public string BearerFormat { get; set; } - /// - /// REQUIRED. An object containing configuration information for the flow types supported. - /// - public virtual OpenApiOAuthFlows Flows { get; set; } + /// + public OpenApiOAuthFlows Flows { get; set; } - /// - /// REQUIRED. OpenId Connect URL to discover OAuth2 configuration values. - /// - public virtual Uri OpenIdConnectUrl { get; set; } + /// + public Uri OpenIdConnectUrl { get; set; } - /// - /// Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); - - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public bool UnresolvedReference { get; set; } - - /// - /// Reference object. - /// - public OpenApiReference Reference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameterless constructor @@ -78,27 +48,26 @@ public class OpenApiSecurityScheme : IOpenApiReferenceable, IOpenApiExtensible public OpenApiSecurityScheme() { } /// - /// Initializes a copy of object + /// Initializes a copy of object /// - public OpenApiSecurityScheme(OpenApiSecurityScheme securityScheme) + internal OpenApiSecurityScheme(IOpenApiSecurityScheme securityScheme) { - Type = securityScheme?.Type; - Description = securityScheme?.Description ?? Description; - Name = securityScheme?.Name ?? Name; - In = securityScheme?.In; - Scheme = securityScheme?.Scheme ?? Scheme; - BearerFormat = securityScheme?.BearerFormat ?? BearerFormat; - Flows = securityScheme?.Flows != null ? new(securityScheme?.Flows) : null; - OpenIdConnectUrl = securityScheme?.OpenIdConnectUrl != null ? new Uri(securityScheme.OpenIdConnectUrl.OriginalString, UriKind.RelativeOrAbsolute) : null; - Extensions = securityScheme?.Extensions != null ? new Dictionary(securityScheme.Extensions) : null; - UnresolvedReference = securityScheme?.UnresolvedReference ?? UnresolvedReference; - Reference = securityScheme?.Reference != null ? new(securityScheme?.Reference) : null; + Utils.CheckArgumentNull(securityScheme); + Type = securityScheme.Type; + Description = securityScheme.Description ?? Description; + Name = securityScheme.Name ?? Name; + In = securityScheme.In; + Scheme = securityScheme.Scheme ?? Scheme; + BearerFormat = securityScheme.BearerFormat ?? BearerFormat; + Flows = securityScheme.Flows != null ? new(securityScheme.Flows) : null; + OpenIdConnectUrl = securityScheme.OpenIdConnectUrl != null ? new Uri(securityScheme.OpenIdConnectUrl.OriginalString, UriKind.RelativeOrAbsolute) : null; + Extensions = securityScheme.Extensions != null ? new Dictionary(securityScheme.Extensions) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } @@ -106,12 +75,12 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -161,7 +130,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio /// /// Serialize to Open Api v2.0 /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); @@ -260,5 +229,11 @@ private static void WriteOAuthFlowForV2(IOpenApiWriter writer, string flowValue, // scopes writer.WriteOptionalMap(OpenApiConstants.Scopes, flow.Scopes, (w, s) => w.WriteValue(s)); } + + /// + public IOpenApiSecurityScheme CreateShallowCopy() + { + return new OpenApiSecurityScheme(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiTag.cs b/src/Microsoft.OpenApi/Models/OpenApiTag.cs index 58fa99694..91e3aac68 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiTag.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiTag.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -11,32 +12,19 @@ namespace Microsoft.OpenApi.Models /// /// Tag Object. /// - public class OpenApiTag : IOpenApiSerializable, IOpenApiExtensible + public class OpenApiTag : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiTag, IOpenApiDescribedElement { - /// - /// The name of the tag. - /// - public virtual string Name { get; set; } + /// + public string Name { get; set; } - /// - /// A short description for the tag. - /// - public virtual string Description { get; set; } - - /// - /// Additional external documentation for this tag. - /// - public virtual OpenApiExternalDocs ExternalDocs { get; set; } + /// + public string Description { get; set; } - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public OpenApiExternalDocs ExternalDocs { get; set; } - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public bool UnresolvedReference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameterless constructor @@ -44,21 +32,21 @@ public class OpenApiTag : IOpenApiSerializable, IOpenApiExtensible public OpenApiTag() { } /// - /// Initializes a copy of an object + /// Initializes a copy of an object /// - public OpenApiTag(OpenApiTag tag) + internal OpenApiTag(IOpenApiTag tag) { - Name = tag?.Name ?? Name; - Description = tag?.Description ?? Description; - ExternalDocs = tag?.ExternalDocs != null ? new(tag.ExternalDocs) : null; - Extensions = tag?.Extensions != null ? new Dictionary(tag.Extensions) : null; - UnresolvedReference = tag?.UnresolvedReference ?? UnresolvedReference; + Utils.CheckArgumentNull(tag); + Name = tag.Name ?? Name; + Description = tag.Description ?? Description; + ExternalDocs = tag.ExternalDocs != null ? new(tag.ExternalDocs) : null; + Extensions = tag.Extensions != null ? new Dictionary(tag.Extensions) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); @@ -67,13 +55,13 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { writer.WriteStartObject(); @@ -96,7 +84,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio /// /// Serialize to Open Api v2.0 /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { writer.WriteStartObject(); @@ -114,5 +102,11 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) writer.WriteEndObject(); } + + /// + public IOpenApiTag CreateShallowCopy() + { + return new OpenApiTag(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs b/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs new file mode 100644 index 000000000..e01545c61 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs @@ -0,0 +1,114 @@ +using System; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; + +namespace Microsoft.OpenApi.Models.References; +/// +/// Base class for OpenApiReferenceHolder. +/// +/// The concrete class implementation type for the model. +/// The interface type for the model. +public abstract class BaseOpenApiReferenceHolder : IOpenApiReferenceHolder where T : class, IOpenApiReferenceable, V where V : IOpenApiSerializable +{ + /// + public virtual T Target + { + get + { + return Reference.HostDocument?.ResolveReferenceTo(Reference); + } + } + /// + /// Copy constructor + /// + /// The parameter reference to copy + protected BaseOpenApiReferenceHolder(BaseOpenApiReferenceHolder source) + { + Utils.CheckArgumentNull(source); + Reference = source.Reference != null ? new(source.Reference) : null; + //no need to copy summary and description as if they are not overridden, they will be fetched from the target + //if they are, the reference copy will handle it + } + /// + /// Constructor initializing the reference object. + /// + /// The reference Id. + /// The host OpenAPI document. + /// The reference type. + /// Optional: External resource in the reference. + /// It may be: + /// 1. a absolute/relative file path, for example: ../commons/pet.json + /// 2. a Url, for example: http://localhost/pet.json + /// + protected BaseOpenApiReferenceHolder(string referenceId, OpenApiDocument hostDocument, ReferenceType referenceType, string externalResource) + { + Utils.CheckArgumentNullOrEmpty(referenceId); + // we're not checking for null hostDocument as it's optional and can be set via additional methods by a walker + // this way object initialization of a whole document is supported + + Reference = new OpenApiReference() + { + Id = referenceId, + HostDocument = hostDocument, + Type = referenceType, + ExternalResource = externalResource + }; + } + /// + public bool UnresolvedReference { get => Reference is null || Target is null; } + /// + public OpenApiReference Reference { get; init; } + /// + public abstract V CopyReferenceAsTargetElementWithOverrides(V source); + /// + public virtual void SerializeAsV3(IOpenApiWriter writer) + { + if (!writer.GetSettings().ShouldInlineReference(Reference)) + { + Reference.SerializeAsV3(writer); + } + else + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); + } + } + + /// + public virtual void SerializeAsV31(IOpenApiWriter writer) + { + if (!writer.GetSettings().ShouldInlineReference(Reference)) + { + Reference.SerializeAsV31(writer); + } + else + { + SerializeInternal(writer, (writer, element) => CopyReferenceAsTargetElementWithOverrides(element).SerializeAsV31(writer)); + } + } + + /// + public virtual void SerializeAsV2(IOpenApiWriter writer) + { + if (!writer.GetSettings().ShouldInlineReference(Reference)) + { + Reference.SerializeAsV2(writer); + } + else + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); + } + } + + /// + /// Serialize the reference as a reference or the target object. + /// This method is used to accelerate the serialization methods implementations. + /// + /// The OpenApiWriter. + /// The action to serialize the target object. + private protected void SerializeInternal(IOpenApiWriter writer, + Action action) + { + Utils.CheckArgumentNull(writer); + action(writer, Target); + } +} diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs index 81985cb12..4c30328d4 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Expressions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models.References @@ -12,28 +13,8 @@ namespace Microsoft.OpenApi.Models.References /// /// Callback Object Reference: A reference to a map of possible out-of band callbacks related to the parent operation. /// - public class OpenApiCallbackReference : OpenApiCallback, IOpenApiReferenceableWithTarget + public class OpenApiCallbackReference : BaseOpenApiReferenceHolder, IOpenApiCallback { -#nullable enable - internal OpenApiCallback _target; - private readonly OpenApiReference _reference; - - /// - /// Gets the target callback. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiCallback Target -#nullable restore - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - return _target; - } - } - /// /// Constructor initializing the reference object. /// @@ -44,72 +25,41 @@ public OpenApiCallback Target /// 1. an absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiCallbackReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiCallbackReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Callback, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Callback, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiCallbackReference(OpenApiCallback target, string referenceId) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiCallbackReference(OpenApiCallbackReference callback):base(callback) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.Callback, - }; + } /// - public override Dictionary PathItems { get => Target.PathItems; set => Target.PathItems = value; } + public Dictionary PathItems { get => Target?.PathItems; } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override void SerializeAsV3(IOpenApiWriter writer) + public override IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(IOpenApiCallback source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } + return source is OpenApiCallback ? new OpenApiCallback(this) : source; } /// - public override void SerializeAsV31(IOpenApiWriter writer) + public override void SerializeAsV2(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } + // examples components are not supported in OAS 2.0 + Reference.SerializeAsV2(writer); } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiCallback CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - action(writer, Target); + return new OpenApiCallbackReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs index c36c43d9a..edfe27b61 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Text.Json.Nodes; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models.References @@ -12,31 +13,8 @@ namespace Microsoft.OpenApi.Models.References /// /// Example Object Reference. /// - public class OpenApiExampleReference : OpenApiExample, IOpenApiReferenceableWithTarget + public class OpenApiExampleReference : BaseOpenApiReferenceHolder, IOpenApiExample { - internal OpenApiExample _target; - private readonly OpenApiReference _reference; - private string _summary; - private string _description; - - /// - /// Gets the target example. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiExample Target - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiExample resolved = new OpenApiExample(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - if (!string.IsNullOrEmpty(_summary)) resolved.Summary = _summary; - return resolved; - } - } - /// /// Constructor initializing the reference object. /// @@ -47,89 +25,69 @@ public OpenApiExample Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiExampleReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiExampleReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Example, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Example, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiExampleReference(OpenApiExample target, string referenceId) + /// + /// Copy constructor + /// + /// The example reference to copy + private OpenApiExampleReference(OpenApiExampleReference example):base(example) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.Example, - }; } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override string Summary + public string Summary { - get => string.IsNullOrEmpty(_summary) ? Target.Summary : _summary; - set => _summary = value; + get => string.IsNullOrEmpty(Reference?.Summary) ? Target?.Summary : Reference.Summary; + set + { + if (Reference is not null) + { + Reference.Summary = value; + } + } } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override string ExternalValue { get => Target.ExternalValue; set => Target.ExternalValue = value; } + public string ExternalValue { get => Target?.ExternalValue; } /// - public override JsonNode Value { get => Target.Value; set => Target.Value = value; } + public JsonNode Value { get => Target?.Value; } /// - public override void SerializeAsV3(IOpenApiWriter writer) + public override IOpenApiExample CopyReferenceAsTargetElementWithOverrides(IOpenApiExample source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - else - { - SerializeInternal(writer, (writer, referenceElement) => referenceElement.SerializeAsV3(writer)); - } + return source is OpenApiExample ? new OpenApiExample(this) : source; } /// - public override void SerializeAsV31(IOpenApiWriter writer) + public override void SerializeAsV2(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, referenceElement) => referenceElement.SerializeAsV31(writer)); - } + // examples components are not supported in OAS 2.0 + Reference.SerializeAsV2(writer); } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiExample CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - action(writer, Target); + return new OpenApiExampleReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs index e8275c23c..719cdce3a 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs @@ -5,36 +5,15 @@ using System.Collections.Generic; using System.Text.Json.Nodes; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Models.References { /// /// Header Object Reference. /// - public class OpenApiHeaderReference : OpenApiHeader, IOpenApiReferenceableWithTarget + public class OpenApiHeaderReference : BaseOpenApiReferenceHolder, IOpenApiHeader { - internal OpenApiHeader _target; - private readonly OpenApiReference _reference; - private string _description; - - /// - /// Gets the target header. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiHeader Target - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiHeader resolved = new OpenApiHeader(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; - } - } - /// /// Constructor initializing the reference object. /// @@ -45,120 +24,74 @@ public OpenApiHeader Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiHeaderReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiHeaderReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Header, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Header, - ExternalResource = externalResource - }; - - Reference = _reference; } - internal OpenApiHeaderReference(OpenApiHeader target, string referenceId) + /// + /// Copy constructor + /// + /// The object to copy + private OpenApiHeaderReference(OpenApiHeaderReference header):base(header) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.Header, - }; } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override bool Required { get => Target.Required; set => Target.Required = value; } - - /// - public override bool Deprecated { get => Target.Deprecated; set => Target.Deprecated = value; } + public bool Required { get => Target?.Required ?? default; } /// - public override bool AllowEmptyValue { get => Target.AllowEmptyValue; set => Target.AllowEmptyValue = value; } + public bool Deprecated { get => Target?.Deprecated ?? default; } /// - public override OpenApiSchema Schema { get => Target.Schema; set => Target.Schema = value; } + public bool AllowEmptyValue { get => Target?.AllowEmptyValue ?? default; } /// - public override ParameterStyle? Style { get => Target.Style; set => Target.Style = value; } + public IOpenApiSchema Schema { get => Target?.Schema; } /// - public override bool Explode { get => Target.Explode; set => Target.Explode = value; } + public ParameterStyle? Style { get => Target?.Style; } /// - public override bool AllowReserved { get => Target.AllowReserved; set => Target.AllowReserved = value; } + public bool Explode { get => Target?.Explode ?? default; } /// - public override JsonNode Example { get => Target.Example; set => Target.Example = value; } + public bool AllowReserved { get => Target?.AllowReserved ?? default; } /// - public override IDictionary Examples { get => Target.Examples; set => Target.Examples = value; } + public JsonNode Example { get => Target?.Example; } /// - public override IDictionary Content { get => Target.Content; set => Target.Content = value; } + public IDictionary Examples { get => Target?.Examples; } /// - public override IDictionary Extensions { get => base.Extensions; set => base.Extensions = value; } - - /// - public override void SerializeAsV31(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } - } + public IDictionary Content { get => Target?.Content; } /// - public override void SerializeAsV3(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } - } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override void SerializeAsV2(IOpenApiWriter writer) + public override IOpenApiHeader CopyReferenceAsTargetElementWithOverrides(IOpenApiHeader source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); - } + return source is OpenApiHeader ? new OpenApiHeader(this) : source; } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiHeader CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - action(writer, Target); + return new OpenApiHeaderReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs index 05817ddc9..f91b5711b 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models.References @@ -11,29 +12,8 @@ namespace Microsoft.OpenApi.Models.References /// /// Link Object Reference. /// - public class OpenApiLinkReference : OpenApiLink, IOpenApiReferenceableWithTarget + public class OpenApiLinkReference : BaseOpenApiReferenceHolder, IOpenApiLink { - internal OpenApiLink _target; - private readonly OpenApiReference _reference; - private string _description; - - /// - /// Gets the target link. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiLink Target - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiLink resolved = new OpenApiLink(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; - } - } - /// /// Constructor initializing the reference object. /// @@ -44,91 +24,64 @@ public OpenApiLink Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiLinkReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiLinkReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Link, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Link, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiLinkReference(OpenApiLink target, string referenceId) + /// + /// Copy constructor. + /// + /// The reference to copy + private OpenApiLinkReference(OpenApiLinkReference reference):base(reference) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.Link, - }; } /// - public override string OperationRef { get => Target.OperationRef; set => Target.OperationRef = value; } + public string Description + { + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } + } /// - public override string OperationId { get => Target.OperationId; set => Target.OperationId = value; } + public string OperationRef { get => Target?.OperationRef; } /// - public override OpenApiServer Server { get => Target.Server; set => Target.Server = value; } + public string OperationId { get => Target?.OperationId; } /// - public override string Description - { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; - } + public OpenApiServer Server { get => Target?.Server; } /// - public override Dictionary Parameters { get => Target.Parameters; set => Target.Parameters = value; } + public IDictionary Parameters { get => Target?.Parameters; } /// - public override RuntimeExpressionAnyWrapper RequestBody { get => Target.RequestBody; set => Target.RequestBody = value; } + public RuntimeExpressionAnyWrapper RequestBody { get => Target?.RequestBody; } /// - public override IDictionary Extensions { get => base.Extensions; set => base.Extensions = value; } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override void SerializeAsV3(IOpenApiWriter writer) + public override void SerializeAsV2(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } + // Link object does not exist in V2. } /// - public override void SerializeAsV31(IOpenApiWriter writer) + public override IOpenApiLink CopyReferenceAsTargetElementWithOverrides(IOpenApiLink source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } - } + return source is OpenApiLink ? new OpenApiLink(this) : source; + } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiLink CreateShallowCopy() { - Utils.CheckArgumentNull(writer);; - action(writer, Target); + return new OpenApiLinkReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs index 9df1e7be2..d337b841e 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs @@ -1,42 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System; using System.Collections.Generic; using System.Text.Json.Nodes; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Models.References { /// /// Parameter Object Reference. /// - public class OpenApiParameterReference : OpenApiParameter, IOpenApiReferenceableWithTarget + public class OpenApiParameterReference : BaseOpenApiReferenceHolder, IOpenApiParameter { - internal OpenApiParameter _target; - private readonly OpenApiReference _reference; - private string _description; - private bool? _explode; - private ParameterStyle? _style; - - /// - /// Gets the target parameter. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiParameter Target - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiParameter resolved = new OpenApiParameter(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; - } - } - /// /// Constructor initializing the reference object. /// @@ -47,134 +23,80 @@ public OpenApiParameter Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiParameterReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiParameterReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Parameter, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Parameter, - ExternalResource = externalResource - }; - - Reference = _reference; } - internal OpenApiParameterReference(OpenApiParameter target, string referenceId) + /// + /// Copy constructor + /// + /// The parameter reference to copy + private OpenApiParameterReference(OpenApiParameterReference parameter):base(parameter) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.Parameter, - }; } /// - public override string Name { get => Target.Name; set => Target.Name = value; } + public string Name { get => Target?.Name; } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override bool Required { get => Target.Required; set => Target.Required = value; } + public bool Required { get => Target?.Required ?? default; } /// - public override bool Deprecated { get => Target.Deprecated; set => Target.Deprecated = value; } + public bool Deprecated { get => Target?.Deprecated ?? default; } /// - public override bool AllowEmptyValue { get => Target.AllowEmptyValue; set => Target.AllowEmptyValue = value; } + public bool AllowEmptyValue { get => Target?.AllowEmptyValue ?? default; } /// - public override bool AllowReserved { get => Target.AllowReserved; set => Target.AllowReserved = value; } + public bool AllowReserved { get => Target?.AllowReserved ?? default; } /// - public override OpenApiSchema Schema { get => Target.Schema; set => Target.Schema = value; } + public IOpenApiSchema Schema { get => Target?.Schema; } /// - public override IDictionary Examples { get => Target.Examples; set => Target.Examples = value; } + public IDictionary Examples { get => Target?.Examples; } /// - public override JsonNode Example { get => Target.Example; set => Target.Example = value; } + public JsonNode Example { get => Target?.Example; } /// - public override ParameterLocation? In { get => Target.In; set => Target.In = value; } + public ParameterLocation? In { get => Target?.In; } /// - public override ParameterStyle? Style - { - get => _style ?? GetDefaultStyleValue(); - set => _style = value; - } + public ParameterStyle? Style { get => Target?.Style; } /// - public override bool Explode - { - get => _explode ?? Style == ParameterStyle.Form; - set => _explode = value; - } + public bool Explode { get => Target?.Explode ?? default; } /// - public override IDictionary Content { get => Target.Content; set => Target.Content = value; } + public IDictionary Content { get => Target?.Content; } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override void SerializeAsV3(IOpenApiWriter writer) + public override IOpenApiParameter CopyReferenceAsTargetElementWithOverrides(IOpenApiParameter source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } - } - - /// - public override void SerializeAsV31(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } - } - - /// - public override void SerializeAsV2(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); - } + return source is OpenApiParameter ? new OpenApiParameter(this) : source; } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiParameter CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - action(writer, Target); + return new OpenApiParameterReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs index fad8922ae..038e1cb13 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models.References @@ -11,30 +11,8 @@ namespace Microsoft.OpenApi.Models.References /// /// Path Item Object Reference: to describe the operations available on a single path. /// - public class OpenApiPathItemReference : OpenApiPathItem, IOpenApiReferenceableWithTarget + public class OpenApiPathItemReference : BaseOpenApiReferenceHolder, IOpenApiPathItem { - internal OpenApiPathItem _target; - private readonly OpenApiReference _reference; - private string _description; - private string _summary; - - /// - /// Gets the target path item. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiPathItem Target - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiPathItem resolved = new OpenApiPathItem(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - if (!string.IsNullOrEmpty(_summary)) resolved.Summary = _summary; - return resolved; - } - } /// /// Constructor initializing the reference object. @@ -46,78 +24,73 @@ public OpenApiPathItem Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiPathItemReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiPathItemReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null): base(referenceId, hostDocument, ReferenceType.PathItem, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.PathItem, - ExternalResource = externalResource - }; - - Reference = _reference; } - internal OpenApiPathItemReference(OpenApiPathItem target, string referenceId) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiPathItemReference(OpenApiPathItemReference pathItem):base(pathItem) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.PathItem, - }; + } /// - public override string Summary + public string Summary { - get => string.IsNullOrEmpty(_summary) ? Target.Summary : _summary; - set => _summary = value; + get => string.IsNullOrEmpty(Reference?.Summary) ? Target?.Summary : Reference.Summary; + set + { + if (Reference is not null) + { + Reference.Summary = value; + } + } } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override IDictionary Operations { get => Target.Operations; set => Target.Operations = value; } + public IDictionary Operations { get => Target?.Operations; } /// - public override IList Servers { get => Target.Servers; set => Target.Servers = value; } + public IList Servers { get => Target?.Servers; } /// - public override IList Parameters { get => Target.Parameters; set => Target.Parameters = value; } + public IList Parameters { get => Target?.Parameters; } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } - + public IDictionary Extensions { get => Target?.Extensions; } + /// - public override void SerializeAsV31(IOpenApiWriter writer) + public override IOpenApiPathItem CopyReferenceAsTargetElementWithOverrides(IOpenApiPathItem source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } + return source is OpenApiPathItem ? new OpenApiPathItem(this) : source; + } + + /// + public IOpenApiPathItem CreateShallowCopy() + { + return new OpenApiPathItemReference(this); } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public override void SerializeAsV2(IOpenApiWriter writer) { - Utils.CheckArgumentNull(writer);; - action(writer, Target); + Reference.SerializeAsV2(writer); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs index 598d70310..966d3aad1 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models.References @@ -11,29 +13,8 @@ namespace Microsoft.OpenApi.Models.References /// /// Request Body Object Reference. /// - public class OpenApiRequestBodyReference : OpenApiRequestBody, IOpenApiReferenceableWithTarget + public class OpenApiRequestBodyReference : BaseOpenApiReferenceHolder, IOpenApiRequestBody { - internal OpenApiRequestBody _target; - private readonly OpenApiReference _reference; - private string _description; - - /// - /// Gets the target request body. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiRequestBody Target - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiRequestBody resolved = new OpenApiRequestBody(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; - } - } - /// /// Constructor initializing the reference object. /// @@ -44,82 +25,80 @@ public OpenApiRequestBody Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiRequestBodyReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiRequestBodyReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.RequestBody, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.RequestBody, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiRequestBodyReference(OpenApiRequestBody target, string referenceId) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiRequestBodyReference(OpenApiRequestBodyReference openApiRequestBodyReference):base(openApiRequestBodyReference) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.RequestBody, - }; + } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override IDictionary Content { get => Target.Content; set => Target.Content = value; } + public IDictionary Content { get => Target?.Content; } /// - public override bool Required { get => Target.Required; set => Target.Required = value; } + public bool Required { get => Target?.Required ?? false; } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override void SerializeAsV3(IOpenApiWriter writer) + public override IOpenApiRequestBody CopyReferenceAsTargetElementWithOverrides(IOpenApiRequestBody source) + { + return source is OpenApiRequestBody ? new OpenApiRequestBody(this) : source; + } + /// + public override void SerializeAsV2(IOpenApiWriter writer) + { + // doesn't exist in v2 + } + /// + public IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) + if (writer.GetSettings().ShouldInlineReference(Reference)) { - _reference.SerializeAsV3(writer); - return; + return Target.ConvertToBodyParameter(writer); } else { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); + return new OpenApiParameterReference(Reference.Id, Reference.HostDocument); } } - /// - public override void SerializeAsV31(IOpenApiWriter writer) + public IEnumerable ConvertToFormDataParameters(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) + if (writer.GetSettings().ShouldInlineReference(Reference)) { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); + return Target.ConvertToFormDataParameters(writer); } + + if (Content == null || !Content.Any()) + return []; + + return Content.First().Value.Schema.Properties.Select(x => new OpenApiParameterReference(x.Key, Reference.HostDocument)); } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiRequestBody CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - action(writer, Target); + return new OpenApiRequestBodyReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs index 0e4ac30ac..9fbfb47a0 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs @@ -4,36 +4,15 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Models.References { /// /// Response Object Reference. /// - public class OpenApiResponseReference : OpenApiResponse, IOpenApiReferenceableWithTarget + public class OpenApiResponseReference : BaseOpenApiReferenceHolder, IOpenApiResponse { - internal OpenApiResponse _target; - private readonly OpenApiReference _reference; - private string _description; - - /// - /// Gets the target response. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiResponse Target - { - get - { - _target ??= Reference.HostDocument?.ResolveReferenceTo(_reference); - OpenApiResponse resolved = new OpenApiResponse(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; - } - } - /// /// Constructor initializing the reference object. /// @@ -44,101 +23,53 @@ public OpenApiResponse Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiResponseReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiResponseReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Response, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Response, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiResponseReference(string referenceId, OpenApiResponse target) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiResponseReference(OpenApiResponseReference openApiResponseReference):base(openApiResponseReference) { - _target ??= target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.Response, - }; - - Reference = _reference; + } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override IDictionary Content { get => Target?.Content; set => Target.Content = value; } + public IDictionary Content { get => Target?.Content; } /// - public override IDictionary Headers { get => Target.Headers; set => Target.Headers = value; } + public IDictionary Headers { get => Target?.Headers; } /// - public override IDictionary Links { get => Target.Links; set => Target.Links = value; } + public IDictionary Links { get => Target?.Links; } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } - - /// - public override void SerializeAsV3(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } - } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override void SerializeAsV31(IOpenApiWriter writer) + public override IOpenApiResponse CopyReferenceAsTargetElementWithOverrides(IOpenApiResponse source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } - } - - /// - public override void SerializeAsV2(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); - } + return source is OpenApiResponse ? new OpenApiResponse(this) : source; } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiResponse CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - action(writer, this); + return new OpenApiResponseReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs index da2f9b745..9252d6b89 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; using System; using System.Collections.Generic; @@ -12,79 +13,8 @@ namespace Microsoft.OpenApi.Models.References /// /// Schema reference object /// - public class OpenApiSchemaReference : OpenApiSchema, IOpenApiReferenceableWithTarget + public class OpenApiSchemaReference : BaseOpenApiReferenceHolder, IOpenApiSchema { -#nullable enable - private OpenApiSchema? _target; - private readonly OpenApiReference _reference; - private string? _description; - private JsonNode? _default; - private JsonNode? _example; - private IList? _examples; - private bool? _nullable; - private IDictionary? _properties; - private string? _title; - private string? _schema; - private string? _comment; - private string? _id; - private string? _dynamicRef; - private string? _dynamicAnchor; - private IDictionary? _vocabulary; - private IDictionary? _definitions; - private decimal? _v31ExclusiveMaximum; - private decimal? _v31ExclusiveMinimum; - private bool? _unEvaluatedProperties; - private JsonSchemaType? _type; - private string? _const; - private string? _format; - private decimal? _maximum; - private bool? _exclusiveMaximum; - private decimal? _minimum; - private bool? _exclusiveMinimum; - private int? _maxLength; - private int? _minLength; - private string? _pattern; - private decimal? _multipleOf; - private bool? _readOnly; - private bool? _writeOnly; - private IList? _allOf; - private IList? _oneOf; - private IList? _anyOf; - private OpenApiSchema? _not; - private ISet? _required; - private OpenApiSchema _items; - private int? _maxItems; - private int? _minItems; - private bool? _uniqueItems; - private IDictionary? _patternProperties; - private int? _maxProperties; - private int? _minProperties; - private bool? _additionalPropertiesAllowed; - private OpenApiSchema? _additionalProperties; - private OpenApiDiscriminator? _discriminator; - private OpenApiExternalDocs? _externalDocs; - private bool? _deprecated; - private OpenApiXml? _xml; - private IDictionary? _extensions; - private bool? _unevaluatedProperties; - private IList? _enum; - - /// - /// Gets the target schema. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiSchema? Target -#nullable restore - { - get - { - _target ??= Reference.HostDocument?.ResolveReferenceTo(_reference); - return _target; - } - } - /// /// Constructor initializing the reference object. /// @@ -95,214 +25,179 @@ public OpenApiSchema? Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiSchemaReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiSchemaReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Schema, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Schema, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiSchemaReference(OpenApiSchema target, string referenceId) + /// + /// Copy constructor + /// + /// The schema reference to copy + private OpenApiSchemaReference(OpenApiSchemaReference schema):base(schema) { - _target = target; + } - _reference = new OpenApiReference() + /// + public string Description + { + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set { - Id = referenceId, - Type = ReferenceType.Schema, - }; + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override string Title { get => string.IsNullOrEmpty(_title) ? Target?.Title : _title; set => _title = value; } + public string Title { get => Target?.Title; } /// - public override string Schema { get => string.IsNullOrEmpty(_schema) ? Target?.Schema : _schema; set => _schema = value; } + public string Schema { get => Target?.Schema; } /// - public override string Id { get => string.IsNullOrEmpty(_id) ? Target?.Id : _id; set => _id = value; } + public string Id { get => Target?.Id; } /// - public override string Comment { get => string.IsNullOrEmpty(_comment) ? Target?.Comment : _comment; set => _comment = value; } + public string Comment { get => Target?.Comment; } /// - public override IDictionary Vocabulary { get => _vocabulary is not null ? _vocabulary : Target?.Vocabulary; set => _vocabulary = value; } + public IDictionary Vocabulary { get => Target?.Vocabulary; } /// - public override string DynamicRef { get => string.IsNullOrEmpty(_dynamicRef) ? Target?.DynamicRef : _dynamicRef; set => _dynamicRef = value; } + public string DynamicRef { get => Target?.DynamicRef; } /// - public override string DynamicAnchor { get => string.IsNullOrEmpty(_dynamicAnchor) ? Target?.DynamicAnchor : _dynamicAnchor; set => _dynamicAnchor = value; } + public string DynamicAnchor { get => Target?.DynamicAnchor; } /// - public override IDictionary Definitions { get => _definitions is not null ? _definitions : Target?.Definitions; set => _definitions = value; } + public IDictionary Definitions { get => Target?.Definitions; } /// - public override decimal? V31ExclusiveMaximum { get => _v31ExclusiveMaximum is not null ? _v31ExclusiveMaximum.Value : Target?.V31ExclusiveMaximum; set => _v31ExclusiveMaximum = value; } + public decimal? V31ExclusiveMaximum { get => Target?.V31ExclusiveMaximum; } /// - public override decimal? V31ExclusiveMinimum { get => _v31ExclusiveMinimum is not null ? _v31ExclusiveMinimum.Value : Target?.V31ExclusiveMinimum; set => _v31ExclusiveMinimum = value; } + public decimal? V31ExclusiveMinimum { get => Target?.V31ExclusiveMinimum; } /// - public override bool UnEvaluatedProperties { get => _unEvaluatedProperties is not null ? _unEvaluatedProperties.Value : Target?.UnEvaluatedProperties ?? false; set => _unEvaluatedProperties = value; } + public bool UnEvaluatedProperties { get => Target?.UnEvaluatedProperties ?? false; } /// - public override JsonSchemaType? Type { get => _type is not null ? _type.Value : Target?.Type; set => _type = value; } + public JsonSchemaType? Type { get => Target?.Type; } /// - public override string Const { get => string.IsNullOrEmpty(_const) ? Target?.Const : _const; set => _const = value; } + public string Const { get => Target?.Const; } /// - public override string Format { get => string.IsNullOrEmpty(_format) ? Target?.Format : _format; set => _format = value; } + public string Format { get => Target?.Format; } /// - public override string Description - { - get => string.IsNullOrEmpty(_description) ? Target?.Description : _description; - set => _description = value; - } + public decimal? Maximum { get => Target?.Maximum; } /// - public override decimal? Maximum { get => _maximum is not null ? _maximum : Target?.Maximum; set => _maximum = value; } + public bool? ExclusiveMaximum { get => Target?.ExclusiveMaximum; } /// - public override bool? ExclusiveMaximum { get => _exclusiveMaximum is not null ? _exclusiveMaximum : Target?.ExclusiveMaximum; set => _exclusiveMaximum = value; } + public decimal? Minimum { get => Target?.Minimum; } /// - public override decimal? Minimum { get => _minimum is not null ? _minimum : Target?.Minimum; set => _minimum = value; } + public bool? ExclusiveMinimum { get => Target?.ExclusiveMinimum; } /// - public override bool? ExclusiveMinimum { get => _exclusiveMinimum is not null ? _exclusiveMinimum : Target?.ExclusiveMinimum; set => _exclusiveMinimum = value; } + public int? MaxLength { get => Target?.MaxLength; } /// - public override int? MaxLength { get => _maxLength is not null ? _maxLength : Target?.MaxLength; set => _maxLength = value; } + public int? MinLength { get => Target?.MinLength; } /// - public override int? MinLength { get => _minLength is not null ? _minLength : Target?.MinLength; set => _minLength = value; } + public string Pattern { get => Target?.Pattern; } /// - public override string Pattern { get => string.IsNullOrEmpty(_pattern) ? Target?.Pattern : _pattern; set => _pattern = value; } + public decimal? MultipleOf { get => Target?.MultipleOf; } /// - public override decimal? MultipleOf { get => _multipleOf is not null ? _multipleOf : Target?.MultipleOf; set => _multipleOf = value; } + public JsonNode Default { get => Target?.Default; } /// - public override JsonNode Default { get => _default is not null ? _default : Target?.Default; set => _default = value; } + public bool ReadOnly { get => Target?.ReadOnly ?? false; } /// - public override bool ReadOnly { get => _readOnly is not null ? _readOnly.Value : Target?.ReadOnly ?? false; set => _readOnly = value; } + public bool WriteOnly { get => Target?.WriteOnly ?? false; } /// - public override bool WriteOnly { get => _writeOnly is not null ? _writeOnly.Value : Target?.WriteOnly ?? false; set => _writeOnly = value; } + public IList AllOf { get => Target?.AllOf; } /// - public override IList AllOf { get => _allOf is not null ? _allOf : Target?.AllOf; set => _allOf = value; } + public IList OneOf { get => Target?.OneOf; } /// - public override IList OneOf { get => _oneOf is not null ? _oneOf : Target?.OneOf; set => _oneOf = value; } + public IList AnyOf { get => Target?.AnyOf; } /// - public override IList AnyOf { get => _anyOf is not null ? _anyOf : Target?.AnyOf; set => _anyOf = value; } + public IOpenApiSchema Not { get => Target?.Not; } /// - public override OpenApiSchema Not { get => _not is not null ? _not : Target?.Not; set => _not = value; } + public ISet Required { get => Target?.Required; } /// - public override ISet Required { get => _required is not null ? _required : Target?.Required; set => _required = value; } + public IOpenApiSchema Items { get => Target?.Items; } /// - public override OpenApiSchema Items { get => _items is not null ? _items : Target?.Items; set => _items = value; } + public int? MaxItems { get => Target?.MaxItems; } /// - public override int? MaxItems { get => _maxItems is not null ? _maxItems : Target?.MaxItems; set => _maxItems = value; } + public int? MinItems { get => Target?.MinItems; } /// - public override int? MinItems { get => _minItems is not null ? _minItems : Target?.MinItems; set => _minItems = value; } + public bool? UniqueItems { get => Target?.UniqueItems; } /// - public override bool? UniqueItems { get => _uniqueItems is not null ? _uniqueItems : Target?.UniqueItems; set => _uniqueItems = value; } + public IDictionary Properties { get => Target?.Properties; } /// - public override IDictionary Properties { get => _properties is not null ? _properties : Target?.Properties; set => _properties = value; } + public IDictionary PatternProperties { get => Target?.PatternProperties; } /// - public override IDictionary PatternProperties { get => _patternProperties is not null ? _patternProperties : Target?.PatternProperties; set => _patternProperties = value; } + public int? MaxProperties { get => Target?.MaxProperties; } /// - public override int? MaxProperties { get => _maxProperties is not null ? _maxProperties : Target?.MaxProperties; set => _maxProperties = value; } + public int? MinProperties { get => Target?.MinProperties; } /// - public override int? MinProperties { get => _minProperties is not null ? _minProperties : Target?.MinProperties; set => _minProperties = value; } + public bool AdditionalPropertiesAllowed { get => Target?.AdditionalPropertiesAllowed ?? true; } /// - public override bool AdditionalPropertiesAllowed { get => _additionalPropertiesAllowed is not null ? _additionalPropertiesAllowed.Value : Target?.AdditionalPropertiesAllowed ?? true; set => _additionalPropertiesAllowed = value; } + public IOpenApiSchema AdditionalProperties { get => Target?.AdditionalProperties; } /// - public override OpenApiSchema AdditionalProperties { get => _additionalProperties is not null ? _additionalProperties : Target?.AdditionalProperties; set => _additionalProperties = value; } + public OpenApiDiscriminator Discriminator { get => Target?.Discriminator; } /// - public override OpenApiDiscriminator Discriminator { get => _discriminator is not null ? _discriminator : Target?.Discriminator; set => _discriminator = value; } + public JsonNode Example { get => Target?.Example; } /// - public override JsonNode Example { get => _example is not null ? _example : Target?.Example; set => _example = value; } + public IList Examples { get => Target?.Examples; } /// - public override IList Examples { get => _examples is not null ? _examples : Target?.Examples; set => _examples = value; } + public IList Enum { get => Target?.Enum; } /// - public override IList Enum { get => _enum is not null ? _enum : Target?.Enum; set => _enum = value; } + public bool UnevaluatedProperties { get => Target?.UnevaluatedProperties ?? false; } /// - public override bool Nullable { get => _nullable is not null ? _nullable.Value : Target?.Nullable ?? false; set => _nullable = value; } + public OpenApiExternalDocs ExternalDocs { get => Target?.ExternalDocs; } /// - public override bool UnevaluatedProperties { get => _unevaluatedProperties is not null ? _unevaluatedProperties.Value : Target?.UnevaluatedProperties ?? false; set => _unevaluatedProperties = value; } + public bool Deprecated { get => Target?.Deprecated ?? false; } /// - public override OpenApiExternalDocs ExternalDocs { get => _externalDocs is not null ? _externalDocs : Target?.ExternalDocs; set => _externalDocs = value; } + public OpenApiXml Xml { get => Target?.Xml; } /// - public override bool Deprecated { get => _deprecated is not null ? _deprecated.Value : Target?.Deprecated ?? false; set => _deprecated = value; } + public IDictionary Extensions { get => Target?.Extensions; } + /// - public override OpenApiXml Xml { get => _xml is not null ? _xml : Target?.Xml; set => _xml = value; } + public IDictionary UnrecognizedKeywords { get => Target?.UnrecognizedKeywords; } + /// - public override IDictionary Extensions { get => _extensions is not null ? _extensions : Target?.Extensions; set => _extensions = value; } + public IDictionary Annotations { get => Target?.Annotations; } /// public override void SerializeAsV31(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - // If Loop is detected then just Serialize as a reference. - else if (!writer.GetSettings().LoopDetector.PushLoop(this)) - { - writer.GetSettings().LoopDetector.SaveLoop(this); - _reference.SerializeAsV31(writer); - return; - } - - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - writer.GetSettings().LoopDetector.PopLoop(); + SerializeAsWithoutLoops(writer, (w, element) => (element is IOpenApiSchema s ? CopyReferenceAsTargetElementWithOverrides(s) : element).SerializeAsV3(w)); } /// public override void SerializeAsV3(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - // If Loop is detected then just Serialize as a reference. - else if (!writer.GetSettings().LoopDetector.PushLoop(this)) - { - writer.GetSettings().LoopDetector.SaveLoop(this); - _reference.SerializeAsV3(writer); - return; - } - - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - writer.GetSettings().LoopDetector.PopLoop(); + SerializeAsWithoutLoops(writer, (w, element) => element.SerializeAsV3(w)); } - /// - internal override void SerializeAsV2( - IOpenApiWriter writer, - ISet parentRequiredProperties, - string propertyName) + public override void SerializeAsV2(IOpenApiWriter writer) + { + SerializeAsWithoutLoops(writer, (w, element) => element.SerializeAsV2(w)); + } + private void SerializeAsWithoutLoops(IOpenApiWriter writer, Action action) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) + if (!writer.GetSettings().ShouldInlineReference(Reference)) { - _reference.SerializeAsV2(writer); + action(writer, Reference); + } + // If Loop is detected then just Serialize as a reference. + else if (!writer.GetSettings().LoopDetector.PushLoop(this)) + { + writer.GetSettings().LoopDetector.SaveLoop(this); + action(writer, Reference); } else { - base.SerializeAsV2(writer, parentRequiredProperties, propertyName); + SerializeInternal(writer, (w, element) => action(w, element)); + writer.GetSettings().LoopDetector.PopLoop(); } - } + } /// - public override void SerializeAsV2(IOpenApiWriter writer) + public override IOpenApiSchema CopyReferenceAsTargetElementWithOverrides(IOpenApiSchema source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); - } + return source is OpenApiSchema ? new OpenApiSchema(this) : source; } - /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiSchema CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - action(writer, Target); + return new OpenApiSchemaReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs index dcd5009b1..75ca30573 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs @@ -4,147 +4,80 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Models.References { /// /// Security Scheme Object Reference. /// - public class OpenApiSecuritySchemeReference : OpenApiSecurityScheme, IOpenApiReferenceableWithTarget + public class OpenApiSecuritySchemeReference : BaseOpenApiReferenceHolder, IOpenApiSecurityScheme { - internal OpenApiSecurityScheme _target; - private readonly OpenApiReference _reference; - private string _description; - - /// - /// Gets the target security scheme. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiSecurityScheme Target - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiSecurityScheme resolved = new OpenApiSecurityScheme(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; - } - } - /// /// Constructor initializing the reference object. /// /// The reference Id. /// The host OpenAPI document. /// The externally referenced file. - public OpenApiSecuritySchemeReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiSecuritySchemeReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.SecurityScheme, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.SecurityScheme, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiSecuritySchemeReference(string referenceId, OpenApiSecurityScheme target) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiSecuritySchemeReference(OpenApiSecuritySchemeReference openApiSecuritySchemeReference):base(openApiSecuritySchemeReference) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.SecurityScheme, - }; + } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override string Name { get => Target.Name; set => Target.Name = value; } + public string Name { get => Target?.Name; } /// - public override ParameterLocation? In { get => Target.In; set => Target.In = value; } + public ParameterLocation? In { get => Target?.In; } /// - public override string Scheme { get => Target.Scheme; set => Target.Scheme = value; } + public string Scheme { get => Target?.Scheme; } /// - public override string BearerFormat { get => Target.BearerFormat; set => Target.BearerFormat = value; } + public string BearerFormat { get => Target?.BearerFormat; } /// - public override OpenApiOAuthFlows Flows { get => Target.Flows; set => Target.Flows = value; } + public OpenApiOAuthFlows Flows { get => Target?.Flows; } /// - public override Uri OpenIdConnectUrl { get => Target.OpenIdConnectUrl; set => Target.OpenIdConnectUrl = value; } + public Uri OpenIdConnectUrl { get => Target?.OpenIdConnectUrl; } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override SecuritySchemeType? Type { get => Target.Type; set => Target.Type = value; } - - /// - public override void SerializeAsV3(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } - } - - /// - public override void SerializeAsV31(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } - } + public SecuritySchemeType? Type { get => Target?.Type; } /// - public override void SerializeAsV2(IOpenApiWriter writer) + public override IOpenApiSecurityScheme CopyReferenceAsTargetElementWithOverrides(IOpenApiSecurityScheme source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); - } + return source is OpenApiSecurityScheme ? new OpenApiSecurityScheme(this) : source; } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiSecurityScheme CreateShallowCopy() { - Utils.CheckArgumentNull(writer);; - action(writer, Target); + return new OpenApiSecuritySchemeReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs index ae15b4085..6f218fc13 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs @@ -5,31 +5,23 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Models.References { /// /// Tag Object Reference /// - public class OpenApiTagReference : OpenApiTag, IOpenApiReferenceableWithTarget + public class OpenApiTagReference : BaseOpenApiReferenceHolder, IOpenApiTag { - internal OpenApiTag _target; - - /// - /// Reference. - /// - public OpenApiReference Reference { get; set; } - /// /// Resolved target of the reference. /// - public OpenApiTag Target + public override OpenApiTag Target { get { - _target ??= Reference.HostDocument?.Tags.FirstOrDefault(t => StringComparer.Ordinal.Equals(t.Name, Reference.Id)); - return _target; + return Reference.HostDocument?.Tags.FirstOrDefault(t => StringComparer.Ordinal.Equals(t.Name, Reference.Id)); } } @@ -38,85 +30,47 @@ public OpenApiTag Target /// /// The reference Id. /// The host OpenAPI document. - public OpenApiTagReference(string referenceId, OpenApiDocument hostDocument) + /// Optional: External resource in the reference. + /// It may be: + /// 1. a absolute/relative file path, for example: ../commons/pet.json + /// 2. a Url, for example: http://localhost/pet.json + /// + public OpenApiTagReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Tag, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - Reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Tag - }; } - /// - /// Copy Constructor + /// Copy constructor /// - /// The source to copy information from. - public OpenApiTagReference(OpenApiTagReference source):base() + /// The reference to copy + private OpenApiTagReference(OpenApiTagReference openApiTagReference):base(openApiTagReference) { - Reference = source?.Reference != null ? new(source.Reference) : null; - _target = source?._target; + } - private const string ReferenceErrorMessage = "Setting the value from the reference is not supported, use the target property instead."; /// - public override string Description { get => Target.Description; set => throw new InvalidOperationException(ReferenceErrorMessage); } + public string Description + { + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + } /// - public override OpenApiExternalDocs ExternalDocs { get => Target.ExternalDocs; set => throw new InvalidOperationException(ReferenceErrorMessage); } + public OpenApiExternalDocs ExternalDocs { get => Target?.ExternalDocs; } /// - public override IDictionary Extensions { get => Target.Extensions; set => throw new InvalidOperationException(ReferenceErrorMessage); } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override string Name { get => Target.Name; set => throw new InvalidOperationException(ReferenceErrorMessage); } - + public string Name { get => Target?.Name; } /// - public override void SerializeAsV3(IOpenApiWriter writer) + public override IOpenApiTag CopyReferenceAsTargetElementWithOverrides(IOpenApiTag source) { - if (!writer.GetSettings().ShouldInlineReference(Reference)) - { - Reference.SerializeAsV3(writer); - } - else - { - SerializeInternal(writer); - } - } - - /// - public override void SerializeAsV31(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(Reference)) - { - Reference.SerializeAsV31(writer); - } - else - { - SerializeInternal(writer); - } - } - - /// - public override void SerializeAsV2(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(Reference)) - { - Reference.SerializeAsV2(writer); - } - else - { - SerializeInternal(writer); - } + return source is OpenApiTag ? new OpenApiTag(this) : source; } /// - private void SerializeInternal(IOpenApiWriter writer) + public IOpenApiTag CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - writer.WriteValue(Name); + return new OpenApiTagReference(this); } } } diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 4aad45278..bac24a51d 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -60,11 +60,9 @@ public ReadResult Read(MemoryStream input, /// /// The JsonNode input. /// The Reader settings to be used during parsing. - /// The OpenAPI format. /// public ReadResult Read(JsonNode jsonNode, - OpenApiReaderSettings settings, - string format = null) + OpenApiReaderSettings settings) { if (jsonNode is null) throw new ArgumentNullException(nameof(jsonNode)); if (settings is null) throw new ArgumentNullException(nameof(settings)); diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 33bea8fb5..9424f053f 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -39,7 +39,11 @@ public static ReadResult Load(MemoryStream stream, string format = null, OpenApiReaderSettings settings = null) { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(stream); +#else if (stream is null) throw new ArgumentNullException(nameof(stream)); +#endif settings ??= new OpenApiReaderSettings(); // Get the format of the stream if not provided @@ -112,7 +116,11 @@ public static async Task LoadAsync(string url, OpenApiSpecVersion version, /// public static async Task LoadAsync(Stream input, string format = null, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(input); +#else if (input is null) throw new ArgumentNullException(nameof(input)); +#endif settings ??= new OpenApiReaderSettings(); Stream preparedStream; @@ -160,7 +168,11 @@ public static async Task LoadAsync(Stream input, CancellationToken token = default) where T : IOpenApiElement { Utils.CheckArgumentNull(openApiDocument); +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(input); +#else if (input is null) throw new ArgumentNullException(nameof(input)); +#endif if (input is MemoryStream memoryStream) { return Load(memoryStream, version, format, openApiDocument, out var _, settings); @@ -185,7 +197,11 @@ public static ReadResult Parse(string input, string format = null, OpenApiReaderSettings settings = null) { - if (input is null) throw new ArgumentNullException(nameof(input)); +#if NET6_0_OR_GREATER + ArgumentException.ThrowIfNullOrEmpty(input); +#else + if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input)); +#endif format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); @@ -212,7 +228,11 @@ public static T Parse(string input, string format = null, OpenApiReaderSettings settings = null) where T : IOpenApiElement { - if (input is null) throw new ArgumentNullException(nameof(input)); +#if NET6_0_OR_GREATER + ArgumentException.ThrowIfNullOrEmpty(input); +#else + if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input)); +#endif format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); @@ -278,11 +298,12 @@ private static ReadResult InternalLoad(MemoryStream input, string format, OpenAp var response = await _httpClient.GetAsync(url, token).ConfigureAwait(false); var mediaType = response.Content.Headers.ContentType.MediaType; var contentType = mediaType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0]; - format = contentType.Split('/').LastOrDefault(); + format = contentType.Split('/').Last().Split('+').Last().Split('-').Last(); + // for non-standard MIME types e.g. text/x-yaml used in older libs or apps #if NETSTANDARD2_0 stream = await response.Content.ReadAsStreamAsync(); #else - stream = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false);; + stream = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false); #endif return (stream, format); } @@ -321,8 +342,12 @@ private static string InspectInputFormat(string input) private static string InspectStreamFormat(Stream stream) { - if (stream == null) throw new ArgumentNullException(nameof(stream)); - +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(stream); +#else + if (stream is null) throw new ArgumentNullException(nameof(stream)); +#endif + long initialPosition = stream.Position; int firstByte = stream.ReadByte(); diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs index 92dd24138..16456c400 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs @@ -4,6 +4,7 @@ using System; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.ParseNodes { @@ -15,7 +16,7 @@ internal class AnyFieldMapParameter public AnyFieldMapParameter( Func propertyGetter, Action propertySetter, - Func SchemaGetter = null) + Func SchemaGetter = null) { this.PropertyGetter = propertyGetter; this.PropertySetter = propertySetter; @@ -35,6 +36,6 @@ public AnyFieldMapParameter( /// /// Function to get the schema to apply to the property. /// - public Func SchemaGetter { get; } + public Func SchemaGetter { get; } } } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs index 4d365125b..52397aed9 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.ParseNodes { @@ -17,7 +18,7 @@ public AnyMapFieldMapParameter( Func> propertyMapGetter, Func propertyGetter, Action propertySetter, - Func schemaGetter) + Func schemaGetter) { this.PropertyMapGetter = propertyMapGetter; this.PropertyGetter = propertyGetter; @@ -43,6 +44,6 @@ public AnyMapFieldMapParameter( /// /// Function to get the schema to apply to the property. /// - public Func SchemaGetter { get; } + public Func SchemaGetter { get; } } } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs index f39d9c345..b71593dca 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs @@ -120,11 +120,10 @@ public override string GetRaw() } public T GetReferencedObject(ReferenceType referenceType, string referenceId, string summary = null, string description = null) - where T : IOpenApiReferenceable, new() + where T : IOpenApiReferenceHolder, new() { return new() { - UnresolvedReference = true, Reference = Context.VersionService.ConvertToOpenApiReference(referenceId, referenceType, summary, description) }; } diff --git a/src/Microsoft.OpenApi/Reader/Services/OpenApiRemoteReferenceCollector.cs b/src/Microsoft.OpenApi/Reader/Services/OpenApiRemoteReferenceCollector.cs index bb66cf9b2..8690735b8 100644 --- a/src/Microsoft.OpenApi/Reader/Services/OpenApiRemoteReferenceCollector.cs +++ b/src/Microsoft.OpenApi/Reader/Services/OpenApiRemoteReferenceCollector.cs @@ -26,13 +26,10 @@ public IEnumerable References } } - /// - /// Collect reference for each reference - /// - /// - public override void Visit(IOpenApiReferenceable referenceable) + /// + public override void Visit(IOpenApiReferenceHolder referenceHolder) { - AddExternalReferences(referenceable.Reference); + AddExternalReferences(referenceHolder.Reference); } /// diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs index d225899cc..00bfc2d74 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs @@ -32,7 +32,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs index 37e146793..0aa2b8093 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs @@ -7,6 +7,8 @@ using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Services; @@ -109,7 +111,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _openApiPatternFields = new() { // We have no semantics to verify X- nodes, therefore treat them as just values. - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static void MakeServers(IList servers, ParsingContext context, RootNode rootNode) @@ -233,7 +235,7 @@ public static OpenApiDocument LoadOpenApi(RootNode rootNode) rootNode.GetMap(), openApiDoc.Paths.Values .SelectMany(path => path.Operations?.Values ?? Enumerable.Empty()) - .SelectMany(operation => operation.Responses?.Values ?? Enumerable.Empty()), + .SelectMany(operation => operation.Responses?.Values ?? Enumerable.Empty()), openApiNode.Context); } @@ -255,11 +257,11 @@ public static OpenApiDocument LoadOpenApi(RootNode rootNode) return openApiDoc; } - private static void ProcessResponsesMediaTypes(MapNode mapNode, IEnumerable responses, ParsingContext context) + private static void ProcessResponsesMediaTypes(MapNode mapNode, IEnumerable responses, ParsingContext context) { if (responses != null) { - foreach (var response in responses) + foreach (var response in responses.OfType()) { ProcessProduces(mapNode, response, context); @@ -302,30 +304,22 @@ private static bool IsHostValid(string host) internal class RequestBodyReferenceFixer : OpenApiVisitorBase { - private IDictionary _requestBodies; - public RequestBodyReferenceFixer(IDictionary requestBodies) + private readonly IDictionary _requestBodies; + public RequestBodyReferenceFixer(IDictionary requestBodies) { _requestBodies = requestBodies; } public override void Visit(OpenApiOperation operation) { - var body = operation.Parameters.FirstOrDefault( + var body = operation.Parameters.OfType().FirstOrDefault( p => p.UnresolvedReference && _requestBodies.ContainsKey(p.Reference.Id)); if (body != null) { operation.Parameters.Remove(body); - operation.RequestBody = new() - { - UnresolvedReference = true, - Reference = new() - { - Id = body.Reference.Id, - Type = ReferenceType.RequestBody - } - }; + operation.RequestBody = new OpenApiRequestBodyReference(body.Reference.Id, body.Reference.HostDocument); } } } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs index 6fc438542..312313585 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs @@ -30,7 +30,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _externalDocsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs index 4a994bdc5..9c712b0a3 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Reader.ParseNodes; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.V2 { @@ -94,15 +95,18 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static OpenApiSchema GetOrCreateSchema(OpenApiHeader p) { - return p.Schema ??= new(); + return p.Schema switch { + OpenApiSchema schema => schema, + _ => (OpenApiSchema)(p.Schema = new OpenApiSchema()), + }; } - public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("header"); var header = new OpenApiHeader(); @@ -112,7 +116,7 @@ public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocum property.ParseField(header, _headerFixedFields, _headerPatternFields, hostDocument); } - var schema = node.Context.GetFromTempStorage("schema"); + var schema = node.Context.GetFromTempStorage("schema"); if (schema != null) { header.Schema = schema; diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs index 74c3ac917..0d33e896c 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs @@ -44,7 +44,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _infoPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs index 8eae690ed..d4a95de89 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs @@ -28,7 +28,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs index 35d20ca4a..37c95c9b2 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs @@ -8,6 +8,8 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Models.References; +using Microsoft.OpenApi.Models.Interfaces; +using System; namespace Microsoft.OpenApi.Reader.V2 { @@ -79,7 +81,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static readonly FixedFieldMap _responsesFixedFields = new(); @@ -87,8 +89,8 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _responsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument) @@ -120,7 +122,7 @@ internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument h } } - foreach (var response in operation.Responses.Values) + foreach (var response in operation.Responses.Values.OfType()) { ProcessProduces(node.CheckMapNode("responses"), response, node.Context); } @@ -146,18 +148,21 @@ private static OpenApiRequestBody CreateFormBody(ParsingContext context, List k.Name, - v => + v => { - var schema = v.Schema; + var schema = v.Schema.CreateShallowCopy(); schema.Description = v.Description; - schema.Extensions = v.Extensions; + if (schema is OpenApiSchema openApiSchema) + { + openApiSchema.Extensions = v.Extensions; + } return schema; }), - Required = new HashSet(formParameters.Where(p => p.Required).Select(p => p.Name)) + Required = new HashSet(formParameters.Where(static p => p.Required).Select(static p => p.Name), StringComparer.Ordinal) } }; @@ -172,15 +177,15 @@ private static OpenApiRequestBody CreateFormBody(ParsingContext context, List mediaType) }; - foreach (var value in formBody.Content.Values.Where(static x => x.Schema is not null && x.Schema.Properties.Any() && x.Schema.Type == null)) - value.Schema.Type = JsonSchemaType.Object; + foreach (var value in formBody.Content.Values.Where(static x => x.Schema is not null && x.Schema.Properties.Any() && x.Schema.Type == null).Select(static x => x.Schema).OfType()) + value.Type = JsonSchemaType.Object; return formBody; } - internal static OpenApiRequestBody CreateRequestBody( + internal static IOpenApiRequestBody CreateRequestBody( ParsingContext context, - OpenApiParameter bodyParameter) + IOpenApiParameter bodyParameter) { var consumes = context.GetFromTempStorage>(TempStorageKeys.OperationConsumes) ?? context.GetFromTempStorage>(TempStorageKeys.GlobalConsumes) ?? diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs index 6a5411070..267ba24d7 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs @@ -6,6 +6,7 @@ using System.Globalization; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -105,7 +106,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _parameterPatternFields = new() { - {s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase) && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; @@ -146,7 +147,10 @@ private static void LoadParameterExamplesExtension(OpenApiParameter parameter, P private static OpenApiSchema GetOrCreateSchema(OpenApiParameter p) { - return p.Schema ??= new(); + return p.Schema switch { + OpenApiSchema schema => schema, + _ => (OpenApiSchema)(p.Schema = new OpenApiSchema()), + }; } private static void ProcessIn(OpenApiParameter o, ParseNode n, OpenApiDocument hostDocument) @@ -183,12 +187,12 @@ private static void ProcessIn(OpenApiParameter o, ParseNode n, OpenApiDocument h } } - public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) { return LoadParameter(node, false, hostDocument); } - public static OpenApiParameter LoadParameter(ParseNode node, bool loadRequestBody, OpenApiDocument hostDocument) + public static IOpenApiParameter LoadParameter(ParseNode node, bool loadRequestBody, OpenApiDocument hostDocument) { // Reset the local variables every time this method is called. node.Context.SetTempStorage(TempStorageKeys.ParameterIsBodyOrFormData, false); @@ -207,7 +211,7 @@ public static OpenApiParameter LoadParameter(ParseNode node, bool loadRequestBod ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields, doc: hostDocument); - var schema = node.Context.GetFromTempStorage("schema"); + var schema = node.Context.GetFromTempStorage("schema"); if (schema != null) { parameter.Schema = schema; @@ -215,7 +219,7 @@ public static OpenApiParameter LoadParameter(ParseNode node, bool loadRequestBod } // load examples from storage and add them to the parameter - var examples = node.Context.GetFromTempStorage>(TempStorageKeys.Examples, parameter); + var examples = node.Context.GetFromTempStorage>(TempStorageKeys.Examples, parameter); if (examples != null) { parameter.Examples = examples; diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs index bc1eb8da6..b1e0da7a8 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Extensions; @@ -17,13 +18,6 @@ internal static partial class OpenApiV2Deserializer { private static readonly FixedFieldMap _pathItemFixedFields = new() { - { - "$ref", (o, n, t) => - { - o.Reference = new() { ExternalResource = n.GetScalarValue() }; - o.UnresolvedReference =true; - } - }, {"get", (o, n, t) => o.AddOperation(OperationType.Get, LoadOperation(n, t))}, {"put", (o, n, t) => o.AddOperation(OperationType.Put, LoadOperation(n, t))}, {"post", (o, n, t) => o.AddOperation(OperationType.Post, LoadOperation(n, t))}, @@ -40,7 +34,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))}, }; public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs index a048316d5..30d1df8a9 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -17,8 +18,8 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("/", StringComparison.OrdinalIgnoreCase), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs index 11b12e8f8..514ed0b44 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -41,7 +42,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _responsePatternFields = new() { - {s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase) && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; @@ -73,9 +74,9 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P ?? context.GetFromTempStorage>(TempStorageKeys.GlobalProduces) ?? context.DefaultContentType ?? new List { "application/octet-stream" }; - var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response); - var examples = context.GetFromTempStorage>(TempStorageKeys.Examples, response) - ?? new Dictionary(); + var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response); + var examples = context.GetFromTempStorage>(TempStorageKeys.Examples, response) + ?? new Dictionary(); foreach (var produce in produces) { @@ -110,10 +111,10 @@ private static void LoadResponseExamplesExtension(OpenApiResponse response, Pars node.Context.SetTempStorage(TempStorageKeys.Examples, examples, response); } - private static Dictionary LoadExamplesExtension(ParseNode node) + private static Dictionary LoadExamplesExtension(ParseNode node) { var mapNode = node.CheckMapNode(OpenApiConstants.ExamplesExtension); - var examples = new Dictionary(); + var examples = new Dictionary(); foreach (var examplesNode in mapNode) { @@ -170,7 +171,7 @@ private static void LoadExample(OpenApiResponse response, string mediaType, Pars { mediaTypeObject = new() { - Schema = node.Context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response) + Schema = node.Context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response) }; response.Content.Add(mediaType, mediaTypeObject); } @@ -178,7 +179,7 @@ private static void LoadExample(OpenApiResponse response, string mediaType, Pars mediaTypeObject.Example = exampleNode; } - public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("response"); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs index 78453f9d2..42575e394 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System.Collections.Generic; @@ -7,6 +7,8 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Models.References; +using Microsoft.OpenApi.Models.Interfaces; +using System; namespace Microsoft.OpenApi.Reader.V2 { @@ -153,10 +155,10 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new PatternFieldMap { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("schema"); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs index 4dfdbba16..7b47ff6c5 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; namespace Microsoft.OpenApi.Reader.V2 @@ -21,7 +23,7 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, foreach (var property in mapNode) { var scheme = LoadSecuritySchemeByReference( - mapNode.Context, + hostDocument, property.Name); var scopes = property.Value.CreateSimpleList((n2, p) => n2.GetScalarValue(), hostDocument); @@ -41,21 +43,11 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, return securityRequirement; } - private static OpenApiSecurityScheme LoadSecuritySchemeByReference( - ParsingContext context, + private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference( + OpenApiDocument openApiDocument, string schemeName) { - var securitySchemeObject = new OpenApiSecurityScheme - { - UnresolvedReference = true, - Reference = new() - { - Id = schemeName, - Type = ReferenceType.SecurityScheme - } - }; - - return securitySchemeObject; + return new OpenApiSecuritySchemeReference(schemeName, openApiDocument); } } } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs index 43151c15a..0dc329f43 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs @@ -1,9 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader.ParseNodes; namespace Microsoft.OpenApi.Reader.V2 @@ -77,10 +78,10 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; - public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) { // Reset the local variables every time this method is called. // TODO: Change _flow to a tempStorage variable to make the deserializer thread-safe. diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs index 23614029a..809dccacd 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -31,7 +32,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs index 0e90a4633..83505670d 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; @@ -98,7 +99,7 @@ private static (string, string) GetReferenceIdAndExternalResource(string pointer { var refSegments = pointer.Split('/'); var refId = refSegments.Last(); - var isExternalResource = !refSegments.First().StartsWith("#"); + var isExternalResource = !refSegments.First().StartsWith("#", StringComparison.OrdinalIgnoreCase); string externalResource = isExternalResource ? $"{refSegments.First()}/{refSegments[1].TrimEnd('#')}" : null; diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2VersionService.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2VersionService.cs index c9e58b519..c4186bb25 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2VersionService.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2VersionService.cs @@ -161,7 +161,7 @@ public OpenApiReference ConvertToOpenApiReference(string reference, ReferenceTyp } else if (segments.Length == 2) { - if (reference.StartsWith("#")) + if (reference.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // "$ref": "#/definitions/Pet" try @@ -178,7 +178,7 @@ public OpenApiReference ConvertToOpenApiReference(string reference, ReferenceTyp // Where fragments point into a non-OpenAPI document, the id will be the complete fragment identifier var id = segments[1]; // $ref: externalSource.yaml#/Pet - if (id.StartsWith("/definitions/")) + if (id.StartsWith("/definitions/", StringComparison.Ordinal)) { var localSegments = id.Split('/'); var referencedType = GetReferenceTypeV2FromName(localSegments[1]); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs index 21c9be0fe..38acf840d 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs @@ -51,7 +51,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _xmlPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs index bdf4a8716..4ec9bfa3a 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Expressions; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -20,11 +22,11 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _callbackPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; - public static OpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("callback"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs index a5e3d082b..76cfc96d7 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -29,7 +30,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _componentsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiComponents LoadComponents(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs index cc5058b52..7eab275c8 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs @@ -32,7 +32,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs index 842b75bf0..c07d28d46 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -33,7 +34,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _openApiPatternFields = new PatternFieldMap { // We have no semantics to verify X- nodes, therefore treat them as just values. - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiDocument LoadOpenApi(RootNode rootNode) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs index 2345436dd..2d324745d 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -47,7 +48,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _encodingPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiEncoding LoadEncoding(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs index 06d1d284a..5ec2665a0 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -37,10 +39,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _examplePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiExample LoadExample(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiExample LoadExample(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("example"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs index a3f20bad0..0d8c25b05 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs @@ -31,7 +31,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _externalDocsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs index 7830c394e..94350d429 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -67,10 +69,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("header"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs index dbe3a554c..48979439d 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs @@ -44,7 +44,7 @@ internal static partial class OpenApiV3Deserializer public static readonly PatternFieldMap InfoPatternFields = new() { - {s => s.StartsWith("x-"), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs index d836c6e0f..4ecdce151 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs @@ -28,7 +28,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; internal static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs index 049ecc8cc..f85fb0328 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -41,10 +43,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _linkPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; - public static OpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("link"); var link = new OpenApiLink(); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs index 69fc53179..6fd96b38d 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader.ParseNodes; namespace Microsoft.OpenApi.Reader.V3 @@ -37,7 +39,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _mediaTypePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _mediaTypeAnyFields = new() @@ -51,7 +53,7 @@ internal static partial class OpenApiV3Deserializer } }; - private static readonly AnyMapFieldMap _mediaTypeAnyMapOpenApiExampleFields = + private static readonly AnyMapFieldMap _mediaTypeAnyMapOpenApiExampleFields = new() { { @@ -59,7 +61,7 @@ internal static partial class OpenApiV3Deserializer new( m => m.Examples, e => e.Value, - (e, v) => e.Value = v, + (e, v) => {if (e is OpenApiExample ex) {ex.Value = v;}}, m => m.Schema) } }; diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs index 1a7f40c15..d60cf0aa5 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs @@ -35,7 +35,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _oAuthFlowPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlow LoadOAuthFlow(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs index e4e003f9c..892ec4701 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -25,7 +26,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _oAuthFlowsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlows LoadOAuthFlows(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs index 1ebb57880..e9712da98 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -72,7 +73,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs index a71f633e5..7d2c5074b 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -87,7 +89,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _parameterPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _parameterAnyFields = new() @@ -101,7 +103,7 @@ internal static partial class OpenApiV3Deserializer } }; - private static readonly AnyMapFieldMap _parameterAnyMapOpenApiExampleFields = + private static readonly AnyMapFieldMap _parameterAnyMapOpenApiExampleFields = new() { { @@ -109,12 +111,12 @@ internal static partial class OpenApiV3Deserializer new( m => m.Examples, e => e.Value, - (e, v) => e.Value = v, + (e, v) => {if (e is OpenApiExample ex) {ex.Value = v;}}, m => m.Schema) } }; - public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("parameter"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs index 9673c5f87..baaf5babc 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -16,12 +18,6 @@ internal static partial class OpenApiV3Deserializer { private static readonly FixedFieldMap _pathItemFixedFields = new() { - { - "$ref", (o, n, _) => { - o.Reference = new() { ExternalResource = n.GetScalarValue() }; - o.UnresolvedReference =true; - } - }, { "summary", (o, n, _) => o.Summary = n.GetScalarValue() @@ -45,10 +41,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("PathItem"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs index e28a9d569..ef27f5d94 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -17,8 +18,8 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("/", StringComparison.OrdinalIgnoreCase), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs index 79bb16638..ac007d813 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -34,10 +36,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _requestBodyPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiRequestBody LoadRequestBody(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiRequestBody LoadRequestBody(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("requestBody"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs index c159443ad..8e10c2e79 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -37,10 +39,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _responsePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("response"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs index 7288c04b1..379811dda 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -17,8 +18,8 @@ internal static partial class OpenApiV3Deserializer public static readonly PatternFieldMap ResponsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs index bad6d04b8..25d68b477 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs @@ -1,10 +1,12 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; +using System; using System.Collections.Generic; using System.Globalization; @@ -84,7 +86,14 @@ internal static partial class OpenApiV3Deserializer }, { "type", - (o, n, _) => o.Type = n.GetScalarValue().ToJsonSchemaType() + (o, n, _) => { + var type = n.GetScalarValue().ToJsonSchemaType(); + // so we don't loose the value from nullable + if (o.Type.HasValue) + o.Type |= type; + else + o.Type = type; + } }, { "allOf", @@ -137,7 +146,16 @@ internal static partial class OpenApiV3Deserializer }, { "nullable", - (o, n, _) => o.Nullable = bool.Parse(n.GetScalarValue()) + (o, n, _) => + { + if (bool.TryParse(n.GetScalarValue(), out var parsed) && parsed) + { + if (o.Type.HasValue) + o.Type |= JsonSchemaType.Null; + else + o.Type = JsonSchemaType.Null; + } + } }, { "discriminator", @@ -171,10 +189,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode(OpenApiConstants.Schema); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs index 73610713c..030f2ef34 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -21,7 +22,7 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, foreach (var property in mapNode) { - var scheme = LoadSecuritySchemeByReference(mapNode.Context, property.Name); + var scheme = LoadSecuritySchemeByReference(hostDocument, property.Name); var scopes = property.Value.CreateSimpleList((value, p) => value.GetScalarValue(), hostDocument); @@ -39,12 +40,11 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, return securityRequirement; } - private static OpenApiSecurityScheme LoadSecuritySchemeByReference( - ParsingContext context, + private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference( + OpenApiDocument openApiDocument, string schemeName) { - var securitySchemeObject = new OpenApiSecuritySchemeReference(schemeName, hostDocument: null); - return securitySchemeObject; + return new OpenApiSecuritySchemeReference(schemeName, openApiDocument); } } } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs index 18c4eae28..993279f1e 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs @@ -1,9 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -69,10 +70,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("securityScheme"); var pointer = mapNode.GetReferencePointer(); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs index 52ee335c0..4e4411625 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -31,7 +32,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _serverPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServer LoadServer(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs index 9436e62fe..3579a40b7 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -33,7 +34,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _serverVariablePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServerVariable LoadServerVariable(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs index e6efafae7..d67d54d7c 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -31,7 +32,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs index cad424c50..67a9b0495 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; @@ -148,7 +149,7 @@ private static RuntimeExpressionAnyWrapper LoadRuntimeExpressionAnyWrapper(Parse { var value = node.GetScalarValue(); - if (value != null && value.StartsWith("$")) + if (value != null && value.StartsWith("$", StringComparison.OrdinalIgnoreCase)) { return new() { @@ -190,7 +191,7 @@ private static (string, string) GetReferenceIdAndExternalResource(string pointer { var refSegments = pointer.Split('/'); var refId = refSegments.Last(); - var isExternalResource = !refSegments.First().StartsWith("#"); + var isExternalResource = !refSegments.First().StartsWith("#", StringComparison.OrdinalIgnoreCase); string externalResource = isExternalResource ? $"{refSegments.First()}/{refSegments[1].TrimEnd('#')}" : null; diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs index 372a8b26f..612c59dfb 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs @@ -102,7 +102,7 @@ public OpenApiReference ConvertToOpenApiReference( } else if (segments.Length == 2) { - if (reference.StartsWith("#")) + if (reference.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // "$ref": "#/components/schemas/Pet" try @@ -116,10 +116,10 @@ public OpenApiReference ConvertToOpenApiReference( } // Where fragments point into a non-OpenAPI document, the id will be the complete fragment identifier var id = segments[1]; - var openApiReference = new OpenApiReference(); + var isFragment = false; // $ref: externalSource.yaml#/Pet - if (id.StartsWith("/components/")) + if (id.StartsWith("/components/", StringComparison.Ordinal)) { var localSegments = segments[1].Split('/'); localSegments[2].TryGetEnumFromDisplayName(out var referencedType); @@ -136,7 +136,7 @@ public OpenApiReference ConvertToOpenApiReference( } id = localSegments[3]; } - else if (id.StartsWith("/paths/")) + else if (id.StartsWith("/paths/", StringComparison.Ordinal)) { var localSegments = segments[1].Split(_pathSeparator, StringSplitOptions.RemoveEmptyEntries); if (localSegments.Length == 2) @@ -152,12 +152,16 @@ public OpenApiReference ConvertToOpenApiReference( } else { - openApiReference.IsFragment = true; + isFragment = true; } - openApiReference.ExternalResource = segments[0]; - openApiReference.Type = type; - openApiReference.Id = id; + var openApiReference = new OpenApiReference + { + ExternalResource = segments[0], + Type = type, + Id = id, + IsFragment = isFragment, + }; return openApiReference; } @@ -179,11 +183,12 @@ public T LoadElement(ParseNode node, OpenApiDocument doc) where T : IOpenApiE /// public string GetReferenceScalarValues(MapNode mapNode, string scalarValue) { - if (mapNode.Any(static x => !"$ref".Equals(x.Name, StringComparison.OrdinalIgnoreCase))) + if (mapNode.Any(static x => !"$ref".Equals(x.Name, StringComparison.OrdinalIgnoreCase)) && + mapNode + .Where(x => x.Name.Equals(scalarValue)) + .Select(static x => x.Value) + .OfType().FirstOrDefault() is {} valueNode) { - var valueNode = mapNode.Where(x => x.Name.Equals(scalarValue)) - .Select(static x => x.Value).OfType().FirstOrDefault(); - return valueNode.GetScalarValue(); } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs index 51b66d348..43245338d 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs @@ -41,7 +41,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _xmlPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs index c0d4c5951..ac1a43998 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs @@ -4,6 +4,7 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Models.References; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.V31 { @@ -19,11 +20,11 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _callbackPatternFields = new() { - {s => !s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, - {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; - public static OpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("callback"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs index c9dccde5d..2520692cd 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs @@ -31,7 +31,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _componentsPatternFields = new() { - {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiComponents LoadComponents(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs index 801eb2de9..be487e434 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs @@ -35,7 +35,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs index 90e904f60..0302149f6 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -30,7 +31,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _discriminatorPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiDiscriminator LoadDiscriminator(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs index 0d1e08479..4f3a05fcc 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -31,7 +32,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _openApiPatternFields = new() { // We have no semantics to verify X- nodes, therefore treat them as just values. - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiDocument LoadOpenApi(RootNode rootNode) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs index 51a5b4ef6..d571a42d0 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -51,7 +52,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _encodingPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiEncoding LoadEncoding(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs index 820c58985..49f7c3fd0 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -43,10 +45,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _examplePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiExample LoadExample(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiExample LoadExample(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("example"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs index 56dd2bc77..a5b06efff 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs @@ -33,7 +33,7 @@ internal static partial class OpenApiV31Deserializer new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs index 32c2b73fc..2c23c70a4 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -81,10 +83,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("header"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs index d3aed5511..86597b421 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs @@ -59,7 +59,7 @@ internal static partial class OpenApiV31Deserializer public static readonly PatternFieldMap InfoPatternFields = new() { - {s => s.StartsWith("x-"), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs index 303f2f65a..7ef705095 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs @@ -35,7 +35,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; internal static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs index a849985fb..9fdea6e29 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -48,10 +50,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _linkPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; - public static OpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("link"); var link = new OpenApiLink(); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs index 36f90383c..2a46b4412 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader.ParseNodes; namespace Microsoft.OpenApi.Reader.V31 @@ -42,7 +44,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _mediaTypePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _mediaTypeAnyFields = new AnyFieldMap @@ -57,15 +59,15 @@ internal static partial class OpenApiV31Deserializer }; - private static readonly AnyMapFieldMap _mediaTypeAnyMapOpenApiExampleFields = - new AnyMapFieldMap + private static readonly AnyMapFieldMap _mediaTypeAnyMapOpenApiExampleFields = + new AnyMapFieldMap { { OpenApiConstants.Examples, - new AnyMapFieldMapParameter( + new AnyMapFieldMapParameter( m => m.Examples, e => e.Value, - (e, v) => e.Value = v, + (e, v) => {if (e is OpenApiExample ex) {ex.Value = v;}}, m => m.Schema) } }; diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs index 5b18caecf..3efc3ef5a 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs @@ -38,7 +38,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _oAuthFlowPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlow LoadOAuthFlow(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs index b20b96775..d472748f8 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -22,7 +23,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _oAuthFlowsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlows LoadOAuthFlows(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs index 2d6c831e3..cb44bb438 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -90,7 +91,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs index 7a2c3d90e..35e1308cb 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -105,7 +107,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _parameterPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _parameterAnyFields = new AnyFieldMap @@ -119,20 +121,20 @@ internal static partial class OpenApiV31Deserializer } }; - private static readonly AnyMapFieldMap _parameterAnyMapOpenApiExampleFields = - new AnyMapFieldMap + private static readonly AnyMapFieldMap _parameterAnyMapOpenApiExampleFields = + new AnyMapFieldMap { { OpenApiConstants.Examples, - new AnyMapFieldMapParameter( + new AnyMapFieldMapParameter( m => m.Examples, e => e.Value, - (e, v) => e.Value = v, + (e, v) => {if (e is OpenApiExample ex) {ex.Value = v;}}, m => m.Schema) } }; - public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("parameter"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs index 7c5fb189e..391a34bf6 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -14,12 +16,6 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _pathItemFixedFields = new() { - { - "$ref", (o,n, _) => { - o.Reference = new OpenApiReference() { ExternalResource = n.GetScalarValue() }; - o.UnresolvedReference =true; - } - }, { "summary", (o, n, _) => { @@ -47,10 +43,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("PathItem"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs index c72394bf2..6e97b41ac 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -14,8 +15,8 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("/", StringComparison.OrdinalIgnoreCase), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs index e26ec20f9..fe786aa44 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -37,10 +39,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _requestBodyPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiRequestBody LoadRequestBody(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiRequestBody LoadRequestBody(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("requestBody"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs index 8e4057a91..6d910761c 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -42,10 +44,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _responsePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("response"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs index 228a0045e..50aad0d9a 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -17,8 +18,8 @@ internal static partial class OpenApiV31Deserializer public static readonly PatternFieldMap ResponsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs index 87ecc8f00..fcd97fca2 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs @@ -1,10 +1,12 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -236,10 +238,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode(OpenApiConstants.Schema); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs index b204c83d4..cddb97699 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -39,10 +40,9 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, return securityRequirement; } - private static OpenApiSecurityScheme LoadSecuritySchemeByReference(string schemeName, OpenApiDocument hostDocument) + private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference(string schemeName, OpenApiDocument hostDocument) { - var securitySchemeObject = new OpenApiSecuritySchemeReference(schemeName, hostDocument); - return securitySchemeObject; + return new OpenApiSecuritySchemeReference(schemeName, hostDocument); } } } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs index b56352c22..2189f1179 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs @@ -1,9 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -79,10 +80,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("securityScheme"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs index 2ae8ac340..b51a16f5d 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -37,7 +38,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _serverPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServer LoadServer(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs index 0c6e8b756..a3aaa141a 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -39,7 +40,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _serverVariablePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServerVariable LoadServerVariable(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs index f1b0065cc..aea4c9c43 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -37,7 +38,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs index 7c3441eed..92e7770df 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Linq; using System.Text.Json.Nodes; using Microsoft.OpenApi.Any; @@ -113,7 +114,7 @@ private static RuntimeExpressionAnyWrapper LoadRuntimeExpressionAnyWrapper(Parse { var value = node.GetScalarValue(); - if (value != null && value.StartsWith("$")) + if (value != null && value.StartsWith("$", StringComparison.OrdinalIgnoreCase)) { return new RuntimeExpressionAnyWrapper { @@ -160,7 +161,7 @@ private static (string, string) GetReferenceIdAndExternalResource(string pointer var refSegments = pointer.Split('/'); string refId = !pointer.Contains('#') ? pointer : refSegments.Last(); - var isExternalResource = !refSegments.First().StartsWith("#"); + var isExternalResource = !refSegments.First().StartsWith("#", StringComparison.OrdinalIgnoreCase); string externalResource = null; if (isExternalResource && pointer.Contains('#')) { diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs index f564c37ab..bfaa82051 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs @@ -105,7 +105,7 @@ public OpenApiReference ConvertToOpenApiReference( } else if (segments.Length == 2) { - if (reference.StartsWith("#")) + if (reference.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // "$ref": "#/components/schemas/Pet" try @@ -121,7 +121,7 @@ public OpenApiReference ConvertToOpenApiReference( // Where fragments point into a non-OpenAPI document, the id will be the complete fragment identifier string id = segments[1]; // $ref: externalSource.yaml#/Pet - if (id.StartsWith("/components/")) + if (id.StartsWith("/components/", StringComparison.Ordinal)) { var localSegments = segments[1].Split('/'); localSegments[2].TryGetEnumFromDisplayName(out var referencedType); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs index 13870f341..0f821e9d2 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs @@ -51,7 +51,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _xmlPatternFields = new PatternFieldMap { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs index 22f1c5ad3..980aafb56 100644 --- a/src/Microsoft.OpenApi/Services/CopyReferences.cs +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; namespace Microsoft.OpenApi.Services; @@ -12,13 +13,10 @@ internal class CopyReferences(OpenApiDocument target) : OpenApiVisitorBase private readonly OpenApiDocument _target = target; public OpenApiComponents Components = new(); - /// - /// Visits IOpenApiReferenceable instances that are references and not in components. - /// - /// An IOpenApiReferenceable object. - public override void Visit(IOpenApiReferenceable referenceable) + /// + public override void Visit(IOpenApiReferenceHolder referenceHolder) { - switch (referenceable) + switch (referenceHolder) { case OpenApiSchemaReference openApiSchemaReference: AddSchemaToComponents(openApiSchemaReference.Target, openApiSchemaReference.Reference.Id); @@ -84,16 +82,16 @@ public override void Visit(IOpenApiReferenceable referenceable) break; } - base.Visit(referenceable); + base.Visit(referenceHolder); } private void AddSchemaToComponents(OpenApiSchema schema, string referenceId = null) { EnsureComponentsExist(); EnsureSchemasExist(); - if (!Components.Schemas.ContainsKey(referenceId ?? schema.Reference.Id)) + if (!Components.Schemas.ContainsKey(referenceId)) { - Components.Schemas.Add(referenceId ?? schema.Reference.Id, schema); + Components.Schemas.Add(referenceId, schema); } } @@ -101,9 +99,9 @@ private void AddParameterToComponents(OpenApiParameter parameter, string referen { EnsureComponentsExist(); EnsureParametersExist(); - if (!Components.Parameters.ContainsKey(referenceId ?? parameter.Reference.Id)) + if (!Components.Parameters.ContainsKey(referenceId)) { - Components.Parameters.Add(referenceId ?? parameter.Reference.Id, parameter); + Components.Parameters.Add(referenceId, parameter); } } @@ -111,87 +109,83 @@ private void AddResponseToComponents(OpenApiResponse response, string referenceI { EnsureComponentsExist(); EnsureResponsesExist(); - if (!Components.Responses.ContainsKey(referenceId ?? response.Reference.Id)) + if (!Components.Responses.ContainsKey(referenceId)) { - Components.Responses.Add(referenceId ?? response.Reference.Id, response); + Components.Responses.Add(referenceId, response); } } private void AddRequestBodyToComponents(OpenApiRequestBody requestBody, string referenceId = null) { EnsureComponentsExist(); EnsureRequestBodiesExist(); - if (!Components.RequestBodies.ContainsKey(referenceId ?? requestBody.Reference.Id)) + if (!Components.RequestBodies.ContainsKey(referenceId)) { - Components.RequestBodies.Add(referenceId ?? requestBody.Reference.Id, requestBody); + Components.RequestBodies.Add(referenceId, requestBody); } } private void AddLinkToComponents(OpenApiLink link, string referenceId = null) { EnsureComponentsExist(); EnsureLinksExist(); - if (!Components.Links.ContainsKey(referenceId ?? link.Reference.Id)) + if (!Components.Links.ContainsKey(referenceId)) { - Components.Links.Add(referenceId ?? link.Reference.Id, link); + Components.Links.Add(referenceId, link); } } private void AddCallbackToComponents(OpenApiCallback callback, string referenceId = null) { EnsureComponentsExist(); EnsureCallbacksExist(); - if (!Components.Callbacks.ContainsKey(referenceId ?? callback.Reference.Id)) + if (!Components.Callbacks.ContainsKey(referenceId)) { - Components.Callbacks.Add(referenceId ?? callback.Reference.Id, callback); + Components.Callbacks.Add(referenceId, callback); } } private void AddHeaderToComponents(OpenApiHeader header, string referenceId = null) { EnsureComponentsExist(); EnsureHeadersExist(); - if (!Components.Headers.ContainsKey(referenceId ?? header.Reference.Id)) + if (!Components.Headers.ContainsKey(referenceId)) { - Components.Headers.Add(referenceId ?? header.Reference.Id, header); + Components.Headers.Add(referenceId, header); } } private void AddExampleToComponents(OpenApiExample example, string referenceId = null) { EnsureComponentsExist(); EnsureExamplesExist(); - if (!Components.Examples.ContainsKey(referenceId ?? example.Reference.Id)) + if (!Components.Examples.ContainsKey(referenceId)) { - Components.Examples.Add(referenceId ?? example.Reference.Id, example); + Components.Examples.Add(referenceId, example); } } private void AddPathItemToComponents(OpenApiPathItem pathItem, string referenceId = null) { EnsureComponentsExist(); EnsurePathItemsExist(); - if (!Components.PathItems.ContainsKey(referenceId ?? pathItem.Reference.Id)) + if (!Components.PathItems.ContainsKey(referenceId)) { - Components.PathItems.Add(referenceId ?? pathItem.Reference.Id, pathItem); + Components.PathItems.Add(referenceId, pathItem); } } private void AddSecuritySchemeToComponents(OpenApiSecurityScheme securityScheme, string referenceId = null) { EnsureComponentsExist(); EnsureSecuritySchemesExist(); - if (!Components.SecuritySchemes.ContainsKey(referenceId ?? securityScheme.Reference.Id)) + if (!Components.SecuritySchemes.ContainsKey(referenceId)) { - Components.SecuritySchemes.Add(referenceId ?? securityScheme.Reference.Id, securityScheme); + Components.SecuritySchemes.Add(referenceId, securityScheme); } } /// - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { // This is needed to handle schemas used in Responses in components if (schema is OpenApiSchemaReference openApiSchemaReference) { AddSchemaToComponents(openApiSchemaReference.Target, openApiSchemaReference.Reference.Id); } - else if (schema.Reference != null) - { - AddSchemaToComponents(schema); - } base.Visit(schema); } @@ -202,50 +196,50 @@ private void EnsureComponentsExist() private void EnsureSchemasExist() { - _target.Components.Schemas ??= new Dictionary(); + _target.Components.Schemas ??= new Dictionary(); } private void EnsureParametersExist() { - _target.Components.Parameters ??= new Dictionary(); + _target.Components.Parameters ??= new Dictionary(); } private void EnsureResponsesExist() { - _target.Components.Responses ??= new Dictionary(); + _target.Components.Responses ??= new Dictionary(); } private void EnsureRequestBodiesExist() { - _target.Components.RequestBodies ??= new Dictionary(); + _target.Components.RequestBodies ??= new Dictionary(); } private void EnsureExamplesExist() { - _target.Components.Examples ??= new Dictionary(); + _target.Components.Examples ??= new Dictionary(); } private void EnsureHeadersExist() { - _target.Components.Headers ??= new Dictionary(); + _target.Components.Headers ??= new Dictionary(); } private void EnsureCallbacksExist() { - _target.Components.Callbacks ??= new Dictionary(); + _target.Components.Callbacks ??= new Dictionary(); } private void EnsureLinksExist() { - _target.Components.Links ??= new Dictionary(); + _target.Components.Links ??= new Dictionary(); } private void EnsureSecuritySchemesExist() { - _target.Components.SecuritySchemes ??= new Dictionary(); + _target.Components.SecuritySchemes ??= new Dictionary(); } private void EnsurePathItemsExist() { - _target.Components.PathItems ??= new Dictionary(); + _target.Components.PathItems ??= new Dictionary(); } } diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index 22916fd7c..20fa54839 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text.RegularExpressions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Services @@ -86,20 +87,20 @@ public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, Fun var results = FindOperations(source, predicate); foreach (var result in results) { - OpenApiPathItem pathItem; + IOpenApiPathItem pathItem; var pathKey = result.CurrentKeys.Path; if (subset.Paths == null) { subset.Paths = new(); - pathItem = new(); + pathItem = new OpenApiPathItem(); subset.Paths.Add(pathKey, pathItem); } else { if (!subset.Paths.TryGetValue(pathKey, out pathItem)) { - pathItem = new(); + pathItem = new OpenApiPathItem(); subset.Paths.Add(pathKey, pathItem); } } diff --git a/src/Microsoft.OpenApi/Services/OpenApiUrlTreeNode.cs b/src/Microsoft.OpenApi/Services/OpenApiUrlTreeNode.cs index ba5d4349d..8a61772dd 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiUrlTreeNode.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiUrlTreeNode.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Services { @@ -30,7 +31,7 @@ public class OpenApiUrlTreeNode /// /// Dictionary of labels and Path Item objects that describe the operations available on a node. /// - public IDictionary PathItems { get; } = new Dictionary(); + public IDictionary PathItems { get; } = new Dictionary(); /// /// A dictionary of key value pairs that contain information about a node. @@ -40,7 +41,7 @@ public class OpenApiUrlTreeNode /// /// Flag indicating whether a node segment is a path parameter. /// - public bool IsParameter => Segment.StartsWith("{"); + public bool IsParameter => Segment.StartsWith("{", StringComparison.OrdinalIgnoreCase); /// /// The subdirectory of a relative path. @@ -136,14 +137,14 @@ public void Attach(OpenApiDocument doc, string label) /// A name tag for labelling the node. /// An node describing an OpenAPI path. public OpenApiUrlTreeNode Attach(string path, - OpenApiPathItem pathItem, + IOpenApiPathItem pathItem, string label) { Utils.CheckArgumentNullOrEmpty(label); Utils.CheckArgumentNullOrEmpty(path); Utils.CheckArgumentNull(pathItem); - if (path.StartsWith(RootPathSegment)) + if (path.StartsWith(RootPathSegment, StringComparison.OrdinalIgnoreCase)) { // Remove leading slash path = path.Substring(1); @@ -173,7 +174,7 @@ public OpenApiUrlTreeNode Attach(string path, /// The relative path of a node. /// An node with all constituent properties assembled. private OpenApiUrlTreeNode Attach(IEnumerable segments, - OpenApiPathItem pathItem, + IOpenApiPathItem pathItem, string label, string currentPath) { diff --git a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs index a889628b3..254528b41 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs @@ -7,6 +7,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; namespace Microsoft.OpenApi.Services @@ -105,14 +106,14 @@ public virtual void Visit(OpenApiPaths paths) /// /// Visits Webhooks> /// - public virtual void Visit(IDictionary webhooks) + public virtual void Visit(IDictionary webhooks) { } /// /// Visits /// - public virtual void Visit(OpenApiPathItem pathItem) + public virtual void Visit(IOpenApiPathItem pathItem) { } @@ -140,42 +141,42 @@ public virtual void Visit(OpenApiOperation operation) /// /// Visits list of /// - public virtual void Visit(IList parameters) + public virtual void Visit(IList parameters) { } /// /// Visits /// - public virtual void Visit(OpenApiParameter parameter) + public virtual void Visit(IOpenApiParameter parameter) { } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiRequestBody requestBody) + public virtual void Visit(IOpenApiRequestBody requestBody) { } /// /// Visits headers. /// - public virtual void Visit(IDictionary headers) + public virtual void Visit(IDictionary headers) { } /// /// Visits callbacks. /// - public virtual void Visit(IDictionary callbacks) + public virtual void Visit(IDictionary callbacks) { } /// /// Visits /// - public virtual void Visit(OpenApiResponse response) + public virtual void Visit(IOpenApiResponse response) { } @@ -210,7 +211,7 @@ public virtual void Visit(OpenApiEncoding encoding) /// /// Visits the examples. /// - public virtual void Visit(IDictionary examples) + public virtual void Visit(IDictionary examples) { } @@ -229,30 +230,30 @@ public virtual void Visit(OpenApiExternalDocs externalDocs) } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiSchema schema) + public virtual void Visit(IOpenApiSchema schema) { } /// /// Visits the links. /// - public virtual void Visit(IDictionary links) + public virtual void Visit(IDictionary links) { } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiLink link) + public virtual void Visit(IOpenApiLink link) { } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiCallback callback) + public virtual void Visit(IOpenApiCallback callback) { } @@ -273,7 +274,7 @@ public virtual void Visit(OpenApiTagReference tag) /// /// Visits /// - public virtual void Visit(OpenApiHeader header) + public virtual void Visit(IOpenApiHeader header) { } @@ -292,16 +293,16 @@ public virtual void Visit(OpenApiSecurityRequirement securityRequirement) } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiSecurityScheme securityScheme) + public virtual void Visit(IOpenApiSecurityScheme securityScheme) { } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiExample example) + public virtual void Visit(IOpenApiExample example) { } @@ -341,9 +342,9 @@ public virtual void Visit(IOpenApiExtension openApiExtension) } /// - /// Visits list of + /// Visits list of /// - public virtual void Visit(IList example) + public virtual void Visit(IList example) { } @@ -365,8 +366,8 @@ public virtual void Visit(IDictionary encodings) /// /// Visits IOpenApiReferenceable instances that are references and not in components /// - /// referenced object - public virtual void Visit(IOpenApiReferenceable referenceable) + /// Referencing object + public virtual void Visit(IOpenApiReferenceHolder referenceHolder) { } } diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index 9321b3b17..ae4430067 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; namespace Microsoft.OpenApi.Services @@ -17,10 +18,9 @@ namespace Microsoft.OpenApi.Services /// public class OpenApiWalker { - private OpenApiDocument _hostDocument; private readonly OpenApiVisitorBase _visitor; - private readonly Stack _schemaLoop = new(); - private readonly Stack _pathItemLoop = new(); + private readonly Stack _schemaLoop = new(); + private readonly Stack _pathItemLoop = new(); /// /// Initializes the class. @@ -41,7 +41,6 @@ public void Walk(OpenApiDocument doc) return; } - _hostDocument = doc; _schemaLoop.Clear(); _pathItemLoop.Clear(); @@ -282,7 +281,7 @@ internal void Walk(OpenApiPaths paths) /// /// Visits Webhooks and child objects /// - internal void Walk(IDictionary webhooks) + internal void Walk(IDictionary webhooks) { if (webhooks == null) { @@ -407,18 +406,18 @@ internal void Walk(OpenApiContact contact) } /// - /// Visits and child objects + /// Visits and child objects /// - internal void Walk(OpenApiCallback callback, bool isComponent = false) + internal void Walk(IOpenApiCallback callback, bool isComponent = false) { if (callback == null) { return; } - if (callback is OpenApiCallbackReference) + if (callback is IOpenApiReferenceHolder openApiReferenceHolder) { - Walk(callback as IOpenApiReferenceable); + Walk(openApiReferenceHolder); return; } @@ -461,7 +460,10 @@ internal void Walk(OpenApiTagReference tag) return; } - Walk(tag as IOpenApiReferenceable); + if (tag is IOpenApiReferenceHolder openApiReferenceHolder) + { + Walk(openApiReferenceHolder); + } } /// @@ -519,16 +521,16 @@ internal void Walk(OpenApiServerVariable serverVariable) /// /// Visits and child objects /// - internal void Walk(OpenApiPathItem pathItem, bool isComponent = false) + internal void Walk(IOpenApiPathItem pathItem, bool isComponent = false) { if (pathItem == null) { return; } - if (pathItem is OpenApiPathItemReference) + if (pathItem is IOpenApiReferenceHolder openApiReferenceHolder) { - Walk(pathItem as IOpenApiReferenceable); + Walk(openApiReferenceHolder); return; } @@ -621,7 +623,7 @@ internal void Walk(IList securityRequirements) /// /// Visits list of /// - internal void Walk(IList parameters) + internal void Walk(IList parameters) { if (parameters == null) { @@ -642,16 +644,16 @@ internal void Walk(IList parameters) /// /// Visits and child objects /// - internal void Walk(OpenApiParameter parameter, bool isComponent = false) + internal void Walk(IOpenApiParameter parameter, bool isComponent = false) { if (parameter == null) { return; } - if (parameter is OpenApiParameterReference) + if (parameter is IOpenApiReferenceHolder openApiReferenceHolder) { - Walk(parameter as IOpenApiReferenceable); + Walk(openApiReferenceHolder); return; } @@ -690,16 +692,16 @@ internal void Walk(OpenApiResponses responses) /// /// Visits and child objects /// - internal void Walk(OpenApiResponse response, bool isComponent = false) + internal void Walk(IOpenApiResponse response, bool isComponent = false) { if (response == null) { return; } - if (response is OpenApiResponseReference) + if (response is IOpenApiReferenceHolder openApiReferenceHolder) { - Walk(response as IOpenApiReferenceable); + Walk(openApiReferenceHolder); return; } @@ -711,18 +713,18 @@ internal void Walk(OpenApiResponse response, bool isComponent = false) } /// - /// Visits and child objects + /// Visits and child objects /// - internal void Walk(OpenApiRequestBody requestBody, bool isComponent = false) + internal void Walk(IOpenApiRequestBody requestBody, bool isComponent = false) { if (requestBody == null) { return; } - if (requestBody is OpenApiRequestBodyReference) + if (requestBody is IOpenApiReferenceHolder openApiReferenceHolder) { - Walk(requestBody as IOpenApiReferenceable); + Walk(openApiReferenceHolder); return; } @@ -738,7 +740,7 @@ internal void Walk(OpenApiRequestBody requestBody, bool isComponent = false) /// /// Visits dictionary of /// - internal void Walk(IDictionary headers) + internal void Walk(IDictionary headers) { if (headers == null) { @@ -758,9 +760,9 @@ internal void Walk(IDictionary headers) } /// - /// Visits dictionary of + /// Visits dictionary of /// - internal void Walk(IDictionary callbacks) + internal void Walk(IDictionary callbacks) { if (callbacks == null) { @@ -862,11 +864,11 @@ internal void Walk(OpenApiEncoding encoding) } /// - /// Visits and child objects + /// Visits and child objects /// - internal void Walk(OpenApiSchema schema, bool isComponent = false) + internal void Walk(IOpenApiSchema schema, bool isComponent = false) { - if (schema == null || ProcessAsReference(schema, isComponent)) + if (schema == null || schema is IOpenApiReferenceHolder holder && ProcessAsReference(holder, isComponent)) { return; } @@ -932,9 +934,9 @@ internal void Walk(OpenApiSchema schema, bool isComponent = false) /// - /// Visits dictionary of + /// Visits dictionary of /// - internal void Walk(IDictionary examples) + internal void Walk(IDictionary examples) { if (examples == null) { @@ -968,18 +970,18 @@ internal void Walk(JsonNode example) } /// - /// Visits and child objects + /// Visits and child objects /// - internal void Walk(OpenApiExample example, bool isComponent = false) + internal void Walk(IOpenApiExample example, bool isComponent = false) { if (example == null) { return; } - if (example is OpenApiExampleReference) + if (example is OpenApiExampleReference reference) { - Walk(example as IOpenApiReferenceable); + Walk(reference); return; } @@ -988,9 +990,9 @@ internal void Walk(OpenApiExample example, bool isComponent = false) } /// - /// Visits the list of and child objects + /// Visits the list of and child objects /// - internal void Walk(IList examples) + internal void Walk(IList examples) { if (examples == null) { @@ -1010,9 +1012,9 @@ internal void Walk(IList examples) } /// - /// Visits a list of and child objects + /// Visits a list of and child objects /// - internal void Walk(IList schemas) + internal void Walk(IList schemas) { if (schemas == null) { @@ -1057,9 +1059,9 @@ internal void Walk(OpenApiOAuthFlow oAuthFlow) } /// - /// Visits dictionary of and child objects + /// Visits dictionary of and child objects /// - internal void Walk(IDictionary links) + internal void Walk(IDictionary links) { if (links == null) { @@ -1082,16 +1084,16 @@ internal void Walk(IDictionary links) /// /// Visits and child objects /// - internal void Walk(OpenApiLink link, bool isComponent = false) + internal void Walk(IOpenApiLink link, bool isComponent = false) { if (link == null) { return; } - if (link is OpenApiLinkReference) + if (link is IOpenApiReferenceHolder openApiReferenceHolder) { - Walk(link as IOpenApiReferenceable); + Walk(openApiReferenceHolder); return; } @@ -1103,16 +1105,16 @@ internal void Walk(OpenApiLink link, bool isComponent = false) /// /// Visits and child objects /// - internal void Walk(OpenApiHeader header, bool isComponent = false) + internal void Walk(IOpenApiHeader header, bool isComponent = false) { if (header == null) { return; } - if (header is OpenApiHeaderReference) + if (header is IOpenApiReferenceHolder openApiReferenceHolder) { - Walk(header as IOpenApiReferenceable); + Walk(openApiReferenceHolder); return; } @@ -1144,18 +1146,18 @@ internal void Walk(OpenApiSecurityRequirement securityRequirement) } /// - /// Visits and child objects + /// Visits and child objects /// - internal void Walk(OpenApiSecurityScheme securityScheme, bool isComponent = false) + internal void Walk(IOpenApiSecurityScheme securityScheme, bool isComponent = false) { if (securityScheme == null) { return; } - if (securityScheme is OpenApiSecuritySchemeReference) + if (securityScheme is IOpenApiReferenceHolder openApiReferenceHolder) { - Walk(securityScheme as IOpenApiReferenceable); + Walk(openApiReferenceHolder); return; } @@ -1166,9 +1168,9 @@ internal void Walk(OpenApiSecurityScheme securityScheme, bool isComponent = fals /// /// Visits and child objects /// - internal void Walk(IOpenApiReferenceable referenceable) + internal void Walk(IOpenApiReferenceHolder referenceableHolder) { - _visitor.Visit(referenceable); + _visitor.Visit(referenceableHolder); } /// @@ -1189,19 +1191,19 @@ internal void Walk(IOpenApiElement element) case OpenApiInfo e: Walk(e); break; case OpenApiComponents e: Walk(e); break; case OpenApiContact e: Walk(e); break; - case OpenApiCallback e: Walk(e); break; + case IOpenApiCallback e: Walk(e); break; case OpenApiEncoding e: Walk(e); break; - case OpenApiExample e: Walk(e); break; - case IDictionary e: Walk(e); break; + case IOpenApiExample e: Walk(e); break; + case IDictionary e: Walk(e); break; case OpenApiExternalDocs e: Walk(e); break; case OpenApiHeader e: Walk(e); break; case OpenApiLink e: Walk(e); break; - case IDictionary e: Walk(e); break; + case IDictionary e: Walk(e); break; case OpenApiMediaType e: Walk(e); break; case OpenApiOAuthFlows e: Walk(e); break; case OpenApiOAuthFlow e: Walk(e); break; case OpenApiOperation e: Walk(e); break; - case OpenApiParameter e: Walk(e); break; + case IOpenApiParameter e: Walk(e); break; case OpenApiPaths e: Walk(e); break; case OpenApiRequestBody e: Walk(e); break; case OpenApiResponse e: Walk(e); break; @@ -1232,13 +1234,13 @@ private void Walk(string context, Action walk) /// /// Identify if an element is just a reference to a component, or an actual component /// - private bool ProcessAsReference(IOpenApiReferenceable referenceable, bool isComponent = false) + private bool ProcessAsReference(IOpenApiReferenceHolder referenceableHolder, bool isComponent = false) { - var isReference = referenceable.Reference != null && - (!isComponent || referenceable.UnresolvedReference); + var isReference = referenceableHolder.Reference != null && + (!isComponent || referenceableHolder.UnresolvedReference); if (isReference) { - Walk(referenceable); + Walk(referenceableHolder); } return isReference; } diff --git a/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs b/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs index f92e6f322..ec368a6c0 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Services { @@ -165,16 +166,16 @@ public bool RegisterComponentForDocument(OpenApiDocument openApiDocument, T c var location = componentToRegister switch { - OpenApiSchema => baseUri + ReferenceType.Schema.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiParameter => baseUri + ReferenceType.Parameter.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiResponse => baseUri + ReferenceType.Response.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiRequestBody => baseUri + ReferenceType.RequestBody.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiLink => baseUri + ReferenceType.Link.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiCallback => baseUri + ReferenceType.Callback.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiPathItem => baseUri + ReferenceType.PathItem.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiExample => baseUri + ReferenceType.Example.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiHeader => baseUri + ReferenceType.Header.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiSecurityScheme => baseUri + ReferenceType.SecurityScheme.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiSchema => baseUri + ReferenceType.Schema.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiParameter => baseUri + ReferenceType.Parameter.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiResponse => baseUri + ReferenceType.Response.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiRequestBody => baseUri + ReferenceType.RequestBody.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiLink => baseUri + ReferenceType.Link.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiCallback => baseUri + ReferenceType.Callback.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiPathItem => baseUri + ReferenceType.PathItem.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiExample => baseUri + ReferenceType.Example.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiHeader => baseUri + ReferenceType.Header.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiSecurityScheme => baseUri + ReferenceType.SecurityScheme.GetDisplayName() + ComponentSegmentSeparator + id, _ => throw new ArgumentException($"Invalid component type {componentToRegister.GetType().Name}"), }; diff --git a/src/Microsoft.OpenApi/Services/OperationSearch.cs b/src/Microsoft.OpenApi/Services/OperationSearch.cs index 8b1dbd1ee..c726ac966 100644 --- a/src/Microsoft.OpenApi/Services/OperationSearch.cs +++ b/src/Microsoft.OpenApi/Services/OperationSearch.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Services { @@ -30,11 +31,8 @@ public OperationSearch(Func pred _predicate = predicate ?? throw new ArgumentNullException(nameof(predicate)); } - /// - /// Visits - /// - /// The target . - public override void Visit(OpenApiPathItem pathItem) + /// + public override void Visit(IOpenApiPathItem pathItem) { foreach (var item in pathItem.Operations) { @@ -57,14 +55,14 @@ public override void Visit(OpenApiPathItem pathItem) /// Visits list of . /// /// The target list of . - public override void Visit(IList parameters) + public override void Visit(IList parameters) { /* The Parameter.Explode property should be true * if Parameter.Style == Form; but OData query params * as used in Microsoft Graph implement explode: false * ex: $select=id,displayName,givenName */ - foreach (var parameter in parameters.Where(x => x.Style == ParameterStyle.Form)) + foreach (var parameter in parameters.OfType().Where(static x => x.Style == ParameterStyle.Form)) { parameter.Explode = false; } diff --git a/src/Microsoft.OpenApi/Services/ReferenceHostDocumentSetter.cs b/src/Microsoft.OpenApi/Services/ReferenceHostDocumentSetter.cs index 1d9bb8e8e..c660d21bd 100644 --- a/src/Microsoft.OpenApi/Services/ReferenceHostDocumentSetter.cs +++ b/src/Microsoft.OpenApi/Services/ReferenceHostDocumentSetter.cs @@ -18,16 +18,10 @@ public ReferenceHostDocumentSetter(OpenApiDocument currentDocument) _currentDocument = currentDocument; } - /// - /// Visits the referenceable element in the host document - /// - /// The referenceable element in the doc. - public override void Visit(IOpenApiReferenceable referenceable) + /// + public override void Visit(IOpenApiReferenceHolder referenceHolder) { - if (referenceable.Reference != null) - { - referenceable.Reference.HostDocument = _currentDocument; - } + referenceHolder.Reference?.EnsureHostDocumentIsSet(_currentDocument); } } } diff --git a/src/Microsoft.OpenApi/Services/SearchResult.cs b/src/Microsoft.OpenApi/Services/SearchResult.cs index 47fff14df..6bbeed27a 100644 --- a/src/Microsoft.OpenApi/Services/SearchResult.cs +++ b/src/Microsoft.OpenApi/Services/SearchResult.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Services { @@ -24,6 +25,6 @@ public class SearchResult /// /// Parameters object /// - public IList Parameters { get; set; } + public IList Parameters { get; set; } } } diff --git a/src/Microsoft.OpenApi/Utils.cs b/src/Microsoft.OpenApi/Utils.cs index b025af8e7..094361bb9 100644 --- a/src/Microsoft.OpenApi/Utils.cs +++ b/src/Microsoft.OpenApi/Utils.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace Microsoft.OpenApi @@ -19,7 +20,11 @@ internal static class Utils /// The input parameter name. /// The input value. internal static T CheckArgumentNull( +#if NET5_0_OR_GREATER + [NotNull] T value, +#else T value, +#endif [CallerArgumentExpression(nameof(value))] string parameterName = "") { return value ?? throw new ArgumentNullException(parameterName, $"Value cannot be null: {parameterName}"); @@ -32,7 +37,11 @@ internal static T CheckArgumentNull( /// The input parameter name. /// The input value. internal static string CheckArgumentNullOrEmpty( +#if NET5_0_OR_GREATER + [NotNull] string value, +#else string value, +#endif [CallerArgumentExpression(nameof(value))] string parameterName = "") { return string.IsNullOrWhiteSpace(value) ? throw new ArgumentNullException(parameterName, $"Value cannot be null or empty: {parameterName}") : value; diff --git a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs index 7281ef258..784f06172 100644 --- a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs +++ b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; namespace Microsoft.OpenApi.Validations @@ -80,10 +81,10 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(OpenApiComponents components) => Validate(components); /// - public override void Visit(OpenApiHeader header) => Validate(header); + public override void Visit(IOpenApiHeader header) => Validate(header); /// - public override void Visit(OpenApiResponse response) => Validate(response); + public override void Visit(IOpenApiResponse response) => Validate(response); /// public override void Visit(OpenApiMediaType mediaType) => Validate(mediaType); @@ -104,10 +105,10 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(OpenApiTag tag) => Validate(tag); /// - public override void Visit(OpenApiParameter parameter) => Validate(parameter); + public override void Visit(IOpenApiParameter parameter) => Validate(parameter); /// - public override void Visit(OpenApiSchema schema) => Validate(schema); + public override void Visit(IOpenApiSchema schema) => Validate(schema); /// public override void Visit(OpenApiServer server) => Validate(server); @@ -116,7 +117,7 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(OpenApiEncoding encoding) => Validate(encoding); /// - public override void Visit(OpenApiCallback callback) => Validate(callback); + public override void Visit(IOpenApiCallback callback) => Validate(callback); /// public override void Visit(IOpenApiExtensible openApiExtensible) => Validate(openApiExtensible); @@ -125,46 +126,46 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(IOpenApiExtension openApiExtension) => Validate(openApiExtension, openApiExtension.GetType()); /// - public override void Visit(IList example) => Validate(example, example.GetType()); + public override void Visit(IList example) => Validate(example, example.GetType()); /// - public override void Visit(OpenApiPathItem pathItem) => Validate(pathItem); + public override void Visit(IOpenApiPathItem pathItem) => Validate(pathItem); /// public override void Visit(OpenApiServerVariable serverVariable) => Validate(serverVariable); /// - public override void Visit(OpenApiSecurityScheme securityScheme) => Validate(securityScheme); + public override void Visit(IOpenApiSecurityScheme securityScheme) => Validate(securityScheme); /// public override void Visit(OpenApiSecurityRequirement securityRequirement) => Validate(securityRequirement); /// - public override void Visit(OpenApiRequestBody requestBody) => Validate(requestBody); + public override void Visit(IOpenApiRequestBody requestBody) => Validate(requestBody); /// public override void Visit(OpenApiPaths paths) => Validate(paths); /// - public override void Visit(OpenApiLink link) => Validate(link); + public override void Visit(IOpenApiLink link) => Validate(link); /// - public override void Visit(OpenApiExample example) => Validate(example); + public override void Visit(IOpenApiExample example) => Validate(example); /// public override void Visit(OpenApiOperation operation) => Validate(operation); /// public override void Visit(IDictionary operations) => Validate(operations, operations.GetType()); /// - public override void Visit(IDictionary headers) => Validate(headers, headers.GetType()); + public override void Visit(IDictionary headers) => Validate(headers, headers.GetType()); /// - public override void Visit(IDictionary callbacks) => Validate(callbacks, callbacks.GetType()); + public override void Visit(IDictionary callbacks) => Validate(callbacks, callbacks.GetType()); /// public override void Visit(IDictionary content) => Validate(content, content.GetType()); /// - public override void Visit(IDictionary examples) => Validate(examples, examples.GetType()); + public override void Visit(IDictionary examples) => Validate(examples, examples.GetType()); /// - public override void Visit(IDictionary links) => Validate(links, links.GetType()); + public override void Visit(IDictionary links) => Validate(links, links.GetType()); /// public override void Visit(IDictionary serverVariables) => Validate(serverVariables, serverVariables.GetType()); /// @@ -189,9 +190,9 @@ private void Validate(object item, Type type) } // Validate unresolved references as references - if (item is IOpenApiReferenceable { UnresolvedReference: true }) + if (item is IOpenApiReferenceHolder { UnresolvedReference: true }) { - type = typeof(IOpenApiReferenceable); + type = typeof(IOpenApiReferenceHolder); } var rules = _ruleSet.FindRules(type); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs index 3509d797f..545f68f85 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -22,7 +23,7 @@ public static class OpenApiExtensibleRules (context, item) => { context.Enter("extensions"); - foreach (var extensible in item.Extensions.Keys.Where(static x => !x.StartsWith("x-", StringComparison.OrdinalIgnoreCase))) + foreach (var extensible in item.Extensions.Keys.Where(static x => !x.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase))) { context.CreateError(nameof(ExtensionNameMustStartWithXDash), string.Format(SRResource.Validation_ExtensionNameMustBeginWithXDash, extensible, context.PathString)); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs index f02be33ee..03661401c 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Validations.Rules { @@ -16,7 +17,7 @@ public static class OpenApiNonDefaultRules /// /// Validate the data matches with the given data type. /// - public static ValidationRule HeaderMismatchedDataType => + public static ValidationRule HeaderMismatchedDataType => new(nameof(HeaderMismatchedDataType), (context, header) => { @@ -46,7 +47,7 @@ public static class OpenApiNonDefaultRules /// /// Validate the data matches with the given data type. /// - public static ValidationRule SchemaMismatchedDataType => + public static ValidationRule SchemaMismatchedDataType => new(nameof(SchemaMismatchedDataType), (context, schema) => { @@ -89,8 +90,8 @@ public static class OpenApiNonDefaultRules private static void ValidateMismatchedDataType(IValidationContext context, string ruleName, JsonNode example, - IDictionary examples, - OpenApiSchema schema) + IDictionary examples, + IOpenApiSchema schema) { // example context.Enter("example"); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiParameterRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiParameterRules.cs index 812bc7f12..26fa30005 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiParameterRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiParameterRules.cs @@ -3,6 +3,7 @@ using System; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -16,7 +17,7 @@ public static class OpenApiParameterRules /// /// Validate the field is required. /// - public static ValidationRule ParameterRequiredFields => + public static ValidationRule ParameterRequiredFields => new(nameof(ParameterRequiredFields), (context, item) => { @@ -42,7 +43,7 @@ public static class OpenApiParameterRules /// /// Validate the "required" field is true when "in" is path. /// - public static ValidationRule RequiredMustBeTrueWhenInIsPath => + public static ValidationRule RequiredMustBeTrueWhenInIsPath => new(nameof(RequiredMustBeTrueWhenInIsPath), (context, item) => { @@ -61,7 +62,7 @@ public static class OpenApiParameterRules /// /// Validate that a path parameter should always appear in the path /// - public static ValidationRule PathParameterShouldBeInThePath => + public static ValidationRule PathParameterShouldBeInThePath => new(nameof(PathParameterShouldBeInThePath), (context, parameter) => { diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiResponseRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiResponseRules.cs index f30b49ea0..ff0503f9b 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiResponseRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiResponseRules.cs @@ -3,6 +3,7 @@ using System; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -16,7 +17,7 @@ public static class OpenApiResponseRules /// /// Validate the field is required. /// - public static ValidationRule ResponseRequiredFields => + public static ValidationRule ResponseRequiredFields => new(nameof(ResponseRequiredFields), (context, response) => { diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs index 054c79c6b..b954c96b6 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -16,14 +18,14 @@ public static class OpenApiSchemaRules /// /// Validates Schema Discriminator /// - public static ValidationRule ValidateSchemaDiscriminator => + public static ValidationRule ValidateSchemaDiscriminator => new(nameof(ValidateSchemaDiscriminator), (context, schema) => { // discriminator context.Enter("discriminator"); - if (schema.Reference != null && schema.Discriminator != null) + if (schema is not null && schema.Discriminator != null) { var discriminatorName = schema.Discriminator?.PropertyName; @@ -31,7 +33,7 @@ public static class OpenApiSchemaRules { context.CreateError(nameof(ValidateSchemaDiscriminator), string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator, - schema.Reference.Id, discriminatorName)); + schema is OpenApiSchemaReference { Reference: not null} schemaReference ? schemaReference.Reference.Id : string.Empty, discriminatorName)); } } @@ -44,7 +46,7 @@ public static class OpenApiSchemaRules /// The parent schema. /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate /// between other schemas which may satisfy the payload description. - public static bool ValidateChildSchemaAgainstDiscriminator(OpenApiSchema schema, string discriminatorName) + public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema, string discriminatorName) { if (!schema.Required?.Contains(discriminatorName) ?? false) { @@ -77,7 +79,7 @@ public static bool ValidateChildSchemaAgainstDiscriminator(OpenApiSchema schema, /// between other schemas which may satisfy the payload description. /// The child schema. /// - public static bool TraverseSchemaElements(string discriminatorName, IList childSchema) + public static bool TraverseSchemaElements(string discriminatorName, IList childSchema) { foreach (var childItem in childSchema) { diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index 61b9d3a0c..63ca4d05e 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -5,6 +5,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Validations.Rules { @@ -44,7 +45,7 @@ public static void ValidateDataTypeMismatch( IValidationContext context, string ruleName, JsonNode value, - OpenApiSchema schema) + IOpenApiSchema schema) { if (schema == null) { @@ -56,11 +57,10 @@ public static void ValidateDataTypeMismatch( var type = schema.Type.ToIdentifier(); var format = schema.Format; - var nullable = schema.Nullable; // Before checking the type, check first if the schema allows null. // If so and the data given is also null, this is allowed for any type. - if (nullable && valueKind is JsonValueKind.Null) + if ((schema.Type.Value & JsonSchemaType.Null) is JsonSchemaType.Null && valueKind is JsonValueKind.Null) { return; } diff --git a/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs b/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs index 7f525d642..aaa160548 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.IO; namespace Microsoft.OpenApi.Writers @@ -189,7 +190,7 @@ public override void WriteValue(string value) WriteChompingIndicator(value); // Write indentation indicator when it starts with spaces - if (value.StartsWith(" ")) + if (value.StartsWith(" ", StringComparison.OrdinalIgnoreCase)) { Writer.Write(IndentationString.Length); } diff --git a/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs b/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs index 708aa7237..22388b076 100644 --- a/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs +++ b/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs @@ -148,7 +148,7 @@ internal static string GetYamlCompatibleString(this string input) // wrap the string in single quote. // http://www.yaml.org/spec/1.2/spec.html#style/flow/plain if (_yamlPlainStringForbiddenCombinations.Any(fc => input.Contains(fc)) || - _yamlIndicators.Any(i => input.StartsWith(i)) || + _yamlIndicators.Any(i => input.StartsWith(i, StringComparison.Ordinal)) || _yamlPlainStringForbiddenTerminals.Any(i => input.EndsWith(i)) || input.Trim() != input) { @@ -199,7 +199,7 @@ internal static string GetJsonCompatibleString(this string value) internal static bool IsHexadecimalNotation(string input) { - return input.StartsWith("0x") && int.TryParse(input.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _); + return input.StartsWith("0x", StringComparison.Ordinal) && int.TryParse(input.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _); } } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs index 110cac88c..da6d8c61e 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs @@ -2,6 +2,7 @@ using Microsoft.OpenApi.Hidi.Formatters; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Xunit; @@ -27,7 +28,7 @@ public void FormatOperationIdsInOpenAPIDocument(string operationId, string expec Servers = new List { new() { Url = "https://localhost/" } }, Paths = new() { - { path, new() { + { path, new OpenApiPathItem() { Operations = new Dictionary { { operationType, new() { OperationId = operationId } } @@ -57,21 +58,23 @@ public void RemoveAnyOfAndOneOfFromSchema() var walker = new OpenApiWalker(powerShellFormatter); walker.Walk(openApiDocument); - var testSchema = openApiDocument.Components?.Schemas?["TestSchema"]; - var averageAudioDegradationProperty = testSchema?.Properties["averageAudioDegradation"]; - var defaultPriceProperty = testSchema?.Properties["defaultPrice"]; + Assert.NotNull(openApiDocument.Components); + Assert.NotNull(openApiDocument.Components.Schemas); + var testSchema = openApiDocument.Components.Schemas["TestSchema"]; + var averageAudioDegradationProperty = testSchema.Properties["averageAudioDegradation"]; + var defaultPriceProperty = testSchema.Properties["defaultPrice"]; // Assert Assert.NotNull(openApiDocument.Components); Assert.NotNull(openApiDocument.Components.Schemas); Assert.NotNull(testSchema); - Assert.Null(averageAudioDegradationProperty?.AnyOf); - Assert.Equal(JsonSchemaType.Number, averageAudioDegradationProperty?.Type); - Assert.Equal("float", averageAudioDegradationProperty?.Format); - Assert.True(averageAudioDegradationProperty?.Nullable); - Assert.Null(defaultPriceProperty?.OneOf); - Assert.Equal(JsonSchemaType.Number, defaultPriceProperty?.Type); - Assert.Equal("double", defaultPriceProperty?.Format); + Assert.Null(averageAudioDegradationProperty.AnyOf); + Assert.Equal(JsonSchemaType.Number | JsonSchemaType.Null, averageAudioDegradationProperty.Type); + Assert.Equal("float", averageAudioDegradationProperty.Format); + Assert.Equal(JsonSchemaType.Null, averageAudioDegradationProperty.Type & JsonSchemaType.Null); + Assert.Null(defaultPriceProperty.OneOf); + Assert.Equal(JsonSchemaType.Number, defaultPriceProperty.Type); + Assert.Equal("double", defaultPriceProperty.Format); Assert.NotNull(testSchema.AdditionalProperties); } @@ -101,7 +104,7 @@ private static OpenApiDocument GetSampleOpenApiDocument() Info = new() { Title = "Test", Version = "1.0" }, Servers = new List { new() { Url = "https://localhost/" } }, Paths = new() { - { "/foo", new() + { "/foo", new OpenApiPathItem() { Operations = new Dictionary { @@ -109,9 +112,9 @@ private static OpenApiDocument GetSampleOpenApiDocument() OperationType.Get, new() { OperationId = "Foo.GetFoo", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "ids", In = ParameterLocation.Query, @@ -121,10 +124,10 @@ private static OpenApiDocument GetSampleOpenApiDocument() "application/json", new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -133,7 +136,7 @@ private static OpenApiDocument GetSampleOpenApiDocument() } } } - }, + ], Extensions = new Dictionary { { @@ -148,32 +151,31 @@ private static OpenApiDocument GetSampleOpenApiDocument() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { { "TestSchema", new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "averageAudioDegradation", new OpenApiSchema { - AnyOf = new List + AnyOf = new List { - new() { Type = JsonSchemaType.Number }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number | JsonSchemaType.Null }, + new OpenApiSchema() { Type = JsonSchemaType.String } }, Format = "float", - Nullable = true } }, { "defaultPrice", new OpenApiSchema { - OneOf = new List + OneOf = new List { - new() { Type = JsonSchemaType.Number, Format = "double" }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "double" }, + new OpenApiSchema() { Type = JsonSchemaType.String } } } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index 77f2c9ae9..a3494ba13 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -3,6 +3,8 @@ using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Tests.UtilityFiles; using Moq; @@ -76,7 +78,7 @@ public void TestPredicateFiltersUsingRelativeRequestUrls() Servers = new List { new() { Url = "https://localhost/" } }, Paths = new() { - {"/foo", new() { + {"/foo", new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() }, @@ -113,26 +115,26 @@ public void CreateFilteredDocumentUsingPredicateFromRequestUrl() Servers = new List { new() { Url = "https://localhost/" } }, Paths = new() { - ["/test/{id}"] = new() + ["/test/{id}"] = new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() }, { OperationType.Patch, new() } }, - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "id", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } } - } + ] } @@ -242,8 +244,10 @@ public async Task CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly( // Assert Assert.Same(doc.Servers, subsetOpenApiDocument.Servers); - Assert.False(responseHeader?.UnresolvedReference); - Assert.False(mediaTypeExample?.UnresolvedReference); + var headerReference = Assert.IsType(responseHeader); + Assert.False(headerReference.UnresolvedReference); + var exampleReference = Assert.IsType(mediaTypeExample); + Assert.False(exampleReference?.UnresolvedReference); Assert.NotNull(targetHeaders); Assert.Single(targetHeaders); Assert.NotNull(targetExamples); diff --git a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs index edbf143fe..3f81c71a3 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs @@ -4,6 +4,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; namespace Microsoft.OpenApi.Tests.UtilityFiles @@ -48,7 +49,7 @@ public static OpenApiDocument CreateOpenApiDocument() }, Paths = new() { - ["/"] = new() // root path + ["/"] = new OpenApiPathItem() // root path { Operations = new Dictionary { @@ -59,7 +60,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200",new() + "200",new OpenApiResponse() { Description = "OK" } @@ -69,7 +70,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [getTeamsActivityByPeriodPath] = new() + [getTeamsActivityByPeriodPath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -78,15 +79,15 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "reports.getTeamsUserActivityCounts", Summary = "Invoke function getTeamsUserActivityUserCounts", - Parameters = new List + Parameters = new List { { - new() + new OpenApiParameter() { Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -96,7 +97,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Success", Content = new Dictionary @@ -105,7 +106,7 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -118,15 +119,15 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - Parameters = new List + Parameters = new List { { - new() + new OpenApiParameter() { Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -134,7 +135,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [getTeamsActivityByDatePath] = new() + [getTeamsActivityByDatePath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -143,15 +144,15 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "reports.getTeamsUserActivityUserDetail-a3f1", Summary = "Invoke function getTeamsUserActivityUserDetail", - Parameters = new List + Parameters = new List { { - new() + new OpenApiParameter() { Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -161,7 +162,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Success", Content = new Dictionary @@ -170,7 +171,7 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -183,21 +184,21 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } } } }, - [usersPath] = new() + [usersPath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -209,7 +210,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entities", Content = new Dictionary @@ -218,25 +219,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Title = "Collection of user", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "value", new OpenApiSchema { Type = JsonSchemaType.Array, - Items = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.user" - } - } } } } @@ -251,7 +244,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [usersByIdPath] = new() + [usersByIdPath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -263,7 +256,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entity", Content = new Dictionary @@ -272,14 +265,6 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.user" - } - } } } } @@ -296,7 +281,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "204", new() + "204", new OpenApiResponse() { Description = "Success" } @@ -306,7 +291,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [messagesByIdPath] = new() + [messagesByIdPath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -316,15 +301,15 @@ public static OpenApiDocument CreateOpenApiDocument() OperationId = "users.GetMessages", Summary = "Get messages from users", Description = "The messages in a mailbox or folder. Read-only. Nullable.", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "$select", In = ParameterLocation.Query, Required = true, Description = "Select properties to be returned", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -334,7 +319,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved navigation property", Content = new Dictionary @@ -343,14 +328,6 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.message" - } - } } } } @@ -361,7 +338,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [administrativeUnitRestorePath] = new() + [administrativeUnitRestorePath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -370,16 +347,16 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "administrativeUnits.restore", Summary = "Invoke action restore", - Parameters = new List + Parameters = new List { { - new() + new OpenApiParameter() { Name = "administrativeUnit-id", In = ParameterLocation.Path, Required = true, Description = "key: id of administrativeUnit", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -389,7 +366,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Success", Content = new Dictionary @@ -398,16 +375,9 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { - AnyOf = new List - { - new() - { - Type = JsonSchemaType.String - } - }, - Nullable = true + Type = JsonSchemaType.String | JsonSchemaType.Null } } } @@ -419,7 +389,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [logoPath] = new() + [logoPath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -431,7 +401,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "204", new() + "204", new OpenApiResponse() { Description = "Success" } @@ -441,7 +411,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [securityProfilesPath] = new() + [securityProfilesPath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -453,7 +423,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved navigation property", Content = new Dictionary @@ -462,25 +432,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Title = "Collection of hostSecurityProfile", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "value", new OpenApiSchema { Type = JsonSchemaType.Array, - Items = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.networkInterface" - } - } } } } @@ -495,7 +457,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [communicationsCallsKeepAlivePath] = new() + [communicationsCallsKeepAlivePath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -504,15 +466,15 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "communications.calls.call.keepAlive", Summary = "Invoke action keepAlive", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "call-id", In = ParameterLocation.Path, Description = "key: id of call", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -527,7 +489,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "204", new() + "204", new OpenApiResponse() { Description = "Success" } @@ -543,7 +505,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [eventsDeltaPath] = new() + [eventsDeltaPath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -552,15 +514,15 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "groups.group.events.event.calendar.events.delta", Summary = "Invoke function delta", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "group-id", In = ParameterLocation.Path, Description = "key: id of group", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -571,13 +533,13 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - new() + new OpenApiParameter() { Name = "event-id", In = ParameterLocation.Path, Description = "key: id of event", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -592,7 +554,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Success", Content = new Dictionary @@ -601,13 +563,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { - Type = JsonSchemaType.Array, - Reference = new() + Properties = new Dictionary { - Type = ReferenceType.Schema, - Id = "microsoft.graph.event" + { + "value", + new OpenApiSchema + { + Type = JsonSchemaType.Array, + } + } } } } @@ -626,7 +592,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - [refPath] = new() + [refPath] = new OpenApiPathItem() { Operations = new Dictionary { @@ -642,21 +608,20 @@ public static OpenApiDocument CreateOpenApiDocument() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { { "microsoft.graph.networkInterface", new OpenApiSchema { Title = "networkInterface", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "description", new OpenApiSchema { - Type = JsonSchemaType.String, + Type = JsonSchemaType.String | JsonSchemaType.Null, Description = "Description of the NIC (e.g. Ethernet adapter, Wireless LAN adapter Local Area Connection <#>, etc.).", - Nullable = true } } } @@ -725,6 +690,11 @@ public static OpenApiDocument CreateOpenApiDocument() document.Paths[communicationsCallsKeepAlivePath].Operations[OperationType.Post].Tags!.Add(new OpenApiTagReference("communications.Actions", document)); document.Paths[eventsDeltaPath].Operations[OperationType.Get].Tags!.Add(new OpenApiTagReference("groups.Functions", document)); document.Paths[refPath].Operations[OperationType.Get].Tags!.Add(new OpenApiTagReference("applications.directoryObject", document)); + ((OpenApiSchema)document.Paths[usersPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.user", document); + document.Paths[usersByIdPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema = new OpenApiSchemaReference("microsoft.graph.user", document); + document.Paths[messagesByIdPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema = new OpenApiSchemaReference("microsoft.graph.message", document); + ((OpenApiSchema)document.Paths[securityProfilesPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.networkInterface", document); + ((OpenApiSchema)document.Paths[eventsDeltaPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.event", document); return document; } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs index 2b079ffb8..68ecbe33e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs @@ -30,7 +30,6 @@ public async Task LoadingDocumentWithResolveAllReferencesShouldLoadDocumentIntoW BaseUrl = new("file://c:\\") }; - // Todo: this should be ReadAsync var stream = new MemoryStream(); var doc = """ openapi: 3.0.0 diff --git a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs index 356f4268d..3edc9ac67 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs @@ -30,20 +30,21 @@ public async Task LoadParameterReference() var reference = new OpenApiParameterReference("skipParam", result.Document); // Assert - reference.Should().BeEquivalentTo( + Assert.Equivalent( new OpenApiParameter { Name = "skip", In = ParameterLocation.Query, Description = "number of items to skip", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" } - }, options => options.Excluding(x => x.Reference) + }, + reference ); } @@ -55,13 +56,13 @@ public async Task LoadSecuritySchemeReference() var reference = new OpenApiSecuritySchemeReference("api_key_sample", result.Document); // Assert - reference.Should().BeEquivalentTo( + Assert.Equivalent( new OpenApiSecurityScheme { Type = SecuritySchemeType.ApiKey, Name = "api_key", In = ParameterLocation.Header - }, options => options.Excluding(x => x.Reference) + }, reference ); } @@ -73,7 +74,7 @@ public async Task LoadResponseReference() var reference = new OpenApiResponseReference("NotFound", result.Document); // Assert - reference.Should().BeEquivalentTo( + Assert.Equivalent( new OpenApiResponse { Description = "Entity not found.", @@ -81,7 +82,7 @@ public async Task LoadResponseReference() { ["application/json"] = new() } - }, options => options.Excluding(x => x.Reference) + }, reference ); } @@ -91,46 +92,23 @@ public async Task LoadResponseAndSchemaReference() var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); var reference = new OpenApiResponseReference("GeneralError", result.Document); - // Assert - reference.Should().BeEquivalentTo( - new OpenApiResponse + var expected = new OpenApiResponse { Description = "General Error", Content = { ["application/json"] = new() { - Schema = new() - { - Description = "Sample description", - Required = new HashSet {"name" }, - Properties = { - ["name"] = new() - { - Type = JsonSchemaType.String - }, - ["tag"] = new() - { - Type = JsonSchemaType.String - } - }, - - Reference = new() - { - Type = ReferenceType.Schema, - Id = "SampleObject2", - HostDocument = result.Document - } - } + Schema = new OpenApiSchemaReference("SampleObject2") } - }, - Reference = new() - { - Type = ReferenceType.Response, - Id = "GeneralError" } - }, options => options.Excluding(x => x.Reference) - ); + }; + + ((OpenApiSchemaReference)expected.Content["application/json"].Schema).Reference.EnsureHostDocumentIsSet(result.Document); + var actual = reference.Target; + + // Assert + Assert.Equivalent(expected, actual); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index 02938f4b0..136c46892 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -10,6 +10,7 @@ using FluentAssertions.Equivalency; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Xunit; @@ -73,12 +74,12 @@ public void ParseDocumentWithDifferentCultureShouldSucceed(string culture) { Schemas = { - ["sampleSchema"] = new() + ["sampleSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["sampleProperty"] = new() + ["sampleProperty"] = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = (decimal)100.54, @@ -106,7 +107,7 @@ public async Task ShouldParseProducesInAnyOrder() var okSchema = new OpenApiSchema { - Properties = new Dictionary + Properties = new Dictionary { { "id", new OpenApiSchema { @@ -119,7 +120,7 @@ public async Task ShouldParseProducesInAnyOrder() var errorSchema = new OpenApiSchema { - Properties = new Dictionary + Properties = new Dictionary { { "code", new OpenApiSchema { @@ -142,7 +143,7 @@ public async Task ShouldParseProducesInAnyOrder() var okMediaType = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("Item", result.Document) @@ -170,7 +171,7 @@ public async Task ShouldParseProducesInAnyOrder() }, Paths = new() { - ["/items"] = new() + ["/items"] = new OpenApiPathItem() { Operations = { @@ -178,7 +179,7 @@ public async Task ShouldParseProducesInAnyOrder() { Responses = { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "An OK response", Content = @@ -187,7 +188,7 @@ public async Task ShouldParseProducesInAnyOrder() ["application/xml"] = okMediaType, } }, - ["default"] = new() + ["default"] = new OpenApiResponse() { Description = "An error response", Content = @@ -202,7 +203,7 @@ public async Task ShouldParseProducesInAnyOrder() { Responses = { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "An OK response", Content = @@ -210,7 +211,7 @@ public async Task ShouldParseProducesInAnyOrder() ["html/text"] = okMediaType } }, - ["default"] = new() + ["default"] = new OpenApiResponse() { Description = "An error response", Content = @@ -224,7 +225,7 @@ public async Task ShouldParseProducesInAnyOrder() { Responses = { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "An OK response", Content = @@ -233,7 +234,7 @@ public async Task ShouldParseProducesInAnyOrder() ["application/xml"] = okMediaType, } }, - ["default"] = new() + ["default"] = new OpenApiResponse() { Description = "An error response", Content = @@ -276,7 +277,7 @@ public async Task ShouldAssignSchemaToAllResponses() var responses = result.Document.Paths["/items"].Operations[OperationType.Get].Responses; foreach (var response in responses) { - var targetSchema = response.Key == "200" ? successSchema : errorSchema; + var targetSchema = response.Key == "200" ? (IOpenApiSchema)successSchema : errorSchema; var json = response.Value.Content["application/json"]; Assert.NotNull(json); @@ -294,9 +295,11 @@ public async Task ShouldAllowComponentsThatJustContainAReference() // Act var actual = (await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "ComponentRootReference.json"))).Document; var schema1 = actual.Components.Schemas["AllPets"]; - Assert.False(schema1.UnresolvedReference); - var schema2 = actual.ResolveReferenceTo(schema1.Reference); - if (schema2.UnresolvedReference && schema1.Reference.Id == schema2.Reference.Id) + var schema1Reference = Assert.IsType(schema1); + Assert.False(schema1Reference.UnresolvedReference); + var schema2 = actual.ResolveReferenceTo(schema1Reference.Reference); + Assert.IsType(schema2); + if (string.IsNullOrEmpty(schema1Reference.Reference.Id) || schema1Reference.UnresolvedReference) { // detected a cycle - this code gets triggered Assert.Fail("A cycle should not be detected"); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs index cc15d8427..1b1187a42 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs @@ -34,7 +34,7 @@ public void ParseHeaderWithDefaultShouldSucceed() header.Should().BeEquivalentTo( new OpenApiHeader { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", @@ -63,7 +63,7 @@ public void ParseHeaderWithEnumShouldSucceed() header.Should().BeEquivalentTo( new OpenApiHeader { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs index 7c76c424c..13339332a 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs @@ -10,6 +10,8 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Reader.V2; using Microsoft.OpenApi.Reader.V3; @@ -29,20 +31,20 @@ public class OpenApiOperationTests Summary = "Updates a pet in the store", Description = "", OperationId = "updatePet", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "petId", In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -62,20 +64,20 @@ public class OpenApiOperationTests Summary = "Updates a pet in the store with request body", Description = "", OperationId = "updatePetWithBody", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "petId", In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } }, - }, + ], RequestBody = new OpenApiRequestBody { Description = "Pet to update with", @@ -84,7 +86,7 @@ public class OpenApiOperationTests { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -214,10 +216,10 @@ public void ParseOperationWithResponseExamplesShouldSucceed() { ["application/json"] = new OpenApiMediaType() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -232,10 +234,10 @@ public void ParseOperationWithResponseExamplesShouldSucceed() }, ["application/xml"] = new OpenApiMediaType() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -507,5 +509,99 @@ public async Task LoadV3ExamplesInRequestBodyParameterAsExtensionsWorks() expected = expected.MakeLineBreaksEnvironmentNeutral(); Assert.Equal(expected, actual); } + [Fact] + public async Task SerializesBodyReferencesWorks() + { + var openApiDocument = new OpenApiDocument(); + + var operation = new OpenApiOperation + { + RequestBody = new OpenApiRequestBodyReference("UserRequest", openApiDocument) + { + Description = "User request body" + } + }; + openApiDocument.Paths.Add("/users", new OpenApiPathItem + { + Operations = new Dictionary + { + [OperationType.Post] = operation + } + }); + openApiDocument.AddComponent("UserRequest", new OpenApiRequestBody + { + Description = "User creation request body", + Content = + { + ["application/json"] = new OpenApiMediaType + { + Schema = new OpenApiSchemaReference("UserSchema", openApiDocument) + } + } + }); + openApiDocument.AddComponent("UserSchema", new OpenApiSchema + { + Type = JsonSchemaType.Object, + Properties = + { + ["name"] = new OpenApiSchema + { + Type = JsonSchemaType.String + }, + ["email"] = new OpenApiSchema + { + Type = JsonSchemaType.String + } + } + }); + + var actual = await openApiDocument.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); + var expected = +""" +{ + "swagger": "2.0", + "info": { }, + "paths": { + "/users": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "$ref": "#/parameters/UserRequest" + } + ], + "responses": { } + } + } + }, + "definitions": { + "UserSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + }, + "parameters": { + "UserRequest": { + "in": "body", + "name": "body", + "description": "User creation request body", + "schema": { + "$ref": "#/definitions/UserSchema" + } + } + } +} +"""; + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs index 1b6300faf..aa11d5137 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs @@ -57,7 +57,7 @@ public void ParsePathParameterShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -86,10 +86,10 @@ public void ParseQueryParameterShouldSucceed() Name = "id", Description = "ID of the object to fetch", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -121,7 +121,7 @@ public void ParseParameterWithNullLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -150,7 +150,7 @@ public void ParseParameterWithNoLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -204,7 +204,7 @@ public void ParseParameterWithUnknownLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -233,7 +233,7 @@ public void ParseParameterWithDefaultShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", @@ -260,7 +260,7 @@ public void ParseParameterWithEnumShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs index d33b9964f..412a74dde 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs @@ -19,25 +19,25 @@ public class OpenApiPathItemTests private static readonly OpenApiPathItem _basicPathItemWithFormData = new() { - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to use", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } }, Style = ParameterStyle.Simple } - }, + ], Operations = { [OperationType.Put] = new() @@ -45,37 +45,37 @@ public class OpenApiPathItemTests Summary = "Puts a pet in the store with form data", Description = "", OperationId = "putPetWithForm", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "petId", In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } } - }, - RequestBody = new() + ], + RequestBody = new OpenApiRequestBody() { Content = { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -89,17 +89,17 @@ public class OpenApiPathItemTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -115,7 +115,7 @@ public class OpenApiPathItemTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Pet updated.", Content = new Dictionary @@ -124,7 +124,7 @@ public class OpenApiPathItemTests ["application/xml"] = new() } }, - ["405"] = new() + ["405"] = new OpenApiResponse() { Description = "Invalid input", Content = new Dictionary @@ -140,53 +140,53 @@ public class OpenApiPathItemTests Summary = "Posts a pet in the store with form data", Description = "", OperationId = "postPetWithForm", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "petId", In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } }, - new() + new OpenApiParameter() { Name = "petName", In = ParameterLocation.Path, Description = "Name of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } } - }, - RequestBody = new() + ], + RequestBody = new OpenApiRequestBody() { Content = { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String }, - ["skill"] = new() + ["skill"] = new OpenApiSchema() { Description = "Updated skill of the pet", Type = JsonSchemaType.String @@ -200,22 +200,22 @@ public class OpenApiPathItemTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String }, - ["skill"] = new() + ["skill"] = new OpenApiSchema() { Description = "Updated skill of the pet", Type = JsonSchemaType.String @@ -231,7 +231,7 @@ public class OpenApiPathItemTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Pet updated.", Content = new Dictionary @@ -249,11 +249,8 @@ public class OpenApiPathItemTests public void ParseBasicPathItemWithFormDataShouldSucceed() { // Arrange - MapNode node; - using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicPathItemWithFormData.yaml"))) - { - node = TestHelper.CreateYamlMapNode(stream); - } + using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicPathItemWithFormData.yaml")); + var node = TestHelper.CreateYamlMapNode(stream); // Act var pathItem = OpenApiV2Deserializer.LoadPathItem(node, new()); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs index 1b36921d7..781b272e1 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs @@ -13,6 +13,7 @@ using FluentAssertions.Equivalency; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Readers.Tests.V2Tests { @@ -108,7 +109,7 @@ public void PropertiesReferenceShouldWork() var targetSchema = new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["prop1"] = new OpenApiSchema() { @@ -121,7 +122,7 @@ public void PropertiesReferenceShouldWork() var referenceSchema = new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["propA"] = new OpenApiSchemaReference(referenceId, workingDocument), } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.ParseDocumentWith31PropertiesWorks.verified.txt b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.ParseDocumentWith31PropertiesWorks.verified.txt index 3392a4bb8..fa7dd54e4 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.ParseDocumentWith31PropertiesWorks.verified.txt +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.ParseDocumentWith31PropertiesWorks.verified.txt @@ -5,7 +5,6 @@ info: description: A sample API demonstrating OpenAPI 3.1 features license: name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0.html identifier: Apache-2.0 version: 2.0.0 summary: Sample OpenAPI 3.1 API with the latest features @@ -93,6 +92,11 @@ components: - 'null' - object description: Dynamic attributes for the pet + securitySchemes: + api_key: + type: apiKey + name: api_key + in: header security: - api_key: [ ] webhooks: diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs index 5f8c9e9bb..9c391ceb2 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs @@ -12,6 +12,7 @@ using Xunit; using VerifyXunit; using VerifyTests; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Readers.Tests.V31Tests { @@ -37,7 +38,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() { Schemas = { - ["petSchema"] = new() + ["petSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -45,42 +46,42 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPetSchema"] = new() + ["newPetSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -96,7 +97,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() Version = "1.0.0", Title = "Webhook Example" }, - Webhooks = new Dictionary + Webhooks = new Dictionary { ["pets"] = new OpenApiPathItem { @@ -106,18 +107,18 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -129,13 +130,13 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -145,7 +146,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -153,7 +154,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -211,9 +212,9 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["petSchema"] = new() + ["petSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -221,42 +222,42 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPetSchema"] = new() + ["newPetSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -270,7 +271,7 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() var newPetSchema = new OpenApiSchemaReference("newPetSchema", actual.Document); - components.PathItems = new Dictionary + components.PathItems = new Dictionary { ["pets"] = new OpenApiPathItem { @@ -280,18 +281,18 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -303,13 +304,13 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -378,7 +379,7 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() Version = "1.0.0" }, JsonSchemaDialect = "http://json-schema.org/draft-07/schema#", - Webhooks = new Dictionary + Webhooks = new Dictionary { ["pets"] = components.PathItems["pets"] }, @@ -387,7 +388,6 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() // Assert actual.Document.Should().BeEquivalentTo(expected, options => options - .Excluding(x => x.Webhooks["pets"].Reference) .Excluding(x => x.Workspace) .Excluding(y => y.BaseUri)); Assert.Equivalent( @@ -419,7 +419,7 @@ public async Task ParseDocumentWithPatternPropertiesInSchemaWorks() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["prop1"] = new OpenApiSchema { @@ -434,7 +434,7 @@ public async Task ParseDocumentWithPatternPropertiesInSchemaWorks() Type = JsonSchemaType.String } }, - PatternProperties = new Dictionary + PatternProperties = new Dictionary { ["^x-.*$"] = new OpenApiSchema { diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs index abcaa9df6..555b71c54 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs @@ -9,6 +9,7 @@ using FluentAssertions; using FluentAssertions.Equivalency; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Tests; using Microsoft.OpenApi.Writers; @@ -42,7 +43,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() Schema = "https://json-schema.org/draft/2020-12/schema", Description = "A representation of a person, company, organization, or place", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["fruits"] = new OpenApiSchema { @@ -57,7 +58,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() Type = JsonSchemaType.Array } }, - Definitions = new Dictionary + Definitions = new Dictionary { ["veggie"] = new OpenApiSchema { @@ -67,7 +68,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() "veggieName", "veggieLike" }, - Properties = new Dictionary + Properties = new Dictionary { ["veggieName"] = new OpenApiSchema { @@ -139,13 +140,11 @@ public void TestSchemaCopyConstructorWithTypeArrayWorks() }; // Act - var schemaWithArrayCopy = new OpenApiSchema(schemaWithTypeArray); + var schemaWithArrayCopy = schemaWithTypeArray.CreateShallowCopy() as OpenApiSchema; schemaWithArrayCopy.Type = JsonSchemaType.String; - var simpleSchemaCopy = new OpenApiSchema(simpleSchema) - { - Type = JsonSchemaType.String | JsonSchemaType.Null - }; + var simpleSchemaCopy = simpleSchema.CreateShallowCopy() as OpenApiSchema; + simpleSchemaCopy.Type = JsonSchemaType.String | JsonSchemaType.Null; // Assert Assert.NotEqual(schemaWithTypeArray.Type, schemaWithArrayCopy.Type); @@ -165,9 +164,9 @@ public async Task ParseV31SchemaShouldSucceed() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["one"] = new() + ["one"] = new OpenApiSchema() { Description = "type array", Type = JsonSchemaType.Integer | JsonSchemaType.String @@ -189,29 +188,29 @@ public async Task ParseAdvancedV31SchemaShouldSucceed() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["one"] = new() + ["one"] = new OpenApiSchema() { Description = "type array", Type = JsonSchemaType.Integer | JsonSchemaType.String }, - ["two"] = new() + ["two"] = new OpenApiSchema() { Description = "type 'null'", Type = JsonSchemaType.Null }, - ["three"] = new() + ["three"] = new OpenApiSchema() { Description = "type array including 'null'", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["four"] = new() + ["four"] = new OpenApiSchema() { Description = "array with no items", Type = JsonSchemaType.Array }, - ["five"] = new() + ["five"] = new OpenApiSchema() { Description = "singular example", Type = JsonSchemaType.String, @@ -220,37 +219,37 @@ public async Task ParseAdvancedV31SchemaShouldSucceed() "exampleValue" } }, - ["six"] = new() + ["six"] = new OpenApiSchema() { Description = "exclusiveMinimum true", V31ExclusiveMinimum = 10 }, - ["seven"] = new() + ["seven"] = new OpenApiSchema() { Description = "exclusiveMinimum false", Minimum = 10 }, - ["eight"] = new() + ["eight"] = new OpenApiSchema() { Description = "exclusiveMaximum true", V31ExclusiveMaximum = 20 }, - ["nine"] = new() + ["nine"] = new OpenApiSchema() { Description = "exclusiveMaximum false", Maximum = 20 }, - ["ten"] = new() + ["ten"] = new OpenApiSchema() { Description = "nullable string", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["eleven"] = new() + ["eleven"] = new OpenApiSchema() { Description = "x-nullable string", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["twelve"] = new() + ["twelve"] = new OpenApiSchema() { Description = "file/binary" } @@ -293,7 +292,7 @@ public void CloningSchemaWithExamplesAndEnumsShouldSucceed() Enum = [1, 2, 3] }; - var clone = new OpenApiSchema(schema); + var clone = schema.CreateShallowCopy() as OpenApiSchema; clone.Examples.Add(4); clone.Enum.Add(4); clone.Default = 6; diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiDocument/documentWith31Properties.yaml b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiDocument/documentWith31Properties.yaml index 35e5ccf80..e3d1b6cf5 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiDocument/documentWith31Properties.yaml +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiDocument/documentWith31Properties.yaml @@ -7,7 +7,6 @@ info: license: name: Apache 2.0 identifier: Apache-2.0 # SPDX license identifier, a new 3.1 feature to define an API's SPDX license expression - url: https://www.apache.org/licenses/LICENSE-2.0.html # JSON Schema 2020-12 feature jsonSchemaDialect: "https://json-schema.org/draft/2020-12/schema" @@ -89,6 +88,11 @@ paths: - name $dynamicAnchor: "addressDef" components: + securitySchemes: + api_key: + type: apiKey + name: api_key + in: header schemas: Pet: $id: 'https://example.com/schemas/pet.json' diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs index 7a1b43f2f..5aabe43d3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.OpenApi.Expressions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Xunit; @@ -79,7 +80,7 @@ public async Task ParseCallbackWithReferenceShouldSucceed() new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }, result.Diagnostic); Assert.Equivalent( - new OpenApiCallback + new OpenApiCallbackReference("simpleHook", result.Document) { PathItems = { @@ -93,7 +94,7 @@ public async Task ParseCallbackWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -110,12 +111,6 @@ public async Task ParseCallbackWithReferenceShouldSucceed() } } }, - Reference = new OpenApiReference - { - Type = ReferenceType.Callback, - Id = "simpleHook", - HostDocument = result.Document - } }, callback); } @@ -135,7 +130,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() var callback1 = subscribeOperation.Callbacks["simpleHook"]; Assert.Equivalent( - new OpenApiCallback + new OpenApiCallbackReference("simpleHook", result.Document) { PathItems = { @@ -149,7 +144,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -166,12 +161,6 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() } } }, - Reference = new OpenApiReference - { - Type = ReferenceType.Callback, - Id = "simpleHook", - HostDocument = result.Document - } }, callback1); var callback2 = subscribeOperation.Callbacks["callback2"]; @@ -191,7 +180,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -226,7 +215,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index a46b32f09..ea287db5e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -11,6 +11,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Tests; @@ -25,13 +26,14 @@ namespace Microsoft.OpenApi.Readers.Tests.V3Tests public class OpenApiDocumentTests { private const string SampleFolderPath = "V3Tests/Samples/OpenApiDocument/"; + private const string codacyApi = "https://api.codacy.com/api/api-docs/swagger.yaml"; public OpenApiDocumentTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); } - private static async Task CloneAsync(T element) where T : IOpenApiSerializable + private static async Task CloneAsync(T element) where T : class, IOpenApiSerializable { using var stream = new MemoryStream(); var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); @@ -48,23 +50,6 @@ private static async Task CloneAsync(T element) where T : IOpenApiSerializ return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, new(), out var _); } - private static async Task CloneSecuritySchemeAsync(OpenApiSecurityScheme element) - { - using var stream = new MemoryStream(); - var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(streamWriter, new OpenApiJsonWriterSettings() - { - InlineLocalReferences = true - }); - element.SerializeAsV3(writer); - await writer.FlushAsync(); - stream.Position = 0; - - using var streamReader = new StreamReader(stream); - var result = await streamReader.ReadToEndAsync(); - return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, new(), out var _); - } - [Fact] public void ParseDocumentFromInlineStringShouldSucceed() { @@ -204,9 +189,9 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet1"] = new() + ["pet1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -214,48 +199,48 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -263,14 +248,14 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -322,18 +307,18 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -345,13 +330,13 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -361,7 +346,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -369,7 +354,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -465,21 +450,21 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -525,21 +510,21 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["204"] = new OpenApiResponse @@ -590,9 +575,9 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet1"] = new() + ["pet1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -600,48 +585,48 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -649,21 +634,21 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } } }, }, - SecuritySchemes = new Dictionary + SecuritySchemes = new Dictionary { ["securitySchemeName1"] = new OpenApiSecurityScheme { @@ -680,51 +665,28 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() }; // Create a clone of the schema to avoid modifying things in components. - var petSchema = await CloneAsync(components.Schemas["pet1"]); - petSchema.Reference = new() - { - Id = "pet1", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; - - var newPetSchema = await CloneAsync(components.Schemas["newPet"]); - - newPetSchema.Reference = new() - { - Id = "newPet", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; + var petSchemaSource = Assert.IsType(components.Schemas["pet1"]); + var petSchema = await CloneAsync(petSchemaSource); + Assert.IsType(petSchema); + var petSchemaReference = new OpenApiSchemaReference("pet1"); - var errorModelSchema = await CloneAsync(components.Schemas["errorModel"]); + var newPetSchemaSource = Assert.IsType(components.Schemas["newPet"]); + var newPetSchema = await CloneAsync(newPetSchemaSource); + Assert.IsType(newPetSchema); + var newPetSchemaReference = new OpenApiSchemaReference("newPet"); - errorModelSchema.Reference = new() - { - Id = "errorModel", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; - - var tagReference1 = new OpenApiTagReference("tagName1", null); + var errorModelSchemaSource = Assert.IsType(components.Schemas["errorModel"]); + var errorModelSchema = await CloneAsync(errorModelSchemaSource); + Assert.IsType(errorModelSchema); + var errorModelSchemaReference = new OpenApiSchemaReference("errorModel"); - var tagReference2 = new OpenApiTagReference("tagName2", null); + var tagReference1 = new OpenApiTagReference("tagName1"); - var securityScheme1 = await CloneSecuritySchemeAsync(components.SecuritySchemes["securitySchemeName1"]); - - securityScheme1.Reference = new OpenApiReference - { - Id = "securitySchemeName1", - Type = ReferenceType.SecurityScheme - }; + var tagReference2 = new OpenApiTagReference("tagName2"); - var securityScheme2 = await CloneSecuritySchemeAsync(components.SecuritySchemes["securitySchemeName2"]); + Assert.IsType(components.SecuritySchemes["securitySchemeName1"]); - securityScheme2.Reference = new OpenApiReference - { - Id = "securitySchemeName2", - Type = ReferenceType.SecurityScheme - }; + Assert.IsType(components.SecuritySchemes["securitySchemeName2"]); var expected = new OpenApiDocument { @@ -769,18 +731,18 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() }, Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -792,13 +754,13 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -808,18 +770,18 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = petSchema + Items = petSchemaReference } }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = petSchema + Items = petSchemaReference } } } @@ -831,7 +793,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -842,7 +804,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -865,7 +827,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = newPetSchema + Schema = newPetSchemaReference } } }, @@ -878,7 +840,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference }, } }, @@ -889,7 +851,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -900,7 +862,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -909,8 +871,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { new OpenApiSecurityRequirement { - [securityScheme1] = new List(), - [securityScheme2] = new List + [new OpenApiSecuritySchemeReference("securitySchemeName1")] = new List(), + [new OpenApiSecuritySchemeReference("securitySchemeName2")] = new List { "scope1", "scope2" @@ -929,21 +891,21 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -953,11 +915,11 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference }, ["application/xml"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference } } }, @@ -968,7 +930,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -979,7 +941,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -989,21 +951,21 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["204"] = new OpenApiResponse @@ -1017,7 +979,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -1028,7 +990,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -1055,8 +1017,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { new OpenApiSecurityRequirement { - [securityScheme1] = new List(), - [securityScheme2] = new List + [new OpenApiSecuritySchemeReference("securitySchemeName1")] = new List(), + [new OpenApiSecuritySchemeReference("securitySchemeName2")] = new List { "scope1", "scope2", @@ -1065,11 +1027,11 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() } } }; - - tagReference1.Reference.HostDocument = expected; - tagReference2.Reference.HostDocument = expected; + expected.RegisterComponents(); + expected.SetReferenceHostDocument(); actual.Document.Should().BeEquivalentTo(expected, options => options + .IgnoringCyclicReferences() .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Reference) .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Reference.HostDocument) .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Target) @@ -1104,8 +1066,7 @@ public async Task GlobalSecurityRequirementShouldReferenceSecurityScheme() var securityRequirement = result.Document.SecurityRequirements[0]; - securityRequirement.Keys.First().Should().BeEquivalentTo(result.Document.Components.SecuritySchemes.First().Value, - options => options.Excluding(x => x.Reference)); + Assert.Equivalent(result.Document.Components.SecuritySchemes.First().Value, securityRequirement.Keys.First()); } [Fact] @@ -1126,14 +1087,13 @@ public async Task HeaderParameterShouldAllowExample() Style = ParameterStyle.Simple, Explode = true, Example = "99391c7e-ad88-49ec-a2ad-99ddcb1f7721", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "uuid" }, }, options => options.IgnoringCyclicReferences() - .Excluding(e => e.Example.Parent) - .Excluding(x => x.Reference)); + .Excluding(e => e.Example.Parent)); var examplesHeader = result.Document.Components?.Headers?["examples-header"]; Assert.NotNull(examplesHeader); @@ -1147,7 +1107,7 @@ public async Task HeaderParameterShouldAllowExample() AllowReserved = true, Style = ParameterStyle.Simple, Explode = true, - Examples = new Dictionary() + Examples = { { "uuid1", new OpenApiExample() { @@ -1160,7 +1120,7 @@ public async Task HeaderParameterShouldAllowExample() } } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "uuid" @@ -1183,7 +1143,6 @@ public async Task ParseDocumentWithReferencedSecuritySchemeWorks() var securityScheme = result.Document.Components.SecuritySchemes["OAuth2"]; // Assert - Assert.False(securityScheme.UnresolvedReference); Assert.NotNull(securityScheme.Flows); } @@ -1225,6 +1184,19 @@ public async Task ValidateExampleShouldNotHaveDataTypeMismatch() [Fact] public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() { + var parameter = new OpenApiParameter + { + Name = "limit", + In = ParameterLocation.Query, + Description = "Limit the number of pets returned", + Required = false, + Schema = new OpenApiSchema() + { + Type = JsonSchemaType.Integer, + Format = "int32", + Default = 10 + }, + }; // Arrange var expected = new OpenApiDocument { @@ -1244,24 +1216,7 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() Summary = "Returns all pets", Parameters = [ - new OpenApiParameter - { - Name = "limit", - In = ParameterLocation.Query, - Description = "Limit the number of pets returned", - Required = false, - Schema = new() - { - Type = JsonSchemaType.Integer, - Format = "int32", - Default = 10 - }, - Reference = new OpenApiReference - { - Id = "LimitParameter", - Type = ReferenceType.Parameter - } - } + new OpenApiParameterReference("LimitParameter"), ], Responses = new OpenApiResponses() } @@ -1270,26 +1225,18 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() }, Components = new OpenApiComponents { - Parameters = new Dictionary + Parameters = new Dictionary { - ["LimitParameter"] = new OpenApiParameter - { - Name = "limit", - In = ParameterLocation.Query, - Description = "Limit the number of pets returned", - Required = false, - Schema = new() - { - Type = JsonSchemaType.Integer, - Format = "int32", - Default = 10 - }, - } + ["LimitParameter"] = parameter } } }; + expected.RegisterComponents(); + expected.SetReferenceHostDocument(); - var expectedSerializedDoc = @"openapi: 3.0.4 + var expectedSerializedDoc = +""" +openapi: 3.0.4 info: title: Pet Store with Referenceable Parameter version: 1.0.0 @@ -1309,7 +1256,8 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() schema: type: integer format: int32 - default: 10"; + default: 10 +"""; using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "minifiedPetStore.yaml")); @@ -1318,10 +1266,14 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() var actualParam = doc.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; var outputDoc = (await doc.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0)).MakeLineBreaksEnvironmentNeutral(); var expectedParam = expected.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; + var expectedParamReference = Assert.IsType(expectedParam); + + var actualParamReference = Assert.IsType(actualParam); // Assert - actualParam.Should().BeEquivalentTo(expectedParam, options => options - .Excluding(x => x.Reference.HostDocument) + actualParamReference.Should().BeEquivalentTo(expectedParamReference, options => options + .Excluding(x => x.Reference) + .Excluding(x => x.Target) .Excluding(x => x.Schema.Default.Parent) .Excluding(x => x.Schema.Default.Options) .IgnoringCyclicReferences()); @@ -1408,12 +1360,16 @@ public async Task ParseDocumentWithEmptyPathsSucceeds() public async Task ParseDocumentWithExampleReferencesPasses() { // Act & Assert: Ensure no NullReferenceException is thrown - Func act = async () => - { - await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "docWithExampleReferences.yaml")); - }; + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "docWithExampleReferences.yaml")); + Assert.Empty(result.Diagnostic.Errors); + } - await act.Should().NotThrowAsync(); + [Fact] + public async Task ParseDocumentWithNonStandardMIMETypePasses() + { + // Act & Assert: Ensure NotSupportedException is not thrown for non-standard MIME type: text/x-yaml + var result = await OpenApiDocument.LoadAsync(codacyApi); + Assert.NotNull(result.Document); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs index 874cf6b04..bee674bfc 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs @@ -49,10 +49,10 @@ public async Task ParseAdvancedEncodingShouldSucceed() Headers = { ["X-Rate-Limit-Limit"] = - new() + new OpenApiHeader() { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs index e3c1435fd..2905266fc 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs @@ -35,7 +35,7 @@ public async Task ParseMediaTypeWithExampleShouldSucceed() new OpenApiMediaType { Example = 5, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -57,16 +57,16 @@ public async Task ParseMediaTypeWithExamplesShouldSucceed() { Examples = { - ["example1"] = new() + ["example1"] = new OpenApiExample() { Value = 5 }, - ["example2"] = new() + ["example2"] = new OpenApiExample() { Value = 7.5 } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs index 22167e0ee..1dd24a128 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs @@ -27,8 +27,7 @@ public async Task OperationWithSecurityRequirementShouldReferenceSecurityScheme( var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "securedOperation.yaml")); var securityScheme = result.Document.Paths["/"].Operations[OperationType.Get].Security[0].Keys.First(); - securityScheme.Should().BeEquivalentTo(result.Document.Components.SecuritySchemes.First().Value, - options => options.Excluding(x => x.Reference)); + Assert.Equivalent(result.Document.Components.SecuritySchemes.First().Value, securityScheme); } [Fact] @@ -56,7 +55,7 @@ public async Task ParseOperationWithParameterWithNoLocationShouldSucceed() Name = "username", Description = "The user name for login", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -67,7 +66,7 @@ public async Task ParseOperationWithParameterWithNoLocationShouldSucceed() Description = "The password for login in clear text", In = ParameterLocation.Query, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs index 8a30fc9ba..efdb87110 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs @@ -9,6 +9,8 @@ using Xunit; using Microsoft.OpenApi.Reader.V3; using System.Threading.Tasks; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; namespace Microsoft.OpenApi.Readers.Tests.V3Tests { @@ -39,7 +41,7 @@ public async Task ParsePathParameterShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -60,10 +62,10 @@ public async Task ParseQueryParameterShouldSucceed() Name = "id", Description = "ID of the object to fetch", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -85,10 +87,10 @@ public async Task ParseQueryParameterWithObjectTypeShouldSucceed() { In = ParameterLocation.Query, Name = "freeForm", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -116,7 +118,7 @@ public async Task ParseQueryParameterWithObjectTypeAndContentShouldSucceed() { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = @@ -126,11 +128,11 @@ public async Task ParseQueryParameterWithObjectTypeAndContentShouldSucceed() }, Properties = { - ["lat"] = new() + ["lat"] = new OpenApiSchema() { Type = JsonSchemaType.Number }, - ["long"] = new() + ["long"] = new OpenApiSchema() { Type = JsonSchemaType.Number } @@ -157,10 +159,10 @@ public async Task ParseHeaderParameterShouldSucceed() Required = true, Style = ParameterStyle.Simple, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64", @@ -183,7 +185,7 @@ public async Task ParseParameterWithNullLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -207,7 +209,7 @@ public async Task ParseParameterWithNoLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -231,7 +233,7 @@ public async Task ParseParameterWithUnknownLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -253,7 +255,7 @@ public async Task ParseParameterWithExampleShouldSucceed() Description = "username to fetch", Required = true, Example = (float)5.0, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -277,16 +279,16 @@ public async Task ParseParameterWithExamplesShouldSucceed() Required = true, Examples = { - ["example1"] = new() + ["example1"] = new OpenApiExample() { Value = 5.0 }, - ["example2"] = new() + ["example2"] = new OpenApiExample() { Value = (float) 7.5 } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -300,6 +302,21 @@ public async Task ParseParameterWithExamplesShouldSucceed() public void ParseParameterWithReferenceWorks() { // Arrange + var parameter = new OpenApiParameter + { + Name = "tags", + In = ParameterLocation.Query, + Description = "tags to filter by", + Required = false, + Schema = new OpenApiSchema() + { + Type = JsonSchemaType.Array, + Items = new OpenApiSchema + { + Type = JsonSchemaType.String + } + } + }; var document = new OpenApiDocument { Info = new OpenApiInfo @@ -324,44 +341,19 @@ public void ParseParameterWithReferenceWorks() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { - new() { - Reference = new OpenApiReference - { - Type = ReferenceType.Parameter, - Id = "tagsParameter" - } - } - }, + Parameters = + [ + new OpenApiParameterReference("tagsParameter"), + ], } } } }, Components = new OpenApiComponents { - Parameters = new Dictionary() + Parameters = new Dictionary() { - ["tagsParameter"] = new OpenApiParameter - { - Name = "tags", - In = ParameterLocation.Query, - Description = "tags to filter by", - Required = false, - Schema = new() - { - Type = JsonSchemaType.Array, - Items = new OpenApiSchema - { - Type = JsonSchemaType.String - } - }, - Reference = new OpenApiReference - { - Type = ReferenceType.Parameter, - Id = "tagsParameter" - } - } + ["tagsParameter"] = parameter, } } }; @@ -377,7 +369,7 @@ public void ParseParameterWithReferenceWorks() var param = OpenApiV3Deserializer.LoadParameter(node, document); // Assert - param.Should().BeEquivalentTo(expected, options => options.Excluding(p => p.Reference.HostDocument)); + Assert.Equivalent(expected, param); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs index 8d94822ef..2fd230a19 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs @@ -165,7 +165,7 @@ public void ParseDictionarySchemaShouldSucceed() new OpenApiSchema { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -199,12 +199,12 @@ public void ParseBasicSchemaWithExampleShouldSucceed() Type = JsonSchemaType.Object, Properties = { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -245,18 +245,18 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() { Schemas = { - ["ErrorModel"] = new() + ["ErrorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Minimum = 100, Maximum = 600 }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -267,7 +267,7 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() "code" } }, - ["ExtendedErrorModel"] = new() + ["ExtendedErrorModel"] = new OpenApiSchema() { AllOf = { @@ -278,7 +278,7 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() Required = {"rootCause"}, Properties = { - ["rootCause"] = new() + ["rootCause"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -302,7 +302,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() { Schemas = { - ["Pet"] = new() + ["Pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Discriminator = new() @@ -311,11 +311,11 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() }, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["petType"] = new() + ["petType"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -326,7 +326,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() "petType" } }, - ["Cat"] = new() + ["Cat"] = new OpenApiSchema() { Description = "A representation of a cat", AllOf = @@ -338,7 +338,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() Required = {"huntingSkill"}, Properties = { - ["huntingSkill"] = new() + ["huntingSkill"] = new OpenApiSchema() { Type = JsonSchemaType.String, Description = "The measured skill for hunting", @@ -354,7 +354,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() } } }, - ["Dog"] = new() + ["Dog"] = new OpenApiSchema() { Description = "A representation of a dog", AllOf = @@ -366,7 +366,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() Required = {"packSize"}, Properties = { - ["packSize"] = new() + ["packSize"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32", diff --git a/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs b/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs index c41bd6e98..dead3b27c 100644 --- a/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs +++ b/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs @@ -15,45 +15,45 @@ public class OpenApiTypeMapperTests { new object[] { typeof(int), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32" } }, new object[] { typeof(decimal), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double" } }, - new object[] { typeof(decimal?), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double", Nullable = true } }, - new object[] { typeof(bool?), new OpenApiSchema { Type = JsonSchemaType.Boolean, Nullable = true } }, + new object[] { typeof(decimal?), new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" } }, + new object[] { typeof(bool?), new OpenApiSchema { Type = JsonSchemaType.Boolean | JsonSchemaType.Null } }, new object[] { typeof(Guid), new OpenApiSchema { Type = JsonSchemaType.String, Format = "uuid" } }, - new object[] { typeof(Guid?), new OpenApiSchema { Type = JsonSchemaType.String, Format = "uuid", Nullable = true } }, + new object[] { typeof(Guid?), new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "uuid" } }, new object[] { typeof(uint), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32" } }, new object[] { typeof(long), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64" } }, - new object[] { typeof(long?), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true } }, + new object[] { typeof(long?), new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int64" } }, new object[] { typeof(ulong), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64" } }, new object[] { typeof(string), new OpenApiSchema { Type = JsonSchemaType.String } }, new object[] { typeof(double), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double" } }, - new object[] { typeof(float?), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "float", Nullable = true } }, - new object[] { typeof(byte?), new OpenApiSchema { Type = JsonSchemaType.String, Format = "byte", Nullable = true } }, - new object[] { typeof(int?), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true } }, - new object[] { typeof(uint?), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true } }, - new object[] { typeof(DateTimeOffset?), new OpenApiSchema { Type = JsonSchemaType.String, Format = "date-time", Nullable = true } }, - new object[] { typeof(double?), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double", Nullable = true } }, - new object[] { typeof(char?), new OpenApiSchema { Type = JsonSchemaType.String, Nullable = true } }, + new object[] { typeof(float?), new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "float" } }, + new object[] { typeof(byte?), new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "byte" } }, + new object[] { typeof(int?), new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32" } }, + new object[] { typeof(uint?), new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32" } }, + new object[] { typeof(DateTimeOffset?), new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "date-time" } }, + new object[] { typeof(double?), new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" } }, + new object[] { typeof(char?), new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null } }, new object[] { typeof(DateTimeOffset), new OpenApiSchema { Type = JsonSchemaType.String, Format = "date-time" } } }; public static IEnumerable OpenApiDataTypes => new List { - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32", Nullable = false}, typeof(int) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true}, typeof(int?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64", Nullable = false}, typeof(long) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true}, typeof(long?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32" }, typeof(int) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32"}, typeof(int?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64" }, typeof(long) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int64"}, typeof(long?) }, new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "decimal"}, typeof(decimal) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = null, Nullable = false}, typeof(long) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = null, Nullable = true}, typeof(long?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = null, Nullable = false}, typeof(double) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = null, Nullable = true}, typeof(double?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "decimal", Nullable = true}, typeof(decimal?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double", Nullable = true}, typeof(double?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.String, Format = "date-time", Nullable = true}, typeof(DateTimeOffset?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.String, Format = "char", Nullable = true}, typeof(char?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.String, Format = "uuid", Nullable = true}, typeof(Guid?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = null }, typeof(long) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = null}, typeof(long?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = null }, typeof(double) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = null}, typeof(double?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "decimal"}, typeof(decimal?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double"}, typeof(double?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "date-time"}, typeof(DateTimeOffset?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "char"}, typeof(char?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "uuid"}, typeof(Guid?) }, new object[] { new OpenApiSchema { Type = JsonSchemaType.String }, typeof(string) }, new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double" }, typeof(double) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "float", Nullable = true }, typeof(float?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "float" }, typeof(float?) }, new object[] { new OpenApiSchema { Type = JsonSchemaType.String, Format = "date-time" }, typeof(DateTimeOffset) } }; diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index f8f8930e2..f87992246 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs index 8c729b7c4..fc232fa3a 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs @@ -16,25 +16,25 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiCallbackTests { - public static OpenApiCallback AdvancedCallback = new() + private static OpenApiCallback AdvancedCallback => new() { PathItems = { [RuntimeExpression.Build("$request.body#/url")] - = new() + = new OpenApiPathItem() { Operations = { [OperationType.Post] = new() { - RequestBody = new() + RequestBody = new OpenApiRequestBody() { Content = { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -43,7 +43,7 @@ public class OpenApiCallbackTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Success" } @@ -54,27 +54,27 @@ public class OpenApiCallbackTests } }; - public static OpenApiCallbackReference CallbackProxy = new(ReferencedCallback, "simpleHook"); + private static OpenApiCallbackReference CallbackProxy => new("simpleHook"); - public static OpenApiCallback ReferencedCallback = new() + private static OpenApiCallback ReferencedCallback => new() { PathItems = { [RuntimeExpression.Build("$request.body#/url")] - = new() + = new OpenApiPathItem() { Operations = { [OperationType.Post] = new() { - RequestBody = new() + RequestBody = new OpenApiRequestBody() { Content = { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -83,7 +83,7 @@ public class OpenApiCallbackTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Success" } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs index 738002b1e..379dc0c4f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Xunit; @@ -15,17 +16,17 @@ public class OpenApiComponentsTests { public static OpenApiComponents AdvancedComponents = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 @@ -33,9 +34,9 @@ public class OpenApiComponentsTests } } }, - SecuritySchemes = new Dictionary + SecuritySchemes = new Dictionary { - ["securityScheme1"] = new() + ["securityScheme1"] = new OpenApiSecurityScheme() { Description = "description1", Type = SecuritySchemeType.OAuth2, @@ -52,7 +53,7 @@ public class OpenApiComponentsTests } } }, - ["securityScheme2"] = new() + ["securityScheme2"] = new OpenApiSecurityScheme() { Description = "description1", Type = SecuritySchemeType.OpenIdConnect, @@ -64,33 +65,33 @@ public class OpenApiComponentsTests public static OpenApiComponents AdvancedComponentsWithReference = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, ["property3"] = new OpenApiSchemaReference("schema2", null) } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer } } }, }, - SecuritySchemes = new Dictionary + SecuritySchemes = new Dictionary { - ["securityScheme1"] = new() + ["securityScheme1"] = new OpenApiSecurityScheme() { Description = "description1", Type = SecuritySchemeType.OAuth2, @@ -106,23 +107,13 @@ public class OpenApiComponentsTests AuthorizationUrl = new("https://example.com/api/oauth") } }, - Reference = new() - { - Type = ReferenceType.SecurityScheme, - Id = "securityScheme1" - } }, - ["securityScheme2"] = new() + ["securityScheme2"] = new OpenApiSecurityScheme() { Description = "description1", Type = SecuritySchemeType.OpenIdConnect, Scheme = OpenApiConstants.Bearer, OpenIdConnectUrl = new("https://example.com/openIdConnect"), - Reference = new() - { - Type = ReferenceType.SecurityScheme, - Id = "securityScheme2" - } } } }; @@ -131,22 +122,22 @@ public class OpenApiComponentsTests public static OpenApiComponents BrokenComponents = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.String }, ["schema2"] = null, ["schema3"] = null, - ["schema4"] = new() + ["schema4"] = new OpenApiSchema() { Type = JsonSchemaType.String, - AllOf = new List + AllOf = new List { null, null, - new() + new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -162,12 +153,12 @@ public class OpenApiComponentsTests Schemas = { ["schema1"] = new OpenApiSchemaReference("schema2", null), - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -180,23 +171,23 @@ public class OpenApiComponentsTests { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -215,11 +206,11 @@ public class OpenApiComponentsTests public static OpenApiComponents ComponentsWithPathItem = new OpenApiComponents { - Schemas = new Dictionary() + Schemas = new Dictionary() { ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["property2"] = new OpenApiSchema() { @@ -229,9 +220,9 @@ public class OpenApiComponentsTests } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["property2"] = new OpenApiSchema() { @@ -240,7 +231,7 @@ public class OpenApiComponentsTests } } }, - PathItems = new Dictionary + PathItems = new Dictionary { ["/pets"] = new OpenApiPathItem { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt index c63fb3250..5d9d7f3da 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt @@ -30,7 +30,6 @@ "name": "tags", "in": "query", "description": "tags to filter by", - "style": "form", "schema": { "type": "array", "items": { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt index f7d8a3f47..5fd0d1e26 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"openapi":"3.0.4","info":{"title":"Swagger Petstore (Simple)","description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification","termsOfService":"http://helloreverb.com/terms/","contact":{"name":"Swagger API team","url":"http://swagger.io","email":"foo@example.com"},"license":{"name":"MIT","url":"http://opensource.org/licenses/MIT"},"version":"1.0.0"},"servers":[{"url":"http://petstore.swagger.io/api"}],"paths":{"/pets":{"get":{"description":"Returns all pets from the system that the user has access to","operationId":"findPets","parameters":[{"name":"tags","in":"query","description":"tags to filter by","style":"form","schema":{"type":"array","items":{"type":"string"}}},{"name":"limit","in":"query","description":"maximum number of results to return","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"type":"array","items":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"application/xml":{"schema":{"type":"array","items":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}},"post":{"description":"Creates a new pet in the store. Duplicates are allowed","operationId":"addPet","requestBody":{"description":"Pet to add to the store","content":{"application/json":{"schema":{"required":["name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"required":true},"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}}},"/pets/{id}":{"get":{"description":"Returns a user based on a single ID, if the user does not have access to the pet","operationId":"findPetById","parameters":[{"name":"id","in":"path","description":"ID of pet to fetch","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}},"application/xml":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}},"delete":{"description":"deletes a single pet based on the ID supplied","operationId":"deletePet","parameters":[{"name":"id","in":"path","description":"ID of pet to delete","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"204":{"description":"pet deleted"},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}}}},"components":{"schemas":{"pet":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}},"newPet":{"required":["name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}},"errorModel":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}} +{"openapi":"3.0.4","info":{"title":"Swagger Petstore (Simple)","description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification","termsOfService":"http://helloreverb.com/terms/","contact":{"name":"Swagger API team","url":"http://swagger.io","email":"foo@example.com"},"license":{"name":"MIT","url":"http://opensource.org/licenses/MIT"},"version":"1.0.0"},"servers":[{"url":"http://petstore.swagger.io/api"}],"paths":{"/pets":{"get":{"description":"Returns all pets from the system that the user has access to","operationId":"findPets","parameters":[{"name":"tags","in":"query","description":"tags to filter by","schema":{"type":"array","items":{"type":"string"}}},{"name":"limit","in":"query","description":"maximum number of results to return","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"type":"array","items":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"application/xml":{"schema":{"type":"array","items":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}},"post":{"description":"Creates a new pet in the store. Duplicates are allowed","operationId":"addPet","requestBody":{"description":"Pet to add to the store","content":{"application/json":{"schema":{"required":["name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"required":true},"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}}},"/pets/{id}":{"get":{"description":"Returns a user based on a single ID, if the user does not have access to the pet","operationId":"findPetById","parameters":[{"name":"id","in":"path","description":"ID of pet to fetch","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}},"application/xml":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}},"delete":{"description":"deletes a single pet based on the ID supplied","operationId":"deletePet","parameters":[{"name":"id","in":"path","description":"ID of pet to delete","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"204":{"description":"pet deleted"},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}}}},"components":{"schemas":{"pet":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}},"newPet":{"required":["name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}},"errorModel":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 752ec7d9f..3716a0b32 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -10,6 +10,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Readers; @@ -33,12 +34,12 @@ public OpenApiDocumentTests() Schemas = { ["schema1"] = new OpenApiSchemaReference("schema2", null), - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String, Annotations = new Dictionary { { "key1", "value" } } @@ -52,30 +53,25 @@ public OpenApiDocumentTests() { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String, Annotations = new Dictionary { { "key1", "value" } } } }, Annotations = new Dictionary { { "key1", "value" } }, - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schema1" - } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -89,13 +85,8 @@ public OpenApiDocumentTests() { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schema1" - } } } }; @@ -132,9 +123,9 @@ public OpenApiDocumentTests() public static readonly OpenApiComponents AdvancedComponentsWithReference = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet"] = new() + ["pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -142,48 +133,48 @@ public OpenApiDocumentTests() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -191,14 +182,14 @@ public OpenApiDocumentTests() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -207,12 +198,12 @@ public OpenApiDocumentTests() } }; - public static OpenApiSchema PetSchemaWithReference = AdvancedComponentsWithReference.Schemas["pet"]; + public static OpenApiSchema PetSchemaWithReference = AdvancedComponentsWithReference.Schemas["pet"] as OpenApiSchema; - public static OpenApiSchema NewPetSchemaWithReference = AdvancedComponentsWithReference.Schemas["newPet"]; + public static OpenApiSchema NewPetSchemaWithReference = AdvancedComponentsWithReference.Schemas["newPet"] as OpenApiSchema; public static OpenApiSchema ErrorModelSchemaWithReference = - AdvancedComponentsWithReference.Schemas["errorModel"]; + AdvancedComponentsWithReference.Schemas["errorModel"] as OpenApiSchema; public static readonly OpenApiDocument AdvancedDocumentWithReference = new OpenApiDocument { @@ -252,18 +243,18 @@ public OpenApiDocumentTests() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -275,13 +266,13 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -291,7 +282,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchemaWithReference @@ -299,7 +290,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchemaWithReference @@ -395,21 +386,21 @@ public OpenApiDocumentTests() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -455,21 +446,21 @@ public OpenApiDocumentTests() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["204"] = new OpenApiResponse @@ -509,9 +500,9 @@ public OpenApiDocumentTests() public static readonly OpenApiComponents AdvancedComponents = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet"] = new() + ["pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -519,48 +510,48 @@ public OpenApiDocumentTests() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -568,14 +559,14 @@ public OpenApiDocumentTests() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -584,11 +575,11 @@ public OpenApiDocumentTests() } }; - public static readonly OpenApiSchema PetSchema = AdvancedComponents.Schemas["pet"]; + public static readonly OpenApiSchema PetSchema = AdvancedComponents.Schemas["pet"] as OpenApiSchema; - public static readonly OpenApiSchema NewPetSchema = AdvancedComponents.Schemas["newPet"]; + public static readonly OpenApiSchema NewPetSchema = AdvancedComponents.Schemas["newPet"] as OpenApiSchema; - public static readonly OpenApiSchema ErrorModelSchema = AdvancedComponents.Schemas["errorModel"]; + public static readonly OpenApiSchema ErrorModelSchema = AdvancedComponents.Schemas["errorModel"] as OpenApiSchema; public OpenApiDocument AdvancedDocument = new OpenApiDocument { @@ -628,7 +619,7 @@ public OpenApiDocumentTests() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List + Parameters = new List { new OpenApiParameter { @@ -636,10 +627,10 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -651,7 +642,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -667,7 +658,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -675,7 +666,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -771,7 +762,7 @@ public OpenApiDocumentTests() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List + Parameters = new List { new OpenApiParameter { @@ -779,7 +770,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -831,7 +822,7 @@ public OpenApiDocumentTests() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List + Parameters = new List { new OpenApiParameter { @@ -839,7 +830,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -890,7 +881,7 @@ public OpenApiDocumentTests() Title = "Webhook Example", Version = "1.0.0" }, - Webhooks = new Dictionary + Webhooks = new Dictionary { ["newPet"] = new OpenApiPathItem { @@ -922,7 +913,7 @@ public OpenApiDocumentTests() }, Components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { ["Pet"] = new OpenApiSchema() { @@ -930,18 +921,18 @@ public OpenApiDocumentTests() { "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -975,7 +966,7 @@ public OpenApiDocumentTests() [OperationType.Get] = new OpenApiOperation { OperationId = "addByOperand1AndByOperand2", - Parameters = new List + Parameters = new List { new OpenApiParameter { @@ -983,7 +974,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "The first operand", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Extensions = new Dictionary @@ -1002,7 +993,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "The second operand", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Extensions = new Dictionary @@ -1025,7 +1016,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1079,7 +1070,7 @@ public OpenApiDocumentTests() }, Paths = new() { - ["/pets"] = new() + ["/pets"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -1087,30 +1078,30 @@ public OpenApiDocumentTests() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "tags", In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } } }, - new() + new OpenApiParameter() { Name = "limit", In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -1119,14 +1110,14 @@ public OpenApiDocumentTests() }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "pet response", Content = new Dictionary { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1134,7 +1125,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1142,7 +1133,7 @@ public OpenApiDocumentTests() } } }, - ["4XX"] = new() + ["4XX"] = new OpenApiResponse() { Description = "unexpected client error", Content = new Dictionary @@ -1153,7 +1144,7 @@ public OpenApiDocumentTests() } } }, - ["5XX"] = new() + ["5XX"] = new OpenApiResponse() { Description = "unexpected server error", Content = new Dictionary @@ -1170,7 +1161,7 @@ public OpenApiDocumentTests() { Description = "Creates a new pet in the store. Duplicates are allowed", OperationId = "addPet", - RequestBody = new() + RequestBody = new OpenApiRequestBody() { Description = "Pet to add to the store", Required = true, @@ -1184,7 +1175,7 @@ public OpenApiDocumentTests() }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "pet response", Content = new Dictionary @@ -1195,7 +1186,7 @@ public OpenApiDocumentTests() }, } }, - ["4XX"] = new() + ["4XX"] = new OpenApiResponse() { Description = "unexpected client error", Content = new Dictionary @@ -1206,7 +1197,7 @@ public OpenApiDocumentTests() } } }, - ["5XX"] = new() + ["5XX"] = new OpenApiResponse() { Description = "unexpected server error", Content = new Dictionary @@ -1221,7 +1212,7 @@ public OpenApiDocumentTests() } } }, - ["/pets/{id}"] = new() + ["/pets/{id}"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -1230,15 +1221,15 @@ public OpenApiDocumentTests() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -1247,7 +1238,7 @@ public OpenApiDocumentTests() }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "pet response", Content = new Dictionary @@ -1262,7 +1253,7 @@ public OpenApiDocumentTests() } } }, - ["4XX"] = new() + ["4XX"] = new OpenApiResponse() { Description = "unexpected client error", Content = new Dictionary @@ -1273,7 +1264,7 @@ public OpenApiDocumentTests() } } }, - ["5XX"] = new() + ["5XX"] = new OpenApiResponse() { Description = "unexpected server error", Content = new Dictionary @@ -1290,15 +1281,15 @@ public OpenApiDocumentTests() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "id", In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -1307,11 +1298,11 @@ public OpenApiDocumentTests() }, Responses = new() { - ["204"] = new() + ["204"] = new OpenApiResponse() { Description = "pet deleted" }, - ["4XX"] = new() + ["4XX"] = new OpenApiResponse() { Description = "unexpected client error", Content = new Dictionary @@ -1322,7 +1313,7 @@ public OpenApiDocumentTests() } } }, - ["5XX"] = new() + ["5XX"] = new OpenApiResponse() { Description = "unexpected server error", Content = new Dictionary @@ -1560,14 +1551,6 @@ public async Task SerializeDocumentWithReferenceButNoComponents() { ["application/json"] = new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Id = "test", - Type = ReferenceType.Schema - } - } } } } @@ -1577,6 +1560,7 @@ public async Task SerializeDocumentWithReferenceButNoComponents() } } }; + document.Paths["/"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema = new OpenApiSchemaReference("test", document); // Act var actual = await document.SerializeAsync(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json); @@ -1732,17 +1716,17 @@ public async Task SerializeV2DocumentWithNonArraySchemaTypeDoesNotWriteOutCollec { [OperationType.Get] = new OpenApiOperation { - Parameters = new List - { + Parameters = + [ new OpenApiParameter { In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } } - }, + ], Responses = new OpenApiResponses() } } @@ -1799,22 +1783,22 @@ public async Task SerializeV2DocumentWithStyleAsNullDoesNotWriteOutStyleValue() { [OperationType.Get] = new OpenApiOperation { - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -1824,7 +1808,7 @@ public async Task SerializeV2DocumentWithStyleAsNullDoesNotWriteOutStyleValue() { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiExampleTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiExampleTests.cs index d1e2cd8f5..fd59b4250 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiExampleTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiExampleTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiExampleTests { - public static OpenApiExample AdvancedExample = new() + private static OpenApiExample AdvancedExample => new() { Value = new JsonObject { @@ -57,8 +57,8 @@ public class OpenApiExampleTests } }; - public static OpenApiExampleReference OpenApiExampleReference = new(ReferencedExample, "example1"); - public static OpenApiExample ReferencedExample = new() + private static OpenApiExampleReference OpenApiExampleReference => new("example1"); + private static OpenApiExample ReferencedExample => new() { Value = new JsonObject { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs index e368c587b..afda460f7 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs @@ -15,22 +15,22 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiHeaderTests { - public static OpenApiHeader AdvancedHeader = new() + private static OpenApiHeader AdvancedHeader => new() { Description = "sampleHeader", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" } }; - public static OpenApiHeaderReference OpenApiHeaderReference = new(ReferencedHeader, "example1"); + private static OpenApiHeaderReference OpenApiHeaderReference => new("example1"); - public static OpenApiHeader ReferencedHeader = new() + private static OpenApiHeader ReferencedHeader => new() { Description = "sampleHeader", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiLinkTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiLinkTests.cs index e1a949348..a6b4bc500 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiLinkTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiLinkTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiLinkTests { - public static readonly OpenApiLink AdvancedLink = new() + private static OpenApiLink AdvancedLink => new() { OperationId = "operationId1", Parameters = @@ -42,14 +42,9 @@ public class OpenApiLinkTests } }; - public static readonly OpenApiLinkReference LinkReference = new(ReferencedLink, "example1"); - public static readonly OpenApiLink ReferencedLink = new() + private static OpenApiLinkReference LinkReference => new("example1"); + private static OpenApiLink ReferencedLink => new() { - Reference = new() - { - Type = ReferenceType.Link, - Id = "example1", - }, OperationId = "operationId1", Parameters = { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiMediaTypeTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiMediaTypeTests.cs index b1f6ca474..ef1ebb420 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiMediaTypeTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiMediaTypeTests.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Xunit; using Xunit.Abstractions; @@ -79,7 +80,7 @@ public class OpenApiMediaTypeTests public static OpenApiMediaType MediaTypeWithObjectExamples = new() { Examples = { - ["object1"] = new() + ["object1"] = new OpenApiExample() { Value = new JsonObject { @@ -433,7 +434,7 @@ public void MediaTypeCopyConstructorWorks() var clone = new OpenApiMediaType(MediaTypeWithObjectExamples) { Example = 42, - Examples = new Dictionary(), + Examples = new Dictionary(), Encoding = new Dictionary(), Extensions = new Dictionary() }; diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs index 1b0b27ada..af22284b9 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs @@ -2,9 +2,11 @@ // Licensed under the MIT license. using System.Collections.Generic; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Xunit; @@ -25,20 +27,20 @@ public class OpenApiOperationTests Url = new("http://external.com") }, OperationId = "operationId1", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { In = ParameterLocation.Path, Name = "parameter1", }, - new() + new OpenApiParameter() { In = ParameterLocation.Header, Name = "parameter2" } - }, - RequestBody = new() + ], + RequestBody = new OpenApiRequestBody() { Description = "description2", Required = true, @@ -46,7 +48,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -57,14 +59,14 @@ public class OpenApiOperationTests }, Responses = new() { - ["200"] = new OpenApiResponseReference("response1", hostDocument: null), - ["400"] = new() + ["200"] = new OpenApiResponseReference("response1"), + ["400"] = new OpenApiResponse() { Content = new Dictionary { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -85,7 +87,7 @@ public class OpenApiOperationTests Annotations = new Dictionary { { "key1", "value1" }, { "key2", 2 } }, }; - private static readonly OpenApiOperation _advancedOperationWithTagsAndSecurity = new() + private static OpenApiOperation _advancedOperationWithTagsAndSecurity => new() { Tags = new List { @@ -99,20 +101,20 @@ public class OpenApiOperationTests Url = new("http://external.com") }, OperationId = "operationId1", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { In = ParameterLocation.Path, Name = "parameter1" }, - new() + new OpenApiParameter() { In = ParameterLocation.Header, Name = "parameter2" } - }, - RequestBody = new() + ], + RequestBody = new OpenApiRequestBody() { Description = "description2", Required = true, @@ -120,7 +122,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -131,14 +133,14 @@ public class OpenApiOperationTests }, Responses = new() { - ["200"] = new OpenApiResponseReference("response1", hostDocument: null), - ["400"] = new() + ["200"] = new OpenApiResponseReference("response1"), + ["400"] = new OpenApiResponse() { Content = new Dictionary { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -152,8 +154,8 @@ public class OpenApiOperationTests { new() { - [new OpenApiSecuritySchemeReference("securitySchemeId1", hostDocument: null)] = new List(), - [new OpenApiSecuritySchemeReference("securitySchemeId2", hostDocument: null)] = new List + [new OpenApiSecuritySchemeReference("securitySchemeId1", __advancedOperationWithTagsAndSecurity_supportingDocument)] = new List(), + [new OpenApiSecuritySchemeReference("securitySchemeId2", __advancedOperationWithTagsAndSecurity_supportingDocument)] = new List { "scopeName1", "scopeName2" @@ -169,6 +171,34 @@ public class OpenApiOperationTests } } }; + private static OpenApiDocument __advancedOperationWithTagsAndSecurity_supportingDocument + { + get + { + var document = new OpenApiDocument() + { + Components = new() + { + SecuritySchemes = new Dictionary + { + ["securitySchemeId1"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.ApiKey, + Name = "apiKeyName1", + In = ParameterLocation.Header, + }, + ["securitySchemeId2"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OpenIdConnect, + OpenIdConnectUrl = new("http://example.com"), + } + } + } + }; + document.RegisterComponents(); + return document; + } + } private static readonly OpenApiOperation _operationWithFormData = new() @@ -176,36 +206,36 @@ public class OpenApiOperationTests Summary = "Updates a pet in the store with form data", Description = "", OperationId = "updatePetWithForm", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "petId", In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } } - }, - RequestBody = new() + ], + RequestBody = new OpenApiRequestBody() { Content = { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -219,16 +249,16 @@ public class OpenApiOperationTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -244,11 +274,11 @@ public class OpenApiOperationTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Pet updated." }, - ["405"] = new() + ["405"] = new OpenApiResponse() { Description = "Invalid input" } @@ -426,9 +456,7 @@ public async Task SerializeAdvancedOperationWithTagAndSecurityAsV3JsonWorks() var actual = await _advancedOperationWithTagsAndSecurity.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -446,9 +474,7 @@ public async Task SerializeBasicOperationAsV2JsonWorks() var actual = await _basicOperation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -525,9 +551,7 @@ public async Task SerializeOperationWithFormDataAsV3JsonWorks() var actual = await _operationWithFormData.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -581,9 +605,7 @@ public async Task SerializeOperationWithFormDataAsV2JsonWorks() var actual = await _operationWithFormData.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -650,9 +672,7 @@ public async Task SerializeOperationWithBodyAsV2JsonWorks() var actual = await _operationWithBody.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -731,9 +751,7 @@ public async Task SerializeAdvancedOperationWithTagAndSecurityAsV2JsonWorks() var actual = await _advancedOperationWithTagsAndSecurity.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -756,9 +774,7 @@ public async Task SerializeOperationWithNullCollectionAsV2JsonWorks() var actual = await operation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=False.verified.txt index 5d3060ec5..d450bda88 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=False.verified.txt @@ -2,7 +2,6 @@ "name": "name1", "in": "query", "description": "description1", - "style": "form", "explode": false, "schema": { "type": "array", diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=True.verified.txt index a4b87db10..33a58c93f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"name":"name1","in":"query","description":"description1","style":"form","explode":false,"schema":{"type":"array","items":{"enum":["value1","value2"]}}} \ No newline at end of file +{"name":"name1","in":"query","description":"description1","explode":false,"schema":{"type":"array","items":{"enum":["value1","value2"]}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=False.verified.txt index 36a9c0168..56944b8db 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=False.verified.txt @@ -2,7 +2,6 @@ "name": "name1", "in": "query", "description": "description1", - "style": "form", "schema": { "type": "array", "items": { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=True.verified.txt index 206902b7b..b9e1ee95f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"name":"name1","in":"query","description":"description1","style":"form","schema":{"type":"array","items":{"enum":["value1","value2"]}}} \ No newline at end of file +{"name":"name1","in":"query","description":"description1","schema":{"type":"array","items":{"enum":["value1","value2"]}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs index 1c2e3329f..da0c00d44 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using VerifyXunit; @@ -18,20 +19,20 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiParameterTests { - public static OpenApiParameter BasicParameter = new() + private static OpenApiParameter BasicParameter => new() { Name = "name1", In = ParameterLocation.Path }; - public static OpenApiParameterReference OpenApiParameterReference = new(ReferencedParameter, "example1"); - public static OpenApiParameter ReferencedParameter = new() + private static OpenApiParameterReference OpenApiParameterReference => new("example1"); + private static OpenApiParameter ReferencedParameter => new() { Name = "name1", In = ParameterLocation.Path }; - public static OpenApiParameter AdvancedPathParameterWithSchema = new() + private static OpenApiParameter AdvancedPathParameterWithSchema => new() { Name = "name1", In = ParameterLocation.Path, @@ -40,19 +41,19 @@ public class OpenApiParameterTests Deprecated = false, Style = ParameterStyle.Simple, Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Title = "title2", Description = "description2", - OneOf = new List + OneOf = new List { - new() { Type = JsonSchemaType.Number, Format = "double" }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "double" }, + new OpenApiSchema() { Type = JsonSchemaType.String } } }, - Examples = new Dictionary + Examples = { - ["test"] = new() + ["test"] = new OpenApiExample() { Summary = "summary3", Description = "description3" @@ -60,17 +61,17 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter ParameterWithFormStyleAndExplodeFalse = new() + private static OpenApiParameter ParameterWithFormStyleAndExplodeFalse => new() { Name = "name1", In = ParameterLocation.Query, Description = "description1", Style = ParameterStyle.Form, Explode = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Enum = { @@ -81,17 +82,17 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter ParameterWithFormStyleAndExplodeTrue = new() + private static OpenApiParameter ParameterWithFormStyleAndExplodeTrue => new() { Name = "name1", In = ParameterLocation.Query, Description = "description1", Style = ParameterStyle.Form, Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Enum = [ @@ -102,11 +103,11 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter QueryParameterWithMissingStyle = new OpenApiParameter + private static OpenApiParameter QueryParameterWithMissingStyle => new OpenApiParameter { Name = "id", In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, AdditionalProperties = new OpenApiSchema @@ -116,7 +117,7 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter AdvancedHeaderParameterWithSchemaReference = new OpenApiParameter + private static OpenApiParameter AdvancedHeaderParameterWithSchemaTypeObject => new() { Name = "name1", In = ParameterLocation.Header, @@ -126,42 +127,13 @@ public class OpenApiParameterTests Style = ParameterStyle.Simple, Explode = true, - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schemaObject1" - }, - UnresolvedReference = true - }, - Examples = new Dictionary - { - ["test"] = new() - { - Summary = "summary3", - Description = "description3" - } - } - }; - - public static OpenApiParameter AdvancedHeaderParameterWithSchemaTypeObject = new() - { - Name = "name1", - In = ParameterLocation.Header, - Description = "description1", - Required = true, - Deprecated = false, - - Style = ParameterStyle.Simple, - Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object }, - Examples = new Dictionary + Examples = { - ["test"] = new() + ["test"] = new OpenApiExample() { Summary = "summary3", Description = "description3" @@ -260,7 +232,6 @@ public async Task SerializeAdvancedParameterAsV3JsonWorks() "in": "path", "description": "description1", "required": true, - "style": "simple", "explode": true, "schema": { "title": "title2", diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs index f391ef4d8..863ce5145 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs @@ -15,7 +15,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiRequestBodyTests { - public static OpenApiRequestBody AdvancedRequestBody = new() + private static OpenApiRequestBody AdvancedRequestBody => new() { Description = "description", Required = true, @@ -23,7 +23,7 @@ public class OpenApiRequestBodyTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -31,8 +31,8 @@ public class OpenApiRequestBodyTests } }; - public static OpenApiRequestBodyReference OpenApiRequestBodyReference = new(ReferencedRequestBody, "example1"); - public static OpenApiRequestBody ReferencedRequestBody = new() + private static OpenApiRequestBodyReference OpenApiRequestBodyReference => new("example1"); + private static OpenApiRequestBody ReferencedRequestBody => new() { Description = "description", Required = true, @@ -40,7 +40,7 @@ public class OpenApiRequestBodyTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs index 14d14e4be..7d077b540 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs @@ -20,16 +20,16 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiResponseTests { - public static OpenApiResponse BasicResponse = new OpenApiResponse(); + private static OpenApiResponse BasicResponse => new OpenApiResponse(); - public static OpenApiResponse AdvancedV2Response = new OpenApiResponse + private static OpenApiResponse AdvancedV2Response => new OpenApiResponse { Description = "A complex object array response", Content = { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -46,7 +46,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -54,21 +54,21 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } }, } }; - public static OpenApiResponse AdvancedV3Response = new OpenApiResponse + private static OpenApiResponse AdvancedV3Response => new OpenApiResponse { Description = "A complex object array response", Content = { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -85,7 +85,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -93,7 +93,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -101,15 +101,15 @@ public class OpenApiResponseTests } }; - public static OpenApiResponseReference V2OpenApiResponseReference = new OpenApiResponseReference("example1", ReferencedV2Response); - public static OpenApiResponse ReferencedV2Response = new OpenApiResponse + private static OpenApiResponseReference V2OpenApiResponseReference => new OpenApiResponseReference("example1"); + private static OpenApiResponse ReferencedV2Response => new OpenApiResponse { Description = "A complex object array response", Content = { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -121,7 +121,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -129,23 +129,23 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } }, } }; - public static OpenApiResponseReference V3OpenApiResponseReference = new OpenApiResponseReference("example1", ReferencedV3Response); + private static OpenApiResponseReference V3OpenApiResponseReference => new OpenApiResponseReference("example1"); - public static OpenApiResponse ReferencedV3Response = new OpenApiResponse + private static OpenApiResponse ReferencedV3Response => new OpenApiResponse { Description = "A complex object array response", Content = { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -157,7 +157,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -165,7 +165,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -173,13 +173,6 @@ public class OpenApiResponseTests } }; - private readonly ITestOutputHelper _output; - - public OpenApiResponseTests(ITestOutputHelper output) - { - _output = output; - } - [Theory] [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json)] [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json)] diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt index b431f1607..aac504993 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt @@ -5,8 +5,8 @@ "minimum": 10, "exclusiveMinimum": true, "type": "integer", - "default": 15, "nullable": true, + "default": 15, "externalDocs": { "url": "http://example.com/externalDocs" } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt index d71a5f0a8..3ed4ce5c8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"title":"title1","multipleOf":3,"maximum":42,"minimum":10,"exclusiveMinimum":true,"type":"integer","default":15,"nullable":true,"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file +{"title":"title1","multipleOf":3,"maximum":42,"minimum":10,"exclusiveMinimum":true,"type":"integer","nullable":true,"default":15,"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=False.verified.txt index b431f1607..aac504993 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=False.verified.txt @@ -5,8 +5,8 @@ "minimum": 10, "exclusiveMinimum": true, "type": "integer", - "default": 15, "nullable": true, + "default": 15, "externalDocs": { "url": "http://example.com/externalDocs" } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=True.verified.txt index d71a5f0a8..3ed4ce5c8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"title":"title1","multipleOf":3,"maximum":42,"minimum":10,"exclusiveMinimum":true,"type":"integer","default":15,"nullable":true,"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file +{"title":"title1","multipleOf":3,"maximum":42,"minimum":10,"exclusiveMinimum":true,"type":"integer","nullable":true,"default":15,"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt index e9543ede7..e30457226 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt @@ -1,4 +1,6 @@ { + "type": "object", + "x-nullable": true, "title": "title1", "required": [ "property1" diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt index 9ea88dee8..d5d9596f0 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"title":"title1","required":["property1"],"properties":{"property1":{"required":["property3"],"properties":{"property2":{"type":"integer"},"property3":{"type":"string","maxLength":15}}},"property4":{"properties":{"property5":{"properties":{"property6":{"type":"boolean"}}},"property7":{"type":"string","minLength":2}},"readOnly":true}},"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file +{"type":"object","x-nullable":true,"title":"title1","required":["property1"],"properties":{"property1":{"required":["property3"],"properties":{"property2":{"type":"integer"},"property3":{"type":"string","maxLength":15}}},"property4":{"properties":{"property5":{"properties":{"property6":{"type":"boolean"}}},"property7":{"type":"string","minLength":2}},"readOnly":true}},"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index 5edd1c0d0..951c96fe8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -12,6 +12,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Writers; using VerifyXunit; @@ -32,9 +33,8 @@ public class OpenApiSchemaTests ExclusiveMinimum = true, Minimum = 10, Default = 15, - Type = JsonSchemaType.Integer, + Type = JsonSchemaType.Integer | JsonSchemaType.Null, - Nullable = true, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -45,38 +45,38 @@ public class OpenApiSchemaTests public static readonly OpenApiSchema AdvancedSchemaObject = new() { Title = "title1", - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 } }, }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property5"] = new() + ["property5"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property6"] = new() + ["property6"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property7"] = new() + ["property7"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 @@ -84,7 +84,7 @@ public class OpenApiSchemaTests }, }, }, - Nullable = true, + Type = JsonSchemaType.Object | JsonSchemaType.Null, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -94,49 +94,49 @@ public class OpenApiSchemaTests public static readonly OpenApiSchema AdvancedSchemaWithAllOf = new() { Title = "title1", - AllOf = new List + AllOf = new List { - new() + new OpenApiSchema() { Title = "title2", - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 } }, }, - new() + new OpenApiSchema() { Title = "title3", - Properties = new Dictionary + Properties = new Dictionary { - ["property3"] = new() + ["property3"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property4"] = new() + ["property4"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property5"] = new() + ["property5"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 } }, - Nullable = true + Type = JsonSchemaType.Object | JsonSchemaType.Null, }, }, - Nullable = true, + Type = JsonSchemaType.Object | JsonSchemaType.Null, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -151,9 +151,8 @@ public class OpenApiSchemaTests ExclusiveMinimum = true, Minimum = 10, Default = 15, - Type = JsonSchemaType.Integer, + Type = JsonSchemaType.Integer | JsonSchemaType.Null, - Nullable = true, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -164,18 +163,18 @@ public class OpenApiSchemaTests { Title = "title1", Required = new HashSet { "property1" }, - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Required = new HashSet { "property3" }, - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15, @@ -184,21 +183,21 @@ public class OpenApiSchemaTests }, ReadOnly = true, }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property5"] = new() + ["property5"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property6"] = new() + ["property6"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property7"] = new() + ["property7"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 @@ -207,7 +206,7 @@ public class OpenApiSchemaTests ReadOnly = true, }, }, - Nullable = true, + Type = JsonSchemaType.Object | JsonSchemaType.Null, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -242,8 +241,8 @@ public async Task SerializeAdvancedSchemaNumberAsV3JsonWorks() "minimum": 10, "exclusiveMinimum": true, "type": "integer", - "default": 15, "nullable": true, + "default": 15, "externalDocs": { "url": "http://example.com/externalDocs" } @@ -254,9 +253,7 @@ public async Task SerializeAdvancedSchemaNumberAsV3JsonWorks() var actual = await AdvancedSchemaNumber.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -267,6 +264,8 @@ public async Task SerializeAdvancedSchemaObjectAsV3JsonWorks() """ { "title": "title1", + "type": "object", + "nullable": true, "properties": { "property1": { "properties": { @@ -295,7 +294,6 @@ public async Task SerializeAdvancedSchemaObjectAsV3JsonWorks() } } }, - "nullable": true, "externalDocs": { "url": "http://example.com/externalDocs" } @@ -306,9 +304,7 @@ public async Task SerializeAdvancedSchemaObjectAsV3JsonWorks() var actual = await AdvancedSchemaObject.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -319,6 +315,8 @@ public async Task SerializeAdvancedSchemaWithAllOfAsV3JsonWorks() """ { "title": "title1", + "type": "object", + "nullable": true, "allOf": [ { "title": "title2", @@ -334,6 +332,8 @@ public async Task SerializeAdvancedSchemaWithAllOfAsV3JsonWorks() }, { "title": "title3", + "type": "object", + "nullable": true, "properties": { "property3": { "properties": { @@ -346,11 +346,9 @@ public async Task SerializeAdvancedSchemaWithAllOfAsV3JsonWorks() "minLength": 2, "type": "string" } - }, - "nullable": true + } } ], - "nullable": true, "externalDocs": { "url": "http://example.com/externalDocs" } @@ -361,9 +359,7 @@ public async Task SerializeAdvancedSchemaWithAllOfAsV3JsonWorks() var actual = await AdvancedSchemaWithAllOf.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonObject.DeepEquals(JsonObject.Parse(expected), JsonObject.Parse(actual))); } [Theory] @@ -423,14 +419,14 @@ public async Task SerializeAsV2ShouldSetFormatPropertyInParentSchemaIfPresentInC // Arrange var schema = new OpenApiSchema { - OneOf = new List + OneOf = new List { - new() + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "decimal" }, - new() { Type = JsonSchemaType.String }, + new OpenApiSchema() { Type = JsonSchemaType.String }, } }; @@ -470,14 +466,12 @@ public void OpenApiSchemaCopyConstructorSucceeds() Format = "date" }; - var actualSchema = new OpenApiSchema(baseSchema) - { - Nullable = true - }; + var actualSchema = baseSchema.CreateShallowCopy() as OpenApiSchema; + actualSchema.Type |= JsonSchemaType.Null; - Assert.Equal(JsonSchemaType.String, actualSchema.Type); + Assert.Equal(JsonSchemaType.String, actualSchema.Type & JsonSchemaType.String); + Assert.Equal(JsonSchemaType.Null, actualSchema.Type & JsonSchemaType.Null); Assert.Equal("date", actualSchema.Format); - Assert.True(actualSchema.Nullable); } [Fact] @@ -492,7 +486,7 @@ public void OpenApiSchemaCopyConstructorWithAnnotationsSucceeds() } }; - var actualSchema = new OpenApiSchema(baseSchema); + var actualSchema = baseSchema.CreateShallowCopy(); Assert.Equal(baseSchema.Annotations["key1"], actualSchema.Annotations["key1"]); @@ -530,7 +524,7 @@ public void CloningSchemaExamplesWorks(JsonNode example) }; // Act && Assert - var schemaCopy = new OpenApiSchema(schema); + var schemaCopy = schema.CreateShallowCopy(); // Act && Assert schema.Example.Should().BeEquivalentTo(schemaCopy.Example, options => options @@ -551,7 +545,7 @@ public void CloningSchemaExtensionsWorks() }; // Act && Assert - var schemaCopy = new OpenApiSchema(schema); + var schemaCopy = schema.CreateShallowCopy() as OpenApiSchema; Assert.Single(schemaCopy.Extensions); // Act && Assert @@ -634,7 +628,7 @@ internal class SchemaVisitor : OpenApiVisitorBase { public List Titles = new(); - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { Titles.Add(schema.Title); } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs index af0343f57..cfbe0ae50 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs @@ -13,6 +13,8 @@ using VerifyXunit; using Microsoft.OpenApi.Models.References; using Xunit; +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Tests.Models { @@ -25,7 +27,7 @@ public class OpenApiSecurityRequirementTests new() { [ - new OpenApiSecuritySchemeReference("scheme1", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme1", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List { "scope1", @@ -33,22 +35,56 @@ public class OpenApiSecurityRequirementTests "scope3", }, [ - new OpenApiSecuritySchemeReference("scheme2", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme2", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List { "scope4", "scope5", }, [ - new OpenApiSecuritySchemeReference("scheme3", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme3", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List() }; + public static OpenApiDocument SecurityRequirementWithReferencedSecurityScheme_supportingDocument + { + get + { + var document = new OpenApiDocument() + { + Components = new() + { + SecuritySchemes = new Dictionary + { + ["scheme1"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.ApiKey, + Name = "apiKeyName1", + In = ParameterLocation.Header, + }, + ["scheme2"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OpenIdConnect, + OpenIdConnectUrl = new("http://example.com"), + }, + ["scheme3"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.Http, + Scheme = "bearer", + BearerFormat = "JWT", + }, + } + } + }; + document.RegisterComponents(); + return document; + } + } public static OpenApiSecurityRequirement SecurityRequirementWithUnreferencedSecurityScheme = new() { [ - new OpenApiSecuritySchemeReference("scheme1", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme1", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List { "scope1", @@ -56,18 +92,14 @@ public class OpenApiSecurityRequirementTests "scope3", }, [ - new() - { - // This security scheme is unreferenced, so this key value pair cannot be serialized. - Name = "brokenUnreferencedScheme" - } + new OpenApiSecuritySchemeReference("brokenUnreferencedScheme", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List { "scope4", "scope5", }, [ - new OpenApiSecuritySchemeReference("scheme3", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme3", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List() }; @@ -127,9 +159,7 @@ public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV3Js var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -156,9 +186,7 @@ public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV2Js var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -181,9 +209,7 @@ public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV3 var actual = await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -207,9 +233,7 @@ public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV2 await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -223,22 +247,12 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality() Type = SecuritySchemeType.ApiKey, Name = "apiKeyName1", In = ParameterLocation.Header, - Reference = new() - { - Id = "securityScheme1", - Type = ReferenceType.SecurityScheme - } }; var securityScheme2 = new OpenApiSecurityScheme { Type = SecuritySchemeType.OpenIdConnect, OpenIdConnectUrl = new("http://example.com"), - Reference = new() - { - Id = "securityScheme2", - Type = ReferenceType.SecurityScheme - } }; var securityScheme1Duplicate = new OpenApiSecurityScheme @@ -246,11 +260,6 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality() Type = SecuritySchemeType.ApiKey, Name = "apiKeyName1", In = ParameterLocation.Header, - Reference = new() - { - Id = "securityScheme1", - Type = ReferenceType.SecurityScheme - } }; var securityScheme1WithDifferentProperties = new OpenApiSecurityScheme @@ -258,21 +267,16 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality() Type = SecuritySchemeType.ApiKey, Name = "apiKeyName2", In = ParameterLocation.Query, - Reference = new() - { - Id = "securityScheme1", - Type = ReferenceType.SecurityScheme - } }; // Act - securityRequirement.Add(securityScheme1, new List()); - securityRequirement.Add(securityScheme2, new List { "scope1", "scope2" }); + securityRequirement.Add(new OpenApiSecuritySchemeReference("securityScheme1"), new List()); + securityRequirement.Add(new OpenApiSecuritySchemeReference("securityScheme2"), new List { "scope1", "scope2" }); var addSecurityScheme1Duplicate = () => - securityRequirement.Add(securityScheme1Duplicate, new List()); + securityRequirement.Add(new OpenApiSecuritySchemeReference("securityScheme1"), new List()); var addSecurityScheme1WithDifferentProperties = () => - securityRequirement.Add(securityScheme1WithDifferentProperties, new List()); + securityRequirement.Add(new OpenApiSecuritySchemeReference("securityScheme1"), new List()); // Assert // Only the first two should be added successfully since the latter two are duplicates of securityScheme1. @@ -287,8 +291,8 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality() { // This should work with any security scheme object // as long as Reference.Id os securityScheme1 - [securityScheme1WithDifferentProperties] = new List(), - [securityScheme2] = new List { "scope1", "scope2" }, + [new OpenApiSecuritySchemeReference("securityScheme1", null)] = new List(), + [new OpenApiSecuritySchemeReference("securityScheme2", null)] = new List { "scope1", "scope2" }, }); } } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs index 9c59ca4bd..12db6c1e8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs @@ -17,7 +17,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiSecuritySchemeTests { - public static OpenApiSecurityScheme ApiKeySecurityScheme = new() + private static OpenApiSecurityScheme ApiKeySecurityScheme => new() { Description = "description1", Name = "parameterName", @@ -25,14 +25,14 @@ public class OpenApiSecuritySchemeTests In = ParameterLocation.Query, }; - public static OpenApiSecurityScheme HttpBasicSecurityScheme = new() + private static OpenApiSecurityScheme HttpBasicSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.Http, Scheme = OpenApiConstants.Basic }; - public static OpenApiSecurityScheme HttpBearerSecurityScheme = new() + private static OpenApiSecurityScheme HttpBearerSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.Http, @@ -40,7 +40,7 @@ public class OpenApiSecuritySchemeTests BearerFormat = OpenApiConstants.Jwt }; - public static OpenApiSecurityScheme OAuth2SingleFlowSecurityScheme = new() + private static OpenApiSecurityScheme OAuth2SingleFlowSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.OAuth2, @@ -58,7 +58,7 @@ public class OpenApiSecuritySchemeTests } }; - public static OpenApiSecurityScheme OAuth2MultipleFlowSecurityScheme = new() + private static OpenApiSecurityScheme OAuth2MultipleFlowSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.OAuth2, @@ -96,7 +96,7 @@ public class OpenApiSecuritySchemeTests } }; - public static OpenApiSecurityScheme OpenIdConnectSecurityScheme = new() + private static OpenApiSecurityScheme OpenIdConnectSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.OpenIdConnect, @@ -104,8 +104,8 @@ public class OpenApiSecuritySchemeTests OpenIdConnectUrl = new("https://example.com/openIdConnect") }; - public static OpenApiSecuritySchemeReference OpenApiSecuritySchemeReference = new(target: ReferencedSecurityScheme, referenceId: "sampleSecurityScheme"); - public static OpenApiSecurityScheme ReferencedSecurityScheme = new() + private static OpenApiSecuritySchemeReference OpenApiSecuritySchemeReference => new("sampleSecurityScheme"); + private static OpenApiSecurityScheme ReferencedSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.OpenIdConnect, diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt deleted file mode 100644 index 2afa516e0..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "pet", - "description": "Pets operations", - "externalDocs": { - "description": "Find more info here", - "url": "https://example.com" - }, - "x-tag-extension": null -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index f0a901938..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"name":"pet","description":"Pets operations","externalDocs":{"description":"Find more info here","url":"https://example.com"},"x-tag-extension":null} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt deleted file mode 100644 index 2afa516e0..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "pet", - "description": "Pets operations", - "externalDocs": { - "description": "Find more info here", - "url": "https://example.com" - }, - "x-tag-extension": null -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index f0a901938..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"name":"pet","description":"Pets operations","externalDocs":{"description":"Find more info here","url":"https://example.com"},"x-tag-extension":null} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs index 508779adf..73ac0d0b7 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using VerifyXunit; @@ -30,7 +31,7 @@ public class OpenApiTagTests } }; - public static OpenApiTag ReferencedTag = new OpenApiTagReference("pet", null); + public static IOpenApiTag ReferencedTag = new OpenApiTagReference("pet"); [Theory] [InlineData(true)] diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeReferencedCallbackAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeReferencedCallbackAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeReferencedCallbackAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeReferencedCallbackAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeReferencedCallbackAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeReferencedCallbackAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeReferencedCallbackAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeReferencedCallbackAsV3JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.cs index 38bf27215..34284b9bd 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.cs @@ -159,37 +159,41 @@ public void CallbackReferenceResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeCallbackReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeCallbackReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineExternalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineExternalReferences = true, InlineLocalReferences = inlineLocalReferences }); // Act _externalCallbackReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeCallbackReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeCallbackReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineExternalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineExternalReferences = true, InlineLocalReferences = inlineLocalReferences}); // Act _externalCallbackReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt deleted file mode 100644 index f71202885..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,10 +0,0 @@ -{ - "summary": "Example of a user", - "description": "This is is an example of a user", - "value": [ - { - "id": "1", - "name": "John Doe" - } - ] -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index cddf257f8..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"summary":"Example of a user","description":"This is is an example of a user","value":[{"id":"1","name":"John Doe"}]} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 59% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt index d3d85c6b5..cb7caa304 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -1,10 +1,5 @@ { "summary": "Example of a local user", "description": "This is an example of a local user", - "value": [ - { - "id": 1, - "name": "John Doe" - } - ] + "$ref": "#/components/examples/UserExample" } \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..def86be23 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"summary":"Example of a local user","description":"This is an example of a local user","$ref":"#/components/examples/UserExample"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..fcff4230d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "#/components/examples/UserExample" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 89% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt index f71202885..8d9c12611 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -3,7 +3,7 @@ "description": "This is is an example of a user", "value": [ { - "id": "1", + "id": 1, "name": "John Doe" } ] diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index 0c1962929..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"summary":"Example of a local user","description":"This is an example of a local user","value":[{"id":1,"name":"John Doe"}]} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..0efca4639 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"#/components/examples/UserExample"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 52% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt index cddf257f8..c1549bf7c 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.SerializeExampleReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -1 +1 @@ -{"summary":"Example of a user","description":"This is is an example of a user","value":[{"id":"1","name":"John Doe"}]} \ No newline at end of file +{"summary":"Example of a user","description":"This is is an example of a user","value":[{"id":1,"name":"John Doe"}]} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.cs index 2cb0ff189..a52c027f9 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.cs @@ -150,37 +150,41 @@ public void ExampleReferenceResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeExampleReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeExampleReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localExampleReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeExampleReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeExampleReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localExampleReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index 1b29be17d..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"description":"The URL of the newly created post","schema":{"type":"string"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt deleted file mode 100644 index b957bd951..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -{ - "description": "Location of the locally referenced post", - "type": "string" -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..38d7a64f2 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "#/headers/LocationHeader" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 60% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=True.verified.txt index f43e25a40..8bd613186 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -1,6 +1,4 @@ { "description": "The URL of the newly created post", - "schema": { - "type": "string" - } + "type": "string" } \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index 17f59471d..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"description":"Location of the locally referenced post","type":"string"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..cfae04d2b --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"#/headers/LocationHeader"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..9d510cb80 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"description":"The URL of the newly created post","type":"string"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 57% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt index badfda7f7..0959c10ea 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -1,6 +1,4 @@ { "description": "Location of the locally referenced post", - "schema": { - "type": "string" - } + "$ref": "#/components/headers/LocationHeader" } \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..eabf641fd --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"description":"Location of the locally referenced post","$ref":"#/components/headers/LocationHeader"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..74963dc5e --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "#/components/headers/LocationHeader" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index cf7cf9e25..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"description":"Location of the locally referenced post","schema":{"type":"string"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..da8e23f86 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"#/components/headers/LocationHeader"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeHeaderReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt deleted file mode 100644 index 8b29b212e..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -{ - "description": "Location of the locally created post", - "type": "string" -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index 243908873..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"description":"Location of the locally created post","type":"string"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs index d7fef6396..9b3c6c544 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs @@ -109,54 +109,60 @@ public void HeaderReferenceResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeHeaderReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeHeaderReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localHeaderReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeHeaderReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeHeaderReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localHeaderReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeHeaderReferenceAsV2JsonWorksAsync(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeHeaderReferenceAsV2JsonWorksAsync(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localHeaderReference.SerializeAsV2(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Fact] @@ -166,7 +172,7 @@ public void OpenApiHeaderTargetShouldResolveReference() { Components = new OpenApiComponents { - Headers = new System.Collections.Generic.Dictionary + Headers = { { "header1", new OpenApiHeader { diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt deleted file mode 100644 index 6fe727ea0..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,7 +0,0 @@ -{ - "operationId": "getUser", - "parameters": { - "userId": "$response.body#/id" - }, - "description": "The id value returned in the response can be used as the userId parameter in GET /users/{userId}" -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index e3df412e9..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"operationId":"getUser","parameters":{"userId":"$response.body#/id"},"description":"The id value returned in the response can be used as the userId parameter in GET /users/{userId}"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..2b8d39932 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,4 @@ +{ + "description": "Use the id returned as the userId in `GET /users/{userId}`", + "$ref": "#/components/links/GetUserByUserId" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..3130ca88d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"description":"Use the id returned as the userId in `GET /users/{userId}`","$ref":"#/components/links/GetUserByUserId"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt deleted file mode 100644 index 89319843f..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,7 +0,0 @@ -{ - "operationId": "getUser", - "parameters": { - "userId": "$response.body#/id" - }, - "description": "Use the id returned as the userId in `GET /users/{userId}`" -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..2fa856caf --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "#/components/links/GetUserByUserId" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index 93208a391..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"operationId":"getUser","parameters":{"userId":"$response.body#/id"},"description":"Use the id returned as the userId in `GET /users/{userId}`"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..431f49da4 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"#/components/links/GetUserByUserId"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.SerializeLinkReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.cs index 4845c2311..44822454f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.cs @@ -158,37 +158,41 @@ public void LinkReferenceResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeLinkReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeLinkReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localLinkReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeLinkReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeLinkReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localLinkReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..9ef7c70ed --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "#/parameters/limitParam" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 66% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=True.verified.txt index 2a64ba6d9..992c2f047 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -1,7 +1,7 @@ { "in": "query", "name": "limit", - "description": "Results to return", + "description": "Number of results to return", "type": "integer", "maximum": 100, "minimum": 1 diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index 8d3cb1803..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"in":"query","name":"limit","description":"Results to return","type":"integer","maximum":100,"minimum":1} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..7463c6c0e --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"#/parameters/limitParam"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..995eb077e --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"in":"query","name":"limit","description":"Number of results to return","type":"integer","maximum":100,"minimum":1} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..045ad6d1d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,4 @@ +{ + "description": "Results to return", + "$ref": "#/components/parameters/limitParam" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 89% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt index 237298009..cd30a5fc2 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -2,7 +2,6 @@ "name": "limit", "in": "query", "description": "Results to return", - "style": "form", "schema": { "maximum": 100, "minimum": 1, diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index e8eac1b64..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"name":"limit","in":"query","description":"Results to return","style":"form","schema":{"maximum":100,"minimum":1,"type":"integer"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..6fdeee0c3 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"description":"Results to return","$ref":"#/components/parameters/limitParam"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..da4f04c14 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"name":"limit","in":"query","description":"Results to return","schema":{"maximum":100,"minimum":1,"type":"integer"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..24f3c7a74 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "#/components/parameters/limitParam" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 67% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt index 237298009..f0066344e 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -1,8 +1,7 @@ { "name": "limit", "in": "query", - "description": "Results to return", - "style": "form", + "description": "Number of results to return", "schema": { "maximum": 100, "minimum": 1, diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index e8eac1b64..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"name":"limit","in":"query","description":"Results to return","style":"form","schema":{"maximum":100,"minimum":1,"type":"integer"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..1eb2fda7d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"#/components/parameters/limitParam"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..2b7ff1cfb --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"name":"limit","in":"query","description":"Number of results to return","schema":{"maximum":100,"minimum":1,"type":"integer"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.cs index 5e95246ae..8afc96f04 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.cs @@ -111,54 +111,60 @@ public void ParameterReferenceResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeParameterReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeParameterReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localParameterReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeParameterReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeParameterReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localParameterReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeParameterReferenceAsV2JsonWorksAsync(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeParameterReferenceAsV2JsonWorksAsync(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput , InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput , InlineLocalReferences = inlineLocalReferences }); // Act _localParameterReference.SerializeAsV2(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt deleted file mode 100644 index 844f5ee81..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,28 +0,0 @@ -{ - "summary": "User path item summary", - "description": "User path item description", - "get": { - "summary": "Get users", - "responses": { - "200": { - "description": "Successful operation" - } - } - }, - "post": { - "summary": "Create a user", - "responses": { - "201": { - "description": "User created successfully" - } - } - }, - "delete": { - "summary": "Delete a user", - "responses": { - "204": { - "description": "User deleted successfully" - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index f43044ef8..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"summary":"User path item summary","description":"User path item description","get":{"summary":"Get users","responses":{"200":{"description":"Successful operation"}}},"post":{"summary":"Create a user","responses":{"201":{"description":"User created successfully"}}},"delete":{"summary":"Delete a user","responses":{"204":{"description":"User deleted successfully"}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt deleted file mode 100644 index 844f5ee81..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,28 +0,0 @@ -{ - "summary": "User path item summary", - "description": "User path item description", - "get": { - "summary": "Get users", - "responses": { - "200": { - "description": "Successful operation" - } - } - }, - "post": { - "summary": "Create a user", - "responses": { - "201": { - "description": "User created successfully" - } - } - }, - "delete": { - "summary": "Delete a user", - "responses": { - "204": { - "description": "User deleted successfully" - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index f43044ef8..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeCallbackReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"summary":"User path item summary","description":"User path item description","get":{"summary":"Get users","responses":{"200":{"description":"Successful operation"}}},"post":{"summary":"Create a user","responses":{"201":{"description":"User created successfully"}}},"delete":{"summary":"Delete a user","responses":{"204":{"description":"User deleted successfully"}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt deleted file mode 100644 index 86685c051..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,28 +0,0 @@ -{ - "get": { - "summary": "Get users", - "responses": { - "200": { - "description": "Successful operation" - } - } - }, - "post": { - "summary": "Create a user", - "responses": { - "201": { - "description": "User created successfully" - } - } - }, - "delete": { - "summary": "Delete a user", - "responses": { - "204": { - "description": "User deleted successfully" - } - } - }, - "x-summary": "Local reference: User path item summary", - "x-description": "Local reference: User path item description" -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index efa477cae..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializeParameterReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"get":{"summary":"Get users","responses":{"200":{"description":"Successful operation"}}},"post":{"summary":"Create a user","responses":{"201":{"description":"User created successfully"}}},"delete":{"summary":"Delete a user","responses":{"204":{"description":"User deleted successfully"}}},"x-summary":"Local reference: User path item summary","x-description":"Local reference: User path item description"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt deleted file mode 100644 index 86685c051..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,28 +0,0 @@ -{ - "get": { - "summary": "Get users", - "responses": { - "200": { - "description": "Successful operation" - } - } - }, - "post": { - "summary": "Create a user", - "responses": { - "201": { - "description": "User created successfully" - } - } - }, - "delete": { - "summary": "Delete a user", - "responses": { - "204": { - "description": "User deleted successfully" - } - } - }, - "x-summary": "Local reference: User path item summary", - "x-description": "Local reference: User path item description" -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index efa477cae..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"get":{"summary":"Get users","responses":{"200":{"description":"Successful operation"}}},"post":{"summary":"Create a user","responses":{"201":{"description":"User created successfully"}}},"delete":{"summary":"Delete a user","responses":{"204":{"description":"User deleted successfully"}}},"x-summary":"Local reference: User path item summary","x-description":"Local reference: User path item description"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..e02b91f3c --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,5 @@ +{ + "summary": "Local reference: User path item summary", + "description": "Local reference: User path item description", + "$ref": "#/components/pathItems/userPathItem" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..0eeb858e3 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"summary":"Local reference: User path item summary","description":"Local reference: User path item description","$ref":"#/components/pathItems/userPathItem"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt deleted file mode 100644 index 844f5ee81..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,28 +0,0 @@ -{ - "summary": "User path item summary", - "description": "User path item description", - "get": { - "summary": "Get users", - "responses": { - "200": { - "description": "Successful operation" - } - } - }, - "post": { - "summary": "Create a user", - "responses": { - "201": { - "description": "User created successfully" - } - } - }, - "delete": { - "summary": "Delete a user", - "responses": { - "204": { - "description": "User deleted successfully" - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index f43044ef8..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.SerializePathItemReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"summary":"User path item summary","description":"User path item description","get":{"summary":"Get users","responses":{"200":{"description":"Successful operation"}}},"post":{"summary":"Create a user","responses":{"201":{"description":"User created successfully"}}},"delete":{"summary":"Delete a user","responses":{"204":{"description":"User deleted successfully"}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.cs index 510dfbda3..55c5bc7b5 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.cs @@ -119,20 +119,22 @@ public void PathItemReferenceResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializePathItemReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializePathItemReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localPathItemReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 60% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt index a9be81418..7d881453b 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -1,3 +1,4 @@ { + "description": "User request body", "$ref": "#/components/requestBodies/UserRequest" } \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..716f480fd --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -0,0 +1,18 @@ +{ + "description": "User request body", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..ac2c2d9ac --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"description":"User request body","$ref":"#/components/requestBodies/UserRequest"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..161f80087 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"description":"User request body","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..c4d9bef00 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -0,0 +1,18 @@ +{ + "description": "User creation request body", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index 04f67afdd..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"#/components/requestBodies/UserRequest"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..3d91acf86 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.SerializeRequestBodyReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"description":"User creation request body","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs index 0f1d8f634..ef9bea785 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs @@ -109,50 +109,56 @@ public void RequestBodyReferenceResolutionWorks() // Assert var localContent = _localRequestBodyReference.Content.Values.FirstOrDefault(); Assert.NotNull(localContent); - Assert.Equal("UserSchema", localContent.Schema.Reference.Id); + var localContentSchema = Assert.IsType(localContent.Schema); + Assert.Equal("UserSchema", localContentSchema.Reference.Id); Assert.Equal("User request body", _localRequestBodyReference.Description); Assert.Equal("application/json", _localRequestBodyReference.Content.First().Key); var externalContent = _externalRequestBodyReference.Content.Values.FirstOrDefault(); Assert.NotNull(externalContent); - Assert.Equal("UserSchema", externalContent.Schema.Reference.Id); + var externalContentSchema = Assert.IsType(externalContent.Schema); + Assert.Equal("UserSchema", externalContentSchema.Reference.Id); Assert.Equal("External Reference: User request body", _externalRequestBodyReference.Description); Assert.Equal("User creation request body", _openApiDoc_2.Components.RequestBodies.First().Value.Description); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeRequestBodyReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeRequestBodyReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput}); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localRequestBodyReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeRequestBodyReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task SerializeRequestBodyReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localRequestBodyReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 61% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt index 3b61b5a39..a3164d20f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -1,3 +1,4 @@ { + "description": "OK response", "$ref": "#/components/responses/OkResponse" } \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..851a6a027 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -0,0 +1,15 @@ +{ + "description": "OK response", + "content": { + "text/plain": { + "schema": { + "type": "object", + "properties": { + "sound": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..4d825baf4 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"description":"OK response","$ref":"#/components/responses/OkResponse"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..04256c77a --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"description":"OK response","content":{"text/plain":{"schema":{"type":"object","properties":{"sound":{"type":"string"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..2408f8a10 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -0,0 +1,15 @@ +{ + "description": "OK", + "content": { + "text/plain": { + "schema": { + "type": "object", + "properties": { + "sound": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index d4776f5df..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"#/components/responses/OkResponse"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..c83ea5371 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"description":"OK","content":{"text/plain":{"schema":{"type":"object","properties":{"sound":{"type":"string"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs index b39d6040b..785ea5e55 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs @@ -92,49 +92,55 @@ public void ResponseReferenceResolutionWorks() // Assert var localContent = _localResponseReference.Content.FirstOrDefault(); Assert.Equal("text/plain", localContent.Key); - Assert.Equal("Pong", localContent.Value.Schema.Reference.Id); + var localContentSchema = Assert.IsType(localContent.Value.Schema); + Assert.Equal("Pong", localContentSchema.Reference.Id); Assert.Equal("OK response", _localResponseReference.Description); var externalContent = _externalResponseReference.Content.FirstOrDefault(); Assert.Equal("text/plain", externalContent.Key); - Assert.Equal("Pong", externalContent.Value.Schema.Reference.Id); + var externalContentSchema = Assert.IsType(externalContent.Value.Schema); + Assert.Equal("Pong", externalContentSchema.Reference.Id); Assert.Equal("External reference: OK response", _externalResponseReference.Description); Assert.Equal("OK", _openApiDoc_2.Components.Responses.First().Value.Description); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeResponseReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(true, true)] + [InlineData(false, true)] + public async Task SerializeResponseReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput}); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localResponseReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeResponseReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(true, true)] + [InlineData(false, true)] + public async Task SerializeResponseReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput}); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localResponseReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..a73e7078d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "mySecurityScheme" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..5c70082e7 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"mySecurityScheme"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..a73e7078d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "mySecurityScheme" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..5c70082e7 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"mySecurityScheme"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs index d13d63c9a..56b7e6d07 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs @@ -57,37 +57,41 @@ public void SecuritySchemeResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeSecuritySchemeReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(true, true)] + [InlineData(false, true)] + public async Task SerializeSecuritySchemeReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _openApiSecuritySchemeReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeSecuritySchemeReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(true, true)] + [InlineData(false, true)] + public async Task SerializeSecuritySchemeReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _openApiSecuritySchemeReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs index 9d409c24b..250f8ee53 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs @@ -74,7 +74,6 @@ public void TagReferenceResolutionWorks() // Assert Assert.Equal("user", _openApiTagReference.Name); Assert.Equal("Operations about users.", _openApiTagReference.Description); - Assert.Throws(() => _openApiTagReference.Description = "New Description"); } [Theory] diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 887fb3db8..8b69cb508 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -159,7 +159,7 @@ namespace Microsoft.OpenApi.Extensions public static void AddExtension(this T element, string name, Microsoft.OpenApi.Interfaces.IOpenApiExtension any) where T : Microsoft.OpenApi.Interfaces.IOpenApiExtensible { } } - public static class OpenApiReferencableExtensions + public static class OpenApiReferenceableExtensions { public static Microsoft.OpenApi.Interfaces.IOpenApiReferenceable ResolveReference(this Microsoft.OpenApi.Interfaces.IOpenApiReferenceable element, Microsoft.OpenApi.JsonPointer pointer) { } } @@ -211,6 +211,10 @@ namespace Microsoft.OpenApi.Interfaces { void Write(Microsoft.OpenApi.Writers.IOpenApiWriter writer, Microsoft.OpenApi.OpenApiSpecVersion specVersion); } + public interface IOpenApiReadOnlyExtensible + { + System.Collections.Generic.IDictionary Extensions { get; } + } public interface IOpenApiReader { Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings); @@ -218,21 +222,28 @@ namespace Microsoft.OpenApi.Interfaces T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, Microsoft.OpenApi.Models.OpenApiDocument openApiDocument, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement; } - public interface IOpenApiReferenceable : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public interface IOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { - Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - bool UnresolvedReference { get; set; } + bool UnresolvedReference { get; } + Microsoft.OpenApi.Models.OpenApiReference Reference { get; init; } } - public interface IOpenApiReferenceableWithTarget : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public interface IOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + where out T : Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, V { T Target { get; } + V CopyReferenceAsTargetElementWithOverrides(V source); } + public interface IOpenApiReferenceable : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { } public interface IOpenApiSerializable : Microsoft.OpenApi.Interfaces.IOpenApiElement { void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer); void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer); void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer); } + public interface IShallowCopyable + { + T CreateShallowCopy(); + } public interface IStreamLoader { System.Threading.Tasks.Task LoadAsync(System.Uri uri); @@ -324,6 +335,153 @@ namespace Microsoft.OpenApi.MicrosoftExtensions public static Microsoft.OpenApi.MicrosoftExtensions.OpenApiReservedParameterExtension Parse(System.Text.Json.Nodes.JsonNode source) { } } } +namespace Microsoft.OpenApi.Models.Interfaces +{ + public interface IOpenApiCallback : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable + { + System.Collections.Generic.Dictionary PathItems { get; } + } + public interface IOpenApiDescribedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement + { + string Description { get; set; } + } + public interface IOpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + { + string ExternalValue { get; } + System.Text.Json.Nodes.JsonNode Value { get; } + } + public interface IOpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + bool AllowEmptyValue { get; } + bool AllowReserved { get; } + System.Collections.Generic.IDictionary Content { get; } + bool Deprecated { get; } + System.Text.Json.Nodes.JsonNode Example { get; } + System.Collections.Generic.IDictionary Examples { get; } + bool Explode { get; } + bool Required { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } + Microsoft.OpenApi.Models.ParameterStyle? Style { get; } + } + public interface IOpenApiLink : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + string OperationId { get; } + string OperationRef { get; } + System.Collections.Generic.IDictionary Parameters { get; } + Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; } + Microsoft.OpenApi.Models.OpenApiServer Server { get; } + } + public interface IOpenApiParameter : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + bool AllowEmptyValue { get; } + bool AllowReserved { get; } + System.Collections.Generic.IDictionary Content { get; } + bool Deprecated { get; } + System.Text.Json.Nodes.JsonNode Example { get; } + System.Collections.Generic.IDictionary Examples { get; } + bool Explode { get; } + Microsoft.OpenApi.Models.ParameterLocation? In { get; } + string Name { get; } + bool Required { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } + Microsoft.OpenApi.Models.ParameterStyle? Style { get; } + } + public interface IOpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + { + System.Collections.Generic.IDictionary Operations { get; } + System.Collections.Generic.IList Parameters { get; } + System.Collections.Generic.IList Servers { get; } + } + public interface IOpenApiReadOnlyDescribedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement + { + string Description { get; } + } + public interface IOpenApiRequestBody : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + System.Collections.Generic.IDictionary Content { get; } + bool Required { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter ConvertToBodyParameter(Microsoft.OpenApi.Writers.IOpenApiWriter writer); + System.Collections.Generic.IEnumerable ConvertToFormDataParameters(Microsoft.OpenApi.Writers.IOpenApiWriter writer); + } + public interface IOpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + System.Collections.Generic.IDictionary Content { get; } + System.Collections.Generic.IDictionary Headers { get; } + System.Collections.Generic.IDictionary Links { get; } + } + public interface IOpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; } + bool AdditionalPropertiesAllowed { get; } + System.Collections.Generic.IList AllOf { get; } + System.Collections.Generic.IDictionary Annotations { get; } + System.Collections.Generic.IList AnyOf { get; } + string Comment { get; } + string Const { get; } + System.Text.Json.Nodes.JsonNode Default { get; } + System.Collections.Generic.IDictionary Definitions { get; } + bool Deprecated { get; } + Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; } + string DynamicAnchor { get; } + string DynamicRef { get; } + System.Collections.Generic.IList Enum { get; } + System.Text.Json.Nodes.JsonNode Example { get; } + System.Collections.Generic.IList Examples { get; } + bool? ExclusiveMaximum { get; } + bool? ExclusiveMinimum { get; } + Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + string Format { get; } + string Id { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; } + int? MaxItems { get; } + int? MaxLength { get; } + int? MaxProperties { get; } + decimal? Maximum { get; } + int? MinItems { get; } + int? MinLength { get; } + int? MinProperties { get; } + decimal? Minimum { get; } + decimal? MultipleOf { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; } + System.Collections.Generic.IList OneOf { get; } + string Pattern { get; } + System.Collections.Generic.IDictionary PatternProperties { get; } + System.Collections.Generic.IDictionary Properties { get; } + bool ReadOnly { get; } + System.Collections.Generic.ISet Required { get; } + string Schema { get; } + string Title { get; } + Microsoft.OpenApi.Models.JsonSchemaType? Type { get; } + bool UnEvaluatedProperties { get; } + bool UnevaluatedProperties { get; } + bool? UniqueItems { get; } + System.Collections.Generic.IDictionary UnrecognizedKeywords { get; } + decimal? V31ExclusiveMaximum { get; } + decimal? V31ExclusiveMinimum { get; } + System.Collections.Generic.IDictionary Vocabulary { get; } + bool WriteOnly { get; } + Microsoft.OpenApi.Models.OpenApiXml Xml { get; } + } + public interface IOpenApiSecurityScheme : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + string BearerFormat { get; } + Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; } + Microsoft.OpenApi.Models.ParameterLocation? In { get; } + string Name { get; } + System.Uri OpenIdConnectUrl { get; } + string Scheme { get; } + Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; } + } + public interface IOpenApiSummarizedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement + { + string Summary { get; set; } + } + public interface IOpenApiTag : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiReadOnlyDescribedElement + { + Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + string Name { get; } + } +} namespace Microsoft.OpenApi.Models { [System.Flags] @@ -337,34 +495,32 @@ namespace Microsoft.OpenApi.Models Object = 32, Array = 64, } - public class OpenApiCallback : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiCallback : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback { public OpenApiCallback() { } - public OpenApiCallback(Microsoft.OpenApi.Models.OpenApiCallback callback) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual System.Collections.Generic.Dictionary PathItems { get; set; } - public virtual bool UnresolvedReference { get; set; } - public void AddPathItem(Microsoft.OpenApi.Expressions.RuntimeExpression expression, Microsoft.OpenApi.Models.OpenApiPathItem pathItem) { } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public System.Collections.Generic.Dictionary PathItems { get; set; } + public void AddPathItem(Microsoft.OpenApi.Expressions.RuntimeExpression expression, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiComponents : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { public OpenApiComponents() { } public OpenApiComponents(Microsoft.OpenApi.Models.OpenApiComponents? components) { } - public System.Collections.Generic.IDictionary? Schemas { get; set; } - public virtual System.Collections.Generic.IDictionary? Callbacks { get; set; } - public virtual System.Collections.Generic.IDictionary? Examples { get; set; } - public virtual System.Collections.Generic.IDictionary? Extensions { get; set; } - public virtual System.Collections.Generic.IDictionary? Headers { get; set; } - public virtual System.Collections.Generic.IDictionary? Links { get; set; } - public virtual System.Collections.Generic.IDictionary? Parameters { get; set; } - public virtual System.Collections.Generic.IDictionary? PathItems { get; set; } - public virtual System.Collections.Generic.IDictionary? RequestBodies { get; set; } - public virtual System.Collections.Generic.IDictionary? Responses { get; set; } - public virtual System.Collections.Generic.IDictionary? SecuritySchemes { get; set; } + public System.Collections.Generic.IDictionary? Callbacks { get; set; } + public System.Collections.Generic.IDictionary? Examples { get; set; } + public System.Collections.Generic.IDictionary? Extensions { get; set; } + public System.Collections.Generic.IDictionary? Headers { get; set; } + public System.Collections.Generic.IDictionary? Links { get; set; } + public System.Collections.Generic.IDictionary? Parameters { get; set; } + public System.Collections.Generic.IDictionary? PathItems { get; set; } + public System.Collections.Generic.IDictionary? RequestBodies { get; set; } + public System.Collections.Generic.IDictionary? Responses { get; set; } + public System.Collections.Generic.IDictionary? Schemas { get; set; } + public System.Collections.Generic.IDictionary? SecuritySchemes { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -564,10 +720,11 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IList? SecurityRequirements { get; set; } public System.Collections.Generic.IList? Servers { get; set; } public System.Collections.Generic.IList? Tags { get; set; } - public System.Collections.Generic.IDictionary? Webhooks { get; set; } + public System.Collections.Generic.IDictionary? Webhooks { get; set; } public Microsoft.OpenApi.Services.OpenApiWorkspace? Workspace { get; set; } public bool AddComponent(string id, T componentToRegister) { } public System.Threading.Tasks.Task GetHashCodeAsync(System.Threading.CancellationToken cancellationToken = default) { } + public void RegisterComponents() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -585,7 +742,7 @@ namespace Microsoft.OpenApi.Models public string ContentType { get; set; } public bool? Explode { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } - public System.Collections.Generic.IDictionary Headers { get; set; } + public System.Collections.Generic.IDictionary Headers { get; set; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -600,21 +757,18 @@ namespace Microsoft.OpenApi.Models public string Pointer { get; set; } public override string ToString() { } } - public class OpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { public OpenApiExample() { } - public OpenApiExample(Microsoft.OpenApi.Models.OpenApiExample example) { } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual string ExternalValue { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual string Summary { get; set; } - public virtual bool UnresolvedReference { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Value { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public void SerializeInternal(Microsoft.OpenApi.Writers.IOpenApiWriter writer, Microsoft.OpenApi.OpenApiSpecVersion version) { } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public string ExternalValue { get; set; } + public string Summary { get; set; } + public System.Text.Json.Nodes.JsonNode Value { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiExample CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public abstract class OpenApiExtensibleDictionary : System.Collections.Generic.Dictionary, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable where T : Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -637,27 +791,25 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader { public OpenApiHeader() { } - public OpenApiHeader(Microsoft.OpenApi.Models.OpenApiHeader header) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual bool AllowEmptyValue { get; set; } - public virtual bool AllowReserved { get; set; } - public virtual System.Collections.Generic.IDictionary Content { get; set; } - public virtual bool Deprecated { get; set; } - public virtual string Description { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Example { get; set; } - public virtual System.Collections.Generic.IDictionary Examples { get; set; } - public virtual bool Explode { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual bool Required { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } - public virtual Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } - public virtual bool UnresolvedReference { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public bool AllowEmptyValue { get; set; } + public bool AllowReserved { get; set; } + public System.Collections.Generic.IDictionary Content { get; set; } + public bool Deprecated { get; set; } + public string Description { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; set; } + public System.Collections.Generic.IDictionary Examples { get; set; } + public bool Explode { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public bool Required { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; set; } + public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiInfo : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -687,22 +839,20 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiLink : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiLink : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiLink { public OpenApiLink() { } - public OpenApiLink(Microsoft.OpenApi.Models.OpenApiLink link) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual string OperationId { get; set; } - public virtual string OperationRef { get; set; } - public virtual System.Collections.Generic.Dictionary Parameters { get; set; } - public virtual Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiServer Server { get; set; } - public virtual bool UnresolvedReference { get; set; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public string OperationId { get; set; } + public string OperationRef { get; set; } + public System.Collections.Generic.IDictionary Parameters { get; set; } + public Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; set; } + public Microsoft.OpenApi.Models.OpenApiServer Server { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiLink CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiMediaType : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -710,9 +860,9 @@ namespace Microsoft.OpenApi.Models public OpenApiMediaType(Microsoft.OpenApi.Models.OpenApiMediaType? mediaType) { } public System.Collections.Generic.IDictionary? Encoding { get; set; } public System.Text.Json.Nodes.JsonNode? Example { get; set; } - public System.Collections.Generic.IDictionary? Examples { get; set; } + public System.Collections.Generic.IDictionary? Examples { get; set; } public System.Collections.Generic.IDictionary? Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema? Schema { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema? Schema { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -747,16 +897,16 @@ namespace Microsoft.OpenApi.Models { public const bool DeprecatedDefault = false; public OpenApiOperation() { } - public OpenApiOperation(Microsoft.OpenApi.Models.OpenApiOperation? operation) { } + public OpenApiOperation(Microsoft.OpenApi.Models.OpenApiOperation operation) { } public System.Collections.Generic.IDictionary? Annotations { get; set; } - public System.Collections.Generic.IDictionary? Callbacks { get; set; } + public System.Collections.Generic.IDictionary? Callbacks { get; set; } public bool Deprecated { get; set; } public string? Description { get; set; } public System.Collections.Generic.IDictionary? Extensions { get; set; } public Microsoft.OpenApi.Models.OpenApiExternalDocs? ExternalDocs { get; set; } public string? OperationId { get; set; } - public System.Collections.Generic.IList? Parameters { get; set; } - public Microsoft.OpenApi.Models.OpenApiRequestBody? RequestBody { get; set; } + public System.Collections.Generic.IList? Parameters { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody? RequestBody { get; set; } public Microsoft.OpenApi.Models.OpenApiResponses? Responses { get; set; } public System.Collections.Generic.IList? Security { get; set; } public System.Collections.Generic.IList? Servers { get; set; } @@ -766,194 +916,182 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiParameter : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiParameter : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter { public OpenApiParameter() { } - public OpenApiParameter(Microsoft.OpenApi.Models.OpenApiParameter parameter) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual bool AllowEmptyValue { get; set; } - public virtual bool AllowReserved { get; set; } - public virtual System.Collections.Generic.IDictionary Content { get; set; } - public virtual bool Deprecated { get; set; } - public virtual string Description { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Example { get; set; } - public virtual System.Collections.Generic.IDictionary Examples { get; set; } - public virtual bool Explode { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } - public virtual string Name { get; set; } - public virtual bool Required { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } - public virtual Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } - public virtual bool UnresolvedReference { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public bool AllowEmptyValue { get; set; } + public bool AllowReserved { get; set; } + public System.Collections.Generic.IDictionary Content { get; set; } + public bool Deprecated { get; set; } + public string Description { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; set; } + public System.Collections.Generic.IDictionary Examples { get; set; } + public bool Explode { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } + public string Name { get; set; } + public bool Required { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; set; } + public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { public OpenApiPathItem() { } - public OpenApiPathItem(Microsoft.OpenApi.Models.OpenApiPathItem pathItem) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public bool UnresolvedReference { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual System.Collections.Generic.IDictionary Operations { get; set; } - public virtual System.Collections.Generic.IList Parameters { get; set; } - public virtual System.Collections.Generic.IList Servers { get; set; } - public virtual string Summary { get; set; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public System.Collections.Generic.IDictionary Operations { get; set; } + public System.Collections.Generic.IList Parameters { get; set; } + public System.Collections.Generic.IList Servers { get; set; } + public string Summary { get; set; } public void AddOperation(Microsoft.OpenApi.Models.OperationType operationType, Microsoft.OpenApi.Models.OpenApiOperation operation) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiPaths : Microsoft.OpenApi.Models.OpenApiExtensibleDictionary + public class OpenApiPaths : Microsoft.OpenApi.Models.OpenApiExtensibleDictionary { public OpenApiPaths() { } public OpenApiPaths(Microsoft.OpenApi.Models.OpenApiPaths paths) { } } - public class OpenApiReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { - public bool IsFragment; public OpenApiReference() { } public OpenApiReference(Microsoft.OpenApi.Models.OpenApiReference reference) { } public string Description { get; set; } - public string ExternalResource { get; set; } - public Microsoft.OpenApi.Models.OpenApiDocument HostDocument { get; set; } - public string Id { get; set; } public bool IsExternal { get; } public bool IsLocal { get; } public string ReferenceV2 { get; } public string ReferenceV3 { get; } public string Summary { get; set; } - public Microsoft.OpenApi.Models.ReferenceType? Type { get; set; } + public string ExternalResource { get; init; } + public Microsoft.OpenApi.Models.OpenApiDocument HostDocument { get; init; } + public string Id { get; init; } + public bool IsFragment { get; init; } + public Microsoft.OpenApi.Models.ReferenceType? Type { get; init; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiRequestBody : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiRequestBody : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody { public OpenApiRequestBody() { } - public OpenApiRequestBody(Microsoft.OpenApi.Models.OpenApiRequestBody requestBody) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public bool UnresolvedReference { get; set; } - public virtual System.Collections.Generic.IDictionary Content { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual bool Required { get; set; } + public System.Collections.Generic.IDictionary Content { get; set; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public bool Required { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter ConvertToBodyParameter(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public System.Collections.Generic.IEnumerable ConvertToFormDataParameters(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse { public OpenApiResponse() { } - public OpenApiResponse(Microsoft.OpenApi.Models.OpenApiResponse response) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public bool UnresolvedReference { get; set; } - public virtual System.Collections.Generic.IDictionary Content { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual System.Collections.Generic.IDictionary Headers { get; set; } - public virtual System.Collections.Generic.IDictionary Links { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public System.Collections.Generic.IDictionary Content { get; set; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public System.Collections.Generic.IDictionary Headers { get; set; } + public System.Collections.Generic.IDictionary Links { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiResponses : Microsoft.OpenApi.Models.OpenApiExtensibleDictionary + public class OpenApiResponses : Microsoft.OpenApi.Models.OpenApiExtensibleDictionary { public OpenApiResponses() { } public OpenApiResponses(Microsoft.OpenApi.Models.OpenApiResponses openApiResponses) { } } - public class OpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiAnnotatable, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema { public OpenApiSchema() { } - public OpenApiSchema(Microsoft.OpenApi.Models.OpenApiSchema schema) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; set; } + public bool AdditionalPropertiesAllowed { get; set; } + public System.Collections.Generic.IList AllOf { get; set; } public System.Collections.Generic.IDictionary Annotations { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema AdditionalProperties { get; set; } - public virtual bool AdditionalPropertiesAllowed { get; set; } - public virtual System.Collections.Generic.IList AllOf { get; set; } - public virtual System.Collections.Generic.IList AnyOf { get; set; } - public virtual string Comment { get; set; } - public virtual string Const { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Default { get; set; } - public virtual System.Collections.Generic.IDictionary Definitions { get; set; } - public virtual bool Deprecated { get; set; } - public virtual string Description { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } - public virtual string DynamicAnchor { get; set; } - public virtual string DynamicRef { get; set; } - public virtual System.Collections.Generic.IList Enum { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Example { get; set; } - public virtual System.Collections.Generic.IList Examples { get; set; } - public virtual bool? ExclusiveMaximum { get; set; } - public virtual bool? ExclusiveMinimum { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public virtual string Format { get; set; } - public virtual string Id { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Items { get; set; } - public virtual int? MaxItems { get; set; } - public virtual int? MaxLength { get; set; } - public virtual int? MaxProperties { get; set; } - public virtual decimal? Maximum { get; set; } - public virtual int? MinItems { get; set; } - public virtual int? MinLength { get; set; } - public virtual int? MinProperties { get; set; } - public virtual decimal? Minimum { get; set; } - public virtual decimal? MultipleOf { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Not { get; set; } - public virtual bool Nullable { get; set; } - public virtual System.Collections.Generic.IList OneOf { get; set; } - public virtual string Pattern { get; set; } - public virtual System.Collections.Generic.IDictionary PatternProperties { get; set; } - public virtual System.Collections.Generic.IDictionary Properties { get; set; } - public virtual bool ReadOnly { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual System.Collections.Generic.ISet Required { get; set; } - public virtual string Schema { get; set; } - public virtual string Title { get; set; } - public virtual Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } - public virtual bool UnEvaluatedProperties { get; set; } - public virtual bool UnevaluatedProperties { get; set; } - public virtual bool? UniqueItems { get; set; } - public virtual System.Collections.Generic.IDictionary UnrecognizedKeywords { get; set; } - public virtual bool UnresolvedReference { get; set; } - public virtual decimal? V31ExclusiveMaximum { get; set; } - public virtual decimal? V31ExclusiveMinimum { get; set; } - public virtual System.Collections.Generic.IDictionary Vocabulary { get; set; } - public virtual bool WriteOnly { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public void SerializeInternal(Microsoft.OpenApi.Writers.IOpenApiWriter writer, Microsoft.OpenApi.OpenApiSpecVersion version, System.Action callback) { } + public System.Collections.Generic.IList AnyOf { get; set; } + public string Comment { get; set; } + public string Const { get; set; } + public System.Text.Json.Nodes.JsonNode Default { get; set; } + public System.Collections.Generic.IDictionary Definitions { get; set; } + public bool Deprecated { get; set; } + public string Description { get; set; } + public Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } + public string DynamicAnchor { get; set; } + public string DynamicRef { get; set; } + public System.Collections.Generic.IList Enum { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; set; } + public System.Collections.Generic.IList Examples { get; set; } + public bool? ExclusiveMaximum { get; set; } + public bool? ExclusiveMinimum { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } + public string Format { get; set; } + public string Id { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; set; } + public int? MaxItems { get; set; } + public int? MaxLength { get; set; } + public int? MaxProperties { get; set; } + public decimal? Maximum { get; set; } + public int? MinItems { get; set; } + public int? MinLength { get; set; } + public int? MinProperties { get; set; } + public decimal? Minimum { get; set; } + public decimal? MultipleOf { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; set; } + public System.Collections.Generic.IList OneOf { get; set; } + public string Pattern { get; set; } + public System.Collections.Generic.IDictionary PatternProperties { get; set; } + public System.Collections.Generic.IDictionary Properties { get; set; } + public bool ReadOnly { get; set; } + public System.Collections.Generic.ISet Required { get; set; } + public string Schema { get; set; } + public string Title { get; set; } + public Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } + public bool UnEvaluatedProperties { get; set; } + public bool UnevaluatedProperties { get; set; } + public bool? UniqueItems { get; set; } + public System.Collections.Generic.IDictionary UnrecognizedKeywords { get; set; } + public decimal? V31ExclusiveMaximum { get; set; } + public decimal? V31ExclusiveMinimum { get; set; } + public System.Collections.Generic.IDictionary Vocabulary { get; set; } + public bool WriteOnly { get; set; } + public Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { public OpenApiSecurityRequirement() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiSecurityScheme : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSecurityScheme : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme { public OpenApiSecurityScheme() { } - public OpenApiSecurityScheme(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public bool UnresolvedReference { get; set; } - public virtual string BearerFormat { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; set; } - public virtual Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } - public virtual string Name { get; set; } - public virtual System.Uri OpenIdConnectUrl { get; set; } - public virtual string Scheme { get; set; } - public virtual Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public string BearerFormat { get; set; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; set; } + public Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } + public string Name { get; set; } + public System.Uri OpenIdConnectUrl { get; set; } + public string Scheme { get; set; } + public Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiServer : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -979,18 +1117,17 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiTag : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiTag : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiReadOnlyDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiTag { public OpenApiTag() { } - public OpenApiTag(Microsoft.OpenApi.Models.OpenApiTag tag) { } - public bool UnresolvedReference { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public virtual string Name { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } + public string Name { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiTag CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiXml : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -1100,208 +1237,216 @@ namespace Microsoft.OpenApi.Models } namespace Microsoft.OpenApi.Models.References { - public class OpenApiCallbackReference : Microsoft.OpenApi.Models.OpenApiCallback, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - { - public OpenApiCallbackReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiCallback Target { get; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override System.Collections.Generic.Dictionary PathItems { get; set; } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public abstract class BaseOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + where T : class, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, V + where V : Microsoft.OpenApi.Interfaces.IOpenApiSerializable + { + protected BaseOpenApiReferenceHolder(Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder source) { } + protected BaseOpenApiReferenceHolder(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, Microsoft.OpenApi.Models.ReferenceType referenceType, string externalResource) { } + public virtual T Target { get; } + public bool UnresolvedReference { get; } + public Microsoft.OpenApi.Models.OpenApiReference Reference { get; init; } + public abstract V CopyReferenceAsTargetElementWithOverrides(V source); + public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiExampleReference : Microsoft.OpenApi.Models.OpenApiExample, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiCallbackReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback { - public OpenApiExampleReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiExample Target { get; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override string ExternalValue { get; set; } - public override string Summary { get; set; } - public override System.Text.Json.Nodes.JsonNode Value { get; set; } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - } - public class OpenApiHeaderReference : Microsoft.OpenApi.Models.OpenApiHeader, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - { - public OpenApiHeaderReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiHeader Target { get; } - public override bool AllowEmptyValue { get; set; } - public override bool AllowReserved { get; set; } - public override System.Collections.Generic.IDictionary Content { get; set; } - public override bool Deprecated { get; set; } - public override string Description { get; set; } - public override System.Text.Json.Nodes.JsonNode Example { get; set; } - public override System.Collections.Generic.IDictionary Examples { get; set; } - public override bool Explode { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override bool Required { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } - public override Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } + public OpenApiCallbackReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public System.Collections.Generic.IDictionary Extensions { get; } + public System.Collections.Generic.Dictionary PathItems { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiLinkReference : Microsoft.OpenApi.Models.OpenApiLink, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - { - public OpenApiLinkReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiLink Target { get; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override string OperationId { get; set; } - public override string OperationRef { get; set; } - public override System.Collections.Generic.Dictionary Parameters { get; set; } - public override Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; set; } - public override Microsoft.OpenApi.Models.OpenApiServer Server { get; set; } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - } - public class OpenApiParameterReference : Microsoft.OpenApi.Models.OpenApiParameter, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - { - public OpenApiParameterReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiParameter Target { get; } - public override bool AllowEmptyValue { get; set; } - public override bool AllowReserved { get; set; } - public override System.Collections.Generic.IDictionary Content { get; set; } - public override bool Deprecated { get; set; } - public override string Description { get; set; } - public override System.Text.Json.Nodes.JsonNode Example { get; set; } - public override System.Collections.Generic.IDictionary Examples { get; set; } - public override bool Explode { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } - public override string Name { get; set; } - public override bool Required { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } - public override Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } + public class OpenApiExampleReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + { + public OpenApiExampleReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; } + public string ExternalValue { get; } + public string Summary { get; set; } + public System.Text.Json.Nodes.JsonNode Value { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiExample CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiExample CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiPathItemReference : Microsoft.OpenApi.Models.OpenApiPathItem, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiHeaderReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader { - public OpenApiPathItemReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiPathItem Target { get; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override System.Collections.Generic.IDictionary Operations { get; set; } - public override System.Collections.Generic.IList Parameters { get; set; } - public override System.Collections.Generic.IList Servers { get; set; } - public override string Summary { get; set; } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public OpenApiHeaderReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public bool AllowEmptyValue { get; } + public bool AllowReserved { get; } + public System.Collections.Generic.IDictionary Content { get; } + public bool Deprecated { get; } + public string Description { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; } + public System.Collections.Generic.IDictionary Examples { get; } + public bool Explode { get; } + public System.Collections.Generic.IDictionary Extensions { get; } + public bool Required { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } + public Microsoft.OpenApi.Models.ParameterStyle? Style { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader CreateShallowCopy() { } + } + public class OpenApiLinkReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiLink + { + public OpenApiLinkReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; } + public string OperationId { get; } + public string OperationRef { get; } + public System.Collections.Generic.IDictionary Parameters { get; } + public Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; } + public Microsoft.OpenApi.Models.OpenApiServer Server { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiLink CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiLink source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiLink CreateShallowCopy() { } + public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiRequestBodyReference : Microsoft.OpenApi.Models.OpenApiRequestBody, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiParameterReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter { - public OpenApiRequestBodyReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiRequestBody Target { get; } - public override System.Collections.Generic.IDictionary Content { get; set; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override bool Required { get; set; } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public OpenApiParameterReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public bool AllowEmptyValue { get; } + public bool AllowReserved { get; } + public System.Collections.Generic.IDictionary Content { get; } + public bool Deprecated { get; } + public string Description { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; } + public System.Collections.Generic.IDictionary Examples { get; } + public bool Explode { get; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.ParameterLocation? In { get; } + public string Name { get; } + public bool Required { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } + public Microsoft.OpenApi.Models.ParameterStyle? Style { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter CreateShallowCopy() { } } - public class OpenApiResponseReference : Microsoft.OpenApi.Models.OpenApiResponse, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiPathItemReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { - public OpenApiResponseReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiResponse Target { get; } - public override System.Collections.Generic.IDictionary Content { get; set; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override System.Collections.Generic.IDictionary Headers { get; set; } - public override System.Collections.Generic.IDictionary Links { get; set; } + public OpenApiPathItemReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; } + public System.Collections.Generic.IDictionary Operations { get; } + public System.Collections.Generic.IList Parameters { get; } + public System.Collections.Generic.IList Servers { get; } + public string Summary { get; set; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiSchemaReference : Microsoft.OpenApi.Models.OpenApiSchema, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - { - public OpenApiSchemaReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiSchema? Target { get; } - public override Microsoft.OpenApi.Models.OpenApiSchema AdditionalProperties { get; set; } - public override bool AdditionalPropertiesAllowed { get; set; } - public override System.Collections.Generic.IList AllOf { get; set; } - public override System.Collections.Generic.IList AnyOf { get; set; } - public override string Comment { get; set; } - public override string Const { get; set; } - public override System.Text.Json.Nodes.JsonNode Default { get; set; } - public override System.Collections.Generic.IDictionary Definitions { get; set; } - public override bool Deprecated { get; set; } - public override string Description { get; set; } - public override Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } - public override string DynamicAnchor { get; set; } - public override string DynamicRef { get; set; } - public override System.Collections.Generic.IList Enum { get; set; } - public override System.Text.Json.Nodes.JsonNode Example { get; set; } - public override System.Collections.Generic.IList Examples { get; set; } - public override bool? ExclusiveMaximum { get; set; } - public override bool? ExclusiveMinimum { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public override string Format { get; set; } - public override string Id { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Items { get; set; } - public override int? MaxItems { get; set; } - public override int? MaxLength { get; set; } - public override int? MaxProperties { get; set; } - public override decimal? Maximum { get; set; } - public override int? MinItems { get; set; } - public override int? MinLength { get; set; } - public override int? MinProperties { get; set; } - public override decimal? Minimum { get; set; } - public override decimal? MultipleOf { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Not { get; set; } - public override bool Nullable { get; set; } - public override System.Collections.Generic.IList OneOf { get; set; } - public override string Pattern { get; set; } - public override System.Collections.Generic.IDictionary PatternProperties { get; set; } - public override System.Collections.Generic.IDictionary Properties { get; set; } - public override bool ReadOnly { get; set; } - public override System.Collections.Generic.ISet Required { get; set; } - public override string Schema { get; set; } - public override string Title { get; set; } - public override Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } - public override bool UnEvaluatedProperties { get; set; } - public override bool UnevaluatedProperties { get; set; } - public override bool? UniqueItems { get; set; } - public override decimal? V31ExclusiveMaximum { get; set; } - public override decimal? V31ExclusiveMinimum { get; set; } - public override System.Collections.Generic.IDictionary Vocabulary { get; set; } - public override bool WriteOnly { get; set; } - public override Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } + public class OpenApiRequestBodyReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody + { + public OpenApiRequestBodyReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public System.Collections.Generic.IDictionary Content { get; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; } + public bool Required { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter ConvertToBodyParameter(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public System.Collections.Generic.IEnumerable ConvertToFormDataParameters(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiSecuritySchemeReference : Microsoft.OpenApi.Models.OpenApiSecurityScheme, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - { - public OpenApiSecuritySchemeReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiSecurityScheme Target { get; } - public override string BearerFormat { get; set; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; set; } - public override Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } - public override string Name { get; set; } - public override System.Uri OpenIdConnectUrl { get; set; } - public override string Scheme { get; set; } - public override Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; set; } + public class OpenApiResponseReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse + { + public OpenApiResponseReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public System.Collections.Generic.IDictionary Content { get; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; } + public System.Collections.Generic.IDictionary Headers { get; } + public System.Collections.Generic.IDictionary Links { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse CreateShallowCopy() { } + } + public class OpenApiSchemaReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema + { + public OpenApiSchemaReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; } + public bool AdditionalPropertiesAllowed { get; } + public System.Collections.Generic.IList AllOf { get; } + public System.Collections.Generic.IDictionary Annotations { get; } + public System.Collections.Generic.IList AnyOf { get; } + public string Comment { get; } + public string Const { get; } + public System.Text.Json.Nodes.JsonNode Default { get; } + public System.Collections.Generic.IDictionary Definitions { get; } + public bool Deprecated { get; } + public string Description { get; set; } + public Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; } + public string DynamicAnchor { get; } + public string DynamicRef { get; } + public System.Collections.Generic.IList Enum { get; } + public System.Text.Json.Nodes.JsonNode Example { get; } + public System.Collections.Generic.IList Examples { get; } + public bool? ExclusiveMaximum { get; } + public bool? ExclusiveMinimum { get; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + public string Format { get; } + public string Id { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; } + public int? MaxItems { get; } + public int? MaxLength { get; } + public int? MaxProperties { get; } + public decimal? Maximum { get; } + public int? MinItems { get; } + public int? MinLength { get; } + public int? MinProperties { get; } + public decimal? Minimum { get; } + public decimal? MultipleOf { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; } + public System.Collections.Generic.IList OneOf { get; } + public string Pattern { get; } + public System.Collections.Generic.IDictionary PatternProperties { get; } + public System.Collections.Generic.IDictionary Properties { get; } + public bool ReadOnly { get; } + public System.Collections.Generic.ISet Required { get; } + public string Schema { get; } + public string Title { get; } + public Microsoft.OpenApi.Models.JsonSchemaType? Type { get; } + public bool UnEvaluatedProperties { get; } + public bool UnevaluatedProperties { get; } + public bool? UniqueItems { get; } + public System.Collections.Generic.IDictionary UnrecognizedKeywords { get; } + public decimal? V31ExclusiveMaximum { get; } + public decimal? V31ExclusiveMinimum { get; } + public System.Collections.Generic.IDictionary Vocabulary { get; } + public bool WriteOnly { get; } + public Microsoft.OpenApi.Models.OpenApiXml Xml { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiTagReference : Microsoft.OpenApi.Models.OpenApiTag, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSecuritySchemeReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme { - public OpenApiTagReference(Microsoft.OpenApi.Models.References.OpenApiTagReference source) { } - public OpenApiTagReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public Microsoft.OpenApi.Models.OpenApiTag Target { get; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public override string Name { get; set; } - public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public OpenApiSecuritySchemeReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public string BearerFormat { get; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; } + public Microsoft.OpenApi.Models.ParameterLocation? In { get; } + public string Name { get; } + public System.Uri OpenIdConnectUrl { get; } + public string Scheme { get; } + public Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme CreateShallowCopy() { } + } + public class OpenApiTagReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiReadOnlyDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiTag + { + public OpenApiTagReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public string Description { get; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + public string Name { get; } + public override Microsoft.OpenApi.Models.OpenApiTag Target { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiTag CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiTag source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiTag CreateShallowCopy() { } } } namespace Microsoft.OpenApi.Reader @@ -1318,7 +1463,7 @@ namespace Microsoft.OpenApi.Reader { public OpenApiJsonReader() { } public Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings) { } - public Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null) { } + public Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings) { } public System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, System.Threading.CancellationToken cancellationToken = default) { } public T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, Microsoft.OpenApi.Models.OpenApiDocument openApiDocument, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } @@ -1461,11 +1606,11 @@ namespace Microsoft.OpenApi.Services public System.Collections.Generic.IDictionary Children { get; } public bool IsParameter { get; } public string Path { get; set; } - public System.Collections.Generic.IDictionary PathItems { get; } + public System.Collections.Generic.IDictionary PathItems { get; } public string Segment { get; } public void AddAdditionalData(System.Collections.Generic.Dictionary> additionalData) { } public void Attach(Microsoft.OpenApi.Models.OpenApiDocument doc, string label) { } - public Microsoft.OpenApi.Services.OpenApiUrlTreeNode Attach(string path, Microsoft.OpenApi.Models.OpenApiPathItem pathItem, string label) { } + public Microsoft.OpenApi.Services.OpenApiUrlTreeNode Attach(string path, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem, string label) { } public bool HasOperations(string label) { } public void WriteMermaid(System.IO.TextWriter writer) { } public static Microsoft.OpenApi.Services.OpenApiUrlTreeNode Create() { } @@ -1480,45 +1625,45 @@ namespace Microsoft.OpenApi.Services public virtual void Exit() { } public virtual void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtensible openApiExtensible) { } public virtual void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtension openApiExtension) { } - public virtual void Visit(Microsoft.OpenApi.Interfaces.IOpenApiReferenceable referenceable) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiCallback callback) { } + public virtual void Visit(Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder referenceHolder) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback callback) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample example) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader header) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiLink link) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter parameter) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme securityScheme) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiEncoding encoding) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiExample example) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiExternalDocs externalDocs) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiHeader header) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiInfo info) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiLicense license) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiLink link) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiMediaType mediaType) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiOAuthFlow openApiOAuthFlow) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiParameter parameter) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiPathItem pathItem) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiRequestBody requestBody) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiResponse response) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiServer server) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiServerVariable serverVariable) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiTag tag) { } public virtual void Visit(Microsoft.OpenApi.Models.References.OpenApiTagReference tag) { } public virtual void Visit(System.Collections.Generic.IDictionary operations) { } - public virtual void Visit(System.Collections.Generic.IDictionary callbacks) { } + public virtual void Visit(System.Collections.Generic.IDictionary callbacks) { } + public virtual void Visit(System.Collections.Generic.IDictionary examples) { } + public virtual void Visit(System.Collections.Generic.IDictionary headers) { } + public virtual void Visit(System.Collections.Generic.IDictionary links) { } + public virtual void Visit(System.Collections.Generic.IDictionary webhooks) { } public virtual void Visit(System.Collections.Generic.IDictionary encodings) { } - public virtual void Visit(System.Collections.Generic.IDictionary examples) { } - public virtual void Visit(System.Collections.Generic.IDictionary headers) { } - public virtual void Visit(System.Collections.Generic.IDictionary links) { } public virtual void Visit(System.Collections.Generic.IDictionary content) { } - public virtual void Visit(System.Collections.Generic.IDictionary webhooks) { } public virtual void Visit(System.Collections.Generic.IDictionary serverVariables) { } - public virtual void Visit(System.Collections.Generic.IList example) { } - public virtual void Visit(System.Collections.Generic.IList parameters) { } + public virtual void Visit(System.Collections.Generic.IList example) { } + public virtual void Visit(System.Collections.Generic.IList parameters) { } public virtual void Visit(System.Collections.Generic.IList openApiSecurityRequirements) { } public virtual void Visit(System.Collections.Generic.IList servers) { } public virtual void Visit(System.Collections.Generic.IList openApiTags) { } @@ -1548,15 +1693,15 @@ namespace Microsoft.OpenApi.Services { public OperationSearch(System.Func predicate) { } public System.Collections.Generic.IList SearchResults { get; } - public override void Visit(Microsoft.OpenApi.Models.OpenApiPathItem pathItem) { } - public override void Visit(System.Collections.Generic.IList parameters) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } + public override void Visit(System.Collections.Generic.IList parameters) { } } public class SearchResult { public SearchResult() { } public Microsoft.OpenApi.Services.CurrentKeys CurrentKeys { get; set; } public Microsoft.OpenApi.Models.OpenApiOperation Operation { get; set; } - public System.Collections.Generic.IList Parameters { get; set; } + public System.Collections.Generic.IList Parameters { get; set; } } } namespace Microsoft.OpenApi.Validations @@ -1580,41 +1725,41 @@ namespace Microsoft.OpenApi.Validations public void AddWarning(Microsoft.OpenApi.Validations.OpenApiValidatorWarning warning) { } public override void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtensible openApiExtensible) { } public override void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtension openApiExtension) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiCallback callback) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback callback) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample example) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader header) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiLink link) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter parameter) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme securityScheme) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiEncoding encoding) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiExample example) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiExternalDocs externalDocs) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiHeader header) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiInfo info) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiLicense license) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiLink link) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiMediaType mediaType) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiOAuthFlow openApiOAuthFlow) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiParameter parameter) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiPathItem pathItem) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiRequestBody requestBody) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiResponse response) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiServer server) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiServerVariable serverVariable) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiTag tag) { } public override void Visit(System.Collections.Generic.IDictionary operations) { } - public override void Visit(System.Collections.Generic.IDictionary callbacks) { } + public override void Visit(System.Collections.Generic.IDictionary callbacks) { } + public override void Visit(System.Collections.Generic.IDictionary examples) { } + public override void Visit(System.Collections.Generic.IDictionary headers) { } + public override void Visit(System.Collections.Generic.IDictionary links) { } public override void Visit(System.Collections.Generic.IDictionary encodings) { } - public override void Visit(System.Collections.Generic.IDictionary examples) { } - public override void Visit(System.Collections.Generic.IDictionary headers) { } - public override void Visit(System.Collections.Generic.IDictionary links) { } public override void Visit(System.Collections.Generic.IDictionary content) { } public override void Visit(System.Collections.Generic.IDictionary serverVariables) { } - public override void Visit(System.Collections.Generic.IList example) { } + public override void Visit(System.Collections.Generic.IList example) { } } public class OpenApiValidatorError : Microsoft.OpenApi.Models.OpenApiError { @@ -1703,10 +1848,10 @@ namespace Microsoft.OpenApi.Validations.Rules } public static class OpenApiNonDefaultRules { - public static Microsoft.OpenApi.Validations.ValidationRule HeaderMismatchedDataType { get; } + public static Microsoft.OpenApi.Validations.ValidationRule HeaderMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule MediaTypeMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule ParameterMismatchedDataType { get; } - public static Microsoft.OpenApi.Validations.ValidationRule SchemaMismatchedDataType { get; } + public static Microsoft.OpenApi.Validations.ValidationRule SchemaMismatchedDataType { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiOAuthFlowRules @@ -1716,9 +1861,9 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiParameterRules { - public static Microsoft.OpenApi.Validations.ValidationRule ParameterRequiredFields { get; } - public static Microsoft.OpenApi.Validations.ValidationRule PathParameterShouldBeInThePath { get; } - public static Microsoft.OpenApi.Validations.ValidationRule RequiredMustBeTrueWhenInIsPath { get; } + public static Microsoft.OpenApi.Validations.ValidationRule ParameterRequiredFields { get; } + public static Microsoft.OpenApi.Validations.ValidationRule PathParameterShouldBeInThePath { get; } + public static Microsoft.OpenApi.Validations.ValidationRule RequiredMustBeTrueWhenInIsPath { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiPathsRules @@ -1729,7 +1874,7 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiResponseRules { - public static Microsoft.OpenApi.Validations.ValidationRule ResponseRequiredFields { get; } + public static Microsoft.OpenApi.Validations.ValidationRule ResponseRequiredFields { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiResponsesRules @@ -1745,9 +1890,9 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiSchemaRules { - public static Microsoft.OpenApi.Validations.ValidationRule ValidateSchemaDiscriminator { get; } - public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList childSchema) { } - public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.Models.OpenApiSchema schema, string discriminatorName) { } + public static Microsoft.OpenApi.Validations.ValidationRule ValidateSchemaDiscriminator { get; } + public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList childSchema) { } + public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema, string discriminatorName) { } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiServerRules diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs index 09ef9b04d..33296cfed6 100644 --- a/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs @@ -18,14 +18,14 @@ public class OpenApiUrlTreeNodeTests { Paths = new() { - ["/"] = new() + ["/"] = new OpenApiPathItem() { Operations = new Dictionary { [OperationType.Get] = new(), } }, - ["/houses"] = new() + ["/houses"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -33,7 +33,7 @@ public class OpenApiUrlTreeNodeTests [OperationType.Post] = new() } }, - ["/cars"] = new() + ["/cars"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -47,9 +47,9 @@ public class OpenApiUrlTreeNodeTests { Paths = new() { - ["/"] = new(), - ["/hotels"] = new(), - ["/offices"] = new() + ["/"] = new OpenApiPathItem(), + ["/hotels"] = new OpenApiPathItem(), + ["/offices"] = new OpenApiPathItem() } }; @@ -68,7 +68,7 @@ public void CreateSingleRootWorks() { Paths = new() { - ["/"] = new() + ["/"] = new OpenApiPathItem() } }; @@ -88,7 +88,7 @@ public void CreatePathWithoutRootWorks() { Paths = new() { - ["/houses"] = new() + ["/houses"] = new OpenApiPathItem() } }; @@ -157,7 +157,7 @@ public void AttachPathWorks() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entities" } @@ -182,7 +182,7 @@ public void AttachPathWorks() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entities" } @@ -211,9 +211,9 @@ public void CreatePathsWithMultipleSegmentsWorks() { Paths = new() { - ["/"] = new(), - ["/houses/apartments/{apartment-id}"] = new(), - ["/cars/coupes"] = new() + ["/"] = new OpenApiPathItem(), + ["/houses/apartments/{apartment-id}"] = new OpenApiPathItem(), + ["/cars/coupes"] = new OpenApiPathItem() } }; @@ -236,9 +236,9 @@ public void HasOperationsWorks() { Paths = new() { - ["/"] = new(), - ["/houses"] = new(), - ["/cars/{car-id}"] = new() + ["/"] = new OpenApiPathItem(), + ["/houses"] = new OpenApiPathItem(), + ["/cars/{car-id}"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -249,7 +249,7 @@ public void HasOperationsWorks() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entity" } @@ -266,7 +266,7 @@ public void HasOperationsWorks() { Paths = new() { - ["/cars/{car-id}"] = new() + ["/cars/{car-id}"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -277,7 +277,7 @@ public void HasOperationsWorks() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entity" } @@ -292,7 +292,7 @@ public void HasOperationsWorks() Responses = new() { { - "204", new() + "204", new OpenApiResponse() { Description = "Success." } @@ -330,8 +330,8 @@ public void SegmentIsParameterWorks() { Paths = new() { - ["/"] = new(), - ["/houses/apartments/{apartment-id}"] = new() + ["/"] = new OpenApiPathItem(), + ["/houses/apartments/{apartment-id}"] = new OpenApiPathItem() } }; @@ -482,7 +482,7 @@ public void SupportsTrailingSlashesInPath(string path, string[] childrenBeforeLa { Paths = new() { - [path] = new() + [path] = new OpenApiPathItem() } }; diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs index ca56ff75c..d11786d5b 100644 --- a/test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs @@ -23,28 +23,30 @@ public class OpenApiValidatorTests [Fact] public void ResponseMustHaveADescription() { - var openApiDocument = new OpenApiDocument(); - openApiDocument.Info = new() - { - Title = "foo", - Version = "1.2.2" - }; - openApiDocument.Paths = new() + var openApiDocument = new OpenApiDocument { + Info = new() + { + Title = "foo", + Version = "1.2.2" + }, + Paths = new() { - "/test", - new() - { - Operations = { - [OperationType.Get] = new() + "/test", + new OpenApiPathItem() { - Responses = + Operations = + { + [OperationType.Get] = new() { - ["200"] = new() + Responses = + { + ["200"] = new OpenApiResponse() + } } } - } + } } } }; diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiComponentsValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiComponentsValidationTests.cs index fe2a230e2..de83299fc 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiComponentsValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiComponentsValidationTests.cs @@ -5,6 +5,7 @@ using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Validations.Rules; using Xunit; @@ -21,7 +22,7 @@ public void ValidateKeyMustMatchRegularExpressionInComponents() var components = new OpenApiComponents { - Responses = new Dictionary + Responses = new Dictionary { { key, new OpenApiResponse { Description = "any" } } } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs index 3a685f3a8..6c96c3d97 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Validations.Rules; using Xunit; @@ -17,7 +18,6 @@ public class OpenApiHeaderValidationTests public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() { // Arrange - IEnumerable errors; var header = new OpenApiHeader { Required = true, @@ -30,18 +30,14 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() // Act var defaultRuleSet = ValidationRuleSet.GetDefaultRuleSet(); - defaultRuleSet.Add(typeof(OpenApiHeader), OpenApiNonDefaultRules.HeaderMismatchedDataType); + defaultRuleSet.Add(typeof(IOpenApiHeader), OpenApiNonDefaultRules.HeaderMismatchedDataType); var validator = new OpenApiValidator(defaultRuleSet); var walker = new OpenApiWalker(validator); - walker.Walk(header); - - errors = validator.Errors; - var warnings = validator.Warnings; - var result = !warnings.Any(); + walker.Walk((IOpenApiHeader)header); // Assert - Assert.False(result); + Assert.NotEmpty(validator.Warnings); } [Fact] @@ -63,11 +59,11 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() }, Examples = { - ["example0"] = new() + ["example0"] = new OpenApiExample() { Value = "1", }, - ["example1"] = new() + ["example1"] = new OpenApiExample() { Value = new JsonObject() { @@ -76,11 +72,11 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() ["z"] = "200" } }, - ["example2"] = new() + ["example2"] = new OpenApiExample() { Value = new JsonArray(){3} }, - ["example3"] = new() + ["example3"] = new OpenApiExample() { Value = new JsonObject() { diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs index 834443135..05b4bb62c 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs @@ -20,7 +20,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() var mediaType = new OpenApiMediaType { Example = 55, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -47,21 +47,21 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() var mediaType = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer, } }, Examples = { - ["example0"] = new() + ["example0"] = new OpenApiExample() { Value = "1", }, - ["example1"] = new() + ["example1"] = new OpenApiExample() { Value = new JsonObject() { @@ -70,11 +70,11 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() ["z"] = "200" } }, - ["example2"] = new() + ["example2"] = new OpenApiExample() { Value = new JsonArray(){3} }, - ["example3"] = new() + ["example3"] = new OpenApiExample() { Value = new JsonObject() { diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs index cacf3d7fa..721445e23 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs @@ -6,6 +6,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Validations.Rules; @@ -49,7 +50,7 @@ public void ValidateRequiredIsTrueWhenInIsPathInParameter() var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); validator.Enter("{name}"); var walker = new OpenApiWalker(validator); - walker.Walk(parameter); + walker.Walk((IOpenApiParameter)parameter); var errors = validator.Errors; // Assert Assert.NotEmpty(errors); @@ -70,7 +71,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() In = ParameterLocation.Path, Required = true, Example = 55, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -93,28 +94,26 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() { // Arrange - IEnumerable warnings; - var parameter = new OpenApiParameter { Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer, } }, Examples = { - ["example0"] = new() + ["example0"] = new OpenApiExample() { Value = "1", }, - ["example1"] = new() + ["example1"] = new OpenApiExample() { Value = new JsonObject() { @@ -123,11 +122,11 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() ["z"] = "200" } }, - ["example2"] = new() + ["example2"] = new OpenApiExample() { Value = new JsonArray(){3} }, - ["example3"] = new() + ["example3"] = new OpenApiExample() { Value = new JsonObject() { @@ -140,32 +139,27 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() // Act var defaultRuleSet = ValidationRuleSet.GetDefaultRuleSet(); - defaultRuleSet.Add(typeof(OpenApiParameter), OpenApiNonDefaultRules.ParameterMismatchedDataType); + defaultRuleSet.Add(typeof(IOpenApiParameter), OpenApiNonDefaultRules.ParameterMismatchedDataType); var validator = new OpenApiValidator(defaultRuleSet); validator.Enter("{parameter1}"); var walker = new OpenApiWalker(validator); - walker.Walk(parameter); - - warnings = validator.Warnings; - var result = !warnings.Any(); + walker.Walk((IOpenApiParameter)parameter); // Assert - Assert.False(result); + Assert.NotEmpty(validator.Warnings); } [Fact] public void PathParameterNotInThePathShouldReturnAnError() { // Arrange - IEnumerable errors; - var parameter = new OpenApiParameter { Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -175,21 +169,18 @@ public void PathParameterNotInThePathShouldReturnAnError() var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); var walker = new OpenApiWalker(validator); - walker.Walk(parameter); - - errors = validator.Errors; - var result = errors.Any(); + walker.Walk((IOpenApiParameter)parameter); // Assert - Assert.True(result); + Assert.NotEmpty(validator.Errors); Assert.Equivalent(new[] { "PathParameterShouldBeInThePath" - }, errors.OfType().Select(e => e.RuleName)); + }, validator.Errors.OfType().Select(e => e.RuleName)); Assert.Equivalent(new[] { "#/in" - }, errors.Select(e => e.Pointer)); + }, validator.Errors.Select(e => e.Pointer)); } [Fact] @@ -203,7 +194,7 @@ public void PathParameterInThePathShouldBeOk() Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs index b7597cb31..b9a73da40 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs @@ -6,6 +6,8 @@ using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Validations; using Xunit; @@ -21,17 +23,12 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() var sharedSchema = new OpenApiSchema { Type = JsonSchemaType.String, - Reference = new() - { - Id = "test" - }, - UnresolvedReference = false }; var document = new OpenApiDocument(); document.Components = new() { - Schemas = new Dictionary() + Schemas = new Dictionary() { ["test"] = sharedSchema } @@ -39,7 +36,7 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() document.Paths = new() { - ["/"] = new() + ["/"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -47,13 +44,13 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() { Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary { ["application/json"] = new() { - Schema = sharedSchema + Schema = new OpenApiSchemaReference("test") } } } @@ -66,8 +63,8 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() // Act var rules = new Dictionary>() { - { typeof(OpenApiSchema), - new List() { new AlwaysFailRule() } + { typeof(IOpenApiSchema), + new List() { new AlwaysFailRule() } } }; @@ -75,7 +72,7 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() // Assert - Assert.True(errors.Count() == 1); + Assert.Single(errors); } [Fact] @@ -86,18 +83,14 @@ public void UnresolvedSchemaReferencedShouldNotBeValidated() var sharedSchema = new OpenApiSchema { Type = JsonSchemaType.String, - Reference = new() - { - Id = "test" - }, - UnresolvedReference = true }; var document = new OpenApiDocument(); + document.AddComponent("test", sharedSchema); document.Paths = new() { - ["/"] = new() + ["/"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -105,13 +98,13 @@ public void UnresolvedSchemaReferencedShouldNotBeValidated() { Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary { ["application/json"] = new() { - Schema = sharedSchema + Schema = new OpenApiSchemaReference("test") } } } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiResponseValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiResponseValidationTests.cs index c1b4ce62d..2350c184b 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiResponseValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiResponseValidationTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Services; using Xunit; @@ -22,15 +23,15 @@ public void ValidateDescriptionIsRequiredInResponse() // Act var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); var walker = new OpenApiWalker(validator); - walker.Walk(response); + walker.Walk((IOpenApiResponse)response); errors = validator.Errors; - var result = !errors.Any(); // Assert - Assert.False(result); + Assert.NotEmpty(errors); Assert.NotNull(errors); - var error = Assert.Single(errors) as OpenApiValidatorError; + Assert.Single(errors); + var error = Assert.IsType(errors.First()); Assert.Equal(string.Format(SRResource.Validation_FieldIsRequired, "description", "response"), error.Message); Assert.Equal("#/description", error.Pointer); } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs index 9edd57c1e..d8820defc 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs @@ -7,6 +7,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Validations.Rules; @@ -89,7 +90,7 @@ public void ValidateEnumShouldNotHaveDataTypeMismatchForSimpleSchema() }).Node }, Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -111,39 +112,38 @@ public void ValidateEnumShouldNotHaveDataTypeMismatchForSimpleSchema() public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() { // Arrange - IEnumerable warnings; var schema = new OpenApiSchema { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } }, - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "password" }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -173,22 +173,18 @@ public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() // Act var defaultRuleSet = ValidationRuleSet.GetDefaultRuleSet(); - defaultRuleSet.Add(typeof(OpenApiSchema), OpenApiNonDefaultRules.SchemaMismatchedDataType); + defaultRuleSet.Add(typeof(IOpenApiSchema), OpenApiNonDefaultRules.SchemaMismatchedDataType); var validator = new OpenApiValidator(defaultRuleSet); var walker = new OpenApiWalker(validator); - walker.Walk(schema); - - warnings = validator.Warnings; - bool result = !warnings.Any(); + walker.Walk((IOpenApiSchema)schema); // Assert - Assert.False(result); + Assert.NotEmpty(validator.Warnings); } [Fact] public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator() { - IEnumerable errors; var components = new OpenApiComponents { Schemas = { @@ -198,7 +194,6 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD { Type = JsonSchemaType.Object, Discriminator = new() { PropertyName = "property1" }, - Reference = new() { Id = "schema1" } } } } @@ -208,17 +203,14 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD var walker = new OpenApiWalker(validator); walker.Walk(components); - errors = validator.Errors; - var result = !errors.Any(); - // Assert - Assert.False(result); + Assert.NotEmpty(validator.Errors); Assert.Equivalent(new List { new OpenApiValidatorError(nameof(OpenApiSchemaRules.ValidateSchemaDiscriminator),"#/schemas/schema1/discriminator", string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator, - "schema1", "property1")) - }, errors); + string.Empty, "property1")) + }, validator.Errors); } [Fact] @@ -238,9 +230,9 @@ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscrim { PropertyName = "type" }, - OneOf = new List + OneOf = new List { - new() + new OpenApiSchema() { Properties = { @@ -252,14 +244,8 @@ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscrim } } }, - Reference = new() - { - Type = ReferenceType.Schema, - Id = "Person" - } } }, - Reference = new() { Id = "Person" } } } } diff --git a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs index e805d4673..581f2998a 100644 --- a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Xunit; @@ -25,43 +26,43 @@ public void ExpectedVirtualsInvolved() visitor.Visit(default(IList)); visitor.Visit(default(OpenApiServer)); visitor.Visit(default(OpenApiPaths)); - visitor.Visit(default(OpenApiPathItem)); + visitor.Visit(default(IOpenApiPathItem)); visitor.Visit(default(OpenApiServerVariable)); visitor.Visit(default(IDictionary)); visitor.Visit(default(OpenApiOperation)); - visitor.Visit(default(IList)); - visitor.Visit(default(OpenApiParameter)); - visitor.Visit(default(OpenApiRequestBody)); - visitor.Visit(default(IDictionary)); - visitor.Visit(default(IDictionary)); - visitor.Visit(default(OpenApiResponse)); + visitor.Visit(default(IList)); + visitor.Visit(default(IOpenApiParameter)); + visitor.Visit(default(IOpenApiRequestBody)); + visitor.Visit(default(IDictionary)); + visitor.Visit(default(IDictionary)); + visitor.Visit(default(IOpenApiResponse)); visitor.Visit(default(OpenApiResponses)); visitor.Visit(default(IDictionary)); visitor.Visit(default(OpenApiMediaType)); visitor.Visit(default(OpenApiEncoding)); - visitor.Visit(default(IDictionary)); + visitor.Visit(default(IDictionary)); visitor.Visit(default(OpenApiComponents)); visitor.Visit(default(OpenApiExternalDocs)); - visitor.Visit(default(OpenApiSchema)); - visitor.Visit(default(IDictionary)); - visitor.Visit(default(OpenApiLink)); - visitor.Visit(default(OpenApiCallback)); + visitor.Visit(default(IOpenApiSchema)); + visitor.Visit(default(IDictionary)); + visitor.Visit(default(IOpenApiLink)); + visitor.Visit(default(IOpenApiCallback)); visitor.Visit(default(OpenApiTag)); - visitor.Visit(default(OpenApiHeader)); + visitor.Visit(default(IOpenApiHeader)); visitor.Visit(default(OpenApiOAuthFlow)); visitor.Visit(default(OpenApiSecurityRequirement)); - visitor.Visit(default(OpenApiSecurityScheme)); - visitor.Visit(default(OpenApiExample)); + visitor.Visit(default(IOpenApiSecurityScheme)); + visitor.Visit(default(IOpenApiExample)); visitor.Visit(default(IList)); visitor.Visit(default(IList)); visitor.Visit(default(IOpenApiExtensible)); visitor.Visit(default(IOpenApiExtension)); - visitor.Visit(default(IList)); + visitor.Visit(default(IList)); visitor.Visit(default(IDictionary)); visitor.Visit(default(IDictionary)); - visitor.Visit(default(IOpenApiReferenceable)); + visitor.Visit(default(IOpenApiReferenceHolder)); visitor.Exit(); - Assert.True(42 < ((TestVisitor)visitor).CallStack.Count()); + Assert.True(42 < ((TestVisitor)visitor).CallStack.Count); } internal protected class TestVisitor : OpenApiVisitorBase @@ -129,7 +130,7 @@ public override void Visit(OpenApiPaths paths) base.Visit(paths); } - public override void Visit(OpenApiPathItem pathItem) + public override void Visit(IOpenApiPathItem pathItem) { EncodeCall(); base.Visit(pathItem); @@ -153,37 +154,37 @@ public override void Visit(OpenApiOperation operation) base.Visit(operation); } - public override void Visit(IList parameters) + public override void Visit(IList parameters) { EncodeCall(); base.Visit(parameters); } - public override void Visit(OpenApiParameter parameter) + public override void Visit(IOpenApiParameter parameter) { EncodeCall(); base.Visit(parameter); } - public override void Visit(OpenApiRequestBody requestBody) + public override void Visit(IOpenApiRequestBody requestBody) { EncodeCall(); base.Visit(requestBody); } - public override void Visit(IDictionary headers) + public override void Visit(IDictionary headers) { EncodeCall(); base.Visit(headers); } - public override void Visit(IDictionary callbacks) + public override void Visit(IDictionary callbacks) { EncodeCall(); base.Visit(callbacks); } - public override void Visit(OpenApiResponse response) + public override void Visit(IOpenApiResponse response) { EncodeCall(); base.Visit(response); @@ -213,7 +214,7 @@ public override void Visit(OpenApiEncoding encoding) base.Visit(encoding); } - public override void Visit(IDictionary examples) + public override void Visit(IDictionary examples) { EncodeCall(); base.Visit(examples); @@ -231,25 +232,25 @@ public override void Visit(OpenApiExternalDocs externalDocs) base.Visit(externalDocs); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { EncodeCall(); base.Visit(schema); } - public override void Visit(IDictionary links) + public override void Visit(IDictionary links) { EncodeCall(); base.Visit(links); } - public override void Visit(OpenApiLink link) + public override void Visit(IOpenApiLink link) { EncodeCall(); base.Visit(link); } - public override void Visit(OpenApiCallback callback) + public override void Visit(IOpenApiCallback callback) { EncodeCall(); base.Visit(callback); @@ -261,7 +262,7 @@ public override void Visit(OpenApiTag tag) base.Visit(tag); } - public override void Visit(OpenApiHeader header) + public override void Visit(IOpenApiHeader header) { EncodeCall(); base.Visit(header); @@ -279,13 +280,13 @@ public override void Visit(OpenApiSecurityRequirement securityRequirement) base.Visit(securityRequirement); } - public override void Visit(OpenApiSecurityScheme securityScheme) + public override void Visit(IOpenApiSecurityScheme securityScheme) { EncodeCall(); base.Visit(securityScheme); } - public override void Visit(OpenApiExample example) + public override void Visit(IOpenApiExample example) { EncodeCall(); base.Visit(example); @@ -315,7 +316,7 @@ public override void Visit(IOpenApiExtension openApiExtension) base.Visit(openApiExtension); } - public override void Visit(IList example) + public override void Visit(IList example) { EncodeCall(); base.Visit(example); @@ -333,7 +334,7 @@ public override void Visit(IDictionary encodings) base.Visit(encodings); } - public override void Visit(IOpenApiReferenceable referenceable) + public override void Visit(IOpenApiReferenceHolder referenceable) { EncodeCall(); base.Visit(referenceable); diff --git a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs index f90d058b2..ce45186c6 100644 --- a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Xunit; @@ -65,7 +67,7 @@ public void LocateTopLevelArrayItems() public void LocatePathOperationContentSchema() { var doc = new OpenApiDocument(); - doc.Paths.Add("/test", new() + doc.Paths.Add("/test", new OpenApiPathItem() { Operations = new Dictionary { @@ -73,7 +75,7 @@ public void LocatePathOperationContentSchema() { Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary { @@ -120,9 +122,9 @@ public void WalkDOMWithCycles() var loopySchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["name"] = new() { Type = JsonSchemaType.String } + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String } } }; @@ -132,7 +134,7 @@ public void WalkDOMWithCycles() { Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { ["loopy"] = loopySchema } @@ -160,34 +162,24 @@ public void WalkDOMWithCycles() [Fact] public void LocateReferences() { - var baseSchema = new OpenApiSchemaReference("base", null); + var baseSchema = new OpenApiSchema(); var derivedSchema = new OpenApiSchema { - AnyOf = new List { baseSchema }, - Reference = new() - { - Id = "derived", - Type = ReferenceType.Schema - }, - UnresolvedReference = false + AnyOf = new List { new OpenApiSchemaReference("base") }, }; + var testHeader = new OpenApiHeader() { - Schema = derivedSchema, - Reference = new() - { - Id = "test-header", - Type = ReferenceType.Header - }, - UnresolvedReference = false + Schema = new OpenApiSchemaReference("derived"), }; + var testHeaderReference = new OpenApiHeaderReference("test-header"); var doc = new OpenApiDocument { Paths = new() { - ["/"] = new() + ["/"] = new OpenApiPathItem() { Operations = new Dictionary { @@ -195,18 +187,18 @@ public void LocateReferences() { Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary { ["application/json"] = new() { - Schema = derivedSchema + Schema = new OpenApiSchemaReference("derived") } }, - Headers = new Dictionary + Headers = { - ["test-header"] = testHeader + ["test-header"] = testHeaderReference } } } @@ -216,18 +208,18 @@ public void LocateReferences() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { ["derived"] = derivedSchema, ["base"] = baseSchema, }, - Headers = new Dictionary + Headers = { ["test-header"] = testHeader }, - SecuritySchemes = new Dictionary + SecuritySchemes = new Dictionary { - ["test-secScheme"] = new OpenApiSecuritySchemeReference("reference-to-scheme", null, null) + ["test-secScheme"] = new OpenApiSecuritySchemeReference("reference-to-scheme") } } }; @@ -238,11 +230,11 @@ public void LocateReferences() Assert.Equivalent(new List { "referenceAt: #/paths/~1/get/responses/200/content/application~1json/schema", - "referenceAt: #/paths/~1/get/responses/200/headers/test-header/schema", + "referenceAt: #/paths/~1/get/responses/200/headers/test-header", "referenceAt: #/components/schemas/derived/anyOf/0", "referenceAt: #/components/securitySchemes/test-secScheme", "referenceAt: #/components/headers/test-header/schema" - }, locator.Locations.Where(l => l.StartsWith("referenceAt:"))); + }, locator.Locations.Where(l => l.StartsWith("referenceAt:", StringComparison.OrdinalIgnoreCase))); } } @@ -271,7 +263,7 @@ public override void Visit(OpenApiPaths paths) Locations.Add(this.PathString); } - public override void Visit(OpenApiPathItem pathItem) + public override void Visit(IOpenApiPathItem pathItem) { Keys.Add(CurrentKeys.Path); Locations.Add(this.PathString); @@ -287,13 +279,13 @@ public override void Visit(OpenApiOperation operation) Keys.Add(CurrentKeys.Operation.ToString()); Locations.Add(this.PathString); } - public override void Visit(OpenApiResponse response) + public override void Visit(IOpenApiResponse response) { Keys.Add(CurrentKeys.Response); Locations.Add(this.PathString); } - public override void Visit(IOpenApiReferenceable referenceable) + public override void Visit(IOpenApiReferenceHolder referenceable) { Locations.Add("referenceAt: " + this.PathString); } @@ -308,7 +300,7 @@ public override void Visit(OpenApiMediaType mediaType) Locations.Add(this.PathString); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { Locations.Add(this.PathString); } diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiReferencableTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiReferencableTests.cs index f93b10375..167d5e359 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiReferencableTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiReferencableTests.cs @@ -20,7 +20,7 @@ public class OpenApiReferencableTests private static readonly OpenApiHeader _headerFragment = new() { Schema = new OpenApiSchema(), - Examples = new Dictionary + Examples = { { "example1", new OpenApiExample() } } @@ -28,7 +28,7 @@ public class OpenApiReferencableTests private static readonly OpenApiParameter _parameterFragment = new() { Schema = new OpenApiSchema(), - Examples = new Dictionary + Examples = { { "example1", new OpenApiExample() } } @@ -36,11 +36,11 @@ public class OpenApiReferencableTests private static readonly OpenApiRequestBody _requestBodyFragment = new(); private static readonly OpenApiResponse _responseFragment = new() { - Headers = new Dictionary + Headers = { { "header1", new OpenApiHeader() } }, - Links = new Dictionary + Links = { { "link1", new OpenApiLink() } } diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs index f8bde4f85..8c5478cf7 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Xunit; @@ -15,11 +16,16 @@ public class OpenApiWorkspaceTests [Fact] public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() { + var testSchema = new OpenApiSchema() + { + Type = JsonSchemaType.String, + Description = "The referenced one" + }; var doc = new OpenApiDocument() { Paths = new OpenApiPaths() { - ["/"] = new() + ["/"] = new OpenApiPathItem() { Operations = new Dictionary() { @@ -27,20 +33,13 @@ public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() { Responses = new OpenApiResponses() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary() { ["application/json"] = new OpenApiMediaType() { - Schema = new() - { - Reference = new() - { - Id = "test", - Type = ReferenceType.Schema - } - } + Schema = new OpenApiSchemaReference("test") } } } @@ -56,11 +55,7 @@ public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() Components = new OpenApiComponents() { Schemas = { - ["test"] = new() - { - Type = JsonSchemaType.String, - Description = "The referenced one" - } + ["test"] = testSchema } } }; @@ -73,11 +68,11 @@ public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() [Fact] public void OpenApiWorkspacesCanResolveExternalReferences() { - var refUri = new Uri("https://everything.json/common#/components/schemas/test"); var workspace = new OpenApiWorkspace(); var externalDoc = CreateCommonDocument(); - workspace.RegisterComponent("https://everything.json/common#/components/schemas/test", externalDoc.Components.Schemas["test"]); + var castSchema = Assert.IsType(externalDoc.Components.Schemas["test"]); + workspace.RegisterComponent("https://everything.json/common#/components/schemas/test", castSchema); var schema = workspace.ResolveReference("https://everything.json/common#/components/schemas/test"); @@ -112,7 +107,7 @@ public void OpenApiWorkspacesCanResolveReferencesToDocumentFragmentsWithJsonPoin var workspace = new OpenApiWorkspace(); var responseFragment = new OpenApiResponse { - Headers = new Dictionary + Headers = { { "header1", new OpenApiHeader() } } @@ -136,7 +131,7 @@ private static OpenApiDocument CreateCommonDocument() { Schemas = { - ["test"] = new() + ["test"] = new OpenApiSchema() { Type = JsonSchemaType.String, Description = "The referenced one" diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs index a26173606..2e05a70a3 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs @@ -113,7 +113,7 @@ public async Task WriteOpenApiFloatAsJsonWorksAsync(float input, bool produceTer var json = await WriteAsJsonAsync(floatValue, produceTerseOutput); // Assert - Assert.Equal(input.ToString(), json); + Assert.Equal(input.ToString(CultureInfo.InvariantCulture), json); } public static IEnumerable DoubleInputs @@ -141,7 +141,7 @@ public async Task WriteOpenApiDoubleAsJsonWorksAsync(double input, bool produceT var json = await WriteAsJsonAsync(doubleValue, produceTerseOutput); // Assert - Assert.Equal(input.ToString(), json); + Assert.Equal(input.ToString(CultureInfo.InvariantCulture), json); } public static IEnumerable StringifiedDateTimes @@ -149,7 +149,7 @@ public static IEnumerable StringifiedDateTimes get { return - from input in new [] { + from input in new[] { "2017-1-2", "1999-01-02T12:10:22", "1999-01-03", @@ -178,7 +178,7 @@ public async Task WriteOpenApiDateTimeAsJsonWorksAsync(string inputString, bool public static IEnumerable BooleanInputs { get => - from input in new [] { true, false } + from input in new[] { true, false } from shouldBeTerse in shouldProduceTerseOutputValues select new object[] { input, shouldBeTerse }; } @@ -258,7 +258,7 @@ private static async Task WriteAsJsonAsync(JsonNode any, bool produceTer // Arrange (continued) using var stream = new MemoryStream(); var writer = new OpenApiJsonWriter( - new StreamWriter(stream), + new CultureInvariantStreamWriter(stream), new() { Terse = produceTerseOutput }); writer.WriteAny(any); @@ -279,5 +279,15 @@ private static async Task WriteAsJsonAsync(JsonNode any, bool produceTer _ => value.MakeLineBreaksEnvironmentNeutral(), }; } + + private class CultureInvariantStreamWriter : StreamWriter + { + public CultureInvariantStreamWriter(Stream stream) : base(stream) + { + } + + public override IFormatProvider FormatProvider => CultureInfo.InvariantCulture; + } + } } diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs index 2210cce59..669f4cb13 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs @@ -8,6 +8,7 @@ using System.IO; using System.Threading.Tasks; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using Xunit; @@ -441,12 +442,6 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() var thingSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - UnresolvedReference = false, - Reference = new() - { - Id = "thing", - Type = ReferenceType.Schema - } }; var doc = new OpenApiDocument() @@ -458,20 +453,20 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() }, Paths = new() { - ["/"] = new() + ["/"] = new OpenApiPathItem() { Operations = { [OperationType.Get] = new() { Responses = { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "OK", Content = { - ["application/json"] = new() - { - Schema = thingSchema - } + ["application/json"] = new() + { + Schema = new OpenApiSchemaReference("thing") + } } } } @@ -485,6 +480,8 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() ["thing"] = thingSchema} } }; + doc.RegisterComponents(); + doc.SetReferenceHostDocument(); return doc; }