use of com.google.template.soy.jssrc.restricted.JsExpr in project closure-templates by google.
the class GenCallCodeUtils method gen.
/**
* Generates the JS expression for a given call.
*
* <p> Important: If there are CallParamContentNode children whose contents are not computable as
* JS expressions, then this function assumes that, elsewhere, code has been generated to define
* their respective 'param<n>' temporary variables.
*
* <p> Here are five example calls:
* <pre>
* {call some.func data="all" /}
* {call some.func data="$boo.foo" /}
* {call some.func}
* {param goo = $moo /}
* {/call}
* {call some.func data="$boo"}
* {param goo}Blah{/param}
* {/call}
* {call some.func}
* {param goo}
* {for $i in range(3)}{$i}{/for}
* {/param}
* {/call}
* </pre>
* Their respective generated calls might be the following:
* <pre>
* some.func(opt_data)
* some.func(opt_data.boo.foo)
* some.func({goo: opt_data.moo})
* some.func(soy.$$assignDefaults({goo: 'Blah'}, opt_data.boo))
* some.func({goo: param65})
* </pre>
* Note that in the last case, the param content is not computable as JS expressions, so we assume
* that code has been generated to define the temporary variable 'param<n>'.
*
* @param callNode The call to generate code for.
* @param templateAliases A mapping of fully qualified calls to a variable in scope.
* @return The JS expression for the call.
*/
public CodeChunk.WithValue gen(CallNode callNode, TemplateAliases templateAliases, TranslationContext translationContext, ErrorReporter errorReporter) {
// Build the JS CodeChunk for the callee's name.
CodeChunk.WithValue callee;
if (callNode instanceof CallBasicNode) {
// Case 1: Basic call.
// TODO(lukes): add the logic for the goog.require here. The simplest strategy requires a
// TemplateRegistry to detect external templates.
callee = CodeChunk.dottedIdNoRequire(templateAliases.get(((CallBasicNode) callNode).getCalleeName()));
} else {
// Case 2: Delegate call.
CallDelegateNode callDelegateNode = (CallDelegateNode) callNode;
CodeChunk.WithValue calleeId = JsRuntime.SOY_GET_DELTEMPLATE_ID.call(stringLiteral(delTemplateNamer.getDelegateName(callDelegateNode)));
ExprRootNode variantSoyExpr = callDelegateNode.getDelCalleeVariantExpr();
CodeChunk.WithValue variant;
if (variantSoyExpr == null) {
// Case 2a: Delegate call with empty variant.
variant = LITERAL_EMPTY_STRING;
} else {
// Case 2b: Delegate call with variant expression.
variant = new TranslateExprNodeVisitor(translationContext, errorReporter).exec(variantSoyExpr);
}
callee = SOY_GET_DELEGATE_FN.call(calleeId, variant, callDelegateNode.allowEmptyDefault() ? LITERAL_TRUE : LITERAL_FALSE);
}
// Generate the data object to pass to callee
CodeChunk.WithValue objToPass = genObjToPass(callNode, templateAliases, translationContext, errorReporter);
// Generate the main call expression.
CodeChunk.WithValue call = callee.call(objToPass, JsRuntime.OPT_IJ_DATA);
if (callNode.getEscapingDirectives().isEmpty()) {
return call;
}
// Apply escaping directives as necessary.
//
// The print directive system continues to use JsExpr, as it is a publicly available API and
// migrating it to CodeChunk would be a major change. Therefore, we convert our CodeChunks
// to JsExpr and back here.
JsExpr callResult = call.singleExprOrName();
RequiresCollector.IntoImmutableSet collector = new RequiresCollector.IntoImmutableSet();
call.collectRequires(collector);
for (SoyPrintDirective directive : callNode.getEscapingDirectives()) {
Preconditions.checkState(directive instanceof SoyJsSrcPrintDirective, "Contextual autoescaping produced a bogus directive: %s", directive.getName());
callResult = ((SoyJsSrcPrintDirective) directive).applyForJsSrc(callResult, ImmutableList.<JsExpr>of());
if (directive instanceof SoyLibraryAssistedJsSrcPrintDirective) {
for (String name : ((SoyLibraryAssistedJsSrcPrintDirective) directive).getRequiredJsLibNames()) {
collector.add(GoogRequire.create(name));
}
}
}
return fromExpr(callResult, collector.get()).withInitialStatements(call.initialStatements());
}
use of com.google.template.soy.jssrc.restricted.JsExpr in project closure-templates by google.
the class TranslateExprNodeVisitor method visitV1ExpressionFunction.
private CodeChunk.WithValue visitV1ExpressionFunction(FunctionNode node) {
StringNode expr = (StringNode) node.getChild(0);
JsExpr jsExpr = V1JsExprTranslator.translateToJsExpr(expr.getValue(), expr.getSourceLocation(), variableMappings, errorReporter);
return CodeChunk.fromExpr(jsExpr, ImmutableList.<GoogRequire>of());
}
use of com.google.template.soy.jssrc.restricted.JsExpr in project closure-templates by google.
the class SoyJsPluginUtils method applyDirective.
/**
* Applies the given print directive to {@code expr} and returns the result.
*
* @param generator The CodeChunk generator to use.
* @param expr The expression to apply the print directive to.
* @param directive The print directive to apply.
* @param args Print directive args, if any.
*/
public static CodeChunk.WithValue applyDirective(CodeChunk.Generator generator, CodeChunk.WithValue expr, SoyJsSrcPrintDirective directive, List<CodeChunk.WithValue> args) {
List<JsExpr> argExprs = Lists.transform(args, TO_JS_EXPR);
JsExpr applied = directive.applyForJsSrc(expr.singleExprOrName(), argExprs);
RequiresCollector.IntoImmutableSet collector = new RequiresCollector.IntoImmutableSet();
expr.collectRequires(collector);
for (CodeChunk.WithValue arg : args) {
arg.collectRequires(collector);
}
if (directive instanceof SoyLibraryAssistedJsSrcPrintDirective) {
for (String name : ((SoyLibraryAssistedJsSrcPrintDirective) directive).getRequiredJsLibNames()) {
collector.add(GoogRequire.create(name));
}
}
ImmutableList.Builder<CodeChunk> initialStatements = ImmutableList.<CodeChunk>builder().addAll(expr.initialStatements());
for (CodeChunk.WithValue arg : args) {
initialStatements.addAll(arg.initialStatements());
}
return fromExpr(applied, collector.get()).withInitialStatements(initialStatements.build());
}
use of com.google.template.soy.jssrc.restricted.JsExpr in project closure-templates by google.
the class CodeChunk method assertExpr.
/**
* Temporary method to ease migration to the CodeChunk DSL.
*
* <p>Because of the recursive nature of the JS codegen system, it is generally not possible
* to convert one codegen method at a time to use the CodeChunk DSL.
* However, the business logic inside those methods can be migrated incrementally.
* Methods that do not yet use the CodeChunk DSL can "unwrap" inputs using this method
* and "wrap" results using {@link CodeChunk#fromExpr(JsExpr)}. This is safe as long as
* each CodeChunk generated for production code is
* {@link CodeChunk.WithValue#isRepresentableAsSingleExpression}.
*
* TODO(user): remove.
*/
public final JsExpr assertExpr() {
RequiresCollector.IntoImmutableSet collector = new RequiresCollector.IntoImmutableSet();
JsExpr expr = assertExprAndCollectRequires(collector);
ImmutableSet<GoogRequire> requires = collector.get();
if (!requires.isEmpty()) {
throw new IllegalStateException("calling assertExpr() would drop requires!: " + requires);
}
return expr;
}
use of com.google.template.soy.jssrc.restricted.JsExpr in project closure-templates by google.
the class FormatNumDirective method applyForJsSrc.
@Override
public JsExpr applyForJsSrc(JsExpr value, List<JsExpr> args) {
String numberFormatType = parseFormat(args);
StringBuilder expr = new StringBuilder();
expr.append("(new goog.i18n.NumberFormat(" + JS_ARGS_TO_ENUM.get(numberFormatType) + "))");
// digits for compact short and long numbers.
if (args.size() > 2) {
String minFractionDigits = args.get(2).getText();
String maxFractionDigits = args.size() > 3 ? args.get(3).getText() : minFractionDigits;
expr.append(".setMinimumFractionDigits(").append(minFractionDigits).append(")");
expr.append(".setMaximumFractionDigits(").append(maxFractionDigits).append(")");
} else if ("'compact_short'".equals(numberFormatType) || "'compact_long'".equals(numberFormatType)) {
// Note that this trims trailing zeros.
expr.append(".setSignificantDigits(3)");
}
expr.append(".format(" + value.getText() + ")");
return new JsExpr(expr.toString(), Integer.MAX_VALUE);
}
Aggregations