Skip to content

Commit

Permalink
Templates no longer use internal StringBuilders, they instead write d…
Browse files Browse the repository at this point in the history
…irectly to the provided Writer
  • Loading branch information
mbosecke committed Jan 3, 2014
1 parent fe9e29b commit 14876e9
Show file tree
Hide file tree
Showing 15 changed files with 159 additions and 80 deletions.
14 changes: 7 additions & 7 deletions src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public class PebbleEngine {
* User Editable Settings
*/
private boolean cacheTemplates = true;
private boolean strictVariables = true;
private boolean strictVariables = false;
private String charset = "UTF-8";
private Locale defaultLocale = Locale.getDefault();

Expand Down Expand Up @@ -184,7 +184,7 @@ private PebbleTemplate compile(String templateName, boolean isPrimary) throws Sy
}

instance = getCompiler().compileToJava(javaSource, className);

// give the template some KNOWLEDGE
instance.setEngine(this);
instance.setGeneratedJavaCode(javaSource);
Expand Down Expand Up @@ -378,7 +378,7 @@ public String getTemplateClassName(String templateName) {
byte[] bytesOfName;
MessageDigest md;
try {
bytesOfName = templateName.getBytes(getCharset());
bytesOfName = templateName.getBytes("UTF-8");
md = MessageDigest.getInstance("MD5");
md.update(bytesOfName);
byte[] hash = md.digest();
Expand Down Expand Up @@ -427,12 +427,12 @@ public String getCharset() {
public void setCharset(String charset) {
this.charset = charset;
}
public Locale getDefaultLocale(){

public Locale getDefaultLocale() {
return defaultLocale;
}
public void setDefaultLocale(Locale locale){

public void setDefaultLocale(Locale locale) {
this.defaultLocale = locale;
}
}
24 changes: 19 additions & 5 deletions src/main/java/com/mitchellbosecke/pebble/node/NodeBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,32 @@ public void setBody(NodeBody body) {

@Override
public void compile(Compiler compiler) {
compileMainBlockMethod(compiler);
compileBlockMethodReturningString(compiler);
}

private void compileMainBlockMethod(Compiler compiler) {
compiler.write(
String.format("public String %s%s() throws com.mitchellbosecke.pebble.error.PebbleException {\n",
String.format(
"public void %s%s(PebbleWrappedWriter writer) throws com.mitchellbosecke.pebble.error.PebbleException {\n",
BLOCK_PREFIX, this.name)).indent();

compiler.write("StringBuilder builder = new StringBuilder();\n");

compiler.subcompile(body);

compiler.raw("\n").write("return builder.toString();");

compiler.raw("\n").outdent().write("}\n");
}

private void compileBlockMethodReturningString(Compiler compiler) {
compiler.write(
String.format("public String %s%s() throws com.mitchellbosecke.pebble.error.PebbleException {\n",
BLOCK_PREFIX, this.name)).indent();

compiler.write("java.io.StringWriter stringWriter = new java.io.StringWriter();\n");
compiler.write("PebbleWrappedWriter writer = new PebbleWrappedWriter(stringWriter);\n");
compiler.write(String.format("%s%s(writer);\n", BLOCK_PREFIX, this.name));
compiler.write("return stringWriter.toString();\n");

compiler.raw("\n").outdent().write("}\n");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public NodeFlush(int lineNumber) {
public void compile(Compiler compiler) {

compiler.raw("\n");
compiler.write("flush();");
compiler.write("writer.flush();");

compiler.raw("\n");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public NodeInclude(int lineNumber, NodeExpression includeExpression) {
public void compile(Compiler compiler) {

compiler.raw("\n");
compiler.write("flush();");
compiler.write("this.engine.compile(").subcompile(includeExpression).raw(").evaluate(writer);");
compiler.write("writer.flush();").raw("\n");
compiler.write("this.engine.compile(").subcompile(includeExpression).raw(").evaluate(writer.getWriter());");

compiler.raw("\n");
}
Expand Down
27 changes: 18 additions & 9 deletions src/main/java/com/mitchellbosecke/pebble/node/NodeMacro.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,36 +34,45 @@ public NodeMacro(int lineNumber, String name, NodeExpressionArguments args, Node
public void compile(Compiler compiler) {

/*
* Add a map as a secret argument
* Because the macro might exist in a different template we must
* manually pass the context and writer as secret arguments.
*
* We prefix them with underscores because technically they get put into
* the context and are then accessible to the user and we want to avoid
* conflicts.
*
* TODO: remove the underscore prefix and simultaneously prevent these
* two args from being added into context object and are therefore
* inaccessible to user.
*/
NodeExpressionDeclaration mapDeclaration = new NodeExpressionDeclaration(args.getLineNumber(), "_context");
args.addArgument(mapDeclaration);
NodeExpressionDeclaration contextDeclaration = new NodeExpressionDeclaration(args.getLineNumber(), "_context");
NodeExpressionDeclaration writerDeclaration = new NodeExpressionDeclaration(args.getLineNumber(), "_writer");
args.addArgument(contextDeclaration);
args.addArgument(writerDeclaration);

compiler.write(String.format("public String %s%s", MACRO_PREFIX, name)).subcompile(args).raw("{\n\n").indent();
compiler.write(String.format("public void %s%s", MACRO_PREFIX, name)).subcompile(args)
.raw(" throws com.mitchellbosecke.pebble.error.PebbleException {\n\n").indent();

/*
* Each macro has it's own copy of the main context. We will add the
* macro arguments into this new context to give them scope and easy
* accessibility.
*
* We can't use pushContext() here because the macro might exist in a
* We can't use pushContext() here because the macro might exist in a
* completely different template.
*/
compiler.write("Context context = new Context(((Context)_context).isStrictVariables());").raw("\n");
compiler.write("context.setParent((Context)_context);").raw("\n");
compiler.write("PebbleWrappedWriter writer = (PebbleWrappedWriter)_writer;").raw("\n");

// put args into scoped context
for (NodeExpression arg : args.getArgs()) {
compiler.write("context.put(").string(((NodeExpressionDeclaration) arg).getName()).raw(",")
.raw(((NodeExpressionDeclaration) arg).getName()).raw(");\n");
}

compiler.write("StringBuilder builder = new StringBuilder();").raw("\n");

compiler.subcompile(body);

compiler.raw("\n").write("return builder.toString();").raw("\n");

compiler.raw("\n").outdent().write("}");

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public NodePrint(NodeExpression expression, int lineNumber) {
@Override
public void compile(Compiler compiler) {

compiler.raw("\n").write("builder.append(printVariable(").subcompile(expression).raw("));");
compiler.raw("\n").write("writer.write(printVariable(").subcompile(expression).raw("));");
}

}
15 changes: 12 additions & 3 deletions src/main/java/com/mitchellbosecke/pebble/node/NodeRoot.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.mitchellbosecke.pebble.compiler.Compiler;
import com.mitchellbosecke.pebble.template.PebbleTemplate;
import com.mitchellbosecke.pebble.utils.Context;
import com.mitchellbosecke.pebble.utils.PebbleWrappedWriter;

public class NodeRoot extends AbstractNode {

Expand Down Expand Up @@ -66,7 +67,13 @@ private void compileClassHeader(Compiler compiler) {
.raw("\n")
.write("import java.util.HashMap;")
.raw("\n")
.write("import ").raw(Context.class.getName()).raw(";")
.write("import ")
.raw(Context.class.getName())
.raw(";")
.raw("\n")
.write("import ")
.raw(PebbleWrappedWriter.class.getName())
.raw(";")
.raw("\n")
.raw("\n")
.write(String.format("public class %s extends %s implements %s {", compiler.getEngine()
Expand All @@ -75,7 +82,9 @@ private void compileClassHeader(Compiler compiler) {
}

private void compileBuildContentFunction(Compiler compiler) {
compiler.raw("\n\n").write("public void buildContent() throws com.mitchellbosecke.pebble.error.PebbleException {").raw("\n").indent();
compiler.raw("\n\n")
.write("public void buildContent() throws com.mitchellbosecke.pebble.error.PebbleException {")
.raw("\n").indent();

body.compile(compiler);

Expand All @@ -94,7 +103,7 @@ private void compileBlockMethods(Compiler compiler) {

private void compileMacroMethods(Compiler compiler) {
for (List<NodeMacro> overloadedMacros : macros.values()) {
for(NodeMacro macro: overloadedMacros){
for (NodeMacro macro : overloadedMacros) {
compiler.raw("\n\n").subcompile(macro);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public NodeText(String data, int lineNumber) {

@Override
public void compile(Compiler compiler) {
compiler.raw("\n").write("builder.append(").string(getData()).raw(");");
compiler.raw("\n").write("writer.write(").string(getData()).raw(");");
}

public String getData() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public NodeExpressionArguments(int lineNumber, NodeExpression[] args) {
}

/**
* NodeMacro will use this method to add a secret _context argument when
* compiling macro declarations.
* NodeMacro will use this method to add a secret context and writer
* arguments.
*/
public void addArgument(NodeExpressionDeclaration declaration) {
List<NodeExpression> arguments = new ArrayList<>(Arrays.asList(args));
Expand All @@ -45,7 +45,7 @@ public void compile(Compiler compiler) {
compiler.subcompile(var, true);

if (i < (args.length - 1)) {
compiler.raw(",");
compiler.raw(", ");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public class NodeExpressionBlockReference extends NodeExpression implements Disp

/*
* output is true if the block is referenced in an expression using the
* block() function, otherwise it is false if it is referenced using block
* tags, ie. {% block name %}
* {{ block() }} function, otherwise it is false if it is referenced using block
* tags, ie. {% block name %}{% endblock %}
*/
private final boolean output;

Expand All @@ -34,9 +34,9 @@ public NodeExpressionBlockReference(int lineNumber, String name, boolean output)
@Override
public void compile(Compiler compiler) {
if (!this.output) {
compiler.raw("\n").write(String.format("builder.append(%s%s());\n", NodeBlock.BLOCK_PREFIX, this.name));
compiler.raw("\n").write(String.format("%s%s(writer);\n", NodeBlock.BLOCK_PREFIX, this.name));
} else {
compiler.raw(String.format("%s%s()\n", NodeBlock.BLOCK_PREFIX, this.name));
compiler.raw(String.format("%s%s()", NodeBlock.BLOCK_PREFIX, this.name));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,40 @@

public class NodeExpressionParentReference extends NodeExpression implements DisplayableNode {

private final String name;
private final String blockName;
private final String parentClassName;

public NodeExpressionParentReference(int lineNumber, String name) {
public NodeExpressionParentReference(int lineNumber, String parentClassName, String blockName) {
super(lineNumber);
this.name = name;
this.blockName = blockName;
this.parentClassName = parentClassName;
}

/*
*
*
* Every block has has two methods, one that writes to a Writer and one that
* returns a String. It's important that the parent() function returns a
* string as it's part of an expression. Unfortunately we can't call
* super.block_blockname() which is the version that returns a String
* because THAT version actually calls the block_blockname(Writer writer)
* version which will end up being the overridden by the child class.
* Therefore we must instantiate an instance of the parent class which has
* no overridden block methods.
*
* So instead of:
* String result = super.block_blockName();
*
* We have:
* String result = (new ParentClass()).block_blockName();
*
* Which is definitely a bit of a shame.
*
*/

@Override
public void compile(Compiler compiler) {
compiler.raw(String.format("super.%s%s()\n", NodeBlock.BLOCK_PREFIX, this.name));
compiler.raw(String.format("(new %s()).%s%s()", parentClassName, NodeBlock.BLOCK_PREFIX, this.blockName));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -342,11 +342,13 @@ private NodeExpression parseFunctionExpression(NodeExpression node) throws Synta
*/
switch ((String) functionName.getValue()) {
case "parent":
return new NodeExpressionParentReference(node.getLineNumber(), parser.peekBlockStack());
String parentClassName = this.parser.getEngine().getTemplateClassName(this.parser.getParentFileName());
return new NodeExpressionParentReference(node.getLineNumber(), parentClassName, parser.peekBlockStack());
case "block":
String blockName = (String) ((NodeExpressionString) args.getArgs()[0]).getValue();
return new NodeExpressionBlockReference(node.getLineNumber(), blockName, true);
}


return new NodeExpressionFunctionCall(lineNumber, functionName, args);
}
Expand Down
Loading

0 comments on commit 14876e9

Please sign in to comment.