Skip to content

Commit

Permalink
[Rgen] Generate casting expressions for native enums.
Browse files Browse the repository at this point in the history
  • Loading branch information
mandel-macaque committed Jan 27, 2025
1 parent fba23cf commit 7a347a9
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ public override int GetHashCode ()
const string IntPtr = "IntPtr";
const string UIntPtr = "UIntPtr";

public string? ToMarshallType (ReferenceKind referenceKind)
public string? ToMarshallType ()
{
#pragma warning disable format
var type = this switch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,48 @@
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.DataModel;
using Microsoft.Macios.Generator.Extensions;
using TypeInfo = Microsoft.Macios.Generator.DataModel.TypeInfo;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace Microsoft.Macios.Generator.Emitters;

static partial class BindingSyntaxFactory {
readonly static string objc_msgSend = "objc_msgSend";
readonly static string objc_msgSendSuper = "objc_msgSendSuper";

/// <summary>
/// Returns the expression needed to cast a parameter to its native type.
/// </summary>
/// <param name="parameter">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</param>
/// <returns></returns>
internal static CastExpressionSyntax? CastToNative (in Parameter parameter)
{
// not an enum and not a native value. we cannot calculate the casting expression.
if (!parameter.Type.IsEnum || !parameter.Type.IsNativeEnum)
return null;

// build a casting expression based on the marshall type of the typeinfo
var marshalType = parameter.Type.ToMarshallType ();
if (marshalType == null)
// cannot calculate the marshal, return null
return null;

var enumBackingValue = parameter.Type.EnumUnderlyingType.Value.GetKeyword ();
var castExpression = CastExpression (IdentifierName (marshalType), // (IntPtr/UIntPtr) cast
CastExpression (
IdentifierName (enumBackingValue),
IdentifierName (parameter.Name)
.WithLeadingTrivia (Space))
.WithLeadingTrivia (Space)); // (backingfield) (variable) cast
return castExpression;
}

static string? GetObjCMessageSendMethodName<T> (ExportData<T> exportData,
TypeInfo returnType, ImmutableArray<Parameter> parameters, bool isSuper = false, bool isStret = false) where T : Enum
{
Expand All @@ -42,7 +73,7 @@ static partial class BindingSyntaxFactory {
}

// return types do not have a reference kind
sb.Append (returnType.ToMarshallType (ReferenceKind.None));
sb.Append (returnType.ToMarshallType ());
sb.Append ('_');
// append the msg method based if it is for super or not, do not append '_' intimidatingly, since if we do
// not have parameters, we are done
Expand All @@ -53,7 +84,7 @@ static partial class BindingSyntaxFactory {
// loop over params and get their native handler name
if (parameters.Length > 0) {
sb.Append ('_');
sb.AppendJoin ('_', parameters.Select (p => p.Type.ToMarshallType (p.ReferenceKind)));
sb.AppendJoin ('_', parameters.Select (p => p.Type.ToMarshallType ()));
}

// check if we do have a custom marshall exception set for the export
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static class SpecialTypeExtensions {
/// </summary>
/// <param name="self">The special type to convert.</param>
/// <returns>The string representation of the keyword.</returns>
public static string? GetKeyword (this SpecialType self)
public static string GetKeyword (this SpecialType self)
{
var kind = self switch {
SpecialType.System_Void => SyntaxKind.VoidKeyword,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ void ToMarshallType (ApplePlatform platform, string inputText, string expectedTy
Assert.NotNull (declaration);
Assert.True (Property.TryCreate (declaration, semanticModel, out var changes));
Assert.NotNull (changes);
var marshall = changes.Value.ReturnType.ToMarshallType (ReferenceKind.None);
var marshall = changes.Value.ReturnType.ToMarshallType ();
Assert.NotNull (marshall);
Assert.Equal (expectedTypeName, marshall);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Collections;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.Macios.Generator.DataModel;
using Xunit;
using static Microsoft.Macios.Generator.Emitters.BindingSyntaxFactory;
using static Microsoft.Macios.Generator.Tests.TestDataFactory;

namespace Microsoft.Macios.Generator.Tests.Emitters;

public class BindingSyntaxFactoryObjCRuntimeTests {

class TestDataCodeChangesFromClassDeclaration : IEnumerable<object []> {
public IEnumerator<object []> GetEnumerator ()
{

// not enum parameter
var boolParam = new Parameter (
position: 0,
type: ReturnTypeForBool (),
name: "myParam");
yield return [boolParam, null!];

// not smart enum parameter
var enumParam = new Parameter (
position: 0,
type: ReturnTypeForEnum ("MyEnum", isNativeEnum: false),
name: "myParam");

yield return [enumParam, null!];

// int64
var byteEnum = new Parameter (
position: 0,
type: ReturnTypeForEnum ("MyEnum", isNativeEnum: true, underlyingType: SpecialType.System_Int64),
name: "myParam");
yield return [byteEnum, "(IntPtr) (long) myParam"];

// uint64
var int64Enum = new Parameter (
position: 0,
type: ReturnTypeForEnum ("MyEnum", isNativeEnum: true, underlyingType: SpecialType.System_UInt64),
name: "myParam");
yield return [int64Enum, "(UIntPtr) (ulong) myParam"];
}

IEnumerator IEnumerable.GetEnumerator () => GetEnumerator ();
}

[Theory]
[ClassData(typeof(TestDataCodeChangesFromClassDeclaration))]
void CastToNativeTests (Parameter parameter, string? expectedCast)
{
var expression = CastToNative (parameter);
if (expectedCast is null) {
Assert.Null (expression);
} else {
Assert.NotNull (expression);
Assert.Equal (expectedCast, expression?.ToString ());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ public static TypeInfo ReturnTypeForStruct (string structName)
isStruct: true
) { Parents = ["System.ValueType", "object"] };

public static TypeInfo ReturnTypeForEnum (string enumName, bool isSmartEnum = false, bool isNativeEnum = false)
public static TypeInfo ReturnTypeForEnum (string enumName, bool isSmartEnum = false, bool isNativeEnum = false,
SpecialType underlyingType = SpecialType.System_Int32)
=> new (
name: enumName,
isBlittable: true,
Expand All @@ -199,7 +200,7 @@ public static TypeInfo ReturnTypeForEnum (string enumName, bool isSmartEnum = fa
"System.ISpanFormattable"
],
IsNativeEnum = isNativeEnum,
EnumUnderlyingType = SpecialType.System_Int32,
EnumUnderlyingType = underlyingType,
};

public static TypeInfo ReturnTypeForArray (string type, bool isNullable = false, bool isBlittable = false)
Expand Down

0 comments on commit 7a347a9

Please sign in to comment.