Inline mask generation and constructor invocation (#908)

* Differentiate local naming from properties with constructor defaults

* Remove constructor invocation and mask creation methods

We're inlining all this

* Add explanatory comment for why we use the default primitive value

* Inline mask generation and constructor invocation to generated adapters

* Remove unused argument

Co-Authored-By: Jake Wharton <jakew@google.com>

* Compute masks directly during code gen

* Opportunistic: remove extraneous double space from control flow

* Just mask and invert directly
This commit is contained in:
Zac Sweers
2019-09-12 16:42:31 -04:00
committed by GitHub
parent 7a4f3513a1
commit a67b4d6a72
4 changed files with 53 additions and 125 deletions

View File

@@ -543,7 +543,6 @@ public final class Util {
* @param targetClass the target kotlin class to instantiate.
* @param <T> the type of {@code targetClass}.
* @return the instantiated {@code targetClass} instance.
* @see #createDefaultValuesParametersMask(boolean...)
*/
public static <T> Constructor<T> lookupDefaultsConstructor(Class<T> targetClass) {
if (DEFAULT_CONSTRUCTOR_MARKER == null) {
@@ -555,42 +554,6 @@ public final class Util {
return defaultConstructor;
}
/**
* Reflectively invokes the defaults constructor of a kotlin class. This allows indicating which
* arguments are "set" or not, and thus recreate the behavior of named a arguments invocation
* dynamically.
*
* @param targetClass the target kotlin class to instantiate.
* @param defaultsConstructor the target class's defaults constructor in kotlin invoke.
* @param mask an int mask indicating which {@code args} are present.
* @param args the constructor arguments, including "unset" values (set to null or the primitive
* default).
* @param <T> the type of {@code targetClass}.
* @return the instantiated {@code targetClass} instance.
* @see #createDefaultValuesParametersMask(boolean...)
*/
public static <T> T invokeDefaultConstructor(
Class<T> targetClass,
Constructor<T> defaultsConstructor,
int mask,
Object... args) {
Object[] finalArgs = Arrays.copyOf(args, args.length + 2);
finalArgs[finalArgs.length - 2] = mask;
finalArgs[finalArgs.length - 1] = null; // DefaultConstructorMarker param
try {
return defaultsConstructor.newInstance(finalArgs);
} catch (InstantiationException e) {
throw new IllegalStateException("Could not instantiate instance of " + targetClass);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not access defaults constructor of " + targetClass);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) throw (RuntimeException) cause;
if (cause instanceof Error) throw (Error) cause;
throw new RuntimeException("Could not invoke defaults constructor of " + targetClass, cause);
}
}
private static <T> Constructor<T> findConstructor(Class<T> targetClass) {
for (Constructor<?> constructor : targetClass.getDeclaredConstructors()) {
Class<?>[] paramTypes = constructor.getParameterTypes();
@@ -604,26 +567,6 @@ public final class Util {
throw new IllegalStateException("No defaults constructor found for " + targetClass);
}
/**
* Creates an mask with bits set to indicate which indices of a default constructor's parameters
* are set.
*
* @param argPresentValues vararg of all present values (set or unset). Max allowable size is 32.
* @return the created mask.
*/
public static int createDefaultValuesParametersMask(boolean... argPresentValues) {
if (argPresentValues.length > 32) {
throw new IllegalArgumentException("Arg present values exceeds max allowable 32.");
}
int mask = 0;
for (int i = 0; i < argPresentValues.length; ++i) {
if (!argPresentValues[i]) {
mask = mask | (1 << i);
}
}
return mask;
}
public static JsonDataException missingProperty(String property, JsonReader reader) {
return jsonDataException(REQUIRED_PROPERTY_TEMPLATE, property, reader);
}