Skip to content

Commit

Permalink
- fixes invalid inheritance cases
Browse files Browse the repository at this point in the history
  • Loading branch information
baywet committed May 15, 2024
1 parent 088c318 commit b0459ef
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 29 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added missing nullable directives for CLI generation.
- Fixed handling of nested arrays to be handled as `UntypedNode` instances [#4549](https://github.com/microsoft/kiota/issues/4549)
- Fixed `InvalidOperationException` thrown when serializing IBacked models with no changes present in the additional data in dotnet [microsoftgraph/msgraph-sdk-dotnet#2471](https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/2471).
- Fixed a bug where enums could be considered inheritance parents. [#4640](https://github.com/microsoft/kiota/issues/4640)
- Fixed `RequestConfiguration` Classes dropped in RequestBuilder methods in python [#4535](https://github.com/microsoft/kiota/issues/4535)
- Fixed incorrect optional types in method parameters in Python [#4507](https://github.com/microsoft/kiota/issues/4507)
- Changed enum parsing methods to return nil in the default case in Go [#4621](https://github.com/microsoft/kiota/issues/4621)
Expand All @@ -31,9 +32,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed a bug where multiple allOf entries type would not get merged if they were part of a discriminator. [#4325](https://github.com/microsoft/kiota/issues/4325)
- Fixed a bug where allOf structure with one entry and properties would not be considered as inheritance case. [#4346](https://github.com/microsoft/kiota/issues/4346)
- Fixed a bug where some allOf scenarios would be missing properties if type object wasn't set on the schema. [#4074](https://github.com/microsoft/kiota/issues/4074)
- Fixed a bug where schema with multiple allOf entries would incorrectly get merged to inherit from the first entry [#4428] (https://github.com/microsoft/kiota/issues/4428)
- Fixed a bug where schema with multiple allOf entries would incorrectly get merged to inherit from the first entry [#4428](https://github.com/microsoft/kiota/issues/4428)
- Fixes constructor generation for nullable properties that are initialized as null in C#,Java and PHP
- Fixed a bug where the hash alias in typescript wasn't being generated uniformly for similar interfaces [#84](https://github.com/microsoftgraph/msgraph-beta-sdk-typescript/issues/84)
- Fixed a bug where the hash alias in typescript wasn't being generated uniformly for similar interfaces [microsoftgraph/msgraph-beta-sdk-typescript#84](https://github.com/microsoftgraph/msgraph-beta-sdk-typescript/issues/84)

## [1.14.0] - 2024-05-02

Expand Down
12 changes: 6 additions & 6 deletions src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ public static bool IsInclusiveUnion(this OpenApiSchema? schema)
public static bool IsInherited(this OpenApiSchema? schema)
{
if (schema is null) return false;
var meaningfulMemberSchemas = schema.AllOf.FlattenSchemaIfRequired(static x => x.AllOf).Where(static x => x.IsSemanticallyMeaningful()).ToArray();
var isRootSchemaMeaningful = schema.IsSemanticallyMeaningful();
var meaningfulMemberSchemas = schema.AllOf.FlattenSchemaIfRequired(static x => x.AllOf).Where(static x => x.IsSemanticallyMeaningful(ignoreEnums: true, ignoreArrays: true, ignoreType: true)).ToArray();
var isRootSchemaMeaningful = schema.IsSemanticallyMeaningful(ignoreEnums: true, ignoreArrays: true, ignoreType: true);
return meaningfulMemberSchemas.Count(static x => !string.IsNullOrEmpty(x.Reference?.Id)) == 1 &&
(meaningfulMemberSchemas.Count(static x => string.IsNullOrEmpty(x.Reference?.Id)) == 1 ||
isRootSchemaMeaningful);
Expand Down Expand Up @@ -141,13 +141,13 @@ public static bool IsComposedEnum(this OpenApiSchema schema)
return schema.AnyOf.Count(static x => !x.IsSemanticallyMeaningful(true)) == 1 && schema.AnyOf.Count(static x => x.IsEnum()) == 1 ||
schema.OneOf.Count(static x => !x.IsSemanticallyMeaningful(true)) == 1 && schema.OneOf.Count(static x => x.IsEnum()) == 1;
}
public static bool IsSemanticallyMeaningful(this OpenApiSchema schema, bool ignoreNullableObjects = false)
public static bool IsSemanticallyMeaningful(this OpenApiSchema schema, bool ignoreNullableObjects = false, bool ignoreEnums = false, bool ignoreArrays = false, bool ignoreType = false)
{
if (schema is null) return false;
return schema.HasAnyProperty() ||
schema.Enum is { Count: > 0 } ||
schema.Items != null ||
(!string.IsNullOrEmpty(schema.Type) &&
(!ignoreEnums && schema.Enum is { Count: > 0 }) ||
(!ignoreArrays && schema.Items != null) ||
(!ignoreType && !string.IsNullOrEmpty(schema.Type) &&
((ignoreNullableObjects && !"object".Equals(schema.Type, StringComparison.OrdinalIgnoreCase)) ||
!ignoreNullableObjects)) ||
!string.IsNullOrEmpty(schema.Format) ||
Expand Down
11 changes: 6 additions & 5 deletions src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1588,9 +1588,12 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode
(false, null, not null) => AddModelDeclarationIfDoesntExist(currentNode, referencedSchema, className, shortestNamespace),
// empty schema + inline schema
(false, not null, null) => AddModelDeclarationIfDoesntExist(currentNode, inlineSchema, className, shortestNamespace),
// meaningless scenarios
// too much information but we can make a choice -> maps to properties + inline schema
(true, not null, not null) when inlineSchema.HasAnyProperty() => AddModelDeclarationIfDoesntExist(currentNode, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, inlineSchema, operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema)),
// too much information but we can make a choice -> maps to properties + referenced schema
(true, not null, not null) when referencedSchema.HasAnyProperty() => AddModelDeclarationIfDoesntExist(currentNode, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchema, operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)),
// meaningless scenario
(false, null, null) or (true, not null, not null) => throw new InvalidOperationException("invalid inheritance case"),

};
if (codeDeclaration is not CodeClass currentClass) throw new InvalidOperationException("Inheritance is only supported for classes");
if (!currentClass.Documentation.DescriptionAvailable &&
Expand Down Expand Up @@ -1894,9 +1897,7 @@ private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema sc
}

var mappings = GetDiscriminatorMappings(currentNode, schema, currentNamespace, newClass)
.Where(x => x.Value is CodeType type &&
type.TypeDefinition != null &&
type.TypeDefinition is CodeClass definition &&
.Where(x => x.Value is { TypeDefinition: CodeClass definition } &&
definition.DerivesFrom(newClass)); // only the mappings that derive from the current class

AddDiscriminatorMethod(newClass, schema.GetDiscriminatorPropertyName(), mappings, static s => s);
Expand Down
32 changes: 16 additions & 16 deletions tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3983,7 +3983,7 @@ public void IntersectionOfInlineSchemasWorks()
[Fact]
public void InheritedTypeWithInlineSchemaWorks()
{
var baseObjet = new OpenApiSchema
var baseObject = new OpenApiSchema
{
Type = "object",
Properties = new Dictionary<string, OpenApiSchema> {
Expand Down Expand Up @@ -4014,11 +4014,11 @@ public void InheritedTypeWithInlineSchemaWorks()
},
UnresolvedReference = false
};
var derivedObjet = new OpenApiSchema
var derivedObject = new OpenApiSchema
{
Type = "object",
AllOf = new List<OpenApiSchema> {
baseObjet,
AllOf = [
baseObject,
new OpenApiSchema {
Type = "object",
Properties = new Dictionary<string, OpenApiSchema> {
Expand All @@ -4037,7 +4037,7 @@ public void InheritedTypeWithInlineSchemaWorks()
}
},
}
},
],
Reference = new OpenApiReference
{
Id = "subNS.derivedObject",
Expand All @@ -4048,8 +4048,8 @@ public void InheritedTypeWithInlineSchemaWorks()
var secondLevelDerivedObject = new OpenApiSchema
{
Type = "object",
AllOf = new List<OpenApiSchema> {
derivedObjet,
AllOf = [
derivedObject,
new OpenApiSchema {
Type = "object",
Properties = new Dictionary<string, OpenApiSchema> {
Expand All @@ -4060,7 +4060,7 @@ public void InheritedTypeWithInlineSchemaWorks()
}
}
}
},
],
Reference = new OpenApiReference
{
Id = "subNS.secondLevelDerivedObject",
Expand All @@ -4082,7 +4082,7 @@ public void InheritedTypeWithInlineSchemaWorks()
["200"] = new OpenApiResponse {
Content = {
["application/json"] = new OpenApiMediaType {
Schema = derivedObjet
Schema = derivedObject
}
}
},
Expand All @@ -4095,10 +4095,10 @@ public void InheritedTypeWithInlineSchemaWorks()
{
Schemas = new Dictionary<string, OpenApiSchema> {
{
"subNS.baseObject", baseObjet
"subNS.baseObject", baseObject
},
{
"subNS.derivedObject", derivedObjet
"subNS.derivedObject", derivedObject
},
{
"subNS.secondLevelDerivedObject", secondLevelDerivedObject
Expand All @@ -4119,12 +4119,12 @@ public void InheritedTypeWithInlineSchemaWorks()
var executorReturnType = requestExecutorMethod.ReturnType as CodeType;
Assert.NotNull(executorReturnType);
Assert.Contains("derivedObject", requestExecutorMethod.ReturnType.Name);
var secondLevelDerivedClass = codeModel.FindChildByName<CodeClass>("derivedObject");
Assert.NotNull(secondLevelDerivedObject);
var factoryMethod = secondLevelDerivedClass.GetChildElements(true).OfType<CodeMethod>().FirstOrDefault(x => x.IsOfKind(CodeMethodKind.Factory));
var derivedObjectClass = codeModel.FindChildByName<CodeClass>("derivedObject");
Assert.NotNull(derivedObjectClass);
var factoryMethod = derivedObjectClass.GetChildElements(true).OfType<CodeMethod>().FirstOrDefault(x => x.IsOfKind(CodeMethodKind.Factory));
Assert.NotNull(factoryMethod);
Assert.Equal("kind", secondLevelDerivedClass.DiscriminatorInformation.DiscriminatorPropertyName);
Assert.NotEmpty(secondLevelDerivedClass.DiscriminatorInformation.DiscriminatorMappings);
Assert.Equal("kind", derivedObjectClass.DiscriminatorInformation.DiscriminatorPropertyName);
Assert.NotEmpty(derivedObjectClass.DiscriminatorInformation.DiscriminatorMappings);
}
[InlineData("string", "", "string")]// https://spec.openapis.org/registry/format/
[InlineData("string", "commonmark", "string")]
Expand Down

0 comments on commit b0459ef

Please sign in to comment.