Search in sources :

Example 1 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class ExpressionCompilerTest method createTemplateBody.

private String createTemplateBody(String soyExpr) {
    // collect all varrefs and apply them as template parameters.  This way all varrefs have a valid
    // vardef
    // TODO(lukes): this logic would be useful in a lot of tests and potentially unblock efforts to
    // eliminate UNDECLARED vars
    ExprNode expr = SoyFileParser.parseExpression(soyExpr, PluginResolver.nullResolver(Mode.ALLOW_UNDEFINED, ErrorReporter.exploding()), ErrorReporter.exploding());
    final StringBuilder templateBody = new StringBuilder();
    new AbstractExprNodeVisitor<Void>() {

        final Set<String> names = new HashSet<>();

        @Override
        protected void visitVarRefNode(VarRefNode node) {
            if (names.add(node.getName())) {
                SoyType type = variables.get(node.getName()).soyType();
                templateBody.append("{@param ").append(node.getName()).append(": ").append(type).append("}\n");
            }
        }

        @Override
        protected void visitExprNode(ExprNode node) {
            if (node instanceof ParentExprNode) {
                visitChildren((ParentExprNode) node);
            }
        }
    }.exec(expr);
    templateBody.append("{" + soyExpr + "}\n");
    return templateBody.toString();
}
Also used : ParentExprNode(com.google.template.soy.exprtree.ExprNode.ParentExprNode) ExprNode(com.google.template.soy.exprtree.ExprNode) ParentExprNode(com.google.template.soy.exprtree.ExprNode.ParentExprNode) VarRefNode(com.google.template.soy.exprtree.VarRefNode) SoyType(com.google.template.soy.types.SoyType) HashSet(java.util.HashSet)

Example 2 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class CheckProtoInitCallsPass method checkProto.

private void checkProto(ProtoInitNode node, SoyProtoType soyType) {
    // Check that all proto required fields are present.
    // TODO(user): Consider writing a soyProtoTypeImpl.getRequiredFields()
    Set<String> givenParams = Sets.newHashSet(node.getParamNames());
    for (FieldDescriptor field : soyType.getDescriptor().getFields()) {
        if (field.isRequired() && !givenParams.contains(field.getName())) {
            errorReporter.report(node.getSourceLocation(), MISSING_REQUIRED_FIELD, field.getName());
        }
    }
    ImmutableSet<String> fields = soyType.getFieldNames();
    for (int i = 0; i < node.numChildren(); i++) {
        String fieldName = node.getParamNames().get(i);
        ExprNode expr = node.getChild(i);
        // Check that each arg exists in the proto.
        if (!fields.contains(fieldName)) {
            String extraErrorMessage = SoyErrors.getDidYouMeanMessageForProtoFields(fields, fieldName);
            errorReporter.report(expr.getSourceLocation(), FIELD_DOES_NOT_EXIST, fieldName, extraErrorMessage);
            continue;
        }
        // Check that the arg type is not null and that it matches the expected field type.
        SoyType argType = expr.getType();
        if (argType.equals(NullType.getInstance())) {
            errorReporter.report(expr.getSourceLocation(), NULL_ARG_TYPE, fieldName);
        }
        SoyType fieldType = soyType.getFieldType(fieldName);
        // Let args with unknown or error types pass
        if (argType.equals(UnknownType.getInstance()) || argType.equals(ErrorType.getInstance())) {
            return;
        }
        // Same for List<?>, for repeated fields
        if (fieldType.getKind() == Kind.LIST && argType.getKind() == Kind.LIST) {
            SoyType argElementType = ((ListType) argType).getElementType();
            if (argElementType == null || argElementType.equals(UnknownType.getInstance())) {
                return;
            }
        }
        SoyType expectedType = SoyTypes.makeNullable(fieldType);
        if (!expectedType.isAssignableFrom(argType)) {
            errorReporter.report(expr.getSourceLocation(), ARGUMENT_TYPE_MISMATCH, fieldName, expectedType, argType);
        }
    }
}
Also used : ExprNode(com.google.template.soy.exprtree.ExprNode) SoyType(com.google.template.soy.types.SoyType) ListType(com.google.template.soy.types.ListType) FieldDescriptor(com.google.protobuf.Descriptors.FieldDescriptor)

Example 3 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class GenIncrementalDomCodeVisitor method visitPrintNode.

/**
 * Visit an {@link PrintNode}, with special cases for a variable being printed within an attribute
 * declaration or as HTML content.
 *
 * <p>For attributes, if the variable is of kind attributes, it is invoked. Any other kind of
 * variable is an error.
 *
 * <p>For HTML, if the variable is of kind HTML, it is invoked. Any other kind of variable gets
 * wrapped in a call to {@code incrementalDom.text}, resulting in a Text node.
 */
