Skip to content

Commit

Permalink
Convert util package to Kotlin (#1461)
Browse files Browse the repository at this point in the history
* Rename .java to .kt

* Convert NonNullJsonAdapter

* Rename .java to .kt

* Convert NullSafeJsonAdapter

* Fix missing null-check

* Rename .java to .kt

* Convert Util (initial pass)

* Push to top-level Util

* Use extensions and properties where possible

* Use knownNotNull

* Spotless

* Clean up impl type classes a bit

* Update code gen

* Use extension for resolving

* Spotless

* Fix master conflicts

* Rename to toStringWithAnnotations()

* for (t in args.indices) {

* for (i in interfaces.indices) {

* Template
  • Loading branch information
ZacSweers committed Jan 6, 2022
1 parent e5e4c48 commit e2c346e
Show file tree
Hide file tree
Showing 21 changed files with 790 additions and 875 deletions.
Expand Up @@ -78,7 +78,7 @@ public JsonAdapter<?> create(
nameStrings = new String[constants.length];
for (int i = 0; i < constants.length; i++) {
String constantName = constants[i].name();
nameStrings[i] = Util.jsonName(constantName, enumType.getField(constantName));
nameStrings[i] = Util.jsonName(enumType.getField(constantName), constantName);
}
options = JsonReader.Options.of(nameStrings);
} catch (NoSuchFieldException e) {
Expand Down
Expand Up @@ -68,7 +68,7 @@ public EnumJsonAdapter<T> withUnknownFallback(@Nullable T fallbackValue) {
nameStrings = new String[constants.length];
for (int i = 0; i < constants.length; i++) {
String constantName = constants[i].name();
nameStrings[i] = jsonName(constantName, enumType.getField(constantName));
nameStrings[i] = jsonName(enumType.getField(constantName), constantName);
}
options = JsonReader.Options.of(nameStrings);
} catch (NoSuchFieldException e) {
Expand Down
Expand Up @@ -39,15 +39,14 @@ import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.internal.Util
import com.squareup.moshi.kotlin.codegen.api.FromJsonComponent.ParameterOnly
import com.squareup.moshi.kotlin.codegen.api.FromJsonComponent.ParameterProperty
import com.squareup.moshi.kotlin.codegen.api.FromJsonComponent.PropertyOnly
import java.lang.reflect.Constructor
import java.lang.reflect.Type
import org.objectweb.asm.Type as AsmType

private val MOSHI_UTIL = Util::class.asClassName()
private const val MOSHI_UTIL_PACKAGE = "com.squareup.moshi.internal"
private const val TO_STRING_PREFIX = "GeneratedJsonAdapter("
private const val TO_STRING_SIZE_BASE = TO_STRING_PREFIX.length + 1 // 1 is the closing paren

Expand All @@ -61,8 +60,8 @@ public class AdapterGenerator(
private companion object {
private val INT_TYPE_BLOCK = CodeBlock.of("%T::class.javaPrimitiveType", INT)
private val DEFAULT_CONSTRUCTOR_MARKER_TYPE_BLOCK = CodeBlock.of(
"%T.DEFAULT_CONSTRUCTOR_MARKER",
Util::class
"%M",
MemberName(MOSHI_UTIL_PACKAGE, "DEFAULT_CONSTRUCTOR_MARKER")
)
private val CN_MOSHI = Moshi::class.asClassName()
private val CN_TYPE = Type::class.asClassName()
Expand Down Expand Up @@ -656,8 +655,8 @@ public class AdapterGenerator(

private fun unexpectedNull(property: PropertyGenerator, reader: ParameterSpec): CodeBlock {
return CodeBlock.of(
"%T.unexpectedNull(%S, %S, %N)",
MOSHI_UTIL,
"%M(%S, %S, %N)",
MemberName(MOSHI_UTIL_PACKAGE, "unexpectedNull"),
property.localName,
property.jsonName,
reader
Expand Down Expand Up @@ -699,8 +698,8 @@ public class AdapterGenerator(
private fun FunSpec.Builder.addMissingPropertyCheck(property: PropertyGenerator, readerParam: ParameterSpec) {
val missingPropertyBlock =
CodeBlock.of(
"%T.missingProperty(%S, %S, %N)",
MOSHI_UTIL,
"%M(%S, %S, %N)",
MemberName(MOSHI_UTIL_PACKAGE, "missingProperty"),
property.localName,
property.jsonName,
readerParam
Expand Down
Expand Up @@ -1270,7 +1270,7 @@ class GeneratedAdaptersTest {
@Test fun customGenerator_withClassPresent() {
val moshi = Moshi.Builder().build()
val adapter = moshi.adapter<CustomGeneratedClass>()
val unwrapped = (adapter as NullSafeJsonAdapter<CustomGeneratedClass>).delegate()
val unwrapped = (adapter as NullSafeJsonAdapter<CustomGeneratedClass>).delegate
assertThat(unwrapped).isInstanceOf(
GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter::class.java
)
Expand Down
Expand Up @@ -22,9 +22,12 @@ import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import com.squareup.moshi.internal.Util
import com.squareup.moshi.internal.Util.generatedAdapter
import com.squareup.moshi.internal.Util.resolve
import com.squareup.moshi.internal.generatedAdapter
import com.squareup.moshi.internal.isPlatformType
import com.squareup.moshi.internal.jsonAnnotations
import com.squareup.moshi.internal.missingProperty
import com.squareup.moshi.internal.resolve
import com.squareup.moshi.internal.unexpectedNull
import com.squareup.moshi.rawType
import java.lang.reflect.Modifier
import java.lang.reflect.Type
Expand Down Expand Up @@ -86,7 +89,7 @@ internal class KotlinJsonAdapter<T>(
values[propertyIndex] = binding.adapter.fromJson(reader)

if (values[propertyIndex] == null && !binding.property.returnType.isMarkedNullable) {
throw Util.unexpectedNull(
throw unexpectedNull(
binding.property.name,
binding.jsonName,
reader
Expand All @@ -102,7 +105,7 @@ internal class KotlinJsonAdapter<T>(
when {
constructor.parameters[i].isOptional -> isFullInitialized = false
constructor.parameters[i].type.isMarkedNullable -> values[i] = null // Replace absent with null.
else -> throw Util.missingProperty(
else -> throw missingProperty(
constructor.parameters[i].name,
allBindings[i]?.jsonName,
reader
Expand Down Expand Up @@ -195,9 +198,9 @@ public class KotlinJsonAdapterFactory : JsonAdapter.Factory {
if (rawType.isInterface) return null
if (rawType.isEnum) return null
if (!rawType.isAnnotationPresent(KOTLIN_METADATA)) return null
if (Util.isPlatformType(rawType)) return null
if (rawType.isPlatformType) return null
try {
val generatedAdapter = generatedAdapter(moshi, type, rawType)
val generatedAdapter = moshi.generatedAdapter(type, rawType)
if (generatedAdapter != null) {
return generatedAdapter
}
Expand Down Expand Up @@ -288,10 +291,10 @@ public class KotlinJsonAdapterFactory : JsonAdapter.Factory {
}
else -> error("Not possible!")
}
val resolvedPropertyType = resolve(type, rawType, propertyType)
val resolvedPropertyType = propertyType.resolve(type, rawType)
val adapter = moshi.adapter<Any?>(
resolvedPropertyType,
Util.jsonAnnotations(allAnnotations.toTypedArray()),
allAnnotations.toTypedArray().jsonAnnotations,
property.name
)

Expand Down
6 changes: 3 additions & 3 deletions moshi/build.gradle.kts
Expand Up @@ -52,12 +52,12 @@ tasks.withType<Test>().configureEach {
tasks.withType<KotlinCompile>()
.configureEach {
kotlinOptions {
val args = mutableListOf("-Xopt-in=kotlin.contracts.ExperimentalContracts")
val toAdd = mutableListOf("-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlin.contracts.ExperimentalContracts")
if (name.contains("test", true)) {
args += "-Xopt-in=kotlin.ExperimentalStdlibApi"
toAdd += "-Xopt-in=kotlin.ExperimentalStdlibApi"
}
@Suppress("SuspiciousCollectionReassignment") // It's not suspicious
freeCompilerArgs += args
freeCompilerArgs += toAdd
}
}

Expand Down
Expand Up @@ -15,7 +15,7 @@
*/
package com.squareup.moshi

import com.squareup.moshi.internal.Util
import com.squareup.moshi.internal.boxIfPrimitive
import java.lang.reflect.GenericArrayType
import java.lang.reflect.Type
import java.lang.reflect.WildcardType
Expand All @@ -42,7 +42,7 @@ public inline fun <reified T : Annotation> Set<Annotation>.nextAnnotations(): Se
public inline fun <reified T> subtypeOf(): WildcardType {
var type = typeOf<T>().javaType
if (type is Class<*>) {
type = Util.boxIfPrimitive(type)
type = type.boxIfPrimitive()
}
return Types.subtypeOf(type)
}
Expand All @@ -55,7 +55,7 @@ public inline fun <reified T> subtypeOf(): WildcardType {
public inline fun <reified T> supertypeOf(): WildcardType {
var type = typeOf<T>().javaType
if (type is Class<*>) {
type = Util.boxIfPrimitive(type)
type = type.boxIfPrimitive()
}
return Types.supertypeOf(type)
}
Expand Down
22 changes: 11 additions & 11 deletions moshi/src/main/java/com/squareup/moshi/AdapterMethodsFactory.java
Expand Up @@ -16,8 +16,8 @@
package com.squareup.moshi;

import static com.squareup.moshi.internal.Util.canonicalize;
import static com.squareup.moshi.internal.Util.jsonAnnotations;
import static com.squareup.moshi.internal.Util.typeAnnotatedWithAnnotations;
import static com.squareup.moshi.internal.Util.getJsonAnnotations;
import static com.squareup.moshi.internal.Util.toStringWithAnnotations;

import com.squareup.moshi.internal.Util;
import java.io.IOException;
Expand Down Expand Up @@ -57,7 +57,7 @@ final class AdapterMethodsFactory implements JsonAdapter.Factory {
"No "
+ missingAnnotation
+ " adapter for "
+ typeAnnotatedWithAnnotations(type, annotations),
+ toStringWithAnnotations(type, annotations),
e);
}
} else {
Expand Down Expand Up @@ -172,7 +172,7 @@ static AdapterMethod toAdapter(Object adapter, Method method) {
&& parametersAreJsonAdapters(2, parameterTypes)) {
// void pointToJson(JsonWriter jsonWriter, Point point) {
// void pointToJson(JsonWriter jsonWriter, Point point, JsonAdapter<?> adapter, ...) {
Set<? extends Annotation> qualifierAnnotations = jsonAnnotations(parameterAnnotations[1]);
Set<? extends Annotation> qualifierAnnotations = getJsonAnnotations(parameterAnnotations[1]);
return new AdapterMethod(
parameterTypes[1],
qualifierAnnotations,
Expand All @@ -190,10 +190,10 @@ public void toJson(Moshi moshi, JsonWriter writer, @Nullable Object value)

} else if (parameterTypes.length == 1 && returnType != void.class) {
// List<Integer> pointToJson(Point point) {
final Set<? extends Annotation> returnTypeAnnotations = jsonAnnotations(method);
final Set<? extends Annotation> returnTypeAnnotations = Util.getJsonAnnotations(method);
final Set<? extends Annotation> qualifierAnnotations =
jsonAnnotations(parameterAnnotations[0]);
boolean nullable = Util.hasNullable(parameterAnnotations[0]);
getJsonAnnotations(parameterAnnotations[0]);
boolean nullable = Util.getHasNullable(parameterAnnotations[0]);
return new AdapterMethod(
parameterTypes[0],
qualifierAnnotations,
Expand Down Expand Up @@ -251,7 +251,7 @@ private static boolean parametersAreJsonAdapters(int offset, Type[] parameterTyp
static AdapterMethod fromAdapter(Object adapter, Method method) {
method.setAccessible(true);
final Type returnType = method.getGenericReturnType();
final Set<? extends Annotation> returnTypeAnnotations = jsonAnnotations(method);
final Set<? extends Annotation> returnTypeAnnotations = Util.getJsonAnnotations(method);
final Type[] parameterTypes = method.getGenericParameterTypes();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();

Expand All @@ -273,8 +273,8 @@ public Object fromJson(Moshi moshi, JsonReader reader)
} else if (parameterTypes.length == 1 && returnType != void.class) {
// Point pointFromJson(List<Integer> o) {
final Set<? extends Annotation> qualifierAnnotations =
jsonAnnotations(parameterAnnotations[0]);
boolean nullable = Util.hasNullable(parameterAnnotations[0]);
getJsonAnnotations(parameterAnnotations[0]);
boolean nullable = Util.getHasNullable(parameterAnnotations[0]);
return new AdapterMethod(
returnType, returnTypeAnnotations, adapter, method, parameterTypes.length, 1, nullable) {
JsonAdapter<Object> delegate;
Expand Down Expand Up @@ -354,7 +354,7 @@ public void bind(Moshi moshi, JsonAdapter.Factory factory) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (int i = adaptersOffset, size = parameterTypes.length; i < size; i++) {
Type type = ((ParameterizedType) parameterTypes[i]).getActualTypeArguments()[0];
Set<? extends Annotation> jsonAnnotations = jsonAnnotations(parameterAnnotations[i]);
Set<? extends Annotation> jsonAnnotations = getJsonAnnotations(parameterAnnotations[i]);
jsonAdapters[i - adaptersOffset] =
Types.equals(this.type, type) && annotations.equals(jsonAnnotations)
? moshi.nextAdapter(factory, type, jsonAnnotations)
Expand Down
6 changes: 3 additions & 3 deletions moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.java
Expand Up @@ -139,16 +139,16 @@ private void createFieldBindings(
if (jsonAnnotation != null && jsonAnnotation.ignore()) continue;

// Look up a type adapter for this type.
Type fieldType = resolve(type, rawType, field.getGenericType());
Set<? extends Annotation> annotations = Util.jsonAnnotations(field);
Type fieldType = resolve(field.getGenericType(), type, rawType);
Set<? extends Annotation> annotations = Util.getJsonAnnotations(field);
String fieldName = field.getName();
JsonAdapter<Object> adapter = moshi.adapter(fieldType, annotations, fieldName);

// Create the binding between field and JSON.
field.setAccessible(true);

// Store it using the field's name. If there was already a field with this name, fail!
String jsonName = jsonName(fieldName, jsonAnnotation);
String jsonName = jsonName(jsonAnnotation, fieldName);
FieldBinding<Object> fieldBinding = new FieldBinding<>(jsonName, field, adapter);
FieldBinding<?> replaced = fieldBindings.put(jsonName, fieldBinding);
if (replaced != null) {
Expand Down
26 changes: 13 additions & 13 deletions moshi/src/main/java/com/squareup/moshi/Moshi.kt
Expand Up @@ -16,12 +16,12 @@
package com.squareup.moshi

import com.squareup.moshi.Types.createJsonQualifierImplementation
import com.squareup.moshi.internal.Util
import com.squareup.moshi.internal.Util.canonicalize
import com.squareup.moshi.internal.Util.isAnnotationPresent
import com.squareup.moshi.internal.Util.removeSubtypeWildcard
import com.squareup.moshi.internal.Util.typeAnnotatedWithAnnotations
import com.squareup.moshi.internal.Util.typesMatch
import com.squareup.moshi.internal.NO_ANNOTATIONS
import com.squareup.moshi.internal.canonicalize
import com.squareup.moshi.internal.isAnnotationPresent
import com.squareup.moshi.internal.removeSubtypeWildcard
import com.squareup.moshi.internal.toStringWithAnnotations
import com.squareup.moshi.internal.typesMatch
import java.lang.reflect.Type
import javax.annotation.CheckReturnValue

Expand All @@ -42,10 +42,10 @@ public class Moshi internal constructor(builder: Builder) {

/** Returns a JSON adapter for `type`, creating it if necessary. */
@CheckReturnValue
public fun <T> adapter(type: Type): JsonAdapter<T> = adapter(type, Util.NO_ANNOTATIONS)
public fun <T> adapter(type: Type): JsonAdapter<T> = adapter(type, NO_ANNOTATIONS)

@CheckReturnValue
public fun <T> adapter(type: Class<T>): JsonAdapter<T> = adapter(type, Util.NO_ANNOTATIONS)
public fun <T> adapter(type: Class<T>): JsonAdapter<T> = adapter(type, NO_ANNOTATIONS)

@CheckReturnValue
public fun <T> adapter(type: Type, annotationType: Class<out Annotation>): JsonAdapter<T> =
Expand Down Expand Up @@ -78,7 +78,7 @@ public class Moshi internal constructor(builder: Builder) {
annotations: Set<Annotation>,
fieldName: String?
): JsonAdapter<T> {
val cleanedType = removeSubtypeWildcard(canonicalize(type))
val cleanedType = type.canonicalize().removeSubtypeWildcard()

// If there's an equivalent adapter in the cache, we're done!
val cacheKey = cacheKey(cleanedType, annotations)
Expand Down Expand Up @@ -107,7 +107,7 @@ public class Moshi internal constructor(builder: Builder) {
success = true
return result
}
throw IllegalArgumentException("No JsonAdapter for ${typeAnnotatedWithAnnotations(type, annotations)}")
throw IllegalArgumentException("No JsonAdapter for ${type.toStringWithAnnotations(annotations)}")
} catch (e: IllegalArgumentException) {
throw lookupChain.exceptionWithLookupStack(e)
} finally {
Expand All @@ -121,15 +121,15 @@ public class Moshi internal constructor(builder: Builder) {
type: Type,
annotations: Set<Annotation>
): JsonAdapter<T> {
val cleanedType = removeSubtypeWildcard(canonicalize(type))
val cleanedType = type.canonicalize().removeSubtypeWildcard()
val skipPastIndex = factories.indexOf(skipPast)
require(skipPastIndex != -1) { "Unable to skip past unknown factory $skipPast" }
for (i in (skipPastIndex + 1) until factories.size) {
@Suppress("UNCHECKED_CAST") // Factories are required to return only matching JsonAdapters.
val result = factories[i].create(cleanedType, annotations, this) as JsonAdapter<T>?
if (result != null) return result
}
throw IllegalArgumentException("No next JsonAdapter for ${typeAnnotatedWithAnnotations(cleanedType, annotations)}")
throw IllegalArgumentException("No next JsonAdapter for ${cleanedType.toStringWithAnnotations(annotations)}")
}

/** Returns a new builder containing all custom factories used by the current instance. */
Expand Down Expand Up @@ -354,7 +354,7 @@ public class Moshi internal constructor(builder: Builder) {
require(annotation.isAnnotationPresent(JsonQualifier::class.java)) { "$annotation does not have @JsonQualifier" }
require(annotation.declaredMethods.isEmpty()) { "Use JsonAdapter.Factory for annotations with elements" }
return JsonAdapter.Factory { targetType, annotations, _ ->
if (typesMatch(type, targetType) && annotations.size == 1 && isAnnotationPresent(annotations, annotation)) {
if (typesMatch(type, targetType) && annotations.size == 1 && annotations.isAnnotationPresent(annotation)) {
jsonAdapter
} else {
null
Expand Down
Expand Up @@ -275,7 +275,7 @@ static final class EnumJsonAdapter<T extends Enum<T>> extends JsonAdapter<T> {
for (int i = 0; i < constants.length; i++) {
T constant = constants[i];
String constantName = constant.name();
nameStrings[i] = Util.jsonName(constantName, enumType.getField(constantName));
nameStrings[i] = Util.jsonName(enumType.getField(constantName), constantName);
}
options = JsonReader.Options.of(nameStrings);
} catch (NoSuchFieldException e) {
Expand Down

0 comments on commit e2c346e

Please sign in to comment.