mirror of
https://github.com/fankes/moshi.git
synced 2025-10-20 00:19:21 +08:00
* Rename to unwrapTypeAliasInternal + simplify * Move down isAnyNullable * Make dynamic explicit * Clean up supertypes doc and filtering * Switch to invoke extensions * Just best guess the annotation * Clean up redundant sequence and use a regular loop * element -> type * supertypes -> superclasses * Spotless * Fix copyright * Add multiple messages check * Link issue Co-authored-by: Jesse Wilson <jesse@swank.ca>
This commit is contained in:
@@ -17,6 +17,7 @@ package com.squareup.moshi.kotlin.codegen.api
|
|||||||
|
|
||||||
import com.squareup.kotlinpoet.AnnotationSpec
|
import com.squareup.kotlinpoet.AnnotationSpec
|
||||||
import com.squareup.kotlinpoet.ClassName
|
import com.squareup.kotlinpoet.ClassName
|
||||||
|
import com.squareup.kotlinpoet.Dynamic
|
||||||
import com.squareup.kotlinpoet.LambdaTypeName
|
import com.squareup.kotlinpoet.LambdaTypeName
|
||||||
import com.squareup.kotlinpoet.ParameterizedTypeName
|
import com.squareup.kotlinpoet.ParameterizedTypeName
|
||||||
import com.squareup.kotlinpoet.TypeName
|
import com.squareup.kotlinpoet.TypeName
|
||||||
@@ -26,52 +27,35 @@ import com.squareup.kotlinpoet.tag
|
|||||||
import com.squareup.kotlinpoet.tags.TypeAliasTag
|
import com.squareup.kotlinpoet.tags.TypeAliasTag
|
||||||
import java.util.TreeSet
|
import java.util.TreeSet
|
||||||
|
|
||||||
internal fun TypeName.unwrapTypeAliasReal(): TypeName {
|
private fun TypeName.unwrapTypeAliasInternal(): TypeName? {
|
||||||
return tag<TypeAliasTag>()?.abbreviatedType?.let { unwrappedType ->
|
return tag<TypeAliasTag>()?.abbreviatedType?.let { unwrappedType ->
|
||||||
// If any type is nullable, then the whole thing is nullable
|
|
||||||
var isAnyNullable = isNullable
|
|
||||||
// Keep track of all annotations across type levels. Sort them too for consistency.
|
// Keep track of all annotations across type levels. Sort them too for consistency.
|
||||||
val runningAnnotations = TreeSet<AnnotationSpec>(compareBy { it.toString() }).apply {
|
val runningAnnotations = TreeSet<AnnotationSpec>(compareBy { it.toString() }).apply {
|
||||||
addAll(annotations)
|
addAll(annotations)
|
||||||
}
|
}
|
||||||
val nestedUnwrappedType = unwrappedType.unwrapTypeAlias()
|
val nestedUnwrappedType = unwrappedType.unwrapTypeAlias()
|
||||||
runningAnnotations.addAll(nestedUnwrappedType.annotations)
|
runningAnnotations.addAll(nestedUnwrappedType.annotations)
|
||||||
isAnyNullable = isAnyNullable || nestedUnwrappedType.isNullable
|
// If any type is nullable, then the whole thing is nullable
|
||||||
|
val isAnyNullable = isNullable || nestedUnwrappedType.isNullable
|
||||||
nestedUnwrappedType.copy(nullable = isAnyNullable, annotations = runningAnnotations.toList())
|
nestedUnwrappedType.copy(nullable = isAnyNullable, annotations = runningAnnotations.toList())
|
||||||
} ?: this
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun TypeName.unwrapTypeAlias(): TypeName {
|
internal fun TypeName.unwrapTypeAlias(): TypeName {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ClassName -> unwrapTypeAliasReal()
|
is ClassName -> unwrapTypeAliasInternal() ?: this
|
||||||
is ParameterizedTypeName -> {
|
is ParameterizedTypeName -> {
|
||||||
if (TypeAliasTag::class in tags) {
|
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
||||||
unwrapTypeAliasReal()
|
|
||||||
} else {
|
|
||||||
deepCopy(TypeName::unwrapTypeAlias)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is TypeVariableName -> {
|
is TypeVariableName -> {
|
||||||
if (TypeAliasTag::class in tags) {
|
unwrapTypeAliasInternal() ?: deepCopy(transform = TypeName::unwrapTypeAlias)
|
||||||
unwrapTypeAliasReal()
|
|
||||||
} else {
|
|
||||||
deepCopy(transform = TypeName::unwrapTypeAlias)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is WildcardTypeName -> {
|
is WildcardTypeName -> {
|
||||||
if (TypeAliasTag::class in tags) {
|
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
||||||
unwrapTypeAliasReal()
|
|
||||||
} else {
|
|
||||||
deepCopy(TypeName::unwrapTypeAlias)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is LambdaTypeName -> {
|
is LambdaTypeName -> {
|
||||||
if (TypeAliasTag::class in tags) {
|
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
||||||
unwrapTypeAliasReal()
|
|
||||||
} else {
|
|
||||||
deepCopy(TypeName::unwrapTypeAlias)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> throw UnsupportedOperationException("Type '${javaClass.simpleName}' is illegal. Only classes, parameterized types, wildcard types, or type variables are allowed.")
|
Dynamic -> throw UnsupportedOperationException("Type '${javaClass.simpleName}' is illegal. Only classes, parameterized types, wildcard types, or type variables are allowed.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,10 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package com.squareup.moshi.kotlin.codegen.apt
|
package com.squareup.moshi.kotlin.codegen.apt
|
||||||
|
|
||||||
|
import com.squareup.kotlinpoet.ClassName
|
||||||
|
import com.squareup.kotlinpoet.DelicateKotlinPoetApi
|
||||||
|
import com.squareup.kotlinpoet.asClassName
|
||||||
|
import javax.lang.model.element.ElementKind.CLASS
|
||||||
import javax.lang.model.element.TypeElement
|
import javax.lang.model.element.TypeElement
|
||||||
import javax.lang.model.type.DeclaredType
|
import javax.lang.model.type.DeclaredType
|
||||||
import javax.lang.model.util.Types
|
import javax.lang.model.util.Types
|
||||||
|
|
||||||
|
private val OBJECT_CLASS = ClassName("java.lang", "Object")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A concrete type like `List<String>` with enough information to know how to resolve its type
|
* A concrete type like `List<String>` with enough information to know how to resolve its type
|
||||||
* variables.
|
* variables.
|
||||||
@@ -27,8 +33,9 @@ internal class AppliedType private constructor(
|
|||||||
val element: TypeElement,
|
val element: TypeElement,
|
||||||
private val mirror: DeclaredType
|
private val mirror: DeclaredType
|
||||||
) {
|
) {
|
||||||
/** Returns all supertypes of this, recursively. Includes both interface and class supertypes. */
|
/** Returns all supertypes of this, recursively. Only [CLASS] is used as we can't really use other types. */
|
||||||
fun supertypes(
|
@OptIn(DelicateKotlinPoetApi::class)
|
||||||
|
fun superclasses(
|
||||||
types: Types,
|
types: Types,
|
||||||
result: LinkedHashSet<AppliedType> = LinkedHashSet()
|
result: LinkedHashSet<AppliedType> = LinkedHashSet()
|
||||||
): LinkedHashSet<AppliedType> {
|
): LinkedHashSet<AppliedType> {
|
||||||
@@ -36,8 +43,14 @@ internal class AppliedType private constructor(
|
|||||||
for (supertype in types.directSupertypes(mirror)) {
|
for (supertype in types.directSupertypes(mirror)) {
|
||||||
val supertypeDeclaredType = supertype as DeclaredType
|
val supertypeDeclaredType = supertype as DeclaredType
|
||||||
val supertypeElement = supertypeDeclaredType.asElement() as TypeElement
|
val supertypeElement = supertypeDeclaredType.asElement() as TypeElement
|
||||||
val appliedSupertype = AppliedType(supertypeElement, supertypeDeclaredType)
|
if (supertypeElement.kind != CLASS) {
|
||||||
appliedSupertype.supertypes(types, result)
|
continue
|
||||||
|
} else if (supertypeElement.asClassName() == OBJECT_CLASS) {
|
||||||
|
// Don't load properties for java.lang.Object.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val appliedSuperclass = AppliedType(supertypeElement, supertypeDeclaredType)
|
||||||
|
appliedSuperclass.superclasses(types, result)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -45,7 +58,7 @@ internal class AppliedType private constructor(
|
|||||||
override fun toString() = mirror.toString()
|
override fun toString() = mirror.toString()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun get(typeElement: TypeElement): AppliedType {
|
operator fun invoke(typeElement: TypeElement): AppliedType {
|
||||||
return AppliedType(typeElement, typeElement.asType() as DeclaredType)
|
return AppliedType(typeElement, typeElement.asType() as DeclaredType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -52,7 +52,6 @@ import java.lang.annotation.RetentionPolicy
|
|||||||
import javax.annotation.processing.Messager
|
import javax.annotation.processing.Messager
|
||||||
import javax.lang.model.element.AnnotationMirror
|
import javax.lang.model.element.AnnotationMirror
|
||||||
import javax.lang.model.element.Element
|
import javax.lang.model.element.Element
|
||||||
import javax.lang.model.element.ElementKind
|
|
||||||
import javax.lang.model.element.TypeElement
|
import javax.lang.model.element.TypeElement
|
||||||
import javax.lang.model.type.DeclaredType
|
import javax.lang.model.type.DeclaredType
|
||||||
import javax.lang.model.util.Elements
|
import javax.lang.model.util.Elements
|
||||||
@@ -63,7 +62,6 @@ import javax.tools.Diagnostic.Kind.WARNING
|
|||||||
private val JSON_QUALIFIER = JsonQualifier::class.java
|
private val JSON_QUALIFIER = JsonQualifier::class.java
|
||||||
private val JSON = Json::class.asClassName()
|
private val JSON = Json::class.asClassName()
|
||||||
private val TRANSIENT = Transient::class.asClassName()
|
private val TRANSIENT = Transient::class.asClassName()
|
||||||
private val OBJECT_CLASS = ClassName("java.lang", "Object")
|
|
||||||
private val VISIBILITY_MODIFIERS = setOf(
|
private val VISIBILITY_MODIFIERS = setOf(
|
||||||
KModifier.INTERNAL,
|
KModifier.INTERNAL,
|
||||||
KModifier.PRIVATE,
|
KModifier.PRIVATE,
|
||||||
@@ -206,7 +204,7 @@ internal fun targetType(
|
|||||||
|
|
||||||
val kotlinApi = cachedClassInspector.toTypeSpec(kmClass)
|
val kotlinApi = cachedClassInspector.toTypeSpec(kmClass)
|
||||||
val typeVariables = kotlinApi.typeVariables
|
val typeVariables = kotlinApi.typeVariables
|
||||||
val appliedType = AppliedType.get(element)
|
val appliedType = AppliedType(element)
|
||||||
|
|
||||||
val constructor = primaryConstructor(element, kotlinApi, elements, messager)
|
val constructor = primaryConstructor(element, kotlinApi, elements, messager)
|
||||||
if (constructor == null) {
|
if (constructor == null) {
|
||||||
@@ -230,28 +228,24 @@ internal fun targetType(
|
|||||||
val properties = mutableMapOf<String, TargetProperty>()
|
val properties = mutableMapOf<String, TargetProperty>()
|
||||||
|
|
||||||
val resolvedTypes = mutableListOf<ResolvedTypeMapping>()
|
val resolvedTypes = mutableListOf<ResolvedTypeMapping>()
|
||||||
val superTypes = appliedType.supertypes(types)
|
val superclass = appliedType.superclasses(types)
|
||||||
.filterNot { supertype ->
|
.onEach { superclass ->
|
||||||
supertype.element.asClassName() == OBJECT_CLASS || // Don't load properties for java.lang.Object.
|
if (superclass.element.getAnnotation(Metadata::class.java) == null) {
|
||||||
supertype.element.kind != ElementKind.CLASS // Don't load properties for interface types.
|
|
||||||
}
|
|
||||||
.onEach { supertype ->
|
|
||||||
if (supertype.element.getAnnotation(Metadata::class.java) == null) {
|
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
ERROR,
|
ERROR,
|
||||||
"@JsonClass can't be applied to $element: supertype $supertype is not a Kotlin type",
|
"@JsonClass can't be applied to $element: supertype $superclass is not a Kotlin type",
|
||||||
element
|
element
|
||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.associateWithTo(LinkedHashMap()) { supertype ->
|
.associateWithTo(LinkedHashMap()) { superclass ->
|
||||||
// Load the kotlin API cache into memory eagerly so we can reuse the parsed APIs
|
// Load the kotlin API cache into memory eagerly so we can reuse the parsed APIs
|
||||||
val api = if (supertype.element == element) {
|
val api = if (superclass.element == element) {
|
||||||
// We've already parsed this api above, reuse it
|
// We've already parsed this api above, reuse it
|
||||||
kotlinApi
|
kotlinApi
|
||||||
} else {
|
} else {
|
||||||
cachedClassInspector.toTypeSpec(supertype.element)
|
cachedClassInspector.toTypeSpec(superclass.element)
|
||||||
}
|
}
|
||||||
|
|
||||||
val apiSuperClass = api.superclass
|
val apiSuperClass = api.superclass
|
||||||
@@ -268,7 +262,7 @@ internal fun targetType(
|
|||||||
// Then when we look at Bar<T> later, we'll look up to the descendent Foo and extract its
|
// Then when we look at Bar<T> later, we'll look up to the descendent Foo and extract its
|
||||||
// materialized type from there.
|
// materialized type from there.
|
||||||
//
|
//
|
||||||
val superSuperClass = supertype.element.superclass as DeclaredType
|
val superSuperClass = superclass.element.superclass as DeclaredType
|
||||||
|
|
||||||
// Convert to an element and back to wipe the typed generics off of this
|
// Convert to an element and back to wipe the typed generics off of this
|
||||||
val untyped = superSuperClass.asElement().asType().asTypeName() as ParameterizedTypeName
|
val untyped = superSuperClass.asElement().asType().asTypeName() as ParameterizedTypeName
|
||||||
@@ -285,7 +279,7 @@ internal fun targetType(
|
|||||||
return@associateWithTo api
|
return@associateWithTo api
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((localAppliedType, supertypeApi) in superTypes.entries) {
|
for ((localAppliedType, supertypeApi) in superclass.entries) {
|
||||||
val appliedClassName = localAppliedType.element.asClassName()
|
val appliedClassName = localAppliedType.element.asClassName()
|
||||||
val supertypeProperties = declaredProperties(
|
val supertypeProperties = declaredProperties(
|
||||||
constructor = constructor,
|
constructor = constructor,
|
||||||
|
@@ -35,8 +35,8 @@ internal class AppliedType private constructor(
|
|||||||
val typeName: TypeName = type.toClassName()
|
val typeName: TypeName = type.toClassName()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/** Returns all supertypes of this, recursively. Includes both interface and class supertypes. */
|
/** Returns all super classes of this, recursively. Only [CLASS] is used as we can't really use other types. */
|
||||||
fun supertypes(
|
fun superclasses(
|
||||||
resolver: Resolver,
|
resolver: Resolver,
|
||||||
): LinkedHashSet<AppliedType> {
|
): LinkedHashSet<AppliedType> {
|
||||||
val result: LinkedHashSet<AppliedType> = LinkedHashSet()
|
val result: LinkedHashSet<AppliedType> = LinkedHashSet()
|
||||||
@@ -63,7 +63,7 @@ internal class AppliedType private constructor(
|
|||||||
override fun toString() = type.qualifiedName!!.asString()
|
override fun toString() = type.qualifiedName!!.asString()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun get(type: KSClassDeclaration): AppliedType {
|
operator fun invoke(type: KSClassDeclaration): AppliedType {
|
||||||
return AppliedType(type)
|
return AppliedType(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,8 +27,8 @@ import com.google.devtools.ksp.symbol.KSAnnotated
|
|||||||
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.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
|
||||||
@@ -66,54 +66,47 @@ private class JsonClassSymbolProcessor(
|
|||||||
|
|
||||||
override fun process(resolver: Resolver): List<KSAnnotated> {
|
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||||
val generatedAnnotation = generatedOption?.let {
|
val generatedAnnotation = generatedOption?.let {
|
||||||
val annotationType = resolver.getClassDeclarationByName(resolver.getKSNameFromString(it))
|
AnnotationSpec.builder(ClassName.bestGuess(it))
|
||||||
?: run {
|
|
||||||
logger.error("Generated annotation type doesn't exist: $it")
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
AnnotationSpec.builder(annotationType.toClassName())
|
|
||||||
.addMember("value = [%S]", JsonClassSymbolProcessor::class.java.canonicalName)
|
.addMember("value = [%S]", JsonClassSymbolProcessor::class.java.canonicalName)
|
||||||
.addMember("comments = %S", "https://github.com/square/moshi")
|
.addMember("comments = %S", "https://github.com/square/moshi")
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
resolver.getSymbolsWithAnnotation(JSON_CLASS_NAME)
|
for (type in resolver.getSymbolsWithAnnotation(JSON_CLASS_NAME)) {
|
||||||
.asSequence()
|
// For the smart cast
|
||||||
.forEach { type ->
|
if (type !is KSDeclaration) {
|
||||||
// For the smart cast
|
logger.error("@JsonClass can't be applied to $type: must be a Kotlin class", type)
|
||||||
if (type !is KSDeclaration) {
|
continue
|
||||||
logger.error("@JsonClass can't be applied to $type: must be a Kotlin class", type)
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
|
|
||||||
val jsonClassAnnotation = type.findAnnotationWithType<JsonClass>() ?: return@forEach
|
|
||||||
|
|
||||||
val generator = jsonClassAnnotation.generator
|
|
||||||
|
|
||||||
if (generator.isNotEmpty()) return@forEach
|
|
||||||
|
|
||||||
if (!jsonClassAnnotation.generateAdapter) return@forEach
|
|
||||||
|
|
||||||
val originatingFile = type.containingFile!!
|
|
||||||
val adapterGenerator = adapterGenerator(logger, resolver, type) ?: return emptyList()
|
|
||||||
try {
|
|
||||||
val preparedAdapter = adapterGenerator
|
|
||||||
.prepare(generateProguardRules) { spec ->
|
|
||||||
spec.toBuilder()
|
|
||||||
.apply {
|
|
||||||
generatedAnnotation?.let(::addAnnotation)
|
|
||||||
}
|
|
||||||
.addOriginatingKSFile(originatingFile)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
preparedAdapter.spec.writeTo(codeGenerator, aggregating = false)
|
|
||||||
preparedAdapter.proguardConfig?.writeTo(codeGenerator, originatingFile)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.error(
|
|
||||||
"Error preparing ${type.simpleName.asString()}: ${e.stackTrace.joinToString("\n")}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val jsonClassAnnotation = type.findAnnotationWithType<JsonClass>() ?: continue
|
||||||
|
|
||||||
|
val generator = jsonClassAnnotation.generator
|
||||||
|
|
||||||
|
if (generator.isNotEmpty()) continue
|
||||||
|
|
||||||
|
if (!jsonClassAnnotation.generateAdapter) continue
|
||||||
|
|
||||||
|
val originatingFile = type.containingFile!!
|
||||||
|
val adapterGenerator = adapterGenerator(logger, resolver, type) ?: return emptyList()
|
||||||
|
try {
|
||||||
|
val preparedAdapter = adapterGenerator
|
||||||
|
.prepare(generateProguardRules) { spec ->
|
||||||
|
spec.toBuilder()
|
||||||
|
.apply {
|
||||||
|
generatedAnnotation?.let(::addAnnotation)
|
||||||
|
}
|
||||||
|
.addOriginatingKSFile(originatingFile)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
preparedAdapter.spec.writeTo(codeGenerator, aggregating = false)
|
||||||
|
preparedAdapter.proguardConfig?.writeTo(codeGenerator, originatingFile)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error(
|
||||||
|
"Error preparing ${type.simpleName.asString()}: ${e.stackTrace.joinToString("\n")}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,7 +53,7 @@ import com.squareup.moshi.kotlin.codegen.api.TargetProperty
|
|||||||
import com.squareup.moshi.kotlin.codegen.api.TargetType
|
import com.squareup.moshi.kotlin.codegen.api.TargetType
|
||||||
import com.squareup.moshi.kotlin.codegen.api.unwrapTypeAlias
|
import com.squareup.moshi.kotlin.codegen.api.unwrapTypeAlias
|
||||||
|
|
||||||
/** Returns a target type for `element`, or null if it cannot be used with code gen. */
|
/** Returns a target type for [type] or null if it cannot be used with code gen. */
|
||||||
internal fun targetType(
|
internal fun targetType(
|
||||||
type: KSDeclaration,
|
type: KSDeclaration,
|
||||||
resolver: Resolver,
|
resolver: Resolver,
|
||||||
@@ -89,7 +89,7 @@ internal fun targetType(
|
|||||||
sourceTypeHint = type.qualifiedName!!.asString()
|
sourceTypeHint = type.qualifiedName!!.asString()
|
||||||
)
|
)
|
||||||
val typeVariables = type.typeParameters.map { it.toTypeVariableName(classTypeParamsResolver) }
|
val typeVariables = type.typeParameters.map { it.toTypeVariableName(classTypeParamsResolver) }
|
||||||
val appliedType = AppliedType.get(type)
|
val appliedType = AppliedType(type)
|
||||||
|
|
||||||
val constructor = primaryConstructor(resolver, type, classTypeParamsResolver, logger)
|
val constructor = primaryConstructor(resolver, type, classTypeParamsResolver, logger)
|
||||||
?: run {
|
?: run {
|
||||||
@@ -108,12 +108,12 @@ internal fun targetType(
|
|||||||
val properties = mutableMapOf<String, TargetProperty>()
|
val properties = mutableMapOf<String, TargetProperty>()
|
||||||
|
|
||||||
val originalType = appliedType.type
|
val originalType = appliedType.type
|
||||||
for (supertype in appliedType.supertypes(resolver)) {
|
for (superclass in appliedType.superclasses(resolver)) {
|
||||||
val classDecl = supertype.type
|
val classDecl = superclass.type
|
||||||
if (!classDecl.isKotlinClass()) {
|
if (!classDecl.isKotlinClass()) {
|
||||||
logger.error(
|
logger.error(
|
||||||
"""
|
"""
|
||||||
@JsonClass can't be applied to $type: supertype $supertype is not a Kotlin type.
|
@JsonClass can't be applied to $type: supertype $superclass is not a Kotlin type.
|
||||||
Origin=${classDecl.origin}
|
Origin=${classDecl.origin}
|
||||||
Annotations=${classDecl.annotations.joinToString(prefix = "[", postfix = "]") { it.shortName.getShortName() }}
|
Annotations=${classDecl.annotations.joinToString(prefix = "[", postfix = "]") { it.shortName.getShortName() }}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
|
@@ -430,8 +430,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
)
|
)
|
||||||
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
|
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
|
||||||
assertThat(result.messages).contains("property a is not visible")
|
assertThat(result.messages).contains("property a is not visible")
|
||||||
// TODO we throw eagerly currently and don't collect
|
assertThat(result.messages).contains("property c is not visible")
|
||||||
// assertThat(result.messages).contains("property c is not visible")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@@ -257,7 +257,7 @@ class DualKotlinTest {
|
|||||||
val result = adapter.fromJson(testJson)!!
|
val result = adapter.fromJson(testJson)!!
|
||||||
assertThat(result.i).isEqualTo(6)
|
assertThat(result.i).isEqualTo(6)
|
||||||
|
|
||||||
// TODO doesn't work yet.
|
// TODO doesn't work yet. https://github.com/square/moshi/issues/1170
|
||||||
// need to invoke the constructor_impl$default static method, invoke constructor with result
|
// need to invoke the constructor_impl$default static method, invoke constructor with result
|
||||||
// val testEmptyJson =
|
// val testEmptyJson =
|
||||||
// """{}"""
|
// """{}"""
|
||||||
|
Reference in New Issue
Block a user