From 116d63a6033650f317bcccdcaccdead19fa7486b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 20 Sep 2023 14:18:15 -0400 Subject: [PATCH] - fixes a bug with composed types naming --- CHANGELOG.md | 3 +- src/Kiota.Builder/CodeDOM/CodeClass.cs | 2 +- src/Kiota.Builder/KiotaBuilder.cs | 6 +- .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 65 +++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 703427eec2..4b0e748c4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Localhost based descriptions are not cached anymore to facilitate development workflows. [#3316](https://github.com/microsoft/kiota/issues/3316) -- Changed parameter order in with_url method body to match the signature of RequestBuilder constructor in Python. [#3328](https://github.com/microsoft/kiota/issues/3328 +- Fixed a bug where inline composed types for components schemas would have the wrong name. [#3067](https://github.com/microsoft/kiota/issues/3067) +- Changed parameter order in with_url method body to match the signature of RequestBuilder constructor in Python. [#3328](https://github.com/microsoft/kiota/issues/3328) - Removed redundant undefined qualifier in TypeScript for properties. [#3244](https://github.com/microsoft/kiota/issues/3244) - The default status code response is now used as 4XX and 5XX when those class responses are not provided in the description. [#3245](https://github.com/microsoft/kiota/issues/3245) diff --git a/src/Kiota.Builder/CodeDOM/CodeClass.cs b/src/Kiota.Builder/CodeDOM/CodeClass.cs index 58d84b8491..5ad49b2aef 100644 --- a/src/Kiota.Builder/CodeDOM/CodeClass.cs +++ b/src/Kiota.Builder/CodeDOM/CodeClass.cs @@ -183,7 +183,7 @@ public bool ContainsPropertyWithWireName(string wireName) } public IEnumerable AddInnerClass(params CodeClass[] codeClasses) { - if (codeClasses == null || codeClasses.Any(x => x == null)) + if (codeClasses == null || codeClasses.Any(static x => x == null)) throw new ArgumentNullException(nameof(codeClasses)); if (!codeClasses.Any()) throw new ArgumentOutOfRangeException(nameof(codeClasses)); diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 9c64aa8cb9..e06f1c4ec3 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1602,9 +1602,9 @@ private CodeTypeBase CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentN if (parentSchema.Items?.Reference?.Id?.EndsWith(title, StringComparison.OrdinalIgnoreCase) ?? false) return parentSchema.Items.Reference.Id; return parentSchema.GetSchemaReferenceIds().FirstOrDefault(refId => refId.EndsWith(title, StringComparison.OrdinalIgnoreCase)); } - private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string suffixForInlineSchema, CodeNamespace codeNamespace, bool isRequestBody) + private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string suffixForInlineSchema, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema) { - var typeName = currentNode.GetClassName(config.StructuredMimeTypes, operation: operation, suffix: suffixForInlineSchema, schema: schema, requestBody: isRequestBody).CleanupSymbolName(); + var typeName = string.IsNullOrEmpty(typeNameForInlineSchema) ? currentNode.GetClassName(config.StructuredMimeTypes, operation: operation, suffix: suffixForInlineSchema, schema: schema, requestBody: isRequestBody).CleanupSymbolName() : typeNameForInlineSchema; var typesCount = schema.AnyOf?.Count ?? schema.OneOf?.Count ?? 0; if (typesCount == 1 && schema.Nullable && schema.IsInclusiveUnion() || // nullable on the root schema outside of anyOf typesCount == 2 && (schema.AnyOf?.Any(static x => // nullable on a schema in the anyOf @@ -1696,7 +1696,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo if ((schema.IsInclusiveUnion() || schema.IsExclusiveUnion()) && string.IsNullOrEmpty(schema.Format) && !schema.IsODataPrimitiveType()) { // OData types are oneOf string, type + format, enum - return CreateComposedModelDeclaration(currentNode, schema, operation, suffix, codeNamespace, isRequestBody); + return CreateComposedModelDeclaration(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema); } if (schema.IsObject() || schema.Properties.Any() || schema.IsEnum() || !string.IsNullOrEmpty(schema.AdditionalProperties?.Type)) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 08857a7638..fa592bef7c 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -275,6 +275,71 @@ public async Task ParsesEnumFlagsInformation() Assert.NotNull(enumDef); Assert.True(enumDef.Flags); } + [Fact] + public async Task NamesComponentsInlineSchemasProperly() + { + 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: + /users: + get: + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/microsoft.graph.directoryObject' +components: + schemas: + microsoft.graph.directoryObject: + title: directoryObject + type: object + properties: + deletedDateTime: + oneOf: + - type: string + pattern: '^[0-9]{4,}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]([.][0-9]{1,12})?(Z|[+-][0-9][0-9]:[0-9][0-9])$' + format: date-time + nullable: true + - type: number + format: int64 + - type: object + properties: + day: + type: integer + format: int32 + month: + type: integer + format: int32 + year: + type: integer + format: int32"); + 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); + var modelsNS = codeModel.FindNamespaceByName("ApiSdk.models.microsoft.graph"); + Assert.NotNull(modelsNS); + var doClass = modelsNS.FindChildByName("DirectoryObject", false); + Assert.NotNull(doClass); + var deletedDateTimeProperty = doClass.FindChildByName("DeletedDateTime", false); + Assert.NotNull(deletedDateTimeProperty); + var unionType = deletedDateTimeProperty.Type as CodeUnionType; + Assert.NotNull(unionType); + Assert.Equal("directoryObject_deletedDateTime", unionType.Name, StringComparer.OrdinalIgnoreCase); + Assert.Equal(3, unionType.Types.Count()); + Assert.Equal("DateTimeOffset", unionType.Types.First().Name, StringComparer.OrdinalIgnoreCase); + Assert.Equal("int64", unionType.Types.ElementAt(1).Name, StringComparer.OrdinalIgnoreCase); + Assert.Equal("directoryObject_deletedDateTimeMember1", unionType.Types.ElementAt(2).Name, StringComparer.OrdinalIgnoreCase); + Assert.Null(modelsNS.FindChildByName("users")); + } [Theory] [InlineData("description: 'Represents an Azure Active Directory user.'")] [InlineData("title: 'user'")]