com.google.clearsilver.jsilver.syntax
Class VarOptimizer
java.lang.Object
com.google.clearsilver.jsilver.syntax.analysis.AnalysisAdapter
com.google.clearsilver.jsilver.syntax.analysis.DepthFirstAdapter
com.google.clearsilver.jsilver.syntax.VarOptimizer
- All Implemented Interfaces:
- Analysis, Switch
public class VarOptimizer
- extends DepthFirstAdapter
Recursively optimizes the syntax tree with a set of simple operations. This class currently
optimizes:
- String concatenation in var commands
- Function calls to escaping functions
String add expressions in var commands are optimized by replacing something like:
<cs? var:a + b ?>
with:
<cs? var:a ?><cs? var:b ?>
This avoids having to construct the intermediate result a + b
at runtime and reduces
runtime heap allocations.
Functions call to escaping functions are optimized by replacing them with the equivalent escaping
construct. This is faster because escapers are called with the strings themselves whereas general
function calls require value objects to be created.
Expressions such as:
<cs? var:html_escape(foo) ?>
are turned into:
<cs? escape:"html" ?>
<cs? var:foo ?>
<?cs /escape ?>
It also optimizes sequences of escaped expressions into a single escaped sequence.
It is important to note that these optimizations cannot be done in isolation if we want to
optimize compound expressions such as:
<cs? html_escape(foo + bar) + baz ?>
which is turned into:
<cs? escape:"html" ?>
<cs? var:foo ?>
<cs? var:bar ?>
<?cs /escape ?>
<?cs var:baz ?>
WARNING: This class isn't strictly just an optimization and its modification of the syntax tree
actually improves JSilver's behavior, bringing it more in line with ClearSilver. Consider the
sequence:
<cs? escape:"html" ?>
<cs? var:url_escape(foo) ?>
<?cs /escape ?>
In JSilver (without this optimizer being run) this would result in foo
being escaped by
both the html escaper and the url escaping function. However ClearSilver treats top-level escaper
functions specially and foo
is only escaped once by the url escaping function.
The good news is that this optimization rewrites the above example to:
<cs? escape:"html" ?>
<cs? escape:"url" ?>
<cs? var:foo ?>
<?cs /escape ?>
<?cs /escape ?>
which fixes the problem because the new url escaper replaces the existing html escaper (rather
than combining with it).
The only fly in the ointment here is the url_validate
function which is treated like an
escaper by ClearSilver but which does not (currently) have an escaper associated with it. This
means that:
<cs? escape:"html" ?>
<cs? var:url_validate(foo) ?>
<?cs /escape ?>
will not be rewritten by this class and will result in foo
being escaped twice.
Methods inherited from class com.google.clearsilver.jsilver.syntax.analysis.DepthFirstAdapter |
caseAAddExpression, caseAAltCommand, caseAAndExpression, caseAAutoescapeCommand, caseACallCommand, caseACommaExpression, caseACommentCommand, caseAContentTypeCommand, caseACsOpenPosition, caseADataCommand, caseADecimalExpression, caseADecNumberVariable, caseADefCommand, caseADescendVariable, caseADivideExpression, caseAEachCommand, caseAEqExpression, caseAEscapeCommand, caseAEvarCommand, caseAExistsExpression, caseAExpandVariable, caseAFunctionExpression, caseAGteExpression, caseAGtExpression, caseAHardIncludeCommand, caseAHardLincludeCommand, caseAHexExpression, caseAHexNumberVariable, caseAIfCommand, caseAIncludeCommand, caseAInlineCommand, caseALincludeCommand, caseALoopCommand, caseALoopIncCommand, caseALoopToCommand, caseALteExpression, caseALtExpression, caseALvarCommand, caseAModuloExpression, caseAMultiplyExpression, caseANameCommand, caseANameVariable, caseANeExpression, caseANegativeExpression, caseANoopCommand, caseANoopExpression, caseANotExpression, caseANumericAddExpression, caseANumericEqExpression, caseANumericExpression, caseANumericNeExpression, caseAOrExpression, caseASequenceExpression, caseASetCommand, caseAStringExpression, caseASubtractExpression, caseAUvarCommand, caseAVariableExpression, caseAWithCommand, caseStart, defaultIn, defaultOut, inAAddExpression, inAAltCommand, inAAndExpression, inAAutoescapeCommand, inACallCommand, inACommaExpression, inACommentCommand, inAContentTypeCommand, inACsOpenPosition, inADataCommand, inADecimalExpression, inADecNumberVariable, inADefCommand, inADescendVariable, inADivideExpression, inAEachCommand, inAEqExpression, inAEscapeCommand, inAEvarCommand, inAExistsExpression, inAExpandVariable, inAFunctionExpression, inAGteExpression, inAGtExpression, inAHardIncludeCommand, inAHardLincludeCommand, inAHexExpression, inAHexNumberVariable, inAIfCommand, inAIncludeCommand, inAInlineCommand, inALincludeCommand, inALoopCommand, inALoopIncCommand, inALoopToCommand, inALteExpression, inALtExpression, inALvarCommand, inAModuloExpression, inAMultipleCommand, inAMultiplyExpression, inANameCommand, inANameVariable, inANeExpression, inANegativeExpression, inANoopCommand, inANoopExpression, inANotExpression, inANumericAddExpression, inANumericEqExpression, inANumericExpression, inANumericNeExpression, inAOrExpression, inASequenceExpression, inASetCommand, inAStringExpression, inASubtractExpression, inAUvarCommand, inAVarCommand, inAVariableExpression, inAWithCommand, inStart, outAAddExpression, outAAltCommand, outAAndExpression, outAAutoescapeCommand, outACallCommand, outACommaExpression, outACommentCommand, outAContentTypeCommand, outACsOpenPosition, outADataCommand, outADecimalExpression, outADecNumberVariable, outADefCommand, outADescendVariable, outADivideExpression, outAEachCommand, outAEqExpression, outAEscapeCommand, outAEvarCommand, outAExistsExpression, outAExpandVariable, outAFunctionExpression, outAGteExpression, outAGtExpression, outAHardIncludeCommand, outAHardLincludeCommand, outAHexExpression, outAHexNumberVariable, outAIfCommand, outAIncludeCommand, outAInlineCommand, outALincludeCommand, outALoopCommand, outALoopIncCommand, outALoopToCommand, outALteExpression, outALtExpression, outALvarCommand, outAModuloExpression, outAMultipleCommand, outAMultiplyExpression, outANameCommand, outANameVariable, outANeExpression, outANegativeExpression, outANoopCommand, outANoopExpression, outANotExpression, outANumericAddExpression, outANumericEqExpression, outANumericExpression, outANumericNeExpression, outAOrExpression, outASequenceExpression, outASetCommand, outAStringExpression, outASubtractExpression, outAUvarCommand, outAVarCommand, outAVariableExpression, outAWithCommand, outStart |
Methods inherited from class com.google.clearsilver.jsilver.syntax.analysis.AnalysisAdapter |
caseEOF, caseTAlt, caseTAnd, caseTArgWhitespace, caseTAssignment, caseTAutoescape, caseTBang, caseTBracketClose, caseTBracketOpen, caseTCall, caseTComma, caseTCommandDelimiter, caseTComment, caseTCommentStart, caseTContentType, caseTCsClose, caseTCsOpen, caseTData, caseTDecNumber, caseTDef, caseTDollar, caseTDot, caseTEach, caseTElse, caseTElseIf, caseTEq, caseTEscape, caseTEvar, caseTGt, caseTGte, caseTHardDelimiter, caseTHash, caseTHexNumber, caseTIf, caseTInclude, caseTInline, caseTLinclude, caseTLoop, caseTLt, caseTLte, caseTLvar, caseTMinus, caseTName, caseTNe, caseTOr, caseTParenClose, caseTParenOpen, caseTPercent, caseTPlus, caseTQuestion, caseTSet, caseTSlash, caseTStar, caseTString, caseTUvar, caseTVar, caseTWith, caseTWord, defaultCase, getIn, getOut, setIn, setOut |
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
VarOptimizer
public VarOptimizer(Collection<String> escaperNames)
caseAMultipleCommand
public void caseAMultipleCommand(AMultipleCommand multiCommand)
- Specified by:
caseAMultipleCommand
in interface Analysis
- Overrides:
caseAMultipleCommand
in class DepthFirstAdapter
caseAVarCommand
public void caseAVarCommand(AVarCommand varCommand)
- Specified by:
caseAVarCommand
in interface Analysis
- Overrides:
caseAVarCommand
in class DepthFirstAdapter
Copyright © 2010-2012 Google. All Rights Reserved.