Fix reflection names in generated proguard files (#1088)

* Fix reflection names in generated proguard files

Proguard wants to speak reflection names

* Opportunistic clean up proguard tests

This ensures we fail the test if there are any unexpected ones
This commit is contained in:
Zac Sweers
2020-01-30 22:58:10 -05:00
committed by GitHub
parent 52cf86d609
commit d64033ed94
3 changed files with 119 additions and 102 deletions

View File

@@ -170,8 +170,8 @@ internal class AdapterGenerator(
} }
val adapterConstructorParams = when (requireNotNull(primaryConstructor).parameters.size) { val adapterConstructorParams = when (requireNotNull(primaryConstructor).parameters.size) {
1 -> listOf(CN_MOSHI.canonicalName) 1 -> listOf(CN_MOSHI.reflectionName())
2 -> listOf(CN_MOSHI.canonicalName, "${CN_TYPE.canonicalName}[]") 2 -> listOf(CN_MOSHI.reflectionName(), "${CN_TYPE.reflectionName()}[]")
// Should never happen // Should never happen
else -> error("Unexpected number of arguments on primary constructor: $primaryConstructor") else -> error("Unexpected number of arguments on primary constructor: $primaryConstructor")
} }
@@ -186,7 +186,7 @@ internal class AdapterGenerator(
} }
hasDefaultProperties = propertyList.any { it.hasDefault } hasDefaultProperties = propertyList.any { it.hasDefault }
parameterTypes = AsmType.getArgumentTypes(constructorSignature.removePrefix("<init>")) parameterTypes = AsmType.getArgumentTypes(constructorSignature.removePrefix("<init>"))
.map { it.toCanonicalString() } .map { it.toReflectionString() }
} }
return ProguardConfig( return ProguardConfig(
targetClass = className, targetClass = className,
@@ -568,7 +568,7 @@ internal class AdapterGenerator(
/** Represents a prepared adapter with its [spec] and optional associated [proguardConfig]. */ /** Represents a prepared adapter with its [spec] and optional associated [proguardConfig]. */
internal data class PreparedAdapter(val spec: FileSpec, val proguardConfig: ProguardConfig?) internal data class PreparedAdapter(val spec: FileSpec, val proguardConfig: ProguardConfig?)
private fun AsmType.toCanonicalString(): String { private fun AsmType.toReflectionString(): String {
return when (this) { return when (this) {
AsmType.VOID_TYPE -> "void" AsmType.VOID_TYPE -> "void"
AsmType.BOOLEAN_TYPE -> "boolean" AsmType.BOOLEAN_TYPE -> "boolean"
@@ -580,7 +580,7 @@ private fun AsmType.toCanonicalString(): String {
AsmType.LONG_TYPE -> "long" AsmType.LONG_TYPE -> "long"
AsmType.DOUBLE_TYPE -> "double" AsmType.DOUBLE_TYPE -> "double"
else -> when (sort) { else -> when (sort) {
AsmType.ARRAY -> "${elementType.toCanonicalString()}[]" AsmType.ARRAY -> "${elementType.toReflectionString()}[]"
// Object type // Object type
else -> className else -> className
} }

View File

@@ -46,7 +46,7 @@ internal data class ProguardConfig(
// private final {adapter fields} // private final {adapter fields}
// } // }
// //
val targetName = targetClass.canonicalName val targetName = targetClass.reflectionName()
val adapterCanonicalName = ClassName(targetClass.packageName, adapterName).canonicalName val adapterCanonicalName = ClassName(targetClass.packageName, adapterName).canonicalName
// Keep the class name for Moshi's reflective lookup based on it // Keep the class name for Moshi's reflective lookup based on it
appendln("-if class $targetName") appendln("-if class $targetName")
@@ -65,7 +65,7 @@ internal data class ProguardConfig(
qualifierProperties.asSequence() qualifierProperties.asSequence()
.flatMap { it.qualifiers.asSequence() } .flatMap { it.qualifiers.asSequence() }
.map(ClassName::canonicalName) .map(ClassName::reflectionName)
.sorted() .sorted()
.forEach { qualifier -> .forEach { qualifier ->
appendln("-if class $targetName") appendln("-if class $targetName")
@@ -83,7 +83,7 @@ internal data class ProguardConfig(
appendln("-if class $targetName") appendln("-if class $targetName")
appendln("-keepnames class kotlin.jvm.internal.DefaultConstructorMarker") appendln("-keepnames class kotlin.jvm.internal.DefaultConstructorMarker")
appendln("-if class $targetName") appendln("-if class $targetName")
appendln("-keepclassmembers class ${targetClass.canonicalName} {") appendln("-keepclassmembers class $targetName {")
val allParams = targetConstructorParams.toMutableList() val allParams = targetConstructorParams.toMutableList()
val maskCount = if (targetConstructorParams.isEmpty()) { val maskCount = if (targetConstructorParams.isEmpty()) {
0 0

View File

@@ -432,6 +432,14 @@ class JsonClassCodegenProcessorTest {
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class Complex<T>(val firstName: FirstName = "", @MyQualifier val names: MutableList<String>, val genericProp: T) data class Complex<T>(val firstName: FirstName = "", @MyQualifier val names: MutableList<String>, val genericProp: T)
object NestedType {
@JsonQualifier
annotation class NestedQualifier
@JsonClass(generateAdapter = true)
data class NestedSimple(@NestedQualifier val firstName: String)
}
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
class MultipleMasks( class MultipleMasks(
@@ -506,101 +514,110 @@ class JsonClassCodegenProcessorTest {
)) ))
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
assertThat(result.generatedFiles.find { it.name == "moshi-testPackage.Aliases.pro" }).hasContent(""" result.generatedFiles.filter { it.extension == "pro" }.forEach { generatedFile ->
-if class testPackage.Aliases when (generatedFile.nameWithoutExtension) {
-keepnames class testPackage.Aliases "moshi-testPackage.Aliases" -> assertThat(generatedFile).hasContent("""
-if class testPackage.Aliases -if class testPackage.Aliases
-keep class testPackage.AliasesJsonAdapter { -keepnames class testPackage.Aliases
public <init>(com.squareup.moshi.Moshi); -if class testPackage.Aliases
-keep class testPackage.AliasesJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent())
"moshi-testPackage.Simple" -> assertThat(generatedFile).hasContent("""
-if class testPackage.Simple
-keepnames class testPackage.Simple
-if class testPackage.Simple
-keep class testPackage.SimpleJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent())
"moshi-testPackage.Generic" -> assertThat(generatedFile).hasContent("""
-if class testPackage.Generic
-keepnames class testPackage.Generic
-if class testPackage.Generic
-keep class testPackage.GenericJsonAdapter {
public <init>(com.squareup.moshi.Moshi,java.lang.reflect.Type[]);
}
""".trimIndent())
"moshi-testPackage.UsingQualifiers" -> assertThat(generatedFile).hasContent("""
-if class testPackage.UsingQualifiers
-keepnames class testPackage.UsingQualifiers
-if class testPackage.UsingQualifiers
-keep class testPackage.UsingQualifiersJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
private com.squareup.moshi.JsonAdapter stringAtMyQualifierAdapter;
}
-if class testPackage.UsingQualifiers
-keep @interface testPackage.MyQualifier
""".trimIndent())
"moshi-testPackage.MixedTypes" -> assertThat(generatedFile).hasContent("""
-if class testPackage.MixedTypes
-keepnames class testPackage.MixedTypes
-if class testPackage.MixedTypes
-keep class testPackage.MixedTypesJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent())
"moshi-testPackage.DefaultParams" -> assertThat(generatedFile).hasContent("""
-if class testPackage.DefaultParams
-keepnames class testPackage.DefaultParams
-if class testPackage.DefaultParams
-keep class testPackage.DefaultParamsJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
-if class testPackage.DefaultParams
-keepnames class kotlin.jvm.internal.DefaultConstructorMarker
-if class testPackage.DefaultParams
-keepclassmembers class testPackage.DefaultParams {
public synthetic <init>(java.lang.String,int,kotlin.jvm.internal.DefaultConstructorMarker);
}
""".trimIndent())
"moshi-testPackage.Complex" -> assertThat(generatedFile).hasContent("""
-if class testPackage.Complex
-keepnames class testPackage.Complex
-if class testPackage.Complex
-keep class testPackage.ComplexJsonAdapter {
public <init>(com.squareup.moshi.Moshi,java.lang.reflect.Type[]);
private com.squareup.moshi.JsonAdapter mutableListOfStringAtMyQualifierAdapter;
}
-if class testPackage.Complex
-keep @interface testPackage.MyQualifier
-if class testPackage.Complex
-keepnames class kotlin.jvm.internal.DefaultConstructorMarker
-if class testPackage.Complex
-keepclassmembers class testPackage.Complex {
public synthetic <init>(java.lang.String,java.util.List,java.lang.Object,int,kotlin.jvm.internal.DefaultConstructorMarker);
}
""".trimIndent())
"moshi-testPackage.MultipleMasks" -> assertThat(generatedFile).hasContent("""
-if class testPackage.MultipleMasks
-keepnames class testPackage.MultipleMasks
-if class testPackage.MultipleMasks
-keep class testPackage.MultipleMasksJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
-if class testPackage.MultipleMasks
-keepnames class kotlin.jvm.internal.DefaultConstructorMarker
-if class testPackage.MultipleMasks
-keepclassmembers class testPackage.MultipleMasks {
public synthetic <init>(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,int,int,int,kotlin.jvm.internal.DefaultConstructorMarker);
}
""".trimIndent())
"moshi-testPackage.NestedType.NestedSimple" -> assertThat(generatedFile).hasContent("""
-if class testPackage.NestedType${'$'}NestedSimple
-keepnames class testPackage.NestedType${'$'}NestedSimple
-if class testPackage.NestedType${'$'}NestedSimple
-keep class testPackage.NestedType_NestedSimpleJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
private com.squareup.moshi.JsonAdapter stringAtNestedQualifierAdapter;
}
-if class testPackage.NestedType${'$'}NestedSimple
-keep @interface testPackage.NestedType${'$'}NestedQualifier
""".trimIndent())
else -> error("Unexpected proguard file! ${generatedFile.name}")
} }
""".trimIndent()) }
assertThat(result.generatedFiles.find { it.name == "moshi-testPackage.Simple.pro" }).hasContent("""
-if class testPackage.Simple
-keepnames class testPackage.Simple
-if class testPackage.Simple
-keep class testPackage.SimpleJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent())
assertThat(result.generatedFiles.find { it.name == "moshi-testPackage.Generic.pro" }).hasContent("""
-if class testPackage.Generic
-keepnames class testPackage.Generic
-if class testPackage.Generic
-keep class testPackage.GenericJsonAdapter {
public <init>(com.squareup.moshi.Moshi,java.lang.reflect.Type[]);
}
""".trimIndent())
assertThat(result.generatedFiles.find { it.name == "moshi-testPackage.UsingQualifiers.pro" }).hasContent("""
-if class testPackage.UsingQualifiers
-keepnames class testPackage.UsingQualifiers
-if class testPackage.UsingQualifiers
-keep class testPackage.UsingQualifiersJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
private com.squareup.moshi.JsonAdapter stringAtMyQualifierAdapter;
}
-if class testPackage.UsingQualifiers
-keep @interface testPackage.MyQualifier
""".trimIndent())
assertThat(result.generatedFiles.find { it.name == "moshi-testPackage.MixedTypes.pro" }).hasContent("""
-if class testPackage.MixedTypes
-keepnames class testPackage.MixedTypes
-if class testPackage.MixedTypes
-keep class testPackage.MixedTypesJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent())
assertThat(result.generatedFiles.find { it.name == "moshi-testPackage.DefaultParams.pro" }).hasContent("""
-if class testPackage.DefaultParams
-keepnames class testPackage.DefaultParams
-if class testPackage.DefaultParams
-keep class testPackage.DefaultParamsJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
-if class testPackage.DefaultParams
-keepnames class kotlin.jvm.internal.DefaultConstructorMarker
-if class testPackage.DefaultParams
-keepclassmembers class testPackage.DefaultParams {
public synthetic <init>(java.lang.String,int,kotlin.jvm.internal.DefaultConstructorMarker);
}
""".trimIndent())
assertThat(result.generatedFiles.find { it.name == "moshi-testPackage.Complex.pro" }).hasContent("""
-if class testPackage.Complex
-keepnames class testPackage.Complex
-if class testPackage.Complex
-keep class testPackage.ComplexJsonAdapter {
public <init>(com.squareup.moshi.Moshi,java.lang.reflect.Type[]);
private com.squareup.moshi.JsonAdapter mutableListOfStringAtMyQualifierAdapter;
}
-if class testPackage.Complex
-keep @interface testPackage.MyQualifier
-if class testPackage.Complex
-keepnames class kotlin.jvm.internal.DefaultConstructorMarker
-if class testPackage.Complex
-keepclassmembers class testPackage.Complex {
public synthetic <init>(java.lang.String,java.util.List,java.lang.Object,int,kotlin.jvm.internal.DefaultConstructorMarker);
}
""".trimIndent())
assertThat(result.generatedFiles.find { it.name == "moshi-testPackage.MultipleMasks.pro" }).hasContent("""
-if class testPackage.MultipleMasks
-keepnames class testPackage.MultipleMasks
-if class testPackage.MultipleMasks
-keep class testPackage.MultipleMasksJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
-if class testPackage.MultipleMasks
-keepnames class kotlin.jvm.internal.DefaultConstructorMarker
-if class testPackage.MultipleMasks
-keepclassmembers class testPackage.MultipleMasks {
public synthetic <init>(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,int,int,int,kotlin.jvm.internal.DefaultConstructorMarker);
}
""".trimIndent())
} }
private fun prepareCompilation(vararg sourceFiles: SourceFile): KotlinCompilation { private fun prepareCompilation(vararg sourceFiles: SourceFile): KotlinCompilation {