use of com.google.template.soy.soytree.SoyFileNode in project closure-templates by google.
the class HtmlRewritePassTest method assertThatSourceString.
private static StringSubject assertThatSourceString(TemplateNode node) {
SoyFileNode parent = node.getParent().copy(new CopyState());
new DesugarHtmlNodesPass().run(parent, new IncrementingIdGenerator());
StringBuilder sb = new StringBuilder();
parent.getChild(0).appendSourceStringForChildren(sb);
return assertThat(sb.toString());
}
use of com.google.template.soy.soytree.SoyFileNode in project closure-templates by google.
the class DesugarHtmlNodesPassTest method runPass.
/**
* Parses the given input as a template content, runs the HtmlRewrite pass and the Desugar Passes
* and returns the resulting source string of the template body
*/
private static String runPass(String input) {
String soyFile = Joiner.on('\n').join("{namespace ns}", "{template .t}", input, "{/template}");
SoyFileNode node = SoyFileSetParserBuilder.forFileContents(soyFile).desugarHtmlNodes(true).parse().fileSet().getChild(0);
assertThat(SoyTreeUtils.hasHtmlNodes(node)).isFalse();
StringBuilder sb = new StringBuilder();
node.getChild(0).appendSourceStringForChildren(sb);
return sb.toString();
}
use of com.google.template.soy.soytree.SoyFileNode in project closure-templates by google.
the class FindIndirectParamsVisitorTest method testFindIndirectParams.
@Test
public void testFindIndirectParams() {
String fileContent1 = "{namespace alpha}\n" + "\n" + "/** @param? a0 @param? b3 */\n" + // 'b3' listed by alpha.zero
"{template .zero}\n" + " {call .zero data=\"all\" /}\n" + // recursive call should not cause 'a0' to be added
" {call .one data=\"all\" /}\n" + " {call .two /}\n" + " {call beta.zero /}\n" + " {call .five data=\"all\"}\n" + " {param a5: $a0 /}\n" + " {param b2: 88 /}\n" + " {/call}\n" + "{/template}\n" + "\n" + "/** @param? a1 */\n" + "{template .one}\n" + " {call .three data=\"all\" /}\n" + " {call .four /}\n" + " {$a1}\n" + "{/template}\n" + "\n" + "/** @param? a2 */\n" + "{template .two}\n" + " {$a2}\n" + "{/template}\n" + "\n" + "/** @param? a3 */\n" + "{template .three}\n" + " {call beta.one data=\"all\" /}\n" + " {$a3}\n" + "{/template}\n" + "\n" + "/** @param? a4 */\n" + "{template .four}\n" + " {call external.one /}\n" + " {$a4}\n" + "{/template}\n" + "\n" + "/** @param? a5 @param? b4 */\n" + // 'b4' listed by alpha.five
"{template .five}\n" + " {call beta.two data=\"all\" /}\n" + " {call beta.three data=\"all\" /}\n" + " {call beta.four data=\"all\" /}\n" + " {$b4}\n" + " {$a5}\n" + "{/template}\n" + "\n" + "/** @param? a6 */\n" + "{template .six}\n" + " {$a6}\n" + "{/template}\n";
String fileContent2 = "{namespace beta}\n" + "\n" + "/** @param? b0 */\n" + "{template .zero}\n" + " {$b0}\n" + "{/template}\n" + "\n" + "/** @param? b1 */\n" + "{template .one}\n" + " {call alpha.six data=\"all\" /}\n" + " {$b1}\n" + "{/template}\n" + "\n" + "/** @param? b2 */\n" + "{template .two}\n" + " {$b2}\n" + "{/template}\n" + "\n" + "/** @param? b3 */\n" + "{template .three}\n" + " {$b3}\n" + "{/template}\n" + "\n" + "/** @param? b4 */\n" + "{template .four}\n" + " {$b4}\n" + "{/template}\n";
ErrorReporter boom = ErrorReporter.exploding();
SoyFileSetNode soyTree = SoyFileSetParserBuilder.forFileContents(fileContent1, fileContent2).errorReporter(boom).parse().fileSet();
TemplateRegistry registry = new TemplateRegistry(soyTree, boom);
SoyFileNode a = soyTree.getChild(0);
TemplateNode a0 = a.getChild(0);
TemplateNode a1 = a.getChild(1);
// TemplateNode a2 = a.getChild(2);
TemplateNode a3 = a.getChild(3);
// TemplateNode a4 = a.getChild(4);
TemplateNode a5 = a.getChild(5);
TemplateNode a6 = a.getChild(6);
SoyFileNode b = soyTree.getChild(1);
// TemplateNode b0 = b.getChild(0);
TemplateNode b1 = b.getChild(1);
// TemplateNode b2 = b.getChild(2);
TemplateNode b3 = b.getChild(3);
TemplateNode b4 = b.getChild(4);
IndirectParamsInfo ipi = new FindIndirectParamsVisitor(registry).exec(a0);
assertThat(ipi.mayHaveIndirectParamsInExternalCalls).isFalse();
assertThat(ipi.mayHaveIndirectParamsInExternalDelCalls).isFalse();
Map<String, TemplateParam> ipMap = ipi.indirectParams;
assertThat(ipMap).hasSize(6);
assertThat(ipMap).doesNotContainKey("a0");
assertThat(ipMap).containsKey("a1");
assertThat(ipMap).doesNotContainKey("a2");
assertThat(ipMap).containsKey("a3");
assertThat(ipMap).doesNotContainKey("a4");
assertThat(ipMap).doesNotContainKey("a5");
assertThat(ipMap).containsKey("a6");
assertThat(ipMap).doesNotContainKey("b0");
assertThat(ipMap).containsKey("b1");
assertThat(ipMap).doesNotContainKey("b2");
assertThat(ipMap).containsKey("b3");
assertThat(ipMap).containsKey("b4");
Multimap<String, TemplateNode> pktcm = ipi.paramKeyToCalleesMultimap;
assertThat(pktcm).valuesForKey("a1").isEqualTo(ImmutableSet.of(a1));
assertThat(pktcm).valuesForKey("a3").isEqualTo(ImmutableSet.of(a3));
assertThat(pktcm).valuesForKey("a6").isEqualTo(ImmutableSet.of(a6));
assertThat(pktcm).valuesForKey("b1").isEqualTo(ImmutableSet.of(b1));
assertThat(pktcm).valuesForKey("b3").isEqualTo(ImmutableSet.of(b3));
// 'b4' listed by alpha.five
assertThat(pktcm).valuesForKey("b4").isEqualTo(ImmutableSet.of(a5, b4));
}
use of com.google.template.soy.soytree.SoyFileNode in project closure-templates by google.
the class GenerateParseInfoVisitor method visitSoyFileSetNode.
// -----------------------------------------------------------------------------------------------
// Implementations for specific nodes.
@Override
protected void visitSoyFileSetNode(SoyFileSetNode node) {
// Figure out the generated class name for each Soy file, including adding number suffixes
// to resolve collisions, and then adding the common suffix "SoyInfo".
Multimap<String, SoyFileNode> baseGeneratedClassNameToSoyFilesMap = HashMultimap.create();
for (SoyFileNode soyFile : node.getChildren()) {
if (soyFile.getSoyFileKind() == SoyFileKind.SRC) {
baseGeneratedClassNameToSoyFilesMap.put(javaClassNameSource.generateBaseClassName(soyFile), soyFile);
}
}
soyFileToJavaClassNameMap = Maps.newHashMap();
for (String baseClassName : baseGeneratedClassNameToSoyFilesMap.keySet()) {
Collection<SoyFileNode> soyFiles = baseGeneratedClassNameToSoyFilesMap.get(baseClassName);
if (soyFiles.size() == 1) {
for (SoyFileNode soyFile : soyFiles) {
soyFileToJavaClassNameMap.put(soyFile, baseClassName + "SoyInfo");
}
} else {
int numberSuffix = 1;
for (SoyFileNode soyFile : soyFiles) {
soyFileToJavaClassNameMap.put(soyFile, baseClassName + numberSuffix + "SoyInfo");
numberSuffix++;
}
}
}
// Run the pass.
for (SoyFileNode soyFile : node.getChildren()) {
visit(soyFile);
}
}
use of com.google.template.soy.soytree.SoyFileNode in project closure-templates by google.
the class ContextualAutoescaper method rewrite.
/**
* Rewrites the given Soy files so that dynamic output is properly escaped according to the
* context in which it appears.
*
* @param fileSet Modified in place.
* @return Extra templates which were derived from templates under fileSet and which must be
* compiled with fileSet to produce a correct output. See {@link DerivedTemplateUtils} for an
* explanation of these.
*/
public List<TemplateNode> rewrite(SoyFileSetNode fileSet, ErrorReporter errorReporter) {
// Defensively copy so our loops below hold.
List<SoyFileNode> files = ImmutableList.copyOf(fileSet.getChildren());
ImmutableListMultimap<String, TemplateNode> templatesByName = findTemplates(files);
// Inferences collects all the typing decisions we make, templates we derive, and escaping modes
// we choose.
Inferences inferences = new Inferences(fileSet.getNodeIdGenerator(), templatesByName);
Collection<TemplateNode> allTemplates = inferences.getAllTemplates();
TemplateCallGraph callGraph = new TemplateCallGraph(templatesByName);
// Generate a call graph, creating a dummy root that calls all non-private template in
// Context.PCDATA, and then type the minimal ancestor set needed to reach all contextual
// templates whether private or not.
// This should have the effect of being a NOP when there are no contextual templates, will type
// all contextual templates, and will not barf on private templates that might be declared
// autoescape="false" because they do funky things that are provably safe by human reason but
// not by this algorithm.
Collection<TemplateNode> thatRequireInference = Collections2.filter(allTemplates, REQUIRES_INFERENCE);
Set<TemplateNode> templateNodesToType = callGraph.callersOf(thatRequireInference);
templateNodesToType.addAll(thatRequireInference);
Set<SourceLocation> errorLocations = new HashSet<>();
for (TemplateNode templateNode : templateNodesToType) {
try {
// In strict mode, the author specifies the kind of SanitizedContent to produce, and thus
// the context in which to escape.
Context startContext = (templateNode.getContentKind() != null) ? Context.getStartContextForContentKind(templateNode.getContentKind()) : Context.HTML_PCDATA;
InferenceEngine.inferTemplateEndContext(templateNode, startContext, inferences, errorReporter);
} catch (SoyAutoescapeException e) {
reportError(errorReporter, errorLocations, e);
}
}
if (!errorLocations.isEmpty()) {
// Bail out early, since future passes won't succeed and may throw precondition errors.
return ImmutableList.<TemplateNode>of();
}
// Store inferences so that after processing, clients can access the output contexts for
// templates.
this.inferences = inferences;
runVisitorOnAllTemplatesIncludingNewOnes(inferences, new NonContextualTypedRenderUnitNodesVisitor(errorReporter));
// Now that we know we don't fail with exceptions, apply the changes to the given files.
List<TemplateNode> extraTemplates = new Rewriter(inferences, printDirectives).rewrite(fileSet);
runVisitorOnAllTemplatesIncludingNewOnes(inferences, new PerformDeprecatedNonContextualAutoescapeVisitor(fileSet.getNodeIdGenerator()));
return extraTemplates;
}
Aggregations