Skip to content

Commit 322ed90

Browse files
committed
[Bytecode] Hide Kotlin synthetic default constructors.
1 parent dcaf794 commit 322ed90

File tree

7 files changed

+59
-38
lines changed

7 files changed

+59
-38
lines changed

src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ static void FixupJavaMethods (Methods methods)
9393
method.AccessFlags = MethodAccessFlags.Private;
9494
}
9595

96+
// Hide constructor if it's the synthetic DefaultConstructorMarker one
97+
foreach (var method in methods.Where (method => method.IsDefaultConstructorMarker ())) {
98+
Log.Debug ($"Kotlin: Hiding synthetic default constructor in class '{method.DeclaringType?.ThisClass.Name.Value}' with signature '{method.Descriptor}'");
99+
method.AccessFlags = ((method.AccessFlags ^ MethodAccessFlags.Public) & method.AccessFlags) | MethodAccessFlags.Private;
100+
}
101+
96102
// Better parameter names in extension methods
97103
foreach (var method in methods.Where (m => m.IsPubliclyVisible && m.AccessFlags.HasFlag (MethodAccessFlags.Static)))
98104
FixupExtensionMethod (method);

src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinUtilities.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,29 @@ public static string GetMethodNameWithoutSuffix (this MethodInfo method)
7272
return index >= 0 ? method.Name.Substring (0, index) : method.Name;
7373
}
7474

75+
public static bool IsDefaultConstructorMarker (this MethodInfo method)
76+
{
77+
// A default constructor is synthetic and always has an int and a
78+
// DefaultConstructorMarker as its final 2 parameters.
79+
if (method.Name != "<init>")
80+
return false;
81+
82+
if (!method.AccessFlags.HasFlag (MethodAccessFlags.Synthetic))
83+
return false;
84+
85+
var parameters = method.GetParameters ();
86+
87+
if (parameters.Length < 2)
88+
return false;
89+
90+
// Final parameter is DefaultConstructorMarker
91+
if (parameters.Last ().Type.TypeSignature != "Lkotlin/jvm/internal/DefaultConstructorMarker;")
92+
return false;
93+
94+
// Next to final parameter is int
95+
return parameters [parameters.Length - 2].Type.TypeSignature == "I";
96+
}
97+
7598
public static bool IsPubliclyVisible (this ClassAccessFlags flags) => flags.HasFlag (ClassAccessFlags.Public) || flags.HasFlag (ClassAccessFlags.Protected);
7699

77100
public static bool IsPubliclyVisible (this KotlinClassVisibility flags) => flags == KotlinClassVisibility.Public || flags == KotlinClassVisibility.Protected;

tests/Xamarin.Android.Tools.Bytecode-Tests/KotlinFixupsTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,32 @@ public void HideInternalConstructor ()
5151
Assert.False (ctor.AccessFlags.HasFlag (MethodAccessFlags.Public));
5252
}
5353

54+
[Test]
55+
public void HideDefaultConstructorMarker ()
56+
{
57+
var klass = LoadClassFile ("DefaultConstructor.class");
58+
59+
// init ()
60+
var ctor_0p = klass.Methods.Single (m => m.Name == "<init>" && m.GetParameters ().Length == 0);
61+
62+
// init (string name)
63+
var ctor_1p = klass.Methods.Single (m => m.Name == "<init>" && m.GetParameters ().Length == 1);
64+
65+
// init (string p0, int p1, DefaultConstructorMarker p2)
66+
var ctor_3p = klass.Methods.Single (m => m.Name == "<init>" && m.GetParameters ().Length == 3);
67+
68+
Assert.True (ctor_3p.AccessFlags.HasFlag (MethodAccessFlags.Public));
69+
70+
KotlinFixups.Fixup (new [] { klass });
71+
72+
// Assert that the normal constructors are still public
73+
Assert.True (ctor_0p.AccessFlags.HasFlag (MethodAccessFlags.Public));
74+
Assert.True (ctor_1p.AccessFlags.HasFlag (MethodAccessFlags.Public));
75+
76+
// Assert that the synthetic "DefaultConstructorMarker" constructor has been marked private
77+
Assert.False (ctor_3p.AccessFlags.HasFlag (MethodAccessFlags.Public));
78+
}
79+
5480
[Test]
5581
public void HideImplementationMethod ()
5682
{

tests/Xamarin.Android.Tools.Bytecode-Tests/Resources/JvmOverloadsConstructor.xml

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -75,44 +75,6 @@
7575
type="boolean"
7676
jni-type="Z" />
7777
</constructor>
78-
<constructor
79-
deprecated="not deprecated"
80-
final="false"
81-
name="JvmOverloadsConstructor"
82-
static="false"
83-
visibility="public"
84-
bridge="false"
85-
synthetic="true"
86-
jni-signature="(LJvmOverloadsConstructor;IILjava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V">
87-
<parameter
88-
name="p0"
89-
type="JvmOverloadsConstructor"
90-
jni-type="LJvmOverloadsConstructor;" />
91-
<parameter
92-
name="p1"
93-
type="int"
94-
jni-type="I" />
95-
<parameter
96-
name="p2"
97-
type="int"
98-
jni-type="I" />
99-
<parameter
100-
name="p3"
101-
type="java.lang.String"
102-
jni-type="Ljava/lang/String;" />
103-
<parameter
104-
name="p4"
105-
type="boolean"
106-
jni-type="Z" />
107-
<parameter
108-
name="p5"
109-
type="int"
110-
jni-type="I" />
111-
<parameter
112-
name="p6"
113-
type="kotlin.jvm.internal.DefaultConstructorMarker"
114-
jni-type="Lkotlin/jvm/internal/DefaultConstructorMarker;" />
115-
</constructor>
11678
<constructor
11779
deprecated="not deprecated"
11880
final="false"
Binary file not shown.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class DefaultConstructor (name: String = "bob") {
2+
}

tools/generator/generator.slnf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
"src\\Java.Interop.Tools.Diagnostics\\Java.Interop.Tools.Diagnostics.csproj",
1010
"src\\Xamarin.Android.Tools.AnnotationSupport\\Xamarin.Android.Tools.AnnotationSupport.csproj",
1111
"src\\Xamarin.Android.Tools.ApiXmlAdjuster\\Xamarin.Android.Tools.ApiXmlAdjuster.csproj",
12+
"src\\Xamarin.Android.Tools.Bytecode\\Xamarin.Android.Tools.Bytecode.csproj",
1213
"src\\Xamarin.SourceWriter\\Xamarin.SourceWriter.csproj",
1314
"tests\\generator-Tests\\generator-Tests.csproj",
15+
"tests\\Xamarin.Android.Tools.Bytecode-Tests\\Xamarin.Android.Tools.Bytecode-Tests.csproj",
1416
"tests\\Xamarin.SourceWriter-Tests\\Xamarin.SourceWriter-Tests.csproj",
1517
"tools\\generator\\generator.csproj",
1618
]

0 commit comments

Comments
 (0)