mirror of
https://github.com/fankes/moshi.git
synced 2025-10-18 23:49:21 +08:00
Parameterize kotlin test infra on CI (#1407)
This commit is contained in:
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -4,15 +4,15 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
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
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
use-ksp: [ true, false ]
|
|
||||||
kotlin-version: [ '1.5.31', '1.6.0-RC' ]
|
kotlin-version: [ '1.5.31', '1.6.0-RC' ]
|
||||||
ksp-version: [ '1.5.31-1.0.0', '1.6.0-RC-1.0.0' ]
|
ksp-version: [ '1.5.31-1.0.0', '1.6.0-RC-1.0.0' ]
|
||||||
|
kotlin-test-mode: [ 'REFLECT', 'KSP', 'KAPT' ]
|
||||||
exclude:
|
exclude:
|
||||||
- kotlin-version: '1.5.31'
|
- kotlin-version: '1.5.31'
|
||||||
ksp-version: '1.6.0-RC-1.0.0'
|
ksp-version: '1.6.0-RC-1.0.0'
|
||||||
@@ -47,10 +47,10 @@ jobs:
|
|||||||
java-version: '17'
|
java-version: '17'
|
||||||
|
|
||||||
- name: Test
|
- 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)
|
- 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
|
run: ./gradlew publish
|
||||||
env:
|
env:
|
||||||
ORG_GRADLE_PROJECT_mavenCentralUsername: '${{ secrets.SONATYPE_NEXUS_USERNAME }}'
|
ORG_GRADLE_PROJECT_mavenCentralUsername: '${{ secrets.SONATYPE_NEXUS_USERNAME }}'
|
||||||
|
@@ -21,16 +21,19 @@ import com.squareup.moshi.JsonDataException
|
|||||||
import com.squareup.moshi.JsonReader
|
import com.squareup.moshi.JsonReader
|
||||||
import com.squareup.moshi.JsonWriter
|
import com.squareup.moshi.JsonWriter
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
|
import com.squareup.moshi.Types
|
||||||
import com.squareup.moshi.internal.Util
|
import com.squareup.moshi.internal.Util
|
||||||
import com.squareup.moshi.internal.Util.generatedAdapter
|
import com.squareup.moshi.internal.Util.generatedAdapter
|
||||||
import com.squareup.moshi.internal.Util.resolve
|
import com.squareup.moshi.internal.Util.resolve
|
||||||
import com.squareup.moshi.rawType
|
import com.squareup.moshi.rawType
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.lang.reflect.Type
|
import java.lang.reflect.Type
|
||||||
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KFunction
|
import kotlin.reflect.KFunction
|
||||||
import kotlin.reflect.KMutableProperty1
|
import kotlin.reflect.KMutableProperty1
|
||||||
import kotlin.reflect.KParameter
|
import kotlin.reflect.KParameter
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
|
import kotlin.reflect.KTypeParameter
|
||||||
import kotlin.reflect.full.findAnnotation
|
import kotlin.reflect.full.findAnnotation
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
import kotlin.reflect.full.primaryConstructor
|
import kotlin.reflect.full.primaryConstructor
|
||||||
@@ -257,7 +260,31 @@ public class KotlinJsonAdapterFactory : JsonAdapter.Factory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val name = jsonAnnotation?.name ?: property.name
|
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<Any>(
|
val adapter = moshi.adapter<Any>(
|
||||||
resolvedPropertyType,
|
resolvedPropertyType,
|
||||||
Util.jsonAnnotations(allAnnotations.toTypedArray()),
|
Util.jsonAnnotations(allAnnotations.toTypedArray()),
|
||||||
|
@@ -14,6 +14,9 @@
|
|||||||
* limitations under the License.
|
* 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
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -22,11 +25,24 @@ plugins {
|
|||||||
id("com.google.devtools.ksp") apply false
|
id("com.google.devtools.ksp") apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
val useKsp = hasProperty("useKsp")
|
enum class TestMode {
|
||||||
if (useKsp) {
|
REFLECT, KAPT, KSP
|
||||||
apply(plugin = "com.google.devtools.ksp")
|
}
|
||||||
} else {
|
|
||||||
apply(plugin = "org.jetbrains.kotlin.kapt")
|
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<Test>().configureEach {
|
tasks.withType<Test>().configureEach {
|
||||||
@@ -48,10 +64,16 @@ tasks.withType<KotlinCompile>().configureEach {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
if (useKsp) {
|
when (testMode) {
|
||||||
"kspTest"(project(":kotlin:codegen"))
|
REFLECT -> {
|
||||||
} else {
|
// Do nothing
|
||||||
"kaptTest"(project(":kotlin:codegen"))
|
}
|
||||||
|
KAPT -> {
|
||||||
|
"kaptTest"(project(":kotlin:codegen"))
|
||||||
|
}
|
||||||
|
KSP -> {
|
||||||
|
"kspTest"(project(":kotlin:codegen"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
testImplementation(project(":moshi"))
|
testImplementation(project(":moshi"))
|
||||||
testImplementation(project(":kotlin:reflect"))
|
testImplementation(project(":kotlin:reflect"))
|
||||||
|
87
kotlin/tests/codegen-only/build.gradle.kts
Normal file
87
kotlin/tests/codegen-only/build.gradle.kts
Normal file
@@ -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<Test>().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<KotlinCompile>().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)
|
||||||
|
}
|
@@ -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<T>(
|
||||||
|
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<String>?
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String> = 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<out String> = mutableListOf(),
|
||||||
|
val nullableWildcardOut: MutableList<out String?> = mutableListOf(),
|
||||||
|
val wildcardIn: Array<in String>,
|
||||||
|
val any: List<*>,
|
||||||
|
val anyTwo: List<Any>,
|
||||||
|
val anyOut: MutableList<out Any>,
|
||||||
|
val nullableAnyOut: MutableList<out Any?>,
|
||||||
|
val favoriteThreeNumbers: IntArray,
|
||||||
|
val favoriteArrayValues: Array<String>,
|
||||||
|
val favoriteNullableArrayValues: Array<String?>,
|
||||||
|
val nullableSetListMapArrayNullableIntWithDefault: Set<List<Map<String, Array<IntArray?>>>>? = null,
|
||||||
|
val aliasedName: TypeAliasName = "Woah",
|
||||||
|
val genericAlias: GenericTypeAlias = listOf("Woah"),
|
||||||
|
// Regression test for https://github.com/square/moshi/issues/1272
|
||||||
|
val nestedArray: Array<Map<String, Any>>? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
typealias TypeAliasName = String
|
||||||
|
typealias GenericTypeAlias = List<String>
|
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.squareup.moshi.kotlin
|
package com.squareup.moshi.kotlin.codegen
|
||||||
|
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
@@ -66,14 +66,6 @@ data class TestClass(
|
|||||||
val dynamicInlineOptional: Int = createInlineInt()
|
val dynamicInlineOptional: Int = createInlineInt()
|
||||||
)
|
)
|
||||||
|
|
||||||
// Regression test for https://github.com/square/moshi/issues/905
|
|
||||||
// Just needs to compile
|
|
||||||
@JsonClass(generateAdapter = true)
|
|
||||||
data class GenericTestClassWithDefaults<T>(
|
|
||||||
val input: String = "",
|
|
||||||
val genericInput: T
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun createInt(): Int {
|
private fun createInt(): Int {
|
||||||
return 3
|
return 3
|
||||||
}
|
}
|
@@ -36,7 +36,6 @@ import org.junit.Assert.fail
|
|||||||
import org.junit.Ignore
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.annotation.AnnotationTarget.TYPE
|
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
|
|
||||||
@@ -1342,19 +1341,6 @@ class GeneratedAdaptersTest {
|
|||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class DeprecatedProperty(@Deprecated("Deprecated for reasons") val foo: String)
|
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() {
|
@Test fun typesSizeCheckMessages_noArgs() {
|
||||||
try {
|
try {
|
||||||
// Note: This is impossible to do if you use the reified adapter extension!
|
// 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
|
// Has to be outside to avoid Types seeing an owning class
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class NullableTypeParams<T>(
|
data class NullableTypeParams<T>(
|
||||||
@@ -1446,45 +1396,3 @@ data class NullableTypeParams<T>(
|
|||||||
val nullableT: T?,
|
val nullableT: T?,
|
||||||
val nonNullT: 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<String> = 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<out String> = mutableListOf(),
|
|
||||||
val nullableWildcardOut: MutableList<out String?> = mutableListOf(),
|
|
||||||
val wildcardIn: Array<in String>,
|
|
||||||
val any: List<*>,
|
|
||||||
val anyTwo: List<Any>,
|
|
||||||
val anyOut: MutableList<out Any>,
|
|
||||||
val nullableAnyOut: MutableList<out Any?>,
|
|
||||||
val favoriteThreeNumbers: IntArray,
|
|
||||||
val favoriteArrayValues: Array<String>,
|
|
||||||
val favoriteNullableArrayValues: Array<String?>,
|
|
||||||
val nullableSetListMapArrayNullableIntWithDefault: Set<List<Map<String, Array<IntArray?>>>>? = null,
|
|
||||||
val aliasedName: TypeAliasName = "Woah",
|
|
||||||
val genericAlias: GenericTypeAlias = listOf("Woah"),
|
|
||||||
// Regression test for https://github.com/square/moshi/issues/1272
|
|
||||||
val nestedArray: Array<Map<String, Any>>? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
// Compile only, regression test for https://github.com/square/moshi/issues/848
|
|
||||||
@JsonClass(generateAdapter = true)
|
|
||||||
data class Hotwords(
|
|
||||||
val `class`: List<String>?
|
|
||||||
)
|
|
||||||
|
|
||||||
typealias TypeAliasName = String
|
|
||||||
typealias GenericTypeAlias = List<String>
|
|
@@ -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<UsesGeneratedAdapter>()
|
||||||
|
val reflectionAdapter = moshi.adapter<UsesReflectionAdapter>()
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
@@ -18,8 +18,6 @@ package com.squareup.moshi.kotlin
|
|||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import com.squareup.moshi.FromJson
|
import com.squareup.moshi.FromJson
|
||||||
import com.squareup.moshi.Json
|
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.JsonClass
|
||||||
import com.squareup.moshi.JsonDataException
|
import com.squareup.moshi.JsonDataException
|
||||||
import com.squareup.moshi.JsonQualifier
|
import com.squareup.moshi.JsonQualifier
|
||||||
@@ -32,53 +30,15 @@ import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
|||||||
import org.intellij.lang.annotations.Language
|
import org.intellij.lang.annotations.Language
|
||||||
import org.junit.Assert.fail
|
import org.junit.Assert.fail
|
||||||
import org.junit.Test
|
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
|
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||||
|
|
||||||
/**
|
class DualKotlinTest {
|
||||||
* 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<Array<*>> {
|
|
||||||
return listOf(
|
|
||||||
arrayOf(true),
|
|
||||||
arrayOf(false)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private val moshi = Moshi.Builder()
|
private val moshi = Moshi.Builder()
|
||||||
.apply {
|
// If code gen ran, the generated adapter will be tried first. If it can't find it, it will
|
||||||
if (useReflection) {
|
// gracefully fall back to the KotlinJsonAdapter. This allows us to easily test both.
|
||||||
add(KotlinJsonAdapterFactory())
|
.addLast(KotlinJsonAdapterFactory())
|
||||||
add(
|
|
||||||
object : Factory {
|
|
||||||
override fun create(
|
|
||||||
type: Type,
|
|
||||||
annotations: MutableSet<out Annotation>,
|
|
||||||
moshi: Moshi
|
|
||||||
): JsonAdapter<*>? {
|
|
||||||
// Prevent falling back to generated adapter lookup
|
|
||||||
val rawType = Types.getRawType(type)
|
|
||||||
val metadataClass = Class.forName("kotlin.Metadata") as Class<out Annotation>
|
|
||||||
check(rawType.isEnum || !rawType.isAnnotationPresent(metadataClass)) {
|
|
||||||
"Unhandled Kotlin type in reflective test! $rawType"
|
|
||||||
}
|
|
||||||
return moshi.nextAdapter<Any>(this, type, annotations)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@Test fun requiredValueAbsent() {
|
@Test fun requiredValueAbsent() {
|
||||||
@@ -366,19 +326,22 @@ class DualKotlinTest(useReflection: Boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(adapter.toJson(data))
|
assertThat(adapter.toJson(data))
|
||||||
//language=JSON
|
//language=JSON
|
||||||
.isEqualTo(
|
.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()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
open class Node<T : Node<T, R>, R : Node<R, T>> {
|
open class Node<T : Node<T, R>, R : Node<R, T>> {
|
||||||
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 r: R? = null
|
||||||
|
var t: T? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
|
@@ -886,28 +886,6 @@ class KotlinJsonAdapterTest {
|
|||||||
assertThat(adapter.toJson(value)).isEqualTo(json)
|
assertThat(adapter.toJson(value)).isEqualTo(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun mixingReflectionAndCodegen() {
|
|
||||||
val moshi = Moshi.Builder()
|
|
||||||
.add(KotlinJsonAdapterFactory())
|
|
||||||
.build()
|
|
||||||
val generatedAdapter = moshi.adapter<UsesGeneratedAdapter>()
|
|
||||||
val reflectionAdapter = moshi.adapter<UsesReflectionAdapter>()
|
|
||||||
|
|
||||||
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)
|
@Retention(RUNTIME)
|
||||||
@JsonQualifier
|
@JsonQualifier
|
||||||
annotation class Uppercase
|
annotation class Uppercase
|
||||||
|
@@ -31,6 +31,7 @@ include(":examples")
|
|||||||
include(":kotlin:reflect")
|
include(":kotlin:reflect")
|
||||||
include(":kotlin:codegen")
|
include(":kotlin:codegen")
|
||||||
include(":kotlin:tests")
|
include(":kotlin:tests")
|
||||||
|
include(":kotlin:tests:codegen-only")
|
||||||
include(":kotlin:tests:extra-moshi-test-module")
|
include(":kotlin:tests:extra-moshi-test-module")
|
||||||
|
|
||||||
enableFeaturePreview("VERSION_CATALOGS")
|
enableFeaturePreview("VERSION_CATALOGS")
|
||||||
|
Reference in New Issue
Block a user