From 5c242ecc1dc5ef1a3a3d8b4df2c1ee421d689527 Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Wed, 29 Jan 2025 10:16:47 -0500 Subject: [PATCH] [Rgen] Add needed factory methods to cast an enum to its primitive type. (#22062) Case to the underlying type if it is not a smart enum, else use the CastToNative method. --------- Co-authored-by: Alex Soto Co-authored-by: GitHub Actions Autoformatter --- .../BindingSyntaxFactory.ObjCRuntime.cs | 35 ++++++++++++-- .../BindingSyntaxFactoryObjCRuntimeTests.cs | 48 +++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.ObjCRuntime.cs b/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.ObjCRuntime.cs index ec0622d4dbc..6e15c444276 100644 --- a/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.ObjCRuntime.cs +++ b/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.ObjCRuntime.cs @@ -23,9 +23,9 @@ static partial class BindingSyntaxFactory { /// /// Returns the expression needed to cast a parameter to its native type. /// - /// The parameter whose castin we need to generate. The type info has to be - /// and enum and be marked as native. If it is not the method returns null - /// + /// The parameter whose casting we need to generate. The type info has to be + /// and enum and be marked as native. If it is not, the method returns null + /// The cast C# expression. internal static CastExpressionSyntax? CastToNative (in Parameter parameter) { // not an enum and not a native value. we cannot calculate the casting expression. @@ -48,6 +48,35 @@ static partial class BindingSyntaxFactory { return castExpression; } + /// + /// Returns the expression needed to cast an enum parameter to its primitive type to be used in marshaling. + /// + /// The parameter for which we need to generate the casting. The type info has to be + /// an enumerator. If it is not, the method returns null. + /// The cast C# expression. + internal static CastExpressionSyntax? CastToPrimitive (in Parameter parameter) + { + if (!parameter.Type.IsEnum) { + return null; + } + + if (parameter.Type.IsNativeEnum) { + // return the native casting + return CastToNative (parameter); + } + + // returns the enum primitive to be used + var marshalType = parameter.Type.ToMarshallType (); + if (marshalType is null) + return null; + + // (byte) parameter + var castExpression = CastExpression ( + type: IdentifierName (marshalType), + expression: IdentifierName (parameter.Name).WithLeadingTrivia (Space)); + return castExpression; + } + /// /// Returns the expression needed to cast a bool to a byte to be used in a native call. /// diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/BindingSyntaxFactoryObjCRuntimeTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/BindingSyntaxFactoryObjCRuntimeTests.cs index 4a34d717499..291949b30b3 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/BindingSyntaxFactoryObjCRuntimeTests.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/BindingSyntaxFactoryObjCRuntimeTests.cs @@ -63,6 +63,54 @@ void CastToNativeTests (Parameter parameter, string? expectedCast) } } + class TestDataCastToPrimitive : IEnumerable { + public IEnumerator GetEnumerator () + { + // not enum parameter + var boolParam = new Parameter ( + position: 0, + type: ReturnTypeForBool (), + name: "myParam"); + yield return [boolParam, null!]; + + var enumParam = new Parameter ( + position: 0, + type: ReturnTypeForEnum ("MyEnum", isNativeEnum: false), + name: "myParam"); + + yield return [enumParam, "(int) myParam"]; + + var byteParam = new Parameter ( + position: 0, + type: ReturnTypeForEnum ("MyEnum", isNativeEnum: false, underlyingType: SpecialType.System_Byte), + name: "myParam"); + + yield return [byteParam, "(byte) myParam"]; + + + var longParam = new Parameter ( + position: 0, + type: ReturnTypeForEnum ("MyEnum", isNativeEnum: false, underlyingType: SpecialType.System_Int64), + name: "myParam"); + + yield return [longParam, "(long) myParam"]; + } + IEnumerator IEnumerable.GetEnumerator () => GetEnumerator (); + } + + [Theory] + [ClassData (typeof (TestDataCastToPrimitive))] + void CastToPrimitiveTests (Parameter parameter, string? expectedCast) + { + var expression = CastToPrimitive (parameter); + if (expectedCast is null) { + Assert.Null (expression); + } else { + Assert.NotNull (expression); + Assert.Equal (expectedCast, expression?.ToString ()); + } + } + [Fact] void CastToByteTests () {