dotnet / java-interop

Java.Interop provides open-source bindings of Java's Java Native Interface (JNI) for use with .NET managed languages such as C#
Other
189 stars 48 forks source link

[Java.Interop.Tools.TypeNameMappings] fix trimmer warnings #1194

Closed jonathanpeppers closed 4 months ago

jonathanpeppers commented 5 months ago

Context: https://github.com/xamarin/xamarin-android/blob/e987ac458536e59a8329a06d5c5d5f4d4ea2c6b6/src/Mono.Android/Mono.Android.csproj#L69-L71

In xamarin/xamarin-android, we import the source for Java.Interop.Tools.TypeNameMappings\JavaNativeTypeManager.cs, and unfortunately there are some trimmer warnings:

external\Java.Interop\src\Java.Interop.Tools.TypeNameMappings\Java.Interop.Tools.TypeNameMappings\JavaNativeTypeManager.cs(182,9):
error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'type' of method 'Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToJniName(Type, ExportParameterKind)' 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.

From the code:

if (!type.GetInterfaces ().Any (t => t.FullName == "Android.Runtime.IJavaObject"))

It appears we can instead look for IJavaPeerable and use trim-safe behavior instead:

if (Type.GetType ("Java.Interop.IJavaPeerable, Java.Interop", throwOnError: true)
    .IsAssignableFrom (type))

I also cached the Type.GetType() call with Lazy<T>.

However, in some cases we run this code under an MSBuild context. In this case, we don't have Java.Interop.dll to load, so we should instead use:

type.GetInterfaces ().Any (t => t.FullName == "Java.Interop.IJavaPeerable");

To catch warnings in this project going forward:

As I targeted net8.0, various null-reference-type warnings appeared, which I also fixed.

jonathanpeppers commented 5 months ago

/cc @simonrozsival @vitek-karas