From 1059199a847e1b5bf2a8f49813f882adb8b49283 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 22 Aug 2024 16:01:04 -0400 Subject: [PATCH 1/3] fix #5201: C# refiner now fixes data types for indexers. --- CHANGELOG.md | 1 + src/Kiota.Builder/Refiners/CSharpRefiner.cs | 8 +- .../Refiners/CommonLanguageRefiner.cs | 7 +- .../Refiners/CSharpLanguageRefinerTests.cs | 147 ++++++++++++++++++ 4 files changed, 160 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e439f607f..40c8c7dc0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Reverts modification of responses in output openApi file when generating plugins [#4945](https://github.com/microsoft/kiota/issues/4945) - Expand properties types with null type for Typescript. [#4993](https://github.com/microsoft/kiota-typescript/issues/1188) - Added Collection, HashMap, Map, Objects, InputStream, BigDecimal to the list of reserved names for Java generation. [#5135](https://github.com/microsoft/kiota/issues/5135) +- C# refiner now fixes data types for indexers. [#5201] (https://github.com/microsoft/kiota/issues/5201) ## [1.17.0] - 2024-08-09 diff --git a/src/Kiota.Builder/Refiners/CSharpRefiner.cs b/src/Kiota.Builder/Refiners/CSharpRefiner.cs index 2a78396e7d..ec5eaa26bb 100644 --- a/src/Kiota.Builder/Refiners/CSharpRefiner.cs +++ b/src/Kiota.Builder/Refiners/CSharpRefiner.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -97,7 +98,7 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance static s => s.ToPascalCase(UnderscoreArray)); DisambiguatePropertiesWithClassNames(generatedCode); // Correct the core types after reserved names for types/properties are done to avoid collision of types e.g. renaming custom model called `DateOnly` to `Date` - CorrectCoreType(generatedCode, CorrectMethodType, CorrectPropertyType); + CorrectCoreType(generatedCode, CorrectMethodType, CorrectPropertyType, correctIndexer: CorrectIndexerType); cancellationToken.ThrowIfCancellationRequested(); AddSerializationModulesImport(generatedCode); AddParentClassToErrorClasses( @@ -226,6 +227,11 @@ protected static void CorrectMethodType(CodeMethod currentMethod) .Union(new[] { currentMethod.ReturnType }) .ToArray()); } + protected static void CorrectIndexerType(CodeIndexer currentIndexer) + { + ArgumentNullException.ThrowIfNull(currentIndexer); + CorrectCoreTypes(currentIndexer.Parent as CodeClass, DateTypesReplacements, currentIndexer.IndexParameter.Type); + } private static readonly Dictionary DateTypesReplacements = new(StringComparer.OrdinalIgnoreCase) { diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs index 3bff4b8ff3..6ce8cf9365 100644 --- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs +++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs @@ -787,7 +787,7 @@ protected static void CrawlTree(CodeElement currentElement, Action foreach (var childElement in currentElement.GetChildElements(innerOnly)) function.Invoke(childElement); } - protected static void CorrectCoreType(CodeElement currentElement, Action? correctMethodType, Action? correctPropertyType, Action? correctImplements = default) + protected static void CorrectCoreType(CodeElement currentElement, Action? correctMethodType, Action? correctPropertyType, Action? correctImplements = default, Action? correctIndexer = default) { switch (currentElement) { @@ -800,8 +800,11 @@ protected static void CorrectCoreType(CodeElement currentElement, Action CorrectCoreType(x, correctMethodType, correctPropertyType, correctImplements), false); + CrawlTree(currentElement, x => CorrectCoreType(x, correctMethodType, correctPropertyType, correctImplements, correctIndexer), false); } protected static void MakeModelPropertiesNullable(CodeElement currentElement) { diff --git a/tests/Kiota.Builder.Tests/Refiners/CSharpLanguageRefinerTests.cs b/tests/Kiota.Builder.Tests/Refiners/CSharpLanguageRefinerTests.cs index cb85b7cb0a..b0a464f459 100644 --- a/tests/Kiota.Builder.Tests/Refiners/CSharpLanguageRefinerTests.cs +++ b/tests/Kiota.Builder.Tests/Refiners/CSharpLanguageRefinerTests.cs @@ -733,6 +733,153 @@ public async Task ReplacesLocallyDefinedTimeOnlyByNativeType() Assert.NotEmpty(model.StartBlock.Usings); Assert.Equal("TimeOnlyObject", method.ReturnType.Name); } + + [Fact] + public async Task ReplacesIndexerDateOnlyTypeWithAbstractedDateType() + { + // Arrange + var requestBuilder = root.AddClass(new CodeClass + { + Name = "requestBuilder" + }).First(); + + requestBuilder.AddIndexer(new CodeIndexer + { + Name = "indexer", + IndexParameter = new CodeParameter + { + Type = new CodeType + { + Name = "DateOnly", + IsExternal = true + } + }, + ReturnType = new CodeType + { + Name = "SomeType" + } + }); + + // Act + await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root); + + // Assert + Assert.Equal("Date", requestBuilder.Indexer.IndexParameter.Type.Name, StringComparer.OrdinalIgnoreCase); + } + + [Fact] + public async Task ReplacesIndexerTimeOnlyTypeWithAbstractedTimeType() + { + // Arrange + var requestBuilder = root.AddClass(new CodeClass + { + Name = "requestBuilder" + }).First(); + + requestBuilder.AddIndexer(new CodeIndexer + { + Name = "indexer", + IndexParameter = new CodeParameter + { + Type = new CodeType + { + Name = "TimeOnly", + IsExternal = true + } + }, + ReturnType = new CodeType + { + Name = "SomeType" + } + }); + + // Act + await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root); + + // Assert + Assert.Equal("Time", requestBuilder.Indexer.IndexParameter.Type.Name, StringComparer.OrdinalIgnoreCase); + } + + [Fact] + public async Task ReplacesIndexerLocallyDefinedDateOnlyTypeWithAbstractedDateType() + { + // Arrange + var requestBuilder = root.AddClass(new CodeClass + { + Name = "requestBuilder" + }).First(); + + var dateOnlyModel = root.AddClass(new CodeClass + { + Name = "DateOnly", + Kind = CodeClassKind.Model + }).First(); + + requestBuilder.AddIndexer(new CodeIndexer + { + Name = "indexer", + IndexParameter = new CodeParameter + { + Type = new CodeType + { + Name = "DateOnly", + IsExternal = false, + TypeDefinition = dateOnlyModel + } + }, + ReturnType = new CodeType + { + Name = "SomeType" + } + }); + + // Act + await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root); + + // Assert + Assert.Equal("DateOnlyObject", requestBuilder.Indexer.IndexParameter.Type.Name, StringComparer.OrdinalIgnoreCase); + } + + [Fact] + public async Task ReplacesIndexerLocallyDefinedTimeOnlyTypeWithAbstractedTimeType() + { + // Arrange + var requestBuilder = root.AddClass(new CodeClass + { + Name = "requestBuilder" + }).First(); + + var timeOnlyModel = root.AddClass(new CodeClass + { + Name = "TimeOnly", + Kind = CodeClassKind.Model + }).First(); + + requestBuilder.AddIndexer(new CodeIndexer + { + Name = "indexer", + IndexParameter = new CodeParameter + { + Type = new CodeType + { + Name = "TimeOnly", + IsExternal = false, + TypeDefinition = timeOnlyModel + } + }, + ReturnType = new CodeType + { + Name = "SomeType" + } + }); + + // Act + await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root); + + // Assert + Assert.Equal("TimeOnlyObject", requestBuilder.Indexer.IndexParameter.Type.Name, StringComparer.OrdinalIgnoreCase); + } + [Fact] public async Task AddsUsingForUntypedNode() { From f78e1d9c2af528b1009532b9858f9e756693f0e3 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 22 Aug 2024 16:13:54 -0400 Subject: [PATCH 2/3] Removed unnecessary using statement. --- src/Kiota.Builder/Refiners/CSharpRefiner.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Kiota.Builder/Refiners/CSharpRefiner.cs b/src/Kiota.Builder/Refiners/CSharpRefiner.cs index ec5eaa26bb..6e6739c035 100644 --- a/src/Kiota.Builder/Refiners/CSharpRefiner.cs +++ b/src/Kiota.Builder/Refiners/CSharpRefiner.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; From 7f351978687556a64a8f61e76258f85d2c3f6624 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 22 Aug 2024 16:15:26 -0400 Subject: [PATCH 3/3] Fixed formatting in CHANGELOG.md. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40c8c7dc0b..83f4e52a26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Reverts modification of responses in output openApi file when generating plugins [#4945](https://github.com/microsoft/kiota/issues/4945) - Expand properties types with null type for Typescript. [#4993](https://github.com/microsoft/kiota-typescript/issues/1188) - Added Collection, HashMap, Map, Objects, InputStream, BigDecimal to the list of reserved names for Java generation. [#5135](https://github.com/microsoft/kiota/issues/5135) -- C# refiner now fixes data types for indexers. [#5201] (https://github.com/microsoft/kiota/issues/5201) +- C# refiner now fixes data types for indexers. [#5201](https://github.com/microsoft/kiota/issues/5201) ## [1.17.0] - 2024-08-09