diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java index da372d04d..1b21a10d8 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java @@ -2052,7 +2052,8 @@ private void visit(Modifiers modifiers) { private void visit(StmtReturn s) { if (s.attrNearestExprStatementsBlock() != null) { ExprStatementsBlock e = s.attrNearestExprStatementsBlock(); - if (!isClosureImplementationBlock(e) && e.getReturnStmt() != s) { + boolean closureImplementationBlock = isClosureImplementationBlock(e); + if (!closureImplementationBlock && e.getReturnStmt() != s) { s.addError("Return in a statements block can only be at the end."); return; } @@ -2062,7 +2063,9 @@ private void visit(StmtReturn s) { s.addError("Cannot return void from statements block."); } } else { - s.addError("Cannot have empty return statement in statements block."); + if (!closureImplementationBlock || !closureReturnsVoid(e)) { + s.addError("Cannot have empty return statement in statements block."); + } } } else { FunctionImplementation func = s.attrNearestFuncDef(); @@ -2079,6 +2082,16 @@ private boolean isClosureImplementationBlock(ExprStatementsBlock block) { return parent instanceof ExprClosure && ((ExprClosure) parent).getImplementation() == block; } + private boolean closureReturnsVoid(ExprStatementsBlock block) { + Element parent = block.getParent(); + if (!(parent instanceof ExprClosure)) { + return false; + } + ExprClosure closure = (ExprClosure) parent; + FuncLink abstractMethod = closure.attrClosureAbstractMethod(); + return abstractMethod != null && abstractMethod.getReturnType().isVoid(); + } + private void checkReturnInFunc(StmtReturn s, FunctionImplementation func) { WurstType returnType = func.attrReturnTyp(); if (s.getReturnedObj() instanceof Expr) { diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ClosureTests.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ClosureTests.java index e027dd6a1..f17925c55 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ClosureTests.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ClosureTests.java @@ -499,6 +499,27 @@ public void closure_multipleEarlyReturns_inStatementsBlock() { ); } + @Test + public void closure_multipleEmptyEarlyReturns_inVoidStatementsBlock() { + testAssertOkLines(true, + "package test", + "native testSuccess()", + "interface FnVoid", + " function run()", + "function call(FnVoid f)", + " f.run()", + "int x = 0", + "init", + " call() ->", + " x = 1", + " if true", + " return", + " x = 2", + " if x == 1", + " testSuccess()" + ); + } + @Test public void statementsBlockOutsideClosure_stillRequiresReturnAtEnd() { testAssertErrorsLines(false, "Return in a statements block can only be at the end.",