From 313683fa980bf2a7e21b084bba712b331b84b1a7 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 25 Oct 2021 11:00:56 -0400 Subject: [PATCH] Parameterize kotlin test infra on CI (#1407) --- .github/workflows/build.yml | 8 +- .../moshi/kotlin/reflect/KotlinJsonAdapter.kt | 29 ++++- kotlin/tests/build.gradle.kts | 40 ++++-- kotlin/tests/codegen-only/build.gradle.kts | 87 +++++++++++++ .../moshi/kotlin/codegen/CompileOnlyTests.kt | 119 ++++++++++++++++++ .../codegen/ComplexGenericsInheritanceTest.kt | 0 .../kotlin/codegen}/DefaultConstructorTest.kt | 10 +- .../kotlin/codegen/GeneratedAdaptersTest.kt | 92 -------------- ...ersTest_CustomGeneratedClassJsonAdapter.kt | 0 .../ClassInPackageThatLooksLikeAClass.kt | 0 .../kotlin/codegen/MixingReflectAndCodeGen.kt | 48 +++++++ .../moshi/kotlin/codegen/MoshiKspTest.kt | 0 .../moshi/kotlin/codegen/MultipleMasksTest.kt | 0 .../UppercaseInAnnotationPackage.kt | 0 .../squareup/moshi/kotlin/DualKotlinTest.kt | 55 ++------ .../kotlin/reflect/KotlinJsonAdapterTest.kt | 22 ---- settings.gradle.kts | 1 + 17 files changed, 328 insertions(+), 183 deletions(-) create mode 100644 kotlin/tests/codegen-only/build.gradle.kts create mode 100644 kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/CompileOnlyTests.kt rename kotlin/tests/{ => codegen-only}/src/test/kotlin/com/squareup/moshi/kotlin/codegen/ComplexGenericsInheritanceTest.kt (100%) rename kotlin/tests/{src/test/kotlin/com/squareup/moshi/kotlin => codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen}/DefaultConstructorTest.kt (90%) rename kotlin/tests/{ => codegen-only}/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt (93%) rename kotlin/tests/{ => codegen-only}/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter.kt (100%) rename kotlin/tests/{ => codegen-only}/src/test/kotlin/com/squareup/moshi/kotlin/codegen/LooksLikeAClass/ClassInPackageThatLooksLikeAClass.kt (100%) create mode 100644 kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MixingReflectAndCodeGen.kt rename kotlin/tests/{ => codegen-only}/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MoshiKspTest.kt (100%) rename kotlin/tests/{ => codegen-only}/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MultipleMasksTest.kt (100%) rename kotlin/tests/{ => codegen-only}/src/test/kotlin/com/squareup/moshi/kotlin/codegen/annotation/UppercaseInAnnotationPackage.kt (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index afea037..745b810 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,15 +4,15 @@ on: [push, pull_request] jobs: build: - name: 'Java ${{ matrix.java-version }} | Kotlin ${{ matrix.kotlin-version }} | KSP ${{ matrix.use-ksp }}' + name: 'Kotlin ${{ matrix.kotlin-version }} | Test Mode ${{ matrix.kotlin-test-mode }}' runs-on: ubuntu-latest strategy: fail-fast: false matrix: - use-ksp: [ true, false ] kotlin-version: [ '1.5.31', '1.6.0-RC' ] ksp-version: [ '1.5.31-1.0.0', '1.6.0-RC-1.0.0' ] + kotlin-test-mode: [ 'REFLECT', 'KSP', 'KAPT' ] exclude: - kotlin-version: '1.5.31' ksp-version: '1.6.0-RC-1.0.0' @@ -47,10 +47,10 @@ jobs: java-version: '17' - name: Test - run: ./gradlew build check --stacktrace -PuseKsp=${{ matrix.use-ksp }} -PkotlinVersion=${{ matrix.kotlin-version }} + run: ./gradlew build check --stacktrace -PkotlinTestMode=${{ matrix.kotlin-test-mode }} -PkotlinVersion=${{ matrix.kotlin-version }} - name: Publish (default branch only) - if: github.repository == 'square/moshi' && github.ref == 'refs/heads/master' && matrix.kotlin-version == '1.5.31' && matrix.use-ksp == 'false' + if: github.repository == 'square/moshi' && github.ref == 'refs/heads/master' && matrix.kotlin-version == '1.5.31' && matrix.kotlin-test-mode == 'reflect' run: ./gradlew publish env: ORG_GRADLE_PROJECT_mavenCentralUsername: '${{ secrets.SONATYPE_NEXUS_USERNAME }}' diff --git a/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapter.kt b/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapter.kt index 0db237e..f4a01ac 100644 --- a/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapter.kt +++ b/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapter.kt @@ -21,16 +21,19 @@ import com.squareup.moshi.JsonDataException import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonWriter import com.squareup.moshi.Moshi +import com.squareup.moshi.Types import com.squareup.moshi.internal.Util import com.squareup.moshi.internal.Util.generatedAdapter import com.squareup.moshi.internal.Util.resolve import com.squareup.moshi.rawType import java.lang.reflect.Modifier import java.lang.reflect.Type +import kotlin.reflect.KClass import kotlin.reflect.KFunction import kotlin.reflect.KMutableProperty1 import kotlin.reflect.KParameter import kotlin.reflect.KProperty1 +import kotlin.reflect.KTypeParameter import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.memberProperties import kotlin.reflect.full.primaryConstructor @@ -257,7 +260,31 @@ public class KotlinJsonAdapterFactory : JsonAdapter.Factory { } val name = jsonAnnotation?.name ?: property.name - val resolvedPropertyType = resolve(type, rawType, property.returnType.javaType) + val propertyType = when (val propertyTypeClassifier = property.returnType.classifier) { + is KClass<*> -> { + if (propertyTypeClassifier.isValue) { + // When it's a value class, we need to resolve the type ourselves because the javaType + // function will return its inlined type + val rawClassifierType = propertyTypeClassifier.java + if (property.returnType.arguments.isEmpty()) { + rawClassifierType + } else { + Types.newParameterizedType( + rawClassifierType, + *property.returnType.arguments.mapNotNull { it.type?.javaType }.toTypedArray() + ) + } + } else { + // This is safe when it's not a value class! + property.returnType.javaType + } + } + is KTypeParameter -> { + property.returnType.javaType + } + else -> error("Not possible!") + } + val resolvedPropertyType = resolve(type, rawType, propertyType) val adapter = moshi.adapter( resolvedPropertyType, Util.jsonAnnotations(allAnnotations.toTypedArray()), diff --git a/kotlin/tests/build.gradle.kts b/kotlin/tests/build.gradle.kts index 4b808e2..e4e9fba 100644 --- a/kotlin/tests/build.gradle.kts +++ b/kotlin/tests/build.gradle.kts @@ -14,6 +14,9 @@ * limitations under the License. */ +import Build_gradle.TestMode.KAPT +import Build_gradle.TestMode.KSP +import Build_gradle.TestMode.REFLECT import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -22,11 +25,24 @@ plugins { id("com.google.devtools.ksp") apply false } -val useKsp = hasProperty("useKsp") -if (useKsp) { - apply(plugin = "com.google.devtools.ksp") -} else { - apply(plugin = "org.jetbrains.kotlin.kapt") +enum class TestMode { + REFLECT, KAPT, KSP +} + +val testMode = findProperty("kotlinTestMode")?.toString() + ?.let(TestMode::valueOf) + ?: REFLECT + +when (testMode) { + REFLECT -> { + // Do nothing! + } + KAPT -> { + apply(plugin = "org.jetbrains.kotlin.kapt") + } + KSP -> { + apply(plugin = "com.google.devtools.ksp") + } } tasks.withType().configureEach { @@ -48,10 +64,16 @@ tasks.withType().configureEach { } dependencies { - if (useKsp) { - "kspTest"(project(":kotlin:codegen")) - } else { - "kaptTest"(project(":kotlin:codegen")) + when (testMode) { + REFLECT -> { + // Do nothing + } + KAPT -> { + "kaptTest"(project(":kotlin:codegen")) + } + KSP -> { + "kspTest"(project(":kotlin:codegen")) + } } testImplementation(project(":moshi")) testImplementation(project(":kotlin:reflect")) diff --git a/kotlin/tests/codegen-only/build.gradle.kts b/kotlin/tests/codegen-only/build.gradle.kts new file mode 100644 index 0000000..7c5acb2 --- /dev/null +++ b/kotlin/tests/codegen-only/build.gradle.kts @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2021 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Build_gradle.TestMode.KAPT +import Build_gradle.TestMode.KSP +import Build_gradle.TestMode.REFLECT +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + kotlin("jvm") + kotlin("kapt") apply false + id("com.google.devtools.ksp") apply false +} + +enum class TestMode { + REFLECT, KAPT, KSP +} + +val testMode = findProperty("kotlinTestMode")?.toString() + ?.let(TestMode::valueOf) + ?: KSP + +when (testMode) { + REFLECT -> { + // Default to KSP. This is a CI-only thing + apply(plugin = "com.google.devtools.ksp") + } + KAPT -> { + apply(plugin = "org.jetbrains.kotlin.kapt") + } + KSP -> { + apply(plugin = "com.google.devtools.ksp") + } +} + +tasks.withType().configureEach { + // ExtendsPlatformClassWithProtectedField tests a case where we set a protected ByteArrayOutputStream.buf field + jvmArgs("--add-opens=java.base/java.io=ALL-UNNAMED") +} + +val useWError = findProperty("kotlinLanguageVersion")?.toString() + ?.startsWith("1.5") + ?: false +tasks.withType().configureEach { + kotlinOptions { + allWarningsAsErrors = useWError + @Suppress("SuspiciousCollectionReassignment") + freeCompilerArgs += listOf( + "-Xopt-in=kotlin.ExperimentalStdlibApi" + ) + } +} + +dependencies { + when (testMode) { + REFLECT -> { + // Default to KSP in this case, this is a CI-only thing + "kspTest"(project(":kotlin:codegen")) + } + KAPT -> { + "kaptTest"(project(":kotlin:codegen")) + } + KSP -> { + "kspTest"(project(":kotlin:codegen")) + } + } + testImplementation(project(":moshi")) + testImplementation(project(":kotlin:reflect")) + testImplementation(project(":kotlin:tests:extra-moshi-test-module")) + testImplementation(kotlin("reflect")) + testImplementation(libs.junit) + testImplementation(libs.assertj) + testImplementation(libs.truth) +} diff --git a/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/CompileOnlyTests.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/CompileOnlyTests.kt new file mode 100644 index 0000000..f231683 --- /dev/null +++ b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/CompileOnlyTests.kt @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2021 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.moshi.kotlin.codegen + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import kotlin.annotation.AnnotationTarget.TYPE + +/* + * These are classes that need only compile. + */ + +// Regression test for https://github.com/square/moshi/issues/905 +@JsonClass(generateAdapter = true) +data class GenericTestClassWithDefaults( + val input: String = "", + val genericInput: T +) + +@Target(TYPE) +annotation class TypeAnnotation + +/** + * Compilation-only test to ensure we don't render types with their annotations. + * Regression test for https://github.com/square/moshi/issues/1033 + */ +@JsonClass(generateAdapter = true) +data class TypeAnnotationClass( + val propertyWithAnnotatedType: @TypeAnnotation String = "", + val generic: List<@TypeAnnotation String> +) + +// Regression test for https://github.com/square/moshi/issues/1277 +@JsonClass(generateAdapter = true) +data class OtherTestModel(val TestModel: TestModel? = null) +@JsonClass(generateAdapter = true) +data class TestModel( + val someVariable: Int, + val anotherVariable: String +) + +// Regression test for https://github.com/square/moshi/issues/1022 +@JsonClass(generateAdapter = true) +internal data class MismatchParentAndNestedClassVisibility( + val type: Int, + val name: String? = null +) { + + @JsonClass(generateAdapter = true) + data class NestedClass( + val nestedProperty: String + ) +} + +// Regression test for https://github.com/square/moshi/issues/1052 +@JsonClass(generateAdapter = true) +data class KeysWithSpaces( + @Json(name = "1. Information") val information: String, + @Json(name = "2. Symbol") val symbol: String, + @Json(name = "3. Last Refreshed") val lastRefreshed: String, + @Json(name = "4. Interval") val interval: String, + @Json(name = "5. Output Size") val size: String, + @Json(name = "6. Time Zone") val timeZone: String +) + +// Regression test for https://github.com/square/moshi/issues/848 +@JsonClass(generateAdapter = true) +data class Hotwords( + val `class`: List? +) + +/** + * This is here mostly just to ensure it still compiles. Covers variance, @Json, default values, + * nullability, primitive arrays, and some wacky generics. + */ +@JsonClass(generateAdapter = true) +data class SmokeTestType( + @Json(name = "first_name") val firstName: String, + @Json(name = "last_name") val lastName: String, + val age: Int, + val nationalities: List = emptyList(), + val weight: Float, + val tattoos: Boolean = false, + val race: String?, + val hasChildren: Boolean = false, + val favoriteFood: String? = null, + val favoriteDrink: String? = "Water", + val wildcardOut: MutableList = mutableListOf(), + val nullableWildcardOut: MutableList = mutableListOf(), + val wildcardIn: Array, + val any: List<*>, + val anyTwo: List, + val anyOut: MutableList, + val nullableAnyOut: MutableList, + val favoriteThreeNumbers: IntArray, + val favoriteArrayValues: Array, + val favoriteNullableArrayValues: Array, + val nullableSetListMapArrayNullableIntWithDefault: Set>>>? = null, + val aliasedName: TypeAliasName = "Woah", + val genericAlias: GenericTypeAlias = listOf("Woah"), + // Regression test for https://github.com/square/moshi/issues/1272 + val nestedArray: Array>? = null +) + +typealias TypeAliasName = String +typealias GenericTypeAlias = List diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/ComplexGenericsInheritanceTest.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/ComplexGenericsInheritanceTest.kt similarity index 100% rename from kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/ComplexGenericsInheritanceTest.kt rename to kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/ComplexGenericsInheritanceTest.kt diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/DefaultConstructorTest.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/DefaultConstructorTest.kt similarity index 90% rename from kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/DefaultConstructorTest.kt rename to kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/DefaultConstructorTest.kt index 4b21e85..a211c7a 100644 --- a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/DefaultConstructorTest.kt +++ b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/DefaultConstructorTest.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.squareup.moshi.kotlin +package com.squareup.moshi.kotlin.codegen import com.squareup.moshi.JsonClass import com.squareup.moshi.Moshi @@ -66,14 +66,6 @@ data class TestClass( val dynamicInlineOptional: Int = createInlineInt() ) -// Regression test for https://github.com/square/moshi/issues/905 -// Just needs to compile -@JsonClass(generateAdapter = true) -data class GenericTestClassWithDefaults( - val input: String = "", - val genericInput: T -) - private fun createInt(): Int { return 3 } diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt similarity index 93% rename from kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt rename to kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt index 8d3d183..86a4bb2 100644 --- a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt +++ b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt @@ -36,7 +36,6 @@ import org.junit.Assert.fail import org.junit.Ignore import org.junit.Test import java.util.Locale -import kotlin.annotation.AnnotationTarget.TYPE import kotlin.properties.Delegates import kotlin.reflect.full.memberProperties @@ -1342,19 +1341,6 @@ class GeneratedAdaptersTest { @JsonClass(generateAdapter = true) data class DeprecatedProperty(@Deprecated("Deprecated for reasons") val foo: String) - @Target(TYPE) - annotation class TypeAnnotation - - /** - * Compilation-only test to ensure we don't render types with their annotations. - * Regression test for https://github.com/square/moshi/issues/1033 - */ - @JsonClass(generateAdapter = true) - data class TypeAnnotationClass( - val propertyWithAnnotatedType: @TypeAnnotation String = "", - val generic: List<@TypeAnnotation String> - ) - @Test fun typesSizeCheckMessages_noArgs() { try { // Note: This is impossible to do if you use the reified adapter extension! @@ -1401,42 +1387,6 @@ class GeneratedAdaptersTest { ) } -// Regression test for https://github.com/square/moshi/issues/1277 -// Compile-only test -@JsonClass(generateAdapter = true) -data class OtherTestModel(val TestModel: TestModel? = null) -@JsonClass(generateAdapter = true) -data class TestModel( - val someVariable: Int, - val anotherVariable: String -) - -// Regression test for https://github.com/square/moshi/issues/1022 -// Compile-only test -@JsonClass(generateAdapter = true) -internal data class MismatchParentAndNestedClassVisibility( - val type: Int, - val name: String? = null -) { - - @JsonClass(generateAdapter = true) - data class NestedClass( - val nestedProperty: String - ) -} - -// Regression test for https://github.com/square/moshi/issues/1052 -// Compile-only test -@JsonClass(generateAdapter = true) -data class KeysWithSpaces( - @Json(name = "1. Information") val information: String, - @Json(name = "2. Symbol") val symbol: String, - @Json(name = "3. Last Refreshed") val lastRefreshed: String, - @Json(name = "4. Interval") val interval: String, - @Json(name = "5. Output Size") val size: String, - @Json(name = "6. Time Zone") val timeZone: String -) - // Has to be outside to avoid Types seeing an owning class @JsonClass(generateAdapter = true) data class NullableTypeParams( @@ -1446,45 +1396,3 @@ data class NullableTypeParams( val nullableT: T?, val nonNullT: T ) - -/** - * This is here mostly just to ensure it still compiles. Covers variance, @Json, default values, - * nullability, primitive arrays, and some wacky generics. - */ -@JsonClass(generateAdapter = true) -data class SmokeTestType( - @Json(name = "first_name") val firstName: String, - @Json(name = "last_name") val lastName: String, - val age: Int, - val nationalities: List = emptyList(), - val weight: Float, - val tattoos: Boolean = false, - val race: String?, - val hasChildren: Boolean = false, - val favoriteFood: String? = null, - val favoriteDrink: String? = "Water", - val wildcardOut: MutableList = mutableListOf(), - val nullableWildcardOut: MutableList = mutableListOf(), - val wildcardIn: Array, - val any: List<*>, - val anyTwo: List, - val anyOut: MutableList, - val nullableAnyOut: MutableList, - val favoriteThreeNumbers: IntArray, - val favoriteArrayValues: Array, - val favoriteNullableArrayValues: Array, - val nullableSetListMapArrayNullableIntWithDefault: Set>>>? = null, - val aliasedName: TypeAliasName = "Woah", - val genericAlias: GenericTypeAlias = listOf("Woah"), - // Regression test for https://github.com/square/moshi/issues/1272 - val nestedArray: Array>? = null -) - -// Compile only, regression test for https://github.com/square/moshi/issues/848 -@JsonClass(generateAdapter = true) -data class Hotwords( - val `class`: List? -) - -typealias TypeAliasName = String -typealias GenericTypeAlias = List diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter.kt similarity index 100% rename from kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter.kt rename to kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter.kt diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/LooksLikeAClass/ClassInPackageThatLooksLikeAClass.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/LooksLikeAClass/ClassInPackageThatLooksLikeAClass.kt similarity index 100% rename from kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/LooksLikeAClass/ClassInPackageThatLooksLikeAClass.kt rename to kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/LooksLikeAClass/ClassInPackageThatLooksLikeAClass.kt diff --git a/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MixingReflectAndCodeGen.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MixingReflectAndCodeGen.kt new file mode 100644 index 0000000..29510c9 --- /dev/null +++ b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MixingReflectAndCodeGen.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.moshi.kotlin.codegen + +import com.google.common.truth.Truth.assertThat +import com.squareup.moshi.JsonClass +import com.squareup.moshi.Moshi +import com.squareup.moshi.adapter +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import org.junit.Test + +class MixingReflectAndCodeGen { + @Test + fun mixingReflectionAndCodegen() { + val moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() + val generatedAdapter = moshi.adapter() + val reflectionAdapter = moshi.adapter() + + assertThat(generatedAdapter.toString()) + .isEqualTo("GeneratedJsonAdapter(MixingReflectAndCodeGen.UsesGeneratedAdapter).nullSafe()") + assertThat(reflectionAdapter.toString()) + .isEqualTo( + "KotlinJsonAdapter(com.squareup.moshi.kotlin.codegen.MixingReflectAndCodeGen" + + ".UsesReflectionAdapter).nullSafe()" + ) + } + + @JsonClass(generateAdapter = true) + class UsesGeneratedAdapter(var a: Int, var b: Int) + + @JsonClass(generateAdapter = false) + class UsesReflectionAdapter(var a: Int, var b: Int) +} diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MoshiKspTest.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MoshiKspTest.kt similarity index 100% rename from kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MoshiKspTest.kt rename to kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MoshiKspTest.kt diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MultipleMasksTest.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MultipleMasksTest.kt similarity index 100% rename from kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MultipleMasksTest.kt rename to kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MultipleMasksTest.kt diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/annotation/UppercaseInAnnotationPackage.kt b/kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/annotation/UppercaseInAnnotationPackage.kt similarity index 100% rename from kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codegen/annotation/UppercaseInAnnotationPackage.kt rename to kotlin/tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/annotation/UppercaseInAnnotationPackage.kt diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/DualKotlinTest.kt b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/DualKotlinTest.kt index 82d20a2..5a1ff64 100644 --- a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/DualKotlinTest.kt +++ b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/DualKotlinTest.kt @@ -18,8 +18,6 @@ package com.squareup.moshi.kotlin import com.google.common.truth.Truth.assertThat import com.squareup.moshi.FromJson import com.squareup.moshi.Json -import com.squareup.moshi.JsonAdapter -import com.squareup.moshi.JsonAdapter.Factory import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonDataException import com.squareup.moshi.JsonQualifier @@ -32,53 +30,15 @@ import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import org.intellij.lang.annotations.Language import org.junit.Assert.fail import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.Parameterized -import org.junit.runners.Parameterized.Parameters -import java.lang.reflect.Type import kotlin.annotation.AnnotationRetention.RUNTIME -/** - * Parameterized tests that test serialization with both [KotlinJsonAdapterFactory] and code gen. - */ -@RunWith(Parameterized::class) -class DualKotlinTest(useReflection: Boolean) { - - companion object { - @Parameters(name = "reflective={0}") - @JvmStatic - fun parameters(): List> { - return listOf( - arrayOf(true), - arrayOf(false) - ) - } - } +class DualKotlinTest { @Suppress("UNCHECKED_CAST") private val moshi = Moshi.Builder() - .apply { - if (useReflection) { - add(KotlinJsonAdapterFactory()) - add( - object : Factory { - override fun create( - type: Type, - annotations: MutableSet, - moshi: Moshi - ): JsonAdapter<*>? { - // Prevent falling back to generated adapter lookup - val rawType = Types.getRawType(type) - val metadataClass = Class.forName("kotlin.Metadata") as Class - check(rawType.isEnum || !rawType.isAnnotationPresent(metadataClass)) { - "Unhandled Kotlin type in reflective test! $rawType" - } - return moshi.nextAdapter(this, type, annotations) - } - } - ) - } - } + // If code gen ran, the generated adapter will be tried first. If it can't find it, it will + // gracefully fall back to the KotlinJsonAdapter. This allows us to easily test both. + .addLast(KotlinJsonAdapterFactory()) .build() @Test fun requiredValueAbsent() { @@ -366,19 +326,22 @@ class DualKotlinTest(useReflection: Boolean) { } } } + assertThat(adapter.toJson(data)) //language=JSON .isEqualTo( """ - {"text":"root","t":{"text":"child 1"},"r":{"number":0,"t":{"number":1},"r":{"text":"grand child 1"}}} + {"text":"root","r":{"number":0,"r":{"text":"grand child 1"},"t":{"number":1}},"t":{"text":"child 1"}} """.trimIndent() ) } @JsonClass(generateAdapter = true) open class Node, R : Node> { - var t: T? = null + // kotlin-reflect doesn't preserve ordering, so put these in alphabetical order so that + // both reflective and code gen tests work the same var r: R? = null + var t: T? = null } @JsonClass(generateAdapter = true) diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt index 23d857c..3a0424b 100644 --- a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt +++ b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt @@ -886,28 +886,6 @@ class KotlinJsonAdapterTest { assertThat(adapter.toJson(value)).isEqualTo(json) } - @Test fun mixingReflectionAndCodegen() { - val moshi = Moshi.Builder() - .add(KotlinJsonAdapterFactory()) - .build() - val generatedAdapter = moshi.adapter() - val reflectionAdapter = moshi.adapter() - - assertThat(generatedAdapter.toString()) - .isEqualTo("GeneratedJsonAdapter(KotlinJsonAdapterTest.UsesGeneratedAdapter).nullSafe()") - assertThat(reflectionAdapter.toString()) - .isEqualTo( - "KotlinJsonAdapter(com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterTest" + - ".UsesReflectionAdapter).nullSafe()" - ) - } - - @JsonClass(generateAdapter = true) - class UsesGeneratedAdapter(var a: Int, var b: Int) - - @JsonClass(generateAdapter = false) - class UsesReflectionAdapter(var a: Int, var b: Int) - @Retention(RUNTIME) @JsonQualifier annotation class Uppercase diff --git a/settings.gradle.kts b/settings.gradle.kts index f3a138f..d3ff693 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -31,6 +31,7 @@ include(":examples") include(":kotlin:reflect") include(":kotlin:codegen") include(":kotlin:tests") +include(":kotlin:tests:codegen-only") include(":kotlin:tests:extra-moshi-test-module") enableFeaturePreview("VERSION_CATALOGS")