Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix/tag reference #2109

Open
wants to merge 2 commits into
base: fix/security-scheme-reference
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,15 @@ public interface IOpenApiDescribedElement : IOpenApiElement
/// </summary>
public string Description { get; set; }
}

/// <summary>
/// Describes an element that has a description.
/// </summary>
public interface IOpenApiReadOnlyDescribedElement : IOpenApiElement
{
/// <summary>
/// Long description for the example.
/// CommonMark syntax MAY be used for rich text representation.
/// </summary>
public string Description { get; }
}
20 changes: 20 additions & 0 deletions src/Microsoft.OpenApi/Models/Interfaces/IOpenApiTag.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Microsoft.OpenApi.Interfaces;

namespace Microsoft.OpenApi.Models.Interfaces;

/// <summary>
/// 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.
/// </summary>
public interface IOpenApiTag : IOpenApiSerializable, IOpenApiReadOnlyExtensible, IOpenApiReadOnlyDescribedElement
{
/// <summary>
/// The name of the tag.
/// </summary>
public string Name { get; }

/// <summary>
/// Additional external documentation for this tag.
/// </summary>
public OpenApiExternalDocs ExternalDocs { get; }
}
45 changes: 16 additions & 29 deletions src/Microsoft.OpenApi/Models/OpenApiTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,48 @@
using System;
using System.Collections.Generic;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Writers;

