mirror of
https://github.com/fankes/moshi.git
synced 2025-10-18 23:49:21 +08:00
Switch from internal to experimental internal annotation (#1410)
This commit is contained in:
@@ -32,6 +32,7 @@ tasks.withType<KotlinCompile>().configureEach {
|
|||||||
"-Xopt-in=kotlin.RequiresOptIn",
|
"-Xopt-in=kotlin.RequiresOptIn",
|
||||||
"-Xopt-in=com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview",
|
"-Xopt-in=com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview",
|
||||||
"-Xopt-in=com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview",
|
"-Xopt-in=com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview",
|
||||||
|
"-Xopt-in=com.squareup.moshi.kotlin.codegen.api.InternalMoshiCodegenApi",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -52,12 +52,13 @@ private const val TO_STRING_PREFIX = "GeneratedJsonAdapter("
|
|||||||
private const val TO_STRING_SIZE_BASE = TO_STRING_PREFIX.length + 1 // 1 is the closing paren
|
private const val TO_STRING_SIZE_BASE = TO_STRING_PREFIX.length + 1 // 1 is the closing paren
|
||||||
|
|
||||||
/** Generates a JSON adapter for a target type. */
|
/** Generates a JSON adapter for a target type. */
|
||||||
internal class AdapterGenerator(
|
@InternalMoshiCodegenApi
|
||||||
|
public class AdapterGenerator(
|
||||||
private val target: TargetType,
|
private val target: TargetType,
|
||||||
private val propertyList: List<PropertyGenerator>
|
private val propertyList: List<PropertyGenerator>
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
private companion object {
|
||||||
private val INT_TYPE_BLOCK = CodeBlock.of("%T::class.javaPrimitiveType", INT)
|
private val INT_TYPE_BLOCK = CodeBlock.of("%T::class.javaPrimitiveType", INT)
|
||||||
private val DEFAULT_CONSTRUCTOR_MARKER_TYPE_BLOCK = CodeBlock.of(
|
private val DEFAULT_CONSTRUCTOR_MARKER_TYPE_BLOCK = CodeBlock.of(
|
||||||
"%T.DEFAULT_CONSTRUCTOR_MARKER",
|
"%T.DEFAULT_CONSTRUCTOR_MARKER",
|
||||||
@@ -166,7 +167,7 @@ internal class AdapterGenerator(
|
|||||||
.initializer("null")
|
.initializer("null")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun prepare(generateProguardRules: Boolean, typeHook: (TypeSpec) -> TypeSpec = { it }): PreparedAdapter {
|
public fun prepare(generateProguardRules: Boolean, typeHook: (TypeSpec) -> TypeSpec = { it }): PreparedAdapter {
|
||||||
val reservedSimpleNames = mutableSetOf<String>()
|
val reservedSimpleNames = mutableSetOf<String>()
|
||||||
for (property in nonTransientProperties) {
|
for (property in nonTransientProperties) {
|
||||||
// Allocate names for simple property types first to avoid collisions
|
// Allocate names for simple property types first to avoid collisions
|
||||||
@@ -727,7 +728,8 @@ private fun FunSpec.Builder.addMissingPropertyCheck(property: PropertyGenerator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Represents a prepared adapter with its [spec] and optional associated [proguardConfig]. */
|
/** Represents a prepared adapter with its [spec] and optional associated [proguardConfig]. */
|
||||||
internal data class PreparedAdapter(val spec: FileSpec, val proguardConfig: ProguardConfig?)
|
@InternalMoshiCodegenApi
|
||||||
|
public data class PreparedAdapter(val spec: FileSpec, val proguardConfig: ProguardConfig?)
|
||||||
|
|
||||||
private fun AsmType.toReflectionString(): String {
|
private fun AsmType.toReflectionString(): String {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
|
@@ -36,15 +36,16 @@ import com.squareup.moshi.Types
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
/** A JsonAdapter that can be used to encode and decode a particular field. */
|
/** A JsonAdapter that can be used to encode and decode a particular field. */
|
||||||
internal data class DelegateKey(
|
@InternalMoshiCodegenApi
|
||||||
|
public data class DelegateKey(
|
||||||
private val type: TypeName,
|
private val type: TypeName,
|
||||||
private val jsonQualifiers: List<AnnotationSpec>,
|
private val jsonQualifiers: List<AnnotationSpec>,
|
||||||
private val instantiateAnnotations: Boolean
|
private val instantiateAnnotations: Boolean
|
||||||
) {
|
) {
|
||||||
val nullable get() = type.isNullable
|
public val nullable: Boolean get() = type.isNullable
|
||||||
|
|
||||||
/** Returns an adapter to use when encoding and decoding this property. */
|
/** Returns an adapter to use when encoding and decoding this property. */
|
||||||
fun generateProperty(
|
internal fun generateProperty(
|
||||||
nameAllocator: NameAllocator,
|
nameAllocator: NameAllocator,
|
||||||
typeRenderer: TypeRenderer,
|
typeRenderer: TypeRenderer,
|
||||||
moshiParameter: ParameterSpec,
|
moshiParameter: ParameterSpec,
|
||||||
|
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.api
|
||||||
|
|
||||||
|
/** Internal Moshi code gen APIs. */
|
||||||
|
@MustBeDocumented
|
||||||
|
@Retention(value = AnnotationRetention.BINARY)
|
||||||
|
@RequiresOptIn(
|
||||||
|
level = RequiresOptIn.Level.WARNING,
|
||||||
|
message = "This is an internal API and may change at any time."
|
||||||
|
)
|
||||||
|
public annotation class InternalMoshiCodegenApi
|
@@ -17,7 +17,8 @@ package com.squareup.moshi.kotlin.codegen.api
|
|||||||
|
|
||||||
import com.squareup.kotlinpoet.ClassName
|
import com.squareup.kotlinpoet.ClassName
|
||||||
|
|
||||||
internal object Options {
|
@InternalMoshiCodegenApi
|
||||||
|
public object Options {
|
||||||
/**
|
/**
|
||||||
* This processing option can be specified to have a `@Generated` annotation
|
* This processing option can be specified to have a `@Generated` annotation
|
||||||
* included in the generated code. It is not encouraged unless you need it for static analysis
|
* included in the generated code. It is not encouraged unless you need it for static analysis
|
||||||
@@ -27,14 +28,14 @@ internal object Options {
|
|||||||
* * `"javax.annotation.processing.Generated"` (JRE 9+)
|
* * `"javax.annotation.processing.Generated"` (JRE 9+)
|
||||||
* * `"javax.annotation.Generated"` (JRE <9)
|
* * `"javax.annotation.Generated"` (JRE <9)
|
||||||
*/
|
*/
|
||||||
const val OPTION_GENERATED: String = "moshi.generated"
|
public const val OPTION_GENERATED: String = "moshi.generated"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This boolean processing option can disable proguard rule generation.
|
* This boolean processing option can disable proguard rule generation.
|
||||||
* Normally, this is not recommended unless end-users build their own JsonAdapter look-up tool.
|
* Normally, this is not recommended unless end-users build their own JsonAdapter look-up tool.
|
||||||
* This is enabled by default.
|
* This is enabled by default.
|
||||||
*/
|
*/
|
||||||
const val OPTION_GENERATE_PROGUARD_RULES: String = "moshi.generateProguardRules"
|
public const val OPTION_GENERATE_PROGUARD_RULES: String = "moshi.generateProguardRules"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This boolean processing option controls whether or not Moshi will directly instantiate
|
* This boolean processing option controls whether or not Moshi will directly instantiate
|
||||||
@@ -42,9 +43,9 @@ internal object Options {
|
|||||||
* but can be disabled to restore the legacy behavior of storing annotations on generated adapter
|
* but can be disabled to restore the legacy behavior of storing annotations on generated adapter
|
||||||
* fields and looking them up reflectively.
|
* fields and looking them up reflectively.
|
||||||
*/
|
*/
|
||||||
const val OPTION_INSTANTIATE_ANNOTATIONS: String = "moshi.instantiateAnnotations"
|
public const val OPTION_INSTANTIATE_ANNOTATIONS: String = "moshi.instantiateAnnotations"
|
||||||
|
|
||||||
val POSSIBLE_GENERATED_NAMES = arrayOf(
|
public val POSSIBLE_GENERATED_NAMES: Map<String, ClassName> = arrayOf(
|
||||||
ClassName("javax.annotation.processing", "Generated"),
|
ClassName("javax.annotation.processing", "Generated"),
|
||||||
ClassName("javax.annotation", "Generated")
|
ClassName("javax.annotation", "Generated")
|
||||||
).associateBy { it.canonicalName }
|
).associateBy { it.canonicalName }
|
||||||
|
@@ -29,9 +29,11 @@ import com.squareup.kotlinpoet.ClassName
|
|||||||
* conditioned on usage of the original target type.
|
* conditioned on usage of the original target type.
|
||||||
*
|
*
|
||||||
* To keep this processor as an ISOLATING incremental processor, we generate one file per target
|
* To keep this processor as an ISOLATING incremental processor, we generate one file per target
|
||||||
* class with a deterministic name (see [outputFile]) with an appropriate originating element.
|
* class with a deterministic name (see [outputFilePathWithoutExtension]) with an appropriate
|
||||||
|
* originating element.
|
||||||
*/
|
*/
|
||||||
internal data class ProguardConfig(
|
@InternalMoshiCodegenApi
|
||||||
|
public data class ProguardConfig(
|
||||||
val targetClass: ClassName,
|
val targetClass: ClassName,
|
||||||
val adapterName: String,
|
val adapterName: String,
|
||||||
val adapterConstructorParams: List<String>,
|
val adapterConstructorParams: List<String>,
|
||||||
@@ -39,11 +41,11 @@ internal data class ProguardConfig(
|
|||||||
val targetConstructorParams: List<String>,
|
val targetConstructorParams: List<String>,
|
||||||
val qualifierProperties: Set<QualifierAdapterProperty>
|
val qualifierProperties: Set<QualifierAdapterProperty>
|
||||||
) {
|
) {
|
||||||
fun outputFilePathWithoutExtension(canonicalName: String): String {
|
public fun outputFilePathWithoutExtension(canonicalName: String): String {
|
||||||
return "META-INF/proguard/moshi-$canonicalName"
|
return "META-INF/proguard/moshi-$canonicalName"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeTo(out: Appendable): Unit = out.run {
|
public fun writeTo(out: Appendable): Unit = out.run {
|
||||||
//
|
//
|
||||||
// -if class {the target class}
|
// -if class {the target class}
|
||||||
// -keepnames class {the target class}
|
// -keepnames class {the target class}
|
||||||
@@ -112,4 +114,5 @@ internal data class ProguardConfig(
|
|||||||
* Represents a qualified property with its [name] in the adapter fields and list of [qualifiers]
|
* Represents a qualified property with its [name] in the adapter fields and list of [qualifiers]
|
||||||
* associated with it.
|
* associated with it.
|
||||||
*/
|
*/
|
||||||
internal data class QualifierAdapterProperty(val name: String, val qualifiers: Set<ClassName>)
|
@InternalMoshiCodegenApi
|
||||||
|
public data class QualifierAdapterProperty(val name: String, val qualifiers: Set<ClassName>)
|
||||||
|
@@ -20,21 +20,22 @@ import com.squareup.kotlinpoet.NameAllocator
|
|||||||
import com.squareup.kotlinpoet.PropertySpec
|
import com.squareup.kotlinpoet.PropertySpec
|
||||||
|
|
||||||
/** Generates functions to encode and decode a property as JSON. */
|
/** Generates functions to encode and decode a property as JSON. */
|
||||||
internal class PropertyGenerator(
|
@InternalMoshiCodegenApi
|
||||||
val target: TargetProperty,
|
public class PropertyGenerator(
|
||||||
val delegateKey: DelegateKey,
|
public val target: TargetProperty,
|
||||||
val isTransient: Boolean = false
|
public val delegateKey: DelegateKey,
|
||||||
|
public val isTransient: Boolean = false
|
||||||
) {
|
) {
|
||||||
val name = target.name
|
public val name: String = target.name
|
||||||
val jsonName = target.jsonName ?: target.name
|
public val jsonName: String = target.jsonName ?: target.name
|
||||||
val hasDefault = target.hasDefault
|
public val hasDefault: Boolean = target.hasDefault
|
||||||
|
|
||||||
lateinit var localName: String
|
public lateinit var localName: String
|
||||||
lateinit var localIsPresentName: String
|
public lateinit var localIsPresentName: String
|
||||||
|
|
||||||
val isRequired get() = !delegateKey.nullable && !hasDefault
|
public val isRequired: Boolean get() = !delegateKey.nullable && !hasDefault
|
||||||
|
|
||||||
val hasConstructorParameter get() = target.parameterIndex != -1
|
public val hasConstructorParameter: Boolean get() = target.parameterIndex != -1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IsPresent is required if the following conditions are met:
|
* IsPresent is required if the following conditions are met:
|
||||||
@@ -46,15 +47,15 @@ internal class PropertyGenerator(
|
|||||||
* This is used to indicate that presence should be checked first before possible assigning null
|
* This is used to indicate that presence should be checked first before possible assigning null
|
||||||
* to an absent value
|
* to an absent value
|
||||||
*/
|
*/
|
||||||
val hasLocalIsPresentName = !isTransient && hasDefault && !hasConstructorParameter && delegateKey.nullable
|
public val hasLocalIsPresentName: Boolean = !isTransient && hasDefault && !hasConstructorParameter && delegateKey.nullable
|
||||||
val hasConstructorDefault = hasDefault && hasConstructorParameter
|
public val hasConstructorDefault: Boolean = hasDefault && hasConstructorParameter
|
||||||
|
|
||||||
fun allocateNames(nameAllocator: NameAllocator) {
|
internal fun allocateNames(nameAllocator: NameAllocator) {
|
||||||
localName = nameAllocator.newName(name)
|
localName = nameAllocator.newName(name)
|
||||||
localIsPresentName = nameAllocator.newName("${name}Set")
|
localIsPresentName = nameAllocator.newName("${name}Set")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateLocalProperty(): PropertySpec {
|
internal fun generateLocalProperty(): PropertySpec {
|
||||||
return PropertySpec.builder(localName, target.type.copy(nullable = true))
|
return PropertySpec.builder(localName, target.type.copy(nullable = true))
|
||||||
.mutable(true)
|
.mutable(true)
|
||||||
.apply {
|
.apply {
|
||||||
@@ -70,7 +71,7 @@ internal class PropertyGenerator(
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateLocalIsPresentProperty(): PropertySpec {
|
internal fun generateLocalIsPresentProperty(): PropertySpec {
|
||||||
return PropertySpec.builder(localIsPresentName, BOOLEAN)
|
return PropertySpec.builder(localIsPresentName, BOOLEAN)
|
||||||
.mutable(true)
|
.mutable(true)
|
||||||
.initializer("false")
|
.initializer("false")
|
||||||
|
@@ -18,7 +18,8 @@ package com.squareup.moshi.kotlin.codegen.api
|
|||||||
import com.squareup.kotlinpoet.KModifier
|
import com.squareup.kotlinpoet.KModifier
|
||||||
|
|
||||||
/** A constructor in user code that should be called by generated code. */
|
/** A constructor in user code that should be called by generated code. */
|
||||||
internal data class TargetConstructor(
|
@InternalMoshiCodegenApi
|
||||||
|
public data class TargetConstructor(
|
||||||
val parameters: LinkedHashMap<String, TargetParameter>,
|
val parameters: LinkedHashMap<String, TargetParameter>,
|
||||||
val visibility: KModifier,
|
val visibility: KModifier,
|
||||||
val signature: String?
|
val signature: String?
|
||||||
|
@@ -19,7 +19,8 @@ import com.squareup.kotlinpoet.AnnotationSpec
|
|||||||
import com.squareup.kotlinpoet.TypeName
|
import com.squareup.kotlinpoet.TypeName
|
||||||
|
|
||||||
/** A parameter in user code that should be populated by generated code. */
|
/** A parameter in user code that should be populated by generated code. */
|
||||||
internal data class TargetParameter(
|
@InternalMoshiCodegenApi
|
||||||
|
public data class TargetParameter(
|
||||||
val name: String,
|
val name: String,
|
||||||
val index: Int,
|
val index: Int,
|
||||||
val type: TypeName,
|
val type: TypeName,
|
||||||
|
@@ -20,7 +20,8 @@ import com.squareup.kotlinpoet.PropertySpec
|
|||||||
import com.squareup.kotlinpoet.TypeName
|
import com.squareup.kotlinpoet.TypeName
|
||||||
|
|
||||||
/** A property in user code that maps to JSON. */
|
/** A property in user code that maps to JSON. */
|
||||||
internal data class TargetProperty(
|
@InternalMoshiCodegenApi
|
||||||
|
public data class TargetProperty(
|
||||||
val propertySpec: PropertySpec,
|
val propertySpec: PropertySpec,
|
||||||
val parameter: TargetParameter?,
|
val parameter: TargetParameter?,
|
||||||
val visibility: KModifier,
|
val visibility: KModifier,
|
||||||
@@ -28,8 +29,8 @@ internal data class TargetProperty(
|
|||||||
) {
|
) {
|
||||||
val name: String get() = propertySpec.name
|
val name: String get() = propertySpec.name
|
||||||
val type: TypeName get() = propertySpec.type
|
val type: TypeName get() = propertySpec.type
|
||||||
val parameterIndex get() = parameter?.index ?: -1
|
val parameterIndex: Int get() = parameter?.index ?: -1
|
||||||
val hasDefault get() = parameter?.hasDefault ?: true
|
val hasDefault: Boolean get() = parameter?.hasDefault ?: true
|
||||||
|
|
||||||
override fun toString() = name
|
override fun toString(): String = name
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,8 @@ import com.squareup.kotlinpoet.TypeName
|
|||||||
import com.squareup.kotlinpoet.TypeVariableName
|
import com.squareup.kotlinpoet.TypeVariableName
|
||||||
|
|
||||||
/** A user type that should be decoded and encoded by generated code. */
|
/** A user type that should be decoded and encoded by generated code. */
|
||||||
internal data class TargetType(
|
@InternalMoshiCodegenApi
|
||||||
|
public data class TargetType(
|
||||||
val typeName: TypeName,
|
val typeName: TypeName,
|
||||||
val constructor: TargetConstructor,
|
val constructor: TargetConstructor,
|
||||||
val properties: Map<String, TargetProperty>,
|
val properties: Map<String, TargetProperty>,
|
||||||
|
Reference in New Issue
Block a user