Skip to content

Commit

Permalink
Revert "Use allOf for all schemas in inheritance (#733)"
Browse files Browse the repository at this point in the history
This reverts commit 74aa14f.
  • Loading branch information
RicoSuter committed Sep 21, 2018
1 parent 14e2190 commit eaeff01
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 120 deletions.
Expand Up @@ -278,7 +278,7 @@ public async Task When_class_has_description_then_csharp_has_xml_comment()
{
//// Arrange
var schema = await JsonSchema4.FromTypeAsync<Teacher>();
schema.ActualSchema.Description = "ClassDesc.";
schema.Description = "ClassDesc.";
var generator = new CSharpGenerator(schema);

//// Act
Expand All @@ -295,7 +295,7 @@ public async Task When_property_has_description_then_csharp_has_xml_comment()
{
//// Arrange
var schema = await JsonSchema4.FromTypeAsync<Teacher>();
schema.ActualProperties["Class"].Description = "PropertyDesc.";
schema.Properties["Class"].Description = "PropertyDesc.";
var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings { ClassStyle = CSharpClassStyle.Poco });

//// Act
Expand Down
Expand Up @@ -19,18 +19,13 @@ public async Task When_class_is_abstract_then_is_abstract_TypeScript_keyword_is_
{
/// Arrange
var schema = await JsonSchema4.FromTypeAsync<AbstractClass>();
var json = schema.ToJson();

/// Act
var generator = new TypeScriptGenerator(schema, new TypeScriptGeneratorSettings { TypeScriptVersion = 2.0m });
var code = generator.GenerateFile("AbstractClass");

/// Assert
Assert.Contains("export abstract class AbstractClass", code);

Assert.Contains("base: string", code);
Assert.Contains("super: string", code);
Assert.Contains("foo: string", code);
}

public class ContainerClass
Expand Down Expand Up @@ -58,12 +53,12 @@ public async Task When_property_is_required_and_abstract_then_it_is_not_instanti
[JsonConverter(typeof(JsonInheritanceConverter))]
public class BaseClass
{
public string Base { get; set; }

}

public class SuperClass : AbstractClass
{
public string Super { get; set; }

}

[Fact]
Expand Down
Expand Up @@ -154,9 +154,7 @@ public async Task When_property_has_description_then_csharp_has_xml_comment()
{
//// Arrange
var schema = await JsonSchema4.FromTypeAsync<Teacher>();
schema.ActualProperties["Class"].Description = "PropertyDesc.";
var json = schema.ToJson();

schema.Properties["Class"].Description = "PropertyDesc.";
var generator = new TypeScriptGenerator(schema);

//// Act
Expand Down
Expand Up @@ -33,7 +33,7 @@ protected ClassTemplateModelBase(TypeResolverBase resolver, JsonSchema4 schema,
public abstract string ClassName { get; }

/// <summary>Gets or sets a value indicating whether the type is abstract.</summary>
public bool IsAbstract => _schema.ActualTypeSchema.IsAbstract;
public bool IsAbstract => _schema.IsAbstract;

/// <summary>Gets the property extension data.</summary>
public IDictionary<string, object> ExtensionData => _schema.ExtensionData;
Expand All @@ -49,7 +49,7 @@ public class DerivedClassModel
{
internal DerivedClassModel(string typeName, JsonSchema4 schema, OpenApiDiscriminator discriminator, TypeResolverBase resolver)
{
var mapping = discriminator.Mapping.SingleOrDefault(m => m.Value.ActualTypeSchema == schema.ActualTypeSchema);
var mapping = discriminator.Mapping.SingleOrDefault(m => m.Value.ActualSchema == schema.ActualSchema);

ClassName = resolver.GetOrGenerateTypeName(schema, typeName);
IsAbstract = schema.ActualTypeSchema.IsAbstract;
Expand Down
2 changes: 1 addition & 1 deletion src/NJsonSchema.Tests/Conversion/ArrayTypeToSchemaTests.cs
Expand Up @@ -32,7 +32,7 @@ public async Task When_converting_type_inheriting_from_dictionary_then_it_should
var data = schema.ToJson();

//// Assert
Assert.Equal(JsonObjectType.Object, schema.ActualTypeSchema.Type);
Assert.Equal(JsonObjectType.Object, schema.Type);
Assert.DoesNotContain("Foo", json);
Assert.DoesNotContain("foo", json);
}
Expand Down
4 changes: 2 additions & 2 deletions src/NJsonSchema.Tests/Generation/ExceptionTypeTests.cs
Expand Up @@ -24,8 +24,8 @@ public async Task When_exception_schema_is_generated_then_special_properties_are
var exceptionSchema = schema.InheritedSchema.ActualSchema;

//// Assert
Assert.True(schema.ActualProperties.ContainsKey("foo"));
Assert.True(exceptionSchema.ActualProperties.ContainsKey("InnerException"));
Assert.True(schema.Properties.ContainsKey("foo"));
Assert.True(exceptionSchema.Properties.ContainsKey("InnerException"));
}
}
}
44 changes: 4 additions & 40 deletions src/NJsonSchema.Tests/Generation/InheritanceTests.cs
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
Expand Down Expand Up @@ -89,9 +88,9 @@ public async Task When_generating_type_with_inheritance_then_allOf_has_one_item(
var schema = await JsonSchema4.FromTypeAsync<Teacher>();

//// Assert
Assert.NotNull(schema.ActualProperties["Class"]);
Assert.NotNull(schema.Properties["Class"]);

Assert.Equal(2, schema.AllOf.Count);
Assert.Equal(1, schema.AllOf.Count);
Assert.Contains(schema.Definitions, d => d.Key == "Person");
Assert.NotNull(schema.AllOf.First().ActualSchema.Properties["Name"]);
}
Expand Down Expand Up @@ -299,45 +298,10 @@ public async Task Existing_non_string_property_cant_be_discriminant()
//// Arrange

//// Act
Task<JsonSchema4> GetSchema() => JsonSchema4.FromTypeAsync<BaseClass_WithIntDiscriminant>();
Task<JsonSchema4> getSchema() => JsonSchema4.FromTypeAsync<BaseClass_WithIntDiscriminant>();

//// Assert
await Assert.ThrowsAsync<InvalidOperationException>(GetSchema);
}

