boolean (PsiReturnStatement[] returns, PsiCodeBlock body) { if (returns.length == 0) return false; ControlFlow controlFlow; try { controlFlow = ControlFlowFactory.getInstance(body.getProject()).getControlFlow(body, new LocalsControlFlowPolicy(body), false); } catch (AnalysisCanceledException e) { return false; } if (LOG.isDebugEnabled()) { LOG.debug("Control flow:"); LOG.debug(controlFlow.toString()); } List<Instruction> instructions = new ArrayList<>(controlFlow.getInstructions()); // temporary replace all return's with empty statements in the flow for (PsiReturnStatement aReturn : returns) { int offset = controlFlow.getStartOffset(aReturn); int endOffset = controlFlow.getEndOffset(aReturn); while (offset <= endOffset && !(instructions.get(offset) instanceof GoToInstruction)) { offset++; } LOG.assertTrue(instructions.get(offset) instanceof GoToInstruction); instructions.set(offset, EmptyInstruction.INSTANCE); } for (PsiReturnStatement aReturn : returns) { int offset = controlFlow.getEndOffset(aReturn); while (offset != instructions.size()) { Instruction instruction = instructions.get(offset); if (instruction instanceof GoToInstruction) { offset = ((GoToInstruction)instruction).offset; } else if (instruction instanceof ThrowToInstruction) { offset = ((ThrowToInstruction)instruction).offset; } else if (instruction instanceof ConditionalThrowToInstruction) { // In case of "conditional throw to", control flow will not be altered // If exception handler is in method, we will inline it to invocation site // If exception handler is at invocation site, execution will continue to get there offset++; } else { return true; } } } return false; }