From 5f5374b433e71370382cbfa3e071d1811c1552a1 Mon Sep 17 00:00:00 2001 From: pettijohn <632844+pettijohn@users.noreply.github.com> Date: Sat, 27 Jul 2024 13:14:53 -0700 Subject: [PATCH 1/8] Always inherit (don't squash) when generating classes referenced from a oneOf discrimintator --- src/Kiota.Builder/KiotaBuilder.cs | 54 +++++++++++++++++-------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index f3535b3cf0..4097df3b30 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1599,14 +1599,14 @@ private CodeType CreateModelDeclarationAndType(OpenApiUrlTreeNode currentNode, O TypeDefinition = codeDeclaration, }; } - private CodeType CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema) + private CodeType CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool referencedByOneOf = false) { return new CodeType { - TypeDefinition = CreateInheritedModelDeclaration(currentNode, schema, operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema), + TypeDefinition = CreateInheritedModelDeclaration(currentNode, schema, operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema, referencedByOneOf), }; } - private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema) + private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool referencedByOneOf = false) { var flattenedAllOfs = schema.AllOf.FlattenSchemaIfRequired(static x => x.AllOf).ToArray(); var referenceId = schema.Reference?.Id; @@ -1624,43 +1624,49 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode typeNameForInlineSchema : currentNode.GetClassName(config.StructuredMimeTypes, operation: operation, suffix: classNameSuffix, schema: schema, requestBody: isRequestBody))) .CleanupSymbolName(); - var codeDeclaration = (rootSchemaHasProperties, inlineSchemas, referencedSchemas) switch + var codeDeclaration = (rootSchemaHasProperties, inlineSchemas, referencedSchemas, referencedByOneOf) switch { // greatest parent type - (true, { Length: 0 }, { Length: 0 }) => + (true, { Length: 0 }, { Length: 0 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace), // inline schema + referenced schema - (false, { Length: > 0 }, { Length: 1 }) => + (false, { Length: > 0 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries([.. referencedSchemas], static x => x.Reference is null)!, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // properties + referenced schema - (true, { Length: 0 }, { Length: 1 }) => + (true, { Length: 0 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // properties + inline schema - (true, { Length: 1 }, { Length: 0 }) => + (true, { Length: 1 }, { Length: 0 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, inlineSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema)), // empty schema + referenced schema - (false, { Length: 0 }, { Length: 1 }) => + (false, { Length: 0 }, { Length: 1 }, false) => AddModelDeclarationIfDoesntExist(currentNode, operation, referencedSchemas[0], className, shortestNamespace), // empty schema + inline schema - (false, { Length: 1 }, { Length: 0 }) => + (false, { Length: 1 }, { Length: 0 }, false) => AddModelDeclarationIfDoesntExist(currentNode, operation, inlineSchemas[0], className, shortestNamespace), + // empty schema + referenced schema and referenced by oneOf + (false, { Length: 0 }, { Length: 1 }, true) => + AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), + // empty schema + inline schema and referenced by oneOf + (false, { Length: 1 }, { Length: 0 }, true) => + AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, inlineSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema)), // too much information but we can make a choice -> maps to properties + inline schema - (true, { Length: 1 }, { Length: 1 }) when inlineSchemas[0].HasAnyProperty() && !referencedSchemas[0].HasAnyProperty() => + (true, { Length: 1 }, { Length: 1 }, _) when inlineSchemas[0].HasAnyProperty() && !referencedSchemas[0].HasAnyProperty() => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, inlineSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema)), // too much information but we can make a choice -> maps to properties + referenced schema - (true, { Length: 1 }, { Length: 1 }) when referencedSchemas[0].HasAnyProperty() && !inlineSchemas[0].HasAnyProperty() => + (true, { Length: 1 }, { Length: 1 }, _) when referencedSchemas[0].HasAnyProperty() && !inlineSchemas[0].HasAnyProperty() => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // too much information but we can merge root + inline schema - (true, { Length: 1 }, { Length: 1 }) when referencedSchemas[0].HasAnyProperty() && inlineSchemas[0].HasAnyProperty() && schema.MergeAllOfSchemaEntries([.. referencedSchemas]) is { } mergedSchema => + (true, { Length: 1 }, { Length: 1 }, _) when referencedSchemas[0].HasAnyProperty() && inlineSchemas[0].HasAnyProperty() && schema.MergeAllOfSchemaEntries([.. referencedSchemas]) is { } mergedSchema => AddModelDeclarationIfDoesntExist(currentNode, operation, mergedSchema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // none of the allOf entries have properties, it's a grandparent schema - (true, { Length: 1 }, { Length: 1 }) => + (true, { Length: 1 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace), // too many entries, we mush everything together - (_, { Length: > 1 }, { Length: > 1 }) or (_, { Length: 0 or 1 }, { Length: > 1 }) or (_, { Length: > 1 }, { Length: 0 or 1 }) => + (_, { Length: > 1 }, { Length: > 1 }, _) or (_, { Length: 0 or 1 }, { Length: > 1 }, _) or (_, { Length: > 1 }, { Length: 0 or 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries()!, className, shortestNamespace), // meaningless scenario - (false, { Length: 0 }, { Length: 0 }) => + (false, { Length: 0 }, { Length: 0 }, _) => throw new InvalidOperationException("the type does not contain any information"), }; if (codeDeclaration is not CodeClass currentClass) throw new InvalidOperationException("Inheritance is only supported for classes"); @@ -1735,7 +1741,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo className = $"{unionType.Name}Member{++membersWithNoName}"; var declarationType = new CodeType { - TypeDefinition = AddModelDeclarationIfDoesntExist(currentNode, operation, currentSchema, className, shortestNamespace), + TypeDefinition = AddModelDeclarationIfDoesntExist(currentNode, operation, currentSchema, className, shortestNamespace, null, true), CollectionKind = currentSchema.IsArray() ? CodeTypeBase.CodeTypeCollectionKind.Complex : default }; if (!unionType.ContainsType(declarationType)) @@ -1743,7 +1749,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo } return unionType; } - private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, OpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false) + private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, OpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false, bool referencedByOneOf = false) { var (codeNamespace, responseValue, suffix) = schema.IsReferencedSchema() switch { @@ -1760,7 +1766,7 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, Ope if (schema.IsInherited()) { - return CreateInheritedModelDeclarationAndType(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema); + return CreateInheritedModelDeclarationAndType(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema, referencedByOneOf); } if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is OpenApiSchema mergedSchema) @@ -1824,7 +1830,7 @@ private CodeNamespace GetSearchNamespace(OpenApiUrlTreeNode currentNode, CodeNam return currentNamespace; } private ConcurrentDictionary classLifecycles = new(StringComparer.OrdinalIgnoreCase); - private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null) + private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null, bool referencedByOneOf = false) { if (GetExistingDeclaration(currentNamespace, currentNode, declarationName) is not CodeElement existingDeclaration) // we can find it in the components { @@ -1832,12 +1838,12 @@ private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentN return enumDeclaration; if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is { } mergedSchema && - AddModelDeclarationIfDoesntExist(currentNode, currentOperation, mergedSchema, declarationName, currentNamespace, inheritsFrom) is CodeClass createdClass) + AddModelDeclarationIfDoesntExist(currentNode, currentOperation, mergedSchema, declarationName, currentNamespace, inheritsFrom, referencedByOneOf) is CodeClass createdClass) { // multiple allOf entries that do not translate to inheritance return createdClass; } - return AddModelClass(currentNode, schema, declarationName, currentNamespace, currentOperation, inheritsFrom); + return AddModelClass(currentNode, schema, declarationName, currentNamespace, currentOperation, inheritsFrom, referencedByOneOf); } return existingDeclaration; } @@ -1913,7 +1919,7 @@ private CodeNamespace GetShortestNamespace(CodeNamespace currentNamespace, OpenA } return currentNamespace; } - private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null) + private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null, bool? referencedByOneOf = false) { if (inheritsFrom == null && schema.AllOf.Where(static x => x.Reference != null).ToArray() is { Length: 1 } referencedSchemas) {// any non-reference would be the current class in some description styles @@ -2160,7 +2166,7 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin logger.LogWarning("Discriminator {ComponentKey} not found in the OpenAPI document.", componentKey); return null; } - if (CreateModelDeclarations(currentNode, discriminatorSchema, currentOperation, GetShortestNamespace(currentNamespace, discriminatorSchema), string.Empty) is not CodeType result) + if (CreateModelDeclarations(currentNode, discriminatorSchema, currentOperation, GetShortestNamespace(currentNamespace, discriminatorSchema), string.Empty, null, string.Empty, false, true) is not CodeType result) { logger.LogWarning("Discriminator {ComponentKey} is not a valid model and points to a union type.", componentKey); return null; From 20c5d87f46a27dd091e78d4e35e46676dc3deb2d Mon Sep 17 00:00:00 2001 From: pettijohn <632844+pettijohn@users.noreply.github.com> Date: Sat, 27 Jul 2024 13:14:53 -0700 Subject: [PATCH 2/8] Always inherit (don't squash) when generating classes referenced from a oneOf discrimintator --- src/Kiota.Builder/KiotaBuilder.cs | 54 +++++++++++++++++-------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index f3535b3cf0..4097df3b30 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1599,14 +1599,14 @@ private CodeType CreateModelDeclarationAndType(OpenApiUrlTreeNode currentNode, O TypeDefinition = codeDeclaration, }; } - private CodeType CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema) + private CodeType CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool referencedByOneOf = false) { return new CodeType { - TypeDefinition = CreateInheritedModelDeclaration(currentNode, schema, operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema), + TypeDefinition = CreateInheritedModelDeclaration(currentNode, schema, operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema, referencedByOneOf), }; } - private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema) + private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool referencedByOneOf = false) { var flattenedAllOfs = schema.AllOf.FlattenSchemaIfRequired(static x => x.AllOf).ToArray(); var referenceId = schema.Reference?.Id; @@ -1624,43 +1624,49 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode typeNameForInlineSchema : currentNode.GetClassName(config.StructuredMimeTypes, operation: operation, suffix: classNameSuffix, schema: schema, requestBody: isRequestBody))) .CleanupSymbolName(); - var codeDeclaration = (rootSchemaHasProperties, inlineSchemas, referencedSchemas) switch + var codeDeclaration = (rootSchemaHasProperties, inlineSchemas, referencedSchemas, referencedByOneOf) switch { // greatest parent type - (true, { Length: 0 }, { Length: 0 }) => + (true, { Length: 0 }, { Length: 0 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace), // inline schema + referenced schema - (false, { Length: > 0 }, { Length: 1 }) => + (false, { Length: > 0 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries([.. referencedSchemas], static x => x.Reference is null)!, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // properties + referenced schema - (true, { Length: 0 }, { Length: 1 }) => + (true, { Length: 0 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // properties + inline schema - (true, { Length: 1 }, { Length: 0 }) => + (true, { Length: 1 }, { Length: 0 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, inlineSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema)), // empty schema + referenced schema - (false, { Length: 0 }, { Length: 1 }) => + (false, { Length: 0 }, { Length: 1 }, false) => AddModelDeclarationIfDoesntExist(currentNode, operation, referencedSchemas[0], className, shortestNamespace), // empty schema + inline schema - (false, { Length: 1 }, { Length: 0 }) => + (false, { Length: 1 }, { Length: 0 }, false) => AddModelDeclarationIfDoesntExist(currentNode, operation, inlineSchemas[0], className, shortestNamespace), + // empty schema + referenced schema and referenced by oneOf + (false, { Length: 0 }, { Length: 1 }, true) => + AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), + // empty schema + inline schema and referenced by oneOf + (false, { Length: 1 }, { Length: 0 }, true) => + AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, inlineSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema)), // too much information but we can make a choice -> maps to properties + inline schema - (true, { Length: 1 }, { Length: 1 }) when inlineSchemas[0].HasAnyProperty() && !referencedSchemas[0].HasAnyProperty() => + (true, { Length: 1 }, { Length: 1 }, _) when inlineSchemas[0].HasAnyProperty() && !referencedSchemas[0].HasAnyProperty() => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, inlineSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema)), // too much information but we can make a choice -> maps to properties + referenced schema - (true, { Length: 1 }, { Length: 1 }) when referencedSchemas[0].HasAnyProperty() && !inlineSchemas[0].HasAnyProperty() => + (true, { Length: 1 }, { Length: 1 }, _) when referencedSchemas[0].HasAnyProperty() && !inlineSchemas[0].HasAnyProperty() => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // too much information but we can merge root + inline schema - (true, { Length: 1 }, { Length: 1 }) when referencedSchemas[0].HasAnyProperty() && inlineSchemas[0].HasAnyProperty() && schema.MergeAllOfSchemaEntries([.. referencedSchemas]) is { } mergedSchema => + (true, { Length: 1 }, { Length: 1 }, _) when referencedSchemas[0].HasAnyProperty() && inlineSchemas[0].HasAnyProperty() && schema.MergeAllOfSchemaEntries([.. referencedSchemas]) is { } mergedSchema => AddModelDeclarationIfDoesntExist(currentNode, operation, mergedSchema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // none of the allOf entries have properties, it's a grandparent schema - (true, { Length: 1 }, { Length: 1 }) => + (true, { Length: 1 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace), // too many entries, we mush everything together - (_, { Length: > 1 }, { Length: > 1 }) or (_, { Length: 0 or 1 }, { Length: > 1 }) or (_, { Length: > 1 }, { Length: 0 or 1 }) => + (_, { Length: > 1 }, { Length: > 1 }, _) or (_, { Length: 0 or 1 }, { Length: > 1 }, _) or (_, { Length: > 1 }, { Length: 0 or 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries()!, className, shortestNamespace), // meaningless scenario - (false, { Length: 0 }, { Length: 0 }) => + (false, { Length: 0 }, { Length: 0 }, _) => throw new InvalidOperationException("the type does not contain any information"), }; if (codeDeclaration is not CodeClass currentClass) throw new InvalidOperationException("Inheritance is only supported for classes"); @@ -1735,7 +1741,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo className = $"{unionType.Name}Member{++membersWithNoName}"; var declarationType = new CodeType { - TypeDefinition = AddModelDeclarationIfDoesntExist(currentNode, operation, currentSchema, className, shortestNamespace), + TypeDefinition = AddModelDeclarationIfDoesntExist(currentNode, operation, currentSchema, className, shortestNamespace, null, true), CollectionKind = currentSchema.IsArray() ? CodeTypeBase.CodeTypeCollectionKind.Complex : default }; if (!unionType.ContainsType(declarationType)) @@ -1743,7 +1749,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo } return unionType; } - private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, OpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false) + private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, OpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false, bool referencedByOneOf = false) { var (codeNamespace, responseValue, suffix) = schema.IsReferencedSchema() switch { @@ -1760,7 +1766,7 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, Ope if (schema.IsInherited()) { - return CreateInheritedModelDeclarationAndType(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema); + return CreateInheritedModelDeclarationAndType(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema, referencedByOneOf); } if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is OpenApiSchema mergedSchema) @@ -1824,7 +1830,7 @@ private CodeNamespace GetSearchNamespace(OpenApiUrlTreeNode currentNode, CodeNam return currentNamespace; } private ConcurrentDictionary classLifecycles = new(StringComparer.OrdinalIgnoreCase); - private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null) + private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null, bool referencedByOneOf = false) { if (GetExistingDeclaration(currentNamespace, currentNode, declarationName) is not CodeElement existingDeclaration) // we can find it in the components { @@ -1832,12 +1838,12 @@ private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentN return enumDeclaration; if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is { } mergedSchema && - AddModelDeclarationIfDoesntExist(currentNode, currentOperation, mergedSchema, declarationName, currentNamespace, inheritsFrom) is CodeClass createdClass) + AddModelDeclarationIfDoesntExist(currentNode, currentOperation, mergedSchema, declarationName, currentNamespace, inheritsFrom, referencedByOneOf) is CodeClass createdClass) { // multiple allOf entries that do not translate to inheritance return createdClass; } - return AddModelClass(currentNode, schema, declarationName, currentNamespace, currentOperation, inheritsFrom); + return AddModelClass(currentNode, schema, declarationName, currentNamespace, currentOperation, inheritsFrom, referencedByOneOf); } return existingDeclaration; } @@ -1913,7 +1919,7 @@ private CodeNamespace GetShortestNamespace(CodeNamespace currentNamespace, OpenA } return currentNamespace; } - private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null) + private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null, bool? referencedByOneOf = false) { if (inheritsFrom == null && schema.AllOf.Where(static x => x.Reference != null).ToArray() is { Length: 1 } referencedSchemas) {// any non-reference would be the current class in some description styles @@ -2160,7 +2166,7 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin logger.LogWarning("Discriminator {ComponentKey} not found in the OpenAPI document.", componentKey); return null; } - if (CreateModelDeclarations(currentNode, discriminatorSchema, currentOperation, GetShortestNamespace(currentNamespace, discriminatorSchema), string.Empty) is not CodeType result) + if (CreateModelDeclarations(currentNode, discriminatorSchema, currentOperation, GetShortestNamespace(currentNamespace, discriminatorSchema), string.Empty, null, string.Empty, false, true) is not CodeType result) { logger.LogWarning("Discriminator {ComponentKey} is not a valid model and points to a union type.", componentKey); return null; From 117b41c655f797e151390e6b8b6eade14fd0ca4a Mon Sep 17 00:00:00 2001 From: pettijohn <632844+pettijohn@users.noreply.github.com> Date: Sat, 10 Aug 2024 09:45:48 -0700 Subject: [PATCH 3/8] Renamed parameter and added comments --- src/Kiota.Builder/KiotaBuilder.cs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 4097df3b30..e2e8c4d556 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1599,14 +1599,14 @@ private CodeType CreateModelDeclarationAndType(OpenApiUrlTreeNode currentNode, O TypeDefinition = codeDeclaration, }; } - private CodeType CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool referencedByOneOf = false) + private CodeType CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool isViaDiscriminator = false) { return new CodeType { - TypeDefinition = CreateInheritedModelDeclaration(currentNode, schema, operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema, referencedByOneOf), + TypeDefinition = CreateInheritedModelDeclaration(currentNode, schema, operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema, isViaDiscriminator), }; } - private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool referencedByOneOf = false) + private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool isViaDiscriminator = false) { var flattenedAllOfs = schema.AllOf.FlattenSchemaIfRequired(static x => x.AllOf).ToArray(); var referenceId = schema.Reference?.Id; @@ -1624,7 +1624,7 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode typeNameForInlineSchema : currentNode.GetClassName(config.StructuredMimeTypes, operation: operation, suffix: classNameSuffix, schema: schema, requestBody: isRequestBody))) .CleanupSymbolName(); - var codeDeclaration = (rootSchemaHasProperties, inlineSchemas, referencedSchemas, referencedByOneOf) switch + var codeDeclaration = (rootSchemaHasProperties, inlineSchemas, referencedSchemas, isViaDiscriminator) switch { // greatest parent type (true, { Length: 0 }, { Length: 0 }, _) => @@ -1644,10 +1644,10 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode // empty schema + inline schema (false, { Length: 1 }, { Length: 0 }, false) => AddModelDeclarationIfDoesntExist(currentNode, operation, inlineSchemas[0], className, shortestNamespace), - // empty schema + referenced schema and referenced by oneOf + // empty schema + referenced schema and referenced by oneOf discriminator (false, { Length: 0 }, { Length: 1 }, true) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), - // empty schema + inline schema and referenced by oneOf + // empty schema + inline schema and referenced by oneOf discriminator (false, { Length: 1 }, { Length: 0 }, true) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, inlineSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema)), // too much information but we can make a choice -> maps to properties + inline schema @@ -1749,7 +1749,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo } return unionType; } - private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, OpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false, bool referencedByOneOf = false) + private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, OpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false, bool isViaDiscriminator = false) { var (codeNamespace, responseValue, suffix) = schema.IsReferencedSchema() switch { @@ -1766,7 +1766,8 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, Ope if (schema.IsInherited()) { - return CreateInheritedModelDeclarationAndType(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema, referencedByOneOf); + // Pass isViaDiscriminator so that we can handle the special case where this model was referenced by a discriminator and we always want to generate a base class. + return CreateInheritedModelDeclarationAndType(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema, isViaDiscriminator); } if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is OpenApiSchema mergedSchema) @@ -1830,7 +1831,7 @@ private CodeNamespace GetSearchNamespace(OpenApiUrlTreeNode currentNode, CodeNam return currentNamespace; } private ConcurrentDictionary classLifecycles = new(StringComparer.OrdinalIgnoreCase); - private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null, bool referencedByOneOf = false) + private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null, bool isViaDiscriminator = false) { if (GetExistingDeclaration(currentNamespace, currentNode, declarationName) is not CodeElement existingDeclaration) // we can find it in the components { @@ -1838,12 +1839,12 @@ private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentN return enumDeclaration; if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is { } mergedSchema && - AddModelDeclarationIfDoesntExist(currentNode, currentOperation, mergedSchema, declarationName, currentNamespace, inheritsFrom, referencedByOneOf) is CodeClass createdClass) + AddModelDeclarationIfDoesntExist(currentNode, currentOperation, mergedSchema, declarationName, currentNamespace, inheritsFrom, isViaDiscriminator) is CodeClass createdClass) { // multiple allOf entries that do not translate to inheritance return createdClass; } - return AddModelClass(currentNode, schema, declarationName, currentNamespace, currentOperation, inheritsFrom, referencedByOneOf); + return AddModelClass(currentNode, schema, declarationName, currentNamespace, currentOperation, inheritsFrom, isViaDiscriminator); } return existingDeclaration; } @@ -1919,7 +1920,7 @@ private CodeNamespace GetShortestNamespace(CodeNamespace currentNamespace, OpenA } return currentNamespace; } - private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null, bool? referencedByOneOf = false) + private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null, bool? isViaDiscriminator = false) { if (inheritsFrom == null && schema.AllOf.Where(static x => x.Reference != null).ToArray() is { Length: 1 } referencedSchemas) {// any non-reference would be the current class in some description styles @@ -1970,6 +1971,7 @@ private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema sc } } + // Recurse into the discriminator & generate its referenced types var mappings = GetDiscriminatorMappings(currentNode, schema, currentNamespace, newClass, currentOperation) .Where(x => x.Value is { TypeDefinition: CodeClass definition } && definition.DerivesFrom(newClass)); // only the mappings that derive from the current class @@ -1979,6 +1981,7 @@ private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema sc } private IEnumerable> GetDiscriminatorMappings(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, CodeNamespace currentNamespace, CodeClass? baseClass, OpenApiOperation? currentOperation) { + // Generate types that this discriminator references return schema.GetDiscriminatorMappings(inheritanceIndex) .Union(baseClass is not null && modelsNamespace is not null && (openApiDocument?.Components?.Schemas?.TryGetValue(baseClass.GetComponentSchemaName(modelsNamespace), out var componentSchema) ?? false) ? @@ -2166,6 +2169,7 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin logger.LogWarning("Discriminator {ComponentKey} not found in the OpenAPI document.", componentKey); return null; } + // Call CreateModelDeclarations with isViaDiscriminator=true. This is for a special case where we always generate a base class when types are referenced via a oneOf discriminator. if (CreateModelDeclarations(currentNode, discriminatorSchema, currentOperation, GetShortestNamespace(currentNamespace, discriminatorSchema), string.Empty, null, string.Empty, false, true) is not CodeType result) { logger.LogWarning("Discriminator {ComponentKey} is not a valid model and points to a union type.", componentKey); From 4a90ff7b71db1f271783d4ba010185285aa679b2 Mon Sep 17 00:00:00 2001 From: pettijohn <632844+pettijohn@users.noreply.github.com> Date: Sat, 10 Aug 2024 10:49:47 -0700 Subject: [PATCH 4/8] Added test --- .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 8be6d794da..18955acc29 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -7840,6 +7840,80 @@ public async Task InheritanceWithAllOfWith3Parts3SchemaChildClass() Assert.Single(groupClass.Properties.Where(static x => x.Name.Equals("facetprop1", StringComparison.OrdinalIgnoreCase))); Assert.Single(groupClass.Properties.Where(static x => x.Name.Equals("facetprop2", StringComparison.OrdinalIgnoreCase))); } + + [Fact] + public async Task InheritanceWithAllOfBaseClassNoAdditionalProperties() + { + var tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); + await using var fs = await GetDocumentStream(@"openapi: 3.0.1 +info: + title: OData Service for namespace microsoft.graph + description: This OData service is located at https://graph.microsoft.com/v1.0 + version: 1.0.1 +servers: + - url: https://graph.microsoft.com/v1.0 +paths: + /directoryObject: + get: + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/microsoft.graph.directoryResult' +components: + schemas: + microsoft.graph.directoryResult: + required: ['fstype'] + oneOf: + - $ref: '#/components/schemas/microsoft.graph.file' + - $ref: '#/components/schemas/microsoft.graph.folder' + - $ref: '#/components/schemas/microsoft.graph.link' + properties: + fstype: + type: string + discriminator: + propertyName: 'fstype' + mapping: + 'file': '#/components/schemas/microsoft.graph.file' + 'folder': '#/components/schemas/microsoft.graph.folder' + 'link': '#/components/schemas/microsoft.graph.link' + microsoft.graph.baseDirectoryObject: + properties: + path: + type: string + microsoft.graph.file: + allOf: + - '$ref': '#/components/schemas/microsoft.graph.baseDirectoryObject' + microsoft.graph.folder: + allOf: + - '$ref': '#/components/schemas/microsoft.graph.baseDirectoryObject' + microsoft.graph.link: + allOf: + - '$ref': '#/components/schemas/microsoft.graph.baseDirectoryObject' + properties: + target: + type: string"); + var mockLogger = new Mock>(); + var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", OpenAPIFilePath = tempFilePath }, _httpClient); + var document = await builder.CreateOpenApiDocumentAsync(fs); + var node = builder.CreateUriSpace(document); + var codeModel = builder.CreateSourceModel(node); + + // Verify that all three classes referenced by the discriminator inherit from baseDirectoryObject + var folder = codeModel.FindChildByName("Folder"); + Assert.NotNull(folder.StartBlock.Inherits); + Assert.Equal("baseDirectoryObject", folder.StartBlock.Inherits.Name); + + var file = codeModel.FindChildByName("File"); + Assert.NotNull(file.StartBlock.Inherits); + Assert.Equal("baseDirectoryObject", file.StartBlock.Inherits.Name); + + var link = codeModel.FindChildByName("Link"); + Assert.NotNull(link.StartBlock.Inherits); + Assert.Equal("baseDirectoryObject", link.StartBlock.Inherits.Name); + } + [Fact] public async Task NestedIntersectionTypeAllOf() { From 995e66e6d0c988a2afe1238f8ccadd8349b12798 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 13 Aug 2024 10:14:02 -0400 Subject: [PATCH 5/8] Update src/Kiota.Builder/KiotaBuilder.cs Co-authored-by: Andrew Omondi --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index e2e8c4d556..c7cca056e1 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1667,7 +1667,7 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries()!, className, shortestNamespace), // meaningless scenario (false, { Length: 0 }, { Length: 0 }, _) => - throw new InvalidOperationException("the type does not contain any information"), + InvalidOperationException($"The type does not contain any information Path: {currentNode.Path}, Reference Id: {referenceId}") }; if (codeDeclaration is not CodeClass currentClass) throw new InvalidOperationException("Inheritance is only supported for classes"); if (!currentClass.Documentation.DescriptionAvailable && From 14dc21c42b0033beb77a32193aaff04840d153c6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 13 Aug 2024 10:15:12 -0400 Subject: [PATCH 6/8] fix: bad merge --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index c7cca056e1..84ae72f5fa 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1667,7 +1667,7 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries()!, className, shortestNamespace), // meaningless scenario (false, { Length: 0 }, { Length: 0 }, _) => - InvalidOperationException($"The type does not contain any information Path: {currentNode.Path}, Reference Id: {referenceId}") + throw new InvalidOperationException($"The type does not contain any information Path: {currentNode.Path}, Reference Id: {referenceId}"), }; if (codeDeclaration is not CodeClass currentClass) throw new InvalidOperationException("Inheritance is only supported for classes"); if (!currentClass.Documentation.DescriptionAvailable && From 5187497defd29c632f52657734fe2c6fce655814 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 13 Aug 2024 10:22:52 -0400 Subject: [PATCH 7/8] chore: cleans up unused parameter Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 84ae72f5fa..e4ade3b5f5 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1741,7 +1741,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo className = $"{unionType.Name}Member{++membersWithNoName}"; var declarationType = new CodeType { - TypeDefinition = AddModelDeclarationIfDoesntExist(currentNode, operation, currentSchema, className, shortestNamespace, null, true), + TypeDefinition = AddModelDeclarationIfDoesntExist(currentNode, operation, currentSchema, className, shortestNamespace, null), CollectionKind = currentSchema.IsArray() ? CodeTypeBase.CodeTypeCollectionKind.Complex : default }; if (!unionType.ContainsType(declarationType)) @@ -1831,7 +1831,7 @@ private CodeNamespace GetSearchNamespace(OpenApiUrlTreeNode currentNode, CodeNam return currentNamespace; } private ConcurrentDictionary classLifecycles = new(StringComparer.OrdinalIgnoreCase); - private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null, bool isViaDiscriminator = false) + private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null) { if (GetExistingDeclaration(currentNamespace, currentNode, declarationName) is not CodeElement existingDeclaration) // we can find it in the components { @@ -1839,12 +1839,12 @@ private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentN return enumDeclaration; if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is { } mergedSchema && - AddModelDeclarationIfDoesntExist(currentNode, currentOperation, mergedSchema, declarationName, currentNamespace, inheritsFrom, isViaDiscriminator) is CodeClass createdClass) + AddModelDeclarationIfDoesntExist(currentNode, currentOperation, mergedSchema, declarationName, currentNamespace, inheritsFrom) is CodeClass createdClass) { // multiple allOf entries that do not translate to inheritance return createdClass; } - return AddModelClass(currentNode, schema, declarationName, currentNamespace, currentOperation, inheritsFrom, isViaDiscriminator); + return AddModelClass(currentNode, schema, declarationName, currentNamespace, currentOperation, inheritsFrom); } return existingDeclaration; } @@ -1920,7 +1920,7 @@ private CodeNamespace GetShortestNamespace(CodeNamespace currentNamespace, OpenA } return currentNamespace; } - private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null, bool? isViaDiscriminator = false) + private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null) { if (inheritsFrom == null && schema.AllOf.Where(static x => x.Reference != null).ToArray() is { Length: 1 } referencedSchemas) {// any non-reference would be the current class in some description styles From dce92439db77464db75f7c1c6098f0d5c49c5f37 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 13 Aug 2024 10:30:00 -0400 Subject: [PATCH 8/8] doc: adds changelog entry for allof squash fix Signed-off-by: Vincent Biret --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b1a04d161..9fb6bb685f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Reverts modification of responses in output openApi file when generating plugings [#4945](https://github.com/microsoft/kiota/issues/4945) +- Fixed an issue where models would be missing when they had no properties and a single allOf entry. [#5014](https://github.com/microsoft/kiota/issues/5014) +- Reverts modification of responses in output openApi file when generating plugins [#4945](https://github.com/microsoft/kiota/issues/4945) ## [1.17.0] - 2024-08-09 @@ -1414,4 +1415,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Initial GitHub release -