public PsiStatement getExitStatementCopy( PsiElement returnStatement, final PsiElement[] elements) { PsiStatement exitStatementCopy = null; // replace all exit-statements such as break's or continue's with appropriate return for (PsiStatement exitStatement : myExitStatements) { if (exitStatement instanceof PsiReturnStatement) { if (!myGenerateConditionalExit) continue; } else if (exitStatement instanceof PsiBreakStatement) { PsiStatement statement = ((PsiBreakStatement) exitStatement).findExitedStatement(); if (statement == null) continue; int startOffset = myControlFlow.getStartOffset(statement); int endOffset = myControlFlow.getEndOffset(statement); if (myFlowStart <= startOffset && endOffset <= myFlowEnd) continue; } else if (exitStatement instanceof PsiContinueStatement) { PsiStatement statement = ((PsiContinueStatement) exitStatement).findContinuedStatement(); if (statement == null) continue; int startOffset = myControlFlow.getStartOffset(statement); int endOffset = myControlFlow.getEndOffset(statement); if (myFlowStart <= startOffset && endOffset <= myFlowEnd) continue; } else { LOG.error(String.valueOf(exitStatement)); continue; } int index = -1; for (int j = 0; j < elements.length; j++) { if (exitStatement.equals(elements[j])) { index = j; break; } } if (exitStatementCopy == null) { if (needExitStatement(exitStatement)) { exitStatementCopy = (PsiStatement) exitStatement.copy(); } } PsiElement result = exitStatement.replace(returnStatement); if (index >= 0) { elements[index] = result; } } return exitStatementCopy; }
private boolean needExitStatement(final PsiStatement exitStatement) { if (exitStatement instanceof PsiContinueStatement) { // IDEADEV-11748 PsiStatement statement = ((PsiContinueStatement) exitStatement).findContinuedStatement(); if (statement == null) return true; if (statement instanceof PsiLoopStatement) statement = ((PsiLoopStatement) statement).getBody(); int endOffset = myControlFlow.getEndOffset(statement); return endOffset > myFlowEnd; } return true; }
public ControlFlowWrapper(Project project, PsiElement codeFragment, PsiElement[] elements) throws PrepareFailedException { try { myControlFlow = ControlFlowFactory.getInstance(project) .getControlFlow( codeFragment, new LocalsControlFlowPolicy(codeFragment), false, false); } catch (AnalysisCanceledException e) { throw new PrepareFailedException( RefactoringBundle.message("extract.method.control.flow.analysis.failed"), e.getErrorElement()); } if (LOG.isDebugEnabled()) { LOG.debug(myControlFlow.toString()); } int flowStart = -1; int index = 0; while (index < elements.length) { flowStart = myControlFlow.getStartOffset(elements[index]); if (flowStart >= 0) break; index++; } int flowEnd; if (flowStart < 0) { // no executable code flowStart = 0; flowEnd = 0; } else { index = elements.length - 1; while (true) { flowEnd = myControlFlow.getEndOffset(elements[index]); if (flowEnd >= 0) break; index--; } } myFlowStart = flowStart; myFlowEnd = flowEnd; if (LOG.isDebugEnabled()) { LOG.debug("start offset:" + myFlowStart); LOG.debug("end offset:" + myFlowEnd); } }
@Override public boolean isVoidCompatible() { final PsiElement body = getBody(); if (body != null) { try { ControlFlow controlFlow = ControlFlowFactory.getInstance(getProject()) .getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance()); int startOffset = controlFlow.getStartOffset(body); int endOffset = controlFlow.getEndOffset(body); return startOffset != -1 && endOffset != -1 && !ControlFlowUtil.canCompleteNormally(controlFlow, startOffset, endOffset); } catch (AnalysisCanceledException e) { return true; } } return true; }
public Collection<PsiStatement> prepareExitStatements( final @NotNull PsiElement[] elements, final @NotNull PsiElement enclosingCodeFragment) throws ExitStatementsNotSameException { myExitPoints = new IntArrayList(); myExitStatements = ControlFlowUtil.findExitPointsAndStatements( myControlFlow, myFlowStart, myFlowEnd, myExitPoints, ControlFlowUtil.DEFAULT_EXIT_STATEMENTS_CLASSES); if (ControlFlowUtil.hasObservableThrowExitPoints( myControlFlow, myFlowStart, myFlowEnd, elements, enclosingCodeFragment)) { throw new ExitStatementsNotSameException(); } if (LOG.isDebugEnabled()) { LOG.debug("exit points:"); for (int i = 0; i < myExitPoints.size(); i++) { LOG.debug(" " + myExitPoints.get(i)); } LOG.debug("exit statements:"); for (PsiStatement exitStatement : myExitStatements) { LOG.debug(" " + exitStatement); } } if (myExitPoints.isEmpty()) { // if the fragment never exits assume as if it exits in the end myExitPoints.add(myControlFlow.getEndOffset(elements[elements.length - 1])); } if (myExitPoints.size() != 1) { myGenerateConditionalExit = true; areExitStatementsTheSame(); } return myExitStatements; }