Skip to content

Commit

Permalink
Merge pull request microsoft#2854 from microsoft/fix/php-requestexecu…
Browse files Browse the repository at this point in the history
…tor-enum

Fix PHP request executor methods returning enums
  • Loading branch information
Ndiritu authored Jul 6, 2023
2 parents 8e3fe8e + dd70b2d commit b6ee9fb
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
26 changes: 15 additions & 11 deletions src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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")});");
Expand Down Expand Up @@ -766,10 +770,10 @@ private static void WriteSerializationRegistration(HashSet<string> 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
Expand Down
69 changes: 69 additions & 0 deletions tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<object[]> SerializerProperties => new List<object[]>
{
new object[]
Expand Down

0 comments on commit b6ee9fb

Please sign in to comment.