use of com.google.template.soy.types.SoyType in project closure-templates by google.
the class EvalVisitor method visitNullSafeItemAccessNode.
private SoyValue visitNullSafeItemAccessNode(ItemAccessNode itemAccess) {
SoyValue base = visitNullSafeNodeRecurse(itemAccess.getBaseExprChild());
// attempting item access on non-SoyMap
if (!(base instanceof SoyLegacyObjectMap || base instanceof SoyMap)) {
if (base == NullSafetySentinel.INSTANCE) {
// Bail out if base expression failed a null-safety check.
return NullSafetySentinel.INSTANCE;
}
if (itemAccess.isNullSafe()) {
if (isNullOrUndefinedBase(base)) {
// Return the sentinel value that indicates that a null-safety check failed.
return NullSafetySentinel.INSTANCE;
} else {
throw RenderException.create(String.format("While evaluating \"%s\", encountered non-map/list just before accessing \"%s\".", itemAccess.toSourceString(), itemAccess.getSourceStringSuffix()));
}
}
// TODO: If feasible, find and fix existing instances, then throw RenderException here.
return UndefinedData.INSTANCE;
}
// base is a valid SoyMap or SoyLegacyObjectMap: get value
maybeMarkBadProtoAccess(itemAccess, base);
SoyValue key = visit(itemAccess.getKeyExprChild());
SoyType baseType = SoyTypes.tryRemoveNull(itemAccess.getBaseExprChild().getType());
// We need to know whether to invoke the SoyMap or SoyLegacyObjectMap method.
// An instanceof check on the runtime value of base is insufficient, since
// DictImpl implements both interfaces. Instead, look at the declared type of the base
// expression.
boolean shouldUseNewMap = MapType.ANY_MAP.isAssignableFrom(baseType);
SoyValue value = shouldUseNewMap ? ((SoyMap) base).get(key) : ((SoyLegacyObjectMap) base).getItem(key);
if (value != null && !TofuTypeChecks.isInstance(itemAccess.getType(), value)) {
throw RenderException.create(String.format("Expected value of type '%s', but actual type was '%s'.", itemAccess.getType(), value.getClass().getSimpleName()));
}
if (value != null) {
return value;
} else if (shouldUseNewMap) {
// UndefinedData is a misfeature. The new map type should return null for failed lookups.
return NullData.INSTANCE;
} else {
return UndefinedData.INSTANCE;
}
}
use of com.google.template.soy.types.SoyType in project closure-templates by google.
the class VeLogValidationPass method validateNodeAgainstConfig.
/**
* Type checks both expressions and assigns the {@link VeLogNode#getLoggingId()} field.
*/
private void validateNodeAgainstConfig(VeLogNode node) {
ValidatedLoggableElement config = loggingConfig.getElement(node.getName().identifier());
if (config == null) {
reporter.report(node.getName().location(), NO_CONFIG_FOR_ELEMENT, SoyErrors.getDidYouMeanMessage(loggingConfig.allKnownIdentifiers(), node.getName().identifier()));
} else {
node.setLoggingId(config.getId());
if (node.getConfigExpression() != null) {
SoyType type = node.getConfigExpression().getType();
Optional<String> protoName = config.getProtoName();
if (!protoName.isPresent()) {
reporter.report(node.getConfigExpression().getSourceLocation(), UNEXPECTED_CONFIG, node.getName().identifier());
} else if (type.getKind() != Kind.ERROR && (type.getKind() != Kind.PROTO || !((SoyProtoType) type).getDescriptor().getFullName().equals(protoName.get()))) {
reporter.report(node.getConfigExpression().getSourceLocation(), WRONG_TYPE, protoName.get(), type);
}
}
if (node.getLogonlyExpression() != null) {
SoyType type = node.getLogonlyExpression().getType();
if (type.getKind() != Kind.BOOL) {
reporter.report(node.getLogonlyExpression().getSourceLocation(), WRONG_TYPE, BoolType.getInstance(), type);
}
}
}
}
use of com.google.template.soy.types.SoyType in project closure-templates by google.
the class ExpressionCompilerTest method testNullCoalescingOpNode.
@Test
public void testNullCoalescingOpNode() {
assertExpression("1 ?: 2").evaluatesTo(1L);
// force the type checker to interpret the left hand side as a nullable string, the literal null
// is rejected by the type checker.
assertExpression("(true ? null : 'a') ?: 2").evaluatesTo(IntegerData.forValue(2));
assertExpression("(true ? null : 'a') ?: 'b'").evaluatesTo(StringData.forValue("b"));
assertExpression("(false ? null : 'a') ?: 'b'").evaluatesTo(StringData.forValue("a"));
variables.put("p1", untypedBoxedSoyExpression(SoyExpression.forString(constantNull(STRING_TYPE))));
variables.put("p2", SoyExpression.forString(constant("a")).box());
assertExpression("$p1 ?: $p2").evaluatesTo(StringData.forValue("a"));
SoyType htmlType = SanitizedType.getTypeForContentKind(SanitizedContentKind.HTML);
variables.put("p1", SoyExpression.forSoyValue(htmlType, MethodRef.ORDAIN_AS_SAFE.invoke(constant("<b>hello</b>"), constant(ContentKind.HTML))));
variables.put("p2", SoyExpression.forString(constant("")).box());
assertExpression("$p1 ?: $p2").evaluatesTo(SanitizedContents.constantHtml("<b>hello</b>"));
variables.put("p1", SoyExpression.forSoyValue(htmlType, constantNull(Type.getType(SanitizedContent.class))).asNullable());
assertExpression("$p1 ?: $p2").evaluatesTo(StringData.forValue(""));
}
use of com.google.template.soy.types.SoyType in project closure-templates by google.
the class TofuTypeChecksTest method testUnionTypeIsInstance.
@Test
public void testUnionTypeIsInstance() {
SoyType utype = UnionType.of(IntType.getInstance(), StringType.getInstance());
assertIsInstance(utype, INTEGER_DATA, STRING_DATA, HTML_DATA, ATTRIBUTES_DATA, CSS_DATA, URI_DATA, TRUSTED_RESOURCE_URI_DATA, JS_DATA);
assertIsNotInstance(utype, NULL_DATA, BOOLEAN_DATA, FLOAT_DATA, LIST_DATA, MAP_DATA, DICT_DATA);
}
use of com.google.template.soy.types.SoyType in project closure-templates by google.
the class MapToLegacyObjectMapFunction method computeForJbcSrc.
@Override
public SoyExpression computeForJbcSrc(JbcSrcPluginContext context, List<SoyExpression> args) {
SoyExpression soyExpression = Iterables.getOnlyElement(args);
SoyType originalType = soyExpression.soyRuntimeType().soyType();
LegacyObjectMapType newType;
if (originalType instanceof MapType) {
newType = LegacyObjectMapType.of(((MapType) originalType).getKeyType(), ((MapType) originalType).getValueType());
} else if (originalType instanceof UnknownType) {
newType = LegacyObjectMapType.of(UnknownType.getInstance(), UnknownType.getInstance());
} else {
throw new IllegalArgumentException("mapToLegacyObjectMap() expects input to be MAP, get " + originalType.getKind());
}
return SoyExpression.forLegacyObjectMap(newType, JbcSrcMethods.MAP_TO_LEGACY_OBJECT_MAP.invoke(soyExpression.box().checkedCast(SoyMap.class)));
}
Aggregations