boolean (Project project, PsiExpression initializer, boolean shouldBeFinal, boolean strictlyFinal, int accessCount, boolean isAccessedForWriting) { if (strictlyFinal) { class CanAllLocalsBeDeclaredFinal extends JavaRecursiveElementWalkingVisitor { private boolean success = true; @Override public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) { final PsiElement psiElement = expression.resolve(); if (psiElement instanceof PsiLocalVariable || psiElement instanceof PsiParameter) { if (!CommonJavaRefactoringUtil.canBeDeclaredFinal((PsiVariable)psiElement)) { success = false; } } } @Override public void visitElement(@NotNull PsiElement element) { if (success) { super.visitElement(element); } } } final CanAllLocalsBeDeclaredFinal canAllLocalsBeDeclaredFinal = new CanAllLocalsBeDeclaredFinal(); initializer.accept(canAllLocalsBeDeclaredFinal); if (!canAllLocalsBeDeclaredFinal.success) return false; } if (initializer instanceof PsiFunctionalExpression) return accessCount <= 1; if (initializer instanceof PsiReferenceExpression) { PsiVariable refVar = (PsiVariable)((PsiReferenceExpression)initializer).resolve(); if (refVar == null) { return !isAccessedForWriting; } if (refVar instanceof PsiField) { if (isAccessedForWriting) return false; if (refVar.hasModifierProperty(PsiModifier.VOLATILE)) return accessCount <= 1; /* PsiField field = (PsiField)refVar; if (isFieldNonModifiable(field)){ return true; } //TODO: other cases return false; */ return true; //TODO: "suspicious" places to review by user! } else { if (isAccessedForWriting) { if (refVar.hasModifierProperty(PsiModifier.FINAL) || shouldBeFinal) return false; PsiReference[] refs = ReferencesSearch.search(refVar, GlobalSearchScope.projectScope(project), false) .toArray(PsiReference.EMPTY_ARRAY); return refs.length == 1; //TODO: control flow } else { if (shouldBeFinal) { return refVar.hasModifierProperty(PsiModifier.FINAL) || CommonJavaRefactoringUtil.canBeDeclaredFinal(refVar); } return true; } } } else if (isAccessedForWriting) { return false; } else if (initializer instanceof PsiCallExpression) { if (accessCount != 1) return false;//don't allow deleting probable side effects or multiply those side effects if (initializer instanceof PsiNewExpression) { final PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)initializer).getArrayInitializer(); if (arrayInitializer != null) { for (PsiExpression expression : arrayInitializer.getInitializers()) { if (!canInlineParameterOrThisVariable(project, expression, shouldBeFinal, strictlyFinal, accessCount, false)) { return false; } } return true; } } final PsiExpressionList argumentList = ((PsiCallExpression)initializer).getArgumentList(); if (argumentList == null) return false; final PsiExpression[] expressions = argumentList.getExpressions(); for (PsiExpression expression : expressions) { if (!canInlineParameterOrThisVariable(project, expression, shouldBeFinal, strictlyFinal, accessCount, false)) { return false; } } PsiMethod method = ((PsiCallExpression)initializer).resolveMethod(); return method == null || JavaMethodContractUtil.isPure(method); } else if (initializer instanceof PsiLiteralExpression) { return true; } else if (initializer instanceof PsiPrefixExpression && ((PsiPrefixExpression)initializer).getOperand() instanceof PsiLiteralExpression) { return true; } else if (initializer instanceof PsiArrayAccessExpression) { final PsiExpression arrayExpression = ((PsiArrayAccessExpression)initializer).getArrayExpression(); final PsiExpression indexExpression = ((PsiArrayAccessExpression)initializer).getIndexExpression(); return canInlineParameterOrThisVariable(project, arrayExpression, shouldBeFinal, strictlyFinal, accessCount, false) && canInlineParameterOrThisVariable(project, indexExpression, shouldBeFinal, strictlyFinal, accessCount, false); } else if (initializer instanceof PsiParenthesizedExpression) { PsiExpression expr = ((PsiParenthesizedExpression)initializer).getExpression(); return expr == null || canInlineParameterOrThisVariable(project, expr, shouldBeFinal, strictlyFinal, accessCount, false); } else if (initializer instanceof PsiTypeCastExpression) { PsiExpression operand = ((PsiTypeCastExpression)initializer).getOperand(); return operand != null && canInlineParameterOrThisVariable(project, operand, shouldBeFinal, strictlyFinal, accessCount, false); } else if (initializer instanceof PsiPolyadicExpression binExpr) { for (PsiExpression op : binExpr.getOperands()) { if (!canInlineParameterOrThisVariable(project, op, shouldBeFinal, strictlyFinal, accessCount, false)) return false; } return true; } else if (initializer instanceof PsiClassObjectAccessExpression) { return true; } else if (initializer instanceof PsiThisExpression) { return true; } else { return initializer instanceof PsiSuperExpression; } }