diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs index edf8e32b..af2b66b4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Text; using Microsoft.OData.Edm; @@ -145,7 +146,9 @@ private string FunctionName(IEdmFunction function, OpenApiConvertSettings settin { string uniqueName = Utils.GetUniqueName(p.Name, parameters); var quote = p.Type.Definition.ShouldPathParameterBeQuoted(settings) ? "'" : string.Empty; - return p.Name + $"={quote}{{{uniqueName}}}{quote}"; + return p is IEdmOptionalParameter + ? p.Name + $"={quote}@{uniqueName}{quote}" + : p.Name + $"={quote}{{{uniqueName}}}{quote}"; }))); functionName.Append(")"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs index cbd2e01d..d273f435 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs @@ -81,7 +81,8 @@ public static IList CreateParameters(this ODataContext context } } - OpenApiParameter parameter; + OpenApiParameter parameter; + bool isOptionalParameter = edmParameter is IEdmOptionalParameter; if (edmParameter.Type.IsStructured() || edmParameter.Type.IsCollection()) { @@ -121,7 +122,6 @@ public static IList CreateParameters(this ODataContext context else { // Primitive parameters use the same type mapping as described for primitive properties. - bool isOptionalParameter = edmParameter is IEdmOptionalParameter; parameter = new OpenApiParameter { Name = parameterNameMapping == null ? edmParameter.Name : parameterNameMapping[edmParameter.Name], @@ -134,7 +134,9 @@ public static IList CreateParameters(this ODataContext context if (parameterNameMapping != null) { var quote = edmParameter.Type.Definition.ShouldPathParameterBeQuoted(context.Settings) ? "'" : string.Empty; - parameter.Description = $"Usage: {edmParameter.Name}={quote}{{{parameterNameMapping[edmParameter.Name]}}}{quote}"; + parameter.Description = isOptionalParameter + ? $"Usage: {edmParameter.Name}={quote}@{parameterNameMapping[edmParameter.Name]}{quote}" + : $"Usage: {edmParameter.Name}={quote}{{{parameterNameMapping[edmParameter.Name]}}}{quote}"; } parameters.Add(parameter); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationSegmentTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationSegmentTests.cs index a571bdb5..2030cd61 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationSegmentTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationSegmentTests.cs @@ -4,7 +4,6 @@ // ------------------------------------------------------------ using System; -using System.Runtime.CompilerServices; using Microsoft.OData.Edm; using Xunit; @@ -74,10 +73,10 @@ public void GetPathItemNameReturnsCorrectActionLiteral(bool unqualifiedCall, boo } [Theory] - [InlineData(true, true, "MyFunction(param={param})")] - [InlineData(true, false, "MyFunction(entity={entity},param={param})")] - [InlineData(false, true, "NS.MyFunction(param={param})")] - [InlineData(false, false, "NS.MyFunction(entity={entity},param={param})")] + [InlineData(true, true, "MyFunction(param={param},param2=@param2)")] + [InlineData(true, false, "MyFunction(entity={entity},param={param},param2=@param2)")] + [InlineData(false, true, "NS.MyFunction(param={param},param2=@param2)")] + [InlineData(false, false, "NS.MyFunction(entity={entity},param={param},param2=@param2)")] public void GetPathItemNameReturnsCorrectFunctionLiteral(bool unqualifiedCall, bool isBound, string expected) { // Arrange & Act @@ -85,6 +84,7 @@ public void GetPathItemNameReturnsCorrectFunctionLiteral(bool unqualifiedCall, b IEdmTypeReference parameterType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Boolean, isNullable: false); EdmFunction boundFunction = BoundFunction("MyFunction", isBound, entityTypeReference); boundFunction.AddParameter("param", parameterType); + boundFunction.AddOptionalParameter("param2", parameterType); var segment = new ODataOperationSegment(boundFunction); OpenApiConvertSettings settings = new OpenApiConvertSettings @@ -97,10 +97,10 @@ public void GetPathItemNameReturnsCorrectFunctionLiteral(bool unqualifiedCall, b } [Theory] - [InlineData(true, true, "{param}")] - [InlineData(true, false, "NS.MyFunction(param='{param}')")] - [InlineData(false, true, "NS.MyFunction(param='{param}')")] - [InlineData(false, false, "NS.MyFunction(param='{param}')")] + [InlineData(true, true, "{param2}")] + [InlineData(true, false, "NS.MyFunction(param='{param}',param2='@param2')")] + [InlineData(false, true, "NS.MyFunction(param='{param}',param2='@param2')")] + [InlineData(false, false, "NS.MyFunction(param='{param}',param2='@param2')")] public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedFunction(bool isEscapedFunction, bool enableEscapeFunctionCall, string expected) { // Arrange & Act @@ -108,6 +108,7 @@ public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedFunction(bool IEdmTypeReference parameterType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.String, isNullable: false); EdmFunction boundFunction = BoundFunction("MyFunction", true, entityTypeReference); boundFunction.AddParameter("param", parameterType); + boundFunction.AddOptionalParameter("param2", parameterType); var segment = new ODataOperationSegment(boundFunction, isEscapedFunction); OpenApiConvertSettings settings = new OpenApiConvertSettings @@ -121,10 +122,10 @@ public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedFunction(bool } [Theory] - [InlineData(true, true, "{param}:")] - [InlineData(true, false, "NS.MyFunction(param='{param}')")] - [InlineData(false, true, "NS.MyFunction(param='{param}')")] - [InlineData(false, false, "NS.MyFunction(param='{param}')")] + [InlineData(true, true, "{param2}:")] + [InlineData(true, false, "NS.MyFunction(param='{param}',param2='@param2')")] + [InlineData(false, true, "NS.MyFunction(param='{param}',param2='@param2')")] + [InlineData(false, false, "NS.MyFunction(param='{param}',param2='@param2')")] public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedComposableFunction(bool isEscapedFunction, bool enableEscapeFunctionCall, string expected) { // Arrange & Act @@ -132,6 +133,7 @@ public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedComposableFunc IEdmTypeReference parameterType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.String, isNullable: false); EdmFunction boundFunction = BoundFunction("MyFunction", true, entityTypeReference, true); boundFunction.AddParameter("param", parameterType); + boundFunction.AddOptionalParameter("param2", parameterType); var segment = new ODataOperationSegment(boundFunction, isEscapedFunction); OpenApiConvertSettings settings = new OpenApiConvertSettings