Skip to content

Commit ba07dd0

Browse files
committed
[Xamarin.Android.Tools.Bytecode] Only hide getters/setters for internal properties.
1 parent 3c83179 commit ba07dd0

File tree

6 files changed

+73
-15
lines changed

6 files changed

+73
-15
lines changed

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,9 @@ public class KotlinProperty : KotlinMethodBase
318318
}
319319

320320
public override string? ToString () => Name;
321+
322+
// Internal has value 0, so we have to check for it by eliminating all other possibilities.
323+
public bool IsInternalVisible => !Flags.HasFlag (KotlinPropertyFlags.Public) && !Flags.HasFlag (KotlinPropertyFlags.Protected) && !Flags.HasFlag (KotlinPropertyFlags.Private) && !Flags.HasFlag (KotlinPropertyFlags.Private) && !Flags.HasFlag (KotlinPropertyFlags.Local);
321324
}
322325

323326
public class KotlinType
@@ -698,15 +701,15 @@ public enum KotlinPropertyFlags
698701
Delegation = 0b10_00_000_0,
699702
Synthesized = 0b11_00_000_0,
700703

701-
IsVar = 0b_000000001_000_00_000_0,
702-
HasGetter = 0b_000000010_000_00_000_0,
703-
HasSetter = 0b_000000100_000_00_000_0,
704-
IsConst = 0b_000001000_000_00_000_0,
705-
IsLateInit = 0b_000010000_000_00_000_0,
706-
HasConstant = 0b_000100000_000_00_000_0,
707-
IsExternalProperty = 0b_001000000_000_00_000_0,
708-
IsDelegated = 0b_010000000_000_00_000_0,
709-
IsExpectProperty = 0b_100000000_000_00_000_0
704+
IsVar = 0b_000000001_00_00_000_0,
705+
HasGetter = 0b_000000010_00_00_000_0,
706+
HasSetter = 0b_000000100_00_00_000_0,
707+
IsConst = 0b_000001000_00_00_000_0,
708+
IsLateInit = 0b_000010000_00_00_000_0,
709+
HasConstant = 0b_000100000_00_00_000_0,
710+
IsExternalProperty = 0b_001000000_00_00_000_0,
711+
IsDelegated = 0b_010000000_00_00_000_0,
712+
IsExpectProperty = 0b_100000000_00_00_000_0
710713
}
711714

