diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceableWithTarget.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceableWithTarget.cs
new file mode 100644
index 000000000..fc4c1daed
--- /dev/null
+++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceableWithTarget.cs
@@ -0,0 +1,17 @@
+// 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/Models/References/OpenApiCallbackReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs
index 632aa485f..81985cb12 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs
@@ -12,12 +12,20 @@ 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
+ public class OpenApiCallbackReference : OpenApiCallback, IOpenApiReferenceableWithTarget
{
+#nullable enable
internal OpenApiCallback _target;
private readonly OpenApiReference _reference;
- private OpenApiCallback Target
+ ///
+ /// Gets the target callback.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiCallback Target
+#nullable restore
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs
index 310ff0a8e..c36c43d9a 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs
@@ -12,14 +12,20 @@ namespace Microsoft.OpenApi.Models.References
///
/// Example Object Reference.
///
- public class OpenApiExampleReference : OpenApiExample
+ public class OpenApiExampleReference : OpenApiExample, IOpenApiReferenceableWithTarget
{
internal OpenApiExample _target;
private readonly OpenApiReference _reference;
private string _summary;
private string _description;
- private OpenApiExample Target
+ ///
+ /// Gets the target example.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiExample Target
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs
index 2ffb0c3de..e8275c23c 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs
@@ -12,13 +12,19 @@ namespace Microsoft.OpenApi.Models.References
///
/// Header Object Reference.
///
- public class OpenApiHeaderReference : OpenApiHeader
+ public class OpenApiHeaderReference : OpenApiHeader, IOpenApiReferenceableWithTarget
{
internal OpenApiHeader _target;
private readonly OpenApiReference _reference;
private string _description;
- private OpenApiHeader Target
+ ///
+ /// Gets the target header.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiHeader Target
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs
index a3c33503e..05817ddc9 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs
@@ -11,13 +11,19 @@ namespace Microsoft.OpenApi.Models.References
///
/// Link Object Reference.
///
- public class OpenApiLinkReference : OpenApiLink
+ public class OpenApiLinkReference : OpenApiLink, IOpenApiReferenceableWithTarget
{
internal OpenApiLink _target;
private readonly OpenApiReference _reference;
private string _description;
- private OpenApiLink Target
+ ///
+ /// Gets the target link.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiLink Target
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs
index 2c2a6c90d..9df1e7be2 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs
@@ -12,7 +12,7 @@ namespace Microsoft.OpenApi.Models.References
///
/// Parameter Object Reference.
///
- public class OpenApiParameterReference : OpenApiParameter
+ public class OpenApiParameterReference : OpenApiParameter, IOpenApiReferenceableWithTarget
{
internal OpenApiParameter _target;
private readonly OpenApiReference _reference;
@@ -20,7 +20,13 @@ public class OpenApiParameterReference : OpenApiParameter
private bool? _explode;
private ParameterStyle? _style;
- private OpenApiParameter Target
+ ///
+ /// Gets the target parameter.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiParameter Target
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs
index f757b7a07..fad8922ae 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs
@@ -11,14 +11,20 @@ namespace Microsoft.OpenApi.Models.References
///
/// Path Item Object Reference: to describe the operations available on a single path.
///
- public class OpenApiPathItemReference : OpenApiPathItem
+ public class OpenApiPathItemReference : OpenApiPathItem, IOpenApiReferenceableWithTarget
{
internal OpenApiPathItem _target;
private readonly OpenApiReference _reference;
private string _description;
private string _summary;
- private OpenApiPathItem Target
+ ///
+ /// Gets the target path item.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiPathItem Target
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs
index 8e3a81ad8..598d70310 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs
@@ -11,13 +11,19 @@ namespace Microsoft.OpenApi.Models.References
///
/// Request Body Object Reference.
///
- public class OpenApiRequestBodyReference : OpenApiRequestBody
+ public class OpenApiRequestBodyReference : OpenApiRequestBody, IOpenApiReferenceableWithTarget
{
internal OpenApiRequestBody _target;
private readonly OpenApiReference _reference;
private string _description;
- private OpenApiRequestBody Target
+ ///
+ /// Gets the target request body.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiRequestBody Target
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs
index c24652504..0e4ac30ac 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs
@@ -11,13 +11,19 @@ namespace Microsoft.OpenApi.Models.References
///
/// Response Object Reference.
///
- public class OpenApiResponseReference : OpenApiResponse
+ public class OpenApiResponseReference : OpenApiResponse, IOpenApiReferenceableWithTarget
{
internal OpenApiResponse _target;
private readonly OpenApiReference _reference;
private string _description;
- private OpenApiResponse Target
+ ///
+ /// Gets the target response.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiResponse Target
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs
index 41a1dceb5..da2f9b745 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs
@@ -12,9 +12,9 @@ namespace Microsoft.OpenApi.Models.References
///
/// Schema reference object
///
- public class OpenApiSchemaReference : OpenApiSchema
+ public class OpenApiSchemaReference : OpenApiSchema, IOpenApiReferenceableWithTarget
{
- #nullable enable
+#nullable enable
private OpenApiSchema? _target;
private readonly OpenApiReference _reference;
private string? _description;
@@ -69,8 +69,14 @@ public class OpenApiSchemaReference : OpenApiSchema
private bool? _unevaluatedProperties;
private IList? _enum;
- private OpenApiSchema? Target
- #nullable restore
+ ///
+ /// Gets the target schema.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiSchema? Target
+#nullable restore
{
get
{
@@ -190,7 +196,7 @@ public override string Description
///
public override bool? UniqueItems { get => _uniqueItems is not null ? _uniqueItems : Target?.UniqueItems; set => _uniqueItems = value; }
///
- public override IDictionary Properties { get => _properties is not null ? _properties : Target?.Properties ; set => _properties = value; }
+ public override IDictionary Properties { get => _properties is not null ? _properties : Target?.Properties; set => _properties = value; }
///
public override IDictionary PatternProperties { get => _patternProperties is not null ? _patternProperties : Target?.PatternProperties; set => _patternProperties = value; }
///
@@ -257,7 +263,7 @@ public override void SerializeAsV3(IOpenApiWriter writer)
_reference.SerializeAsV3(writer);
return;
}
-
+
SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer));
writer.GetSettings().LoopDetector.PopLoop();
}
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs
index faf6ae3bc..dcd5009b1 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs
@@ -11,13 +11,19 @@ namespace Microsoft.OpenApi.Models.References
///
/// Security Scheme Object Reference.
///
- public class OpenApiSecuritySchemeReference : OpenApiSecurityScheme
+ public class OpenApiSecuritySchemeReference : OpenApiSecurityScheme, IOpenApiReferenceableWithTarget
{
internal OpenApiSecurityScheme _target;
private readonly OpenApiReference _reference;
private string _description;
- private OpenApiSecurityScheme Target
+ ///
+ /// Gets the target security scheme.
+ ///
+ ///
+ /// If the reference is not resolved, this will return null.
+ ///
+ public OpenApiSecurityScheme Target
{
get
{
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs
index ddf7ad4e2..ae15b4085 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs
@@ -12,7 +12,7 @@ namespace Microsoft.OpenApi.Models.References
///
/// Tag Object Reference
///
- public class OpenApiTagReference : OpenApiTag, IOpenApiReferenceable
+ public class OpenApiTagReference : OpenApiTag, IOpenApiReferenceableWithTarget
{
internal OpenApiTag _target;
diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs
index 73bb667b6..22f1c5ad3 100644
--- a/src/Microsoft.OpenApi/Services/CopyReferences.cs
+++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs
@@ -4,183 +4,248 @@
using System.Collections.Generic;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
-namespace Microsoft.OpenApi.Services
+namespace Microsoft.OpenApi.Services;
+internal class CopyReferences(OpenApiDocument target) : OpenApiVisitorBase
{
- internal class CopyReferences : 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)
{
- private readonly OpenApiDocument _target;
- public OpenApiComponents Components = new();
-
- public CopyReferences(OpenApiDocument target)
+ switch (referenceable)
{
- _target = target;
+ case OpenApiSchemaReference openApiSchemaReference:
+ AddSchemaToComponents(openApiSchemaReference.Target, openApiSchemaReference.Reference.Id);
+ break;
+ case OpenApiSchema schema:
+ AddSchemaToComponents(schema);
+ break;
+ case OpenApiParameterReference openApiParameterReference:
+ AddParameterToComponents(openApiParameterReference.Target, openApiParameterReference.Reference.Id);
+ break;
+ case OpenApiParameter parameter:
+ AddParameterToComponents(parameter);
+ break;
+ case OpenApiResponseReference openApiResponseReference:
+ AddResponseToComponents(openApiResponseReference.Target, openApiResponseReference.Reference.Id);
+ break;
+ case OpenApiResponse response:
+ AddResponseToComponents(response);
+ break;
+ case OpenApiRequestBodyReference openApiRequestBodyReference:
+ AddRequestBodyToComponents(openApiRequestBodyReference.Target, openApiRequestBodyReference.Reference.Id);
+ break;
+ case OpenApiRequestBody requestBody:
+ AddRequestBodyToComponents(requestBody);
+ break;
+ case OpenApiExampleReference openApiExampleReference:
+ AddExampleToComponents(openApiExampleReference.Target, openApiExampleReference.Reference.Id);
+ break;
+ case OpenApiExample example:
+ AddExampleToComponents(example);
+ break;
+ case OpenApiHeaderReference openApiHeaderReference:
+ AddHeaderToComponents(openApiHeaderReference.Target, openApiHeaderReference.Reference.Id);
+ break;
+ case OpenApiHeader header:
+ AddHeaderToComponents(header);
+ break;
+ case OpenApiCallbackReference openApiCallbackReference:
+ AddCallbackToComponents(openApiCallbackReference.Target, openApiCallbackReference.Reference.Id);
+ break;
+ case OpenApiCallback callback:
+ AddCallbackToComponents(callback);
+ break;
+ case OpenApiLinkReference openApiLinkReference:
+ AddLinkToComponents(openApiLinkReference.Target, openApiLinkReference.Reference.Id);
+ break;
+ case OpenApiLink link:
+ AddLinkToComponents(link);
+ break;
+ case OpenApiSecuritySchemeReference openApiSecuritySchemeReference:
+ AddSecuritySchemeToComponents(openApiSecuritySchemeReference.Target, openApiSecuritySchemeReference.Reference.Id);
+ break;
+ case OpenApiSecurityScheme securityScheme:
+ AddSecuritySchemeToComponents(securityScheme);
+ break;
+ case OpenApiPathItemReference openApiPathItemReference:
+ AddPathItemToComponents(openApiPathItemReference.Target, openApiPathItemReference.Reference.Id);
+ break;
+ case OpenApiPathItem pathItem:
+ AddPathItemToComponents(pathItem);
+ break;
+ default:
+ break;
}
- ///
- /// Visits IOpenApiReferenceable instances that are references and not in components.
- ///
- /// An IOpenApiReferenceable object.
- public override void Visit(IOpenApiReferenceable referenceable)
+ base.Visit(referenceable);
+ }
+
+ private void AddSchemaToComponents(OpenApiSchema schema, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureSchemasExist();
+ if (!Components.Schemas.ContainsKey(referenceId ?? schema.Reference.Id))
{
- switch (referenceable)
- {
- case OpenApiSchema schema:
- EnsureComponentsExist();
- EnsureSchemasExist();
- if (!Components.Schemas.ContainsKey(schema.Reference.Id))
- {
- Components.Schemas.Add(schema.Reference.Id, schema);
- }
- break;
-
- case OpenApiParameter parameter:
- EnsureComponentsExist();
- EnsureParametersExist();
- if (!Components.Parameters.ContainsKey(parameter.Reference.Id))
- {
- Components.Parameters.Add(parameter.Reference.Id, parameter);
- }
- break;
-
- case OpenApiResponse response:
- EnsureComponentsExist();
- EnsureResponsesExist();
- if (!Components.Responses.ContainsKey(response.Reference.Id))
- {
- Components.Responses.Add(response.Reference.Id, response);
- }
- break;
-
- case OpenApiRequestBody requestBody:
- EnsureComponentsExist();
- EnsureResponsesExist();
- EnsureRequestBodiesExist();
- if (!Components.RequestBodies.ContainsKey(requestBody.Reference.Id))
- {
- Components.RequestBodies.Add(requestBody.Reference.Id, requestBody);
- }
- break;
-
- case OpenApiExample example:
- EnsureComponentsExist();
- EnsureExamplesExist();
- if (!Components.Examples.ContainsKey(example.Reference.Id))
- {
- Components.Examples.Add(example.Reference.Id, example);
- }
- break;
-
- case OpenApiHeader header:
- EnsureComponentsExist();
- EnsureHeadersExist();
- if (!Components.Headers.ContainsKey(header.Reference.Id))
- {
- Components.Headers.Add(header.Reference.Id, header);
- }
- break;
-
- case OpenApiCallback callback:
- EnsureComponentsExist();
- EnsureCallbacksExist();
- if (!Components.Callbacks.ContainsKey(callback.Reference.Id))
- {
- Components.Callbacks.Add(callback.Reference.Id, callback);
- }
- break;
-
- case OpenApiLink link:
- EnsureComponentsExist();
- EnsureLinksExist();
- if (!Components.Links.ContainsKey(link.Reference.Id))
- {
- Components.Links.Add(link.Reference.Id, link);
- }
- break;
-
- case OpenApiSecurityScheme securityScheme:
- EnsureComponentsExist();
- EnsureSecuritySchemesExist();
- if (!Components.SecuritySchemes.ContainsKey(securityScheme.Reference.Id))
- {
- Components.SecuritySchemes.Add(securityScheme.Reference.Id, securityScheme);
- }
- break;
-
- default:
- break;
- }
-
- base.Visit(referenceable);
+ Components.Schemas.Add(referenceId ?? schema.Reference.Id, schema);
}
+ }
- ///
- /// Visits
- ///
- /// The OpenApiSchema to be visited.
- public override void Visit(OpenApiSchema schema)
+ private void AddParameterToComponents(OpenApiParameter parameter, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureParametersExist();
+ if (!Components.Parameters.ContainsKey(referenceId ?? parameter.Reference.Id))
{
- // This is needed to handle schemas used in Responses in components
- if (schema.Reference != null)
- {
- EnsureComponentsExist();
- EnsureSchemasExist();
- if (!Components.Schemas.ContainsKey(schema.Reference.Id))
- {
- Components.Schemas.Add(schema.Reference.Id, schema);
- }
- }
- base.Visit(schema);
+ Components.Parameters.Add(referenceId ?? parameter.Reference.Id, parameter);
}
+ }
- private void EnsureComponentsExist()
+ private void AddResponseToComponents(OpenApiResponse response, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureResponsesExist();
+ if (!Components.Responses.ContainsKey(referenceId ?? response.Reference.Id))
{
- _target.Components ??= new();
+ Components.Responses.Add(referenceId ?? response.Reference.Id, response);
}
-
- private void EnsureSchemasExist()
+ }
+ private void AddRequestBodyToComponents(OpenApiRequestBody requestBody, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureRequestBodiesExist();
+ if (!Components.RequestBodies.ContainsKey(referenceId ?? requestBody.Reference.Id))
{
- _target.Components.Schemas ??= new Dictionary();
+ Components.RequestBodies.Add(referenceId ?? requestBody.Reference.Id, requestBody);
}
-
- private void EnsureParametersExist()
+ }
+ private void AddLinkToComponents(OpenApiLink link, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureLinksExist();
+ if (!Components.Links.ContainsKey(referenceId ?? link.Reference.Id))
{
- _target.Components.Parameters ??= new Dictionary();
+ Components.Links.Add(referenceId ?? link.Reference.Id, link);
}
-
- private void EnsureResponsesExist()
+ }
+ private void AddCallbackToComponents(OpenApiCallback callback, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureCallbacksExist();
+ if (!Components.Callbacks.ContainsKey(referenceId ?? callback.Reference.Id))
{
- _target.Components.Responses ??= new Dictionary();
+ Components.Callbacks.Add(referenceId ?? callback.Reference.Id, callback);
}
-
- private void EnsureRequestBodiesExist()
+ }
+ private void AddHeaderToComponents(OpenApiHeader header, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureHeadersExist();
+ if (!Components.Headers.ContainsKey(referenceId ?? header.Reference.Id))
{
- _target.Components.RequestBodies ??= new Dictionary();
+ Components.Headers.Add(referenceId ?? header.Reference.Id, header);
}
-
- private void EnsureExamplesExist()
+ }
+ private void AddExampleToComponents(OpenApiExample example, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureExamplesExist();
+ if (!Components.Examples.ContainsKey(referenceId ?? example.Reference.Id))
{
- _target.Components.Examples ??= new Dictionary();
+ Components.Examples.Add(referenceId ?? example.Reference.Id, example);
}
-
- private void EnsureHeadersExist()
+ }
+ private void AddPathItemToComponents(OpenApiPathItem pathItem, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsurePathItemsExist();
+ if (!Components.PathItems.ContainsKey(referenceId ?? pathItem.Reference.Id))
{
- _target.Components.Headers ??= new Dictionary();
+ Components.PathItems.Add(referenceId ?? pathItem.Reference.Id, pathItem);
}
-
- private void EnsureCallbacksExist()
+ }
+ private void AddSecuritySchemeToComponents(OpenApiSecurityScheme securityScheme, string referenceId = null)
+ {
+ EnsureComponentsExist();
+ EnsureSecuritySchemesExist();
+ if (!Components.SecuritySchemes.ContainsKey(referenceId ?? securityScheme.Reference.Id))
{
- _target.Components.Callbacks ??= new Dictionary();
+ Components.SecuritySchemes.Add(referenceId ?? securityScheme.Reference.Id, securityScheme);
}
+ }
- private void EnsureLinksExist()
+ ///
+ public override void Visit(OpenApiSchema schema)
+ {
+ // This is needed to handle schemas used in Responses in components
+ if (schema is OpenApiSchemaReference openApiSchemaReference)
{
- _target.Components.Links ??= new Dictionary();
+ AddSchemaToComponents(openApiSchemaReference.Target, openApiSchemaReference.Reference.Id);
}
-
- private void EnsureSecuritySchemesExist()
+ else if (schema.Reference != null)
{
- _target.Components.SecuritySchemes ??= new Dictionary();
+ AddSchemaToComponents(schema);
}
+ base.Visit(schema);
+ }
+
+ private void EnsureComponentsExist()
+ {
+ _target.Components ??= new();
+ }
+
+ private void EnsureSchemasExist()
+ {
+ _target.Components.Schemas ??= new Dictionary();
+ }
+
+ private void EnsureParametersExist()
+ {
+ _target.Components.Parameters ??= new Dictionary();
+ }
+
+ private void EnsureResponsesExist()
+ {
+ _target.Components.Responses ??= new Dictionary();
+ }
+
+ private void EnsureRequestBodiesExist()
+ {
+ _target.Components.RequestBodies ??= new Dictionary();
+ }
+
+ private void EnsureExamplesExist()
+ {
+ _target.Components.Examples ??= new Dictionary();
+ }
+
+ private void EnsureHeadersExist()
+ {
+ _target.Components.Headers ??= new Dictionary();
+ }
+
+ private void EnsureCallbacksExist()
+ {
+ _target.Components.Callbacks ??= new Dictionary();
+ }
+
+ private void EnsureLinksExist()
+ {
+ _target.Components.Links ??= new Dictionary();
+ }
+
+ private void EnsureSecuritySchemesExist()
+ {
+ _target.Components.SecuritySchemes ??= new Dictionary();
+ }
+ private void EnsurePathItemsExist()
+ {
+ _target.Components.PathItems ??= new Dictionary();
}
}
diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterSettings.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterSettings.cs
index 3ff128ae6..e6364affa 100644
--- a/src/Microsoft.OpenApi/Writers/OpenApiWriterSettings.cs
+++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterSettings.cs
@@ -24,10 +24,5 @@ internal bool ShouldInlineReference(OpenApiReference reference)
return (reference.IsLocal && InlineLocalReferences)
|| (reference.IsExternal && InlineExternalReferences);
}
-
- internal bool ShouldInlineReference()
- {
- return InlineLocalReferences || InlineExternalReferences;
- }
}
}
diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs
index 70eca5e9e..d7fef6396 100644
--- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs
+++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs
@@ -19,7 +19,7 @@ namespace Microsoft.OpenApi.Tests.Models.References
public class OpenApiHeaderReferenceTests
{
// OpenApi doc with external $ref
- private const string OpenApi= @"
+ private const string OpenApi = @"
openapi: 3.0.0
info:
title: Sample API
@@ -149,7 +149,7 @@ public async Task SerializeHeaderReferenceAsV2JsonWorksAsync(bool produceTerseOu
{
// 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 = true });
// Act
_localHeaderReference.SerializeAsV2(writer);
@@ -158,5 +158,34 @@ public async Task SerializeHeaderReferenceAsV2JsonWorksAsync(bool produceTerseOu
// Assert
await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput);
}
+
+ [Fact]
+ public void OpenApiHeaderTargetShouldResolveReference()
+ {
+ var doc = new OpenApiDocument
+ {
+ Components = new OpenApiComponents
+ {
+ Headers = new System.Collections.Generic.Dictionary
+ {
+ { "header1", new OpenApiHeader
+ {
+ Description = "test header",
+ Schema = new OpenApiSchema
+ {
+ Type = JsonSchemaType.String
+ }
+ }
+ }
+ }
+ }
+ };
+
+ doc.Workspace.RegisterComponents(doc);
+
+ var headerReference = new OpenApiHeaderReference("header1", doc);
+ Assert.Equal("test header", headerReference.Description);
+ Assert.Equal(JsonSchemaType.String, headerReference.Schema.Type);
+ }
}
}
diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
index fe5ad5bad..887fb3db8 100644
--- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
+++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
@@ -223,6 +223,10 @@ namespace Microsoft.OpenApi.Interfaces
Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; }
bool UnresolvedReference { get; set; }
}
+ public interface IOpenApiReferenceableWithTarget : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
+ {
+ T Target { get; }
+ }
public interface IOpenApiSerializable : Microsoft.OpenApi.Interfaces.IOpenApiElement
{
void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer);
@@ -1096,17 +1100,19 @@ namespace Microsoft.OpenApi.Models
}
namespace Microsoft.OpenApi.Models.References
{
- public class OpenApiCallbackReference : Microsoft.OpenApi.Models.OpenApiCallback
+ 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 class OpenApiExampleReference : Microsoft.OpenApi.Models.OpenApiExample
+ public class OpenApiExampleReference : Microsoft.OpenApi.Models.OpenApiExample, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
{
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; }
@@ -1115,9 +1121,10 @@ namespace Microsoft.OpenApi.Models.References
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
+ 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; }
@@ -1134,9 +1141,10 @@ namespace Microsoft.OpenApi.Models.References
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
+ 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; }
@@ -1147,9 +1155,10 @@ namespace Microsoft.OpenApi.Models.References
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
+ 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; }
@@ -1168,9 +1177,10 @@ namespace Microsoft.OpenApi.Models.References
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
+ public class OpenApiPathItemReference : Microsoft.OpenApi.Models.OpenApiPathItem, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
{
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; }
@@ -1179,9 +1189,10 @@ namespace Microsoft.OpenApi.Models.References
public override string Summary { get; set; }
public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
}
- public class OpenApiRequestBodyReference : Microsoft.OpenApi.Models.OpenApiRequestBody
+ public class OpenApiRequestBodyReference : Microsoft.OpenApi.Models.OpenApiRequestBody, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
{
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; }
@@ -1189,9 +1200,10 @@ namespace Microsoft.OpenApi.Models.References
public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
}
- public class OpenApiResponseReference : Microsoft.OpenApi.Models.OpenApiResponse
+ public class OpenApiResponseReference : Microsoft.OpenApi.Models.OpenApiResponse, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
{
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; }
@@ -1201,9 +1213,10 @@ namespace Microsoft.OpenApi.Models.References
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
+ 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; }
@@ -1259,9 +1272,10 @@ namespace Microsoft.OpenApi.Models.References
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
+ 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; }
@@ -1275,7 +1289,7 @@ namespace Microsoft.OpenApi.Models.References
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.IOpenApiSerializable
+ public class OpenApiTagReference : Microsoft.OpenApi.Models.OpenApiTag, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiReferenceableWithTarget, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
{
public OpenApiTagReference(Microsoft.OpenApi.Models.References.OpenApiTagReference source) { }
public OpenApiTagReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument) { }