Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ public static string GetMethodNameWithoutUnsignedSuffix (string name)

public static bool IsDefaultConstructorMarker (this MethodInfo method)
{
// A default constructor is synthetic and always has an int and a
// DefaultConstructorMarker as its final 2 parameters.
// A default constructor is synthetic and has a DefaultConstructorMarker as its final parameter.
if (method.Name != "<init>")
return false;

Expand All @@ -107,12 +106,11 @@ public static bool IsDefaultConstructorMarker (this MethodInfo method)

var parameters = method.GetParameters ();

if (parameters.Length < 2)
if (parameters.Length < 1)
return false;

// Parameter list ends with `int, DefaultConstructorMarker`.
return parameters [parameters.Length - 2].Type.TypeSignature == "I" &&
parameters [parameters.Length - 1].Type.TypeSignature == "Lkotlin/jvm/internal/DefaultConstructorMarker;";
// Parameter list ends with `DefaultConstructorMarker`.
return parameters [parameters.Length - 1].Type.TypeSignature == "Lkotlin/jvm/internal/DefaultConstructorMarker;";
}

// Sometimes the Kotlin provided JvmSignature is null (or unhelpful), so we need to construct one ourselves
Expand Down
22 changes: 22 additions & 0 deletions tests/Xamarin.Android.Tools.Bytecode-Tests/KotlinFixupsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,28 @@ public void HideDefaultConstructorMarker ()
Assert.False (ctor_3p.AccessFlags.HasFlag (MethodAccessFlags.Public));
}

[Test]
public void HidePrivateDefaultConstructorMarker ()
{
var klass = LoadClassFile ("PrivateDefaultConstructor.class");

// init (int isFoo)
var ctor_1p = klass.Methods.Single (m => m.Name == "<init>" && m.GetParameters ().Length == 1);

// init (int isFoo, DefaultConstructorMarker p1)
var ctor_2p = klass.Methods.Single (m => m.Name == "<init>" && m.GetParameters ().Length == 2);

Assert.True (ctor_2p.AccessFlags.HasFlag (MethodAccessFlags.Public));

KotlinFixups.Fixup ([klass]);

// Assert that the normal constructor is still public
Assert.False (ctor_1p.AccessFlags.HasFlag (MethodAccessFlags.Public));

// Assert that the synthetic "DefaultConstructorMarker" constructor has been marked private
Assert.False (ctor_2p.AccessFlags.HasFlag (MethodAccessFlags.Public));
}

[Test]
public void HideImplementationMethod ()
{
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public open class PrivateDefaultConstructor private constructor (internal val isFoo: Boolean) {
init { }

public companion object Default : PrivateDefaultConstructor (isFoo = false) { }
}