712715
[Flags]

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,8 @@ static void FixupProperty (MethodInfo? getter, MethodInfo? setter, KotlinPropert
272272
if (getter is null && setter is null)
273273
return;
274274

275-
// Hide property if it isn't Public/Protected
276-
if (!metadata.Flags.IsPubliclyVisible ()) {
275+
// Hide getters/setters if property is Internal
276+
if (metadata.IsInternalVisible) {
277277

278278
if (getter?.IsPubliclyVisible == true) {
279279
Log.Debug ($"Kotlin: Hiding internal getter method {getter.DeclaringType?.ThisClass.Name.Value} - {getter.Name}");
@@ -384,7 +384,9 @@ static void FixupField (FieldInfo? field, KotlinProperty metadata)
384384

385385
static MethodInfo? FindJavaPropertyGetter (KotlinFile kotlinClass, KotlinProperty property, ClassFile klass)
386386
{
387-
var possible_methods = klass.Methods.Where (method => string.Compare (method.GetMethodNameWithoutSuffix (), $"get{property.Name}", StringComparison.OrdinalIgnoreCase) == 0 &&
387+
var method_name = $"get{property.Name.Capitalize ()}$";
388+
389+
var possible_methods = klass.Methods.Where (method => method.Name.StartsWith (method_name, StringComparison.Ordinal) &&
388390
method.GetParameters ().Length == 0 &&
389391
property.ReturnType != null &&
390392
TypesMatch (method.ReturnType, property.ReturnType, kotlinClass));
@@ -394,7 +396,9 @@ static void FixupField (FieldInfo? field, KotlinProperty metadata)
394396

395397
static MethodInfo? FindJavaPropertySetter (KotlinFile kotlinClass, KotlinProperty property, ClassFile klass)
396398
{
397-
var possible_methods = klass.Methods.Where (method => string.Compare (method.GetMethodNameWithoutSuffix (), $"set{property.Name}", StringComparison.OrdinalIgnoreCase) == 0 &&
399+
var method_name = $"set{property.Name.Capitalize ()}$";
400+
401+
var possible_methods = klass.Methods.Where (method => method.Name.StartsWith (method_name, StringComparison.Ordinal) &&
398402
property.ReturnType != null &&
399403
method.GetParameters ().Length == 1 &&
400404
method.ReturnType.BinaryName == "V" &&

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45
using System.Text;
56
using System.Threading.Tasks;
@@ -8,6 +9,18 @@ namespace Xamarin.Android.Tools.Bytecode
89
{
910
public static class KotlinUtilities
1011
{
12+
[return: NotNullIfNotNull (nameof (value))]
13+
public static string? Capitalize (this string? value)
14+
{
15+
if (string.IsNullOrWhiteSpace (value))
16+
return value;
17+
18+
if (value.Length < 1)
19+
return value;
20+
21+
return char.ToUpperInvariant (value [0]) + value.Substring (1);
22+
}
23+
1124
public static string ConvertKotlinTypeSignature (KotlinType? type, KotlinFile? metadata = null, bool convertUnsignedToPrimitive = true)
1225
{
1326
if (type is null)

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,29 @@ public void HandleKotlinNameShadowing ()
324324

325325
Assert.True (klass.Methods.Single (m => m.Name == "count").AccessFlags.HasFlag (MethodAccessFlags.Public));
326326
Assert.True (klass.Methods.Single (m => m.Name == "hitCount").AccessFlags.HasFlag (MethodAccessFlags.Public));
327+
328+
// Private property and explicit getter/setter
329+
// There is no generated getter/setter, and explicit ones should be public
330+
Assert.True (klass.Methods.Single (m => m.Name == "getType").AccessFlags.HasFlag (MethodAccessFlags.Public));
327331
Assert.True (klass.Methods.Single (m => m.Name == "setType").AccessFlags.HasFlag (MethodAccessFlags.Public));
332+
333+
// Private immutable property and explicit getter/setter
334+
// There is no generated getter/setter, and explicit ones should be public
335+
Assert.True (klass.Methods.Single (m => m.Name == "getType2").AccessFlags.HasFlag (MethodAccessFlags.Public));
336+
Assert.True (klass.Methods.Single (m => m.Name == "setType2").AccessFlags.HasFlag (MethodAccessFlags.Public));
337+
338+
// Internal property and explicit getter/setter
339+
// Generated getter/setter should not be public, and explicit ones should be public
340+
Assert.False (klass.Methods.Single (m => m.Name == "getItype$main").AccessFlags.HasFlag (MethodAccessFlags.Public));
341+
Assert.False (klass.Methods.Single (m => m.Name == "setItype$main").AccessFlags.HasFlag (MethodAccessFlags.Public));
342+
Assert.True (klass.Methods.Single (m => m.Name == "getItype").AccessFlags.HasFlag (MethodAccessFlags.Public));
343+
Assert.True (klass.Methods.Single (m => m.Name == "setItype").AccessFlags.HasFlag (MethodAccessFlags.Public));
344+
345+
// Internal immutable property and explicit getter/setter
346+
// Generated getter should not be public, and explicit ones should be public
347+
Assert.False (klass.Methods.Single (m => m.Name == "getItype2$main").AccessFlags.HasFlag (MethodAccessFlags.Public));
348+
Assert.True (klass.Methods.Single (m => m.Name == "getItype2").AccessFlags.HasFlag (MethodAccessFlags.Public));
349+
Assert.True (klass.Methods.Single (m => m.Name == "setItype2").AccessFlags.HasFlag (MethodAccessFlags.Public));
328350
}
329351

330352
[Test]
Binary file not shown.

tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/NameShadowing.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,23 @@ public class NameShadowing {
88
private var hitCount = 0
99
fun hitCount(): Int = hitCount
1010

11-
// Property and setter
11+
// Private property and explicit getter/setter
1212
private var type = 0
13-
fun setType(type: Int) = { println (type); }
13+
fun getType(): Int = type
14+
fun setType(type: Int) { }
15+
16+
// Private immutable property and explicit getter/setter
17+
private val type2 = 0
18+
fun getType2(): Int = type2
19+
fun setType2(type: Int) { }
20+
21+
// Internal property and explicit getter/setter
22+
internal var itype = 0
23+
fun getItype(): Int = itype
24+
fun setItype(type: Int) { }
25+
26+
// Internal immutable property and explicit getter/setter
27+
internal val itype2 = 0
28+
fun getItype2(): Int = itype2
29+
fun setItype2(type: Int) { }
1430
}

0 commit comments

Comments
 (0)