Skip to content

Commit 8168df3

Browse files
authored
Fix closure void return anywhere (#1172)
1 parent b7cb017 commit 8168df3

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,7 +2052,8 @@ private void visit(Modifiers modifiers) {
20522052
private void visit(StmtReturn s) {
20532053
if (s.attrNearestExprStatementsBlock() != null) {
20542054
ExprStatementsBlock e = s.attrNearestExprStatementsBlock();
2055-
if (!isClosureImplementationBlock(e) && e.getReturnStmt() != s) {
2055+
boolean closureImplementationBlock = isClosureImplementationBlock(e);
2056+
if (!closureImplementationBlock && e.getReturnStmt() != s) {
20562057
s.addError("Return in a statements block can only be at the end.");
20572058
return;
20582059
}
@@ -2062,7 +2063,9 @@ private void visit(StmtReturn s) {
20622063
s.addError("Cannot return void from statements block.");
20632064
}
20642065
} else {
2065-
s.addError("Cannot have empty return statement in statements block.");
2066+
if (!closureImplementationBlock || !closureReturnsVoid(e)) {
2067+
s.addError("Cannot have empty return statement in statements block.");
2068+
}
20662069
}
20672070
} else {
20682071
FunctionImplementation func = s.attrNearestFuncDef();
@@ -2079,6 +2082,16 @@ private boolean isClosureImplementationBlock(ExprStatementsBlock block) {
20792082
return parent instanceof ExprClosure && ((ExprClosure) parent).getImplementation() == block;
20802083
}
20812084

2085+
private boolean closureReturnsVoid(ExprStatementsBlock block) {
2086+
Element parent = block.getParent();
2087+
if (!(parent instanceof ExprClosure)) {
2088+
return false;
2089+
}
2090+
ExprClosure closure = (ExprClosure) parent;
2091+
FuncLink abstractMethod = closure.attrClosureAbstractMethod();
2092+
return abstractMethod != null && abstractMethod.getReturnType().isVoid();
2093+
}
2094+
20822095
private void checkReturnInFunc(StmtReturn s, FunctionImplementation func) {
20832096
WurstType returnType = func.attrReturnTyp();
20842097
if (s.getReturnedObj() instanceof Expr) {

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ClosureTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,27 @@ public void closure_multipleEarlyReturns_inStatementsBlock() {
499499
);
500500
}
501501

502+
@Test
503+
public void closure_multipleEmptyEarlyReturns_inVoidStatementsBlock() {
504+
testAssertOkLines(true,
505+
"package test",
506+
"native testSuccess()",
507+
"interface FnVoid",
508+
" function run()",
509+
"function call(FnVoid f)",
510+
" f.run()",
511+
"int x = 0",
512+
"init",
513+
" call() ->",
514+
" x = 1",
515+
" if true",
516+
" return",
517+
" x = 2",
518+
" if x == 1",
519+
" testSuccess()"
520+
);
521+
}
522+
502523
@Test
503524
public void statementsBlockOutsideClosure_stillRequiresReturnAtEnd() {
504525
testAssertErrorsLines(false, "Return in a statements block can only be at the end.",

0 commit comments

Comments
 (0)