private static void findSubmemberHidesFieldCollisions(final PsiField field, final String newName, final List<UsageInfo> result) { if (field.getContainingClass() == null) return; if (field.hasModifierProperty(PsiModifier.PRIVATE)) return; final PsiClass containingClass = field.getContainingClass(); Collection<PsiClass> inheritors = ClassInheritorsSearch.search(containingClass, true).findAll(); for (PsiClass inheritor : inheritors) { PsiField conflictingField = inheritor.findFieldByName(newName, false); if (conflictingField != null) { result.add(new SubmemberHidesMemberUsageInfo(conflictingField, field)); } else { //local class final PsiMember member = PsiTreeUtil.getParentOfType(inheritor, PsiMember.class); if (member != null) { final ArrayList<PsiVariable> variables = new ArrayList<PsiVariable>(); ControlFlowUtil.collectOuterLocals(variables, inheritor, inheritor, member); for (PsiVariable variable : variables) { if (newName.equals(variable.getName())) { result.add(new FieldHidesLocalUsageInfo(variable, field)); } } } } } }
private static boolean blockCompletesAbruptly(@NotNull final PsiCodeBlock finallyBlock) { try { ControlFlow flow = ControlFlowFactory.getInstance(finallyBlock.getProject()).getControlFlow(finallyBlock, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false); int completionReasons = ControlFlowUtil.getCompletionReasons(flow, 0, flow.getSize()); if(!BitUtil.isSet(completionReasons, ControlFlowUtil.NORMAL_COMPLETION_REASON)) { return true; } } catch(AnalysisCanceledException e) { return true; } return false; }
public static boolean isReassigned(@NotNull PsiVariable variable, @NotNull Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems) { if(variable instanceof PsiLocalVariable) { final PsiElement parent = variable.getParent(); if(parent == null) { return false; } final PsiElement declarationScope = parent.getParent(); if(declarationScope == null) { return false; } Collection<ControlFlowUtil.VariableInfo> codeBlockProblems = getFinalVariableProblemsInBlock(finalVarProblems, declarationScope); return codeBlockProblems.contains(new ControlFlowUtil.VariableInfo(variable, null)); } if(variable instanceof PsiParameter) { final PsiParameter parameter = (PsiParameter) variable; return isAssigned(parameter); } return false; }
@NotNull private static Collection<ControlFlowUtil.VariableInfo> getFinalVariableProblemsInBlock(@NotNull Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems, @NotNull PsiElement codeBlock) { Collection<ControlFlowUtil.VariableInfo> codeBlockProblems = finalVarProblems.get(codeBlock); if(codeBlockProblems == null) { try { final ControlFlow controlFlow = getControlFlowNoConstantEvaluate(codeBlock); codeBlockProblems = ControlFlowUtil.getInitializedTwice(controlFlow); } catch(AnalysisCanceledException e) { codeBlockProblems = Collections.emptyList(); } finalVarProblems.put(codeBlock, codeBlockProblems); } return codeBlockProblems; }
@Nullable static HighlightInfo checkInitializerCompleteNormally(@NotNull PsiClassInitializer initializer) { final PsiCodeBlock body = initializer.getBody(); // unhandled exceptions already reported try { final ControlFlow controlFlow = getControlFlowNoConstantEvaluate(body); final int completionReasons = ControlFlowUtil.getCompletionReasons(controlFlow, 0, controlFlow.getSize()); if((completionReasons & ControlFlowUtil.NORMAL_COMPLETION_REASON) == 0) { String description = JavaErrorMessages.message("initializer.must.be.able.to.complete.normally"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(body).descriptionAndTooltip(description).create(); } } catch(AnalysisCanceledException e) { // incomplete code } return null; }
private void declareNecessaryVariablesInsideBody(PsiCodeBlock body) throws IncorrectOperationException { List<PsiVariable> usedVariables = myControlFlowWrapper.getUsedVariablesInBody(ControlFlowUtil.findCodeFragment(myElements[0]), myOutputVariables); for(PsiVariable variable : usedVariables) { boolean toDeclare = !isDeclaredInside(variable) && myInputVariables.toDeclareInsideBody(variable); if(toDeclare) { String name = variable.getName(); PsiDeclarationStatement statement = myElementFactory.createVariableDeclarationStatement(name, variable.getType(), null); body.add(statement); } } if(myArtificialOutputVariable instanceof PsiField && !myIsChainedConstructor) { body.add(myElementFactory.createVariableDeclarationStatement(myArtificialOutputVariable.getName(), myArtificialOutputVariable.getType(), null)); } }
private static boolean canBeFinal(@NotNull PsiVariable variable, @NotNull List<PsiReferenceExpression> references) { // if there is at least one assignment to this variable, it cannot be final Map<PsiElement, Collection<PsiReferenceExpression>> uninitializedVarProblems = new THashMap<PsiElement, Collection<PsiReferenceExpression>>(); Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems = new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>(); for (PsiReferenceExpression expression : references) { if (ControlFlowUtil.isVariableAssignedInLoop(expression, variable)) return false; HighlightInfo highlightInfo = HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, variable, uninitializedVarProblems, variable.getContainingFile()); if (highlightInfo != null) return false; highlightInfo = HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, finalVarProblems); if (highlightInfo != null) return false; if (variable instanceof PsiParameter && PsiUtil.isAccessedForWriting(expression)) return false; } return true; }
public static void makeFinalIfNeeded(@NotNull InsertionContext context, @NotNull PsiVariable variable) { PsiElement place = context.getFile().findElementAt(context.getTailOffset() - 1); if (!Registry.is("java.completion.make.outer.variables.final") || place == null || PsiUtil.isLanguageLevel8OrHigher(place) || JspPsiUtil.isInJspFile(place)) { return; } if (HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, place) != null && !HighlightControlFlowUtil.isReassigned(variable, new HashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>())) { PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, true); } }
private void declareNecessaryVariablesInsideBody(PsiCodeBlock body) throws IncorrectOperationException { List<PsiVariable> usedVariables = myControlFlowWrapper.getUsedVariablesInBody(ControlFlowUtil.findCodeFragment(myElements[0]), myOutputVariables); for (PsiVariable variable : usedVariables) { boolean toDeclare = !isDeclaredInside(variable) && myInputVariables.toDeclareInsideBody(variable); if (toDeclare) { String name = variable.getName(); PsiDeclarationStatement statement = myElementFactory.createVariableDeclarationStatement(name, variable.getType(), null); body.add(statement); } } if (myArtificialOutputVariable instanceof PsiField && !myIsChainedConstructor) { body.add(myElementFactory.createVariableDeclarationStatement(myArtificialOutputVariable.getName(), myArtificialOutputVariable.getType(), null)); } }
private static boolean canBeFinal(PsiVariable variable, List<PsiReferenceExpression> references) { // if there is at least one assignment to this variable, it cannot be final Map<PsiElement, Collection<PsiReferenceExpression>> uninitializedVarProblems = new THashMap<PsiElement, Collection<PsiReferenceExpression>>(); Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems = new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>(); for (PsiReferenceExpression expression : references) { if (ControlFlowUtil.isVariableAssignedInLoop(expression, variable)) return false; HighlightInfo highlightInfo = HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, variable, uninitializedVarProblems, variable.getContainingFile()); if (highlightInfo != null) return false; highlightInfo = HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, finalVarProblems); if (highlightInfo != null) return false; if (variable instanceof PsiParameter && PsiUtil.isAccessedForWriting(expression)) return false; } return true; }
private boolean isValueCompatibleNoCache() { final PsiElement body = getBody(); if(body instanceof PsiCodeBlock) { try { ControlFlow controlFlow = ControlFlowFactory.getInstance(getProject()).getControlFlow(body, ourPolicy, false, false); int startOffset = controlFlow.getStartOffset(body); int endOffset = controlFlow.getEndOffset(body); if(startOffset != -1 && endOffset != -1 && ControlFlowUtil.canCompleteNormally(controlFlow, startOffset, endOffset)) { return false; } } //error would be shown inside body catch(AnalysisCanceledException ignore) { } for(PsiReturnStatement statement : PsiUtil.findReturnStatements((PsiCodeBlock) body)) { if(statement.getReturnValue() == null) { return false; } } } return true; }
@Nullable static HighlightInfo checkMissingReturnStatement(@Nullable PsiCodeBlock body, @Nullable PsiType returnType) { if(body == null || returnType == null || PsiType.VOID.equals(returnType.getDeepComponentType())) { return null; } // do not compute constant expressions for if() statement condition // see JLS 14.20 Unreachable Statements try { ControlFlow controlFlow = getControlFlowNoConstantEvaluate(body); if(!ControlFlowUtil.returnPresent(controlFlow)) { PsiJavaToken rBrace = body.getRBrace(); PsiElement context = rBrace == null ? body.getLastChild() : rBrace; String message = JavaErrorMessages.message("missing.return.statement"); HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(context).descriptionAndTooltip(message).create(); PsiElement parent = body.getParent(); if(parent instanceof PsiMethod) { PsiMethod method = (PsiMethod) parent; QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddReturnFix(method)); QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createMethodReturnFix(method, PsiType.VOID, true)); } return info; } } catch(AnalysisCanceledException ignored) { } return null; }
static HighlightInfo checkUnreachableStatement(@Nullable PsiCodeBlock codeBlock) { if(codeBlock == null) { return null; } // do not compute constant expressions for if() statement condition // see JLS 14.20 Unreachable Statements try { AllVariablesControlFlowPolicy policy = AllVariablesControlFlowPolicy.getInstance(); final ControlFlow controlFlow = ControlFlowFactory.getInstance(codeBlock.getProject()).getControlFlow(codeBlock, policy, false, false); final PsiElement unreachableStatement = ControlFlowUtil.getUnreachableStatement(controlFlow); if(unreachableStatement != null) { String description = JavaErrorMessages.message("unreachable.statement"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(unreachableStatement).descriptionAndTooltip(description).create(); } } catch(AnalysisCanceledException e) { // incomplete code } catch(IndexNotReadyException ignored) { } return null; }
/** * see JLS chapter 16 * * @return true if variable assigned (maybe more than once) */ private static boolean variableDefinitelyAssignedIn(@NotNull PsiVariable variable, @NotNull PsiElement context) { try { ControlFlow controlFlow = getControlFlow(context); return ControlFlowUtil.isVariableDefinitelyAssigned(variable, controlFlow); } catch(AnalysisCanceledException e) { return false; } }
private static boolean variableDefinitelyNotAssignedIn(@NotNull PsiVariable variable, @NotNull PsiElement context) { try { ControlFlow controlFlow = getControlFlow(context); return ControlFlowUtil.isVariableDefinitelyNotAssigned(variable, controlFlow); } catch(AnalysisCanceledException e) { return false; } }
@Nullable static HighlightInfo checkFinalVariableInitializedInLoop(@NotNull PsiReferenceExpression expression, @NotNull PsiElement resolved) { if(ControlFlowUtil.isVariableAssignedInLoop(expression, resolved)) { String description = JavaErrorMessages.message("variable.assigned.in.loop", ((PsiVariable) resolved).getName()); final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createModifierListFix((PsiVariable) resolved, PsiModifier.FINAL, false, false)); return highlightInfo; } return null; }
private void declareLocalVariables() throws IncorrectOperationException { final PsiElement codeFragment = ControlFlowUtil.findCodeFragment(getMatchStart()); try { final Project project = getMatchStart().getProject(); final ControlFlow controlFlow = ControlFlowFactory.getInstance(project) .getControlFlow(codeFragment, new LocalsControlFlowPolicy(codeFragment)); final int endOffset = controlFlow.getEndOffset(getMatchEnd()); final int startOffset = controlFlow.getStartOffset(getMatchStart()); final List<PsiVariable> usedVariables = ControlFlowUtil.getUsedVariables(controlFlow, endOffset, controlFlow.getSize()); Collection<ControlFlowUtil.VariableInfo> reassigned = ControlFlowUtil.getInitializedTwice(controlFlow, endOffset, controlFlow.getSize()); final Collection<PsiVariable> outVariables = ControlFlowUtil.getWrittenVariables(controlFlow, startOffset, endOffset, false); for (PsiVariable variable : usedVariables) { if (!outVariables.contains(variable)) { final PsiIdentifier identifier = variable.getNameIdentifier(); if (identifier != null) { final TextRange textRange = checkRange(identifier); final TextRange startRange = checkRange(getMatchStart()); final TextRange endRange = checkRange(getMatchEnd()); if (textRange.getStartOffset() >= startRange.getStartOffset() && textRange.getEndOffset() <= endRange.getEndOffset()) { final String name = variable.getName(); LOG.assertTrue(name != null); PsiDeclarationStatement statement = JavaPsiFacade.getInstance(project).getElementFactory().createVariableDeclarationStatement(name, variable.getType(), null); if (reassigned.contains(new ControlFlowUtil.VariableInfo(variable, null))) { final PsiElement[] psiElements = statement.getDeclaredElements(); final PsiModifierList modifierList = ((PsiVariable)psiElements[0]).getModifierList(); LOG.assertTrue(modifierList != null); modifierList.setModifierProperty(PsiModifier.FINAL, false); } getMatchStart().getParent().addBefore(statement, getMatchStart()); } } } } } catch (AnalysisCanceledException e) { //skip match } }
private void highlightExitPoints(final PsiStatement parent, final PsiCodeBlock body) throws AnalysisCanceledException { final Project project = myTarget.getProject(); ControlFlow flow = ControlFlowFactory.getInstance(project).getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false); Collection<PsiStatement> exitStatements = ControlFlowUtil.findExitPointsAndStatements(flow, 0, flow.getSize(), new IntArrayList(), PsiReturnStatement.class, PsiBreakStatement.class, PsiContinueStatement.class, PsiThrowStatement.class); if(!exitStatements.contains(parent)) { return; } PsiElement originalTarget = getExitTarget(parent); final Iterator<PsiStatement> it = exitStatements.iterator(); while(it.hasNext()) { PsiStatement psiStatement = it.next(); if(getExitTarget(psiStatement) != originalTarget) { it.remove(); } } for(PsiElement e : exitStatements) { addOccurrence(e); } myStatusText = CodeInsightBundle.message("status.bar.exit.points.highlighted.message", exitStatements.size(), HighlightUsagesHandler.getShortcutText()); }
public Collection<PsiStatement> prepareExitStatements(final PsiElement[] elements) throws ExitStatementsNotSameException { myExitPoints = new IntArrayList(); myExitStatements = ControlFlowUtil.findExitPointsAndStatements(myControlFlow, myFlowStart, myFlowEnd, myExitPoints, ControlFlowUtil.DEFAULT_EXIT_STATEMENTS_CLASSES); 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; }
public void testMethodWithOnlyDoWhileStatementHasExitPoints() throws Exception { configureFromFileText("a.java", "public class Foo {\n" + " public void foo() {\n" + " boolean f;\n" + " do {\n" + " f = something();\n" + " } while (f);\n" + " }\n" + "}"); final PsiCodeBlock body = ((PsiJavaFile)getFile()).getClasses()[0].getMethods()[0].getBody(); ControlFlow flow = ControlFlowFactory.getInstance(getProject()).getControlFlow(body, new LocalsControlFlowPolicy(body), false); IntArrayList exitPoints = new IntArrayList(); ControlFlowUtil.findExitPointsAndStatements(flow, 0, flow.getSize() -1 , exitPoints, ControlFlowUtil.DEFAULT_EXIT_STATEMENTS_CLASSES); assertEquals(1, exitPoints.size()); }
/** * Invoked in atomic action */ public boolean prepare(@Nullable Pass<ExtractMethodProcessor> pass) throws PrepareFailedException { myExpression = null; if (myElements.length == 1 && myElements[0] instanceof PsiExpression) { final PsiExpression expression = (PsiExpression)myElements[0]; if (expression instanceof PsiAssignmentExpression && expression.getParent() instanceof PsiExpressionStatement) { myElements[0] = expression.getParent(); } else { myExpression = expression; } } final PsiElement codeFragment = ControlFlowUtil.findCodeFragment(myElements[0]); myCodeFragmentMember = codeFragment.getUserData(ElementToWorkOn.PARENT); if (myCodeFragmentMember == null) { myCodeFragmentMember = codeFragment.getParent(); } if (myCodeFragmentMember == null) { myCodeFragmentMember = ControlFlowUtil.findCodeFragment(codeFragment.getContext()).getParent(); } myControlFlowWrapper = new ControlFlowWrapper(myProject, codeFragment, myElements); try { myExitStatements = myControlFlowWrapper.prepareExitStatements(myElements); if (myControlFlowWrapper.isGenerateConditionalExit()) { myGenerateConditionalExit = true; } else { myHasReturnStatement = myExpression == null && myControlFlowWrapper.isReturnPresentBetween(); } myFirstExitStatementCopy = myControlFlowWrapper.getFirstExitStatementCopy(); } catch (ControlFlowWrapper.ExitStatementsNotSameException e) { myExitStatements = myControlFlowWrapper.getExitStatements(); myNotNullConditionalCheck = areAllExitPointsAreNotNull(getExpectedReturnType()); if (!myNotNullConditionalCheck) { showMultipleExitPointsMessage(); return false; } } myOutputVariables = myControlFlowWrapper.getOutputVariables(); return chooseTargetClass(codeFragment, pass); }
public static boolean canBeDeclaredFinal(@NotNull PsiVariable variable) { LOG.assertTrue(variable instanceof PsiLocalVariable || variable instanceof PsiParameter); final boolean isReassigned = HighlightControlFlowUtil .isReassigned(variable, new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>()); return !isReassigned; }
/** * Invoked in atomic action */ public boolean prepare(@Nullable Pass<ExtractMethodProcessor> pass) throws PrepareFailedException { myExpression = null; if (myElements.length == 1 && myElements[0] instanceof PsiExpression) { final PsiExpression expression = (PsiExpression)myElements[0]; if (expression instanceof PsiAssignmentExpression && expression.getParent() instanceof PsiExpressionStatement) { myElements[0] = expression.getParent(); } else { myExpression = expression; } } final PsiElement codeFragment = ControlFlowUtil.findCodeFragment(myElements[0]); myCodeFragmentMember = codeFragment.getUserData(ElementToWorkOn.PARENT); if (myCodeFragmentMember == null) { myCodeFragmentMember = codeFragment.getParent(); } if (myCodeFragmentMember == null) { myCodeFragmentMember = ControlFlowUtil.findCodeFragment(codeFragment.getContext()).getParent(); } myControlFlowWrapper = new ControlFlowWrapper(myProject, codeFragment, myElements); try { myExitStatements = myControlFlowWrapper.prepareExitStatements(myElements); if (myControlFlowWrapper.isGenerateConditionalExit()) { myGenerateConditionalExit = true; } else { myHasReturnStatement = myExpression == null && myControlFlowWrapper.isReturnPresentBetween(); } myFirstExitStatementCopy = myControlFlowWrapper.getFirstExitStatementCopy(); } catch (ControlFlowWrapper.ExitStatementsNotSameException e) { myExitStatements = myControlFlowWrapper.getExitStatements(); showMultipleExitPointsMessage(); return false; } myOutputVariables = myControlFlowWrapper.getOutputVariables(); checkCanBeChainedConstructor(); return chooseTargetClass(codeFragment, pass); }
public static boolean canBeDeclaredFinal(PsiVariable variable) { LOG.assertTrue(variable instanceof PsiLocalVariable || variable instanceof PsiParameter); final boolean isReassigned = HighlightControlFlowUtil .isReassigned(variable, new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>()); return !isReassigned; }
@NotNull private static List<PsiClassType> getTryExceptions(@NotNull PsiTryStatement tryStatement) { List<PsiClassType> array = ContainerUtil.newArrayList(); PsiResourceList resourceList = tryStatement.getResourceList(); if(resourceList != null) { for(PsiResourceListElement resource : resourceList) { addExceptions(array, getUnhandledCloserExceptions(resource, resourceList)); } } PsiCodeBlock tryBlock = tryStatement.getTryBlock(); if(tryBlock != null) { addExceptions(array, getThrownExceptions(tryBlock)); } for(PsiParameter parameter : tryStatement.getCatchBlockParameters()) { PsiType exception = parameter.getType(); for(int j = array.size() - 1; j >= 0; j--) { PsiClassType exception1 = array.get(j); if(exception.isAssignableFrom(exception1)) { array.remove(exception1); } } } for(PsiCodeBlock catchBlock : tryStatement.getCatchBlocks()) { addExceptions(array, getThrownExceptions(catchBlock)); } PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock(); if(finallyBlock != null) { // if finally block completes normally, exception not caught // if finally block completes abruptly, exception gets lost try { ControlFlow flow = ControlFlowFactory.getInstance(finallyBlock.getProject()).getControlFlow(finallyBlock, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false); int completionReasons = ControlFlowUtil.getCompletionReasons(flow, 0, flow.getSize()); List<PsiClassType> thrownExceptions = getThrownExceptions(finallyBlock); if(!BitUtil.isSet(completionReasons, ControlFlowUtil.NORMAL_COMPLETION_REASON)) { array = ContainerUtil.newArrayList(thrownExceptions); } else { addExceptions(array, thrownExceptions); } } catch(AnalysisCanceledException e) { // incomplete code } } return array; }
public static boolean isEffectivelyFinal(@NotNull PsiVariable variable, @NotNull PsiElement scope, @Nullable PsiJavaCodeReferenceElement context) { boolean effectivelyFinal; if(variable instanceof PsiParameter) { effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(((PsiParameter) variable).getDeclarationScope())); } else { final ControlFlow controlFlow; try { PsiElement codeBlock = PsiUtil.getVariableCodeBlock(variable, context); if(codeBlock == null) { return true; } controlFlow = getControlFlow(codeBlock); } catch(AnalysisCanceledException e) { return true; } final List<PsiReferenceExpression> readBeforeWriteLocals = ControlFlowUtil.getReadBeforeWriteLocals(controlFlow); for(PsiReferenceExpression expression : readBeforeWriteLocals) { if(expression.resolve() == variable) { return PsiUtil.isAccessedForReading(expression); } } final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow); effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null)); if(effectivelyFinal) { effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(scope)); } } return effectivelyFinal; }
public DuplicatesFinder(PsiElement[] pattern, InputVariables parameters, @Nullable ReturnValue returnValue, @NotNull List<? extends PsiVariable> outputParameters) { myReturnValue = returnValue; LOG.assertTrue(pattern.length > 0); myPattern = pattern; myPatternAsList = Arrays.asList(myPattern); myParameters = parameters; myOutputParameters = outputParameters; final PsiElement codeFragment = ControlFlowUtil.findCodeFragment(pattern[0]); try { final ControlFlow controlFlow = ControlFlowFactory.getInstance(codeFragment.getProject()).getControlFlow(codeFragment, new LocalsControlFlowPolicy(codeFragment), false); int startOffset; int i = 0; do { startOffset = controlFlow.getStartOffset(pattern[i++]); } while(startOffset < 0 && i < pattern.length); int endOffset; int j = pattern.length - 1; do { endOffset = controlFlow.getEndOffset(pattern[j--]); } while(endOffset < 0 && j >= 0); IntArrayList exitPoints = new IntArrayList(); final Collection<PsiStatement> exitStatements = ControlFlowUtil.findExitPointsAndStatements(controlFlow, startOffset, endOffset, exitPoints, ControlFlowUtil.DEFAULT_EXIT_STATEMENTS_CLASSES); myMultipleExitPoints = exitPoints.size() > 1; if(myMultipleExitPoints) { myParameters.removeParametersUsedInExitsOnly(codeFragment, exitStatements, controlFlow, startOffset, endOffset); } } catch(AnalysisCanceledException e) { } }
private boolean checkPostVariableUsages(final ArrayList<PsiElement> candidates, final Match match) { final PsiElement codeFragment = ControlFlowUtil.findCodeFragment(candidates.get(0)); try { final ControlFlow controlFlow = ControlFlowFactory.getInstance(codeFragment.getProject()).getControlFlow(codeFragment, new LocalsControlFlowPolicy(codeFragment), false); int startOffset; int i = 0; do { startOffset = controlFlow.getStartOffset(candidates.get(i++)); } while(startOffset < 0 && i < candidates.size()); int endOffset; int j = candidates.size() - 1; do { endOffset = controlFlow.getEndOffset(candidates.get(j--)); } while(endOffset < 0 && j >= 0); final IntArrayList exitPoints = new IntArrayList(); ControlFlowUtil.findExitPointsAndStatements(controlFlow, startOffset, endOffset, exitPoints, ControlFlowUtil.DEFAULT_EXIT_STATEMENTS_CLASSES); final PsiVariable[] outVariables = ControlFlowUtil.getOutputVariables(controlFlow, startOffset, endOffset, exitPoints.toArray()); if(outVariables.length > 0) { if(outVariables.length == 1) { ReturnValue returnValue = match.getReturnValue(); if(returnValue == null) { returnValue = myReturnValue; } if(returnValue instanceof VariableReturnValue) { final ReturnValue value = match.getOutputVariableValue(((VariableReturnValue) returnValue).getVariable()); if(value != null) { if(value.isEquivalent(new VariableReturnValue(outVariables[0]))) { return false; } if(value instanceof ExpressionReturnValue) { final PsiExpression expression = ((ExpressionReturnValue) value).getExpression(); if(expression instanceof PsiReferenceExpression) { final PsiElement variable = ((PsiReferenceExpression) expression).resolve(); return variable == null || !PsiEquivalenceUtil.areElementsEquivalent(variable, outVariables[0]); } } } } } return true; } } catch(AnalysisCanceledException e) { } return false; }
/** * Invoked in atomic action */ public boolean prepare(@Nullable Pass<ExtractMethodProcessor> pass) throws PrepareFailedException { myExpression = null; if(myElements.length == 1 && myElements[0] instanceof PsiExpression) { final PsiExpression expression = (PsiExpression) myElements[0]; if(expression instanceof PsiAssignmentExpression && expression.getParent() instanceof PsiExpressionStatement) { myElements[0] = expression.getParent(); } else { myExpression = expression; } } final PsiElement codeFragment = ControlFlowUtil.findCodeFragment(myElements[0]); myCodeFragmentMember = codeFragment.getUserData(ElementToWorkOn.PARENT); if(myCodeFragmentMember == null) { myCodeFragmentMember = codeFragment.getParent(); } if(myCodeFragmentMember == null) { myCodeFragmentMember = ControlFlowUtil.findCodeFragment(codeFragment.getContext()).getParent(); } myControlFlowWrapper = new ControlFlowWrapper(myProject, codeFragment, myElements); try { myExitStatements = myControlFlowWrapper.prepareExitStatements(myElements); if(myControlFlowWrapper.isGenerateConditionalExit()) { myGenerateConditionalExit = true; } else { myHasReturnStatement = myExpression == null && myControlFlowWrapper.isReturnPresentBetween(); } myFirstExitStatementCopy = myControlFlowWrapper.getFirstExitStatementCopy(); } catch(ControlFlowWrapper.ExitStatementsNotSameException e) { myExitStatements = myControlFlowWrapper.getExitStatements(); myNotNullConditionalCheck = areAllExitPointsAreNotNull(getExpectedReturnType()); if(!myNotNullConditionalCheck) { showMultipleExitPointsMessage(); return false; } } myOutputVariables = myControlFlowWrapper.getOutputVariables(); return chooseTargetClass(codeFragment, pass); }
public boolean isReturnPresentBetween() { return ControlFlowUtil.returnPresentBetween(myControlFlow, myFlowStart, myFlowEnd); }
public List<PsiVariable> getUsedVariables(int start, int end) { return ControlFlowUtil.getUsedVariables(myControlFlow, start, end); }
public Collection<ControlFlowUtil.VariableInfo> getInitializedTwice(int start) { return ControlFlowUtil.getInitializedTwice(myControlFlow, start, myControlFlow.getSize()); }
public Collection<ControlFlowUtil.VariableInfo> getInitializedTwice() { return getInitializedTwice(myFlowEnd); }