mirror of
https://github.com/fankes/moshi.git
synced 2025-10-18 15:39:22 +08:00
Add AdapterRegistryGenerator and related functionality for default adapter registration
This commit is contained in:
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.api
|
||||||
|
|
||||||
|
import com.squareup.kotlinpoet.ClassName
|
||||||
|
import com.squareup.kotlinpoet.CodeBlock
|
||||||
|
import com.squareup.kotlinpoet.FileSpec
|
||||||
|
import com.squareup.kotlinpoet.FunSpec
|
||||||
|
import com.squareup.kotlinpoet.KModifier
|
||||||
|
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
||||||
|
import com.squareup.kotlinpoet.PropertySpec
|
||||||
|
import com.squareup.kotlinpoet.STAR
|
||||||
|
import com.squareup.kotlinpoet.TypeSpec
|
||||||
|
import com.squareup.kotlinpoet.WildcardTypeName
|
||||||
|
import com.squareup.kotlinpoet.asClassName
|
||||||
|
|
||||||
|
private const val DEFAULT_ADAPTER_REGISTRY_PACKAGE_NAME_PREFIX = "com.squareup.moshi.generated"
|
||||||
|
private const val DEFAULT_ADAPTER_REGISTRY_CLASS_NAME = "DefaultMoshiAdapterRegistry"
|
||||||
|
|
||||||
|
public data class AdapterRegistration(
|
||||||
|
val targetClassName: ClassName,
|
||||||
|
val adapterClassName: ClassName,
|
||||||
|
val hasTypeParameters: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
/** Generates a registry of adapters. */
|
||||||
|
@InternalMoshiCodegenApi
|
||||||
|
public class AdapterRegistryGenerator(
|
||||||
|
private val adapterRegistrations: List<AdapterRegistration>
|
||||||
|
) {
|
||||||
|
|
||||||
|
public fun generate(): FileSpec {
|
||||||
|
// Get the top-level package name of the project (inferred from the shortest package name)
|
||||||
|
val packageName = run {
|
||||||
|
val firstPackage = adapterRegistrations
|
||||||
|
.filter { it.targetClassName.packageName.isNotEmpty() }
|
||||||
|
.minByOrNull { it.targetClassName.packageName.length }
|
||||||
|
?.targetClassName?.packageName
|
||||||
|
|
||||||
|
firstPackage
|
||||||
|
} ?: "default" // fallback package name
|
||||||
|
|
||||||
|
// Generate a package hash of the package name to avoid potential collisions.
|
||||||
|
val packageHash = packageName.hashCode().toUInt().toString(16).take(12)
|
||||||
|
val registryPackageName = "$DEFAULT_ADAPTER_REGISTRY_PACKAGE_NAME_PREFIX.r$packageHash"
|
||||||
|
|
||||||
|
val moshiClass = ClassName("com.squareup.moshi", "Moshi")
|
||||||
|
val adapterRegistryClass = moshiClass.nestedClass("AdapterRegistry")
|
||||||
|
val jsonAdapterClass = ClassName("com.squareup.moshi", "JsonAdapter")
|
||||||
|
val typeClass = ClassName("java.lang.reflect", "Type")
|
||||||
|
|
||||||
|
val adaptersMapBuilder = CodeBlock.builder()
|
||||||
|
adaptersMapBuilder.add("mapOf(")
|
||||||
|
|
||||||
|
val nonGenericAdapters = adapterRegistrations.filter { !it.hasTypeParameters }
|
||||||
|
nonGenericAdapters.forEachIndexed { index, registration ->
|
||||||
|
if (index > 0) adaptersMapBuilder.add(",")
|
||||||
|
adaptersMapBuilder.add(
|
||||||
|
"\n %T::class.java to %T::class.java",
|
||||||
|
registration.targetClassName,
|
||||||
|
registration.adapterClassName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nonGenericAdapters.isNotEmpty()) {
|
||||||
|
adaptersMapBuilder.add("\n")
|
||||||
|
}
|
||||||
|
adaptersMapBuilder.add(")")
|
||||||
|
|
||||||
|
val adaptersProperty = PropertySpec.builder(
|
||||||
|
"adapters",
|
||||||
|
Map::class.asClassName().parameterizedBy(
|
||||||
|
typeClass,
|
||||||
|
Class::class.asClassName().parameterizedBy(
|
||||||
|
WildcardTypeName.producerOf(jsonAdapterClass.parameterizedBy(STAR))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.addModifiers(KModifier.OVERRIDE)
|
||||||
|
.getter(
|
||||||
|
FunSpec.getterBuilder()
|
||||||
|
.addCode("return %L", adaptersMapBuilder.build())
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val registryClass = TypeSpec.classBuilder(DEFAULT_ADAPTER_REGISTRY_CLASS_NAME)
|
||||||
|
.addSuperinterface(adapterRegistryClass)
|
||||||
|
.addProperty(adaptersProperty)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val file = FileSpec.builder(registryPackageName, DEFAULT_ADAPTER_REGISTRY_CLASS_NAME)
|
||||||
|
.addFileComment(
|
||||||
|
"""
|
||||||
|
This file is auto generated by Moshi Kotlin CodeGen.
|
||||||
|
**DO NOT EDIT THIS FILE MANUALLY**
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
.addType(registryClass)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
}
|
@@ -37,6 +37,27 @@ public object Options {
|
|||||||
*/
|
*/
|
||||||
public const val OPTION_GENERATE_PROGUARD_RULES: String = "moshi.generateProguardRules"
|
public const val OPTION_GENERATE_PROGUARD_RULES: String = "moshi.generateProguardRules"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This boolean processing option can enable omission of `-keepnames` rules for target classes.
|
||||||
|
* Moshi's reflective lookup of adapters by class name will fail if obfuscation is applied
|
||||||
|
* to the target class. Only enable this if you are sure you won't be using Moshi's
|
||||||
|
* reflective adapter lookup.
|
||||||
|
* If you set [OPTION_GENERATE_DEFAULT_ADAPTER_REGISTRY] to `true` and decide to
|
||||||
|
* manually set the generated registry, you can also enable this option to
|
||||||
|
* avoid keeping target class names. (LET THEM BE OBFUSCATION, I DON'T WANT THE CLASS NAME TO BE RETAINED!)
|
||||||
|
* This option is automatically invalid if [OPTION_GENERATE_PROGUARD_RULES] is set to `false`.
|
||||||
|
* This is disabled by default for backward compatibility.
|
||||||
|
*/
|
||||||
|
public const val OPTION_PROGUARD_RULES_DONT_KEEP_CLASS_NAMES: String = "moshi.proguardRulesDontKeepClassNames"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This boolean processing option can enable generation of a default adapter registry that
|
||||||
|
* a compile-time adapter registry that doesn't depend on class names for lookup.
|
||||||
|
* The generated registry content is a class annotated with `@JsonClass(generateAdapter = true)`.
|
||||||
|
* This is disabled by default for backward compatibility.
|
||||||
|
*/
|
||||||
|
public const val OPTION_GENERATE_DEFAULT_ADAPTER_REGISTRY: String = "moshi.generateDefaultAdapterRegistry"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This boolean processing option controls whether or not Moshi will directly instantiate
|
* This boolean processing option controls whether or not Moshi will directly instantiate
|
||||||
* JsonQualifier annotations in Kotlin 1.6+. Note that this is enabled by default in Kotlin 1.6
|
* JsonQualifier annotations in Kotlin 1.6+. Note that this is enabled by default in Kotlin 1.6
|
||||||
|
@@ -45,7 +45,7 @@ public data class ProguardConfig(
|
|||||||
return "META-INF/proguard/moshi-$canonicalName"
|
return "META-INF/proguard/moshi-$canonicalName"
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun writeTo(out: Appendable): Unit = out.run {
|
public fun writeTo(out: Appendable, dontKeepClassNames: Boolean): Unit = out.run {
|
||||||
//
|
//
|
||||||
// -keepnames class {the target class}
|
// -keepnames class {the target class}
|
||||||
// -if class {the target class}
|
// -if class {the target class}
|
||||||
@@ -56,11 +56,17 @@ public data class ProguardConfig(
|
|||||||
//
|
//
|
||||||
val targetName = targetClass.reflectionName()
|
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
|
|
||||||
appendLine("-keepnames class $targetName")
|
// Keep the class name for Moshi's reflective lookup based on it,
|
||||||
|
// but only if the user hasn't opted out of this.
|
||||||
|
if (!dontKeepClassNames)
|
||||||
|
appendLine("-keepnames class $targetName")
|
||||||
|
|
||||||
|
// Keep the `JsonClass` annotation on the target class, R8 will shrink it away otherwise.
|
||||||
|
appendLine("-keep${if (dontKeepClassNames) ",allowobfuscation" else ""} @com.squareup.moshi.JsonClass class *")
|
||||||
|
|
||||||
appendLine("-if class $targetName")
|
appendLine("-if class $targetName")
|
||||||
appendLine("-keep class $adapterCanonicalName {")
|
appendLine("-${if (dontKeepClassNames) "keepclassmembers" else "keep"} class $adapterCanonicalName {")
|
||||||
// Keep the constructor for Moshi's reflective lookup
|
// Keep the constructor for Moshi's reflective lookup
|
||||||
val constructorArgs = adapterConstructorParams.joinToString(",")
|
val constructorArgs = adapterConstructorParams.joinToString(",")
|
||||||
appendLine(" public <init>($constructorArgs);")
|
appendLine(" public <init>($constructorArgs);")
|
||||||
|
@@ -24,16 +24,22 @@ import com.google.devtools.ksp.processing.SymbolProcessor
|
|||||||
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||||
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||||
import com.google.devtools.ksp.symbol.KSAnnotated
|
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||||
|
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||||
import com.google.devtools.ksp.symbol.KSDeclaration
|
import com.google.devtools.ksp.symbol.KSDeclaration
|
||||||
import com.google.devtools.ksp.symbol.KSFile
|
import com.google.devtools.ksp.symbol.KSFile
|
||||||
import com.squareup.kotlinpoet.AnnotationSpec
|
import com.squareup.kotlinpoet.AnnotationSpec
|
||||||
import com.squareup.kotlinpoet.ClassName
|
import com.squareup.kotlinpoet.ClassName
|
||||||
import com.squareup.kotlinpoet.ksp.addOriginatingKSFile
|
import com.squareup.kotlinpoet.ksp.addOriginatingKSFile
|
||||||
|
import com.squareup.kotlinpoet.ksp.toClassName
|
||||||
import com.squareup.kotlinpoet.ksp.writeTo
|
import com.squareup.kotlinpoet.ksp.writeTo
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import com.squareup.moshi.kotlin.codegen.api.AdapterGenerator
|
import com.squareup.moshi.kotlin.codegen.api.AdapterGenerator
|
||||||
|
import com.squareup.moshi.kotlin.codegen.api.AdapterRegistration
|
||||||
|
import com.squareup.moshi.kotlin.codegen.api.AdapterRegistryGenerator
|
||||||
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATED
|
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATED
|
||||||
|
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATE_DEFAULT_ADAPTER_REGISTRY
|
||||||
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATE_PROGUARD_RULES
|
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_GENERATE_PROGUARD_RULES
|
||||||
|
import com.squareup.moshi.kotlin.codegen.api.Options.OPTION_PROGUARD_RULES_DONT_KEEP_CLASS_NAMES
|
||||||
import com.squareup.moshi.kotlin.codegen.api.Options.POSSIBLE_GENERATED_NAMES
|
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.ProguardConfig
|
||||||
import com.squareup.moshi.kotlin.codegen.api.PropertyGenerator
|
import com.squareup.moshi.kotlin.codegen.api.PropertyGenerator
|
||||||
@@ -63,6 +69,10 @@ private class JsonClassSymbolProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private val generateProguardRules = environment.options[OPTION_GENERATE_PROGUARD_RULES]?.toBooleanStrictOrNull() ?: true
|
private val generateProguardRules = environment.options[OPTION_GENERATE_PROGUARD_RULES]?.toBooleanStrictOrNull() ?: true
|
||||||
|
private val proguardRulesDontKeepClassNames = environment.options[OPTION_PROGUARD_RULES_DONT_KEEP_CLASS_NAMES]?.toBooleanStrictOrNull() ?: false
|
||||||
|
private val generateDefaultAdapterRegistry = environment.options[OPTION_GENERATE_DEFAULT_ADAPTER_REGISTRY]?.toBooleanStrictOrNull() ?: false
|
||||||
|
|
||||||
|
private val adapterRegistrations = mutableListOf<AdapterRegistration>()
|
||||||
|
|
||||||
override fun process(resolver: Resolver): List<KSAnnotated> {
|
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||||
val generatedAnnotation = generatedOption?.let {
|
val generatedAnnotation = generatedOption?.let {
|
||||||
@@ -100,13 +110,40 @@ private class JsonClassSymbolProcessor(
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
preparedAdapter.spec.writeTo(codeGenerator, aggregating = false)
|
preparedAdapter.spec.writeTo(codeGenerator, aggregating = false)
|
||||||
preparedAdapter.proguardConfig?.writeTo(codeGenerator, originatingFile)
|
preparedAdapter.proguardConfig?.writeTo(codeGenerator, originatingFile, proguardRulesDontKeepClassNames)
|
||||||
|
|
||||||
|
// Collect adapter registration information.
|
||||||
|
if (generateDefaultAdapterRegistry && type is KSClassDeclaration) {
|
||||||
|
val targetClassName = type.toClassName()
|
||||||
|
val adapterClassName = ClassName(
|
||||||
|
targetClassName.packageName,
|
||||||
|
"${targetClassName.simpleNames.joinToString("_")}JsonAdapter"
|
||||||
|
)
|
||||||
|
val hasTypeParameters = type.typeParameters.isNotEmpty()
|
||||||
|
|
||||||
|
adapterRegistrations.add(
|
||||||
|
AdapterRegistration(
|
||||||
|
targetClassName = targetClassName,
|
||||||
|
adapterClassName = adapterClassName,
|
||||||
|
hasTypeParameters = hasTypeParameters
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.error(
|
logger.error(
|
||||||
"Error preparing ${type.simpleName.asString()}: ${e.stackTrace.joinToString("\n")}",
|
"Error preparing ${type.simpleName.asString()}: ${e.stackTrace.joinToString("\n")}",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adapterRegistrations.isNotEmpty()) {
|
||||||
|
// FileAlreadyExistsException can happen if multiple compilations.
|
||||||
|
runCatching {
|
||||||
|
val adapterRegistryGenerator = adapterRegistryGenerator()
|
||||||
|
adapterRegistryGenerator.generate().writeTo(codeGenerator, aggregating = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,10 +181,12 @@ private class JsonClassSymbolProcessor(
|
|||||||
|
|
||||||
return AdapterGenerator(type, sortedProperties)
|
return AdapterGenerator(type, sortedProperties)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun adapterRegistryGenerator() = AdapterRegistryGenerator(adapterRegistrations)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Writes this config to a [codeGenerator]. */
|
/** Writes this config to a [codeGenerator]. */
|
||||||
private fun ProguardConfig.writeTo(codeGenerator: CodeGenerator, originatingKSFile: KSFile) {
|
private fun ProguardConfig.writeTo(codeGenerator: CodeGenerator, originatingKSFile: KSFile, dontKeepClassNames: Boolean) {
|
||||||
val file = codeGenerator.createNewFile(
|
val file = codeGenerator.createNewFile(
|
||||||
dependencies = Dependencies(aggregating = false, originatingKSFile),
|
dependencies = Dependencies(aggregating = false, originatingKSFile),
|
||||||
packageName = "",
|
packageName = "",
|
||||||
@@ -156,5 +195,5 @@ private fun ProguardConfig.writeTo(codeGenerator: CodeGenerator, originatingKSFi
|
|||||||
)
|
)
|
||||||
// Don't use writeTo(file) because that tries to handle directories under the hood
|
// Don't use writeTo(file) because that tries to handle directories under the hood
|
||||||
OutputStreamWriter(file, StandardCharsets.UTF_8)
|
OutputStreamWriter(file, StandardCharsets.UTF_8)
|
||||||
.use(::writeTo)
|
.use { writeTo(it, dontKeepClassNames) }
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,8 @@ public class Moshi internal constructor(builder: Builder) {
|
|||||||
private val lookupChainThreadLocal = ThreadLocal<LookupChain>()
|
private val lookupChainThreadLocal = ThreadLocal<LookupChain>()
|
||||||
private val adapterCache = LinkedHashMap<Any?, JsonAdapter<*>?>()
|
private val adapterCache = LinkedHashMap<Any?, JsonAdapter<*>?>()
|
||||||
|
|
||||||
|
internal val registry = builder.registry
|
||||||
|
|
||||||
/** Returns a JSON adapter for `type`, creating it if necessary. */
|
/** Returns a JSON adapter for `type`, creating it if necessary. */
|
||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
public fun <T> adapter(type: Type): JsonAdapter<T> = adapter(type, NO_ANNOTATIONS)
|
public fun <T> adapter(type: Type): JsonAdapter<T> = adapter(type, NO_ANNOTATIONS)
|
||||||
@@ -191,6 +193,7 @@ public class Moshi internal constructor(builder: Builder) {
|
|||||||
public class Builder {
|
public class Builder {
|
||||||
internal val factories = mutableListOf<JsonAdapter.Factory>()
|
internal val factories = mutableListOf<JsonAdapter.Factory>()
|
||||||
internal var lastOffset = 0
|
internal var lastOffset = 0
|
||||||
|
internal var registry: AdapterRegistry? = null
|
||||||
|
|
||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
@@ -239,10 +242,42 @@ public class Moshi internal constructor(builder: Builder) {
|
|||||||
addLast(AdapterMethodsFactory(adapter))
|
addLast(AdapterMethodsFactory(adapter))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun setRegistry(adapterRegistry: AdapterRegistry): Builder = apply {
|
||||||
|
this.registry = adapterRegistry
|
||||||
|
}
|
||||||
|
|
||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
public fun build(): Moshi = Moshi(this)
|
public fun build(): Moshi = Moshi(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A registry of [JsonAdapter]s to be registered with a [Moshi] instance.
|
||||||
|
*
|
||||||
|
* To use, create a subclass and implement [adapters]. Then set an instance of your subclass on
|
||||||
|
* [Moshi.Builder.setRegistry].
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```
|
||||||
|
* class MyAdapterRegistry : Moshi.AdapterRegistry {
|
||||||
|
* override val adapters = mapOf(
|
||||||
|
* MyType::class.java to MyTypeJsonAdapter::class.java,
|
||||||
|
* Types.newParameterizedType(List::class.java, String::class.java) to MyStringListJsonAdapter::class.java
|
||||||
|
* )
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* val myRegistry = MyAdapterRegistry()
|
||||||
|
*
|
||||||
|
* val builder = Moshi.Builder().setRegistry(myRegistry)
|
||||||
|
* val moshi = builder.build()
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
public interface AdapterRegistry {
|
||||||
|
/**
|
||||||
|
* A map of [Type] to [JsonAdapter] to be registered.
|
||||||
|
*/
|
||||||
|
public val adapters: Map<Type, Class<out JsonAdapter<*>>>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A possibly-reentrant chain of lookups for JSON adapters.
|
* A possibly-reentrant chain of lookups for JSON adapters.
|
||||||
*
|
*
|
||||||
|
@@ -378,12 +378,24 @@ public fun Moshi.generatedAdapter(
|
|||||||
if (jsonClass == null || !jsonClass.generateAdapter) {
|
if (jsonClass == null || !jsonClass.generateAdapter) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val adapterClassName = Types.generatedJsonAdapterName(rawType.name)
|
|
||||||
|
val adapters = registry?.adapters
|
||||||
|
|
||||||
|
val rawAdapterClassName = Types.generatedJsonAdapterName(rawType.name)
|
||||||
var possiblyFoundAdapter: Class<out JsonAdapter<*>>? = null
|
var possiblyFoundAdapter: Class<out JsonAdapter<*>>? = null
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val adapterClass = Class.forName(adapterClassName, true, rawType.classLoader) as Class<out JsonAdapter<*>>
|
val adapterClass = adapters?.firstNotNullOfOrNull { (regType, regAdapter) ->
|
||||||
|
if (typesMatch(rawType, regType)) {
|
||||||
|
regAdapter
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} ?: Class.forName(rawAdapterClassName, true, rawType.classLoader) as? Class<out JsonAdapter<*>>?
|
||||||
|
?: throw ClassNotFoundException()
|
||||||
possiblyFoundAdapter = adapterClass
|
possiblyFoundAdapter = adapterClass
|
||||||
|
|
||||||
var constructor: Constructor<out JsonAdapter<*>>
|
var constructor: Constructor<out JsonAdapter<*>>
|
||||||
var args: Array<Any>
|
var args: Array<Any>
|
||||||
if (type is ParameterizedType) {
|
if (type is ParameterizedType) {
|
||||||
|
Reference in New Issue
Block a user