Skip to content

Commit 566a461

Browse files
authored
[Xamarin.Android.Tools.Bytecode] Kotlin name shadowing support (#573)
Fixes: #571 Don't mark `public` Kotlin methods as `private` if they "shadow" -- share the same name as -- a private property or field. If a library uses Kotlin's `NAME_SHADOWING` we incorrectly match the `private` property/field to the `public` method and mark the methods as `private`. Given Kotlin: @Suppress("NAME_SHADOWING") public class NameShadowing { // Property and method private val count: Int = 3 fun count(): Int = count // Field and method private var hitCount = 0 fun hitCount(): Int = hitCount // Property and setter private var type = 0 fun setType(type: Int) = { println (type); } } Then the public methods `NameShadowing.count()`, `NameShadowing.hitCount()`, and `NameShadowing.setType()` were not present within the C# binding. Support name shadowing by only considering `getFoo()` methods as potential property getters, instead of allowing `foo`. (Allowing `foo` was likely incorrect anyways.) Additionally, when considering if a method is a potential property setter, also check that the method's return type is `void`. [Xamarin.Android.Tools.Bytecode] Kotlin name shadowing support (#573)
1 parent 5d8a60e commit 566a461

File tree

4 files changed

+28
-2
lines changed

4 files changed

+28
-2
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,7 @@ static FieldInfo FindJavaFieldProperty (KotlinFile kotlinClass, KotlinProperty p
232232

233233
static MethodInfo FindJavaPropertyGetter (KotlinFile kotlinClass, KotlinProperty property, ClassFile klass)
234234
{
235-
var possible_methods = klass.Methods.Where (method => (string.Compare (method.GetMethodNameWithoutSuffix (), $"get{property.Name}", true) == 0 ||
236-
string.Compare (method.GetMethodNameWithoutSuffix (), property.Name, true) == 0) &&
235+
var possible_methods = klass.Methods.Where (method => string.Compare (method.GetMethodNameWithoutSuffix (), $"get{property.Name}", true) == 0 &&
237236
method.GetParameters ().Length == 0 &&
238237
TypesMatch (method.ReturnType, property.ReturnType, kotlinClass));
239238

@@ -245,6 +244,7 @@ static MethodInfo FindJavaPropertySetter (KotlinFile kotlinClass, KotlinProperty
245244
var possible_methods = klass.Methods.Where (method => string.Compare (method.GetMethodNameWithoutSuffix (), $"set{property.Name}", true) == 0 &&
246245
property.ReturnType != null &&
247246
method.GetParameters ().Length == 1 &&
247+
method.ReturnType.BinaryName == "V" &&
248248
TypesMatch (method.GetParameters () [0].Type, property.ReturnType, kotlinClass));
249249

250250
return possible_methods.FirstOrDefault ();

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,5 +236,17 @@ public void UnsignedMethodsXml ()
236236
Assert.AreEqual ("ubyte[]", xml.Elements ("method").Single (f => f.Attribute ("name").Value == "foo_ubytearray-GBYM_sE").Attribute ("return").Value);
237237
Assert.AreEqual ("ubyte[]", xml.Elements ("method").Single (f => f.Attribute ("name").Value == "foo_ubytearray-GBYM_sE").Element ("parameter").Attribute ("type").Value);
238238
}
239+
240+
[Test]
241+
public void HandleKotlinNameShadowing ()
242+
{
243+
var klass = LoadClassFile ("NameShadowing.class");
244+
245+
KotlinFixups.Fixup (new [] { klass });
246+
247+
Assert.True (klass.Methods.Single (m => m.Name == "count").AccessFlags.HasFlag (MethodAccessFlags.Public));
248+
Assert.True (klass.Methods.Single (m => m.Name == "hitCount").AccessFlags.HasFlag (MethodAccessFlags.Public));
249+
Assert.True (klass.Methods.Single (m => m.Name == "setType").AccessFlags.HasFlag (MethodAccessFlags.Public));
250+
}
239251
}
240252
}
Binary file not shown.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
@Suppress("NAME_SHADOWING")
2+
public class NameShadowing {
3+
// Property and method
4+
private val count: Int = 3
5+
fun count(): Int = count
6+
7+
// Field and method
8+
private var hitCount = 0
9+
fun hitCount(): Int = hitCount
10+
11+
// Property and setter
12+
private var type = 0
13+
fun setType(type: Int) = { println (type); }
14+
}

0 commit comments

Comments
 (0)