Skip to content

Commit

Permalink
[Java.Interop] address some "easy" trimmer warnings (#1184)
Browse files Browse the repository at this point in the history
Context: #1157

We want to enable `$(IsAotCompatible)`=true, so we can identify and
fix trimmer warnings within `Java.Interop.dll`.  (Then later work our
way "up the stack", fixing trimmer warnings within `Mono.Android.dll`
and `Microsoft.Maui.dll` and…)

On the path to enabling `$(IsAotCompatible)`=true, we can enable some
settings to get started:

	<IsTrimmable>true</IsTrimmable>
	<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
	<EnableAotAnalyzer>true</EnableAotAnalyzer>

This opts into the analyzers without declaring that the assembly is
fully AOT-compatible.

Starting out, I got 33 warnings: this is an attempt to address the
ones that don't require too much thinking.  Unfortunately, solving
one warning likely will create dozens more -- as you have to update
all callers.

This results in 24 warnings remaining.  Since `Release` builds have
`$(TreatWarningsAsErrors)`, I will wait to enable the analyzers until
all warnings are addressed.

~~ Example Warnings ~~

**`System.Linq.Expression` usage:**
`JniRuntime.JniValueManager.CreateParameterFromManagedExpression()`

	/* 638 */ partial class JavaPeerableValueMarshaler {
	/* 667 */     public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize)
	/* 668 */     {
	/* 669 */         var r = CreateIntermediaryExpressionFromManagedExpression (context, sourceValue);
	/* 670 */         var h = Expression.Variable (typeof (IntPtr), sourceValue.Name + "_handle");
	/* 671 */         context.LocalVariables.Add (h);
	/* 672 */         context.CreationStatements.Add (Expression.Assign (h, Expression.Property (r, "Handle")));
	/* 674 */         return h;
	/* 675 */     }
	/* 710 */ }

emits an IL2026:

	src\Java.Interop\Java.Interop\JniRuntime.JniValueManager.cs(672,58):
	warning IL2026: Using member 'System.Linq.Expressions.Expression.Property(Expression, String)'
	which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.
	Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.

I updated this with:

	partial class JniValueMarshaler {
	    internal const string ExpressionRequiresUnreferencedCode = "System.Linq.Expression usage may trim away required code.";

	    [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
	    public virtual Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) => …
	}
	partial class JavaPeerableValueMarshaler /* indirectly inherits JniValueMarshaler */ {
	    [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
	    public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) => …
	}

