Java control flow: Detect unreachable code when a break or continue in the try block is overridden in the finally block of the same try statement (IDEA-35597)

This commit is contained in:
Pavel Dolgov
2016-07-29 14:54:49 +03:00
parent 3e3b40df65
commit 7b97664b85
3 changed files with 98 additions and 11 deletions
@@ -412,6 +412,8 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
startElement(statement);
PsiStatement exitedStatement = statement.findExitedStatement();
if (exitedStatement != null) {
callFinallyBlocksOnExit(exitedStatement);
final Instruction instruction;
final PsiElement finallyBlock = findEnclosingFinallyBlockElement(statement, exitedStatement);
final int finallyStartOffset = finallyBlock == null ? -1 : myCurrentFlow.getStartOffset(finallyBlock);
@@ -430,6 +432,18 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
finishElement(statement);
}
private void callFinallyBlocksOnExit(PsiStatement exitedStatement) {
for (final ListIterator<PsiElement> it = myFinallyBlocks.listIterator(myFinallyBlocks.size()); it.hasPrevious(); ) {
final PsiElement finallyBlock = it.previous();
final PsiElement enclosingTryStatement = finallyBlock.getParent();
if (enclosingTryStatement == null || !PsiTreeUtil.isAncestor(exitedStatement, enclosingTryStatement, false)) {
break;
}
myCurrentFlow.addInstruction(new CallInstruction(0, 0, myStack));
addElementOffsetLater(finallyBlock, true);
}
}
private PsiElement findEnclosingFinallyBlockElement(@NotNull PsiElement sourceElement, @Nullable PsiElement jumpElement) {
PsiElement element = sourceElement;
while (element != null && !(element instanceof PsiFile)) {
@@ -451,21 +465,14 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
PsiStatement continuedStatement = statement.findContinuedStatement();
if (continuedStatement != null) {
PsiElement body = null;
if (continuedStatement instanceof PsiForStatement) {
body = ((PsiForStatement)continuedStatement).getBody();
}
else if (continuedStatement instanceof PsiWhileStatement) {
body = ((PsiWhileStatement)continuedStatement).getBody();
}
else if (continuedStatement instanceof PsiDoWhileStatement) {
body = ((PsiDoWhileStatement)continuedStatement).getBody();
}
else if (continuedStatement instanceof PsiForeachStatement) {
body = ((PsiForeachStatement)continuedStatement).getBody();
if (continuedStatement instanceof PsiLoopStatement) {
body = ((PsiLoopStatement)continuedStatement).getBody();
}
if (body == null) {
body = myCodeFragment;
}
callFinallyBlocksOnExit(continuedStatement);
final Instruction instruction;
final PsiElement finallyBlock = findEnclosingFinallyBlockElement(statement, continuedStatement);
final int finallyStartOffset = finallyBlock == null ? -1 : myCurrentFlow.getStartOffset(finallyBlock);