Search in sources :

Example 1 with SoyMap

use of com.google.template.soy.data.SoyMap 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;
    }
}
Also used : SoyLegacyObjectMap(com.google.template.soy.data.SoyLegacyObjectMap) SoyType(com.google.template.soy.types.SoyType) SoyMap(com.google.template.soy.data.SoyMap) SoyValue(com.google.template.soy.data.SoyValue)

Aggregations

SoyLegacyObjectMap (com.google.template.soy.data.SoyLegacyObjectMap)1 SoyMap (com.google.template.soy.data.SoyMap)1 SoyValue (com.google.template.soy.data.SoyValue)1 SoyType (com.google.template.soy.types.SoyType)1