mirror of
https://github.com/fankes/moshi.git
synced 2025-10-18 23:49:21 +08:00
Update dependency com.pinterest.ktlint:ktlint-cli to v1.2.0 (#1814)
* Update dependency com.pinterest.ktlint:ktlint-cli to v1.2.0 * Appease ktlint --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jake Wharton <jw@squareup.com>
This commit is contained in:
@@ -37,4 +37,4 @@ kotlinCompileTesting = { module = "dev.zacsweers.kctfork:core", version.ref = "k
|
|||||||
kotlinCompileTesting-ksp = { module = "dev.zacsweers.kctfork:ksp", version.ref ="kotlinCompileTesting" }
|
kotlinCompileTesting-ksp = { module = "dev.zacsweers.kctfork:ksp", version.ref ="kotlinCompileTesting" }
|
||||||
truth = "com.google.truth:truth:1.4.1"
|
truth = "com.google.truth:truth:1.4.1"
|
||||||
googleJavaFormat = "com.google.googlejavaformat:google-java-format:1.20.0"
|
googleJavaFormat = "com.google.googlejavaformat:google-java-format:1.20.0"
|
||||||
ktlint = "com.pinterest.ktlint:ktlint-cli:1.1.1"
|
ktlint = "com.pinterest.ktlint:ktlint-cli:1.2.0"
|
||||||
|
@@ -200,7 +200,9 @@ public class AdapterGenerator(
|
|||||||
private fun TypeSpec.createProguardRule(): ProguardConfig {
|
private fun TypeSpec.createProguardRule(): ProguardConfig {
|
||||||
val adapterConstructorParams = when (requireNotNull(primaryConstructor).parameters.size) {
|
val adapterConstructorParams = when (requireNotNull(primaryConstructor).parameters.size) {
|
||||||
1 -> listOf(CN_MOSHI.reflectionName())
|
1 -> listOf(CN_MOSHI.reflectionName())
|
||||||
|
|
||||||
2 -> listOf(CN_MOSHI.reflectionName(), "${CN_TYPE.reflectionName()}[]")
|
2 -> listOf(CN_MOSHI.reflectionName(), "${CN_TYPE.reflectionName()}[]")
|
||||||
|
|
||||||
// Should never happen
|
// Should never happen
|
||||||
else -> error("Unexpected number of arguments on primary constructor: $primaryConstructor")
|
else -> error("Unexpected number of arguments on primary constructor: $primaryConstructor")
|
||||||
}
|
}
|
||||||
@@ -726,16 +728,26 @@ public data class PreparedAdapter(val spec: FileSpec, val proguardConfig: Progua
|
|||||||
private fun AsmType.toReflectionString(): String {
|
private fun AsmType.toReflectionString(): String {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
AsmType.VOID_TYPE -> "void"
|
AsmType.VOID_TYPE -> "void"
|
||||||
|
|
||||||
AsmType.BOOLEAN_TYPE -> "boolean"
|
AsmType.BOOLEAN_TYPE -> "boolean"
|
||||||
|
|
||||||
AsmType.CHAR_TYPE -> "char"
|
AsmType.CHAR_TYPE -> "char"
|
||||||
|
|
||||||
AsmType.BYTE_TYPE -> "byte"
|
AsmType.BYTE_TYPE -> "byte"
|
||||||
|
|
||||||
AsmType.SHORT_TYPE -> "short"
|
AsmType.SHORT_TYPE -> "short"
|
||||||
|
|
||||||
AsmType.INT_TYPE -> "int"
|
AsmType.INT_TYPE -> "int"
|
||||||
|
|
||||||
AsmType.FLOAT_TYPE -> "float"
|
AsmType.FLOAT_TYPE -> "float"
|
||||||
|
|
||||||
AsmType.LONG_TYPE -> "long"
|
AsmType.LONG_TYPE -> "long"
|
||||||
|
|
||||||
AsmType.DOUBLE_TYPE -> "double"
|
AsmType.DOUBLE_TYPE -> "double"
|
||||||
|
|
||||||
else -> when (sort) {
|
else -> when (sort) {
|
||||||
AsmType.ARRAY -> "${elementType.toReflectionString()}[]"
|
AsmType.ARRAY -> "${elementType.toReflectionString()}[]"
|
||||||
|
|
||||||
// Object type
|
// Object type
|
||||||
else -> className
|
else -> className
|
||||||
}
|
}
|
||||||
|
@@ -64,6 +64,7 @@ public data class DelegateKey(
|
|||||||
|
|
||||||
val (initializerString, args) = when {
|
val (initializerString, args) = when {
|
||||||
jsonQualifiers.isEmpty() -> ", %M()" to arrayOf(MemberName("kotlin.collections", "emptySet"))
|
jsonQualifiers.isEmpty() -> ", %M()" to arrayOf(MemberName("kotlin.collections", "emptySet"))
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
", setOf(%L)" to arrayOf(jsonQualifiers.map { it.asInstantiationExpression() }.joinToCode())
|
", setOf(%L)" to arrayOf(jsonQualifiers.map { it.asInstantiationExpression() }.joinToCode())
|
||||||
}
|
}
|
||||||
|
@@ -92,10 +92,12 @@ internal abstract class TypeRenderer {
|
|||||||
target = typeName.inTypes[0]
|
target = typeName.inTypes[0]
|
||||||
method = "supertypeOf"
|
method = "supertypeOf"
|
||||||
}
|
}
|
||||||
|
|
||||||
typeName.outTypes.size == 1 -> {
|
typeName.outTypes.size == 1 -> {
|
||||||
target = typeName.outTypes[0]
|
target = typeName.outTypes[0]
|
||||||
method = "subtypeOf"
|
method = "subtypeOf"
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw IllegalArgumentException(
|
else -> throw IllegalArgumentException(
|
||||||
"Unrepresentable wildcard type. Cannot have more than one bound: $typeName",
|
"Unrepresentable wildcard type. Cannot have more than one bound: $typeName",
|
||||||
)
|
)
|
||||||
|
@@ -49,7 +49,9 @@ internal fun TypeName.rawType(): ClassName {
|
|||||||
internal fun TypeName.findRawType(): ClassName? {
|
internal fun TypeName.findRawType(): ClassName? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ClassName -> this
|
is ClassName -> this
|
||||||
|
|
||||||
is ParameterizedTypeName -> rawType
|
is ParameterizedTypeName -> rawType
|
||||||
|
|
||||||
is LambdaTypeName -> {
|
is LambdaTypeName -> {
|
||||||
var count = parameters.size
|
var count = parameters.size
|
||||||
if (receiver != null) {
|
if (receiver != null) {
|
||||||
@@ -62,6 +64,7 @@ internal fun TypeName.findRawType(): ClassName? {
|
|||||||
}
|
}
|
||||||
ClassName("kotlin.jvm.functions", functionSimpleName)
|
ClassName("kotlin.jvm.functions", functionSimpleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,11 +107,14 @@ internal fun TypeName.asTypeBlock(): CodeBlock {
|
|||||||
rawType.asTypeBlock()
|
rawType.asTypeBlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is TypeVariableName -> {
|
is TypeVariableName -> {
|
||||||
val bound = bounds.firstOrNull() ?: ANY
|
val bound = bounds.firstOrNull() ?: ANY
|
||||||
return bound.asTypeBlock()
|
return bound.asTypeBlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
is LambdaTypeName -> return rawType().asTypeBlock()
|
is LambdaTypeName -> return rawType().asTypeBlock()
|
||||||
|
|
||||||
is ClassName -> {
|
is ClassName -> {
|
||||||
// Check against the non-nullable version for equality, but we'll keep the nullability in
|
// Check against the non-nullable version for equality, but we'll keep the nullability in
|
||||||
// consideration when creating the CodeBlock if needed.
|
// consideration when creating the CodeBlock if needed.
|
||||||
@@ -121,10 +127,13 @@ internal fun TypeName.asTypeBlock(): CodeBlock {
|
|||||||
CodeBlock.of("%T::class.javaPrimitiveType!!", this)
|
CodeBlock.of("%T::class.javaPrimitiveType!!", this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIT, Void::class.asTypeName(), NOTHING -> throw IllegalStateException("Parameter with void, Unit, or Nothing type is illegal")
|
UNIT, Void::class.asTypeName(), NOTHING -> throw IllegalStateException("Parameter with void, Unit, or Nothing type is illegal")
|
||||||
|
|
||||||
else -> CodeBlock.of("%T::class.java", copy(nullable = false))
|
else -> CodeBlock.of("%T::class.java", copy(nullable = false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw UnsupportedOperationException("Parameter with type '${javaClass.simpleName}' is illegal. Only classes, parameterized types, or type variables are allowed.")
|
else -> throw UnsupportedOperationException("Parameter with type '${javaClass.simpleName}' is illegal. Only classes, parameterized types, or type variables are allowed.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,11 +147,15 @@ internal fun KModifier.checkIsVisibility() {
|
|||||||
internal fun TypeName.stripTypeVarVariance(resolver: TypeVariableResolver): TypeName {
|
internal fun TypeName.stripTypeVarVariance(resolver: TypeVariableResolver): TypeName {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ClassName -> this
|
is ClassName -> this
|
||||||
|
|
||||||
is ParameterizedTypeName -> {
|
is ParameterizedTypeName -> {
|
||||||
deepCopy { it.stripTypeVarVariance(resolver) }
|
deepCopy { it.stripTypeVarVariance(resolver) }
|
||||||
}
|
}
|
||||||
|
|
||||||
is TypeVariableName -> resolver[name]
|
is TypeVariableName -> resolver[name]
|
||||||
|
|
||||||
is WildcardTypeName -> deepCopy { it.stripTypeVarVariance(resolver) }
|
is WildcardTypeName -> deepCopy { it.stripTypeVarVariance(resolver) }
|
||||||
|
|
||||||
else -> throw UnsupportedOperationException("Type '${javaClass.simpleName}' is illegal. Only classes, parameterized types, wildcard types, or type variables are allowed.")
|
else -> throw UnsupportedOperationException("Type '${javaClass.simpleName}' is illegal. Only classes, parameterized types, wildcard types, or type variables are allowed.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,14 +181,17 @@ internal fun WildcardTypeName.deepCopy(transform: (TypeName) -> TypeName): TypeN
|
|||||||
// Consumer type - single element inTypes, single ANY element outType.
|
// Consumer type - single element inTypes, single ANY element outType.
|
||||||
return when {
|
return when {
|
||||||
this == STAR -> this
|
this == STAR -> this
|
||||||
|
|
||||||
outTypes.isNotEmpty() && inTypes.isEmpty() -> {
|
outTypes.isNotEmpty() && inTypes.isEmpty() -> {
|
||||||
WildcardTypeName.producerOf(transform(outTypes[0]))
|
WildcardTypeName.producerOf(transform(outTypes[0]))
|
||||||
.copy(nullable = isNullable, annotations = annotations)
|
.copy(nullable = isNullable, annotations = annotations)
|
||||||
}
|
}
|
||||||
|
|
||||||
inTypes.isNotEmpty() -> {
|
inTypes.isNotEmpty() -> {
|
||||||
WildcardTypeName.consumerOf(transform(inTypes[0]))
|
WildcardTypeName.consumerOf(transform(inTypes[0]))
|
||||||
.copy(nullable = isNullable, annotations = annotations)
|
.copy(nullable = isNullable, annotations = annotations)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw UnsupportedOperationException("Not possible.")
|
else -> throw UnsupportedOperationException("Not possible.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,18 +44,23 @@ private fun TypeName.unwrapTypeAliasInternal(): TypeName? {
|
|||||||
internal fun TypeName.unwrapTypeAlias(): TypeName {
|
internal fun TypeName.unwrapTypeAlias(): TypeName {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ClassName -> unwrapTypeAliasInternal() ?: this
|
is ClassName -> unwrapTypeAliasInternal() ?: this
|
||||||
|
|
||||||
is ParameterizedTypeName -> {
|
is ParameterizedTypeName -> {
|
||||||
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
||||||
}
|
}
|
||||||
|
|
||||||
is TypeVariableName -> {
|
is TypeVariableName -> {
|
||||||
unwrapTypeAliasInternal() ?: deepCopy(transform = TypeName::unwrapTypeAlias)
|
unwrapTypeAliasInternal() ?: deepCopy(transform = TypeName::unwrapTypeAlias)
|
||||||
}
|
}
|
||||||
|
|
||||||
is WildcardTypeName -> {
|
is WildcardTypeName -> {
|
||||||
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
||||||
}
|
}
|
||||||
|
|
||||||
is LambdaTypeName -> {
|
is LambdaTypeName -> {
|
||||||
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
unwrapTypeAliasInternal() ?: deepCopy(TypeName::unwrapTypeAlias)
|
||||||
}
|
}
|
||||||
|
|
||||||
Dynamic -> 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.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -152,6 +152,7 @@ internal fun targetType(
|
|||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
!kmClass.isClass -> {
|
!kmClass.isClass -> {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
ERROR,
|
ERROR,
|
||||||
@@ -160,6 +161,7 @@ internal fun targetType(
|
|||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
kmClass.isInner -> {
|
kmClass.isInner -> {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
ERROR,
|
ERROR,
|
||||||
@@ -168,6 +170,7 @@ internal fun targetType(
|
|||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
kmClass.flags.isSealed -> {
|
kmClass.flags.isSealed -> {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
ERROR,
|
ERROR,
|
||||||
@@ -176,6 +179,7 @@ internal fun targetType(
|
|||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
kmClass.flags.isAbstract -> {
|
kmClass.flags.isAbstract -> {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
ERROR,
|
ERROR,
|
||||||
@@ -184,6 +188,7 @@ internal fun targetType(
|
|||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
kmClass.flags.isLocal -> {
|
kmClass.flags.isLocal -> {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
ERROR,
|
ERROR,
|
||||||
@@ -192,6 +197,7 @@ internal fun targetType(
|
|||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
!kmClass.flags.isPublic && !kmClass.flags.isInternal -> {
|
!kmClass.flags.isPublic && !kmClass.flags.isInternal -> {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
ERROR,
|
ERROR,
|
||||||
@@ -350,15 +356,18 @@ private fun resolveTypeArgs(
|
|||||||
|
|
||||||
return when {
|
return when {
|
||||||
resolvedType !is TypeVariableName -> resolvedType
|
resolvedType !is TypeVariableName -> resolvedType
|
||||||
|
|
||||||
entryStartIndex != 0 -> {
|
entryStartIndex != 0 -> {
|
||||||
// We need to go deeper
|
// We need to go deeper
|
||||||
resolveTypeArgs(targetClass, resolvedType, resolvedTypes, allowedTypeVars, entryStartIndex - 1)
|
resolveTypeArgs(targetClass, resolvedType, resolvedTypes, allowedTypeVars, entryStartIndex - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolvedType.copy(nullable = false) in allowedTypeVars -> {
|
resolvedType.copy(nullable = false) in allowedTypeVars -> {
|
||||||
// This is a generic type in the top-level declared class. This is fine to leave in because
|
// This is a generic type in the top-level declared class. This is fine to leave in because
|
||||||
// this will be handled by the `Type` array passed in at runtime.
|
// this will be handled by the `Type` array passed in at runtime.
|
||||||
resolvedType
|
resolvedType
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> error("Could not find $resolvedType in $resolvedTypes. Also not present in allowable top-level type vars $allowedTypeVars")
|
else -> error("Could not find $resolvedType in $resolvedTypes. Also not present in allowable top-level type vars $allowedTypeVars")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -76,6 +76,7 @@ private fun addValueToBlock(value: Any, resolver: Resolver, member: CodeBlock.Bu
|
|||||||
}
|
}
|
||||||
member.add("⇤⇤)")
|
member.add("⇤⇤)")
|
||||||
}
|
}
|
||||||
|
|
||||||
is KSType -> {
|
is KSType -> {
|
||||||
val unwrapped = value.unwrapTypeAlias()
|
val unwrapped = value.unwrapTypeAlias()
|
||||||
val isEnum = (unwrapped.declaration as KSClassDeclaration).classKind == ClassKind.ENUM_ENTRY
|
val isEnum = (unwrapped.declaration as KSClassDeclaration).classKind == ClassKind.ENUM_ENTRY
|
||||||
@@ -87,13 +88,16 @@ private fun addValueToBlock(value: Any, resolver: Resolver, member: CodeBlock.Bu
|
|||||||
member.add("%T::class", unwrapped.toClassName())
|
member.add("%T::class", unwrapped.toClassName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is KSName ->
|
is KSName ->
|
||||||
member.add(
|
member.add(
|
||||||
"%T.%L",
|
"%T.%L",
|
||||||
ClassName.bestGuess(value.getQualifier()),
|
ClassName.bestGuess(value.getQualifier()),
|
||||||
value.getShortName(),
|
value.getShortName(),
|
||||||
)
|
)
|
||||||
|
|
||||||
is KSAnnotation -> member.add("%L", value.toAnnotationSpec(resolver))
|
is KSAnnotation -> member.add("%L", value.toAnnotationSpec(resolver))
|
||||||
|
|
||||||
else -> member.add(memberForValue(value))
|
else -> member.add(memberForValue(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,13 +109,21 @@ private fun addValueToBlock(value: Any, resolver: Resolver, member: CodeBlock.Bu
|
|||||||
*/
|
*/
|
||||||
internal fun memberForValue(value: Any) = when (value) {
|
internal fun memberForValue(value: Any) = when (value) {
|
||||||
is Class<*> -> CodeBlock.of("%T::class", value)
|
is Class<*> -> CodeBlock.of("%T::class", value)
|
||||||
|
|
||||||
is Enum<*> -> CodeBlock.of("%T.%L", value.javaClass, value.name)
|
is Enum<*> -> CodeBlock.of("%T.%L", value.javaClass, value.name)
|
||||||
|
|
||||||
is String -> CodeBlock.of("%S", value)
|
is String -> CodeBlock.of("%S", value)
|
||||||
|
|
||||||
is Float -> CodeBlock.of("%Lf", value)
|
is Float -> CodeBlock.of("%Lf", value)
|
||||||
|
|
||||||
is Double -> CodeBlock.of("%L", value)
|
is Double -> CodeBlock.of("%L", value)
|
||||||
|
|
||||||
is Char -> CodeBlock.of("$value.toChar()")
|
is Char -> CodeBlock.of("$value.toChar()")
|
||||||
|
|
||||||
is Byte -> CodeBlock.of("$value.toByte()")
|
is Byte -> CodeBlock.of("$value.toByte()")
|
||||||
|
|
||||||
is Short -> CodeBlock.of("$value.toShort()")
|
is Short -> CodeBlock.of("$value.toShort()")
|
||||||
|
|
||||||
// Int or Boolean
|
// Int or Boolean
|
||||||
else -> CodeBlock.of("%L", value)
|
else -> CodeBlock.of("%L", value)
|
||||||
}
|
}
|
||||||
|
@@ -80,32 +80,39 @@ private fun KSAnnotation.createInvocationHandler(clazz: Class<*>): InvocationHan
|
|||||||
}
|
}
|
||||||
when (val result = argument.value ?: method.defaultValue) {
|
when (val result = argument.value ?: method.defaultValue) {
|
||||||
is Proxy -> result
|
is Proxy -> result
|
||||||
|
|
||||||
is List<*> -> {
|
is List<*> -> {
|
||||||
val value = { result.asArray(method) }
|
val value = { result.asArray(method) }
|
||||||
cache.getOrPut(Pair(method.returnType, result), value)
|
cache.getOrPut(Pair(method.returnType, result), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
when {
|
when {
|
||||||
method.returnType.isEnum -> {
|
method.returnType.isEnum -> {
|
||||||
val value = { result.asEnum(method.returnType) }
|
val value = { result.asEnum(method.returnType) }
|
||||||
cache.getOrPut(Pair(method.returnType, result), value)
|
cache.getOrPut(Pair(method.returnType, result), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
method.returnType.isAnnotation -> {
|
method.returnType.isAnnotation -> {
|
||||||
val value = { (result as KSAnnotation).asAnnotation(method.returnType) }
|
val value = { (result as KSAnnotation).asAnnotation(method.returnType) }
|
||||||
cache.getOrPut(Pair(method.returnType, result), value)
|
cache.getOrPut(Pair(method.returnType, result), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
method.returnType.name == "java.lang.Class" -> {
|
method.returnType.name == "java.lang.Class" -> {
|
||||||
val value = { (result as KSType).asClass() }
|
val value = { (result as KSType).asClass() }
|
||||||
cache.getOrPut(Pair(method.returnType, result), value)
|
cache.getOrPut(Pair(method.returnType, result), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
method.returnType.name == "byte" -> {
|
method.returnType.name == "byte" -> {
|
||||||
val value = { result.asByte() }
|
val value = { result.asByte() }
|
||||||
cache.getOrPut(Pair(method.returnType, result), value)
|
cache.getOrPut(Pair(method.returnType, result), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
method.returnType.name == "short" -> {
|
method.returnType.name == "short" -> {
|
||||||
val value = { result.asShort() }
|
val value = { result.asShort() }
|
||||||
cache.getOrPut(Pair(method.returnType, result), value)
|
cache.getOrPut(Pair(method.returnType, result), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> result // original value
|
else -> result // original value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,27 +136,39 @@ private fun KSAnnotation.asAnnotation(
|
|||||||
private fun List<*>.asArray(method: Method) =
|
private fun List<*>.asArray(method: Method) =
|
||||||
when (method.returnType.componentType.name) {
|
when (method.returnType.componentType.name) {
|
||||||
"boolean" -> (this as List<Boolean>).toBooleanArray()
|
"boolean" -> (this as List<Boolean>).toBooleanArray()
|
||||||
|
|
||||||
"byte" -> (this as List<Byte>).toByteArray()
|
"byte" -> (this as List<Byte>).toByteArray()
|
||||||
|
|
||||||
"short" -> (this as List<Short>).toShortArray()
|
"short" -> (this as List<Short>).toShortArray()
|
||||||
|
|
||||||
"char" -> (this as List<Char>).toCharArray()
|
"char" -> (this as List<Char>).toCharArray()
|
||||||
|
|
||||||
"double" -> (this as List<Double>).toDoubleArray()
|
"double" -> (this as List<Double>).toDoubleArray()
|
||||||
|
|
||||||
"float" -> (this as List<Float>).toFloatArray()
|
"float" -> (this as List<Float>).toFloatArray()
|
||||||
|
|
||||||
"int" -> (this as List<Int>).toIntArray()
|
"int" -> (this as List<Int>).toIntArray()
|
||||||
|
|
||||||
"long" -> (this as List<Long>).toLongArray()
|
"long" -> (this as List<Long>).toLongArray()
|
||||||
|
|
||||||
"java.lang.Class" -> (this as List<KSType>).map {
|
"java.lang.Class" -> (this as List<KSType>).map {
|
||||||
Class.forName(it.declaration.qualifiedName!!.asString())
|
Class.forName(it.declaration.qualifiedName!!.asString())
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
|
|
||||||
"java.lang.String" -> (this as List<String>).toTypedArray()
|
"java.lang.String" -> (this as List<String>).toTypedArray()
|
||||||
|
|
||||||
else -> { // arrays of enums or annotations
|
else -> { // arrays of enums or annotations
|
||||||
when {
|
when {
|
||||||
method.returnType.componentType.isEnum -> {
|
method.returnType.componentType.isEnum -> {
|
||||||
this.toArray(method) { result -> result.asEnum(method.returnType.componentType) }
|
this.toArray(method) { result -> result.asEnum(method.returnType.componentType) }
|
||||||
}
|
}
|
||||||
|
|
||||||
method.returnType.componentType.isAnnotation -> {
|
method.returnType.componentType.isAnnotation -> {
|
||||||
this.toArray(method) { result ->
|
this.toArray(method) { result ->
|
||||||
(result as KSAnnotation).asAnnotation(method.returnType.componentType)
|
(result as KSAnnotation).asAnnotation(method.returnType.componentType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw IllegalStateException("Unable to process type ${method.returnType.componentType.name}")
|
else -> throw IllegalStateException("Unable to process type ${method.returnType.componentType.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -668,6 +668,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.Simple" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.Simple" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.Simple
|
-if class testPackage.Simple
|
||||||
@@ -678,6 +679,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.Generic" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.Generic" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.Generic
|
-if class testPackage.Generic
|
||||||
@@ -688,6 +690,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.UsingQualifiers" -> {
|
"moshi-testPackage.UsingQualifiers" -> {
|
||||||
assertThat(generatedFile.readText()).contains(
|
assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
@@ -700,6 +703,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
"moshi-testPackage.MixedTypes" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.MixedTypes" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.MixedTypes
|
-if class testPackage.MixedTypes
|
||||||
@@ -710,6 +714,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.DefaultParams" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.DefaultParams" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.DefaultParams
|
-if class testPackage.DefaultParams
|
||||||
@@ -726,6 +731,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.Complex" -> {
|
"moshi-testPackage.Complex" -> {
|
||||||
assertThat(generatedFile.readText()).contains(
|
assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
@@ -744,6 +750,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
"moshi-testPackage.MultipleMasks" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.MultipleMasks" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.MultipleMasks
|
-if class testPackage.MultipleMasks
|
||||||
@@ -760,6 +767,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.NestedType.NestedSimple" -> {
|
"moshi-testPackage.NestedType.NestedSimple" -> {
|
||||||
assertThat(generatedFile.readText()).contains(
|
assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
@@ -772,6 +780,7 @@ class JsonClassCodegenProcessorTest {
|
|||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> error("Unexpected proguard file! ${generatedFile.name}")
|
else -> error("Unexpected proguard file! ${generatedFile.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -718,6 +718,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.Simple" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.Simple" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.Simple
|
-if class testPackage.Simple
|
||||||
@@ -728,6 +729,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.Generic" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.Generic" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.Generic
|
-if class testPackage.Generic
|
||||||
@@ -738,6 +740,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.UsingQualifiers" -> {
|
"moshi-testPackage.UsingQualifiers" -> {
|
||||||
assertThat(generatedFile.readText()).contains(
|
assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
@@ -750,6 +753,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
"moshi-testPackage.MixedTypes" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.MixedTypes" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.MixedTypes
|
-if class testPackage.MixedTypes
|
||||||
@@ -760,6 +764,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.DefaultParams" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.DefaultParams" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.DefaultParams
|
-if class testPackage.DefaultParams
|
||||||
@@ -776,6 +781,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.Complex" -> {
|
"moshi-testPackage.Complex" -> {
|
||||||
assertThat(generatedFile.readText()).contains(
|
assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
@@ -794,6 +800,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
"moshi-testPackage.MultipleMasks" -> assertThat(generatedFile.readText()).contains(
|
"moshi-testPackage.MultipleMasks" -> assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
-if class testPackage.MultipleMasks
|
-if class testPackage.MultipleMasks
|
||||||
@@ -810,6 +817,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
}
|
}
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
"moshi-testPackage.NestedType.NestedSimple" -> {
|
"moshi-testPackage.NestedType.NestedSimple" -> {
|
||||||
assertThat(generatedFile.readText()).contains(
|
assertThat(generatedFile.readText()).contains(
|
||||||
"""
|
"""
|
||||||
@@ -822,6 +830,7 @@ class JsonClassSymbolProcessorTest {
|
|||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> error("Unexpected proguard file! ${generatedFile.name}")
|
else -> error("Unexpected proguard file! ${generatedFile.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,9 +24,11 @@ when (testMode) {
|
|||||||
REFLECT -> {
|
REFLECT -> {
|
||||||
// Do nothing!
|
// Do nothing!
|
||||||
}
|
}
|
||||||
|
|
||||||
KAPT -> {
|
KAPT -> {
|
||||||
apply(plugin = "org.jetbrains.kotlin.kapt")
|
apply(plugin = "org.jetbrains.kotlin.kapt")
|
||||||
}
|
}
|
||||||
|
|
||||||
KSP -> {
|
KSP -> {
|
||||||
apply(plugin = "com.google.devtools.ksp")
|
apply(plugin = "com.google.devtools.ksp")
|
||||||
}
|
}
|
||||||
@@ -51,9 +53,11 @@ dependencies {
|
|||||||
REFLECT -> {
|
REFLECT -> {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
KAPT -> {
|
KAPT -> {
|
||||||
"kaptTest"(project(":moshi-kotlin-codegen"))
|
"kaptTest"(project(":moshi-kotlin-codegen"))
|
||||||
}
|
}
|
||||||
|
|
||||||
KSP -> {
|
KSP -> {
|
||||||
"kspTest"(project(":moshi-kotlin-codegen"))
|
"kspTest"(project(":moshi-kotlin-codegen"))
|
||||||
}
|
}
|
||||||
|
@@ -25,9 +25,11 @@ when (testMode) {
|
|||||||
// Default to KSP. This is a CI-only thing
|
// Default to KSP. This is a CI-only thing
|
||||||
apply(plugin = "com.google.devtools.ksp")
|
apply(plugin = "com.google.devtools.ksp")
|
||||||
}
|
}
|
||||||
|
|
||||||
KAPT -> {
|
KAPT -> {
|
||||||
apply(plugin = "org.jetbrains.kotlin.kapt")
|
apply(plugin = "org.jetbrains.kotlin.kapt")
|
||||||
}
|
}
|
||||||
|
|
||||||
KSP -> {
|
KSP -> {
|
||||||
apply(plugin = "com.google.devtools.ksp")
|
apply(plugin = "com.google.devtools.ksp")
|
||||||
}
|
}
|
||||||
@@ -53,9 +55,11 @@ dependencies {
|
|||||||
// Default to KSP in this case, this is a CI-only thing
|
// Default to KSP in this case, this is a CI-only thing
|
||||||
"kspTest"(project(":moshi-kotlin-codegen"))
|
"kspTest"(project(":moshi-kotlin-codegen"))
|
||||||
}
|
}
|
||||||
|
|
||||||
KAPT -> {
|
KAPT -> {
|
||||||
"kaptTest"(project(":moshi-kotlin-codegen"))
|
"kaptTest"(project(":moshi-kotlin-codegen"))
|
||||||
}
|
}
|
||||||
|
|
||||||
KSP -> {
|
KSP -> {
|
||||||
"kspTest"(project(":moshi-kotlin-codegen"))
|
"kspTest"(project(":moshi-kotlin-codegen"))
|
||||||
}
|
}
|
||||||
|
@@ -104,7 +104,10 @@ internal class KotlinJsonAdapter<T>(
|
|||||||
if (values[i] === ABSENT_VALUE) {
|
if (values[i] === ABSENT_VALUE) {
|
||||||
when {
|
when {
|
||||||
constructor.parameters[i].isOptional -> isFullInitialized = false
|
constructor.parameters[i].isOptional -> isFullInitialized = false
|
||||||
constructor.parameters[i].type.isMarkedNullable -> values[i] = null // Replace absent with null.
|
|
||||||
|
// Replace absent with null.
|
||||||
|
constructor.parameters[i].type.isMarkedNullable -> values[i] = null
|
||||||
|
|
||||||
else -> throw missingProperty(
|
else -> throw missingProperty(
|
||||||
constructor.parameters[i].name,
|
constructor.parameters[i].name,
|
||||||
allBindings[i]?.jsonName,
|
allBindings[i]?.jsonName,
|
||||||
@@ -285,9 +288,11 @@ public class KotlinJsonAdapterFactory : JsonAdapter.Factory {
|
|||||||
property.returnType.javaType
|
property.returnType.javaType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is KTypeParameter -> {
|
is KTypeParameter -> {
|
||||||
property.returnType.javaType
|
property.returnType.javaType
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> error("Not possible!")
|
else -> error("Not possible!")
|
||||||
}
|
}
|
||||||
val resolvedPropertyType = propertyType.resolve(type, rawType)
|
val resolvedPropertyType = propertyType.resolve(type, rawType)
|
||||||
|
@@ -61,7 +61,9 @@ internal class AdapterMethodsFactory(
|
|||||||
override fun toJson(writer: JsonWriter, value: Any?) {
|
override fun toJson(writer: JsonWriter, value: Any?) {
|
||||||
when {
|
when {
|
||||||
toAdapter == null -> knownNotNull(delegate).toJson(writer, value)
|
toAdapter == null -> knownNotNull(delegate).toJson(writer, value)
|
||||||
|
|
||||||
!toAdapter.nullable && value == null -> writer.nullValue()
|
!toAdapter.nullable && value == null -> writer.nullValue()
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
try {
|
try {
|
||||||
toAdapter.toJson(moshi, writer, value)
|
toAdapter.toJson(moshi, writer, value)
|
||||||
@@ -77,7 +79,9 @@ internal class AdapterMethodsFactory(
|
|||||||
override fun fromJson(reader: JsonReader): Any? {
|
override fun fromJson(reader: JsonReader): Any? {
|
||||||
return when {
|
return when {
|
||||||
fromAdapter == null -> knownNotNull(delegate).fromJson(reader)
|
fromAdapter == null -> knownNotNull(delegate).fromJson(reader)
|
||||||
|
|
||||||
!fromAdapter.nullable && reader.peek() == JsonReader.Token.NULL -> reader.nextNull<Any>()
|
!fromAdapter.nullable && reader.peek() == JsonReader.Token.NULL -> reader.nextNull<Any>()
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
try {
|
try {
|
||||||
fromAdapter.fromJson(moshi, reader)
|
fromAdapter.fromJson(moshi, reader)
|
||||||
@@ -161,6 +165,7 @@ internal class AdapterMethodsFactory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterTypes.size == 1 && returnType != Void.TYPE -> {
|
parameterTypes.size == 1 && returnType != Void.TYPE -> {
|
||||||
// List<Integer> pointToJson(Point point) {
|
// List<Integer> pointToJson(Point point) {
|
||||||
val returnTypeAnnotations = method.jsonAnnotations
|
val returnTypeAnnotations = method.jsonAnnotations
|
||||||
@@ -194,6 +199,7 @@ internal class AdapterMethodsFactory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
throw IllegalArgumentException(
|
throw IllegalArgumentException(
|
||||||
"""
|
"""
|
||||||
@@ -249,6 +255,7 @@ internal class AdapterMethodsFactory(
|
|||||||
override fun fromJson(moshi: Moshi, reader: JsonReader) = invokeMethod(reader)
|
override fun fromJson(moshi: Moshi, reader: JsonReader) = invokeMethod(reader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterTypes.size == 1 && returnType != Void.TYPE -> {
|
parameterTypes.size == 1 && returnType != Void.TYPE -> {
|
||||||
// Point pointFromJson(List<Integer> o) {
|
// Point pointFromJson(List<Integer> o) {
|
||||||
val qualifierAnnotations = parameterAnnotations[0].jsonAnnotations
|
val qualifierAnnotations = parameterAnnotations[0].jsonAnnotations
|
||||||
@@ -279,6 +286,7 @@ internal class AdapterMethodsFactory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
throw IllegalArgumentException(
|
throw IllegalArgumentException(
|
||||||
"""
|
"""
|
||||||
|
@@ -49,41 +49,49 @@ internal class ArrayJsonAdapter(
|
|||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is ByteArray -> {
|
is ByteArray -> {
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is CharArray -> {
|
is CharArray -> {
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is DoubleArray -> {
|
is DoubleArray -> {
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is FloatArray -> {
|
is FloatArray -> {
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is IntArray -> {
|
is IntArray -> {
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is LongArray -> {
|
is LongArray -> {
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is ShortArray -> {
|
is ShortArray -> {
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is Array<*> -> {
|
is Array<*> -> {
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
elementAdapter.toJson(writer, element)
|
elementAdapter.toJson(writer, element)
|
||||||
|
@@ -53,9 +53,11 @@ internal abstract class CollectionJsonAdapter<C : MutableCollection<T?>, T> priv
|
|||||||
List::class.java, Collection::class.java -> {
|
List::class.java, Collection::class.java -> {
|
||||||
newArrayListAdapter<Any>(type, moshi).nullSafe()
|
newArrayListAdapter<Any>(type, moshi).nullSafe()
|
||||||
}
|
}
|
||||||
|
|
||||||
Set::class.java -> {
|
Set::class.java -> {
|
||||||
newLinkedHashSetAdapter<Any>(type, moshi).nullSafe()
|
newLinkedHashSetAdapter<Any>(type, moshi).nullSafe()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -483,6 +483,7 @@ public sealed class JsonReader : Closeable {
|
|||||||
endArray()
|
endArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token.BEGIN_OBJECT -> {
|
Token.BEGIN_OBJECT -> {
|
||||||
return buildMap {
|
return buildMap {
|
||||||
beginObject()
|
beginObject()
|
||||||
@@ -497,10 +498,15 @@ public sealed class JsonReader : Closeable {
|
|||||||
endObject()
|
endObject()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token.STRING -> nextString()
|
Token.STRING -> nextString()
|
||||||
|
|
||||||
Token.NUMBER -> nextDouble()
|
Token.NUMBER -> nextDouble()
|
||||||
|
|
||||||
Token.BOOLEAN -> nextBoolean()
|
Token.BOOLEAN -> nextBoolean()
|
||||||
|
|
||||||
Token.NULL -> nextNull<Any>()
|
Token.NULL -> nextNull<Any>()
|
||||||
|
|
||||||
else -> throw IllegalStateException("Expected a value but was ${peek()} at path $path")
|
else -> throw IllegalStateException("Expected a value but was ${peek()} at path $path")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -59,12 +59,14 @@ internal object JsonScope {
|
|||||||
for (i in 0 until stackSize) {
|
for (i in 0 until stackSize) {
|
||||||
when (stack[i]) {
|
when (stack[i]) {
|
||||||
EMPTY_ARRAY, NONEMPTY_ARRAY -> append('[').append(pathIndices[i]).append(']')
|
EMPTY_ARRAY, NONEMPTY_ARRAY -> append('[').append(pathIndices[i]).append(']')
|
||||||
|
|
||||||
EMPTY_OBJECT, DANGLING_NAME, NONEMPTY_OBJECT -> {
|
EMPTY_OBJECT, DANGLING_NAME, NONEMPTY_OBJECT -> {
|
||||||
append('.')
|
append('.')
|
||||||
if (pathNames[i] != null) {
|
if (pathNames[i] != null) {
|
||||||
append(pathNames[i])
|
append(pathNames[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NONEMPTY_DOCUMENT, EMPTY_DOCUMENT, CLOSED -> {}
|
NONEMPTY_DOCUMENT, EMPTY_DOCUMENT, CLOSED -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -147,6 +147,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
val peekStack = scopes[stackSize - 1]
|
val peekStack = scopes[stackSize - 1]
|
||||||
when (peekStack) {
|
when (peekStack) {
|
||||||
JsonScope.EMPTY_ARRAY -> scopes[stackSize - 1] = JsonScope.NONEMPTY_ARRAY
|
JsonScope.EMPTY_ARRAY -> scopes[stackSize - 1] = JsonScope.NONEMPTY_ARRAY
|
||||||
|
|
||||||
JsonScope.NONEMPTY_ARRAY -> {
|
JsonScope.NONEMPTY_ARRAY -> {
|
||||||
// Look for a comma before the next element.
|
// Look for a comma before the next element.
|
||||||
val c = nextNonWhitespace(true).toChar()
|
val c = nextNonWhitespace(true).toChar()
|
||||||
@@ -155,11 +156,16 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
']' -> {
|
']' -> {
|
||||||
return setPeeked(PEEKED_END_ARRAY)
|
return setPeeked(PEEKED_END_ARRAY)
|
||||||
}
|
}
|
||||||
|
|
||||||
';' -> checkLenient()
|
';' -> checkLenient()
|
||||||
',' -> Unit /*no op*/
|
|
||||||
|
/*no op*/
|
||||||
|
',' -> Unit
|
||||||
|
|
||||||
else -> throw syntaxError("Unterminated array")
|
else -> throw syntaxError("Unterminated array")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.EMPTY_OBJECT, JsonScope.NONEMPTY_OBJECT -> {
|
JsonScope.EMPTY_OBJECT, JsonScope.NONEMPTY_OBJECT -> {
|
||||||
scopes[stackSize - 1] = JsonScope.DANGLING_NAME
|
scopes[stackSize - 1] = JsonScope.DANGLING_NAME
|
||||||
// Look for a comma before the next element.
|
// Look for a comma before the next element.
|
||||||
@@ -170,8 +176,12 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
'}' -> {
|
'}' -> {
|
||||||
return setPeeked(PEEKED_END_OBJECT)
|
return setPeeked(PEEKED_END_OBJECT)
|
||||||
}
|
}
|
||||||
',' -> Unit /*no op*/
|
|
||||||
|
/*no op*/
|
||||||
|
',' -> Unit
|
||||||
|
|
||||||
';' -> checkLenient()
|
';' -> checkLenient()
|
||||||
|
|
||||||
else -> throw syntaxError("Unterminated object")
|
else -> throw syntaxError("Unterminated object")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,17 +190,20 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
buffer.readByte() // consume the '\"'.
|
buffer.readByte() // consume the '\"'.
|
||||||
PEEKED_DOUBLE_QUOTED_NAME
|
PEEKED_DOUBLE_QUOTED_NAME
|
||||||
}
|
}
|
||||||
|
|
||||||
'\'' -> {
|
'\'' -> {
|
||||||
buffer.readByte() // consume the '\''.
|
buffer.readByte() // consume the '\''.
|
||||||
checkLenient()
|
checkLenient()
|
||||||
PEEKED_SINGLE_QUOTED_NAME
|
PEEKED_SINGLE_QUOTED_NAME
|
||||||
}
|
}
|
||||||
|
|
||||||
'}' -> if (peekStack != JsonScope.NONEMPTY_OBJECT) {
|
'}' -> if (peekStack != JsonScope.NONEMPTY_OBJECT) {
|
||||||
buffer.readByte() // consume the '}'.
|
buffer.readByte() // consume the '}'.
|
||||||
PEEKED_END_OBJECT
|
PEEKED_END_OBJECT
|
||||||
} else {
|
} else {
|
||||||
throw syntaxError("Expected name")
|
throw syntaxError("Expected name")
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
checkLenient()
|
checkLenient()
|
||||||
if (isLiteral(c.code)) {
|
if (isLiteral(c.code)) {
|
||||||
@@ -203,23 +216,29 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
peeked = next
|
peeked = next
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.DANGLING_NAME -> {
|
JsonScope.DANGLING_NAME -> {
|
||||||
scopes[stackSize - 1] = JsonScope.NONEMPTY_OBJECT
|
scopes[stackSize - 1] = JsonScope.NONEMPTY_OBJECT
|
||||||
// Look for a colon before the value.
|
// Look for a colon before the value.
|
||||||
val c = nextNonWhitespace(true).toChar()
|
val c = nextNonWhitespace(true).toChar()
|
||||||
buffer.readByte() // Consume ':'.
|
buffer.readByte() // Consume ':'.
|
||||||
when (c) {
|
when (c) {
|
||||||
':' -> Unit /*no op*/
|
/*no op*/
|
||||||
|
':' -> Unit
|
||||||
|
|
||||||
'=' -> {
|
'=' -> {
|
||||||
checkLenient()
|
checkLenient()
|
||||||
if (source.request(1) && buffer[0].asChar() == '>') {
|
if (source.request(1) && buffer[0].asChar() == '>') {
|
||||||
buffer.readByte() // Consume '>'.
|
buffer.readByte() // Consume '>'.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw syntaxError("Expected ':'")
|
else -> throw syntaxError("Expected ':'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.EMPTY_DOCUMENT -> scopes[stackSize - 1] = JsonScope.NONEMPTY_DOCUMENT
|
JsonScope.EMPTY_DOCUMENT -> scopes[stackSize - 1] = JsonScope.NONEMPTY_DOCUMENT
|
||||||
|
|
||||||
JsonScope.NONEMPTY_DOCUMENT -> {
|
JsonScope.NONEMPTY_DOCUMENT -> {
|
||||||
if (nextNonWhitespace(false) == -1) {
|
if (nextNonWhitespace(false) == -1) {
|
||||||
return setPeeked(PEEKED_EOF)
|
return setPeeked(PEEKED_EOF)
|
||||||
@@ -227,12 +246,14 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
checkLenient()
|
checkLenient()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.STREAMING_VALUE -> {
|
JsonScope.STREAMING_VALUE -> {
|
||||||
valueSource!!.discard()
|
valueSource!!.discard()
|
||||||
valueSource = null
|
valueSource = null
|
||||||
stackSize--
|
stackSize--
|
||||||
return doPeek()
|
return doPeek()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> check(peekStack != JsonScope.CLOSED) { "JsonReader is closed" }
|
else -> check(peekStack != JsonScope.CLOSED) { "JsonReader is closed" }
|
||||||
}
|
}
|
||||||
// "fallthrough" from previous `when`
|
// "fallthrough" from previous `when`
|
||||||
@@ -243,39 +264,48 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
buffer.readByte() // Consume ']'.
|
buffer.readByte() // Consume ']'.
|
||||||
setPeeked(PEEKED_END_ARRAY)
|
setPeeked(PEEKED_END_ARRAY)
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.NONEMPTY_ARRAY -> {
|
JsonScope.NONEMPTY_ARRAY -> {
|
||||||
// In lenient mode, a 0-length literal in an array means 'null'.
|
// In lenient mode, a 0-length literal in an array means 'null'.
|
||||||
checkLenient()
|
checkLenient()
|
||||||
setPeeked(PEEKED_NULL)
|
setPeeked(PEEKED_NULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw syntaxError("Unexpected value")
|
else -> throw syntaxError("Unexpected value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In lenient mode, a 0-length literal in an array means 'null'.
|
// In lenient mode, a 0-length literal in an array means 'null'.
|
||||||
';', ',' -> return when (peekStack) {
|
';', ',' -> return when (peekStack) {
|
||||||
JsonScope.EMPTY_ARRAY, JsonScope.NONEMPTY_ARRAY -> {
|
JsonScope.EMPTY_ARRAY, JsonScope.NONEMPTY_ARRAY -> {
|
||||||
checkLenient()
|
checkLenient()
|
||||||
setPeeked(PEEKED_NULL)
|
setPeeked(PEEKED_NULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw syntaxError("Unexpected value")
|
else -> throw syntaxError("Unexpected value")
|
||||||
}
|
}
|
||||||
|
|
||||||
'\'' -> {
|
'\'' -> {
|
||||||
checkLenient()
|
checkLenient()
|
||||||
buffer.readByte() // Consume '\''.
|
buffer.readByte() // Consume '\''.
|
||||||
return setPeeked(PEEKED_SINGLE_QUOTED)
|
return setPeeked(PEEKED_SINGLE_QUOTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
'"' -> {
|
'"' -> {
|
||||||
buffer.readByte() // Consume '\"'.
|
buffer.readByte() // Consume '\"'.
|
||||||
return setPeeked(PEEKED_DOUBLE_QUOTED)
|
return setPeeked(PEEKED_DOUBLE_QUOTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
'[' -> {
|
'[' -> {
|
||||||
buffer.readByte() // Consume '['.
|
buffer.readByte() // Consume '['.
|
||||||
return setPeeked(PEEKED_BEGIN_ARRAY)
|
return setPeeked(PEEKED_BEGIN_ARRAY)
|
||||||
}
|
}
|
||||||
|
|
||||||
'{' -> {
|
'{' -> {
|
||||||
buffer.readByte() // Consume '{'.
|
buffer.readByte() // Consume '{'.
|
||||||
return setPeeked(PEEKED_BEGIN_OBJECT)
|
return setPeeked(PEEKED_BEGIN_OBJECT)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> Unit /* no-op */
|
else -> Unit /* no-op */
|
||||||
}
|
}
|
||||||
var result = peekKeyword()
|
var result = peekKeyword()
|
||||||
@@ -305,16 +335,19 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
keywordUpper = "TRUE"
|
keywordUpper = "TRUE"
|
||||||
peeking = PEEKED_TRUE
|
peeking = PEEKED_TRUE
|
||||||
}
|
}
|
||||||
|
|
||||||
'f', 'F' -> {
|
'f', 'F' -> {
|
||||||
keyword = "false"
|
keyword = "false"
|
||||||
keywordUpper = "FALSE"
|
keywordUpper = "FALSE"
|
||||||
peeking = PEEKED_FALSE
|
peeking = PEEKED_FALSE
|
||||||
}
|
}
|
||||||
|
|
||||||
'n', 'N' -> {
|
'n', 'N' -> {
|
||||||
keyword = "null"
|
keyword = "null"
|
||||||
keywordUpper = "NULL"
|
keywordUpper = "NULL"
|
||||||
peeking = PEEKED_NULL
|
peeking = PEEKED_NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return PEEKED_NONE
|
else -> return PEEKED_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,6 +391,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
NUMBER_CHAR_EXP_E -> {
|
NUMBER_CHAR_EXP_E -> {
|
||||||
last = NUMBER_CHAR_EXP_SIGN
|
last = NUMBER_CHAR_EXP_SIGN
|
||||||
i++
|
i++
|
||||||
@@ -366,6 +400,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
}
|
}
|
||||||
return PEEKED_NONE
|
return PEEKED_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
'+' -> {
|
'+' -> {
|
||||||
if (last == NUMBER_CHAR_EXP_E) {
|
if (last == NUMBER_CHAR_EXP_E) {
|
||||||
last = NUMBER_CHAR_EXP_SIGN
|
last = NUMBER_CHAR_EXP_SIGN
|
||||||
@@ -374,6 +409,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
}
|
}
|
||||||
return PEEKED_NONE
|
return PEEKED_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
'e', 'E' -> {
|
'e', 'E' -> {
|
||||||
if (last == NUMBER_CHAR_DIGIT || last == NUMBER_CHAR_FRACTION_DIGIT) {
|
if (last == NUMBER_CHAR_DIGIT || last == NUMBER_CHAR_FRACTION_DIGIT) {
|
||||||
last = NUMBER_CHAR_EXP_E
|
last = NUMBER_CHAR_EXP_E
|
||||||
@@ -382,6 +418,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
}
|
}
|
||||||
return PEEKED_NONE
|
return PEEKED_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
'.' -> {
|
'.' -> {
|
||||||
if (last == NUMBER_CHAR_DIGIT) {
|
if (last == NUMBER_CHAR_DIGIT) {
|
||||||
last = NUMBER_CHAR_DECIMAL
|
last = NUMBER_CHAR_DECIMAL
|
||||||
@@ -390,6 +427,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
}
|
}
|
||||||
return PEEKED_NONE
|
return PEEKED_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if (c !in '0'..'9') {
|
if (c !in '0'..'9') {
|
||||||
if (!isLiteral(c.code)) break
|
if (!isLiteral(c.code)) break
|
||||||
@@ -400,6 +438,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
value = -(c - '0').toLong()
|
value = -(c - '0').toLong()
|
||||||
last = NUMBER_CHAR_DIGIT
|
last = NUMBER_CHAR_DIGIT
|
||||||
}
|
}
|
||||||
|
|
||||||
NUMBER_CHAR_DIGIT -> {
|
NUMBER_CHAR_DIGIT -> {
|
||||||
if (value == 0L) {
|
if (value == 0L) {
|
||||||
return PEEKED_NONE // Leading '0' prefix is not allowed (since it could be octal).
|
return PEEKED_NONE // Leading '0' prefix is not allowed (since it could be octal).
|
||||||
@@ -413,7 +452,9 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
)
|
)
|
||||||
value = newValue
|
value = newValue
|
||||||
}
|
}
|
||||||
|
|
||||||
NUMBER_CHAR_DECIMAL -> last = NUMBER_CHAR_FRACTION_DIGIT
|
NUMBER_CHAR_DECIMAL -> last = NUMBER_CHAR_FRACTION_DIGIT
|
||||||
|
|
||||||
NUMBER_CHAR_EXP_E, NUMBER_CHAR_EXP_SIGN -> last = NUMBER_CHAR_EXP_DIGIT
|
NUMBER_CHAR_EXP_E, NUMBER_CHAR_EXP_SIGN -> last = NUMBER_CHAR_EXP_DIGIT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -431,12 +472,14 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
buffer.skip(i)
|
buffer.skip(i)
|
||||||
setPeeked(PEEKED_LONG)
|
setPeeked(PEEKED_LONG)
|
||||||
}
|
}
|
||||||
|
|
||||||
last == NUMBER_CHAR_DIGIT ||
|
last == NUMBER_CHAR_DIGIT ||
|
||||||
last == NUMBER_CHAR_FRACTION_DIGIT ||
|
last == NUMBER_CHAR_FRACTION_DIGIT ||
|
||||||
last == NUMBER_CHAR_EXP_DIGIT -> {
|
last == NUMBER_CHAR_EXP_DIGIT -> {
|
||||||
peekedNumberLength = i.toInt()
|
peekedNumberLength = i.toInt()
|
||||||
setPeeked(PEEKED_NUMBER)
|
setPeeked(PEEKED_NUMBER)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> PEEKED_NONE
|
else -> PEEKED_NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,8 +491,10 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
checkLenient() // fall-through
|
checkLenient() // fall-through
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x000C = \f
|
// 0x000C = \f
|
||||||
'{', '}', '[', ']', ':', ',', ' ', '\t', '\u000C', '\r', '\n' -> false
|
'{', '}', '[', ']', ':', ',', ' ', '\t', '\u000C', '\r', '\n' -> false
|
||||||
|
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,13 +503,17 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
override fun nextName(): String {
|
override fun nextName(): String {
|
||||||
val result = when (peekIfNone()) {
|
val result = when (peekIfNone()) {
|
||||||
PEEKED_UNQUOTED_NAME -> nextUnquotedValue()
|
PEEKED_UNQUOTED_NAME -> nextUnquotedValue()
|
||||||
|
|
||||||
PEEKED_DOUBLE_QUOTED_NAME -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
PEEKED_DOUBLE_QUOTED_NAME -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
||||||
|
|
||||||
PEEKED_SINGLE_QUOTED_NAME -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH)
|
PEEKED_SINGLE_QUOTED_NAME -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH)
|
||||||
|
|
||||||
PEEKED_BUFFERED_NAME -> {
|
PEEKED_BUFFERED_NAME -> {
|
||||||
val name = peekedString!!
|
val name = peekedString!!
|
||||||
peekedString = null
|
peekedString = null
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw JsonDataException("Expected a name but was ${peek()} at path $path")
|
else -> throw JsonDataException("Expected a name but was ${peek()} at path $path")
|
||||||
}
|
}
|
||||||
peeked = PEEKED_NONE
|
peeked = PEEKED_NONE
|
||||||
@@ -539,15 +588,21 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
override fun nextString(): String {
|
override fun nextString(): String {
|
||||||
val result = when (peekIfNone()) {
|
val result = when (peekIfNone()) {
|
||||||
PEEKED_UNQUOTED -> nextUnquotedValue()
|
PEEKED_UNQUOTED -> nextUnquotedValue()
|
||||||
|
|
||||||
PEEKED_DOUBLE_QUOTED -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
PEEKED_DOUBLE_QUOTED -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
||||||
|
|
||||||
PEEKED_SINGLE_QUOTED -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH)
|
PEEKED_SINGLE_QUOTED -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH)
|
||||||
|
|
||||||
PEEKED_BUFFERED -> {
|
PEEKED_BUFFERED -> {
|
||||||
val buffered = peekedString!!
|
val buffered = peekedString!!
|
||||||
peekedString = null
|
peekedString = null
|
||||||
buffered
|
buffered
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_LONG -> peekedLong.toString()
|
PEEKED_LONG -> peekedLong.toString()
|
||||||
|
|
||||||
PEEKED_NUMBER -> buffer.readUtf8(peekedNumberLength.toLong())
|
PEEKED_NUMBER -> buffer.readUtf8(peekedNumberLength.toLong())
|
||||||
|
|
||||||
else -> throw JsonDataException("Expected a string but was ${peek()} at path $path")
|
else -> throw JsonDataException("Expected a string but was ${peek()} at path $path")
|
||||||
}
|
}
|
||||||
peeked = PEEKED_NONE
|
peeked = PEEKED_NONE
|
||||||
@@ -601,11 +656,13 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
pathIndices[stackSize - 1]++
|
pathIndices[stackSize - 1]++
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_FALSE -> {
|
PEEKED_FALSE -> {
|
||||||
peeked = PEEKED_NONE
|
peeked = PEEKED_NONE
|
||||||
pathIndices[stackSize - 1]++
|
pathIndices[stackSize - 1]++
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw JsonDataException("Expected a boolean but was ${peek()} at path $path")
|
else -> throw JsonDataException("Expected a boolean but was ${peek()} at path $path")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -630,13 +687,18 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
}
|
}
|
||||||
val next = when (p) {
|
val next = when (p) {
|
||||||
PEEKED_NUMBER -> buffer.readUtf8(peekedNumberLength.toLong()).also { peekedString = it }
|
PEEKED_NUMBER -> buffer.readUtf8(peekedNumberLength.toLong()).also { peekedString = it }
|
||||||
|
|
||||||
PEEKED_DOUBLE_QUOTED -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH).also { peekedString = it }
|
PEEKED_DOUBLE_QUOTED -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH).also { peekedString = it }
|
||||||
|
|
||||||
PEEKED_SINGLE_QUOTED -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH).also { peekedString = it }
|
PEEKED_SINGLE_QUOTED -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH).also { peekedString = it }
|
||||||
|
|
||||||
PEEKED_UNQUOTED -> nextUnquotedValue().also { peekedString = it }
|
PEEKED_UNQUOTED -> nextUnquotedValue().also { peekedString = it }
|
||||||
|
|
||||||
PEEKED_BUFFERED -> {
|
PEEKED_BUFFERED -> {
|
||||||
// PEEKED_BUFFERED means the value's been stored in peekedString
|
// PEEKED_BUFFERED means the value's been stored in peekedString
|
||||||
knownNotNull(peekedString)
|
knownNotNull(peekedString)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw JsonDataException("Expected a double but was " + peek() + " at path " + path)
|
else -> throw JsonDataException("Expected a double but was " + peek() + " at path " + path)
|
||||||
}
|
}
|
||||||
peeked = PEEKED_BUFFERED
|
peeked = PEEKED_BUFFERED
|
||||||
@@ -663,6 +725,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
p == PEEKED_NUMBER -> peekedString = buffer.readUtf8(peekedNumberLength.toLong())
|
p == PEEKED_NUMBER -> peekedString = buffer.readUtf8(peekedNumberLength.toLong())
|
||||||
|
|
||||||
p == PEEKED_DOUBLE_QUOTED || p == PEEKED_SINGLE_QUOTED -> {
|
p == PEEKED_DOUBLE_QUOTED || p == PEEKED_SINGLE_QUOTED -> {
|
||||||
peekedString = if (p == PEEKED_DOUBLE_QUOTED) nextQuotedValue(DOUBLE_QUOTE_OR_SLASH) else nextQuotedValue(SINGLE_QUOTE_OR_SLASH)
|
peekedString = if (p == PEEKED_DOUBLE_QUOTED) nextQuotedValue(DOUBLE_QUOTE_OR_SLASH) else nextQuotedValue(SINGLE_QUOTE_OR_SLASH)
|
||||||
try {
|
try {
|
||||||
@@ -674,6 +737,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
// Fall back to parse as a BigDecimal below.
|
// Fall back to parse as a BigDecimal below.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p != PEEKED_BUFFERED -> {
|
p != PEEKED_BUFFERED -> {
|
||||||
throw JsonDataException("Expected a long but was " + peek() + " at path " + path)
|
throw JsonDataException("Expected a long but was " + peek() + " at path " + path)
|
||||||
}
|
}
|
||||||
@@ -768,6 +832,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
PEEKED_NUMBER -> {
|
PEEKED_NUMBER -> {
|
||||||
buffer.readUtf8(peekedNumberLength.toLong()).also { peekedString = it }
|
buffer.readUtf8(peekedNumberLength.toLong()).also { peekedString = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_DOUBLE_QUOTED, PEEKED_SINGLE_QUOTED -> {
|
PEEKED_DOUBLE_QUOTED, PEEKED_SINGLE_QUOTED -> {
|
||||||
val next = if (p == PEEKED_DOUBLE_QUOTED) {
|
val next = if (p == PEEKED_DOUBLE_QUOTED) {
|
||||||
nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
||||||
@@ -785,10 +850,12 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
next
|
next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_BUFFERED -> {
|
PEEKED_BUFFERED -> {
|
||||||
// PEEKED_BUFFERED means the value's been stored in peekedString
|
// PEEKED_BUFFERED means the value's been stored in peekedString
|
||||||
knownNotNull(peekedString)
|
knownNotNull(peekedString)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw JsonDataException("Expected an int but was ${peek()} at path $path")
|
else -> throw JsonDataException("Expected an int but was ${peek()} at path $path")
|
||||||
}
|
}
|
||||||
peeked = PEEKED_BUFFERED
|
peeked = PEEKED_BUFFERED
|
||||||
@@ -826,10 +893,12 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
pushScope(JsonScope.EMPTY_ARRAY)
|
pushScope(JsonScope.EMPTY_ARRAY)
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_BEGIN_OBJECT -> {
|
PEEKED_BEGIN_OBJECT -> {
|
||||||
pushScope(JsonScope.EMPTY_OBJECT)
|
pushScope(JsonScope.EMPTY_OBJECT)
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_END_ARRAY -> {
|
PEEKED_END_ARRAY -> {
|
||||||
count--
|
count--
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
@@ -837,6 +906,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
}
|
}
|
||||||
stackSize--
|
stackSize--
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_END_OBJECT -> {
|
PEEKED_END_OBJECT -> {
|
||||||
count--
|
count--
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
@@ -844,10 +914,15 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
}
|
}
|
||||||
stackSize--
|
stackSize--
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_UNQUOTED_NAME, PEEKED_UNQUOTED -> skipUnquotedValue()
|
PEEKED_UNQUOTED_NAME, PEEKED_UNQUOTED -> skipUnquotedValue()
|
||||||
|
|
||||||
PEEKED_DOUBLE_QUOTED, PEEKED_DOUBLE_QUOTED_NAME -> skipQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
PEEKED_DOUBLE_QUOTED, PEEKED_DOUBLE_QUOTED_NAME -> skipQuotedValue(DOUBLE_QUOTE_OR_SLASH)
|
||||||
|
|
||||||
PEEKED_SINGLE_QUOTED, PEEKED_SINGLE_QUOTED_NAME -> skipQuotedValue(SINGLE_QUOTE_OR_SLASH)
|
PEEKED_SINGLE_QUOTED, PEEKED_SINGLE_QUOTED_NAME -> skipQuotedValue(SINGLE_QUOTE_OR_SLASH)
|
||||||
|
|
||||||
PEEKED_NUMBER -> buffer.skip(peekedNumberLength.toLong())
|
PEEKED_NUMBER -> buffer.skip(peekedNumberLength.toLong())
|
||||||
|
|
||||||
PEEKED_EOF -> throw JsonDataException("Expected a value but was ${peek()} at path $path")
|
PEEKED_EOF -> throw JsonDataException("Expected a value but was ${peek()} at path $path")
|
||||||
}
|
}
|
||||||
peeked = PEEKED_NONE
|
peeked = PEEKED_NONE
|
||||||
@@ -867,29 +942,38 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
state = JsonValueSource.STATE_JSON
|
state = JsonValueSource.STATE_JSON
|
||||||
valueSourceStackSize++
|
valueSourceStackSize++
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_BEGIN_OBJECT -> {
|
PEEKED_BEGIN_OBJECT -> {
|
||||||
prefix.writeUtf8("{")
|
prefix.writeUtf8("{")
|
||||||
state = JsonValueSource.STATE_JSON
|
state = JsonValueSource.STATE_JSON
|
||||||
valueSourceStackSize++
|
valueSourceStackSize++
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_DOUBLE_QUOTED -> {
|
PEEKED_DOUBLE_QUOTED -> {
|
||||||
prefix.writeUtf8("\"")
|
prefix.writeUtf8("\"")
|
||||||
state = JsonValueSource.STATE_DOUBLE_QUOTED
|
state = JsonValueSource.STATE_DOUBLE_QUOTED
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_SINGLE_QUOTED -> {
|
PEEKED_SINGLE_QUOTED -> {
|
||||||
prefix.writeUtf8("'")
|
prefix.writeUtf8("'")
|
||||||
state = JsonValueSource.STATE_SINGLE_QUOTED
|
state = JsonValueSource.STATE_SINGLE_QUOTED
|
||||||
}
|
}
|
||||||
|
|
||||||
PEEKED_NUMBER, PEEKED_LONG, PEEKED_UNQUOTED -> prefix.writeUtf8(nextString())
|
PEEKED_NUMBER, PEEKED_LONG, PEEKED_UNQUOTED -> prefix.writeUtf8(nextString())
|
||||||
|
|
||||||
PEEKED_TRUE -> prefix.writeUtf8("true")
|
PEEKED_TRUE -> prefix.writeUtf8("true")
|
||||||
|
|
||||||
PEEKED_FALSE -> prefix.writeUtf8("false")
|
PEEKED_FALSE -> prefix.writeUtf8("false")
|
||||||
|
|
||||||
PEEKED_NULL -> prefix.writeUtf8("null")
|
PEEKED_NULL -> prefix.writeUtf8("null")
|
||||||
|
|
||||||
PEEKED_BUFFERED -> {
|
PEEKED_BUFFERED -> {
|
||||||
val string = nextString()
|
val string = nextString()
|
||||||
JsonWriter.of(prefix).use { jsonWriter ->
|
JsonWriter.of(prefix).use { jsonWriter ->
|
||||||
jsonWriter.value(string)
|
jsonWriter.value(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw JsonDataException("Expected a value but was ${peek()} at path $path")
|
else -> throw JsonDataException("Expected a value but was ${peek()} at path $path")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,6 +1026,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
p = 0
|
p = 0
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
'/' -> {
|
'/' -> {
|
||||||
// skip a // end-of-line comment
|
// skip a // end-of-line comment
|
||||||
buffer.readByte() // '/'
|
buffer.readByte() // '/'
|
||||||
@@ -950,9 +1035,11 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
p = 0
|
p = 0
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> c.code
|
else -> c.code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'#' -> {
|
'#' -> {
|
||||||
// Skip a # hash end-of-line comment. The JSON RFC doesn't specify this behaviour, but it's
|
// Skip a # hash end-of-line comment. The JSON RFC doesn't specify this behaviour, but it's
|
||||||
// required to parse existing documents.
|
// required to parse existing documents.
|
||||||
@@ -960,6 +1047,7 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
skipToEndOfLine()
|
skipToEndOfLine()
|
||||||
p = 0
|
p = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return c.code
|
else -> return c.code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1026,12 +1114,20 @@ internal class JsonUtf8Reader : JsonReader {
|
|||||||
buffer.skip(4)
|
buffer.skip(4)
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
't' -> '\t'
|
't' -> '\t'
|
||||||
|
|
||||||
'b' -> '\b'
|
'b' -> '\b'
|
||||||
|
|
||||||
'n' -> '\n'
|
'n' -> '\n'
|
||||||
|
|
||||||
'r' -> '\r'
|
'r' -> '\r'
|
||||||
'f' -> '\u000C' /*\f*/
|
|
||||||
|
/*\f*/
|
||||||
|
'f' -> '\u000C'
|
||||||
|
|
||||||
'\n', '\'', '"', '\\', '/' -> escaped
|
'\n', '\'', '"', '\\', '/' -> escaped
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if (!lenient) throw syntaxError("Invalid escape sequence: \\$escaped")
|
if (!lenient) throw syntaxError("Invalid escape sequence: \\$escaped")
|
||||||
escaped
|
escaped
|
||||||
|
@@ -302,21 +302,27 @@ internal class JsonUtf8Writer(
|
|||||||
}
|
}
|
||||||
nextTop = JsonScope.NONEMPTY_DOCUMENT
|
nextTop = JsonScope.NONEMPTY_DOCUMENT
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.EMPTY_DOCUMENT -> nextTop = JsonScope.NONEMPTY_DOCUMENT
|
JsonScope.EMPTY_DOCUMENT -> nextTop = JsonScope.NONEMPTY_DOCUMENT
|
||||||
|
|
||||||
JsonScope.NONEMPTY_ARRAY -> {
|
JsonScope.NONEMPTY_ARRAY -> {
|
||||||
sink.writeByte(','.code)
|
sink.writeByte(','.code)
|
||||||
newline()
|
newline()
|
||||||
nextTop = JsonScope.NONEMPTY_ARRAY
|
nextTop = JsonScope.NONEMPTY_ARRAY
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.EMPTY_ARRAY -> {
|
JsonScope.EMPTY_ARRAY -> {
|
||||||
newline()
|
newline()
|
||||||
nextTop = JsonScope.NONEMPTY_ARRAY
|
nextTop = JsonScope.NONEMPTY_ARRAY
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.DANGLING_NAME -> {
|
JsonScope.DANGLING_NAME -> {
|
||||||
nextTop = JsonScope.NONEMPTY_OBJECT
|
nextTop = JsonScope.NONEMPTY_OBJECT
|
||||||
sink.writeUtf8(separator)
|
sink.writeUtf8(separator)
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonScope.STREAMING_VALUE -> throw IllegalStateException("Sink from valueSink() was not closed")
|
JsonScope.STREAMING_VALUE -> throw IllegalStateException("Sink from valueSink() was not closed")
|
||||||
|
|
||||||
else -> throw IllegalStateException("Nesting problem.")
|
else -> throw IllegalStateException("Nesting problem.")
|
||||||
}
|
}
|
||||||
replaceTop(nextTop)
|
replaceTop(nextTop)
|
||||||
|
@@ -113,13 +113,21 @@ internal class JsonValueReader : JsonReader {
|
|||||||
// If the top of the stack is an iterator, take its first element and push it on the stack.
|
// If the top of the stack is an iterator, take its first element and push it on the stack.
|
||||||
return when (val peeked = stack[stackSize - 1]) {
|
return when (val peeked = stack[stackSize - 1]) {
|
||||||
is JsonIterator -> peeked.endToken
|
is JsonIterator -> peeked.endToken
|
||||||
|
|
||||||
is List<*> -> Token.BEGIN_ARRAY
|
is List<*> -> Token.BEGIN_ARRAY
|
||||||
|
|
||||||
is Map<*, *> -> Token.BEGIN_OBJECT
|
is Map<*, *> -> Token.BEGIN_OBJECT
|
||||||
|
|
||||||
is Map.Entry<*, *> -> Token.NAME
|
is Map.Entry<*, *> -> Token.NAME
|
||||||
|
|
||||||
is String -> Token.STRING
|
is String -> Token.STRING
|
||||||
|
|
||||||
is Boolean -> Token.BOOLEAN
|
is Boolean -> Token.BOOLEAN
|
||||||
|
|
||||||
is Number -> Token.NUMBER
|
is Number -> Token.NUMBER
|
||||||
|
|
||||||
null -> Token.NULL
|
null -> Token.NULL
|
||||||
|
|
||||||
else -> ifNotClosed(peeked) {
|
else -> ifNotClosed(peeked) {
|
||||||
throw typeMismatch(peeked, "a JSON value")
|
throw typeMismatch(peeked, "a JSON value")
|
||||||
}
|
}
|
||||||
@@ -170,10 +178,12 @@ internal class JsonValueReader : JsonReader {
|
|||||||
remove()
|
remove()
|
||||||
peeked
|
peeked
|
||||||
}
|
}
|
||||||
|
|
||||||
is Number -> {
|
is Number -> {
|
||||||
remove()
|
remove()
|
||||||
peeked.toString()
|
peeked.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> ifNotClosed(peeked) {
|
else -> ifNotClosed(peeked) {
|
||||||
throw typeMismatch(peeked, Token.STRING)
|
throw typeMismatch(peeked, Token.STRING)
|
||||||
}
|
}
|
||||||
@@ -211,6 +221,7 @@ internal class JsonValueReader : JsonReader {
|
|||||||
override fun nextDouble(): Double {
|
override fun nextDouble(): Double {
|
||||||
val result = when (val peeked = require<Any>(Token.NUMBER)) {
|
val result = when (val peeked = require<Any>(Token.NUMBER)) {
|
||||||
is Number -> peeked.toDouble()
|
is Number -> peeked.toDouble()
|
||||||
|
|
||||||
is String -> {
|
is String -> {
|
||||||
try {
|
try {
|
||||||
peeked.toDouble()
|
peeked.toDouble()
|
||||||
@@ -218,6 +229,7 @@ internal class JsonValueReader : JsonReader {
|
|||||||
throw typeMismatch(peeked, Token.NUMBER)
|
throw typeMismatch(peeked, Token.NUMBER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
throw typeMismatch(peeked, Token.NUMBER)
|
throw typeMismatch(peeked, Token.NUMBER)
|
||||||
}
|
}
|
||||||
@@ -232,6 +244,7 @@ internal class JsonValueReader : JsonReader {
|
|||||||
override fun nextLong(): Long {
|
override fun nextLong(): Long {
|
||||||
val result: Long = when (val peeked = require<Any>(Token.NUMBER)) {
|
val result: Long = when (val peeked = require<Any>(Token.NUMBER)) {
|
||||||
is Number -> peeked.toLong()
|
is Number -> peeked.toLong()
|
||||||
|
|
||||||
is String -> try {
|
is String -> try {
|
||||||
peeked.toLong()
|
peeked.toLong()
|
||||||
} catch (e: NumberFormatException) {
|
} catch (e: NumberFormatException) {
|
||||||
@@ -241,6 +254,7 @@ internal class JsonValueReader : JsonReader {
|
|||||||
throw typeMismatch(peeked, Token.NUMBER)
|
throw typeMismatch(peeked, Token.NUMBER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw typeMismatch(peeked, Token.NUMBER)
|
else -> throw typeMismatch(peeked, Token.NUMBER)
|
||||||
}
|
}
|
||||||
remove()
|
remove()
|
||||||
@@ -250,6 +264,7 @@ internal class JsonValueReader : JsonReader {
|
|||||||
override fun nextInt(): Int {
|
override fun nextInt(): Int {
|
||||||
val result = when (val peeked = require<Any>(Token.NUMBER)) {
|
val result = when (val peeked = require<Any>(Token.NUMBER)) {
|
||||||
is Number -> peeked.toInt()
|
is Number -> peeked.toInt()
|
||||||
|
|
||||||
is String -> try {
|
is String -> try {
|
||||||
peeked.toInt()
|
peeked.toInt()
|
||||||
} catch (e: NumberFormatException) {
|
} catch (e: NumberFormatException) {
|
||||||
@@ -259,6 +274,7 @@ internal class JsonValueReader : JsonReader {
|
|||||||
throw typeMismatch(peeked, Token.NUMBER)
|
throw typeMismatch(peeked, Token.NUMBER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw typeMismatch(peeked, Token.NUMBER)
|
else -> throw typeMismatch(peeked, Token.NUMBER)
|
||||||
}
|
}
|
||||||
remove()
|
remove()
|
||||||
|
@@ -91,19 +91,23 @@ internal class JsonValueSource @JvmOverloads constructor(
|
|||||||
stackSize++
|
stackSize++
|
||||||
limit = index + 1
|
limit = index + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
']', '}' -> {
|
']', '}' -> {
|
||||||
stackSize--
|
stackSize--
|
||||||
if (stackSize == 0) state = STATE_END_OF_JSON
|
if (stackSize == 0) state = STATE_END_OF_JSON
|
||||||
limit = index + 1
|
limit = index + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
'\"' -> {
|
'\"' -> {
|
||||||
state = STATE_DOUBLE_QUOTED
|
state = STATE_DOUBLE_QUOTED
|
||||||
limit = index + 1
|
limit = index + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
'\'' -> {
|
'\'' -> {
|
||||||
state = STATE_SINGLE_QUOTED
|
state = STATE_SINGLE_QUOTED
|
||||||
limit = index + 1
|
limit = index + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
'/' -> {
|
'/' -> {
|
||||||
source.require(index + 2)
|
source.require(index + 2)
|
||||||
when (buffer[index + 1]) {
|
when (buffer[index + 1]) {
|
||||||
@@ -111,20 +115,24 @@ internal class JsonValueSource @JvmOverloads constructor(
|
|||||||
state = STATE_END_OF_LINE_COMMENT
|
state = STATE_END_OF_LINE_COMMENT
|
||||||
limit = index + 2
|
limit = index + 2
|
||||||
}
|
}
|
||||||
|
|
||||||
'*'.code.toByte() -> {
|
'*'.code.toByte() -> {
|
||||||
state = STATE_C_STYLE_COMMENT
|
state = STATE_C_STYLE_COMMENT
|
||||||
limit = index + 2
|
limit = index + 2
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
limit = index + 1
|
limit = index + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'#' -> {
|
'#' -> {
|
||||||
state = STATE_END_OF_LINE_COMMENT
|
state = STATE_END_OF_LINE_COMMENT
|
||||||
limit = index + 1
|
limit = index + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state === STATE_SINGLE_QUOTED || state === STATE_DOUBLE_QUOTED -> {
|
state === STATE_SINGLE_QUOTED || state === STATE_DOUBLE_QUOTED -> {
|
||||||
if (b == '\\'.code.toByte()) {
|
if (b == '\\'.code.toByte()) {
|
||||||
source.require(index + 2)
|
source.require(index + 2)
|
||||||
@@ -134,6 +142,7 @@ internal class JsonValueSource @JvmOverloads constructor(
|
|||||||
limit = index + 1
|
limit = index + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state === STATE_C_STYLE_COMMENT -> {
|
state === STATE_C_STYLE_COMMENT -> {
|
||||||
source.require(index + 2)
|
source.require(index + 2)
|
||||||
if (buffer[index + 1] == '/'.code.toByte()) {
|
if (buffer[index + 1] == '/'.code.toByte()) {
|
||||||
@@ -143,10 +152,12 @@ internal class JsonValueSource @JvmOverloads constructor(
|
|||||||
limit = index + 1
|
limit = index + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state === STATE_END_OF_LINE_COMMENT -> {
|
state === STATE_END_OF_LINE_COMMENT -> {
|
||||||
limit = index + 1
|
limit = index + 1
|
||||||
state = STATE_JSON
|
state = STATE_JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
throw AssertionError()
|
throw AssertionError()
|
||||||
}
|
}
|
||||||
|
@@ -168,10 +168,13 @@ internal class JsonValueWriter : JsonWriter() {
|
|||||||
override fun value(value: Number?): JsonWriter = apply {
|
override fun value(value: Number?): JsonWriter = apply {
|
||||||
when (value) {
|
when (value) {
|
||||||
null -> nullValue()
|
null -> nullValue()
|
||||||
|
|
||||||
// If it's trivially converted to a long, do that.
|
// If it's trivially converted to a long, do that.
|
||||||
is Byte, is Short, is Int, is Long -> value(value.toLong())
|
is Byte, is Short, is Int, is Long -> value(value.toLong())
|
||||||
|
|
||||||
// If it's trivially converted to a double, do that.
|
// If it's trivially converted to a double, do that.
|
||||||
is Float, is Double -> value(value.toDouble())
|
is Float, is Double -> value(value.toDouble())
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
// Everything else gets converted to a BigDecimal.
|
// Everything else gets converted to a BigDecimal.
|
||||||
val bigDecimalValue = if (value is BigDecimal) value else BigDecimal(value.toString())
|
val bigDecimalValue = if (value is BigDecimal) value else BigDecimal(value.toString())
|
||||||
@@ -229,6 +232,7 @@ internal class JsonValueWriter : JsonWriter() {
|
|||||||
scopes[stackSize - 1] = NONEMPTY_DOCUMENT
|
scopes[stackSize - 1] = NONEMPTY_DOCUMENT
|
||||||
stack[stackSize - 1] = newTop
|
stack[stackSize - 1] = newTop
|
||||||
}
|
}
|
||||||
|
|
||||||
scope == EMPTY_OBJECT && deferredName != null -> {
|
scope == EMPTY_OBJECT && deferredName != null -> {
|
||||||
if (newTop != null || serializeNulls) {
|
if (newTop != null || serializeNulls) {
|
||||||
// Our maps always have string keys and object values.
|
// Our maps always have string keys and object values.
|
||||||
@@ -242,13 +246,16 @@ internal class JsonValueWriter : JsonWriter() {
|
|||||||
}
|
}
|
||||||
deferredName = null
|
deferredName = null
|
||||||
}
|
}
|
||||||
|
|
||||||
scope == EMPTY_ARRAY -> {
|
scope == EMPTY_ARRAY -> {
|
||||||
// Our lists always have object values.
|
// Our lists always have object values.
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val list = stack[stackSize - 1] as MutableList<Any?>
|
val list = stack[stackSize - 1] as MutableList<Any?>
|
||||||
list.add(newTop)
|
list.add(newTop)
|
||||||
}
|
}
|
||||||
|
|
||||||
scope == STREAMING_VALUE -> throw IllegalStateException("Sink from valueSink() was not closed")
|
scope == STREAMING_VALUE -> throw IllegalStateException("Sink from valueSink() was not closed")
|
||||||
|
|
||||||
else -> throw IllegalStateException("Nesting problem.")
|
else -> throw IllegalStateException("Nesting problem.")
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
|
@@ -151,22 +151,15 @@ public sealed class JsonWriter : Closeable, Flushable {
|
|||||||
* pretty printing.
|
* pretty printing.
|
||||||
*/
|
*/
|
||||||
@JvmField
|
@JvmField
|
||||||
@Suppress("ktlint:standard:property-naming") // Exposed to sealed subtypes.
|
@Suppress("ktlint:standard:backing-property-naming") // Exposed to sealed subtypes.
|
||||||
protected var _indent: String? = null
|
protected var _indent: String? = null
|
||||||
public open var indent: String
|
|
||||||
/**
|
|
||||||
* Returns a string containing only whitespace, used for each level of indentation. If empty,
|
|
||||||
* the encoded document will be compact.
|
|
||||||
*/
|
|
||||||
get() = _indent.orEmpty()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the indentation string to be repeated for each level of indentation in the encoded
|
* A string containing only whitespace, used for each level of indentation.
|
||||||
* document. If `indent.isEmpty()` the encoded document will be compact. Otherwise, the
|
* If empty, the encoded document will be compact.
|
||||||
* encoded document will be more human-readable.
|
*/
|
||||||
*
|
public open var indent: String
|
||||||
* @param value a string containing only whitespace.
|
get() = _indent.orEmpty()
|
||||||
*/
|
|
||||||
set(value) {
|
set(value) {
|
||||||
_indent = value.ifEmpty { null }
|
_indent = value.ifEmpty { null }
|
||||||
}
|
}
|
||||||
@@ -402,6 +395,7 @@ public sealed class JsonWriter : Closeable, Flushable {
|
|||||||
}
|
}
|
||||||
endObject()
|
endObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
is List<*> -> {
|
is List<*> -> {
|
||||||
beginArray()
|
beginArray()
|
||||||
for (element in value) {
|
for (element in value) {
|
||||||
@@ -409,12 +403,19 @@ public sealed class JsonWriter : Closeable, Flushable {
|
|||||||
}
|
}
|
||||||
endArray()
|
endArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
is String -> value(value as String?)
|
is String -> value(value as String?)
|
||||||
|
|
||||||
is Boolean -> value(value)
|
is Boolean -> value(value)
|
||||||
|
|
||||||
is Double -> value(value)
|
is Double -> value(value)
|
||||||
|
|
||||||
is Long -> value(value)
|
is Long -> value(value)
|
||||||
|
|
||||||
is Number -> value(value)
|
is Number -> value(value)
|
||||||
|
|
||||||
null -> nullValue()
|
null -> nullValue()
|
||||||
|
|
||||||
else -> throw IllegalArgumentException("Unsupported type: ${value.javaClass.name}")
|
else -> throw IllegalArgumentException("Unsupported type: ${value.javaClass.name}")
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
|
@@ -14,14 +14,10 @@ private val NATURAL_ORDER = Comparator<Any> { o1, o2 -> (o1 as Comparable<Any>).
|
|||||||
* removal.
|
* removal.
|
||||||
*
|
*
|
||||||
* This implementation was derived from Android 4.1's TreeMap and LinkedHashMap classes.
|
* This implementation was derived from Android 4.1's TreeMap and LinkedHashMap classes.
|
||||||
*/
|
|
||||||
internal class LinkedHashTreeMap<K, V>
|
|
||||||
/**
|
|
||||||
* Create a tree map ordered by [comparator]. This map's keys may only be null if [comparator] permits.
|
|
||||||
*
|
*
|
||||||
* @param comparator the comparator to order elements with, or null to use the natural ordering.
|
* @param comparator the comparator to order elements with, or null to use the natural ordering.
|
||||||
*/
|
*/
|
||||||
constructor(
|
internal class LinkedHashTreeMap<K, V>(
|
||||||
comparator: Comparator<Any?>? = null,
|
comparator: Comparator<Any?>? = null,
|
||||||
) : AbstractMutableMap<K, V>(), Serializable {
|
) : AbstractMutableMap<K, V>(), Serializable {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -402,6 +398,7 @@ constructor(
|
|||||||
break // no further rotations will be necessary
|
break // no further rotations will be necessary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
2 -> {
|
2 -> {
|
||||||
val leftLeft = left!!.left
|
val leftLeft = left!!.left
|
||||||
val leftRight = left.right
|
val leftRight = left.right
|
||||||
@@ -417,12 +414,14 @@ constructor(
|
|||||||
break // no further rotations will be necessary
|
break // no further rotations will be necessary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
0 -> {
|
0 -> {
|
||||||
node.height = leftHeight + 1 // leftHeight == rightHeight
|
node.height = leftHeight + 1 // leftHeight == rightHeight
|
||||||
if (insert) {
|
if (insert) {
|
||||||
break // the insert caused balance, so rebalancing is done!
|
break // the insert caused balance, so rebalancing is done!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
assert(delta == -1 || delta == 1)
|
assert(delta == -1 || delta == 1)
|
||||||
node.height = max(leftHeight, rightHeight) + 1
|
node.height = max(leftHeight, rightHeight) + 1
|
||||||
@@ -748,6 +747,7 @@ internal class AvlBuilder<K, V> {
|
|||||||
left.parent = center
|
left.parent = center
|
||||||
right.parent = center
|
right.parent = center
|
||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
// Pop right and center, then make center the top of the stack.
|
// Pop right and center, then make center the top of the stack.
|
||||||
val right = stack
|
val right = stack
|
||||||
@@ -759,6 +759,7 @@ internal class AvlBuilder<K, V> {
|
|||||||
right.parent = center
|
right.parent = center
|
||||||
leavesSkipped = 0
|
leavesSkipped = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
2 -> {
|
2 -> {
|
||||||
leavesSkipped = 0
|
leavesSkipped = 0
|
||||||
}
|
}
|
||||||
|
@@ -238,11 +238,17 @@ internal object StandardJsonAdapters : JsonAdapter.Factory {
|
|||||||
override fun fromJson(reader: JsonReader): Any? {
|
override fun fromJson(reader: JsonReader): Any? {
|
||||||
return when (reader.peek()) {
|
return when (reader.peek()) {
|
||||||
JsonReader.Token.BEGIN_ARRAY -> listJsonAdapter.fromJson(reader)
|
JsonReader.Token.BEGIN_ARRAY -> listJsonAdapter.fromJson(reader)
|
||||||
|
|
||||||
JsonReader.Token.BEGIN_OBJECT -> mapAdapter.fromJson(reader)
|
JsonReader.Token.BEGIN_OBJECT -> mapAdapter.fromJson(reader)
|
||||||
|
|
||||||
JsonReader.Token.STRING -> stringAdapter.fromJson(reader)
|
JsonReader.Token.STRING -> stringAdapter.fromJson(reader)
|
||||||
|
|
||||||
JsonReader.Token.NUMBER -> doubleAdapter.fromJson(reader)
|
JsonReader.Token.NUMBER -> doubleAdapter.fromJson(reader)
|
||||||
|
|
||||||
JsonReader.Token.BOOLEAN -> booleanAdapter.fromJson(reader)
|
JsonReader.Token.BOOLEAN -> booleanAdapter.fromJson(reader)
|
||||||
|
|
||||||
JsonReader.Token.NULL -> reader.nextNull()
|
JsonReader.Token.NULL -> reader.nextNull()
|
||||||
|
|
||||||
else -> throw IllegalStateException(
|
else -> throw IllegalStateException(
|
||||||
"Expected a value but was ${reader.peek()} at path ${reader.path}",
|
"Expected a value but was ${reader.peek()} at path ${reader.path}",
|
||||||
)
|
)
|
||||||
|
@@ -163,22 +163,27 @@ public object Types {
|
|||||||
// type is a normal class.
|
// type is a normal class.
|
||||||
type
|
type
|
||||||
}
|
}
|
||||||
|
|
||||||
is ParameterizedType -> {
|
is ParameterizedType -> {
|
||||||
// I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
|
// I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
|
||||||
// suspects some pathological case related to nested classes exists.
|
// suspects some pathological case related to nested classes exists.
|
||||||
val rawType = type.rawType
|
val rawType = type.rawType
|
||||||
rawType as Class<*>
|
rawType as Class<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
is GenericArrayType -> {
|
is GenericArrayType -> {
|
||||||
val componentType = type.genericComponentType
|
val componentType = type.genericComponentType
|
||||||
java.lang.reflect.Array.newInstance(getRawType(componentType), 0).javaClass
|
java.lang.reflect.Array.newInstance(getRawType(componentType), 0).javaClass
|
||||||
}
|
}
|
||||||
|
|
||||||
is TypeVariable<*> -> {
|
is TypeVariable<*> -> {
|
||||||
// We could use the variable's bounds, but that won't work if there are multiple. having a raw
|
// We could use the variable's bounds, but that won't work if there are multiple. having a raw
|
||||||
// type that's more general than necessary is okay.
|
// type that's more general than necessary is okay.
|
||||||
Any::class.java
|
Any::class.java
|
||||||
}
|
}
|
||||||
|
|
||||||
is WildcardType -> getRawType(type.upperBounds[0])
|
is WildcardType -> getRawType(type.upperBounds[0])
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val className = type?.javaClass?.name?.toString()
|
val className = type?.javaClass?.name?.toString()
|
||||||
throw IllegalArgumentException("Expected a Class, ParameterizedType, or GenericArrayType, but <$type> is of type $className")
|
throw IllegalArgumentException("Expected a Class, ParameterizedType, or GenericArrayType, but <$type> is of type $className")
|
||||||
@@ -222,6 +227,7 @@ public object Types {
|
|||||||
a == b // Class already specifies equals().
|
a == b // Class already specifies equals().
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is ParameterizedType -> {
|
is ParameterizedType -> {
|
||||||
// Class instance with generic info, from method return types
|
// Class instance with generic info, from method return types
|
||||||
if (b is Class<*> && a.rawType == b.rawType) {
|
if (b is Class<*> && a.rawType == b.rawType) {
|
||||||
@@ -235,6 +241,7 @@ public object Types {
|
|||||||
(a.rawType == b.rawType) && aTypeArguments.contentEquals(bTypeArguments)
|
(a.rawType == b.rawType) && aTypeArguments.contentEquals(bTypeArguments)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is GenericArrayType -> {
|
is GenericArrayType -> {
|
||||||
if (b is Class<*>) {
|
if (b is Class<*>) {
|
||||||
return equals(b.componentType, a.genericComponentType)
|
return equals(b.componentType, a.genericComponentType)
|
||||||
@@ -242,14 +249,17 @@ public object Types {
|
|||||||
if (b !is GenericArrayType) return false
|
if (b !is GenericArrayType) return false
|
||||||
return equals(a.genericComponentType, b.genericComponentType)
|
return equals(a.genericComponentType, b.genericComponentType)
|
||||||
}
|
}
|
||||||
|
|
||||||
is WildcardType -> {
|
is WildcardType -> {
|
||||||
if (b !is WildcardType) return false
|
if (b !is WildcardType) return false
|
||||||
return (a.upperBounds.contentEquals(b.upperBounds) && a.lowerBounds.contentEquals(b.lowerBounds))
|
return (a.upperBounds.contentEquals(b.upperBounds) && a.lowerBounds.contentEquals(b.lowerBounds))
|
||||||
}
|
}
|
||||||
|
|
||||||
is TypeVariable<*> -> {
|
is TypeVariable<*> -> {
|
||||||
if (b !is TypeVariable<*>) return false
|
if (b !is TypeVariable<*>) return false
|
||||||
return (a.genericDeclaration === b.genericDeclaration && (a.name == b.name))
|
return (a.genericDeclaration === b.genericDeclaration && (a.name == b.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return false // This isn't a supported type.
|
else -> return false // This isn't a supported type.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,12 +315,16 @@ public object Types {
|
|||||||
) { proxy, method, args ->
|
) { proxy, method, args ->
|
||||||
when (method.name) {
|
when (method.name) {
|
||||||
"annotationType" -> annotationType
|
"annotationType" -> annotationType
|
||||||
|
|
||||||
"equals" -> {
|
"equals" -> {
|
||||||
val o = args[0]
|
val o = args[0]
|
||||||
annotationType.isInstance(o)
|
annotationType.isInstance(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
"hashCode" -> 0
|
"hashCode" -> 0
|
||||||
|
|
||||||
"toString" -> "@${annotationType.name}()"
|
"toString" -> "@${annotationType.name}()"
|
||||||
|
|
||||||
else -> method.invoke(proxy, *args)
|
else -> method.invoke(proxy, *args)
|
||||||
}
|
}
|
||||||
} as T
|
} as T
|
||||||
|
@@ -176,18 +176,22 @@ internal fun Type.canonicalize(): Type {
|
|||||||
is Class<*> -> {
|
is Class<*> -> {
|
||||||
if (isArray) GenericArrayTypeImpl(this@canonicalize.componentType.canonicalize()) else this
|
if (isArray) GenericArrayTypeImpl(this@canonicalize.componentType.canonicalize()) else this
|
||||||
}
|
}
|
||||||
|
|
||||||
is ParameterizedType -> {
|
is ParameterizedType -> {
|
||||||
if (this is ParameterizedTypeImpl) return this
|
if (this is ParameterizedTypeImpl) return this
|
||||||
ParameterizedTypeImpl(ownerType, rawType, *actualTypeArguments)
|
ParameterizedTypeImpl(ownerType, rawType, *actualTypeArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
is GenericArrayType -> {
|
is GenericArrayType -> {
|
||||||
if (this is GenericArrayTypeImpl) return this
|
if (this is GenericArrayTypeImpl) return this
|
||||||
GenericArrayTypeImpl(genericComponentType)
|
GenericArrayTypeImpl(genericComponentType)
|
||||||
}
|
}
|
||||||
|
|
||||||
is WildcardType -> {
|
is WildcardType -> {
|
||||||
if (this is WildcardTypeImpl) return this
|
if (this is WildcardTypeImpl) return this
|
||||||
WildcardTypeImpl(upperBounds, lowerBounds)
|
WildcardTypeImpl(upperBounds, lowerBounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> this // This type is unsupported!
|
else -> this // This type is unsupported!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,18 +230,21 @@ private fun Type.resolve(
|
|||||||
toResolve = resolveTypeVariable(context, contextRawType, typeVariable)
|
toResolve = resolveTypeVariable(context, contextRawType, typeVariable)
|
||||||
if (toResolve === typeVariable) return toResolve
|
if (toResolve === typeVariable) return toResolve
|
||||||
}
|
}
|
||||||
|
|
||||||
toResolve is Class<*> && toResolve.isArray -> {
|
toResolve is Class<*> && toResolve.isArray -> {
|
||||||
val original = toResolve
|
val original = toResolve
|
||||||
val componentType: Type = original.componentType
|
val componentType: Type = original.componentType
|
||||||
val newComponentType = componentType.resolve(context, contextRawType, visitedTypeVariables)
|
val newComponentType = componentType.resolve(context, contextRawType, visitedTypeVariables)
|
||||||
return if (componentType === newComponentType) original else newComponentType.asArrayType()
|
return if (componentType === newComponentType) original else newComponentType.asArrayType()
|
||||||
}
|
}
|
||||||
|
|
||||||
toResolve is GenericArrayType -> {
|
toResolve is GenericArrayType -> {
|
||||||
val original = toResolve
|
val original = toResolve
|
||||||
val componentType = original.genericComponentType
|
val componentType = original.genericComponentType
|
||||||
val newComponentType = componentType.resolve(context, contextRawType, visitedTypeVariables)
|
val newComponentType = componentType.resolve(context, contextRawType, visitedTypeVariables)
|
||||||
return if (componentType === newComponentType) original else newComponentType.asArrayType()
|
return if (componentType === newComponentType) original else newComponentType.asArrayType()
|
||||||
}
|
}
|
||||||
|
|
||||||
toResolve is ParameterizedType -> {
|
toResolve is ParameterizedType -> {
|
||||||
val original = toResolve
|
val original = toResolve
|
||||||
val ownerType: Type? = original.ownerType
|
val ownerType: Type? = original.ownerType
|
||||||
@@ -258,6 +265,7 @@ private fun Type.resolve(
|
|||||||
}
|
}
|
||||||
return if (changed) ParameterizedTypeImpl(newOwnerType, original.rawType, *args) else original
|
return if (changed) ParameterizedTypeImpl(newOwnerType, original.rawType, *args) else original
|
||||||
}
|
}
|
||||||
|
|
||||||
toResolve is WildcardType -> {
|
toResolve is WildcardType -> {
|
||||||
val original = toResolve
|
val original = toResolve
|
||||||
val originalLowerBound = original.lowerBounds
|
val originalLowerBound = original.lowerBounds
|
||||||
@@ -275,6 +283,7 @@ private fun Type.resolve(
|
|||||||
}
|
}
|
||||||
return original
|
return original
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return toResolve
|
else -> return toResolve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user