Switch from internal to experimental internal annotation (#1410)

This commit is contained in:
Zac Sweers
2021-10-30 12:15:08 -04:00
committed by GitHub
parent 313683fa98
commit c288ad6133
11 changed files with 78 additions and 40 deletions

View File

@@ -32,6 +32,7 @@ tasks.withType<KotlinCompile>().configureEach {
"-Xopt-in=kotlin.RequiresOptIn",
"-Xopt-in=com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview",
"-Xopt-in=com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview",
"-Xopt-in=com.squareup.moshi.kotlin.codegen.api.InternalMoshiCodegenApi",
)
}
}

View File

@@ -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
/** Generates a JSON adapter for a target type. */
internal class AdapterGenerator(
@InternalMoshiCodegenApi
public class AdapterGenerator(
private val target: TargetType,
private val propertyList: List<PropertyGenerator>
) {
companion object {
private companion object {
private val INT_TYPE_BLOCK = CodeBlock.of("%T::class.javaPrimitiveType", INT)
private val DEFAULT_CONSTRUCTOR_MARKER_TYPE_BLOCK = CodeBlock.of(
"%T.DEFAULT_CONSTRUCTOR_MARKER",
@@ -166,7 +167,7 @@ internal class AdapterGenerator(
.initializer("null")
.build()
fun prepare(generateProguardRules: Boolean, typeHook: (TypeSpec) -> TypeSpec = { it }): PreparedAdapter {
public fun prepare(generateProguardRules: Boolean, typeHook: (TypeSpec) -> TypeSpec = { it }): PreparedAdapter {
val reservedSimpleNames = mutableSetOf<String>()
for (property in nonTransientProperties) {
// 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]. */
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 {
return when (this) {

View File

@@ -36,15 +36,16 @@ import com.squareup.moshi.Types
import java.util.Locale
/** 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 jsonQualifiers: List<AnnotationSpec>,
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. */
fun generateProperty(
internal fun generateProperty(
nameAllocator: NameAllocator,
typeRenderer: TypeRenderer,
moshiParameter: ParameterSpec,

View File

@@ -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

View File

@@ -17,7 +17,8 @@ package com.squareup.moshi.kotlin.codegen.api
import com.squareup.kotlinpoet.ClassName
internal object Options {
@InternalMoshiCodegenApi
public object Options {
/**
* 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
@@ -27,14 +28,14 @@ internal object Options {
* * `"javax.annotation.processing.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.
* Normally, this is not recommended unless end-users build their own JsonAdapter look-up tool.
* 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
@@ -42,9 +43,9 @@ internal object Options {
* but can be disabled to restore the legacy behavior of storing annotations on generated adapter
* 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", "Generated")
).associateBy { it.canonicalName }

View File

@@ -29,9 +29,11 @@ import com.squareup.kotlinpoet.ClassName
* conditioned on usage of the original target type.
*
* 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 adapterName: String,
val adapterConstructorParams: List<String>,
@@ -39,11 +41,11 @@ internal data class ProguardConfig(
val targetConstructorParams: List<String>,
val qualifierProperties: Set<QualifierAdapterProperty>
) {
fun outputFilePathWithoutExtension(canonicalName: String): String {
public fun outputFilePathWithoutExtension(canonicalName: String): String {
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}
// -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]
* 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>)

View File

@@ -20,21 +20,22 @@ import com.squareup.kotlinpoet.NameAllocator
import com.squareup.kotlinpoet.PropertySpec
/** Generates functions to encode and decode a property as JSON. */
internal class PropertyGenerator(
val target: TargetProperty,
val delegateKey: DelegateKey,
val isTransient: Boolean = false
@InternalMoshiCodegenApi
public class PropertyGenerator(
public val target: TargetProperty,
public val delegateKey: DelegateKey,
public val isTransient: Boolean = false
) {
val name = target.name
val jsonName = target.jsonName ?: target.name
val hasDefault = target.hasDefault
public val name: String = target.name
public val jsonName: String = target.jsonName ?: target.name
public val hasDefault: Boolean = target.hasDefault
lateinit var localName: String
lateinit var localIsPresentName: String
public lateinit var localName: 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:
@@ -46,15 +47,15 @@ internal class PropertyGenerator(
* This is used to indicate that presence should be checked first before possible assigning null
* to an absent value
*/
val hasLocalIsPresentName = !isTransient && hasDefault && !hasConstructorParameter && delegateKey.nullable
val hasConstructorDefault = hasDefault && hasConstructorParameter
public val hasLocalIsPresentName: Boolean = !isTransient && hasDefault && !hasConstructorParameter && delegateKey.nullable
public val hasConstructorDefault: Boolean = hasDefault && hasConstructorParameter
fun allocateNames(nameAllocator: NameAllocator) {
internal fun allocateNames(nameAllocator: NameAllocator) {
localName = nameAllocator.newName(name)
localIsPresentName = nameAllocator.newName("${name}Set")
}
fun generateLocalProperty(): PropertySpec {
internal fun generateLocalProperty(): PropertySpec {
return PropertySpec.builder(localName, target.type.copy(nullable = true))
.mutable(true)
.apply {
@@ -70,7 +71,7 @@ internal class PropertyGenerator(
.build()
}
fun generateLocalIsPresentProperty(): PropertySpec {
internal fun generateLocalIsPresentProperty(): PropertySpec {
return PropertySpec.builder(localIsPresentName, BOOLEAN)
.mutable(true)
.initializer("false")

View File

@@ -18,7 +18,8 @@ package com.squareup.moshi.kotlin.codegen.api
import com.squareup.kotlinpoet.KModifier
/** 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 visibility: KModifier,
val signature: String?

View File

@@ -19,7 +19,8 @@ import com.squareup.kotlinpoet.AnnotationSpec
import com.squareup.kotlinpoet.TypeName
/** 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 index: Int,
val type: TypeName,

View File

@@ -20,7 +20,8 @@ import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeName
/** A property in user code that maps to JSON. */
internal data class TargetProperty(
@InternalMoshiCodegenApi
public data class TargetProperty(
val propertySpec: PropertySpec,
val parameter: TargetParameter?,
val visibility: KModifier,
@@ -28,8 +29,8 @@ internal data class TargetProperty(
) {
val name: String get() = propertySpec.name
val type: TypeName get() = propertySpec.type
val parameterIndex get() = parameter?.index ?: -1
val hasDefault get() = parameter?.hasDefault ?: true
val parameterIndex: Int get() = parameter?.index ?: -1
val hasDefault: Boolean get() = parameter?.hasDefault ?: true
override fun toString() = name
override fun toString(): String = name
}

View File

@@ -20,7 +20,8 @@ import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.TypeVariableName
/** 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 constructor: TargetConstructor,
val properties: Map<String, TargetProperty>,