hasEarlyReturns.ceylon
import ceylon.ast.core {
Body,
ControlStructure,
IfElse,
Return,
Visitor
}
"Determines if a body contains an early return.
In a body without early returns, removing a return statement
does not cause execution of additional statements, because
no statements occurred behind the return in the original body.
For example, this body contains an early return:
~~~
if (condition) {
return a;
}
return b;
~~~
On the other hand, this one has no early returns:
~~~
if (condition) {
return a;
} else {
return b;
}
~~~"
shared Boolean hasEarlyReturns(Body body) {
class VisitAbortion() extends Exception("Abort visit") {}
try {
body.visit {
object visitor satisfies Visitor {
variable Boolean returnAllowed = true;
shared actual void visitBody(Body that) {
that.children.last?.visit(this);
returnAllowed = false;
for (statement in that.children[... that.children.size - 2]) {
statement.visit(this);
}
}
shared actual void visitIfElse(IfElse that) {
value myReturnAllowed = returnAllowed;
that.ifClause.block.visit(this);
returnAllowed = myReturnAllowed;
that.elseClause?.visit(this);
}
shared actual void visitControlStructure(ControlStructure that) {
returnAllowed = false;
super.visitControlStructure(that);
}
shared actual void visitReturn(Return that) {
if (!returnAllowed) {
throw VisitAbortion();
}
}
}
};
return false;
} catch (VisitAbortion va) {
return true;
}
}