Skip to content

Commit a5ccf61

Browse files
Shashank Shailabhjknack
authored andcommitted
change parsing rule to disallow multiple else statements
1 parent 275b5ec commit a5ccf61

File tree

3 files changed

+55
-48
lines changed

3 files changed

+55
-48
lines changed

handlebars/src/main/antlr4/com/github/jknack/handlebars/internal/HbsParser.g4

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ block
7474
:
7575
startToken = START_BLOCK DECORATOR? sexpr blockParams? END
7676
thenBody=body
77-
elseBlock*
77+
elseBlock
7878
END_BLOCK nameEnd=QID END
7979
;
8080

@@ -97,8 +97,8 @@ sexpr
9797

9898
elseBlock
9999
:
100-
elseStmt
101-
| elseStmtChain
100+
elseStmtChain*
101+
elseStmt?
102102
;
103103

104104
elseStmt

handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateBuilder.java

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -240,53 +240,53 @@ public Template visitBlock(final BlockContext ctx) {
240240
}
241241
// else
242242
Block elseroot = block;
243-
for (ElseBlockContext elseBlock : ctx.elseBlock()) {
244-
ElseStmtContext elseStmt = elseBlock.elseStmt();
245-
if (elseStmt != null) {
246-
// basic else
247-
Template unless = visitBody(elseStmt.unlessBody);
248-
if (unless != null) {
249-
String inverseLabel = elseStmt.inverseToken.getText();
250-
if (inverseLabel.startsWith(startDelim)) {
251-
inverseLabel = inverseLabel.substring(startDelim.length());
252-
}
253-
if (inverseLabel.endsWith("~")) {
254-
inverseLabel = inverseLabel.substring(0, inverseLabel.length() - 1);
255-
}
256-
elseroot.inverse(inverseLabel, unless);
257-
}
258-
} else {
259-
// else chain
260-
ElseStmtChainContext elseStmtChain = elseBlock.elseStmtChain();
261-
SexprContext elseexpr = elseStmtChain.sexpr();
262-
Token elsenameStart = elseexpr.QID().getSymbol();
263-
String elsename = elsenameStart.getText();
264-
String type = elseStmtChain.inverseToken.getText();
265-
if (type.equals("else")) {
266-
type = "else ";
267-
}
268-
Block elseblock =
269-
new Block(
270-
handlebars,
271-
elsename,
272-
false,
273-
type,
274-
params(elseexpr.param()),
275-
hash(elseexpr.hash()),
276-
blockParams(elseStmtChain.blockParams()));
277-
elseblock.filename(source.filename());
278-
elseblock.position(elsenameStart.getLine(), elsenameStart.getCharPositionInLine());
279-
elseblock.startDelimiter(startDelim);
280-
elseblock.endDelimiter(elseStmtChain.END().getText());
281-
Template elsebody = visitBody(elseStmtChain.unlessBody);
282-
elseblock.body(elsebody);
283-
284-
String inverseLabel = elseStmtChain.inverseToken.getText();
243+
ElseBlockContext elseBlock = ctx.elseBlock();
244+
ElseStmtContext elseStmt = elseBlock.elseStmt();
245+
List<ElseStmtChainContext> elseStmtChain = elseBlock.elseStmtChain();
246+
for (ElseStmtChainContext elseStmtChainContext : elseStmtChain) {
247+
// else if chain
248+
SexprContext elseexpr = elseStmtChainContext.sexpr();
249+
Token elsenameStart = elseexpr.QID().getSymbol();
250+
String elsename = elsenameStart.getText();
251+
String type = elseStmtChainContext.inverseToken.getText();
252+
if (type.equals("else")) {
253+
type = "else ";
254+
}
255+
Block elseblock =
256+
new Block(
257+
handlebars,
258+
elsename,
259+
false,
260+
type,
261+
params(elseexpr.param()),
262+
hash(elseexpr.hash()),
263+
blockParams(elseStmtChainContext.blockParams()));
264+
elseblock.filename(source.filename());
265+
elseblock.position(elsenameStart.getLine(), elsenameStart.getCharPositionInLine());
266+
elseblock.startDelimiter(startDelim);
267+
elseblock.endDelimiter(elseStmtChainContext.END().getText());
268+
Template elsebody = visitBody(elseStmtChainContext.unlessBody);
269+
elseblock.body(elsebody);
270+
271+
String inverseLabel = elseStmtChainContext.inverseToken.getText();
272+
if (inverseLabel.startsWith(startDelim)) {
273+
inverseLabel = inverseLabel.substring(startDelim.length());
274+
}
275+
elseroot.inverse(inverseLabel, elseblock);
276+
elseroot = elseblock;
277+
}
278+
if (elseStmt != null) {
279+
// basic else
280+
Template unless = visitBody(elseStmt.unlessBody);
281+
if (unless != null) {
282+
String inverseLabel = elseStmt.inverseToken.getText();
285283
if (inverseLabel.startsWith(startDelim)) {
286284
inverseLabel = inverseLabel.substring(startDelim.length());
287285
}
288-
elseroot.inverse(inverseLabel, elseblock);
289-
elseroot = elseblock;
286+
if (inverseLabel.endsWith("~")) {
287+
inverseLabel = inverseLabel.substring(0, inverseLabel.length() - 1);
288+
}
289+
elseroot.inverse(inverseLabel, unless);
290290
}
291291
}
292292
hasTag(true);

handlebars/src/test/java/com/github/jknack/handlebars/ParsingErrorTest.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ public class ParsingErrorTest extends AbstractTest {
5959
"idx3",
6060
"{{list.[]}}",
6161
"idx4",
62-
"{{list.[}}");
62+
"{{list.[}}",
63+
"multipleElse",
64+
"{{#if true}} b1 {{else}} b2 {{else}} b3 {{/if}}");
6365

6466
@Test
6567
public void correctPath() throws IOException {
@@ -166,6 +168,11 @@ public void idx4() throws IOException {
166168
assertThrows(HandlebarsException.class, () -> parse("idx4"));
167169
}
168170

171+
@Test
172+
public void multipleElse() throws IOException {
173+
assertThrows(HandlebarsException.class, () -> parse("multipleElse"));
174+
}
175+
169176
private void parse(final String candidate) throws IOException {
170177
try {
171178
String input = (String) source.get(candidate);

0 commit comments

Comments
 (0)