From dd70b2de2ffdecc856c827d7e43027aee9f7ed96 Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Wed, 5 Jul 2023 17:41:33 +0300 Subject: [PATCH] Fix PHP request executor methods returning enums --- CHANGELOG.md | 1 + .../Writers/Php/CodeMethodWriter.cs | 26 ++++--- .../Writers/Php/CodeMethodWriterTests.cs | 69 +++++++++++++++++++ 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c477f802e..44f7c22c0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix failing PHP integration tests [2378](https://github.com/microsoft/kiota/issues/2378) - Fixed generation of properties with identical names after symbol cleanup. - Prevents method overloading for go getters and setters with different values. [#2719](https://github.com/microsoft/kiota/issues/2719) +- Fixed PHP request executor methods that return enums. ## [1.3.0] - 2023-06-09 diff --git a/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs index c0cce3f5da..8dd0d40edf 100644 --- a/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs @@ -696,7 +696,7 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeClass parentCl joinedParams = string.Join(", ", callParams); } - var returnType = conventions.TranslateType(codeElement.ReturnType); + var returnTypeName = conventions.TranslateType(codeElement.ReturnType); writer.WriteLine($"$requestInfo = $this->{generatorMethodName}({joinedParams});"); writer.WriteLine("try {"); writer.IncreaseIndent(); @@ -716,20 +716,24 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeClass parentCl writer.WriteLine("];"); } - var returnsVoid = returnType.Equals("void", StringComparison.OrdinalIgnoreCase); - var isStream = returnType.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase); + var returnsVoid = returnTypeName.Equals("void", StringComparison.OrdinalIgnoreCase); + var isStream = returnTypeName.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase); var isCollection = codeElement.ReturnType.IsCollection; - var methodName = GetSendRequestMethodName(returnsVoid, isStream, isCollection, returnType); + var isEnum = codeElement.ReturnType is CodeType returnType && returnType.TypeDefinition is CodeEnum; + var methodName = GetSendRequestMethodName(returnsVoid, isStream, isCollection, isEnum, returnTypeName); var returnTypeFactory = codeElement.ReturnType is CodeType rt && rt.TypeDefinition is CodeClass - ? $", [{returnType}::class, '{CreateDiscriminatorMethodName}']" + ? $", [{returnTypeName}::class, '{CreateDiscriminatorMethodName}']" : string.Empty; var returnWithCustomType = - !returnsVoid && string.IsNullOrEmpty(returnTypeFactory) && conventions.CustomTypes.Contains(returnType) - ? $", {returnType}::class" + !returnsVoid && string.IsNullOrEmpty(returnTypeFactory) && conventions.CustomTypes.Contains(returnTypeName) + ? $", {returnTypeName}::class" : returnTypeFactory; - var finalReturn = string.IsNullOrEmpty(returnWithCustomType) && !returnsVoid - ? $", '{returnType}'" + var returnEnumType = codeElement.ReturnType is CodeType codeType && codeType.TypeDefinition is CodeEnum + ? $", {returnTypeName}::class" : returnWithCustomType; + var finalReturn = string.IsNullOrEmpty(returnEnumType) && !returnsVoid + ? $", '{returnTypeName}'" + : returnEnumType; var requestAdapterProperty = parentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter) ?? throw new InvalidOperationException("Request adapter property not found"); writer.WriteLine( $"return {GetPropertyCall(requestAdapterProperty, string.Empty)}->{methodName}({RequestInfoVarName}{finalReturn}, {(hasErrorMappings ? $"{errorMappingsVarName}" : "null")});"); @@ -766,10 +770,10 @@ private static void WriteSerializationRegistration(HashSet serialization writer.WriteLine($"ApiClientBuilder::{methodName}({module}::class);"); } - protected string GetSendRequestMethodName(bool isVoid, bool isStream, bool isCollection, string returnType) + protected string GetSendRequestMethodName(bool isVoid, bool isStream, bool isCollection, bool isEnum, string returnType) { if (isVoid) return "sendNoContentAsync"; - if (isStream || conventions.PrimitiveTypes.Contains(returnType)) + if (isStream || isEnum || conventions.PrimitiveTypes.Contains(returnType)) if (isCollection) return "sendPrimitiveCollectionAsync"; else diff --git a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs index 8fd8cb0c67..a4f7dfb9e3 100644 --- a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs @@ -264,6 +264,75 @@ public async void WriteRequestExecutor() Assert.Contains("return $this->requestAdapter->sendPrimitiveAsync($requestInfo, StreamInterface::class, $errorMappings);", result); } + [Fact] + public async void WritesRequestExecutorForEnumTypes() + { + CodeProperty[] properties = + { + new CodeProperty { Kind = CodePropertyKind.RequestAdapter, Name = "requestAdapter", Type = new CodeType { Name = "string" } }, + new CodeProperty { Kind = CodePropertyKind.UrlTemplate, Name = "urlTemplate", Type = new CodeType { Name = "string" } }, + new CodeProperty { Kind = CodePropertyKind.PathParameters, Name = "pathParameters", Type = new CodeType { Name = "string" } }, + }; + parentClass.AddProperty(properties); + var countryCodeEnum = root.AddEnum(new CodeEnum { Name = "CountryCode" }); + var codeMethod = new CodeMethod + { + Name = "post", + HttpMethod = HttpMethod.Post, + ReturnType = new CodeType + { + IsExternal = true, + Name = "phoneNumberPrefix", + TypeDefinition = countryCodeEnum.First() + }, + Documentation = new() + { + Description = "This will send a POST request", + DocumentationLink = new Uri("https://learn.microsoft.com/"), + DocumentationLabel = "Learning" + }, + Kind = CodeMethodKind.RequestExecutor + }; + var codeMethodRequestGenerator = new CodeMethod + { + Kind = CodeMethodKind.RequestGenerator, + HttpMethod = HttpMethod.Post, + Name = "createPostRequestInformation", + ReturnType = new CodeType + { + Name = "RequestInformation" + } + }; + parentClass.AddMethod(codeMethod); + parentClass.AddMethod(codeMethodRequestGenerator); + var error4XX = root.AddClass(new CodeClass + { + Name = "Error4XX", + }).First(); + var error5XX = root.AddClass(new CodeClass + { + Name = "Error5XX", + }).First(); + var error401 = root.AddClass(new CodeClass + { + Name = "Error401", + }).First(); + codeMethod.AddErrorMapping("4XX", new CodeType { Name = "Error4XX", TypeDefinition = error4XX }); + codeMethod.AddErrorMapping("5XX", new CodeType { Name = "Error5XX", TypeDefinition = error5XX }); + codeMethod.AddErrorMapping("403", new CodeType { Name = "Error403", TypeDefinition = error401 }); + await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.PHP }, root); + _codeMethodWriter.WriteCodeElement(codeMethod, languageWriter); + var result = stringWriter.ToString(); + + Assert.Contains("public function post(): Promise", result); + Assert.Contains("$requestInfo = $this->createPostRequestInformation();", result); + Assert.Contains("RejectedPromise", result); + Assert.Contains("@link https://learn.microsoft.com/ Learning", result); + Assert.Contains("catch(Exception $ex)", result); + Assert.Contains("'403' => [Error403::class, 'createFromDiscriminatorValue']", result); + Assert.Contains("return $this->requestAdapter->sendPrimitiveAsync($requestInfo, PhoneNumberPrefix::class, $errorMappings);", result); + } + public static IEnumerable SerializerProperties => new List { new object[]