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

[Xamain.Android.Tools.Bytecode] Hide private Kotlin default constructors. #1206

Closed jpobst closed 3 months ago

jpobst commented 4 months ago

Kotlin.Stdlib contains the public class kotlin.io.encoding.Base64 which is not intended to be instantiated by external users. Thus it only contains a private default constructor.

https://github.com/JetBrains/kotlin/blob/3fbb7bc92086bdf3bde123a8f774bce25b19ef37/libraries/stdlib/src/kotlin/io/encoding/Base64.kt

public open class Base64 private constructor (internal val isUrlSafe: Boolean, internal val isMimeScheme: Boolean) {
   public companion object Default : Base64(isUrlSafe = false, isMimeScheme = false) { ... }
}

This compiles into the following Java constructors:

private <init> (Boolean isUrlSafe, Boolean isMimeScheme) { ... }

public <init> (Boolean isUrlSafe, Boolean isMimeScheme, kotlin.jvm.internal.DefaultConstructorMarker $constructor_marker) { ... }
// ^ synthetic constructor

Previously we believed that a synthetic default constructor would always end in an int and a DefaultConstructorMarker parameter, however this one does not.

https://github.com/xamarin/java.interop/blob/651de42732d194cee5a45fae45feda37706a8c16/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinUtilities.cs#L100-L103

This synthetic constructor causes us to generate some bizarre constructors:

[Register (".ctor", "(ZZLkotlin/jvm/internal/DefaultConstructorMarker;)V", "")]
public unsafe Base64 (bool isUrlSafe, bool isMimeScheme, global::Kotlin.Jvm.Internal.DefaultConstructorMarker? _constructor_marker) 
    : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer) { ... }

This commit extends our Kotlin default constructor marker detection logic to look for any synthetic constructor whose final parameter is DefaultConstructorMarker to handle this additional case.

With the change, Kotlin.IO.Encoding.Base64 no longer generates a public constructor.

jpobst commented 3 months ago

Ran this change against our AndroidX repo to ensure only intended constructors were getting removed. Diff file looks good.

output.txt