diff --git a/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs b/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs index 542dc8404..ae4d78077 100644 --- a/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs +++ b/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs @@ -67,21 +67,41 @@ static void FixupClassVisibility (ClassFile klass, KotlinClass metadata) // Hide class if it isn't Public/Protected if (klass.AccessFlags.IsPubliclyVisible () && !metadata.Visibility.IsPubliclyVisible ()) { - // Interfaces should be set to "package-private", which is "no visibility flags" + // Interfaces should be set to "package-private" if (klass.AccessFlags.HasFlag (ClassAccessFlags.Interface)) { - Log.Debug ($"Kotlin: Setting interface {klass.ThisClass.Name.Value} to package-private"); - klass.AccessFlags = (klass.AccessFlags ^ ClassAccessFlags.Public) & klass.AccessFlags; - klass.AccessFlags = (klass.AccessFlags ^ ClassAccessFlags.Protected) & klass.AccessFlags; - klass.AccessFlags = (klass.AccessFlags ^ ClassAccessFlags.Private) & klass.AccessFlags; + Log.Debug ($"Kotlin: Setting internal interface {klass.ThisClass.Name.Value} to package-private"); + klass.AccessFlags = SetPackagePrivate (klass.AccessFlags); + + foreach (var ic in klass.InnerClasses) { + Log.Debug ($"Kotlin: Setting nested type {ic.InnerClass.Name.Value} in an internal interface to package-private"); + ic.InnerClassAccessFlags = SetPackagePrivate (ic.InnerClassAccessFlags); + } + return; } Log.Debug ($"Kotlin: Hiding internal class {klass.ThisClass.Name.Value}"); klass.AccessFlags = ClassAccessFlags.Private; + + foreach (var ic in klass.InnerClasses) { + Log.Debug ($"Kotlin: Hiding nested internal type {ic.InnerClass.Name.Value}"); + ic.InnerClassAccessFlags = ClassAccessFlags.Private; + } + return; } } + static ClassAccessFlags SetPackagePrivate (ClassAccessFlags flags) + { + // Package-private is stored as "no visibility flags" + flags = (flags ^ ClassAccessFlags.Public) & flags; + flags = (flags ^ ClassAccessFlags.Protected) & flags; + flags = (flags ^ ClassAccessFlags.Private) & flags; + + return flags; + } + static void FixupJavaMethods (Methods methods) { // We do the following method level fixups here because we can operate on all methods, diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/KotlinFixupsTests.cs b/tests/Xamarin.Android.Tools.Bytecode-Tests/KotlinFixupsTests.cs index fed16412d..05e813456 100644 --- a/tests/Xamarin.Android.Tools.Bytecode-Tests/KotlinFixupsTests.cs +++ b/tests/Xamarin.Android.Tools.Bytecode-Tests/KotlinFixupsTests.cs @@ -15,20 +15,25 @@ public class KotlinFixupsTests : ClassFileFixture public void HideInternalClass () { var klass = LoadClassFile ("InternalClass.class"); + var inner_class = klass.InnerClasses.First (); Assert.True (klass.AccessFlags.HasFlag (ClassAccessFlags.Public)); + Assert.True (inner_class.InnerClassAccessFlags.HasFlag (ClassAccessFlags.Public)); KotlinFixups.Fixup (new [] { klass }); Assert.False (klass.AccessFlags.HasFlag (ClassAccessFlags.Public)); + Assert.False (inner_class.InnerClassAccessFlags.HasFlag (ClassAccessFlags.Public)); } [Test] public void MakeInternalInterfacePackagePrivate () { var klass = LoadClassFile ("InternalInterface.class"); + var inner_class = klass.InnerClasses.First (); Assert.True (klass.AccessFlags.HasFlag (ClassAccessFlags.Public)); + Assert.True (inner_class.InnerClassAccessFlags.HasFlag (ClassAccessFlags.Public)); KotlinFixups.Fixup (new [] { klass }); @@ -36,6 +41,10 @@ public void MakeInternalInterfacePackagePrivate () Assert.False (klass.AccessFlags.HasFlag (ClassAccessFlags.Public)); Assert.False (klass.AccessFlags.HasFlag (ClassAccessFlags.Protected)); Assert.False (klass.AccessFlags.HasFlag (ClassAccessFlags.Private)); + + Assert.False (inner_class.InnerClassAccessFlags.HasFlag (ClassAccessFlags.Public)); + Assert.False (inner_class.InnerClassAccessFlags.HasFlag (ClassAccessFlags.Protected)); + Assert.False (inner_class.InnerClassAccessFlags.HasFlag (ClassAccessFlags.Private)); } [Test] diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalClass.class b/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalClass.class index aa615c801..5708648aa 100644 Binary files a/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalClass.class and b/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalClass.class differ diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalClass.kt b/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalClass.kt index 8cd461778..3fbb91711 100644 --- a/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalClass.kt +++ b/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalClass.kt @@ -1 +1,3 @@ -internal class InternalClass \ No newline at end of file +internal class InternalClass { + enum class ChildEnum { VALUE1, VALUE2 } +} \ No newline at end of file diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalInterface.class b/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalInterface.class index f00e1ca4a..de140482e 100644 Binary files a/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalInterface.class and b/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalInterface.class differ diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalInterface.kt b/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalInterface.kt index 382d3537c..3a109d6ad 100644 --- a/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalInterface.kt +++ b/tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin/InternalInterface.kt @@ -1 +1,3 @@ -internal interface InternalInterface \ No newline at end of file +internal interface InternalInterface { + enum class ChildEnum { VALUE1, VALUE2 } +} \ No newline at end of file