diff --git a/.github/workflows/pre-integration.yml b/.github/workflows/pre-integration.yml index aa57f46e7..a3b4ec146 100644 --- a/.github/workflows/pre-integration.yml +++ b/.github/workflows/pre-integration.yml @@ -89,9 +89,10 @@ jobs: with: dotnet-version: '5.0.x' - - name: 📐 Ensure nuget.org added as package source + - name: 📐 Ensure nuget.org added as package source on Windows if: matrix.os == 'windows-latest' run: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org --configfile $env:APPDATA\NuGet\NuGet.Config + continue-on-error: true - name: 🔁 Restore packages run: dotnet restore diff --git a/docs/CodeDoc/Atc.Rest.ApiGenerator/Atc.Rest.ApiGenerator.Helpers.md b/docs/CodeDoc/Atc.Rest.ApiGenerator/Atc.Rest.ApiGenerator.Helpers.md index d46f91c12..ef6b02d3e 100644 --- a/docs/CodeDoc/Atc.Rest.ApiGenerator/Atc.Rest.ApiGenerator.Helpers.md +++ b/docs/CodeDoc/Atc.Rest.ApiGenerator/Atc.Rest.ApiGenerator.Helpers.md @@ -58,6 +58,11 @@ public static class GenerateAtcCodingRulesHelper ### Static Fields +#### FileNameDirectoryBuildProps + +```csharp +string FileNameDirectoryBuildProps +``` #### FileNameEditorConfig ```csharp diff --git a/docs/CodeDoc/Atc.Rest.ApiGenerator/IndexExtended.md b/docs/CodeDoc/Atc.Rest.ApiGenerator/IndexExtended.md index 92eb1c41e..7637104a9 100644 --- a/docs/CodeDoc/Atc.Rest.ApiGenerator/IndexExtended.md +++ b/docs/CodeDoc/Atc.Rest.ApiGenerator/IndexExtended.md @@ -124,6 +124,7 @@ - HasSharedResponseContract(OpenApiDocument document, List<ApiOperationSchemaMap> operationSchemaMappings, string focusOnSegmentName) - [GenerateAtcCodingRulesHelper](Atc.Rest.ApiGenerator.Helpers.md#generateatccodingruleshelper) - Static Fields + - string FileNameDirectoryBuildProps - string FileNameEditorConfig - Static Methods - Generate(string outputSlnPath, DirectoryInfo outputSrcPath, DirectoryInfo outputTestPath) diff --git a/src/Atc.Rest.ApiGenerator/Factories/ProjectApiFactory.cs b/src/Atc.Rest.ApiGenerator/Factories/ProjectApiFactory.cs index 9868c758f..6b6a35d37 100644 --- a/src/Atc.Rest.ApiGenerator/Factories/ProjectApiFactory.cs +++ b/src/Atc.Rest.ApiGenerator/Factories/ProjectApiFactory.cs @@ -204,6 +204,7 @@ public static string[] CreateUsingListForContractResult( if (responses.HasSchemaTypeOfArray()) { + list.Add("System.Linq"); list.Add("System.Collections.Generic"); } diff --git a/src/Atc.Rest.ApiGenerator/NameConstants.cs b/src/Atc.Rest.ApiGenerator/NameConstants.cs index 30e5820a8..8e37edb2e 100644 --- a/src/Atc.Rest.ApiGenerator/NameConstants.cs +++ b/src/Atc.Rest.ApiGenerator/NameConstants.cs @@ -28,5 +28,7 @@ internal static class NameConstants public const string Handler = "Handler"; public const string ClientRequestParameters = "RequestParameters"; + + public const string AbstractCollectionTypeName = "IEnumerable"; } } diff --git a/src/Atc.Rest.ApiGenerator/SyntaxGenerators/Api/SyntaxGeneratorContractResult.cs b/src/Atc.Rest.ApiGenerator/SyntaxGenerators/Api/SyntaxGeneratorContractResult.cs index e6428a9ea..8a3d550c6 100644 --- a/src/Atc.Rest.ApiGenerator/SyntaxGenerators/Api/SyntaxGeneratorContractResult.cs +++ b/src/Atc.Rest.ApiGenerator/SyntaxGenerators/Api/SyntaxGeneratorContractResult.cs @@ -245,6 +245,16 @@ private List CreateMethods(string className) { methodDeclaration = CreateTypeRequestObjectResult(className, httpStatusCode.ToNormalizedString(), schema.GetDataType(), "response", isList, isPagination); } + else if (schema != null && string.Equals(schema.Type, OpenApiDataTypeConstants.Array, StringComparison.Ordinal)) + { + methodDeclaration = CreateTypeRequestObjectResult( + className, + httpStatusCode.ToNormalizedString(), + schema.Items.GetDataType(), + "response", + isList, + isPagination); + } else { methodDeclaration = CreateTypeRequestWithMessageAllowNull(className, httpStatusCode, nameof(OkObjectResult)); @@ -558,9 +568,13 @@ private static MethodDeclarationSyntax CreateTypeRequestObjectResult( bool asGenericPagination = false) { string? genericListTypeName = null; + string objectResultParameter = asGenericList + ? parameterName + $" ?? Enumerable.Empty<{parameterTypeName}>()" + : parameterName; + if (asGenericList) { - genericListTypeName = Microsoft.OpenApi.Models.NameConstants.List; + genericListTypeName = NameConstants.AbstractCollectionTypeName; } else if (asGenericPagination) { @@ -585,7 +599,7 @@ private static MethodDeclarationSyntax CreateTypeRequestObjectResult( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Argument( SyntaxObjectCreationExpressionFactory.Create(methodName + nameof(ObjectResult)) - .WithArgumentList(SyntaxArgumentListFactory.CreateWithOneItem(parameterName)))))))) + .WithArgumentList(SyntaxArgumentListFactory.CreateWithOneItem(objectResultParameter)))))))) .WithSemicolonToken(SyntaxTokenFactory.Semicolon()); } @@ -669,10 +683,10 @@ private static ConversionOperatorDeclarationSyntax CreateImplicitOperator( SyntaxFactory.IdentifierName(SyntaxFactory.Identifier(className))) .WithModifiers(SyntaxTokenListFactory.PublicStaticKeyword(true)) .WithOperatorKeyword(SyntaxTokenFactory.OperatorKeyword()) - .AddParameterListParameters(SyntaxParameterFactory.Create(typeName, "x", genericListTypeName)) + .AddParameterListParameters(SyntaxParameterFactory.Create(typeName, "response", genericListTypeName)) .WithExpressionBody(SyntaxFactory.ArrowExpressionClause( SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName(SyntaxFactory.Identifier(httpStatus))) - .AddArgumentListArguments(SyntaxArgumentFactory.Create("x"))) + .AddArgumentListArguments(SyntaxArgumentFactory.Create("response"))) .WithArrowToken(SyntaxTokenFactory.EqualsGreaterThan())) .WithSemicolonToken(SyntaxTokenFactory.Semicolon()); } diff --git a/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkArrayTypeResponse.verified.cs b/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkArrayTypeResponse.verified.cs new file mode 100644 index 000000000..913d61ea7 --- /dev/null +++ b/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkArrayTypeResponse.verified.cs @@ -0,0 +1,36 @@ +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Linq; +using Atc.Rest.Results; +using Microsoft.AspNetCore.Mvc; + +//------------------------------------------------------------------------------ +// This code was auto-generated by ApiGenerator x.x.x.x. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +//------------------------------------------------------------------------------ +namespace TestProject.AtcTest.Contracts.Test +{ + /// + /// Results for operation request. + /// Description: Get. + /// Operation: Get. + /// Area: Test. + /// + [GeneratedCode("ApiGenerator", "x.x.x.x")] + public class GetResult : ResultBase + { + private GetResult(ActionResult result) : base(result) { } + + /// + /// 200 - Ok response. + /// + public static GetResult Ok(IEnumerable response) => new GetResult(new OkObjectResult(response ?? Enumerable.Empty())); + + /// + /// Performs an implicit conversion from GetResult to ActionResult. + /// + public static implicit operator GetResult(List response) => Ok(response); + } +} \ No newline at end of file diff --git a/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkArrayTypeResponse.yaml b/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkArrayTypeResponse.yaml new file mode 100644 index 000000000..d7f0ee6a8 --- /dev/null +++ b/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkArrayTypeResponse.yaml @@ -0,0 +1,17 @@ +openapi: 3.0.0 +paths: + /: + get: + summary: Get + description: Get + operationId: get + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + type: string \ No newline at end of file diff --git a/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkResponse.verified.cs b/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkResponse.verified.cs index 047297a4d..80b6cb674 100644 --- a/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkResponse.verified.cs +++ b/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkResponse.verified.cs @@ -12,23 +12,23 @@ namespace TestProject.AtcTest.Contracts.Test { /// /// Results for operation request. - /// Description: Get all users. - /// Operation: GetUsers. + /// Description: Get. + /// Operation: Get. /// Area: Test. /// [GeneratedCode("ApiGenerator", "x.x.x.x")] - public class GetUsersResult : ResultBase + public class GetResult : ResultBase { - private GetUsersResult(ActionResult result) : base(result) { } + private GetResult(ActionResult result) : base(result) { } /// /// 200 - Ok response. /// - public static GetUsersResult Ok(string? message = null) => new GetUsersResult(new OkObjectResult(message)); + public static GetResult Ok(string? message = null) => new GetResult(new OkObjectResult(message)); /// - /// Performs an implicit conversion from GetUsersResult to ActionResult. + /// Performs an implicit conversion from GetResult to ActionResult. /// - public static implicit operator GetUsersResult(string x) => Ok(x); + public static implicit operator GetResult(string response) => Ok(response); } } \ No newline at end of file diff --git a/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkResponse.yaml b/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkResponse.yaml index 3f764225f..264cf8957 100644 --- a/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkResponse.yaml +++ b/test/Atc.Rest.ApiGenerator.Tests/SyntaxGenerators/Api/XUnitTestData/ContractResult/getOkResponse.yaml @@ -1,15 +1,15 @@ openapi: 3.0.0 paths: - /users: + /: get: - summary: Get all users - description: Get all users - operationId: getUsers + summary: Get + description: Get + operationId: get tags: [] responses: '200': description: OK content: - application/json: + text/plain: schema: - $ref: '#/components/schemas/Users' \ No newline at end of file + type: string \ No newline at end of file