TryWithResources: fixed unbalanced stack

This commit is contained in:
Tagir Valeev
2017-11-13 16:19:07 +07:00
parent ec0da9f9b7
commit c99ce0966e
4 changed files with 70 additions and 43 deletions
@@ -93,11 +93,6 @@ public class ControlFlow {
public int getInstructionOffset() {
return myElementToStartOffsetMap.get(element);
}
@Override
public String toString() {
return String.valueOf(myElementToStartOffsetMap.get(element));
}
};
}
@@ -107,11 +102,6 @@ public class ControlFlow {
public int getInstructionOffset() {
return myElementToEndOffsetMap.get(element);
}
@Override
public String toString() {
return String.valueOf(myElementToEndOffsetMap.get(element));
}
};
}
@@ -127,8 +117,13 @@ public class ControlFlow {
return result.toString();
}
public interface ControlFlowOffset {
int getInstructionOffset();
public abstract static class ControlFlowOffset {
public abstract int getInstructionOffset();
@Override
public String toString() {
return String.valueOf(getInstructionOffset());
}
}
static ControlFlowOffset deltaOffset(final ControlFlowOffset delegate, final int delta) {
@@ -922,32 +922,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
myTrapStack = myTrapStack.prepend(new Trap.TryCatch(statement, clauses));
}
Set<PsiClassType> closerExceptions = Collections.emptySet();
Trap.TwrFinally twrFinallyDescriptor = null;
if (resourceList != null) {
resourceList.accept(this);
closerExceptions = StreamEx.of(resourceList.iterator()).flatCollection(ExceptionUtil::getCloserExceptions).toSet();
if (!closerExceptions.isEmpty()) {
twrFinallyDescriptor = new Trap.TwrFinally(resourceList, getStartOffset(resourceList));
myTrapStack = myTrapStack.prepend(twrFinallyDescriptor);
}
}
if (tryBlock != null) {
tryBlock.accept(this);
}
if (twrFinallyDescriptor != null) {
assert myTrapStack.getHead() instanceof Trap.TwrFinally;
InstructionTransfer gotoEnd = new InstructionTransfer(getEndOffset(resourceList), getVariablesInside(tryBlock));
controlTransfer(gotoEnd, FList.createFromReversed(ContainerUtil.createMaybeSingletonList(twrFinallyDescriptor)));
myTrapStack = myTrapStack.getTail();
startElement(resourceList);
addThrows(null, closerExceptions.toArray(PsiClassType.EMPTY_ARRAY));
addInstruction(new ControlTransferInstruction(null)); // DfaControlTransferValue is on stack
finishElement(resourceList);
}
processTryWithResources(resourceList, tryBlock);
InstructionTransfer gotoEnd = new InstructionTransfer(getEndOffset(statement), getVariablesInside(tryBlock));
FList<Trap> singleFinally = FList.createFromReversed(ContainerUtil.createMaybeSingletonList(finallyDescriptor));
@@ -980,6 +955,37 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
finishElement(statement);
}
private void processTryWithResources(@Nullable PsiResourceList resourceList, @Nullable PsiCodeBlock tryBlock) {
Set<PsiClassType> closerExceptions = Collections.emptySet();
Trap.TwrFinally twrFinallyDescriptor = null;
if (resourceList != null) {
resourceList.accept(this);
closerExceptions = StreamEx.of(resourceList.iterator()).flatCollection(ExceptionUtil::getCloserExceptions).toSet();
if (!closerExceptions.isEmpty()) {
twrFinallyDescriptor = new Trap.TwrFinally(resourceList, getStartOffset(resourceList));
myTrapStack = myTrapStack.prepend(twrFinallyDescriptor);
}
}
if (tryBlock != null) {
tryBlock.accept(this);
}
if (twrFinallyDescriptor != null) {
assert myTrapStack.getHead() instanceof Trap.TwrFinally;
InstructionTransfer gotoEnd = new InstructionTransfer(getEndOffset(resourceList), getVariablesInside(tryBlock));
controlTransfer(gotoEnd, FList.createFromReversed(ContainerUtil.createMaybeSingletonList(twrFinallyDescriptor)));
myTrapStack = myTrapStack.getTail().prepend(new Trap.InsideFinally(resourceList));
startElement(resourceList);
addThrows(null, closerExceptions.toArray(PsiClassType.EMPTY_ARRAY));
addInstruction(new ControlTransferInstruction(null)); // DfaControlTransferValue is on stack
finishElement(resourceList);
assert myTrapStack.getHead() instanceof Trap.InsideFinally;
myTrapStack = myTrapStack.getTail();
}
}
@Override
public void visitResourceList(PsiResourceList resourceList) {
for (PsiResourceListElement resource : resourceList) {
@@ -59,14 +59,23 @@ open class ControlTransferInstruction(val transfer: DfaControlTransferValue?) :
fun getPossibleTargetInstructions(allInstructions: Array<Instruction>) = getPossibleTargetIndices().map { allInstructions[it] }
override fun toString() = transfer.toString()
override fun toString() = if (transfer == null) "RET" else "TRANSFER " + transfer.toString()
}
sealed class Trap(val anchor: PsiElement) {
class TryCatch(tryStatement : PsiTryStatement, val clauses: LinkedHashMap<PsiCatchSection, ControlFlow.ControlFlowOffset>): Trap(tryStatement)
class TryFinally(val finallyBlock: PsiCodeBlock, val jumpOffset: ControlFlow.ControlFlowOffset): Trap(finallyBlock)
class TwrFinally(resourceList: PsiResourceList, val jumpOffset: ControlFlow.ControlFlowOffset): Trap(resourceList)
class InsideFinally(val finallyBlock: PsiCodeBlock): Trap(finallyBlock)
class TryCatch(tryStatement: PsiTryStatement, val clauses: LinkedHashMap<PsiCatchSection, ControlFlow.ControlFlowOffset>)
: Trap(tryStatement) {
override fun toString(): String = "TryCatch -> " + clauses.values
}
class TryFinally(finallyBlock: PsiCodeBlock, val jumpOffset: ControlFlow.ControlFlowOffset): Trap(finallyBlock) {
override fun toString(): String = "TryFinally -> " + jumpOffset
}
class TwrFinally(resourceList: PsiResourceList, val jumpOffset: ControlFlow.ControlFlowOffset): Trap(resourceList) {
override fun toString(): String = "TwrFinally -> " + jumpOffset
}
class InsideFinally(finallyBlock: PsiElement): Trap(finallyBlock) {
override fun toString(): String = "InsideFinally"
}
internal fun getPossibleTargets(): Collection<Int> {
return when (this) {
@@ -1,4 +1,5 @@
import java.io.*;
import java.util.*;
// IDEA-181860
class bugcheck {
@@ -48,4 +49,20 @@ class bugcheck {
// s is never null here
return s.trim();
}
static List<String> inLoop(String[] paths) {
List<String> strings = new ArrayList<>();
for (String path : paths) {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
String s = br.readLine();
if (s != null) {
strings.add(s);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
return strings;
}
}