Skip to content

Commit

Permalink
[Rgen] Allows to mark a property or accessor to marshal native except…
Browse files Browse the repository at this point in the history
…ions

Properties can also do it. Allow to set the flag and provide a method
that will allow use to know if an accessor should marshal the native
exceptions or not.
  • Loading branch information
mandel-macaque committed Jan 16, 2025
1 parent 02ad356 commit 322c1db
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/ObjCBindings/ExportTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ public enum Property : Int64 {
/// Generate a notification for the property.
/// </summary>
Notification = 1 << 3,

/// <summary>
/// Make a method support native (Objective-C) exceptions. Instead of calling objc_msgSend directly, the invocation
/// will go through a custom trampoline which catches ObjectiveC exceptions and marshals them into managed exceptions.
/// </summary>
MarshalNativeExceptions = 1 << 4,

}
}

11 changes: 11 additions & 0 deletions src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ namespace Microsoft.Macios.Generator.DataModel;
/// The data of the field attribute used to mark the value as a property binding.
/// </summary>
public ExportData<ObjCBindings.Property>? ExportPropertyData { get; init; }

public bool MarshalNativeExceptions
=> ExportPropertyData is not null && ExportPropertyData.Value.Flags.HasFlag (ObjCBindings.Property.MarshalNativeExceptions);

/// <summary>
/// List of attribute code changes of the accessor.
Expand Down Expand Up @@ -57,6 +60,14 @@ public Accessor (AccessorKind accessorKind,
Modifiers = modifiers;
}

/// <summary>
/// Returns if the accessor should marshal native exceptions with the associated property.
/// </summary>
/// <param name="property">The property associated with the accessor.</param>
/// <returns>True if either the accessor or the property were marked with the MarshalNativeExceptions flag.</returns>
public bool ShouldMarshalNativeExceptions (in Property property)
=> MarshalNativeExceptions || property.MarshalNativeExceptions;

/// <inheritdoc />
public bool Equals (Accessor other)
{
Expand Down
5 changes: 5 additions & 0 deletions src/rgen/Microsoft.Macios.Generator/DataModel/Method.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ namespace Microsoft.Macios.Generator.DataModel;
/// </summary>
public ExportData<ObjCBindings.Method> ExportMethodData { get; }

/// <summary>
/// True if the method was exported with the MarshalNativeExceptions flag allowing it to support native exceptions.
/// </summary>
public bool MarshalNativeExceptions => ExportMethodData.Flags.HasFlag (ObjCBindings.Method.MarshalNativeExceptions);

/// <summary>
/// Get the attributes added to the constructor.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions src/rgen/Microsoft.Macios.Generator/DataModel/Property.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ public bool IsNotification
/// Get the attributes added to the member.
/// </summary>
public ImmutableArray<AttributeCodeChange> Attributes { get; } = [];

/// <summary>
/// True if the method was exported with the MarshalNativeExceptions flag allowing it to support native exceptions.
/// </summary>
public bool MarshalNativeExceptions
=> IsProperty && ExportPropertyData.Value.Flags.HasFlag (ObjCBindings.Property.MarshalNativeExceptions);

/// <summary>
/// Get the modifiers of the property.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma warning disable APL0003
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
using Microsoft.Macios.Generator.DataModel;
using ObjCRuntime;
using Xunit;
using static Microsoft.Macios.Generator.Tests.TestDataFactory;

namespace Microsoft.Macios.Generator.Tests.DataModel;

Expand Down Expand Up @@ -308,4 +311,45 @@ public void CompareSameKindSameAttrSameAvailability ()
Assert.True (x == y);
Assert.False (x != y);
}

[Theory]
[InlineData (false, false, false)]
[InlineData (false, true, true)]
[InlineData (true, false, true)]
[InlineData (true, true, true)]
public void ShouldMarshalNativeExceptionsBothFalse (bool propertyHasFlag, bool accessorHasFalg, bool expectedResult)
{
var property = new Property (
name: "MyProperty",
returnType: ReturnTypeForString (),
symbolAvailability: new (),
attributes: [],
modifiers: [],
accessors: []
) {
ExportPropertyData = new (
selector: "selector",
argumentSemantic: ArgumentSemantic.None,
flags: propertyHasFlag ? ObjCBindings.Property.MarshalNativeExceptions : ObjCBindings.Property.Default),
};

var accessor = new Accessor (
accessorKind: AccessorKind.Getter,
symbolAvailability: new (),
exportPropertyData: new (
selector: "selector",
argumentSemantic: ArgumentSemantic.None,
flags: accessorHasFalg ? ObjCBindings.Property.MarshalNativeExceptions : ObjCBindings.Property.Default),
attributes: [
new ("First"),
new ("Second"),
],
modifiers: [
SyntaxFactory.Token (SyntaxKind.PublicKeyword),
SyntaxFactory.Token (SyntaxKind.PrivateKeyword)
]);
Assert.Equal (expectedResult, accessor.ShouldMarshalNativeExceptions (property));
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
using Microsoft.Macios.Generator.DataModel;
using ObjCRuntime;
using Xamarin.Tests;
using Xamarin.Utils;
using Xunit;
Expand Down Expand Up @@ -443,6 +444,44 @@ public class TestClass {
ExportPropertyData = new (selector: "name"),
}
];

const string marshallNativeException = @"
using System;
using ObjCBindings;
namespace Test;
public class TestClass {
[Export<Property>(""name"", Property.MarshalNativeExceptions)]
public string Name { get; }
}
";
yield return [
marshallNativeException,
new Property (
name: "Name",
returnType: ReturnTypeForString (),
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Property>", ["name", "ObjCBindings.Property.MarshalNativeExceptions"])
],
modifiers: [
SyntaxFactory.Token (kind: SyntaxKind.PublicKeyword),
],
accessors: [
new (
accessorKind: AccessorKind.Getter,
symbolAvailability: new (),
exportPropertyData: null,
attributes: [],
modifiers: []
)
]
) {
ExportPropertyData = new (selector: "name", ArgumentSemantic.None, ObjCBindings.Property.MarshalNativeExceptions),
}
];

const string valueTypeProperty = @"
using System;
Expand Down

0 comments on commit 322c1db

Please sign in to comment.