Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/ObjCBindings/ExportAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class ExportAttribute<T> : Attribute where T : Enum {
/// <summary>
/// The type of the result for an async method.
/// </summary>
public TypeInfo? ResultType { get; set; } = null;
public Type? ResultType { get; set; } = null;

/// <summary>
/// The name of the generated async method.
Expand All @@ -71,6 +71,16 @@ public class ExportAttribute<T> : Attribute where T : Enum {
/// </summary>
public string? PostNonResultSnippet { get; set; } = null;

/// <summary>
/// The type of the strong delegate for a weak delegate property.
/// </summary>
public Type? StrongDelegateType { get; set; } = null;

/// <summary>
/// The name of the strong delegate for a weak delegate property.
/// </summary>
public string? StrongDelegateName { get; set; } = null;

protected ExportAttribute () { }

/// <summary>
Expand Down
14 changes: 8 additions & 6 deletions src/arkit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
// Copyright 2017 Microsoft Inc. All rights reserved.
//

#nullable enable

using System;
using System.ComponentModel;
using System.Numerics;
Expand Down Expand Up @@ -724,7 +726,7 @@ interface ARReferenceImage : NSCopying {
[iOS (13, 0)]
[Async]
[Export ("validateWithCompletionHandler:")]
void Validate (Action<NSError> completionHandler);
void Validate (Action<NSError?> completionHandler);

/// <param name="image">To be added.</param>
/// <param name="orientation">To be added.</param>
Expand Down Expand Up @@ -1010,7 +1012,7 @@ interface ARSession {
<remarks>To be added.</remarks>
""")]
[Export ("getCurrentWorldMapWithCompletionHandler:")]
void GetCurrentWorldMap (Action<ARWorldMap, NSError> completionHandler);
void GetCurrentWorldMap (Action<ARWorldMap?, NSError?> completionHandler);

[Async (XmlDocs = """
<param name="transform">The transform to the position and orientation of the region from which to create a reference object.</param>
Expand All @@ -1022,7 +1024,7 @@ interface ARSession {
""")]
[MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")]
[Export ("createReferenceObjectWithTransform:center:extent:completionHandler:")]
void CreateReferenceObject (Matrix4 transform, Vector3 center, Vector3 extent, Action<ARReferenceObject, NSError> completionHandler);
void CreateReferenceObject (Matrix4 transform, Vector3 center, Vector3 extent, Action<ARReferenceObject?, NSError?> completionHandler);

[iOS (13, 0)]
[Export ("raycast:")]
Expand All @@ -1047,7 +1049,7 @@ interface ARSession {
[iOS (16, 0)]
[Async]
[Export ("captureHighResolutionFrameWithCompletion:")]
void CaptureHighResolutionFrame (Action<ARFrame, NSError> handler);
void CaptureHighResolutionFrame (Action<ARFrame?, NSError?> handler);
}

/// <summary>Interface defining methods that respond to events in an <see cref="ARKit.ARSession" />.</summary>
Expand Down Expand Up @@ -2696,12 +2698,12 @@ interface ARGeoTrackingConfiguration {
[Async]
[Static]
[Export ("checkAvailabilityWithCompletionHandler:")]
void CheckAvailability (Action<bool, NSError> completionHandler);
void CheckAvailability (Action<bool, NSError?> completionHandler);

[Async]
[Static]
[Export ("checkAvailabilityAtCoordinate:completionHandler:")]
void CheckAvailability (CLLocationCoordinate2D coordinate, Action<bool, NSError> completionHandler);
void CheckAvailability (CLLocationCoordinate2D coordinate, Action<bool, NSError?> completionHandler);

[Static]
[Export ("new")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11">
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="4.14.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.9.2" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2"/>
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="4.14.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.9.2"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" />
</ItemGroup>

<ItemGroup>
Expand Down
30 changes: 29 additions & 1 deletion src/rgen/Microsoft.Macios.Generator/Attributes/ExportData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ namespace Microsoft.Macios.Generator.Attributes;
/// </summary>
public string? PostNonResultSnippet { get; init; }

/// <summary>
/// The type of the strong delegate for a weak delegate property.
/// </summary>
public TypeInfo? StrongDelegateType { get; init; }

/// <summary>
/// The name of the strong delegate for a weak delegate property.
/// </summary>
public string? StrongDelegateName { get; init; }

public ExportData () { }

public ExportData (string? selector)
Expand Down Expand Up @@ -119,6 +129,9 @@ public static bool TryParse (AttributeData attributeData,
string? methodName = null;
string? resultTypeName = null;
string? postNonResultSnippet = null;
// weak delegate related data
TypeInfo? strongDelegateType = null;
string? strongDelegateName = null;

switch (count) {
case 1:
Expand Down Expand Up @@ -163,6 +176,7 @@ public static bool TryParse (AttributeData attributeData,

// from this point we have to check the name of the argument AND if the export method is an Async method.
var isAsync = typeof (T) == typeof (ObjCBindings.Method) && flags is not null && flags.HasFlag (ObjCBindings.Method.Async);
var isWeakDelegate = typeof (T) == typeof (ObjCBindings.Property) && flags is not null && flags.HasFlag (ObjCBindings.Property.WeakDelegate);

// loop over all the named arguments and set the data accordingly, ignore the Flags one since we already set it
foreach (var (name, value) in attrsDict) {
Expand Down Expand Up @@ -206,6 +220,17 @@ public static bool TryParse (AttributeData attributeData,
postNonResultSnippet = (string?) value;
}
break;
// weak delegate related data
case "StrongDelegateType":
if (isWeakDelegate) {
strongDelegateType = new ((INamedTypeSymbol) value!);
}
break;
case "StrongDelegateName":
if (isWeakDelegate) {
strongDelegateName = (string?) value!;
}
break;
default:
data = null;
return false;
Expand All @@ -221,7 +246,10 @@ public static bool TryParse (AttributeData attributeData,
ResultType = isAsync ? resultType : null,
MethodName = isAsync ? methodName : null,
ResultTypeName = isAsync ? resultTypeName : null,
PostNonResultSnippet = isAsync ? postNonResultSnippet : null
PostNonResultSnippet = isAsync ? postNonResultSnippet : null,
// we set the data for the weak delegate only if the flags are set
StrongDelegateType = isWeakDelegate ? strongDelegateType : null,
StrongDelegateName = isWeakDelegate ? strongDelegateName : null
};
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,19 @@ public bool Equals (Property other)
return RequiresDirtyCheck == other.RequiresDirtyCheck;
}

public Property ToStrongDelegate ()
{
// has to be a property, weak delegate and have its strong delegate type set
if (!IsProperty || !IsWeakDelegate || ExportPropertyData.Value.StrongDelegateType is null)
return this;

// update the return type, all the rest is the same
return this with {
Name = ExportPropertyData.Value.StrongDelegateName ?? Name.Remove (0, 4 /* "Weak".Length */),
ReturnType = ExportPropertyData.Value.StrongDelegateType.Value.WithNullable (true),
};
}

/// <inheritdoc />
public override string ToString ()
{
Expand Down
2 changes: 1 addition & 1 deletion src/rgen/Microsoft.Macios.Generator/DataModel/Property.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace Microsoft.Macios.Generator.DataModel;
/// <summary>
/// Name of the property.
/// </summary>
public string Name { get; } = string.Empty;
public string Name { get; init; } = string.Empty;

readonly string? backingField = null;

Expand Down
15 changes: 7 additions & 8 deletions src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -556,20 +556,19 @@ public TypeInfo ToArrayElementType ()
}

/// <summary>
/// If the current <see cref="TypeInfo"/> is nullable, this method returns a new <see cref="TypeInfo"/>
/// representing the non-nullable version of the type. Otherwise, it returns the current instance.
/// Returns a new <see cref="TypeInfo"/> with the specified nullability.
/// </summary>
/// <param name="isNullable">A boolean value indicating whether the new type should be nullable.</param>
/// <returns>
/// A new <see cref="TypeInfo"/> instance with <see cref="IsNullable"/> set to false if the original <see cref="IsNullable"/> was true;
/// otherwise, returns the current <see cref="TypeInfo"/> instance.
/// A new <see cref="TypeInfo"/> instance with the specified nullability. If the current instance already has the
/// specified nullability, the current instance is returned.
/// </returns>
public TypeInfo ToNonNullable ()
public TypeInfo WithNullable (bool isNullable)
{
if (!IsNullable)
if (IsNullable == isNullable)
return this;
// copy all the elements from the current array type and set the array type to false
return this with {
IsNullable = false,
IsNullable = isNullable,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1229,12 +1229,12 @@ internal static SyntaxNode ThrowIfNull (string variableName)

// NSObject[] => CFArray.ArrayFromHandle<Foundation.NSMetadataItem> (global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, Selector.GetHandle ("results")))!;
{ Type.IsArray: true, Type.ArrayElementTypeIsWrapped: true }
=> GetCFArrayFromHandle (info.Type.ToArrayElementType ().ToNonNullable ().GetIdentifierSyntax (), [
=> GetCFArrayFromHandle (info.Type.ToArrayElementType ().WithNullable (isNullable: false).GetIdentifierSyntax (), [
Argument (expression)
], suppressNullableWarning: !info.Type.IsNullable),

{ Type.IsArray: true, Type.ArrayElementIsINativeObject: true }
=> GetCFArrayFromHandle (info.Type.ToArrayElementType ().ToNonNullable ().GetIdentifierSyntax (), [
=> GetCFArrayFromHandle (info.Type.ToArrayElementType ().WithNullable (isNullable: false).GetIdentifierSyntax (), [
Argument (expression)
], suppressNullableWarning: !info.Type.IsNullable),

Expand All @@ -1244,7 +1244,7 @@ internal static SyntaxNode ThrowIfNull (string variableName)
// Runtime.GetINativeObject<NSString> (auxVariable, false)!;
{ Type.IsINativeObject: true, Type.IsNSObject: false, ReleaseHandle: not null}
=> GetINativeObject (
nsObjectType: info.Type.ToNonNullable ().GetIdentifierSyntax (),
nsObjectType: info.Type.WithNullable (isNullable: false).GetIdentifierSyntax (),
args: [
Argument (expression),
BoolArgument (info.ReleaseHandle.Value)
Expand All @@ -1253,7 +1253,7 @@ internal static SyntaxNode ThrowIfNull (string variableName)

{ Type.IsINativeObject: true, Type.IsNSObject: false, ReleaseHandle: null}
=> GetINativeObject (
nsObjectType: info.Type.ToNonNullable ().GetIdentifierSyntax (),
nsObjectType: info.Type.WithNullable (isNullable: false).GetIdentifierSyntax (),
args: [
Argument (expression),
],
Expand All @@ -1263,7 +1263,7 @@ internal static SyntaxNode ThrowIfNull (string variableName)
// Runtime.GetNSObject<NSString> (auxVariable, false)!;
{ Type.IsNSObject: true, ReleaseHandle: not null}
=> GetNSObject (
nsObjectType: info.Type.ToNonNullable ().GetIdentifierSyntax (),
nsObjectType: info.Type.WithNullable (isNullable: false).GetIdentifierSyntax (),
args: [
Argument (expression),
BoolArgument (false)
Expand All @@ -1272,7 +1272,7 @@ internal static SyntaxNode ThrowIfNull (string variableName)

{ Type.IsNSObject: true, ReleaseHandle: null}
=> GetNSObject (
nsObjectType: info.Type.ToNonNullable ().GetIdentifierSyntax (),
nsObjectType: info.Type.WithNullable (isNullable: false).GetIdentifierSyntax (),
args: [
Argument (expression),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ internal static (SyntaxToken ParameterName, TypeSyntax ParameterType) GetTrampol
// parameters that are passed by reference, depend on the type that is referenced
{ IsByRef: true, Type.IsReferenceType: false, Type.IsNullable: true}
=> (parameterIdentifier,
PointerType (GetLowLevelType (parameterType.ToNonNullable ()))),
PointerType (GetLowLevelType (parameterType.WithNullable (isNullable: false)))),

{ IsByRef: true, Type.IsReferenceType: false, Type.IsNullable: false}
=> (parameterIdentifier,
Expand Down Expand Up @@ -333,7 +333,7 @@ internal static ArgumentSyntax GetTrampolineInvokeArgument (string trampolineNam

// Runtime.GetNSObject<ParameterType> (ParameterName)
{ Type.IsNSObject: true, Type.IsNullable: true} =>
GetNSObject (parameterType.ToNonNullable ().GetIdentifierSyntax (), [
GetNSObject (parameterType.WithNullable (isNullable: false).GetIdentifierSyntax (), [
Argument (parameterIdentifier)
], suppressNullableWarning: false),

Expand All @@ -345,7 +345,7 @@ internal static ArgumentSyntax GetTrampolineInvokeArgument (string trampolineNam

// Runtime.GetINativeObject<ParameterType> (ParameterName, false)!
{ Type.IsINativeObject: true, Type.IsNullable: true } =>
GetINativeObject (parameterType.ToNonNullable ().GetIdentifierSyntax (), [
GetINativeObject (parameterType.WithNullable (isNullable: false).GetIdentifierSyntax (), [
Argument (parameterIdentifier),
BoolArgument (false)
], suppressNullableWarning: false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,37 @@ static ExpressionSyntax StaticInvocationGenericExpression (ExpressionSyntax stat
: invocation;
}

/// <summary>
/// Creates an invocation expression for calling a method on an instance variable.
/// </summary>
/// <param name="instanceVariable">The name of the instance variable.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="arguments">The arguments to pass to the method.</param>
/// <returns>An invocation expression for the method call.</returns>
static InvocationExpressionSyntax MemberInvocationExpression (TypeSyntax instanceVariable, string methodName,
ImmutableArray<ArgumentSyntax> arguments)
{
var argumentList = ArgumentList (
SeparatedList<ArgumentSyntax> (arguments.ToSyntaxNodeOrTokenArray ()));
return InvocationExpression (
MemberAccessExpression (
SyntaxKind.SimpleMemberAccessExpression,
instanceVariable,
IdentifierName (methodName).WithTrailingTrivia (Space)))
.WithArgumentList (argumentList);
}

/// <summary>
/// Creates an invocation expression for calling a method on an instance variable.
/// </summary>
/// <param name="instanceVariable">The name of the instance variable.</param>
/// <param name="methodName">The name of the method to call.</param>
/// <param name="arguments">The arguments to pass to the method.</param>
/// <returns>An invocation expression for the method call.</returns>
static InvocationExpressionSyntax MemberInvocationExpression (string instanceVariable, string methodName,
ImmutableArray<ArgumentSyntax> arguments)
=> MemberInvocationExpression (IdentifierName (instanceVariable), methodName, arguments);

static ExpressionSyntax ThrowException (string type, string? message = null)
{
var throwExpression = ObjectCreationExpression (IdentifierName (type));
Expand Down Expand Up @@ -296,4 +327,25 @@ internal static ArgumentSyntax ArgumentForParameter (in Parameter parameter)
/// <returns>An <see cref="ArgumentSyntax"/> representing the parameter.</returns>
internal static ArgumentSyntax ArgumentForParameter (in DelegateParameter parameter)
=> ArgumentForParameter (parameter.Name, parameter.ReferenceKind);

/// <summary>
/// Creates an invocation expression for the SetException method of a TaskCompletionSource.
/// </summary>
/// <param name="tcsVariableName">The name of the TaskCompletionSource variable.</param>
/// <param name="arguments">The arguments to pass to the SetException method.</param>
/// <returns>An invocation expression for the SetException method.</returns>
internal static InvocationExpressionSyntax TcsSetException (string tcsVariableName,
ImmutableArray<ArgumentSyntax> arguments)
=> MemberInvocationExpression (tcsVariableName, "SetException", arguments);

/// <summary>
/// Creates an invocation expression for the SetResult method of a TaskCompletionSource.
/// </summary>
/// <param name="tcsVariableName">The name of the TaskCompletionSource variable.</param>
/// <param name="arguments">The arguments to pass to the SetResult method.</param>
/// <returns>An invocation expression for the SetResult method.</returns>
internal static InvocationExpressionSyntax TcsSetResult (string tcsVariableName,
ImmutableArray<ArgumentSyntax> arguments)
=> MemberInvocationExpression (tcsVariableName, "SetResult", arguments);

}
Loading
Loading