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/reference proxy single copy #2031

Merged
merged 15 commits into from
Jan 7, 2025
1 change: 0 additions & 1 deletion src/Microsoft.OpenApi/Models/OpenApiComponents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.Writers;
Expand Down
15 changes: 15 additions & 0 deletions src/Microsoft.OpenApi/Models/OpenApiDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,21 @@ public static ReadResult Parse(string input,
{
return OpenApiModelFactory.Parse(input, format, settings);
}
/// <summary>
/// Adds a schema to the components object of the current document.
/// </summary>
/// <param name="openApiSchema">The schema to add</param>
/// <param name="id">The id for the component</param>
/// <returns>Whether the schema was added to the components.</returns>
public bool AddComponentSchema(string id, OpenApiSchema openApiSchema)
baywet marked this conversation as resolved.
Show resolved Hide resolved
{
Utils.CheckArgumentNull(openApiSchema);
Utils.CheckArgumentNullOrEmpty(id);
Components ??= new();
Components.Schemas ??= new Dictionary<string, OpenApiSchema>();
Components.Schemas.Add(id, openApiSchema);
return Workspace?.RegisterSchemaForDocument(this, openApiSchema, id) ?? false;
}
}

internal class FindSchemaReferences : OpenApiVisitorBase
Expand Down
180 changes: 107 additions & 73 deletions src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,68 @@ namespace Microsoft.OpenApi.Models.References
/// </summary>
public class OpenApiSchemaReference : OpenApiSchema
{
internal OpenApiSchema _target;
#nullable enable
private OpenApiSchema? _target;
private readonly OpenApiReference _reference;
private string _description;
private JsonNode _default;
private JsonNode _example;
private IList<JsonNode> _examples;
private string? _description;
private JsonNode? _default;
private JsonNode? _example;
private IList<JsonNode>? _examples;
private bool? _nullable;
private IDictionary<string, OpenApiSchema>? _properties;
private string? _title;
private string? _schema;
private string? _comment;
private string? _id;
private string? _dynamicRef;
private string? _dynamicAnchor;
private IDictionary<string, bool>? _vocabulary;
private IDictionary<string, OpenApiSchema>? _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<OpenApiSchema>? _allOf;
private IList<OpenApiSchema>? _oneOf;
private IList<OpenApiSchema>? _anyOf;
private OpenApiSchema? _not;
private ISet<string>? _required;
private OpenApiSchema _items;
private int? _maxItems;
private int? _minItems;
private bool? _uniqueItems;
private IDictionary<string, OpenApiSchema>? _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<string, IOpenApiExtension>? _extensions;
private bool? _unevaluatedProperties;
private IList<JsonNode>? _enum;

private OpenApiSchema Target
private OpenApiSchema? Target
#nullable restore
{
get
{
_target ??= Reference.HostDocument?.ResolveReferenceTo<OpenApiSchema>(_reference);
OpenApiSchema resolved = new OpenApiSchema(_target);
if (!string.IsNullOrEmpty(_description)) resolved.Description = _description;
return resolved;
return _target;
}
}

Expand Down Expand Up @@ -69,123 +116,111 @@ internal OpenApiSchemaReference(OpenApiSchema target, string referenceId)
}