namespace Microsoft.OpenApi.Models
{
/// <summary>
/// Tag Object.
/// </summary>
public class OpenApiTag : IOpenApiReferenceable, IOpenApiExtensible
public class OpenApiTag : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiTag, IOpenApiDescribedElement
{
/// <summary>
/// The name of the tag.
/// </summary>
public virtual string Name { get; set; }
/// <inheritdoc/>
public string Name { get; set; }

/// <summary>
/// A short description for the tag.
/// </summary>
public virtual string Description { get; set; }
/// <inheritdoc/>
public string Description { get; set; }

/// <summary>
/// Additional external documentation for this tag.
/// </summary>
public virtual OpenApiExternalDocs ExternalDocs { get; set; }
/// <inheritdoc/>
public OpenApiExternalDocs ExternalDocs { get; set; }

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

/// <summary>
/// Indicates if object is populated with data or is just a reference to the data
/// </summary>
public bool UnresolvedReference { get; set; }
/// <inheritdoc/>
public IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();

/// <summary>
/// Parameterless constructor
/// </summary>
public OpenApiTag() { }

/// <summary>
/// Initializes a copy of an <see cref="OpenApiTag"/> object
/// Initializes a copy of an <see cref="IOpenApiTag"/> object
/// </summary>
public OpenApiTag(OpenApiTag tag)
public 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<string, IOpenApiExtension>(tag.Extensions) : null;
UnresolvedReference = tag?.UnresolvedReference ?? UnresolvedReference;
}

/// <summary>
/// Serialize <see cref="OpenApiTag"/> to Open Api v3.1
/// </summary>
public virtual void SerializeAsV31(IOpenApiWriter writer)
public void SerializeAsV31(IOpenApiWriter writer)
{
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1,
(writer, element) => element.SerializeAsV31(writer));
Expand All @@ -67,13 +54,13 @@ public virtual void SerializeAsV31(IOpenApiWriter writer)
/// <summary>
/// Serialize <see cref="OpenApiTag"/> to Open Api v3.0
/// </summary>
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<IOpenApiWriter, IOpenApiSerializable> callback)
{
writer.WriteStartObject();
Expand All @@ -96,7 +83,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio
/// <summary>
/// Serialize <see cref="OpenApiTag"/> to Open Api v2.0
/// </summary>
public virtual void SerializeAsV2(IOpenApiWriter writer)
public void SerializeAsV2(IOpenApiWriter writer)
{
writer.WriteStartObject();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ namespace Microsoft.OpenApi.Models.References;
/// <typeparam name="V">The interface type for the model.</typeparam>
public abstract class BaseOpenApiReferenceHolder<T, V> : IOpenApiReferenceHolder<T, V> where T : class, IOpenApiReferenceable, V where V : IOpenApiSerializable
{
private T _target;
/// <summary>
/// The resolved target object.
/// </summary>
protected T _target;
/// <inheritdoc/>
public T Target
public virtual T Target
{
get
{
Expand Down
86 changes: 13 additions & 73 deletions src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,19 @@
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
{
/// <summary>
/// Tag Object Reference
/// </summary>
public class OpenApiTagReference : OpenApiTag, IOpenApiReferenceHolder<OpenApiTag>
public class OpenApiTagReference : BaseOpenApiReferenceHolder<OpenApiTag, IOpenApiTag>, IOpenApiTag
{
internal OpenApiTag _target;

/// <summary>
/// Reference.
/// </summary>
public OpenApiReference Reference { get; set; }

/// <summary>
/// Resolved target of the reference.
/// </summary>
public OpenApiTag Target
public override OpenApiTag Target
{
get
{
Expand All @@ -38,85 +31,32 @@ public OpenApiTag Target
/// </summary>
/// <param name="referenceId">The reference Id.</param>
/// <param name="hostDocument">The host OpenAPI document.</param>
public OpenApiTagReference(string referenceId, OpenApiDocument hostDocument)
public OpenApiTagReference(string referenceId, OpenApiDocument hostDocument):base(referenceId, hostDocument, ReferenceType.Tag)
{
Utils.CheckArgumentNullOrEmpty(referenceId);

Reference = new OpenApiReference()
{
Id = referenceId,
HostDocument = hostDocument,
Type = ReferenceType.Tag
};
}

/// <summary>
/// Copy Constructor
/// </summary>
/// <param name="source">The source to copy information from.</param>
public OpenApiTagReference(OpenApiTagReference source):base()
internal OpenApiTagReference(OpenApiTag target, string referenceId):base(target, referenceId, ReferenceType.Tag)
{
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.";
/// <inheritdoc/>
public override string Description { get => Target.Description; set => throw new InvalidOperationException(ReferenceErrorMessage); }

/// <inheritdoc/>
public override OpenApiExternalDocs ExternalDocs { get => Target.ExternalDocs; set => throw new InvalidOperationException(ReferenceErrorMessage); }

/// <inheritdoc/>
public override IDictionary<string, IOpenApiExtension> Extensions { get => Target.Extensions; set => throw new InvalidOperationException(ReferenceErrorMessage); }

/// <inheritdoc/>
public override string Name { get => Target.Name; set => throw new InvalidOperationException(ReferenceErrorMessage); }

/// <inheritdoc/>
public override void SerializeAsV3(IOpenApiWriter writer)
public string Description
{
if (!writer.GetSettings().ShouldInlineReference(Reference))
{
Reference.SerializeAsV3(writer);
}
else
{
SerializeInternal(writer);
}
get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description;
}

/// <inheritdoc/>
public override void SerializeAsV31(IOpenApiWriter writer)
{
if (!writer.GetSettings().ShouldInlineReference(Reference))
{
Reference.SerializeAsV31(writer);
}
else
{
SerializeInternal(writer);
}
}
public OpenApiExternalDocs ExternalDocs { get => Target?.ExternalDocs; }

/// <inheritdoc/>
public override void SerializeAsV2(IOpenApiWriter writer)
{
if (!writer.GetSettings().ShouldInlineReference(Reference))
{
Reference.SerializeAsV2(writer);
}
else
{
SerializeInternal(writer);
}
}
public IDictionary<string, IOpenApiExtension> Extensions { get => Target?.Extensions; }

/// <inheritdoc/>
private void SerializeInternal(IOpenApiWriter writer)
public string Name { get => Target?.Name; }
/// <inheritdoc/>
public override IOpenApiTag CopyReferenceAsTargetElementWithOverrides(IOpenApiTag source)
{
Utils.CheckArgumentNull(writer);
writer.WriteValue(Name);
return source is OpenApiTag ? new OpenApiTag(this) : source;
}
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 2 additions & 1 deletion test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,7 +31,7 @@ public class OpenApiTagTests
}
};

public static OpenApiTag ReferencedTag = new OpenApiTagReference("pet", null);
public static IOpenApiTag ReferencedTag = new OpenApiTagReference(AdvancedTag, "pet");

[Theory]
[InlineData(true)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ public void TagReferenceResolutionWorks()
// Assert
Assert.Equal("user", _openApiTagReference.Name);
Assert.Equal("Operations about users.", _openApiTagReference.Description);
Assert.Throws<InvalidOperationException>(() => _openApiTagReference.Description = "New Description");
}

[Theory]
Expand Down
Loading
Loading