**`Type.GetNestedType()` usage:**
`JniRuntime.JniTypeManager.TryLoadJniMarshalMethods()`:

	/*  82 */ partial class JniRuntime.JniTypeManager {
	/* 445 */     bool TryLoadJniMarshalMethods (JniType nativeClass, Type type, string? methods)
	/* 446 */     {
	/* 447 */         var marshalType = type?.GetNestedType ("__<$>_jni_marshal_methods", BindingFlags.NonPublic);

emits an IL2070 warning:

	src\Java.Interop\Java.Interop\JniRuntime.JniTypeManager.cs(447,28):
	warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.NonPublicNestedTypes' in call to
	'System.Type.GetNestedType(String, BindingFlags)'.
	The parameter 'type' of method 'Java.Interop.JniRuntime.JniTypeManager.TryLoadJniMarshalMethods(JniType, Type, String)'
	does not have matching annotations.
	The source value must declare at least the same requirements as those declared on the target location it is assigned to.

I updated this with:

	partial class JniRuntime.JniTypeManager {
	    bool TryLoadJniMarshalMethods (
	            JniType nativeClass,
	            [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
	            Type type,
	            string? methods) => …

**`Activator.CreateInstance()` usage:**
`JniRuntime.JniValueManager.GetValueMarshaler()`:

	/*  50 */ partial class JniRuntime.JniValueManager {
	/* 530 */     public JniValueMarshaler GetValueMarshaler (Type type)
	/* 531 */     {
	/* 541 */         if (marshalerAttr != null)
	/* 542 */             return (JniValueMarshaler) Activator.CreateInstance (marshalerAttr.MarshalerType)!;
	/* 591 */     }
	/* 612 */ }

emits an IL2072 warning:

	src\Java.Interop\Java.Interop\JniRuntime.JniValueManager.cs(542,33): warning IL2072:
	'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor'
	in call to 'System.Activator.CreateInstance(Type)'.
	The return value of method 'Java.Interop.JniValueMarshalerAttribute.MarshalerType.get' does not have matching annotations.
	The source value must declare at least the same requirements as those declared on the target location it is assigned to.

I updated this with:

	partial class JniRuntime.JniValueManager {
	    public JniValueMarshaler GetValueMarshaler (
	            [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)]
	            Type type)
	        => …
	}
	partial class JniValueMarshalerAttribute {
	    public Type MarshalerType {
	        [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
	        get;
	    }
	}


~~ Code that Actually Changed ~~

As I added more attributes, these snowballed into more and more
warnings!  I eventually had to make
`JniRuntime.JniValueManager.GetPeerType()` look like:

	partial class JniRuntime.JniValueManager {
	    internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;

	    [return: DynamicallyAccessedMembers (Constructors)]
	    static Type GetPeerType ([DynamicallyAccessedMembers Constructors)] Type type) => …
	}

The analyzer was not able to understand code like:

	partial class JniRuntime.JniValueManager {
	    static  readonly    KeyValuePair<Type, Type>[]      PeerTypeMappings = new []{
	        new KeyValuePair<Type, Type>(typeof (object),           typeof (JavaObject)),
	        new KeyValuePair<Type, Type>(typeof (IJavaPeerable),    typeof (JavaObject)),
	        new KeyValuePair<Type, Type>(typeof (Exception),        typeof (JavaException)),
	    };
	    static Type GetPeerType (Type type)
	    {
	        foreach (var m in PeerTypeMappings) {
	            if (m.Key == type)
	                return m.Value;
	        }
	    }
	}

Simply removing the `PeerTypeMappings` array and using `if` statements
solved the warnings.  This may be the only real code change if any.
  • Loading branch information
jonathanpeppers authored Feb 13, 2024
1 parent dfcbd67 commit b8f6f88
Show file tree
Hide file tree
Showing 16 changed files with 499 additions and 106 deletions.
4 changes: 4 additions & 0 deletions src/Java.Interop/Java.Interop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
<!-- TODO: enable these when all warnings are solved -->
<!--<IsTrimmable>true</IsTrimmable>-->
<!--<EnableAotAnalyzer>true</EnableAotAnalyzer>-->
<MSBuildWarningsAsMessages>NU1702</MSBuildWarningsAsMessages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
Expand Down
7 changes: 6 additions & 1 deletion src/Java.Interop/Java.Interop/JavaArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,12 @@ public void Dispose ()
}
}

public abstract class JavaPrimitiveArray<T> : JavaArray<T> {
public abstract class JavaPrimitiveArray<
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
T
>
: JavaArray<T>
{

internal JavaPrimitiveArray (ref JniObjectReference reference, JniObjectReferenceOptions transfer)
: base (ref reference, transfer)
Expand Down
3 changes: 3 additions & 0 deletions src/Java.Interop/Java.Interop/JavaObject.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#nullable enable

using System;
using System.Diagnostics.CodeAnalysis;

namespace Java.Interop
{
[JniTypeSignature ("java/lang/Object", GenerateJavaPeer=false)]
unsafe public class JavaObject : IJavaPeerable
{
internal const DynamicallyAccessedMemberTypes ConstructorsAndInterfaces = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.Interfaces;

readonly static JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (JavaObject));

public int JniIdentityHashCode { get; private set; }
Expand Down
20 changes: 16 additions & 4 deletions src/Java.Interop/Java.Interop/JavaObjectArray.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#nullable enable
#nullable enable

using System;
using System.Collections.Generic;
Expand All @@ -7,7 +7,11 @@

namespace Java.Interop
{
public class JavaObjectArray<T> : JavaArray<T>
public class JavaObjectArray<
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
T
>
: JavaArray<T>
{
internal static readonly ValueMarshaler Instance = new ValueMarshaler ();

Expand Down Expand Up @@ -164,7 +168,11 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)

internal sealed class ValueMarshaler : JniValueMarshaler<IList<T>> {

public override IList<T> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<T> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<T>.CreateValue (ref reference, options, targetType, (ref JniObjectReference h, JniObjectReferenceOptions t) => new JavaObjectArray<T> (ref h, t) {
forMarshalCollection = true,
Expand Down Expand Up @@ -194,7 +202,11 @@ partial class JniEnvironment {
[SuppressMessage ("Design", "CA1034", Justification = "https://github.com/xamarin/Java.Interop/commit/bb7ca5d02aa3fc2b447ad57af1256e74e5f954fa")]
partial class Arrays {

public static JavaObjectArray<T>? CreateMarshalObjectArray<T> (IEnumerable<T>? value)
public static JavaObjectArray<T>? CreateMarshalObjectArray<
[DynamicallyAccessedMembers (JavaObject.ConstructorsAndInterfaces)]
T
> (
IEnumerable<T>? value)
{
if (value == null) {
return null;
Expand Down
96 changes: 80 additions & 16 deletions src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,14 +244,21 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
typeof (JavaBooleanArray) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<Boolean>> {

public override IList<Boolean> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<Boolean> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<Boolean>.CreateValue (
ref reference,
Expand All @@ -276,6 +283,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList<Boolean> val
JavaArray<Boolean>.DestroyArgumentState<JavaBooleanArray> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = JavaBooleanArray.CreateMarshaledValue;
Expand Down Expand Up @@ -439,14 +447,21 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
typeof (JavaSByteArray) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<SByte>> {

public override IList<SByte> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<SByte> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<SByte>.CreateValue (
ref reference,
Expand All @@ -471,6 +486,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList<SByte> value
JavaArray<SByte>.DestroyArgumentState<JavaSByteArray> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = JavaSByteArray.CreateMarshaledValue;
Expand Down Expand Up @@ -634,14 +650,21 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
typeof (JavaCharArray) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<Char>> {

public override IList<Char> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<Char> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<Char>.CreateValue (
ref reference,
Expand All @@ -666,6 +689,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList<Char> value,
JavaArray<Char>.DestroyArgumentState<JavaCharArray> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = JavaCharArray.CreateMarshaledValue;
Expand Down Expand Up @@ -829,14 +853,21 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
typeof (JavaInt16Array) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<Int16>> {

public override IList<Int16> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<Int16> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<Int16>.CreateValue (
ref reference,
Expand All @@ -861,6 +892,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList<Int16> value
JavaArray<Int16>.DestroyArgumentState<JavaInt16Array> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = JavaInt16Array.CreateMarshaledValue;
Expand Down Expand Up @@ -1024,14 +1056,21 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
typeof (JavaInt32Array) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<Int32>> {

public override IList<Int32> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<Int32> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<Int32>.CreateValue (
ref reference,
Expand All @@ -1056,6 +1095,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList<Int32> value
JavaArray<Int32>.DestroyArgumentState<JavaInt32Array> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = JavaInt32Array.CreateMarshaledValue;
Expand Down Expand Up @@ -1219,14 +1259,21 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
typeof (JavaInt64Array) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<Int64>> {

public override IList<Int64> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<Int64> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<Int64>.CreateValue (
ref reference,
Expand All @@ -1251,6 +1298,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList<Int64> value
JavaArray<Int64>.DestroyArgumentState<JavaInt64Array> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = JavaInt64Array.CreateMarshaledValue;
Expand Down Expand Up @@ -1414,14 +1462,21 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
typeof (JavaSingleArray) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<Single>> {

public override IList<Single> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<Single> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<Single>.CreateValue (
ref reference,
Expand All @@ -1446,6 +1501,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList<Single> valu
JavaArray<Single>.DestroyArgumentState<JavaSingleArray> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = JavaSingleArray.CreateMarshaledValue;
Expand Down Expand Up @@ -1609,14 +1665,21 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
typeof (JavaDoubleArray) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<Double>> {

public override IList<Double> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<Double> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<Double>.CreateValue (
ref reference,
Expand All @@ -1641,6 +1704,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList<Double> valu
JavaArray<Double>.DestroyArgumentState<JavaDoubleArray> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = JavaDoubleArray.CreateMarshaledValue;
Expand Down
12 changes: 10 additions & 2 deletions src/Java.Interop/Java.Interop/JavaPrimitiveArrays.tt
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,21 @@ namespace Java.Interop {
typeof (Java<#= info.TypeModifier #>Array) == targetType;
}

public static object? CreateMarshaledValue (IntPtr handle, Type? targetType)
public static object? CreateMarshaledValue (
IntPtr handle,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return ArrayMarshaler.CreateValue (handle, targetType);
}

internal sealed class ValueMarshaler : JniValueMarshaler<IList<<#= info.TypeModifier #>>> {

public override IList<<#= info.TypeModifier #>> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType)
public override IList<<#= info.TypeModifier #>> CreateGenericValue (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (ConstructorsAndInterfaces)]
Type? targetType)
{
return JavaArray<<#= info.TypeModifier #>>.CreateValue (
ref reference,
Expand All @@ -273,6 +280,7 @@ namespace Java.Interop {
JavaArray<<#= info.ManagedType #>>.DestroyArgumentState<Java<#= info.TypeModifier #>Array> (value, ref state, synchronize);
}

[RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)]
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null)
{
Func<IntPtr, Type?, object?> m = Java<#= info.TypeModifier #>Array.CreateMarshaledValue;
Expand Down
Loading

0 comments on commit b8f6f88

Please sign in to comment.