/// <inheritdoc/>
public override string Title { get => Target.Title; set => Target.Title = value; }
public override string Title { get => string.IsNullOrEmpty(_title) ? Target?.Title : _title; set => _title = value; }
/// <inheritdoc/>
public override string Schema { get => Target.Schema; set => Target.Schema = value; }
public override string Schema { get => string.IsNullOrEmpty(_schema) ? Target?.Schema : _schema; set => _schema = value; }
/// <inheritdoc/>
public override string Id { get => Target.Id; set => Target.Id = value; }
public override string Id { get => string.IsNullOrEmpty(_id) ? Target?.Id : _id; set => _id = value; }
/// <inheritdoc/>
public override string Comment { get => Target.Comment; set => Target.Comment = value; }
public override string Comment { get => string.IsNullOrEmpty(_comment) ? Target?.Comment : _comment; set => _comment = value; }
/// <inheritdoc/>
public override IDictionary<string, bool> Vocabulary { get => Target.Vocabulary; set => Target.Vocabulary = value; }
public override IDictionary<string, bool> Vocabulary { get => _vocabulary is not null ? _vocabulary : Target?.Vocabulary; set => _vocabulary = value; }
/// <inheritdoc/>
public override string DynamicRef { get => Target.DynamicRef; set => Target.DynamicRef = value; }
public override string DynamicRef { get => string.IsNullOrEmpty(_dynamicRef) ? Target?.DynamicRef : _dynamicRef; set => _dynamicRef = value; }
/// <inheritdoc/>
public override string DynamicAnchor { get => Target.DynamicAnchor; set => Target.DynamicAnchor = value; }
public override string DynamicAnchor { get => string.IsNullOrEmpty(_dynamicAnchor) ? Target?.DynamicAnchor : _dynamicAnchor; set => _dynamicAnchor = value; }
/// <inheritdoc/>
public override IDictionary<string, OpenApiSchema> Definitions { get => Target.Definitions; set => Target.Definitions = value; }
public override IDictionary<string, OpenApiSchema> Definitions { get => _definitions is not null ? _definitions : Target?.Definitions; set => _definitions = value; }
/// <inheritdoc/>
public override decimal? V31ExclusiveMaximum { get => Target.V31ExclusiveMaximum; set => Target.V31ExclusiveMaximum = value; }
public override decimal? V31ExclusiveMaximum { get => _v31ExclusiveMaximum is not null ? _v31ExclusiveMaximum.Value : Target?.V31ExclusiveMaximum; set => _v31ExclusiveMaximum = value; }
/// <inheritdoc/>
public override decimal? V31ExclusiveMinimum { get => Target.V31ExclusiveMinimum; set => Target.V31ExclusiveMinimum = value; }
public override decimal? V31ExclusiveMinimum { get => _v31ExclusiveMinimum is not null ? _v31ExclusiveMinimum.Value : Target?.V31ExclusiveMinimum; set => _v31ExclusiveMinimum = value; }
/// <inheritdoc/>
public override bool UnEvaluatedProperties { get => Target.UnEvaluatedProperties; set => Target.UnEvaluatedProperties = value; }
public override bool UnEvaluatedProperties { get => _unEvaluatedProperties is not null ? _unEvaluatedProperties.Value : Target?.UnEvaluatedProperties ?? false; set => _unEvaluatedProperties = value; }
/// <inheritdoc/>
public override JsonSchemaType? Type { get => Target.Type; set => Target.Type = value; }
public override JsonSchemaType? Type { get => _type is not null ? _type.Value : Target?.Type; set => _type = value; }
/// <inheritdoc/>
public override string Const { get => Target.Const; set => Target.Const = value; }
public override string Const { get => string.IsNullOrEmpty(_const) ? Target?.Const : _const; set => _const = value; }
/// <inheritdoc/>
public override string Format { get => Target.Format; set => Target.Format = value; }
public override string Format { get => string.IsNullOrEmpty(_format) ? Target?.Format : _format; set => _format = value; }
/// <inheritdoc/>
public override string Description
{
get => string.IsNullOrEmpty(_description) ? Target.Description : _description;
get => string.IsNullOrEmpty(_description) ? Target?.Description : _description;
set => _description = value;
}
/// <inheritdoc/>
public override decimal? Maximum { get => Target.Maximum; set => Target.Maximum = value; }
public override decimal? Maximum { get => _maximum is not null ? _maximum : Target?.Maximum; set => _maximum = value; }
/// <inheritdoc/>
public override bool? ExclusiveMaximum { get => Target.ExclusiveMaximum; set => Target.ExclusiveMaximum = value; }
public override bool? ExclusiveMaximum { get => _exclusiveMaximum is not null ? _exclusiveMaximum : Target?.ExclusiveMaximum; set => _exclusiveMaximum = value; }
/// <inheritdoc/>
public override decimal? Minimum { get => Target.Minimum; set => Target.Minimum = value; }
public override decimal? Minimum { get => _minimum is not null ? _minimum : Target?.Minimum; set => _minimum = value; }
/// <inheritdoc/>
public override bool? ExclusiveMinimum { get => Target.ExclusiveMinimum; set => Target.ExclusiveMinimum = value; }
public override bool? ExclusiveMinimum { get => _exclusiveMinimum is not null ? _exclusiveMinimum : Target?.ExclusiveMinimum; set => _exclusiveMinimum = value; }
/// <inheritdoc/>
public override int? MaxLength { get => Target.MaxLength; set => Target.MaxLength = value; }
public override int? MaxLength { get => _maxLength is not null ? _maxLength : Target?.MaxLength; set => _maxLength = value; }
/// <inheritdoc/>
public override int? MinLength { get => Target.MinLength; set => Target.MinLength = value; }
public override int? MinLength { get => _minLength is not null ? _minLength : Target?.MinLength; set => _minLength = value; }
/// <inheritdoc/>
public override string Pattern { get => Target.Pattern; set => Target.Pattern = value; }
public override string Pattern { get => string.IsNullOrEmpty(_pattern) ? Target?.Pattern : _pattern; set => _pattern = value; }
/// <inheritdoc/>
public override decimal? MultipleOf { get => Target.MultipleOf; set => Target.MultipleOf = value; }
public override decimal? MultipleOf { get => _multipleOf is not null ? _multipleOf : Target?.MultipleOf; set => _multipleOf = value; }
/// <inheritdoc/>
public override JsonNode Default
{
get => _default ??= Target.Default;
set => _default = value;
}
public override JsonNode Default { get => _default is not null ? _default : Target?.Default; set => _default = value; }
/// <inheritdoc/>
public override bool ReadOnly { get => Target.ReadOnly; set => Target.ReadOnly = value; }
public override bool ReadOnly { get => _readOnly is not null ? _readOnly.Value : Target?.ReadOnly ?? false; set => _readOnly = value; }
/// <inheritdoc/>
public override bool WriteOnly { get => Target.WriteOnly; set => Target.WriteOnly = value; }
public override bool WriteOnly { get => _writeOnly is not null ? _writeOnly.Value : Target?.WriteOnly ?? false; set => _writeOnly = value; }
/// <inheritdoc/>
public override IList<OpenApiSchema> AllOf { get => Target.AllOf; set => Target.AllOf = value; }
public override IList<OpenApiSchema> AllOf { get => _allOf is not null ? _allOf : Target?.AllOf; set => _allOf = value; }
/// <inheritdoc/>
public override IList<OpenApiSchema> OneOf { get => Target.OneOf; set => Target.OneOf = value; }
public override IList<OpenApiSchema> OneOf { get => _oneOf is not null ? _oneOf : Target?.OneOf; set => _oneOf = value; }
/// <inheritdoc/>
public override IList<OpenApiSchema> AnyOf { get => Target.AnyOf; set => Target.AnyOf = value; }
public override IList<OpenApiSchema> AnyOf { get => _anyOf is not null ? _anyOf : Target?.AnyOf; set => _anyOf = value; }
/// <inheritdoc/>
public override OpenApiSchema Not { get => Target.Not; set => Target.Not = value; }
public override OpenApiSchema Not { get => _not is not null ? _not : Target?.Not; set => _not = value; }
/// <inheritdoc/>
public override ISet<string> Required { get => Target.Required; set => Target.Required = value; }
public override ISet<string> Required { get => _required is not null ? _required : Target?.Required; set => _required = value; }
/// <inheritdoc/>
public override OpenApiSchema Items { get => Target.Items; set => Target.Items = value; }
public override OpenApiSchema Items { get => _items is not null ? _items : Target?.Items; set => _items = value; }
/// <inheritdoc/>
public override int? MaxItems { get => Target.MaxItems; set => Target.MaxItems = value; }
public override int? MaxItems { get => _maxItems is not null ? _maxItems : Target?.MaxItems; set => _maxItems = value; }
/// <inheritdoc/>
public override int? MinItems { get => Target.MinItems; set => Target.MinItems = value; }
public override int? MinItems { get => _minItems is not null ? _minItems : Target?.MinItems; set => _minItems = value; }
/// <inheritdoc/>
public override bool? UniqueItems { get => Target.UniqueItems; set => Target.UniqueItems = value; }
public override bool? UniqueItems { get => _uniqueItems is not null ? _uniqueItems : Target?.UniqueItems; set => _uniqueItems = value; }
/// <inheritdoc/>
public override IDictionary<string, OpenApiSchema> Properties { get => Target.Properties; set => Target.Properties = value; }
public override IDictionary<string, OpenApiSchema> Properties { get => _properties is not null ? _properties : Target?.Properties ; set => _properties = value; }
/// <inheritdoc/>
public override IDictionary<string, OpenApiSchema> PatternProperties { get => Target.PatternProperties; set => Target.PatternProperties = value; }
public override IDictionary<string, OpenApiSchema> PatternProperties { get => _patternProperties is not null ? _patternProperties : Target?.PatternProperties; set => _patternProperties = value; }
/// <inheritdoc/>
public override int? MaxProperties { get => Target.MaxProperties; set => Target.MaxProperties = value; }
public override int? MaxProperties { get => _maxProperties is not null ? _maxProperties : Target?.MaxProperties; set => _maxProperties = value; }
/// <inheritdoc/>
public override int? MinProperties { get => Target.MinProperties; set => Target.MinProperties = value; }
public override int? MinProperties { get => _minProperties is not null ? _minProperties : Target?.MinProperties; set => _minProperties = value; }
/// <inheritdoc/>
public override bool AdditionalPropertiesAllowed { get => Target.AdditionalPropertiesAllowed; set => Target.AdditionalPropertiesAllowed = value; }
public override bool AdditionalPropertiesAllowed { get => _additionalPropertiesAllowed is not null ? _additionalPropertiesAllowed.Value : Target?.AdditionalPropertiesAllowed ?? true; set => _additionalPropertiesAllowed = value; }
/// <inheritdoc/>
public override OpenApiSchema AdditionalProperties { get => Target.AdditionalProperties; set => Target.AdditionalProperties = value; }
public override OpenApiSchema AdditionalProperties { get => _additionalProperties is not null ? _additionalProperties : Target?.AdditionalProperties; set => _additionalProperties = value; }
/// <inheritdoc/>
public override OpenApiDiscriminator Discriminator { get => Target.Discriminator; set => Target.Discriminator = value; }
public override OpenApiDiscriminator Discriminator { get => _discriminator is not null ? _discriminator : Target?.Discriminator; set => _discriminator = value; }
/// <inheritdoc/>
public override JsonNode Example
{
get => _example ??= Target.Example;
set => _example = value;
}
public override JsonNode Example { get => _example is not null ? _example : Target?.Example; set => _example = value; }
/// <inheritdoc/>
public override IList<JsonNode> Examples
{
get => _examples ??= Target.Examples;
set => Target.Examples = value;
}
public override IList<JsonNode> Examples { get => _examples is not null ? _examples : Target?.Examples; set => _examples = value; }
/// <inheritdoc/>
public override IList<JsonNode> Enum { get => Target.Enum; set => Target.Enum = value; }
public override IList<JsonNode> Enum { get => _enum is not null ? _enum : Target?.Enum; set => _enum = value; }
/// <inheritdoc/>
public override bool Nullable { get => Target.Nullable; set => Target.Nullable = value; }
public override bool Nullable { get => _nullable is not null ? _nullable.Value : Target?.Nullable ?? false; set => _nullable = value; }
/// <inheritdoc/>
public override bool UnevaluatedProperties { get => Target.UnevaluatedProperties; set => Target.UnevaluatedProperties = value; }
public override bool UnevaluatedProperties { get => _unevaluatedProperties is not null ? _unevaluatedProperties.Value : Target?.UnevaluatedProperties ?? false; set => _unevaluatedProperties = value; }
/// <inheritdoc/>
public override OpenApiExternalDocs ExternalDocs { get => Target.ExternalDocs; set => Target.ExternalDocs = value; }
public override OpenApiExternalDocs ExternalDocs { get => _externalDocs is not null ? _externalDocs : Target?.ExternalDocs; set => _externalDocs = value; }
/// <inheritdoc/>
public override bool Deprecated { get => Target.Deprecated; set => Target.Deprecated = value; }
public override bool Deprecated { get => _deprecated is not null ? _deprecated.Value : Target?.Deprecated ?? false; set => _deprecated = value; }
/// <inheritdoc/>
public override OpenApiXml Xml { get => Target.Xml; set => Target.Xml = value; }
public override OpenApiXml Xml { get => _xml is not null ? _xml : Target?.Xml; set => _xml = value; }
/// <inheritdoc/>
public override IDictionary<string, IOpenApiExtension> Extensions { get => Target.Extensions; set => Target.Extensions = value; }
public override IDictionary<string, IOpenApiExtension> Extensions { get => _extensions is not null ? _extensions : Target?.Extensions; set => _extensions = value; }

/// <inheritdoc/>
public override void SerializeAsV31(IOpenApiWriter writer)
Expand Down Expand Up @@ -233,7 +268,6 @@ public override void SerializeAsV2(IOpenApiWriter writer)
if (!writer.GetSettings().ShouldInlineReference(_reference))
{
_reference.SerializeAsV2(writer);
return;
}
else
{
Expand Down
Loading
Loading