From b8f6f8884ac11775107cbb55a9f57a38cbd53240 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 12 Feb 2024 18:20:25 -0600 Subject: [PATCH] [Java.Interop] address some "easy" trimmer warnings (#1184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Context: https://github.com/xamarin/java.interop/issues/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: true true true 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[] PeerTypeMappings = new []{ new KeyValuePair(typeof (object), typeof (JavaObject)), new KeyValuePair(typeof (IJavaPeerable), typeof (JavaObject)), new KeyValuePair(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. --- src/Java.Interop/Java.Interop.csproj | 4 + src/Java.Interop/Java.Interop/JavaArray.cs | 7 +- src/Java.Interop/Java.Interop/JavaObject.cs | 3 + .../Java.Interop/JavaObjectArray.cs | 20 +- .../Java.Interop/JavaPrimitiveArrays.cs | 96 ++++++++-- .../Java.Interop/JavaPrimitiveArrays.tt | 12 +- .../Java.Interop/JniBuiltinMarshalers.cs | 172 +++++++++++++++--- .../Java.Interop/JniBuiltinMarshalers.tt | 30 ++- .../JniRuntime.JniMarshalMemberBuilder.cs | 18 +- .../Java.Interop/JniRuntime.JniTypeManager.cs | 50 ++++- .../JniRuntime.JniValueManager.cs | 127 ++++++++++--- src/Java.Interop/Java.Interop/JniRuntime.cs | 2 +- .../Java.Interop/JniStringValueMarshaler.cs | 9 +- .../Java.Interop/JniValueMarshaler.cs | 37 +++- .../JniValueMarshalerAttribute.cs | 6 +- src/Java.Interop/Java.Interop/ManagedPeer.cs | 12 +- 16 files changed, 499 insertions(+), 106 deletions(-) diff --git a/src/Java.Interop/Java.Interop.csproj b/src/Java.Interop/Java.Interop.csproj index 5f04bb680..51bb3a90d 100644 --- a/src/Java.Interop/Java.Interop.csproj +++ b/src/Java.Interop/Java.Interop.csproj @@ -14,6 +14,10 @@ true enable true + true + + + NU1702 diff --git a/src/Java.Interop/Java.Interop/JavaArray.cs b/src/Java.Interop/Java.Interop/JavaArray.cs index 5b05131b4..7b6889f25 100644 --- a/src/Java.Interop/Java.Interop/JavaArray.cs +++ b/src/Java.Interop/Java.Interop/JavaArray.cs @@ -362,7 +362,12 @@ public void Dispose () } } - public abstract class JavaPrimitiveArray : JavaArray { + public abstract class JavaPrimitiveArray< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > + : JavaArray + { internal JavaPrimitiveArray (ref JniObjectReference reference, JniObjectReferenceOptions transfer) : base (ref reference, transfer) diff --git a/src/Java.Interop/Java.Interop/JavaObject.cs b/src/Java.Interop/Java.Interop/JavaObject.cs index 8ce5212db..df666821d 100644 --- a/src/Java.Interop/Java.Interop/JavaObject.cs +++ b/src/Java.Interop/Java.Interop/JavaObject.cs @@ -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; } diff --git a/src/Java.Interop/Java.Interop/JavaObjectArray.cs b/src/Java.Interop/Java.Interop/JavaObjectArray.cs index 89fe35e0e..a9f960ef2 100644 --- a/src/Java.Interop/Java.Interop/JavaObjectArray.cs +++ b/src/Java.Interop/Java.Interop/JavaObjectArray.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; @@ -7,7 +7,11 @@ namespace Java.Interop { - public class JavaObjectArray : JavaArray + public class JavaObjectArray< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > + : JavaArray { internal static readonly ValueMarshaler Instance = new ValueMarshaler (); @@ -164,7 +168,11 @@ internal override bool TargetTypeIsCurrentType (Type? targetType) internal sealed class ValueMarshaler : JniValueMarshaler> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue (ref reference, options, targetType, (ref JniObjectReference h, JniObjectReferenceOptions t) => new JavaObjectArray (ref h, t) { forMarshalCollection = true, @@ -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? CreateMarshalObjectArray (IEnumerable? value) + public static JavaObjectArray? CreateMarshalObjectArray< + [DynamicallyAccessedMembers (JavaObject.ConstructorsAndInterfaces)] + T + > ( + IEnumerable? value) { if (value == null) { return null; diff --git a/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs b/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs index 1aa030839..d23484a03 100644 --- a/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs +++ b/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs @@ -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> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue ( ref reference, @@ -276,6 +283,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList val JavaArray.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = JavaBooleanArray.CreateMarshaledValue; @@ -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> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue ( ref reference, @@ -471,6 +486,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList value JavaArray.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = JavaSByteArray.CreateMarshaledValue; @@ -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> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue ( ref reference, @@ -666,6 +689,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList value, JavaArray.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = JavaCharArray.CreateMarshaledValue; @@ -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> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue ( ref reference, @@ -861,6 +892,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList value JavaArray.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = JavaInt16Array.CreateMarshaledValue; @@ -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> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue ( ref reference, @@ -1056,6 +1095,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList value JavaArray.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = JavaInt32Array.CreateMarshaledValue; @@ -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> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue ( ref reference, @@ -1251,6 +1298,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList value JavaArray.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = JavaInt64Array.CreateMarshaledValue; @@ -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> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue ( ref reference, @@ -1446,6 +1501,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList valu JavaArray.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = JavaSingleArray.CreateMarshaledValue; @@ -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> { - public override IList CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IList CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JavaArray.CreateValue ( ref reference, @@ -1641,6 +1704,7 @@ public override void DestroyGenericArgumentState ([AllowNull] IList valu JavaArray.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = JavaDoubleArray.CreateMarshaledValue; diff --git a/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.tt b/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.tt index c644d61f6..be362d091 100644 --- a/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.tt +++ b/src/Java.Interop/Java.Interop/JavaPrimitiveArrays.tt @@ -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>> { - 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, @@ -273,6 +280,7 @@ namespace Java.Interop { JavaArray<<#= info.ManagedType #>>.DestroyArgumentStateArray> (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = Java<#= info.TypeModifier #>Array.CreateMarshaledValue; diff --git a/src/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs b/src/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs index b75e46b6d..4d39b6638 100644 --- a/src/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs +++ b/src/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs @@ -1,14 +1,14 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; using Java.Interop.Expressions; -using System.Diagnostics.CodeAnalysis; namespace Java.Interop { @@ -223,14 +223,22 @@ public override Type MarshalType { get {return typeof (Boolean);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override Boolean CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Boolean CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (Boolean); @@ -263,16 +271,19 @@ public override void DestroyGenericArgumentState (Boolean value, ref JniValueMar state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -283,7 +294,11 @@ sealed class JniNullableBooleanValueMarshaler : JniValueMarshaler { internal static readonly JniNullableBooleanValueMarshaler Instance = new JniNullableBooleanValueMarshaler (); - public override Boolean? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Boolean? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; @@ -350,14 +365,22 @@ public override Type MarshalType { get {return typeof (SByte);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override SByte CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override SByte CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (SByte); @@ -390,16 +413,19 @@ public override void DestroyGenericArgumentState (SByte value, ref JniValueMarsh state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -410,7 +436,11 @@ sealed class JniNullableSByteValueMarshaler : JniValueMarshaler { internal static readonly JniNullableSByteValueMarshaler Instance = new JniNullableSByteValueMarshaler (); - public override SByte? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override SByte? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; @@ -477,14 +507,22 @@ public override Type MarshalType { get {return typeof (Char);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override Char CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Char CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (Char); @@ -517,16 +555,19 @@ public override void DestroyGenericArgumentState (Char value, ref JniValueMarsha state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -537,7 +578,11 @@ sealed class JniNullableCharValueMarshaler : JniValueMarshaler { internal static readonly JniNullableCharValueMarshaler Instance = new JniNullableCharValueMarshaler (); - public override Char? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Char? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; @@ -604,14 +649,22 @@ public override Type MarshalType { get {return typeof (Int16);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override Int16 CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Int16 CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (Int16); @@ -644,16 +697,19 @@ public override void DestroyGenericArgumentState (Int16 value, ref JniValueMarsh state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -664,7 +720,11 @@ sealed class JniNullableInt16ValueMarshaler : JniValueMarshaler { internal static readonly JniNullableInt16ValueMarshaler Instance = new JniNullableInt16ValueMarshaler (); - public override Int16? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Int16? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; @@ -731,14 +791,22 @@ public override Type MarshalType { get {return typeof (Int32);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override Int32 CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Int32 CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (Int32); @@ -771,16 +839,19 @@ public override void DestroyGenericArgumentState (Int32 value, ref JniValueMarsh state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -791,7 +862,11 @@ sealed class JniNullableInt32ValueMarshaler : JniValueMarshaler { internal static readonly JniNullableInt32ValueMarshaler Instance = new JniNullableInt32ValueMarshaler (); - public override Int32? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Int32? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; @@ -858,14 +933,22 @@ public override Type MarshalType { get {return typeof (Int64);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override Int64 CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Int64 CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (Int64); @@ -898,16 +981,19 @@ public override void DestroyGenericArgumentState (Int64 value, ref JniValueMarsh state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -918,7 +1004,11 @@ sealed class JniNullableInt64ValueMarshaler : JniValueMarshaler { internal static readonly JniNullableInt64ValueMarshaler Instance = new JniNullableInt64ValueMarshaler (); - public override Int64? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Int64? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; @@ -985,14 +1075,22 @@ public override Type MarshalType { get {return typeof (Single);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override Single CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Single CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (Single); @@ -1025,16 +1123,19 @@ public override void DestroyGenericArgumentState (Single value, ref JniValueMars state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -1045,7 +1146,11 @@ sealed class JniNullableSingleValueMarshaler : JniValueMarshaler { internal static readonly JniNullableSingleValueMarshaler Instance = new JniNullableSingleValueMarshaler (); - public override Single? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Single? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; @@ -1112,14 +1217,22 @@ public override Type MarshalType { get {return typeof (Double);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override Double CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Double CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (Double); @@ -1152,16 +1265,19 @@ public override void DestroyGenericArgumentState (Double value, ref JniValueMars state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -1172,7 +1288,11 @@ sealed class JniNullableDoubleValueMarshaler : JniValueMarshaler { internal static readonly JniNullableDoubleValueMarshaler Instance = new JniNullableDoubleValueMarshaler (); - public override Double? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override Double? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; diff --git a/src/Java.Interop/Java.Interop/JniBuiltinMarshalers.tt b/src/Java.Interop/Java.Interop/JniBuiltinMarshalers.tt index d5910cf62..e5c911bf5 100644 --- a/src/Java.Interop/Java.Interop/JniBuiltinMarshalers.tt +++ b/src/Java.Interop/Java.Interop/JniBuiltinMarshalers.tt @@ -1,4 +1,4 @@ -<#@ template language="C#" #> +<#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.Linq" #> @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; @@ -181,14 +182,22 @@ namespace Java.Interop { get {return typeof (<#= type.Type #>);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; return CreateGenericValue (ref reference, options, targetType); } - public override <#= type.Type #> CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override <#= type.Type #> CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return default (<#= type.Type #>); @@ -196,12 +205,12 @@ namespace Java.Interop { return Jni<#= type.Name #>.GetValueFromJni (ref reference, options, targetType); } - public override JniValueMarshalerState CreateGenericArgumentState (<#= type.Type #> value, ParameterAttributes synchronize = ParameterAttributes.In) + public override JniValueMarshalerState CreateGenericArgumentState ([MaybeNull] <#= type.Type #> value, ParameterAttributes synchronize = ParameterAttributes.In) { return new JniValueMarshalerState (new JniArgumentValue (value)); } - public override JniValueMarshalerState CreateGenericObjectReferenceArgumentState (<#= type.Type #> value, ParameterAttributes synchronize) + public override JniValueMarshalerState CreateGenericObjectReferenceArgumentState ([MaybeNull] <#= type.Type #> value, ParameterAttributes synchronize) { var r = Jni<#= type.Name #>.CreateLocalRef (value); return new JniValueMarshalerState (r); @@ -221,16 +230,19 @@ namespace Java.Interop { state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; @@ -241,7 +253,11 @@ namespace Java.Interop { internal static readonly JniNullable<#= type.Type #>ValueMarshaler Instance = new JniNullable<#= type.Type #>ValueMarshaler (); - public override <#= type.Type #>? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override <#= type.Type #>? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { if (!reference.IsValid) return null; @@ -249,7 +265,7 @@ namespace Java.Interop { return Jni<#= type.Name #>.GetValueFromJni (ref reference, options, targetType: null); } - public override JniValueMarshalerState CreateGenericObjectReferenceArgumentState (<#= type.Type #>? value, ParameterAttributes synchronize) + public override JniValueMarshalerState CreateGenericObjectReferenceArgumentState ([MaybeNull] <#= type.Type #>? value, ParameterAttributes synchronize) { if (!value.HasValue) return new JniValueMarshalerState (); diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs index 11fabae92..e52bae71b 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; @@ -31,6 +31,7 @@ public JniMarshalMemberBuilder MarshalMemberBuilder { #if NET [DynamicDependency (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor, "Java.Interop.MarshalMemberBuilder", "Java.Interop.Export")] [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "DynamicDependency should preserve the constructor.")] + [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "DynamicDependency should preserve the constructor.")] [UnconditionalSuppressMessage ("Trimming", "IL2035", Justification = "Java.Interop.Export.dll is not always present.")] #endif partial void SetMarshalMemberBuilder (CreationOptions options) @@ -179,28 +180,39 @@ public bool IsDirectMethod (ParameterInfo[] methodParameters) sealed class IntPtrValueMarshaler : JniValueMarshaler { internal static IntPtrValueMarshaler Instance = new IntPtrValueMarshaler (); + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (Java.Interop.Expressions.JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (Java.Interop.Expressions.JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return sourceValue; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (Java.Interop.Expressions.JniValueMarshalerContext context, ParameterExpression sourceValue) { return sourceValue; } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { throw new NotSupportedException (); } - public override IntPtr CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IntPtr CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { throw new NotSupportedException (); } diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs index 6251e48ee..12bbff89b 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; @@ -81,6 +81,10 @@ public override string ToString () public partial class JniTypeManager : IDisposable, ISetRuntime { + internal const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods; + internal const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes; + internal const DynamicallyAccessedMemberTypes MethodsConstructorsInterfaces = MethodsAndPrivateNested | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.Interfaces; + JniRuntime? runtime; bool disposed; @@ -267,7 +271,7 @@ protected virtual IEnumerable GetSimpleReferences (Type type) static readonly Type[] EmptyTypeArray = Array.Empty (); - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + [return: DynamicallyAccessedMembers (MethodsConstructorsInterfaces)] public Type? GetType (JniTypeSignature typeSignature) { AssertValid (); @@ -405,12 +409,20 @@ IEnumerable CreateGetTypesForSimpleReferenceEnumerator (string jniSimpleRe protected virtual ReplacementMethodInfo? GetReplacementMethodInfoCore (string jniSimpleReference, string jniMethodName, string jniMethodSignature) => null; - public virtual void RegisterNativeMembers (JniType nativeClass, Type type, ReadOnlySpan methods) + public virtual void RegisterNativeMembers ( + JniType nativeClass, + [DynamicallyAccessedMembers (MethodsAndPrivateNested)] + Type type, + ReadOnlySpan methods) { TryRegisterNativeMembers (nativeClass, type, methods); } - protected bool TryRegisterNativeMembers (JniType nativeClass, Type type, ReadOnlySpan methods) + protected bool TryRegisterNativeMembers ( + JniType nativeClass, + [DynamicallyAccessedMembers (MethodsAndPrivateNested)] + Type type, + ReadOnlySpan methods) { AssertValid (); @@ -425,7 +437,11 @@ protected bool TryRegisterNativeMembers (JniType nativeClass, Type type, ReadOnl #if NET [Obsolete ("Use RegisterNativeMembers(JniType, Type, ReadOnlySpan)")] #endif // NET - public virtual void RegisterNativeMembers (JniType nativeClass, Type type, string? methods) + public virtual void RegisterNativeMembers ( + JniType nativeClass, + [DynamicallyAccessedMembers (MethodsAndPrivateNested)] + Type type, + string? methods) { TryRegisterNativeMembers (nativeClass, type, methods); } @@ -433,7 +449,11 @@ public virtual void RegisterNativeMembers (JniType nativeClass, Type type, strin #if NET [Obsolete ("Use RegisterNativeMembers(JniType, Type, ReadOnlySpan)")] #endif // NET - protected bool TryRegisterNativeMembers (JniType nativeClass, Type type, string? methods) + protected bool TryRegisterNativeMembers ( + JniType nativeClass, + [DynamicallyAccessedMembers (MethodsAndPrivateNested)] + Type type, + string? methods) { AssertValid (); @@ -442,7 +462,11 @@ protected bool TryRegisterNativeMembers (JniType nativeClass, Type type, string? static Type [] registerMethodParameters = new Type [] { typeof (JniNativeMethodRegistrationArguments) }; - bool TryLoadJniMarshalMethods (JniType nativeClass, Type type, string? methods) + bool TryLoadJniMarshalMethods ( + JniType nativeClass, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] + Type type, + string? methods) { var marshalType = type?.GetNestedType ("__<$>_jni_marshal_methods", BindingFlags.NonPublic); if (marshalType == null) { @@ -461,7 +485,12 @@ bool TryLoadJniMarshalMethods (JniType nativeClass, Type type, string? methods) static List sharedRegistrations = new List (); - bool TryRegisterNativeMembers (JniType nativeClass, Type marshalType, string? methods, MethodInfo? registerMethod) + bool TryRegisterNativeMembers ( + JniType nativeClass, + [DynamicallyAccessedMembers (Methods)] + Type marshalType, + string? methods, + MethodInfo? registerMethod) { bool lockTaken = false; bool rv = false; @@ -493,7 +522,10 @@ bool TryRegisterNativeMembers (JniType nativeClass, Type marshalType, string? me return rv; } - bool FindAndCallRegisterMethod (Type marshalType, JniNativeMethodRegistrationArguments arguments) + bool FindAndCallRegisterMethod ( + [DynamicallyAccessedMembers (Methods)] + Type marshalType, + JniNativeMethodRegistrationArguments arguments) { if (!Runtime.JniAddNativeMethodRegistrationAttributePresent) return false; diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs index 691ef7b51..91e862dc7 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs @@ -49,6 +49,9 @@ partial void SetValueManager (CreationOptions options) public abstract partial class JniValueManager : ISetRuntime, IDisposable { + internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; + internal const DynamicallyAccessedMemberTypes ConstructorsAndInterfaces = Constructors | DynamicallyAccessedMemberTypes.Interfaces; + JniRuntime? runtime; bool disposed; public JniRuntime Runtime { @@ -252,22 +255,23 @@ protected virtual bool TryUnboxPeerObject (IJavaPeerable value, [NotNullWhen (tr : null; } - static readonly KeyValuePair[] PeerTypeMappings = new []{ - new KeyValuePair(typeof (object), typeof (JavaObject)), - new KeyValuePair(typeof (IJavaPeerable), typeof (JavaObject)), - new KeyValuePair(typeof (Exception), typeof (JavaException)), - }; - - static Type GetPeerType (Type type) + [return: DynamicallyAccessedMembers (Constructors)] + static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type) { - foreach (var m in PeerTypeMappings) { - if (m.Key == type) - return m.Value; - } + if (type == typeof (object)) + return typeof (JavaObject); + if (type == typeof (IJavaPeerable)) + return typeof (JavaObject); + if (type == typeof (Exception)) + return typeof (JavaException); return type; } - public virtual IJavaPeerable? CreatePeer (ref JniObjectReference reference, JniObjectReferenceOptions transfer, Type? targetType) + public virtual IJavaPeerable? CreatePeer ( + ref JniObjectReference reference, + JniObjectReferenceOptions transfer, + [DynamicallyAccessedMembers (Constructors)] + Type? targetType) { if (disposed) throw new ObjectDisposedException (GetType ().Name); @@ -298,7 +302,10 @@ static Type GetPeerType (Type type) static readonly Type ByRefJniObjectReference = typeof (JniObjectReference).MakeByRefType (); - ConstructorInfo? GetPeerConstructor (JniObjectReference instance, Type fallbackType) + ConstructorInfo? GetPeerConstructor ( + JniObjectReference instance, + [DynamicallyAccessedMembers (Constructors)] + Type fallbackType) { var klass = JniEnvironment.Types.GetObjectClass (instance); var jniTypeName = JniEnvironment.Types.GetJniTypeNameFromClass (klass); @@ -333,7 +340,9 @@ static Type GetPeerType (Type type) return GetActivationConstructor (fallbackType); } - static ConstructorInfo? GetActivationConstructor (Type type) + static ConstructorInfo? GetActivationConstructor ( + [DynamicallyAccessedMembers (Constructors)] + Type type) { if (type.IsAbstract || type.IsInterface) { type = GetInvokerType (type) ?? type; @@ -346,6 +355,7 @@ static Type GetPeerType (Type type) return null; } + [return: DynamicallyAccessedMembers (Constructors)] static Type? GetInvokerType (Type type) { const string suffix = "Invoker"; @@ -363,7 +373,11 @@ static Type GetPeerType (Type type) return suffixDefinition.MakeGenericType (arguments); } - public object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType = null) + public object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType = null) { if (disposed) throw new ObjectDisposedException (GetType ().Name); @@ -393,7 +407,14 @@ static Type GetPeerType (Type type) } [return: MaybeNull] - public T CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType = null) + public T CreateValue< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType = null) { if (disposed) throw new ObjectDisposedException (GetType ().Name); @@ -430,6 +451,7 @@ public T CreateValue (ref JniObjectReference reference, JniObjectReferenceOpt return marshaler.CreateGenericValue (ref reference, options, targetType); } + [return: DynamicallyAccessedMembers (ConstructorsAndInterfaces)] internal Type? GetRuntimeType (JniObjectReference reference) { if (!reference.IsValid) @@ -440,7 +462,11 @@ public T CreateValue (ref JniObjectReference reference, JniObjectReferenceOpt return Runtime.TypeManager.GetType (signature); } - public object? GetValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType = null) + public object? GetValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType = null) { if (disposed) throw new ObjectDisposedException (GetType ().Name); @@ -468,14 +494,25 @@ public T CreateValue (ref JniObjectReference reference, JniObjectReferenceOpt } [return: MaybeNull] - public T GetValue (IntPtr handle) + public T GetValue< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > ( + IntPtr handle) { var r = new JniObjectReference (handle); return GetValue (ref r, JniObjectReferenceOptions.Copy); } [return: MaybeNull] - public T GetValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType = null) + public T GetValue< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType = null) { if (!reference.IsValid) { #pragma warning disable 8653 @@ -511,7 +548,10 @@ public T GetValue (ref JniObjectReference reference, JniObjectReferenceOption Dictionary Marshalers = new Dictionary (); - public JniValueMarshaler GetValueMarshaler() + public JniValueMarshaler GetValueMarshaler< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > () { if (disposed) throw new ObjectDisposedException (GetType ().Name); @@ -527,7 +567,9 @@ public JniValueMarshaler GetValueMarshaler() } } - public JniValueMarshaler GetValueMarshaler (Type type) + public JniValueMarshaler GetValueMarshaler ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] + Type type) { if (disposed) throw new ObjectDisposedException (GetType ().Name); @@ -599,7 +641,10 @@ static JniValueMarshaler GetObjectArrayMarshaler (Type elementType) return direct (); } - static JniValueMarshaler GetObjectArrayMarshalerHelper () + static JniValueMarshaler GetObjectArrayMarshalerHelper< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > () { return JavaObjectArray.Instance; } @@ -619,7 +664,11 @@ public override Type MarshalType { get {return typeof (void);} } - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { throw new NotSupportedException (); } @@ -640,7 +689,11 @@ sealed class JavaPeerableValueMarshaler : JniValueMarshaler { internal static JavaPeerableValueMarshaler Instance = new JavaPeerableValueMarshaler (); [return: MaybeNull] - public override IJavaPeerable? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IJavaPeerable? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { var jvm = JniEnvironment.Runtime; var marshaler = jvm.ValueManager.GetValueMarshaler (targetType ?? typeof(IJavaPeerable)); @@ -664,6 +717,7 @@ public override void DestroyGenericArgumentState ([MaybeNull]IJavaPeerable? valu state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { var r = CreateIntermediaryExpressionFromManagedExpression (context, sourceValue); @@ -674,6 +728,7 @@ public override Expression CreateParameterFromManagedExpression (JniValueMarshal return h; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] Expression CreateIntermediaryExpressionFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { var r = Expression.Variable (typeof (JniObjectReference), sourceValue.Name + "_ref"); @@ -687,11 +742,13 @@ Expression CreateIntermediaryExpressionFromManagedExpression (JniValueMarshalerC return r; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return ReturnObjectReferenceToJni (context, sourceValue.Name, CreateIntermediaryExpressionFromManagedExpression (context, sourceValue)); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { targetType ??= typeof (object); @@ -709,7 +766,12 @@ public override Expression CreateParameterToManagedExpression (JniValueMarshaler } } - sealed class DelegatingValueMarshaler : JniValueMarshaler { + sealed class DelegatingValueMarshaler< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > + : JniValueMarshaler + { JniValueMarshaler ValueMarshaler; @@ -719,7 +781,11 @@ public DelegatingValueMarshaler (JniValueMarshaler valueMarshaler) } [return: MaybeNull] - public override T CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override T CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return (T) ValueMarshaler.CreateValue (ref reference, options, targetType ?? typeof (T))!; } @@ -734,16 +800,19 @@ public override void DestroyGenericArgumentState ([AllowNull]T value, ref JniVal ValueMarshaler.DestroyArgumentState (value, ref state, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { return ValueMarshaler.CreateParameterFromManagedExpression (context, sourceValue, synchronize); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { return ValueMarshaler.CreateParameterToManagedExpression (context, sourceValue, synchronize, targetType); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { return ValueMarshaler.CreateReturnValueFromManagedExpression (context, sourceValue); @@ -755,7 +824,11 @@ sealed class ProxyValueMarshaler : JniValueMarshaler { internal static ProxyValueMarshaler Instance = new ProxyValueMarshaler (); [return: MaybeNull] - public override object? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override object? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { var jvm = JniEnvironment.Runtime; diff --git a/src/Java.Interop/Java.Interop/JniRuntime.cs b/src/Java.Interop/Java.Interop/JniRuntime.cs index 75b1b4485..57b1bb721 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.cs @@ -271,7 +271,7 @@ T SetRuntime (T value) static unsafe JavaVMInterface CreateInvoker (IntPtr handle) { IntPtr p = Marshal.ReadIntPtr (handle); - return (JavaVMInterface) Marshal.PtrToStructure (p, typeof (JavaVMInterface))!; + return (JavaVMInterface) Marshal.PtrToStructure (p)!; } ~JniRuntime () diff --git a/src/Java.Interop/Java.Interop/JniStringValueMarshaler.cs b/src/Java.Interop/Java.Interop/JniStringValueMarshaler.cs index e16e00886..36a3e53a5 100644 --- a/src/Java.Interop/Java.Interop/JniStringValueMarshaler.cs +++ b/src/Java.Interop/Java.Interop/JniStringValueMarshaler.cs @@ -14,7 +14,11 @@ sealed class JniStringValueMarshaler : JniValueMarshaler { internal static readonly JniStringValueMarshaler Instance = new JniStringValueMarshaler (); - public override string? CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override string? CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { return JniEnvironment.Strings.ToString (ref reference, options, targetType ?? typeof (string)); } @@ -32,6 +36,7 @@ public override void DestroyGenericArgumentState (string? value, ref JniValueMar state = new JniValueMarshalerState (); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { Func m = JniEnvironment.Strings.NewString; @@ -46,6 +51,7 @@ public override Expression CreateParameterFromManagedExpression (JniValueMarshal return hdl; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { Func m = JniEnvironment.Strings.NewString; @@ -57,6 +63,7 @@ public override Expression CreateReturnValueFromManagedExpression (JniValueMarsh return ReturnObjectReferenceToJni (context, sourceValue.Name, obj); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type? targetType) { Func m = JniEnvironment.Strings.ToString; diff --git a/src/Java.Interop/Java.Interop/JniValueMarshaler.cs b/src/Java.Interop/Java.Interop/JniValueMarshaler.cs index d3351c358..ae8e096c2 100644 --- a/src/Java.Interop/Java.Interop/JniValueMarshaler.cs +++ b/src/Java.Interop/Java.Interop/JniValueMarshaler.cs @@ -120,6 +120,9 @@ public override string ToString () public abstract class JniValueMarshaler { + internal const DynamicallyAccessedMemberTypes ConstructorsAndInterfaces = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.Interfaces; + internal const string ExpressionRequiresUnreferencedCode = "System.Linq.Expression usage may trim away required code."; + public virtual bool IsJniValueType { get {return false;} } @@ -129,7 +132,11 @@ public virtual Type MarshalType { get {return IntPtr_type;} } - public abstract object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType = null); + public abstract object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType = null); public virtual JniValueMarshalerState CreateArgumentState (object? value, ParameterAttributes synchronize = 0) { @@ -139,12 +146,16 @@ public virtual JniValueMarshalerState CreateArgumentState (object? value, public abstract JniValueMarshalerState CreateObjectReferenceArgumentState (object? value, ParameterAttributes synchronize = 0); public abstract void DestroyArgumentState (object? value, ref JniValueMarshalerState state, ParameterAttributes synchronize = 0); - internal object? CreateValue (IntPtr handle, Type? targetType) + internal object? CreateValue ( + IntPtr handle, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType) { var r = new JniObjectReference (handle); return CreateValue (ref r, JniObjectReferenceOptions.Copy, targetType); } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public virtual Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize = 0, Type? targetType = null) { Func m = CreateValue; @@ -165,6 +176,7 @@ Expression CreateSelf (JniValueMarshalerContext context, ParameterExpression sou return self; } + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public virtual Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue) { CreateParameterFromManagedExpression (context, sourceValue, 0); @@ -186,6 +198,8 @@ protected Expression ReturnObjectReferenceToJni (JniValueMarshalerContext contex } delegate void DestroyArgumentStateCb (object value, ref JniValueMarshalerState state, ParameterAttributes synchronize); + + [RequiresUnreferencedCode (ExpressionRequiresUnreferencedCode)] public virtual Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize) { Func c = CreateArgumentState; @@ -216,10 +230,19 @@ protected static Expression DisposeObjectReference (Expression sourceValue) } } - public abstract class JniValueMarshaler : JniValueMarshaler { + public abstract class JniValueMarshaler< + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + T + > + : JniValueMarshaler + { [return: MaybeNull] - public abstract T CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType = null); + public abstract T CreateGenericValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType = null); public virtual JniValueMarshalerState CreateGenericArgumentState ([MaybeNull] T value, ParameterAttributes synchronize = 0) { @@ -229,7 +252,11 @@ public virtual JniValueMarshalerState CreateGenericArgumentState ([MaybeNu public abstract JniValueMarshalerState CreateGenericObjectReferenceArgumentState ([MaybeNull] T value, ParameterAttributes synchronize = 0); public abstract void DestroyGenericArgumentState ([AllowNull] T value, ref JniValueMarshalerState state, ParameterAttributes synchronize = 0); - public override object? CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType = null) + public override object? CreateValue ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (ConstructorsAndInterfaces)] + Type? targetType = null) { return CreateGenericValue (ref reference, options, targetType ?? typeof (T)); } diff --git a/src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs b/src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs index 9e94157a3..f4869fcf1 100644 --- a/src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs +++ b/src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs @@ -1,6 +1,7 @@ #nullable enable using System; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace Java.Interop { @@ -25,7 +26,10 @@ public JniValueMarshalerAttribute (Type marshalerType) MarshalerType = marshalerType; } - public Type MarshalerType {get;} + public Type MarshalerType { + [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + get; + } } } diff --git a/src/Java.Interop/Java.Interop/ManagedPeer.cs b/src/Java.Interop/Java.Interop/ManagedPeer.cs index b23277fde..f3874b635 100644 --- a/src/Java.Interop/Java.Interop/ManagedPeer.cs +++ b/src/Java.Interop/Java.Interop/ManagedPeer.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; @@ -17,6 +17,8 @@ namespace Java.Interop { /* static */ sealed class ManagedPeer : JavaObject { internal const string JniTypeName = "net/dot/jni/ManagedPeer"; + internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; + internal const DynamicallyAccessedMemberTypes ConstructorsMethodsNestedTypes = Constructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes; static readonly JniPeerMembers _members = new JniPeerMembers (JniTypeName, typeof (ManagedPeer)); @@ -140,7 +142,11 @@ static Exception CreateJniLocationException () static Dictionary ConstructorCache = new Dictionary (); - static ConstructorInfo? GetConstructor (Type type, string jniTypeName, string signature) + static ConstructorInfo? GetConstructor ( + [DynamicallyAccessedMembers (Constructors)] + Type type, + string jniTypeName, + string signature) { var ctorCacheKey = jniTypeName + "." + signature; lock (ConstructorCache) { @@ -290,7 +296,7 @@ static unsafe void RegisterNativeMembers ( } } - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + [return: DynamicallyAccessedMembers (ConstructorsMethodsNestedTypes)] static Type GetTypeFromSignature (JniRuntime.JniTypeManager typeManager, JniTypeSignature typeSignature, string? context = null) { return typeManager.GetType (typeSignature) ??