diff --git a/CHANGELOG.md b/CHANGELOG.md index 17076aa315..d85163d3e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed Python error when a class inherits from a base class and implements an interface. [5637](https://github.com/microsoft/kiota/issues/5637) - Fix anyOf/oneOf generation in TypeScript. [5353](https://github.com/microsoft/kiota/issues/5353) - Fixed invalid code in Php caused by "*/*/" in property description. [5635](https://github.com/microsoft/kiota/issues/5635) +- Fixed a bug where discriminator property name lookup could end up in an infinite loop. [#5771](https://github.com/microsoft/kiota/issues/5771) - Fixed TypeScript generation error when generating usings from shaken serializers. [#5634](https://github.com/microsoft/kiota/issues/5634) ## [1.20.0] - 2024-11-07 diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index c5ed4b24e9..045218eced 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -246,19 +246,25 @@ private static IEnumerable FlattenEmptyEntries(this IEnumerable? visitedSchemas = default) { + if (schema == null) return string.Empty; + visitedSchemas ??= []; + if (visitedSchemas.Contains(schema)) + return string.Empty; + visitedSchemas.Add(schema); + if (!string.IsNullOrEmpty(schema.Discriminator?.PropertyName)) return schema.Discriminator.PropertyName; - if (schema.OneOf.Select(GetDiscriminatorPropertyName).FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string oneOfDiscriminatorPropertyName) + if (schema.OneOf.Select(x => x.GetDiscriminatorPropertyName(visitedSchemas)).FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string oneOfDiscriminatorPropertyName) return oneOfDiscriminatorPropertyName; - if (schema.AnyOf.Select(GetDiscriminatorPropertyName).FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string anyOfDiscriminatorPropertyName) + if (schema.AnyOf.Select(x => x.GetDiscriminatorPropertyName(visitedSchemas)).FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string anyOfDiscriminatorPropertyName) return anyOfDiscriminatorPropertyName; - if (schema.AllOf.Select(GetDiscriminatorPropertyName).FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string allOfDiscriminatorPropertyName) + if (schema.AllOf.Select(x => x.GetDiscriminatorPropertyName(visitedSchemas)).FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string allOfDiscriminatorPropertyName) return allOfDiscriminatorPropertyName; return string.Empty; diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index d0c7a81f9f..800a449504 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -847,4 +847,63 @@ public void IsOdataPrimitiveBackwardCompatible() }; Assert.True(schema.IsODataPrimitiveType()); } + [Fact] + public void ReturnsEmptyPropertyNameOnCircularReferences() + { + var entitySchema = new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = "microsoft.graph.entity" + }, + Properties = new Dictionary + { + ["id"] = new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = "microsoft.graph.entity" + } + } + } + }; + var userSchema = new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = "microsoft.graph.user" + }, + OneOf = + [ + entitySchema, + new OpenApiSchema + { + Type = "object", + Properties = new Dictionary + { + ["firstName"] = new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = "microsoft.graph.entity" + } + } + } + } + ], + Discriminator = new OpenApiDiscriminator + { + Mapping = new Dictionary + { + ["microsoft.graph.entity"] = "entity", + ["microsoft.graph.user"] = "user" + } + } + }; + entitySchema.AllOf = + [ + userSchema + ]; + Assert.Empty(userSchema.GetDiscriminatorPropertyName()); + } }