Skip to content

Commit

Permalink
Have invocation builders coerce values to SoyValues directly when pos…
Browse files Browse the repository at this point in the history
…sible, rather than always going through the generic SoyValueConverter api

For simple well typed parameters, this should be more performant.  For complex parameters, this should be more accurate. Consider list<map<string,string>> the current approach converts the inner map<> to a DictImpl with an unknown runtime type, the new approach marks it as a SoyMapImpl. In well typed code there is no difference, but if the map value wonders into untyped code it might get inferred to be a legacy_object_map.

This also allows us to support list<css> and list<attributes>

GITHUB_BREAKING_CHANGES=none

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=302062291
  • Loading branch information
lukesandberg authored and emspishak committed Mar 23, 2020
1 parent 70cc87f commit b67abee
Show file tree
Hide file tree
Showing 14 changed files with 461 additions and 478 deletions.
293 changes: 198 additions & 95 deletions java/src/com/google/template/soy/data/BaseSoyTemplateImpl.java

Large diffs are not rendered by default.

10 changes: 0 additions & 10 deletions java/src/com/google/template/soy/data/CssParam.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,4 @@ public static CssParam of(SafeStyleSheet safeStyleSheet) {
abstract SafeStyle safeStyle();

abstract SafeStyleSheet safeStyleSheet();

public Object toSoyValue() {
switch (type()) {
case SAFE_STYLE:
return safeStyle();
case SAFE_STYLE_SHEET:
return safeStyleSheet();
}
throw new AssertionError();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,10 @@

package com.google.template.soy.invocationbuilders.javatypes;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.Immutable;
import com.google.template.soy.data.BaseSoyTemplateImpl.AbstractBuilder;
import com.google.template.soy.data.BaseSoyTemplateImpl.AbstractBuilderWithAccumulatorParameters;
import com.google.template.soy.data.SoyTemplateParam;
import com.google.template.soy.data.SoyValueConverter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
Expand All @@ -35,44 +31,13 @@ public final class CodeGenUtils {

private CodeGenUtils() {}

public static final Member AS_MAP_OF_NUMBERS =
MethodImpl.method(AbstractBuilder.class, "asMapOfNumbers");
public static final Member SET_PARAM_INTERNAL =
MethodImpl.method(AbstractBuilder.class, "setParamInternal");
public static final Member ADD_TO_LIST_PARAM =
MethodImpl.method(AbstractBuilderWithAccumulatorParameters.class, "addToListParam");
public static final Member INIT_LIST_PARAM =
MethodImpl.method(AbstractBuilderWithAccumulatorParameters.class, "initListParam");
public static final Member CHECK_NOT_NULL =
MethodImpl.fullyQualifiedMethod(Preconditions.class, "checkNotNull");
public static final Member AS_RECORD = MethodImpl.method(AbstractBuilder.class, "asRecord");
public static final Member AS_NUMBER = MethodImpl.method(AbstractBuilder.class, "asNumber");
public static final Member AS_NULLABLE_NUMBER =
MethodImpl.method(AbstractBuilder.class, "asNullableNumber");
public static final Member AS_NUMBER_COLLECTION =
MethodImpl.method(AbstractBuilder.class, "asNumberCollection");
public static final Member AS_COLLECTION =
MethodImpl.method(AbstractBuilder.class, "asCollection");
public static final Member AS_LIST_OF_DOUBLES =
MethodImpl.method(AbstractBuilder.class, "asListOfDoubles");
public static final Member DOUBLE_MAPPER =
MethodImpl.field(AbstractBuilder.class, "doubleMapper");
public static final Member LONG_MAPPER = MethodImpl.field(AbstractBuilder.class, "longMapper");
public static final Member NUMBER_MAPPER =
MethodImpl.field(AbstractBuilder.class, "numberMapper");
public static final Member AS_LIST_OF_LONGS =
MethodImpl.method(AbstractBuilder.class, "asListOfLongs");
public static final Member MARK_AS_SOY_MAP =
MethodImpl.fullyQualifiedMethod(SoyValueConverter.class, "markAsSoyMap");
public static final Member AS_NULLABLE_ATTRIBUTES =
MethodImpl.method(AbstractBuilder.class, "asNullableAttributes");
public static final Member AS_ATTRIBUTES =
MethodImpl.method(AbstractBuilder.class, "asAttributes");
public static final Member AS_NULLABLE_CSS =
MethodImpl.method(AbstractBuilder.class, "asNullableCss");
public static final Member AS_CSS = MethodImpl.method(AbstractBuilder.class, "asCss");
public static final Member TO_IMMUTABLE_MAP =
MethodImpl.fullyQualifiedMethod(ImmutableMap.class, "copyOf");
public static final Member AS_RECORD = castFunction("asRecord");

public static final Member OPTIONAL_P =
MethodImpl.fullyQualifiedMethod(SoyTemplateParam.class, "optional");
Expand All @@ -83,6 +48,10 @@ private CodeGenUtils() {}
public static final Member INJECTED_P =
MethodImpl.fullyQualifiedMethod(SoyTemplateParam.class, "injected");

static Member castFunction(String name) {
return MethodImpl.method(AbstractBuilder.class, name);
}

/** A field or method that can be printed in code generation. */
@Immutable
public interface Member {
Expand All @@ -94,7 +63,7 @@ public interface Member {
private static class MethodImpl implements Member {
private final String name;

private MethodImpl(java.lang.reflect.Member method, boolean qualified) {
private MethodImpl(java.lang.reflect.Method method, boolean qualified) {
this.name = (qualified ? method.getDeclaringClass().getName() + "." : "") + method.getName();
}

Expand All @@ -106,30 +75,18 @@ private static MethodImpl fullyQualifiedMethod(Class<?> type, String methodName)
return new MethodImpl(findAnyMethod(type, methodName), /*qualified=*/ true);
}

private static MethodImpl field(Class<?> type, String fieldName) {
return new MethodImpl(findAnyField(type, fieldName), /*qualified=*/ false);
}

@Override
public String toString() {
return name;
}
}

private static Method findAnyMethod(Class<?> type, String methodName) {
return findAny(type.getDeclaredMethods(), methodName);
}

private static Field findAnyField(Class<?> type, String fieldName) {
return findAny(type.getDeclaredFields(), fieldName);
}

private static <T extends java.lang.reflect.Member> T findAny(T[] members, String name) {
for (T member : members) {
if (name.equals(member.getName())) {
return member;
for (Method method : type.getDeclaredMethods()) {
if (methodName.equals(method.getName())) {
return method;
}
}
throw new IllegalArgumentException();
throw new IllegalArgumentException("Can't find a method named: " + methodName + " in: " + type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,20 @@
*/
package com.google.template.soy.invocationbuilders.javatypes;

import com.google.common.base.Preconditions;
import static com.google.common.base.Preconditions.checkArgument;

/** Represents a Future<T> type for generated Soy Java invocation builders. */
public final class FutureJavaType extends JavaType {

private static final CodeGenUtils.Member AS_FUTURE = CodeGenUtils.castFunction("asFuture");
private final JavaType type;

public FutureJavaType(JavaType type) {
super(/* isNullable= */ false);
Preconditions.checkArgument(type.isGenericsTypeSupported());
checkArgument(type.isGenericsTypeSupported());
this.type = type;
}

@Override
boolean isPrimitive() {
return false;
}

@Override
public String toJavaTypeString() {
return "java.util.concurrent.Future<" + type.asGenericsTypeArgumentString() + ">";
Expand All @@ -47,8 +43,14 @@ public JavaType getType() {
return type;
}

@Override
public String asInlineCast(String variableName, int depth) {
return AS_FUTURE + "(" + variableName + ", " + type.getAsInlineCastFunction(depth) + ")";
}

@Override
public JavaType asNullable() {
// TODO(lukes): throw UnsupportedOperationExceptiopn?
return this;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.google.template.soy.invocationbuilders.javatypes;

import static com.google.template.soy.invocationbuilders.javatypes.CodeGenUtils.CHECK_NOT_NULL;

import com.google.common.base.Strings;

Expand Down Expand Up @@ -49,32 +48,40 @@ public abstract class JavaType {
*
* <p>The return value would be "myListAsLong".
*/
public String asInlineCast(String variableName) {
if (!isNullable() && !isPrimitive()) {
return CHECK_NOT_NULL + "(" + variableName + ")";
}
return variableName;
public final String asInlineCast(String variableName) {
return asInlineCast(variableName, 0);
}

abstract String asInlineCast(String variableName, int depth);

/** Whether the type should be treated as {@code @Nullable}). */
public boolean isNullable() {
return isNullable;
}

/** Whether this is a primitive type. */
abstract boolean isPrimitive();

/** Returns this type as a nullable type. Primitive should make sure to switch to a boxed type. */
public abstract JavaType asNullable();

/**
* Returns the string to use if this is a type argument for a generic type (e.g. "? extends
* Number" instead of "Number", so we can accept Long/Double).
* Returns a string that evaluates to a Function for converting values of the Java type to
* SoyValueProviders.
*
* <p>Note that this is NOT public because it should only be used by other java types (e.g.
* ListJavaType needs to get its element type as a generic type string to know what to put in the
* <>).
* <p>subtypes should override to supply method reference where they can
*/
public String getAsInlineCastFunction(int depth) {
// use the depth to generate a unique lambda name
String lambdaName = "v" + (depth == 0 ? "" : depth);
return lambdaName + " -> " + asInlineCast(lambdaName, depth + 1);
}

/*
Returns the string to use if this is a type argument for a generic type (e.g. "? extends
* Number" instead of "Number", so we can accept Long/Double).
*
* <p>Note that this is NOT public because it should only be used by other java types (e.g.
* ListJavaType needs to get its element type as a generic type string to know what to put in the
* <>).
*/
abstract String asGenericsTypeArgumentString();

public boolean isGenericsTypeSupported() {
Expand Down
Loading

0 comments on commit b67abee

Please sign in to comment.