@Override
protected void visitPrintNode(PrintNode node) {
    ExprNode firstNode = node.getExpr().getRoot();
    // TODO(b/71896143): directives are not handled correctly in the html_tag case.
    switch(node.getHtmlContext()) {
        case HTML_TAG:
            if (tryGenerateFunctionCall(SoyType.Kind.ATTRIBUTES, firstNode) == GenerateFunctionCallResult.INDIRECT_NODE) {
                // Inside an HTML tag, we cannot emit indirect calls (like incrementalDom.text); the only
                // valid commands
                // are idom incrementalDom.attr() calls (which direct ATTRIBUTES functions will call).
                // If we can't emit the print node as a direct call, give up and report an error.
                errorReporter.report(node.getSourceLocation(), PRINT_ATTR_INVALID_KIND, firstNode.getType().getKind());
            }
            break;
        case HTML_PCDATA:
            // But if we statically know that it's an HTML function, we can call it directly.
            if (tryGenerateFunctionCall(SoyType.Kind.HTML, firstNode) == GenerateFunctionCallResult.INDIRECT_NODE) {
                List<CodeChunk.WithValue> chunks = genJsExprsVisitor.exec(node);
                CodeChunk.WithValue printCall = SOY_IDOM_PRINT.call(CodeChunkUtils.concatChunks(chunks));
                JsCodeBuilder codeBuilder = getJsCodeBuilder();
                codeBuilder.append(printCall);
            }
            break;
        default:
            super.visitPrintNode(node);
            break;
    }
}
Also used : ExprNode(com.google.template.soy.exprtree.ExprNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) JsCodeBuilder(com.google.template.soy.jssrc.internal.JsCodeBuilder)

Example 4 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class TemplateAnalysis method isListExpressionEmpty.

// consider moving this to SoyTreeUtils or some similar place.
private static StaticAnalysisResult isListExpressionEmpty(ForNode node) {
    Optional<RangeArgs> rangeArgs = RangeArgs.createFromNode(node);
    if (rangeArgs.isPresent()) {
        return isRangeExpressionEmpty(rangeArgs.get());
    }
    ExprNode expr = node.getExpr().getRoot();
    if (expr instanceof ListLiteralNode) {
        return ((ListLiteralNode) expr).numChildren() > 0 ? StaticAnalysisResult.FALSE : StaticAnalysisResult.TRUE;
    }
    return StaticAnalysisResult.UNKNOWN;
}
Also used : ExprNode(com.google.template.soy.exprtree.ExprNode) ListLiteralNode(com.google.template.soy.exprtree.ListLiteralNode) RangeArgs(com.google.template.soy.shared.RangeArgs)

Example 5 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class MsgIdFunctionPass method handleMsgIdCall.

/**
 * Rewrites calls to msgId($msgVar) to either a static constant message id or a conditional if
 * there is a fallback.
 */
private void handleMsgIdCall(FunctionNode fn, MsgFallbackGroupNode msgNode) {
    ExprNode replacement;
    long primaryMsgId = MsgUtils.computeMsgIdForDualFormat(msgNode.getChild(0));
    if (msgNode.numChildren() == 1) {
        // easy peasy
        replacement = createMsgIdNode(primaryMsgId, fn.getSourceLocation());
    } else {
        long fallbackMsgId = MsgUtils.computeMsgIdForDualFormat(msgNode.getChild(1));
        ConditionalOpNode condOpNode = new ConditionalOpNode(fn.getSourceLocation());
        FunctionNode isPrimaryMsgInUse = new FunctionNode(BuiltinFunction.IS_PRIMARY_MSG_IN_USE, fn.getSourceLocation());
        // We add the varRef, and the 2 message ids to the funcitonnode as arguments so they are
        // trivial to access in the backends.  This is a little hacky however since we never generate
        // code for these things.
        // We could formalize the hack by providing a way to stash arbitrary data in the FunctionNode
        // and then just pack this up in a non-AST datastructure.
        isPrimaryMsgInUse.addChild(fn.getChild(0));
        isPrimaryMsgInUse.addChild(new IntegerNode(primaryMsgId, fn.getSourceLocation()));
        isPrimaryMsgInUse.addChild(new IntegerNode(fallbackMsgId, fn.getSourceLocation()));
        condOpNode.addChild(isPrimaryMsgInUse);
        condOpNode.addChild(createMsgIdNode(primaryMsgId, fn.getSourceLocation()));
        condOpNode.addChild(createMsgIdNode(fallbackMsgId, fn.getSourceLocation()));
        replacement = condOpNode;
    }
    fn.getParent().replaceChild(fn, replacement);
}
Also used : ExprNode(com.google.template.soy.exprtree.ExprNode) ConditionalOpNode(com.google.template.soy.exprtree.OperatorNodes.ConditionalOpNode) IntegerNode(com.google.template.soy.exprtree.IntegerNode) FunctionNode(com.google.template.soy.exprtree.FunctionNode)

Aggregations

ExprNode (com.google.template.soy.exprtree.ExprNode)38 ParentExprNode (com.google.template.soy.exprtree.ExprNode.ParentExprNode)7 IntegerNode (com.google.template.soy.exprtree.IntegerNode)7 StringNode (com.google.template.soy.exprtree.StringNode)7 FunctionNode (com.google.template.soy.exprtree.FunctionNode)5 Test (org.junit.Test)5 ImmutableList (com.google.common.collect.ImmutableList)4 SoyValue (com.google.template.soy.data.SoyValue)4 GlobalNode (com.google.template.soy.exprtree.GlobalNode)4 VarRefNode (com.google.template.soy.exprtree.VarRefNode)4 CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)4 SoyType (com.google.template.soy.types.SoyType)4 LinkedHashMap (java.util.LinkedHashMap)4 AbstractParentExprNode (com.google.template.soy.exprtree.AbstractParentExprNode)3 FloatNode (com.google.template.soy.exprtree.FloatNode)3 SourceLocation (com.google.template.soy.base.SourceLocation)2 ErrorReporter (com.google.template.soy.error.ErrorReporter)2 BooleanNode (com.google.template.soy.exprtree.BooleanNode)2 PrimitiveNode (com.google.template.soy.exprtree.ExprNode.PrimitiveNode)2 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)2