Upgrade to Kotlin 1.6 + always instantiate annotations (#1425)

This commit is contained in:
Zac Sweers
2021-11-17 12:46:47 -05:00
committed by GitHub
parent 9440e5c7d0
commit 73553286fb
15 changed files with 96 additions and 383 deletions

View File

@@ -10,19 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
kotlin-version: [ '1.5.31', '1.6.0-RC' ]
# TODO add back KSP 1.6.0-1.0.1 once it's out
ksp-version: [ '1.5.31-1.0.1' ]
kotlin-test-mode: [ 'REFLECT', 'KSP', 'KAPT' ]
exclude:
# - kotlin-version: '1.5.31'
# ksp-version: '1.6.0-RC-1.0.1-RC'
- kotlin-version: '1.6.0-RC'
ksp-version: '1.5.31-1.0.1'
env:
MOSHI_KOTLIN_VERSION: '${{ matrix.kotlin-version }}'
MOSHI_KSP_VERSION: '${{ matrix.ksp-version }}'
steps:
- name: Checkout
@@ -48,10 +36,10 @@ jobs:
java-version: '17'
- name: Test
run: ./gradlew build check --stacktrace -PkotlinTestMode=${{ matrix.kotlin-test-mode }} -PkotlinVersion=${{ matrix.kotlin-version }}
run: ./gradlew build check --stacktrace -PkotlinTestMode=${{ matrix.kotlin-test-mode }}
- name: Publish (default branch only)
if: github.repository == 'square/moshi' && github.ref == 'refs/heads/master' && matrix.kotlin-version == '1.5.31' && matrix.kotlin-test-mode == 'reflect'
if: github.repository == 'square/moshi' && github.ref == 'refs/heads/master' && matrix.kotlin-test-mode == 'reflect'
run: ./gradlew publish
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: '${{ secrets.SONATYPE_NEXUS_USERNAME }}'

View File

@@ -14,34 +14,15 @@
# limitations under the License.
#
# For Dokka https://github.com/Kotlin/dokka/issues/1405
# Memory for Dokka https://github.com/Kotlin/dokka/issues/1405
# --add-opens for GJF https://github.com/google/google-java-format#jdk-16
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 \
--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
kotlin.daemon.jvmargs=-Dfile.encoding=UTF-8 \
--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
# Kapt doesn't read the above jvm args when workers are used
# https://youtrack.jetbrains.com/issue/KT-48402
kapt.use.worker.api=false
kapt.include.compile.classpath=false
GROUP=com.squareup.moshi

View File

@@ -16,14 +16,14 @@
autoService = "1.0"
gjf = "1.11.0"
jvmTarget = "1.8"
kotlin = "1.5.31"
kotlin = "1.6.0"
kotlinCompileTesting = "1.4.4"
kotlinpoet = "1.10.2"
ksp = "1.5.31-1.0.1"
ksp = "1.6.0-1.0.1"
ktlint = "0.41.0"
[plugins]
dokka = { id = "org.jetbrains.dokka", version = "1.5.30" }
dokka = { id = "org.jetbrains.dokka", version = "1.5.31" }
japicmp = { id = "me.champeau.gradle.japicmp", version = "0.2.9" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.17.0" }

View File

@@ -37,6 +37,7 @@ tasks.withType<KotlinCompile>().configureEach {
}
}
// --add-opens for kapt to work. KGP covers this for us but local JVMs in tests do not
tasks.withType<Test>().configureEach {
jvmArgs(
"--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",

View File

@@ -186,32 +186,14 @@ public class AdapterGenerator(
result.addAnnotation(COMMON_SUPPRESS)
result.addType(generatedAdapter)
val proguardConfig = if (generateProguardRules) {
generatedAdapter.createProguardRule(target.instantiateAnnotations)
generatedAdapter.createProguardRule()
} else {
null
}
return PreparedAdapter(result.build(), proguardConfig)
}
private fun TypeSpec.createProguardRule(instantiateAnnotations: Boolean): ProguardConfig {
val adapterProperties = if (instantiateAnnotations) {
// Don't need to do anything special if we instantiate them directly!
emptySet()
} else {
propertySpecs
.asSequence()
.filter { prop ->
prop.type.rawType() == JsonAdapter::class.asClassName()
}
.filter { prop -> prop.annotations.isNotEmpty() }
.mapTo(mutableSetOf()) { prop ->
QualifierAdapterProperty(
name = prop.name,
qualifiers = prop.annotations.mapTo(mutableSetOf()) { it.typeName.rawType() }
)
}
}
private fun TypeSpec.createProguardRule(): ProguardConfig {
val adapterConstructorParams = when (requireNotNull(primaryConstructor).parameters.size) {
1 -> listOf(CN_MOSHI.reflectionName())
2 -> listOf(CN_MOSHI.reflectionName(), "${CN_TYPE.reflectionName()}[]")
@@ -237,7 +219,6 @@ public class AdapterGenerator(
adapterConstructorParams = adapterConstructorParams,
targetConstructorHasDefaults = hasDefaultProperties,
targetConstructorParams = parameterTypes,
qualifierProperties = adapterProperties
)
}

View File

@@ -29,10 +29,8 @@ import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.TypeVariableName
import com.squareup.kotlinpoet.WildcardTypeName
import com.squareup.kotlinpoet.asClassName
import com.squareup.kotlinpoet.asTypeName
import com.squareup.kotlinpoet.joinToCode
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Types
import java.util.Locale
/** A JsonAdapter that can be used to encode and decode a particular field. */
@@ -40,7 +38,6 @@ import java.util.Locale
public data class DelegateKey(
private val type: TypeName,
private val jsonQualifiers: List<AnnotationSpec>,
private val instantiateAnnotations: Boolean
) {
public val nullable: Boolean get() = type.isNullable
@@ -67,22 +64,13 @@ public data class DelegateKey(
val (initializerString, args) = when {
jsonQualifiers.isEmpty() -> ", %M()" to arrayOf(MemberName("kotlin.collections", "emptySet"))
instantiateAnnotations -> {
", setOf(%L)" to arrayOf(jsonQualifiers.map { it.asInstantiationExpression() }.joinToCode())
}
else -> {
", %T.getFieldJsonQualifierAnnotations(javaClass, " +
"%S)" to arrayOf(Types::class.asTypeName(), adapterName)
", setOf(%L)" to arrayOf(jsonQualifiers.map { it.asInstantiationExpression() }.joinToCode())
}
}
val finalArgs = arrayOf(*standardArgs, *args, propertyName)
return PropertySpec.builder(adapterName, adapterTypeName, KModifier.PRIVATE)
.apply {
if (!instantiateAnnotations) {
addAnnotations(jsonQualifiers)
}
}
.initializer("%N.adapter(%L$initializerString, %S)", *finalArgs)
.build()
}

View File

@@ -39,7 +39,6 @@ public data class ProguardConfig(
val adapterConstructorParams: List<String>,
val targetConstructorHasDefaults: Boolean,
val targetConstructorParams: List<String>,
val qualifierProperties: Set<QualifierAdapterProperty>
) {
public fun outputFilePathWithoutExtension(canonicalName: String): String {
return "META-INF/proguard/moshi-$canonicalName"
@@ -66,21 +65,8 @@ public data class ProguardConfig(
// Keep the constructor for Moshi's reflective lookup
val constructorArgs = adapterConstructorParams.joinToString(",")
appendLine(" public <init>($constructorArgs);")
// Keep any qualifier properties
for (qualifierProperty in qualifierProperties) {
appendLine(" private com.squareup.moshi.JsonAdapter ${qualifierProperty.name};")
}
appendLine("}")
qualifierProperties.asSequence()
.flatMap { it.qualifiers.asSequence() }
.map(ClassName::reflectionName)
.sorted()
.forEach { qualifier ->
appendLine("-if class $targetName")
appendLine("-keep @interface $qualifier")
}
if (targetConstructorHasDefaults) {
// If the target class has default parameter values, keep its synthetic constructor
//

View File

@@ -28,7 +28,6 @@ public data class TargetType(
val typeVariables: List<TypeVariableName>,
val isDataClass: Boolean,
val visibility: KModifier,
val instantiateAnnotations: Boolean
) {
init {

View File

@@ -144,12 +144,11 @@ public class JsonClassCodegenProcessor : AbstractProcessor() {
types,
element,
cachedClassInspector,
instantiateAnnotations
) ?: return null
val properties = mutableMapOf<String, PropertyGenerator>()
for (property in type.properties.values) {
val generator = property.generator(messager, element, elements, type.instantiateAnnotations)
val generator = property.generator(messager, element, elements)
if (generator != null) {
properties[property.name] = generator
}

View File

@@ -47,10 +47,8 @@ import com.squareup.moshi.kotlin.codegen.api.rawType
import com.squareup.moshi.kotlin.codegen.api.unwrapTypeAlias
import kotlinx.metadata.KmConstructor
import kotlinx.metadata.jvm.signature
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
import javax.annotation.processing.Messager
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
@@ -72,7 +70,6 @@ private val VISIBILITY_MODIFIERS = setOf(
KModifier.PROTECTED,
KModifier.PUBLIC
)
private val ANNOTATION_INSTANTIATION_MIN_VERSION = KotlinVersion(1, 6, 0)
private fun Collection<KModifier>.visibility(): KModifier {
return find { it in VISIBILITY_MODIFIERS } ?: KModifier.PUBLIC
@@ -126,7 +123,6 @@ internal fun targetType(
types: Types,
element: TypeElement,
cachedClassInspector: MoshiCachedClassInspector,
instantiateAnnotationsEnabled: Boolean
): TargetType? {
val typeMetadata = element.getAnnotation(Metadata::class.java)
if (typeMetadata == null) {
@@ -208,11 +204,6 @@ internal fun targetType(
}
}
val instantiateAnnotations = instantiateAnnotationsEnabled && run {
val (major, minor, patch) = typeMetadata.metadataVersion
val languageVersion = KotlinVersion(major, minor, patch)
languageVersion >= ANNOTATION_INSTANTIATION_MIN_VERSION
}
val kotlinApi = cachedClassInspector.toTypeSpec(kmClass)
val typeVariables = kotlinApi.typeVariables
val appliedType = AppliedType.get(element)
@@ -329,7 +320,6 @@ internal fun targetType(
typeVariables = typeVariables,
isDataClass = KModifier.DATA in kotlinApi.modifiers,
visibility = resolvedVisibility,
instantiateAnnotations = instantiateAnnotations
)
}
@@ -431,7 +421,6 @@ internal fun TargetProperty.generator(
messager: Messager,
sourceElement: TypeElement,
elements: Elements,
instantiateAnnotations: Boolean
): PropertyGenerator? {
if (jsonIgnore) {
if (!hasDefault) {
@@ -442,7 +431,7 @@ internal fun TargetProperty.generator(
)
return null
}
return PropertyGenerator(this, DelegateKey(type, emptyList(), instantiateAnnotations), true)
return PropertyGenerator(this, DelegateKey(type, emptyList()), true)
}
if (!isVisible) {
@@ -474,16 +463,6 @@ internal fun TargetProperty.generator(
)
}
}
if (!instantiateAnnotations) {
annotationElement.getAnnotation(Target::class.java)?.let {
if (ElementType.FIELD !in it.value) {
messager.printMessage(
ERROR,
"JsonQualifier @${qualifierRawType.simpleName} must support FIELD target"
)
}
}
}
}
val jsonQualifierSpecs = qualifiers.map {
@@ -494,7 +473,7 @@ internal fun TargetProperty.generator(
return PropertyGenerator(
this,
DelegateKey(type, jsonQualifierSpecs, instantiateAnnotations)
DelegateKey(type, jsonQualifierSpecs)
)
}

View File

@@ -34,7 +34,6 @@ import com.squareup.moshi.JsonClass
import com.squareup.moshi.kotlin.codegen.api.AdapterGenerator
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATED
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATE_PROGUARD_RULES
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_INSTANTIATE_ANNOTATIONS
import com.squareup.moshi.kotlin.codegen.api.Options.POSSIBLE_GENERATED_NAMES
import com.squareup.moshi.kotlin.codegen.api.ProguardConfig
import com.squareup.moshi.kotlin.codegen.api.PropertyGenerator
@@ -64,8 +63,6 @@ private class JsonClassSymbolProcessor(
}
}
private val generateProguardRules = environment.options[OPTION_GENERATE_PROGUARD_RULES]?.toBooleanStrictOrNull() ?: true
private val instantiateAnnotations = (environment.options[OPTION_INSTANTIATE_ANNOTATIONS]?.toBooleanStrictOrNull() ?: true) &&
environment.kotlinVersion.isAtLeast(1, 6)
override fun process(resolver: Resolver): List<KSAnnotated> {
val generatedAnnotation = generatedOption?.let {
@@ -125,11 +122,11 @@ private class JsonClassSymbolProcessor(
resolver: Resolver,
originalType: KSDeclaration,
): AdapterGenerator? {
val type = targetType(originalType, resolver, logger, instantiateAnnotations) ?: return null
val type = targetType(originalType, resolver, logger) ?: return null
val properties = mutableMapOf<String, PropertyGenerator>()
for (property in type.properties.values) {
val generator = property.generator(logger, resolver, originalType, type.instantiateAnnotations)
val generator = property.generator(logger, resolver, originalType)
if (generator != null) {
properties[property.name] = generator
}

View File

@@ -43,7 +43,6 @@ internal fun TargetProperty.generator(
logger: KSPLogger,
resolver: Resolver,
originalType: KSDeclaration,
instantiateAnnotations: Boolean
): PropertyGenerator? {
if (jsonIgnore) {
if (!hasDefault) {
@@ -53,7 +52,7 @@ internal fun TargetProperty.generator(
)
return null
}
return PropertyGenerator(this, DelegateKey(type, emptyList(), instantiateAnnotations), true)
return PropertyGenerator(this, DelegateKey(type, emptyList()), true)
}
if (!isVisible) {
@@ -81,15 +80,6 @@ internal fun TargetProperty.generator(
)
}
}
if (!instantiateAnnotations) {
annotationElement.findAnnotationWithType<Target>()?.let {
if (AnnotationTarget.FIELD !in it.allowedTargets) {
logger.error(
"JsonQualifier @${qualifierRawType.simpleName} must support FIELD target"
)
}
}
}
}
}
@@ -101,7 +91,7 @@ internal fun TargetProperty.generator(
return PropertyGenerator(
this,
DelegateKey(type, jsonQualifierSpecs, instantiateAnnotations)
DelegateKey(type, jsonQualifierSpecs)
)
}

View File

@@ -58,7 +58,6 @@ internal fun targetType(
type: KSDeclaration,
resolver: Resolver,
logger: KSPLogger,
instantiateAnnotations: Boolean
): TargetType? {
if (type !is KSClassDeclaration) {
logger.error("@JsonClass can't be applied to ${type.qualifiedName?.asString()}: must be a Kotlin class", type)
@@ -154,7 +153,6 @@ internal fun targetType(
typeVariables = typeVariables,
isDataClass = Modifier.DATA in type.modifiers,
visibility = resolvedVisibility,
instantiateAnnotations = instantiateAnnotations
)
}

View File

@@ -20,7 +20,6 @@ import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATED
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATE_PROGUARD_RULES
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_INSTANTIATE_ANNOTATIONS
import com.tschuchort.compiletesting.KotlinCompilation
import com.tschuchort.compiletesting.SourceFile
import com.tschuchort.compiletesting.SourceFile.Companion.kotlin
@@ -28,8 +27,6 @@ import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import kotlin.reflect.KClass
import kotlin.reflect.KClassifier
import kotlin.reflect.KType
@@ -40,23 +37,7 @@ import kotlin.reflect.full.createType
import kotlin.reflect.full.declaredMemberProperties
/** Execute kotlinc to confirm that either files are generated or errors are printed. */
@RunWith(Parameterized::class)
class JsonClassCodegenProcessorTest(
private val languageVersion: String,
private val instantiateAnnotations: Boolean
) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "languageVersion={0},instantiateAnnotations={1}")
fun data(): Collection<Array<Any>> {
return listOf(
arrayOf("1.5", true),
arrayOf("1.6", true),
arrayOf("1.6", false)
)
}
}
class JsonClassCodegenProcessorTest {
@Rule @JvmField var temporaryFolder: TemporaryFolder = TemporaryFolder()
@@ -494,13 +475,8 @@ class JsonClassCodegenProcessorTest(
"""
)
)
if (languageVersion == "1.5" || !instantiateAnnotations) {
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
assertThat(result.messages).contains("JsonQualifier @UpperCase must support FIELD target")
} else {
// We instantiate directly!
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
}
// We instantiate directly so doesn't need to be FIELD
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
}
@Test
@@ -710,32 +686,16 @@ class JsonClassCodegenProcessorTest(
""".trimIndent()
)
"moshi-testPackage.UsingQualifiers" -> {
if (languageVersion == "1.5" || !instantiateAnnotations) {
assertThat(generatedFile.readText()).contains(
"""
-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()
)
} else {
assertThat(generatedFile.readText()).contains(
"""
-if class testPackage.UsingQualifiers
-keepnames class testPackage.UsingQualifiers
-if class testPackage.UsingQualifiers
-keep class testPackage.UsingQualifiersJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent()
)
}
assertThat(generatedFile.readText()).contains(
"""
-if class testPackage.UsingQualifiers
-keepnames class testPackage.UsingQualifiers
-if class testPackage.UsingQualifiers
-keep class testPackage.UsingQualifiersJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent()
)
}
"moshi-testPackage.MixedTypes" -> assertThat(generatedFile.readText()).contains(
"""
@@ -764,44 +724,22 @@ class JsonClassCodegenProcessorTest(
""".trimIndent()
)
"moshi-testPackage.Complex" -> {
if (languageVersion == "1.5" || !instantiateAnnotations) {
assertThat(generatedFile.readText()).contains(
"""
-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()
)
} else {
assertThat(generatedFile.readText()).contains(
"""
-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[]);
}
-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(generatedFile.readText()).contains(
"""
-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[]);
}
-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.readText()).contains(
"""
@@ -820,32 +758,16 @@ class JsonClassCodegenProcessorTest(
""".trimIndent()
)
"moshi-testPackage.NestedType.NestedSimple" -> {
if (languageVersion == "1.5" || !instantiateAnnotations) {
assertThat(generatedFile.readText()).contains(
"""
-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 {
assertThat(generatedFile.readText()).contains(
"""
-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);
}
""".trimIndent()
)
}
assertThat(generatedFile.readText()).contains(
"""
-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);
}
""".trimIndent()
)
}
else -> error("Unexpected proguard file! ${generatedFile.name}")
}
@@ -860,8 +782,6 @@ class JsonClassCodegenProcessorTest(
inheritClassPath = true
sources = sourceFiles.asList()
verbose = false
kotlincArguments = listOf("-language-version", languageVersion)
kaptArgs[OPTION_INSTANTIATE_ANNOTATIONS] = "$instantiateAnnotations"
}
}

View File

@@ -16,7 +16,6 @@
package com.squareup.moshi.kotlin.codegen.ksp
import com.google.common.truth.Truth.assertThat
import com.squareup.moshi.kotlin.codegen.api.Options
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATED
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATE_PROGUARD_RULES
import com.tschuchort.compiletesting.KotlinCompilation
@@ -31,41 +30,9 @@ import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
/** Execute kotlinc to confirm that either files are generated or errors are printed. */
@RunWith(Parameterized::class)
class JsonClassSymbolProcessorTest(
private val languageVersion: String,
private val instantiateAnnotations: Boolean
) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "languageVersion={0},instantiateAnnotations={1}")
fun data(): Collection<Array<Any>> {
// TODO KSP doesn't recognize language version yet https://github.com/google/ksp/issues/611
// toe-holds for the future
val runtimeVersion = KotlinVersion.CURRENT
return mutableListOf<Array<Any>>().apply {
if (runtimeVersion.major != 1 || runtimeVersion.minor != 6) {
// True by default but still 1.5
// Can't test when running with 1.6 because lang version is still 1.6 per above comment
add(arrayOf("1.5", true))
}
// Redundant case, set to false but still 1.5
add(arrayOf("1.5", false))
if (runtimeVersion.major != 1 || runtimeVersion.minor != 5) {
// Happy case - 1.6 and true by default
// Can't test when running with 1.5 because lang version is still 1.5 per above comment
add(arrayOf("1.6", true))
}
// 1.6 but explicitly disabled
add(arrayOf("1.6", false))
}
}
}
class JsonClassSymbolProcessorTest {
@Rule @JvmField var temporaryFolder: TemporaryFolder = TemporaryFolder()
@@ -538,13 +505,8 @@ class JsonClassSymbolProcessorTest(
"""
)
)
if (languageVersion == "1.5" || !instantiateAnnotations) {
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
assertThat(result.messages).contains("JsonQualifier @UpperCase must support FIELD target")
} else {
// We instantiate directly!
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
}
// We instantiate directly, no FIELD site target necessary
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
}
@Test
@@ -758,32 +720,16 @@ class JsonClassSymbolProcessorTest(
""".trimIndent()
)
"moshi-testPackage.UsingQualifiers" -> {
if (languageVersion == "1.5" || !instantiateAnnotations) {
assertThat(generatedFile.readText()).contains(
"""
-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()
)
} else {
assertThat(generatedFile.readText()).contains(
"""
-if class testPackage.UsingQualifiers
-keepnames class testPackage.UsingQualifiers
-if class testPackage.UsingQualifiers
-keep class testPackage.UsingQualifiersJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent()
)
}
assertThat(generatedFile.readText()).contains(
"""
-if class testPackage.UsingQualifiers
-keepnames class testPackage.UsingQualifiers
-if class testPackage.UsingQualifiers
-keep class testPackage.UsingQualifiersJsonAdapter {
public <init>(com.squareup.moshi.Moshi);
}
""".trimIndent()
)
}
"moshi-testPackage.MixedTypes" -> assertThat(generatedFile.readText()).contains(
"""
@@ -812,44 +758,22 @@ class JsonClassSymbolProcessorTest(
""".trimIndent()
)
"moshi-testPackage.Complex" -> {
if (languageVersion == "1.5" || !instantiateAnnotations) {
assertThat(generatedFile.readText()).contains(
"""
-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()
)
} else {
assertThat(generatedFile.readText()).contains(
"""
-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[]);
}
-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(generatedFile.readText()).contains(
"""
-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[]);
}
-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.readText()).contains(
"""
@@ -868,32 +792,16 @@ class JsonClassSymbolProcessorTest(
""".trimIndent()
)
"moshi-testPackage.NestedType.NestedSimple" -> {
if (languageVersion == "1.5" || !instantiateAnnotations) {
assertThat(generatedFile.readText()).contains(
"""
-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 {
assertThat(generatedFile.readText()).contains(
"""
-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);
}
""".trimIndent()
)
}
assertThat(generatedFile.readText()).contains(
"""
-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);
}
""".trimIndent()
)
}
else -> error("Unexpected proguard file! ${generatedFile.name}")
}
@@ -909,8 +817,6 @@ class JsonClassSymbolProcessorTest(
sources = sourceFiles.asList()
verbose = false
kspIncremental = true // The default now
kotlincArguments = listOf("-language-version", languageVersion)
kspArgs[Options.OPTION_INSTANTIATE_ANNOTATIONS] = "$instantiateAnnotations"
}
}