From 7bed07a04eb7336b3053448e0023d4afd18bfbc4 Mon Sep 17 00:00:00 2001 From: Aayush Pandey Date: Sun, 26 Jul 2026 00:08:29 -0700 Subject: [PATCH] fix: preserve empty enum wire values --- src/Kiota.Builder/CodeDOM/CodeEnumOption.cs | 18 +++++++++++++++--- src/Kiota.Builder/KiotaBuilder.cs | 8 ++++---- .../CodeDOM/CodeEnumTests.cs | 14 ++++++++++++++ tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 4 ++++ .../Writers/Go/CodeEnumWriterTests.cs | 15 +++++++++++++++ 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/Kiota.Builder/CodeDOM/CodeEnumOption.cs b/src/Kiota.Builder/CodeDOM/CodeEnumOption.cs index a709fb8fe3..7cc5dbc355 100644 --- a/src/Kiota.Builder/CodeDOM/CodeEnumOption.cs +++ b/src/Kiota.Builder/CodeDOM/CodeEnumOption.cs @@ -5,18 +5,30 @@ namespace Kiota.Builder.CodeDOM; public class CodeEnumOption : CodeElement, IDocumentedElement, ITypeDefinition, IAlternativeName { /// - public string SerializationName { get; set; } = string.Empty; + public string SerializationName + { + get => serializationName; + set + { + serializationName = value ?? string.Empty; + hasSerializationName = true; + } + } + private string serializationName = string.Empty; + private bool hasSerializationName; public CodeDocumentation Documentation { get; set; } = new(); /// public bool IsNameEscaped { - get => !string.IsNullOrEmpty(SerializationName); + get => hasSerializationName; } /// public string WireName => IsNameEscaped ? SerializationName : Name; /// public string SymbolName { - get => IsNameEscaped ? SerializationName.CleanupSymbolName() : Name; + get => IsNameEscaped && !string.IsNullOrEmpty(SerializationName) ? + SerializationName.CleanupSymbolName() : + Name; } } diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 1045c042e0..fef827bba2 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -2195,16 +2195,16 @@ private static void SetEnumOptions(IOpenApiSchema schema, CodeEnum target) target.AddOption(schema.Enum?.OfType() .Where(static x => x.GetValueKind() is JsonValueKind.String or JsonValueKind.Number) .Select(static x => x.GetValueKind() is JsonValueKind.String ? x.GetValue() : x.GetValue().ToString(CultureInfo.InvariantCulture)) - .Where(static x => !string.IsNullOrEmpty(x)) .Distinct(StringComparer.OrdinalIgnoreCase) .Select((x) => { var optionDescription = extensionInformation?.ValuesDescriptions.Find(y => y.Value.Equals(x, StringComparison.OrdinalIgnoreCase)); + var optionName = optionDescription?.Name is string name && !string.IsNullOrEmpty(name) ? + name : + string.IsNullOrEmpty(x) ? "Empty" : x; return new CodeEnumOption { - Name = (optionDescription?.Name is string name && !string.IsNullOrEmpty(name) ? - name : - x).CleanupSymbolName(), + Name = optionName.CleanupSymbolName(), SerializationName = x, Documentation = new() { diff --git a/tests/Kiota.Builder.Tests/CodeDOM/CodeEnumTests.cs b/tests/Kiota.Builder.Tests/CodeDOM/CodeEnumTests.cs index b2e8ff18ab..c1c95c1fe7 100644 --- a/tests/Kiota.Builder.Tests/CodeDOM/CodeEnumTests.cs +++ b/tests/Kiota.Builder.Tests/CodeDOM/CodeEnumTests.cs @@ -23,4 +23,18 @@ public void EnumInits() }).First(); codeEnum.AddOption(new CodeEnumOption { Name = "option1" }); } + + [Fact] + public void PreservesExplicitEmptySerializationName() + { + var option = new CodeEnumOption + { + Name = "Empty", + SerializationName = string.Empty, + }; + + Assert.True(option.IsNameEscaped); + Assert.Empty(option.WireName); + Assert.Equal("Empty", option.SymbolName); + } } diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 16a52c8fa8..7a9f692daa 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -530,6 +530,7 @@ public async Task ParsesEnumDescriptionsAsync() - Standard_RAGRS - Premium_LRS - Premium_LRS + - '' x-ms-enum: name: AccountType modelAsString: false @@ -568,6 +569,9 @@ public async Task ParsesEnumDescriptionsAsync() Assert.Equal("StandardLocalRedundancy", thirdOption.Name); Assert.NotEmpty(thirdOption.Documentation.DescriptionTemplate); Assert.Single(enumDef.Options, static x => x.Name.Equals("Premium_LRS", StringComparison.OrdinalIgnoreCase)); + var emptyOption = Assert.Single(enumDef.Options, static x => x.Name.Equals("Empty", StringComparison.OrdinalIgnoreCase)); + Assert.Empty(emptyOption.SerializationName); + Assert.Empty(emptyOption.WireName); } [Fact] diff --git a/tests/Kiota.Builder.Tests/Writers/Go/CodeEnumWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Go/CodeEnumWriterTests.cs index e8d3c2ba84..2af801b6b9 100644 --- a/tests/Kiota.Builder.Tests/Writers/Go/CodeEnumWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Go/CodeEnumWriterTests.cs @@ -232,4 +232,19 @@ public void EscapesEnumWireValues() Assert.Contains("return []string{\"line1\\\"\\nline2\"}[i]", result); Assert.Contains("case \"line1\\\"\\nline2\":", result); } + + [Fact] + public void WritesEmptyEnumWireValue() + { + currentEnum.AddOption( + new CodeEnumOption { Name = "option1" }, + new CodeEnumOption { Name = "empty", SerializationName = string.Empty }); + + writer.Write(currentEnum); + var result = tw.ToString(); + + Assert.Contains("return []string{\"option1\", \"\"}[i]", result); + Assert.Contains("case \"\":", result); + Assert.Contains("result = EMPTY_SOMEENUM", result); + } }