Merge "Fixed array bug for proguard keep file generation" am: d98baeca50 am: 5ba4db04eb
am: 15c6aa1023
Change-Id: Ic53ea8c705a67cec8b9d880efdb07ae247ecb176
diff --git a/src/main/java/com/android/tools/metalava/ProguardWriter.kt b/src/main/java/com/android/tools/metalava/ProguardWriter.kt
index 5ff6612..54e45e5 100644
--- a/src/main/java/com/android/tools/metalava/ProguardWriter.kt
+++ b/src/main/java/com/android/tools/metalava/ProguardWriter.kt
@@ -127,7 +127,12 @@
private fun getCleanTypeName(t: TypeItem?): String {
t ?: return ""
- val cls = t.asClass() ?: return t.toSimpleType()
- return cls.qualifiedNameWithDollarInnerClasses()
+ val cls = t.asClass() ?: return t.toCanonicalType()
+ var qualifiedName = cls.qualifiedNameWithDollarInnerClasses()
+
+ for (i in 0 until t.arrayDimensions()) {
+ qualifiedName += "[]"
+ }
+ return qualifiedName
}
}
\ No newline at end of file
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
index d879463..32c55f3 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
@@ -569,7 +569,11 @@
val cls = psiType.resolve() ?: return null
return findOrCreateClass(cls)
} else if (psiType is PsiArrayType) {
- val componentType = psiType.componentType
+ var componentType = psiType.componentType
+ // We repeatedly get the component type because the array may have multiple dimensions
+ while (componentType is PsiArrayType) {
+ componentType = componentType.componentType
+ }
if (componentType is PsiClassType) {
val cls = componentType.resolve() ?: return null
return findOrCreateClass(cls)
diff --git a/src/test/java/com/android/tools/metalava/KeepFileTest.kt b/src/test/java/com/android/tools/metalava/KeepFileTest.kt
index 960d825..e35a9f8 100644
--- a/src/test/java/com/android/tools/metalava/KeepFileTest.kt
+++ b/src/test/java/com/android/tools/metalava/KeepFileTest.kt
@@ -82,4 +82,279 @@
extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
)
}
+
+ @Test
+ fun `Primitive types`() {
+ check(
+ checkDoclava1 = true,
+ sourceFiles = *arrayOf(
+ java(
+ """
+ package test.pkg;
+ public class MyClass {
+ public int testMethodA(int a) {}
+ public boolean testMethodB(boolean a) {}
+ public float testMethodC(float a) {}
+ public double testMethodD(double a) {}
+ public byte testMethodE(byte a) {}
+ }
+ """
+ )
+ ),
+ proguard = """
+ -keep class test.pkg.MyClass {
+ <init>();
+ public int testMethodA(int);
+ public boolean testMethodB(boolean);
+ public float testMethodC(float);
+ public double testMethodD(double);
+ public byte testMethodE(byte);
+ }
+ """,
+ extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
+ )
+ }
+
+ @Test
+ fun `Primitive array types`() {
+ check(
+ checkDoclava1 = true,
+ sourceFiles = *arrayOf(
+ java(
+ """
+ package test.pkg;
+ public class MyClass {
+ public int[] testMethodA(int[] a) {}
+ public float[][] testMethodB(float[][] a) {}
+ public double[][][] testMethodC(double[][][] a) {}
+ public byte testMethodD(byte... a) {}
+ }
+ """
+ )
+ ),
+ proguard = """
+ -keep class test.pkg.MyClass {
+ <init>();
+ public int[] testMethodA(int[]);
+ public float[][] testMethodB(float[][]);
+ public double[][][] testMethodC(double[][][]);
+ public byte testMethodD(byte[]);
+ }
+ """,
+ extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
+ )
+ }
+
+ @Test
+ fun `Object Array parameters`() {
+ check(
+ checkDoclava1 = true,
+ sourceFiles = *arrayOf(
+ java(
+ """
+ package test.pkg;
+ public class MyClass {
+ public void testMethodA(String a) {}
+ public void testMethodB(Boolean[] a) {}
+ public void testMethodC(Integer... a) {}
+ }
+ """
+ )
+ ),
+ proguard = """
+ -keep class test.pkg.MyClass {
+ <init>();
+ public void testMethodA(java.lang.String);
+ public void testMethodB(java.lang.Boolean[]);
+ public void testMethodC(java.lang.Integer[]);
+ }
+ """,
+ extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
+ )
+ }
+
+ @Test
+ fun `Arrays with Inner class`() {
+ check(
+ checkDoclava1 = true,
+ sourceFiles = *arrayOf(
+ java(
+ """
+ package test.pkg;
+ public class MyClass {
+ public void testMethodA(InnerClass a) {}
+ public void testMethodB(InnerClass[] a) {}
+ public void testMethodC(InnerClass... a) {}
+ public class InnerClass {}
+ }
+ """
+ )
+ ),
+ proguard = """
+ -keep class test.pkg.MyClass {
+ <init>();
+ public void testMethodA(test.pkg.MyClass${"$"}InnerClass);
+ public void testMethodB(test.pkg.MyClass${"$"}InnerClass[]);
+ public void testMethodC(test.pkg.MyClass${"$"}InnerClass[]);
+ }
+ -keep class test.pkg.MyClass${"$"}InnerClass {
+ <init>();
+ }
+ """,
+ extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
+ )
+ }
+
+ @Test
+ fun `Conflicting Class Names in parameters`() {
+ check(
+ checkDoclava1 = true,
+ sourceFiles = *arrayOf(
+ java(
+ """
+ package test.pkg;
+ public class String {}
+ """
+ ),
+ java(
+ """
+ package test.pkg;
+ public class MyClass {
+ public void testMethodA(String a, String b) {}
+ public void testMethodB(String a, test.pkg.String b) {}
+ public void testMethodC(String a, java.lang.String b) {}
+ public void testMethodD(java.lang.String a, test.pkg.String b) {}
+ }
+ """
+ ),
+ java(
+ """
+ package test.pkg;
+ public class MyClassArrays {
+ public void testMethodA(String[] a, String[] b) {}
+ public void testMethodB(String[] a, test.pkg.String[] b) {}
+ public void testMethodC(String[] a, java.lang.String[] b) {}
+ public void testMethodD(java.lang.String... a, test.pkg.String... b) {}
+ }
+ """
+ )
+ ),
+ proguard = """
+ -keep class test.pkg.MyClass {
+ <init>();
+ public void testMethodA(test.pkg.String, test.pkg.String);
+ public void testMethodB(test.pkg.String, test.pkg.String);
+ public void testMethodC(test.pkg.String, java.lang.String);
+ public void testMethodD(java.lang.String, test.pkg.String);
+ }
+ -keep class test.pkg.MyClassArrays {
+ <init>();
+ public void testMethodA(test.pkg.String[], test.pkg.String[]);
+ public void testMethodB(test.pkg.String[], test.pkg.String[]);
+ public void testMethodC(test.pkg.String[], java.lang.String[]);
+ public void testMethodD(java.lang.String[], test.pkg.String[]);
+ }
+ -keep class test.pkg.String {
+ <init>();
+ }
+ """,
+ extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
+ )
+ }
+
+ @Test
+ fun `Multi dimensional arrays`() {
+ check(
+ checkDoclava1 = true,
+ sourceFiles = *arrayOf(
+ java(
+ """
+ package test.pkg;
+ public class String {}
+ """
+ ),
+ java(
+ """
+ package test.pkg;
+ public class MyClassArrays {
+ public void testMethodA(String[][] a, String[][] b) {}
+ public void testMethodB(String[][][] a, test.pkg.String[][][] b) {}
+ public void testMethodC(String[][] a, java.lang.String[][] b) {}
+ public class InnerClass {}
+ public void testMethodD(InnerClass[][] a) {}
+ }
+ """
+ )
+ ),
+ proguard = """
+ -keep class test.pkg.MyClassArrays {
+ <init>();
+ public void testMethodA(test.pkg.String[][], test.pkg.String[][]);
+ public void testMethodB(test.pkg.String[][][], test.pkg.String[][][]);
+ public void testMethodC(test.pkg.String[][], java.lang.String[][]);
+ public void testMethodD(test.pkg.MyClassArrays${"$"}InnerClass[][]);
+ }
+ -keep class test.pkg.MyClassArrays${"$"}InnerClass {
+ <init>();
+ }
+ -keep class test.pkg.String {
+ <init>();
+ }
+ """,
+ extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
+ )
+ }
+
+ @Test
+ fun `Methods with arrays as the return type`() {
+ check(
+ checkDoclava1 = true,
+ sourceFiles = *arrayOf(
+ java(
+ """
+ package test.pkg;
+ public class MyClass {
+ public String[] testMethodA() {}
+ public String[][] testMethodB() {}
+ public String[][][] testMethodC() {}
+ }
+ """
+ ),
+ java(
+ """
+ package test.pkg;
+ public class MyOtherClass {
+ public java.lang.String[] testMethodA() {}
+ public String[][] testMethodB() {}
+ public test.pkg.String[][][] testMethodC() {}
+ }
+ """
+ ),
+ java(
+ """
+ package test.pkg;
+ public class String {}
+ """
+ )
+ ),
+ proguard = """
+ -keep class test.pkg.MyClass {
+ <init>();
+ public test.pkg.String[] testMethodA();
+ public test.pkg.String[][] testMethodB();
+ public test.pkg.String[][][] testMethodC();
+ }
+ -keep class test.pkg.MyOtherClass {
+ <init>();
+ public java.lang.String[] testMethodA();
+ public test.pkg.String[][] testMethodB();
+ public test.pkg.String[][][] testMethodC();
+ }
+ -keep class test.pkg.String {
+ <init>();
+ }
+ """,
+ extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
+ )
+ }
}
\ No newline at end of file