diff --git a/CHANGELOG.md b/CHANGELOG.md index ef79d80849..64a36d356c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed a bug where untyped not imports in TypeScripts would not be erasable. [microsoft/kiota-typescript#1381](https://github.com/microsoft/kiota-typescript/issues/1381) - Updated schema link in plugin manifest to the correct url. [#5441](https://github.com/microsoft/kiota/issues/5441) - Removed registration of default serialization and deserialization classes in client constructor. [#5478](https://github.com/microsoft/kiota/pull/5478) +- Fixed incorrect type name generation in aliased scenario in TS due to broad searching of types in root namespaces. [#5404](https://github.com/microsoft/kiota/issues/5404) ## [1.18.0] - 2024-09-05 diff --git a/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs b/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs index 1b3b2b22e8..ebb98ab309 100644 --- a/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs +++ b/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs @@ -295,9 +295,9 @@ public static string GetFactoryMethodName(CodeTypeBase targetClassType, CodeElem throw new InvalidOperationException($"Unable to find factory method for {targetClassType}"); } - private static CodeFunction? GetFactoryMethod(CodeInterface definitionClass, string factoryMethodName) + internal static CodeFunction? GetFactoryMethod(CodeInterface definitionClass, string factoryMethodName) { - return definitionClass.GetImmediateParentOfType(definitionClass)?.FindChildByName(factoryMethodName); + return definitionClass.GetImmediateParentOfType(definitionClass)?.FindChildByName(factoryMethodName); } public string GetDeserializationMethodName(CodeTypeBase codeType, CodeMethod method, bool? IsCollection = null) diff --git a/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs b/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs index f26cbb41e8..540f49f10d 100644 --- a/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs +++ b/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs @@ -594,6 +594,82 @@ public async Task AliasesDuplicateUsingSymbolsAsync() Assert.DoesNotContain(modelInterface.Usings, x => x.Declaration?.TypeDefinition == source2Interface); Assert.DoesNotContain(modelInterface.Usings, x => x.Declaration?.TypeDefinition == source1Interface); } + + [Fact] + public async Task AliasesDuplicateUsingSymbolsAsyncWithAliasedReferencesToParentNamespaceAsync() + { + var generationConfiguration = new GenerationConfiguration { Language = GenerationLanguage.TypeScript }; + var source1 = TestHelper.CreateModelClassInModelsNamespace(generationConfiguration, root, "source"); + var modelsNS = root.FindNamespaceByName(generationConfiguration.ModelsNamespaceName); + Assert.NotNull(modelsNS); + var submodelsNS = modelsNS.AddNamespace($"{generationConfiguration.ModelsNamespaceName}.submodels"); + var source2 = TestHelper.CreateModelClass(submodelsNS, "source"); + var model = TestHelper.CreateModelClass(submodelsNS, "model"); + + var source1Factory = new CodeMethod + { + Name = "factory", + Kind = CodeMethodKind.Factory, + IsAsync = false, + IsStatic = true, + ReturnType = new CodeType { Name = "source", TypeDefinition = source2, }, + }; + source1.AddMethod(source1Factory); + + var using1 = new CodeUsing + { + Name = modelsNS.Name, + Declaration = new CodeType + { + Name = source1.Name, + TypeDefinition = source1, + IsExternal = false, + } + }; + + var source2Factory = new CodeMethod + { + Name = "factory", + Kind = CodeMethodKind.Factory, + IsAsync = false, + IsStatic = true, + ReturnType = new CodeType { Name = "source", TypeDefinition = source2 }, + }; + + source2.AddMethod(source2Factory); + var using2 = new CodeUsing + { + Name = submodelsNS.Name, + Declaration = new CodeType + { + Name = source2.Name, + TypeDefinition = source2, + IsExternal = false, + } + }; + model.AddUsing(using1); + var property1 = new CodeProperty { Name = "source1", Type = new CodeType { TypeDefinition = source1, } }; + model.AddProperty(property1); + var property2 = new CodeProperty { Name = "source2", Type = new CodeType { TypeDefinition = source2, } }; + model.AddProperty(property2); + model.AddUsing(using2); + await ILanguageRefiner.RefineAsync(new GenerationConfiguration { Language = GenerationLanguage.TypeScript }, root); + + var sourceCodeFile = modelsNS.FindChildByName(IndexFileName, false); + Assert.NotNull(sourceCodeFile); + var source1Interface = sourceCodeFile.Interfaces.First(x => x.Name == source1.Name.ToFirstCharacterUpperCase()); + + var modelCodeFile = submodelsNS.FindChildByName(IndexFileName, false); + Assert.NotNull(modelCodeFile); + var source2Interface = modelCodeFile.Interfaces.First(x => x.Name == source1.Name.ToFirstCharacterUpperCase()); + + var result1 = Kiota.Builder.Writers.TypeScript.TypeScriptConventionService.GetFactoryMethod(source1Interface, "createSourceFromDiscriminatorValue"); + Assert.NotNull(result1); + var result2 = Kiota.Builder.Writers.TypeScript.TypeScriptConventionService.GetFactoryMethod(source2Interface, "createSourceFromDiscriminatorValue"); + Assert.NotNull(result2); + Assert.NotEqual(result1, result2);// they should be different discriminators despite having the same name + } + [Fact] public async Task DoesNotKeepCancellationParametersInRequestExecutorsAsync() {