public static boolean isEffectivelyFinal(@NotNull PsiVariable variable, @NotNull PsiElement scope, @Nullable PsiJavaCodeReferenceElement context) {
    boolean effectivelyFinal;
    if (variable instanceof PsiParameter) {
      effectivelyFinal = !VariableAccessUtils.variableIsAssigned(variable, ((PsiParameter)variable).getDeclarationScope());
    }
    else {
      PsiElement codeBlock = PsiUtil.getVariableCodeBlock(variable, context);
      ControlFlow controlFlow;
      try {
        if (codeBlock == null) return true;
        controlFlow = getControlFlow(codeBlock);
      }
      catch (AnalysisCanceledException e) {
        return true;
      }

      Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
      effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
      if (effectivelyFinal) {
        List<PsiReferenceExpression> readBeforeWriteLocals = ControlFlowUtil.getReadBeforeWriteLocals(controlFlow);
        for (PsiReferenceExpression expression : readBeforeWriteLocals) {
          if (expression.resolve() == variable) {
            return PsiUtil.isAccessedForReading(expression);
          }
        }
        effectivelyFinal = !VariableAccessUtils.variableIsAssigned(variable, scope);
        if (effectivelyFinal) {
          Ref<Boolean> stopped = new Ref<>(false);
          codeBlock.accept(new JavaRecursiveElementWalkingVisitor() {
            @Override
            public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
              if (expression.isReferenceTo(variable) &&
                  PsiUtil.isAccessedForWriting(expression) &&
                  ControlFlowUtil.isVariableAssignedInLoop(expression, variable)) {
                stopWalking();
                stopped.set(true);
              }
            }
          });
          return !stopped.get();
        }
      }
    }
    return effectivelyFinal;
  }
public static boolean isEffectivelyFinal(@NotNull PsiVariable variable, @NotNull PsiElement scope, @Nullable PsiJavaCodeReferenceElement context)