diff --git a/src/Java.Interop/Java.Interop.csproj b/src/Java.Interop/Java.Interop.csproj index 51bb3a90d..80eb91aee 100644 --- a/src/Java.Interop/Java.Interop.csproj +++ b/src/Java.Interop/Java.Interop.csproj @@ -15,9 +15,8 @@ enable true true - - - + true + true NU1702 diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs index e52bae71b..e2c6047cf 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs @@ -152,6 +152,12 @@ string GetTypeSignature (ParameterInfo p) public JniValueMarshaler GetParameterMarshaler (ParameterInfo parameter) { + // Activator.CreateInstance requires DynamicallyAccessedMemberTypes.PublicParameterlessConstructor + // GetValueMarshaler requires DynamicallyAccessedMemberTypes.Interfaces + [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "JniValueMarshalerAttribute is decorated with [DynamicallyAccessedMembers]")] + static JniValueMarshaler GetValueMarshaler (JniValueManager manager, ParameterInfo parameter) => + manager.GetValueMarshaler (parameter.ParameterType); + if (parameter.ParameterType == typeof (IntPtr)) return IntPtrValueMarshaler.Instance; @@ -164,7 +170,7 @@ public JniValueMarshaler GetParameterMarshaler (ParameterInfo parameter) if (attr != null) { return (JniValueMarshaler) Activator.CreateInstance (attr.MarshalerType)!; } - return Runtime.ValueManager.GetValueMarshaler (parameter.ParameterType); + return GetValueMarshaler (Runtime.ValueManager, parameter); } // Heuristic: if first two parameters are IntPtr, this is a "direct" wrapper. diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs index 12bbff89b..6e4867192 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs @@ -269,8 +269,18 @@ protected virtual IEnumerable GetSimpleReferences (Type type) static readonly string[] EmptyStringArray = Array.Empty (); static readonly Type[] EmptyTypeArray = Array.Empty (); + const string NotUsedInAndroid = "This code path is not used in Android projects."; + // FIXME: https://github.com/xamarin/java.interop/issues/1192 + [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = NotUsedInAndroid)] + static Type MakeArrayType (Type type) => type.MakeArrayType (); + // FIXME: https://github.com/xamarin/java.interop/issues/1192 + [UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = NotUsedInAndroid)] + [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = NotUsedInAndroid)] + static Type MakeGenericType (Type type, Type arrayType) => type.MakeGenericType (arrayType); + + [UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = "Types returned here should be preserved via other means.")] [return: DynamicallyAccessedMembers (MethodsConstructorsInterfaces)] public Type? GetType (JniTypeSignature typeSignature) { @@ -309,7 +319,7 @@ IEnumerable CreateGetTypesEnumerator (JniTypeSignature typeSignature) var rank = typeSignature.ArrayRank; var arrayType = type; while (rank-- > 0) { - arrayType = typeof (JavaObjectArray<>).MakeGenericType (arrayType); + arrayType = MakeGenericType (typeof (JavaObjectArray<>), arrayType); } yield return arrayType; } @@ -318,7 +328,7 @@ IEnumerable CreateGetTypesEnumerator (JniTypeSignature typeSignature) var rank = typeSignature.ArrayRank; var arrayType = type; while (rank-- > 0) { - arrayType = arrayType.MakeArrayType (); + arrayType = MakeArrayType (arrayType); } yield return arrayType; } @@ -341,14 +351,14 @@ IEnumerable GetPrimitiveArrayTypesForSimpleReference (JniTypeSignature typ var rank = typeSignature.ArrayRank-1; var arrayType = t; while (rank-- > 0) { - arrayType = typeof (JavaObjectArray<>).MakeGenericType (arrayType); + arrayType = MakeGenericType (typeof (JavaObjectArray<>), arrayType); } yield return arrayType; rank = typeSignature.ArrayRank-1; arrayType = t; while (rank-- > 0) { - arrayType = arrayType.MakeArrayType (); + arrayType = MakeArrayType (arrayType); } yield return arrayType; } @@ -462,6 +472,11 @@ protected bool TryRegisterNativeMembers ( static Type [] registerMethodParameters = new Type [] { typeof (JniNativeMethodRegistrationArguments) }; + // https://github.com/xamarin/xamarin-android/blob/5472eec991cc075e4b0c09cd98a2331fb93aa0f3/src/Microsoft.Android.Sdk.ILLink/PreserveRegistrations.cs#L85 + const string MarshalMethods = "'jni_marshal_methods' is preserved by the PreserveRegistrations trimmer step."; + + [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = MarshalMethods)] + [UnconditionalSuppressMessage ("Trimming", "IL2075", Justification = MarshalMethods)] bool TryLoadJniMarshalMethods ( JniType nativeClass, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs index 91e862dc7..181469f6d 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs @@ -359,18 +359,36 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type) static Type? GetInvokerType (Type type) { const string suffix = "Invoker"; + + // https://github.com/xamarin/xamarin-android/blob/5472eec991cc075e4b0c09cd98a2331fb93aa0f3/src/Microsoft.Android.Sdk.ILLink/MarkJavaObjects.cs#L176-L186 + const string assemblyGetTypeMessage = "'Invoker' types are preserved by the MarkJavaObjects trimmer step."; + const string makeGenericTypeMessage = "Generic 'Invoker' types are preserved by the MarkJavaObjects trimmer step."; + + [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = assemblyGetTypeMessage)] + [UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = assemblyGetTypeMessage)] + [return: DynamicallyAccessedMembers (Constructors)] + static Type? AssemblyGetType (Assembly assembly, string typeName) => + assembly.GetType (typeName); + + // FIXME: https://github.com/xamarin/java.interop/issues/1192 + [UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = makeGenericTypeMessage)] + [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = makeGenericTypeMessage)] + [return: DynamicallyAccessedMembers (Constructors)] + static Type MakeGenericType (Type type, Type [] arguments) => + type.MakeGenericType (arguments); + Type[] arguments = type.GetGenericArguments (); if (arguments.Length == 0) - return type.Assembly.GetType (type + suffix); + return AssemblyGetType (type.Assembly, type + suffix); Type definition = type.GetGenericTypeDefinition (); int bt = definition.FullName!.IndexOf ("`", StringComparison.Ordinal); if (bt == -1) throw new NotSupportedException ("Generic type doesn't follow generic type naming convention! " + type.FullName); - Type? suffixDefinition = definition.Assembly.GetType ( + Type? suffixDefinition = AssemblyGetType (definition.Assembly, definition.FullName.Substring (0, bt) + suffix + definition.FullName.Substring (bt)); if (suffixDefinition == null) return null; - return suffixDefinition.MakeGenericType (arguments); + return MakeGenericType (suffixDefinition, arguments); } public object? CreateValue ( @@ -634,9 +652,17 @@ public JniValueMarshaler GetValueMarshaler ( static JniValueMarshaler GetObjectArrayMarshaler (Type elementType) { + const string makeGenericMethodMessage = "This code path is not used in Android projects."; + + // FIXME: https://github.com/xamarin/java.interop/issues/1192 + [UnconditionalSuppressMessage ("Trimming", "IL2060", Justification = makeGenericMethodMessage)] + [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = makeGenericMethodMessage)] + static MethodInfo MakeGenericMethod (MethodInfo method, Type type) => + method.MakeGenericMethod (type); + Func indirect = GetObjectArrayMarshalerHelper; - var reifiedMethodInfo = indirect.Method.GetGenericMethodDefinition () - .MakeGenericMethod (elementType); + var reifiedMethodInfo = MakeGenericMethod ( + indirect.Method.GetGenericMethodDefinition (), elementType); Func direct = (Func) Delegate.CreateDelegate (typeof (Func), reifiedMethodInfo); return direct (); } diff --git a/src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs b/src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs index f4869fcf1..b674094be 100644 --- a/src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs +++ b/src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Diagnostics.CodeAnalysis; @@ -8,13 +8,16 @@ namespace Java.Interop { [AttributeUsage (Targets, AllowMultiple=false)] public class JniValueMarshalerAttribute : Attribute { + const DynamicallyAccessedMemberTypes ParameterlessConstructorsInterfaces = DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.Interfaces; const AttributeTargets Targets = AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Parameter | AttributeTargets.ReturnValue; - public JniValueMarshalerAttribute (Type marshalerType) + public JniValueMarshalerAttribute ( + [DynamicallyAccessedMembers (ParameterlessConstructorsInterfaces)] + Type marshalerType) { if (marshalerType == null) throw new ArgumentNullException (nameof (marshalerType)); @@ -27,7 +30,7 @@ public JniValueMarshalerAttribute (Type marshalerType) } public Type MarshalerType { - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + [return: DynamicallyAccessedMembers (ParameterlessConstructorsInterfaces)] get; } } diff --git a/src/Java.Interop/Java.Interop/ManagedPeer.cs b/src/Java.Interop/Java.Interop/ManagedPeer.cs index f3874b635..763e439f2 100644 --- a/src/Java.Interop/Java.Interop/ManagedPeer.cs +++ b/src/Java.Interop/Java.Interop/ManagedPeer.cs @@ -229,6 +229,11 @@ static List[] GetConstructorCandidateParameterTypes (string signature) static object?[]? GetValues (JniRuntime runtime, JniObjectReference values, ConstructorInfo cinfo) { + // https://github.com/xamarin/xamarin-android/blob/5472eec991cc075e4b0c09cd98a2331fb93aa0f3/src/Microsoft.Android.Sdk.ILLink/MarkJavaObjects.cs#L51-L132 + [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "Constructors are preserved by the MarkJavaObjects trimmer step.")] + static object? ValueManagerGetValue (JniRuntime runtime, ref JniObjectReference value, ParameterInfo parameter) => + runtime.ValueManager.GetValue (ref value, JniObjectReferenceOptions.CopyAndDispose, parameter.ParameterType); + if (!values.IsValid) return null; @@ -240,7 +245,7 @@ static List[] GetConstructorCandidateParameterTypes (string signature) var pvalues = new object? [len]; for (int i = 0; i < len; ++i) { var n_value = JniEnvironment.Arrays.GetObjectArrayElement (values, i); - var value = runtime.ValueManager.GetValue (ref n_value, JniObjectReferenceOptions.CopyAndDispose, parameters [i].ParameterType); + var value = ValueManagerGetValue (runtime, ref n_value, parameters [i]); pvalues [i] = value; } diff --git a/src/Java.Interop/Properties/AssemblyInfo.cs b/src/Java.Interop/Properties/AssemblyInfo.cs index b32e4cf93..01afd8e26 100644 --- a/src/Java.Interop/Properties/AssemblyInfo.cs +++ b/src/Java.Interop/Properties/AssemblyInfo.cs @@ -6,7 +6,6 @@ [assembly: AssemblyDescription ("")] [assembly: AssemblyCulture ("")] [assembly: AssemblyTrademark ("Microsoft Corporation")] -[assembly: AssemblyMetadata ("IsTrimmable", "True")] [assembly: InternalsVisibleTo ( "Java.Interop.GenericMarshaler, PublicKey=" +