return false;
}
}
public void render(RenderContext rc) {
TokenConsumer out = rc.getOut();
out.mark(getFilePosition());
switch (op.getType()) {
case PREFIX:
out.consume(op.getSymbol());
renderParam(0, rc);
if (op == Operator.CONSTRUCTOR) {
// We emit zero-arg constructors without (), because it's shorter,
// but that has implications in parenthesize() below.
int n = children().size();
if (1 < n) {
out.consume("(");
for (int k = 1; k < n; k++) {
if (1 < k) { out.consume(","); }
renderParam(k, rc);
}
out.consume(")");
}
}
break;
case POSTFIX:
renderParam(0, rc);
out.mark(FilePosition.endOfOrNull(getFilePosition()));
out.consume(op.getSymbol());
break;
case INFIX:
renderParam(0, rc);
switch (getOperator()) {
default:
// These spaces are necessary for security.
// If they are not present, then rendered javascript might include
// the strings ]]> or </script> which would prevent it from being
// safely embedded in HTML or XML.
out.consume(" ");
out.consume(op.getSymbol());
out.consume(" ");
renderParam(1, rc);
break;
case MEMBER_ACCESS:
renderMemberAccess(rc);
break;
case COMMA:
out.consume(op.getSymbol());
renderParam(1, rc);
break;
}
break;
case BRACKET:
// Note that FUNCTION_CALL is a BRACKET operator; this is why we can
// have any number of child expressions, not just two.
renderParam(0, rc);
out.consume(op.getOpeningSymbol());
boolean seen = false;
for (ParseTreeNode e : children().subList(1, children().size())) {
if (seen) {
out.consume(",");
} else {
seen = true;
}
// make sure that comma operators are properly escaped
if (!parenthesize(Operator.COMMA, false, (Expression) e)) {
e.render(rc);
} else {
out.consume("(");
e.render(rc);
out.mark(FilePosition.endOfOrNull(e.getFilePosition()));
out.consume(")");
}
}
out.mark(FilePosition.endOfOrNull(getFilePosition()));
out.consume(op.getClosingSymbol());
break;
case TERNARY:
renderParam(0, rc);
out.consume(op.getOpeningSymbol());
out.consume(" ");
renderParam(1, rc);
out.consume(op.getClosingSymbol());
out.consume(" ");
renderParam(2, rc);
break;
}
}