public class Foo
{
public Bar Bar { get; set; }
}

public class Bar : Dictionary<string, string>
{
public string Baz { get; set; }
}

[Fact]
public async Task When_class_inherits_from_dictionary_then_allOf_contains_base_dictionary_schema_and_actual_schema()
{
//// Arrange
var settings = new JsonSchemaGeneratorSettings
{
SchemaType = SchemaType.OpenApi3
};

//// Act
var schema = await JsonSchema4.FromTypeAsync<Foo>(settings);
var json = schema.ToJson();

//// Assert
var bar = schema.Definitions["Bar"];

Assert.Equal(2, bar.AllOf.Count);

Assert.Equal(bar.AllOf.Last(), bar.ActualTypeSchema);
Assert.Equal(bar.AllOf.First(), bar.InheritedSchema);

Assert.True(bar.AllOf.First().IsDictionary); // base class (dictionary)
Assert.True(bar.AllOf.Last().ActualProperties.Any()); // actual class
await Assert.ThrowsAsync<InvalidOperationException>(getSchema);
}
}
}
66 changes: 22 additions & 44 deletions src/NJsonSchema/Generation/JsonSchemaGenerator.cs
Expand Up @@ -146,7 +146,9 @@ public virtual async Task GenerateAsync<TSchemaType>(Type type, IEnumerable<Attr
schema.Reference = schemaResolver.GetSchema(type, false);
else if (schema.GetType() == typeof(JsonSchema4))
{
await GenerateObjectAsync(type, typeDescription, schema, schemaResolver).ConfigureAwait(false);
typeDescription.ApplyType(schema);
schema.Description = await type.GetTypeInfo().GetDescriptionAsync(type.GetTypeInfo().GetCustomAttributes()).ConfigureAwait(false);
await GenerateObjectAsync(type, schema, schemaResolver).ConfigureAwait(false);
}
else
schema.Reference = await GenerateAsync(type, parentAttributes, schemaResolver).ConfigureAwait(false);
Expand Down Expand Up @@ -309,35 +311,22 @@ public virtual string GetPropertyName(Newtonsoft.Json.Serialization.JsonProperty
}

/// <summary>Generates the properties for the given type and schema.</summary>
/// <typeparam name="TSchemaType">The type of the schema type.</typeparam>
/// <param name="type">The types.</param>
/// <param name="typeDescription">The type description.</param>
/// <param name="schema">The properties</param>
/// <param name="schemaResolver">The schema resolver.</param>
/// <returns>The task.</returns>
protected virtual async Task GenerateObjectAsync(Type type,
JsonTypeDescription typeDescription, JsonSchema4 schema, JsonSchemaResolver schemaResolver)
protected virtual async Task GenerateObjectAsync<TSchemaType>(
Type type, TSchemaType schema, JsonSchemaResolver schemaResolver)
where TSchemaType : JsonSchema4, new()
{
schemaResolver.AddSchema(type, false, schema);
var rootSchema = schema;

var hasInheritance = await GenerateInheritanceAsync(type, schema, schemaResolver).ConfigureAwait(false);
if (hasInheritance)
{
var actualSchema = new JsonSchema4();
schema.AllOf.Add(actualSchema);
schema = actualSchema;
}

typeDescription.ApplyType(schema);
schema.Description = await type.GetTypeInfo().GetDescriptionAsync(type.GetTypeInfo().GetCustomAttributes()).ConfigureAwait(false);
schema.AllowAdditionalProperties = false;
schema.IsAbstract = type.GetTypeInfo().IsAbstract;

await GeneratePropertiesAsync(type, schema, schemaResolver).ConfigureAwait(false);
await GeneratePropertiesAndInheritanceAsync(type, schema, schemaResolver).ConfigureAwait(false);
await ApplyAdditionalPropertiesAsync(type, schema, schemaResolver).ConfigureAwait(false);

GenerateInheritanceDiscriminator(type, rootSchema);

if (Settings.GenerateKnownTypes)
await GenerateKnownTypesAsync(type, schemaResolver).ConfigureAwait(false);

Expand Down Expand Up @@ -521,7 +510,7 @@ private async Task GenerateDictionaryAsync<TSchemaType>(TSchemaType schema, Type
schema.AllowAdditionalProperties = true;
}

private async Task GeneratePropertiesAsync(Type type, JsonSchema4 schema, JsonSchemaResolver schemaResolver)
private async Task GeneratePropertiesAndInheritanceAsync(Type type, JsonSchema4 schema, JsonSchemaResolver schemaResolver)
{
#if !LEGACY
var propertiesAndFields = type.GetTypeInfo()
Expand Down Expand Up @@ -614,6 +603,8 @@ private async Task GeneratePropertiesAsync(Type type, JsonSchema4 schema, JsonSc
await LoadPropertyOrFieldAsync(property, info, type, schema, schemaResolver).ConfigureAwait(false);
}
}

await GenerateInheritanceAsync(type, schema, schemaResolver).ConfigureAwait(false);
}

/// <summary>Gets the properties of the given type or null to take all properties.</summary>
Expand Down Expand Up @@ -665,7 +656,7 @@ private async Task AddKnownTypeAsync(Type type, JsonSchemaResolver schemaResolve
await GenerateAsync(type, schemaResolver).ConfigureAwait(false);
}

private async Task<bool> GenerateInheritanceAsync(Type type, JsonSchema4 schema, JsonSchemaResolver schemaResolver)
private async Task GenerateInheritanceAsync(Type type, JsonSchema4 schema, JsonSchemaResolver schemaResolver)
{
var baseType = type.GetTypeInfo().BaseType;
if (baseType != null && baseType != typeof(object) && baseType != typeof(ValueType))
Expand All @@ -678,12 +669,7 @@ private async Task<bool> GenerateInheritanceAsync(Type type, JsonSchema4 schema,
{
var typeDescription = Settings.ReflectionService.GetDescription(baseType, null, Settings);
if (!typeDescription.IsDictionary && !type.IsArray)
{
await GeneratePropertiesAsync(baseType, schema, schemaResolver).ConfigureAwait(false);
await GenerateInheritanceAsync(baseType, schema, schemaResolver).ConfigureAwait(false);

GenerateInheritanceDiscriminator(baseType, schema);
}
await GeneratePropertiesAndInheritanceAsync(baseType, schema, schemaResolver).ConfigureAwait(false);
}
else
{
Expand All @@ -701,8 +687,6 @@ private async Task<bool> GenerateInheritanceAsync(Type type, JsonSchema4 schema,
}
else
schema.AllOf.Add(baseSchema);

return true;
}
}
}
Expand All @@ -716,18 +700,12 @@ private async Task<bool> GenerateInheritanceAsync(Type type, JsonSchema4 schema,
#endif
{
var typeDescription = Settings.ReflectionService.GetDescription(i, null, Settings);
if (!typeDescription.IsDictionary && !type.IsArray &&
!typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(i.GetTypeInfo()))
{
await GeneratePropertiesAsync(i, schema, schemaResolver).ConfigureAwait(false);
await GenerateInheritanceAsync(i, schema, schemaResolver).ConfigureAwait(false);

GenerateInheritanceDiscriminator(i, schema);
}
if (!typeDescription.IsDictionary && !type.IsArray && !typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(i.GetTypeInfo()))
await GeneratePropertiesAndInheritanceAsync(i, schema, schemaResolver).ConfigureAwait(false);
}
}

return false;
GenerateInheritanceDiscriminator(type, schema);
}

