1717package com .google .template .soy .passes ;
1818
1919import com .google .common .base .Preconditions ;
20- import com .google .template .soy .basetree .SyntaxVersion ;
2120import com .google .template .soy .error .ErrorReporter ;
21+ import com .google .template .soy .error .SoyError ;
2222import com .google .template .soy .soytree .AbstractSoyNodeVisitor ;
2323import com .google .template .soy .soytree .CallBasicNode ;
2424import com .google .template .soy .soytree .SoyFileNode ;
2525import com .google .template .soy .soytree .SoyFileSetNode ;
2626import com .google .template .soy .soytree .SoyNode ;
2727import com .google .template .soy .soytree .SoyNode .ParentSoyNode ;
28- import com .google .template .soy .soytree .SoySyntaxExceptionUtils ;
2928
3029import java .util .Map ;
3130
3231/**
33- * Visitor for setting the full callee name on each CallBasicNode whose callee name in the source
34- * code either (a) is a partial template name or (b) starts with an alias.
35- *
36- * <p> Important: Do not use outside of Soy code (treat as superpackage-private).
32+ * Sets the full callee name on each {@link CallBasicNode} whose callee name
33+ * in the source code either is a partial template name or starts with an alias.
3734 *
3835 * <p> {@link #exec} should be called on a full parse tree or a Soy file. This pass mutates
39- * {@code CallBasicNode}s. There is no return value.
36+ * CallBasicNodes. There is no return value.
37+ *
38+ * <p>TODO(brndn): consider folding into TemplateParser.
4039 *
4140 */
4241final class SetFullCalleeNamesVisitor extends AbstractSoyNodeVisitor <Void > {
4342
43+ private static final SoyError CALL_COLLIDES_WITH_NAMESPACE_ALIAS =
44+ SoyError .of ("Call collides with namespace alias ''{0}''" );
45+ private static final SoyError NAMESPACE_RELATIVE_CALL_IN_FILE_WITHOUT_NAMESPACE_DECL =
46+ SoyError .of ("Namespace-relative template calls are allowed only in files "
47+ + "with namespace declarations" );
4448
4549 /** The namespace of the current file that we're in (during the pass). */
4650 private String currNamespace ;
@@ -76,11 +80,10 @@ final class SetFullCalleeNamesVisitor extends AbstractSoyNodeVisitor<Void> {
7680 if (currNamespace == null ) {
7781 String srcCalleeName = node .getSrcCalleeName ();
7882 // TODO: If feasible, change existing instances and remove the startsWith(".") part below.
79- if (node .couldHaveSyntaxVersionAtLeast (SyntaxVersion .V2_0 ) && srcCalleeName .startsWith ("." )) {
80- throw SoySyntaxExceptionUtils .createWithNode (
81- "Missing namespace in Soy file containing 'call' with namespace-relative callee name" +
82- " (" + node .getTagString () + ")." ,
83- node );
83+ if (srcCalleeName .startsWith ("." )) {
84+ errorReporter .report (
85+ node .getSourceLocation (), NAMESPACE_RELATIVE_CALL_IN_FILE_WITHOUT_NAMESPACE_DECL );
86+ return ; // To prevent IllegalStateException in setCalleeName below
8487 }
8588 node .setCalleeName (node .getSrcCalleeName ());
8689
@@ -103,10 +106,8 @@ final class SetFullCalleeNamesVisitor extends AbstractSoyNodeVisitor<Void> {
103106 } else {
104107 // Case 3: Source callee name is a single ident (not dotted).
105108 if (currAliasToNamespaceMap .containsKey (srcCalleeName )) {
106- throw SoySyntaxExceptionUtils .createWithNode (
107- "In 'call' tag, found callee that is a single identifier (not dotted) and matches" +
108- " a namespace alias ('" + srcCalleeName + "'), which is not allowed." ,
109- node );
109+ errorReporter .report (
110+ node .getSourceLocation (), CALL_COLLIDES_WITH_NAMESPACE_ALIAS , srcCalleeName );
110111 }
111112 node .setCalleeName (srcCalleeName );
112113 }
0 commit comments