Skip to content

Commit

Permalink
Allow expressions in {call} statements in the parser. (Nothing done w…
Browse files Browse the repository at this point in the history
…ith them yet; I will update all backends to handle them individually).

GITHUB_BREAKING_CHANGES=Reserved Soy keywords 'and', 'for', 'if', 'in' and 'not' are no longer allowed as template names or package names.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=313764042
  • Loading branch information
cwgordon authored and emspishak committed Jun 1, 2020
1 parent 46ec132 commit c238012
Show file tree
Hide file tree
Showing 40 changed files with 645 additions and 422 deletions.
37 changes: 20 additions & 17 deletions java/src/com/google/template/soy/TemplateMetadataSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import com.google.template.soy.soytree.TemplateKindP;
import com.google.template.soy.soytree.TemplateMetadata;
import com.google.template.soy.soytree.TemplateMetadata.DataAllCallSituation;
import com.google.template.soy.soytree.TemplateMetadata.Kind;
import com.google.template.soy.soytree.TemplateMetadata.Parameter;
import com.google.template.soy.soytree.TemplateMetadataP;
import com.google.template.soy.soytree.TemplateNode;
Expand Down Expand Up @@ -85,8 +84,8 @@ public final class TemplateMetadataSerializer {

private static final Converter<VisibilityP, Visibility> VISIBILITY_CONVERTER =
createEnumConverter(VisibilityP.class, Visibility.class);
private static final Converter<TemplateKindP, TemplateMetadata.Kind> TEMPLATE_KIND_CONVERTER =
createEnumConverter(TemplateKindP.class, TemplateMetadata.Kind.class);
private static final Converter<TemplateKindP, TemplateType.TemplateKind> TEMPLATE_KIND_CONVERTER =
createEnumConverter(TemplateKindP.class, TemplateType.TemplateKind.class);
private static final Converter<SanitizedContentKindP, SanitizedContentKind>
CONTENT_KIND_CONVERTER =
createEnumConverter(SanitizedContentKindP.class, SanitizedContentKind.class);
Expand Down Expand Up @@ -141,7 +140,7 @@ private static TemplateMetadataP protoFromTemplate(TemplateMetadata meta, SoyFil
TemplateMetadataP.Builder builder =
TemplateMetadataP.newBuilder()
.setTemplateName(
meta.getTemplateKind() == Kind.DELTEMPLATE
meta.getTemplateKind() == TemplateType.TemplateKind.DELTEMPLATE
? meta.getDelTemplateName()
: maybeShortenTemplateName(fileNode.getNamespace(), meta.getTemplateName()))
.setTemplateKind(TEMPLATE_KIND_CONVERTER.reverse().convert(meta.getTemplateKind()))
Expand Down Expand Up @@ -170,7 +169,7 @@ private static TemplateMetadata metadataFromProto(
String filePath,
ErrorReporter errorReporter) {
TemplateMetadata.Builder builder = TemplateMetadata.builder();
TemplateMetadata.Kind templateKind =
TemplateType.TemplateKind templateKind =
TEMPLATE_KIND_CONVERTER.convert(templateProto.getTemplateKind());
@Nullable String delPackageName = emptyToNull(fileProto.getDelpackage());
String templateName;
Expand Down Expand Up @@ -369,22 +368,26 @@ private static SoyType fromProto(
}
case TEMPLATE:
{
List<TemplateType.Argument> arguments = new ArrayList<>();
List<TemplateType.Parameter> parameters = new ArrayList<>();
// TODO: this relies on proto map insertion order, which is not guaranteed by the spec.
for (Map.Entry<String, SoyTypeP> entry :
proto.getTemplate().getArgumentMap().entrySet()) {
arguments.add(
TemplateType.argumentOf(
proto.getTemplate().getParameterMap().entrySet()) {
parameters.add(
TemplateType.Parameter.create(
entry.getKey(),
fromProto(entry.getValue(), typeRegistry, filePath, errorReporter)));
fromProto(entry.getValue(), typeRegistry, filePath, errorReporter),
true /* isRequired */));
}
return typeRegistry.getOrCreateTemplateType(
arguments,
fromProto(
SoyTypeP.newBuilder().setPrimitive(proto.getTemplate().getReturnType()).build(),
typeRegistry,
filePath,
errorReporter));
return typeRegistry.internTemplateType(
TemplateType.declaredTypeOf(
parameters,
fromProto(
SoyTypeP.newBuilder()
.setPrimitive(proto.getTemplate().getReturnType())
.build(),
typeRegistry,
filePath,
errorReporter)));
}
case UNION:
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ protected R visit(ExprNode node) {

case VE_LITERAL_NODE:
return visitVeLiteralNode((VeLiteralNode) node);
case TEMPLATE_LITERAL_NODE:
return visitTemplateLiteralNode((TemplateLiteralNode) node);

default:
throw new UnsupportedOperationException();
Expand Down Expand Up @@ -360,6 +362,12 @@ protected R visitVeLiteralNode(VeLiteralNode node) {
return visitExprNode(node);
}

// -----------------------------------------------------------------------------------------------
// Implementations for template nodes.
protected R visitTemplateLiteralNode(TemplateLiteralNode node) {
return visitExprNode(node);
}

// -----------------------------------------------------------------------------------------------
// Fallback implementation.

Expand Down
17 changes: 15 additions & 2 deletions java/src/com/google/template/soy/exprtree/TemplateLiteralNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,31 @@ public final class TemplateLiteralNode extends AbstractExprNode {

private final Identifier templateIdentifier;
private final String resolvedName;
// True for 'synthetic' template literal nodes that are the direct children of {call} statements.
// These are exempt from some checks around the explicit template() expressions.
private final boolean isSynthetic;

private SoyType type;

public TemplateLiteralNode(Identifier templateIdentifier, SourceLocation sourceLocation) {
public TemplateLiteralNode(
Identifier templateIdentifier, SourceLocation sourceLocation, boolean isSynthetic) {
super(sourceLocation);
this.templateIdentifier = templateIdentifier;
this.resolvedName = templateIdentifier.identifier();
this.type = new NamedTemplateType(resolvedName);
this.isSynthetic = isSynthetic;
}

private TemplateLiteralNode(TemplateLiteralNode orig, CopyState copyState) {
super(orig, copyState);
this.templateIdentifier = orig.templateIdentifier;
this.resolvedName = orig.resolvedName;
this.type = orig.type;
this.isSynthetic = orig.isSynthetic;
}

public boolean isSynthetic() {
return isSynthetic;
}

public String getResolvedName() {
Expand All @@ -62,7 +73,9 @@ public Kind getKind() {

@Override
public String toSourceString() {
return templateIdentifier.identifier();
return isSynthetic
? templateIdentifier.originalName()
: "template(" + templateIdentifier.originalName() + ")";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import com.google.template.soy.soytree.TemplateMetadata.Parameter;
import com.google.template.soy.soytree.TemplateNode;
import com.google.template.soy.soytree.TemplateRegistry;
import com.google.template.soy.soytree.TemplateSignature;
import com.google.template.soy.soytree.Visibility;
import com.google.template.soy.soytree.defn.TemplateParam;
import com.google.template.soy.types.SoyType;
Expand Down Expand Up @@ -329,7 +328,7 @@ private void addIndirectParams(TemplateNode template, Map<String, ParamInfo> par

IndirectParamsInfo idi =
indirectParamsCalculator.calculateIndirectParams(
TemplateSignature.fromTemplateMetadata(TemplateMetadata.fromTemplate(template)));
TemplateMetadata.asTemplateType(TemplateMetadata.fromTemplate(template)));

for (Map.Entry<String, Parameter> entry : idi.indirectParams.entrySet()) {
String paramName = entry.getKey();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.template.soy.base.internal.SanitizedContentKind;
import com.google.template.soy.soytree.TemplateMetadata;
import com.google.template.soy.soytree.TemplateRegistry;
import com.google.template.soy.types.TemplateType;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
Expand All @@ -46,7 +47,7 @@ final class CompiledTemplateRegistry {
CompiledTemplateMetadata.create(template.getTemplateName(), template.getSoyFileKind());
templateToMetadata.put(template.getTemplateName(), metadata);
classToMetadata.put(metadata.typeInfo().className(), metadata);
if (template.getTemplateKind() == TemplateMetadata.Kind.DELTEMPLATE) {
if (template.getTemplateKind() == TemplateType.TemplateKind.DELTEMPLATE) {
delegateTemplateNames.add(template.getTemplateName());
// all delegates are guaranteed to have the same content kind by the
// checkdelegatesvisitor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@
import com.google.template.soy.soytree.SwitchNode;
import com.google.template.soy.soytree.TemplateDelegateNode;
import com.google.template.soy.soytree.TemplateElementNode;
import com.google.template.soy.soytree.TemplateMetadata;
import com.google.template.soy.soytree.TemplateNode;
import com.google.template.soy.soytree.TemplateRegistry;
import com.google.template.soy.soytree.TemplateSignature;
import com.google.template.soy.soytree.VeLogNode;
import com.google.template.soy.soytree.Visibility;
import com.google.template.soy.soytree.defn.TemplateParam;
Expand Down Expand Up @@ -1491,7 +1491,7 @@ private String genParamsRecordType(TemplateNode node) {
IndirectParamsInfo ipi =
new IndirectParamsCalculator(templateRegistry)
.calculateIndirectParams(
TemplateSignature.fromTemplateMetadata(templateRegistry.getMetadata(node)));
TemplateMetadata.asTemplateType(templateRegistry.getMetadata(node)));
// If there are any calls outside of the file set, then we can't know
// the complete types of any indirect params. In such a case, we can simply
// omit the indirect params from the function type signature, since record
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@
import com.google.template.soy.soytree.TemplateMetadata.Parameter;
import com.google.template.soy.soytree.TemplateNode;
import com.google.template.soy.soytree.TemplateRegistry;
import com.google.template.soy.soytree.TemplateSignature;
import com.google.template.soy.soytree.Visibility;
import com.google.template.soy.soytree.defn.TemplateParam;
import com.google.template.soy.types.SoyTypeRegistry;
import com.google.template.soy.types.TemplateType;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -485,7 +485,7 @@ protected void visitTemplateNode(TemplateNode node) {
// Indirect params.
IndirectParamsInfo indirectParamsInfo =
new IndirectParamsCalculator(templateRegistry)
.calculateIndirectParams(TemplateSignature.fromTemplateMetadata(nodeMetadata));
.calculateIndirectParams(TemplateMetadata.asTemplateType(nodeMetadata));

@SuppressWarnings("ConstantConditions") // for IntelliJ
String upperUnderscoreName =
Expand Down Expand Up @@ -690,7 +690,7 @@ private static String buildTemplateNameForJavadoc(
StringBuilder resultSb = new StringBuilder();

if (template.getSourceLocation().getFilePath().equals(currSoyFile.getFilePath())
&& template.getTemplateKind() != TemplateMetadata.Kind.DELTEMPLATE) {
&& template.getTemplateKind() != TemplateType.TemplateKind.DELTEMPLATE) {
resultSb.append(
template.getTemplateName().substring(template.getTemplateName().lastIndexOf('.')));
} else {
Expand All @@ -712,7 +712,7 @@ private static String buildTemplateNameForJavadoc(
if (template.getVisibility() != Visibility.PUBLIC) {
resultSb.append(" (private)");
}
if (template.getTemplateKind() == TemplateMetadata.Kind.DELTEMPLATE) {
if (template.getTemplateKind() == TemplateType.TemplateKind.DELTEMPLATE) {
resultSb.append(" (delegate)");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
import com.google.template.soy.soytree.SoyNode.RenderUnitNode;
import com.google.template.soy.soytree.SwitchDefaultNode;
import com.google.template.soy.soytree.SwitchNode;
import com.google.template.soy.soytree.TemplateMetadata;
import com.google.template.soy.soytree.TemplateNode;
import com.google.template.soy.types.TemplateType;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -503,12 +503,12 @@ protected void visitSoyNode(SoyNode node) {
* <p>This relies on CheckDelegatesPass to print friendly messages if the deltemplates differ in
* content kind.
*/
private SanitizedContentKind getCommonContentKindIfStrict(List<TemplateMetadata> templates) {
private SanitizedContentKind getCommonContentKindIfStrict(List<TemplateType> templates) {
if (templates.isEmpty()) {
return null;
}
SanitizedContentKind contentKind = templates.get(0).getContentKind();
for (TemplateMetadata template : templates) {
for (TemplateType template : templates) {
Preconditions.checkArgument(template.getContentKind() == contentKind);
}
return contentKind;
Expand All @@ -525,7 +525,7 @@ private SanitizedContentKind getCommonContentKindIfStrict(List<TemplateMetadata>
* side-effect of this call.
*/
private Context inferCallSite(CallNode callNode, Context startContext, Inferences inferences) {
List<TemplateMetadata> targets = inferences.lookupTemplates(callNode);
List<TemplateType> targets = inferences.lookupTemplates(callNode);
SanitizedContentKind calleeStrictContentKind = getCommonContentKindIfStrict(targets);
// Check what kind of template is being called.
if (calleeStrictContentKind != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import com.google.template.soy.soytree.PrintDirectiveNode;
import com.google.template.soy.soytree.PrintNode;
import com.google.template.soy.soytree.SoyNode;
import com.google.template.soy.soytree.TemplateMetadata;
import com.google.template.soy.soytree.TemplateRegistry;
import com.google.template.soy.types.TemplateType;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -69,7 +69,7 @@ public Inferences(TemplateRegistry templates) {
*
* @param templateName A qualified template name.
*/
ImmutableList<TemplateMetadata> lookupTemplates(CallNode call) {
ImmutableList<TemplateType> lookupTemplates(CallNode call) {
return templates.getTemplates(call);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@
import com.google.template.soy.soytree.SoyNode.ExprHolderNode;
import com.google.template.soy.soytree.SoyNode.ParentSoyNode;
import com.google.template.soy.soytree.SoyTreeUtils;
import com.google.template.soy.soytree.TemplateMetadata;
import com.google.template.soy.soytree.TemplateNode;
import com.google.template.soy.soytree.Visibility;
import com.google.template.soy.soytree.defn.LocalVar;
import com.google.template.soy.soytree.defn.TemplateParam;
import com.google.template.soy.types.SanitizedType;
import com.google.template.soy.types.TemplateType;
import java.util.function.Function;
import javax.annotation.Nullable;

Expand Down Expand Up @@ -264,7 +264,7 @@ protected void visitCallNode(CallNode node) {
// deltemplates but there is currently no strong guarantee that they are compatible. So be
// conservative here.
if (node instanceof CallBasicNode) {
ImmutableList<TemplateMetadata> targets = inferences.lookupTemplates(node);
ImmutableList<TemplateType> targets = inferences.lookupTemplates(node);
if (!targets.isEmpty()) {
directives =
ShortCircuitables.filterDirectivesForKind(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ public Void visit(RecordTypeNode node) {

@Override
public Void visit(TemplateTypeNode node) {
for (TemplateTypeNode.Argument argument : node.arguments()) {
argument.type().accept(this);
for (TemplateTypeNode.Parameter parameter : node.parameters()) {
parameter.type().accept(this);
}
node.returnType().accept(this);
return null;
Expand Down
26 changes: 17 additions & 9 deletions java/src/com/google/template/soy/passes/CheckDelegatesPass.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
import com.google.template.soy.error.ErrorReporter;
import com.google.template.soy.error.SoyErrorKind;
import com.google.template.soy.error.SoyErrorKind.StyleAllowance;
import com.google.template.soy.exprtree.TemplateLiteralNode;
import com.google.template.soy.shared.internal.DelTemplateSelector;
import com.google.template.soy.soytree.CallBasicNode;
import com.google.template.soy.soytree.CallDelegateNode;
import com.google.template.soy.soytree.CallParamContentNode;
import com.google.template.soy.soytree.SoyFileNode;
Expand All @@ -51,6 +51,10 @@ final class CheckDelegatesPass implements CompilerFileSetPass {

private static final SoyErrorKind CALL_TO_DELTEMPLATE =
SoyErrorKind.of("''call'' to delegate template ''{0}'' (expected ''delcall'').");
private static final SoyErrorKind DELTEMPLATE_IN_EXPRESSION =
SoyErrorKind.of(
"Delegate template `{0}` not allowed in expression; only basic templates may be used in"
+ " expressions.");
private static final SoyErrorKind CROSS_PACKAGE_DELCALL =
SoyErrorKind.of(
"Found illegal call from ''{0}'' to ''{1}'', which is in a different delegate package.");
Expand Down Expand Up @@ -87,9 +91,10 @@ public Result run(
for (TemplateNode template : fileNode.getTemplates()) {
String currTemplateNameForUserMsgs = template.getTemplateNameForUserMsgs();
String currDelPackageName = template.getDelPackageName();
for (CallBasicNode callNode :
SoyTreeUtils.getAllNodesOfType(template, CallBasicNode.class)) {
checkCallBasicNode(callNode, registry, currDelPackageName, currTemplateNameForUserMsgs);
for (TemplateLiteralNode templateLiteralNode :
SoyTreeUtils.getAllNodesOfType(template, TemplateLiteralNode.class)) {
checkTemplateLiteralNode(
templateLiteralNode, registry, currDelPackageName, currTemplateNameForUserMsgs);
}
for (CallDelegateNode callNode :
SoyTreeUtils.getAllNodesOfType(template, CallDelegateNode.class)) {
Expand Down Expand Up @@ -193,17 +198,20 @@ private static Set<TemplateMetadata.Parameter> getRequiredParamSet(TemplateMetad
.collect(Collectors.toSet());
}

private void checkCallBasicNode(
CallBasicNode node,
private void checkTemplateLiteralNode(
TemplateLiteralNode node,
TemplateRegistry templateRegistry,
@Nullable String currDelPackageName,
String currTemplateNameForUserMsgs) {

String calleeName = node.getCalleeName();
String calleeName = node.getResolvedName();

// Check that the callee name is not a delegate template name.
if (templateRegistry.getDelTemplateSelector().hasDelTemplateNamed(calleeName)) {
errorReporter.report(node.getSourceLocation(), CALL_TO_DELTEMPLATE, calleeName);
if (node.isSynthetic()) {
errorReporter.report(node.getSourceLocation(), CALL_TO_DELTEMPLATE, calleeName);
} else {
errorReporter.report(node.getSourceLocation(), DELTEMPLATE_IN_EXPRESSION, calleeName);
}
}

// Check that the callee is either not in a delegate package or in the same delegate package.
Expand Down
Loading

0 comments on commit c238012

Please sign in to comment.