private void GenerateInheritanceDiscriminator(Type type, JsonSchema4 schema)
Expand Down Expand Up @@ -1024,15 +1002,15 @@ private void ApplyRangeAttribute(JsonSchema4 schema, IEnumerable<Attribute> pare
{
if (rangeAttribute.OperandType == typeof(double))
{
var minimum = (double)Convert.ChangeType(rangeAttribute.Minimum, typeof(double));
var minimum = (double) Convert.ChangeType(rangeAttribute.Minimum, typeof(double));
if (minimum > double.MinValue)
{
schema.Minimum = (decimal)minimum;
schema.Minimum = (decimal) minimum;
}
}
else
{
var minimum = (decimal)Convert.ChangeType(rangeAttribute.Minimum, typeof(decimal));
var minimum = (decimal) Convert.ChangeType(rangeAttribute.Minimum, typeof(decimal));
if (minimum > decimal.MinValue)
{
schema.Minimum = minimum;
Expand All @@ -1044,15 +1022,15 @@ private void ApplyRangeAttribute(JsonSchema4 schema, IEnumerable<Attribute> pare
{
if (rangeAttribute.OperandType == typeof(double))
{
var maximum = (double)Convert.ChangeType(rangeAttribute.Maximum, typeof(double));
var maximum = (double) Convert.ChangeType(rangeAttribute.Maximum, typeof(double));
if (maximum < double.MaxValue)
{
schema.Maximum = (decimal)maximum;
schema.Maximum = (decimal) maximum;
}
}
else
{
var maximum = (decimal)Convert.ChangeType(rangeAttribute.Maximum, typeof(decimal));
var maximum = (decimal) Convert.ChangeType(rangeAttribute.Maximum, typeof(decimal));
if (maximum < decimal.MaxValue)
{
schema.Maximum = maximum;
Expand Down
6 changes: 1 addition & 5 deletions src/NJsonSchema/Infrastructure/XmlDocumentationExtensions.cs
Expand Up @@ -463,11 +463,7 @@ private static string RemoveLineBreakWhiteSpaces(string documentation)
private static string GetMemberElementName(dynamic member)
{
char prefixCode;

var memberName = member is Type memberType && !string.IsNullOrEmpty(memberType.FullName) ?
memberType.FullName :
member.DeclaringType.FullName + "." + member.Name;

string memberName = member is Type ? ((Type)member).FullName : (member.DeclaringType.FullName + "." + member.Name);
switch ((string)member.MemberType.ToString())
{
case "Constructor":
Expand Down
15 changes: 1 addition & 14 deletions src/NJsonSchema/JsonSchema4.Reference.cs
Expand Up @@ -8,10 +8,8 @@

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Newtonsoft.Json;
using NJsonSchema.Collections;
using NJsonSchema.References;

namespace NJsonSchema
Expand All @@ -28,18 +26,7 @@ public partial class JsonSchema4 : JsonReferenceBase<JsonSchema4>, IJsonReferenc
/// <exception cref="InvalidOperationException">Cyclic references detected.</exception>
/// <exception cref="InvalidOperationException">The schema reference path has not been resolved.</exception>
[JsonIgnore]
public virtual JsonSchema4 ActualTypeSchema
{
get
{
if (AllOf.Count > 1 && AllOf.Count(s => !s.HasReference && !s.IsDictionary) == 1)
{
return AllOf.First(s => !s.HasReference && !s.IsDictionary);
}

return OneOf.FirstOrDefault(o => !o.IsNullable(SchemaType.JsonSchema))?.ActualSchema ?? ActualSchema;
}
}
public virtual JsonSchema4 ActualTypeSchema => OneOf.FirstOrDefault(o => !o.IsNullable(SchemaType.JsonSchema))?.ActualSchema ?? ActualSchema;

/// <summary>Gets a value indicating whether this is a schema reference ($ref or <see cref="HasAllOfSchemaReference"/>).</summary>
[JsonIgnore]
Expand Down

0 comments on commit eaeff01

Please sign in to comment.