@Override
 public void onInitialize(RefElement refElement) {
   ((RefElementImpl) refElement).setFlag(true, CAN_BE_FINAL_MASK);
   if (refElement instanceof RefClass) {
     final RefClass refClass = (RefClass) refElement;
     final PsiClass psiClass = refClass.getElement();
     if (refClass.isEntry()) {
       ((RefClassImpl) refClass).setFlag(false, CAN_BE_FINAL_MASK);
       return;
     }
     if (refClass.isAbstract() || refClass.isAnonymous() || refClass.isInterface()) {
       ((RefClassImpl) refClass).setFlag(false, CAN_BE_FINAL_MASK);
       return;
     }
     if (!refClass.isSelfInheritor(psiClass)) {
       for (PsiClass psiSuperClass : psiClass.getSupers()) {
         if (myManager.belongsToScope(psiSuperClass)) {
           RefClass refSuperClass = (RefClass) myManager.getReference(psiSuperClass);
           if (refSuperClass != null) {
             ((RefClassImpl) refSuperClass).setFlag(false, CAN_BE_FINAL_MASK);
           }
         }
       }
     }
   } else if (refElement instanceof RefMethod) {
     final RefMethod refMethod = (RefMethod) refElement;
     final PsiElement element = refMethod.getElement();
     if (element instanceof PsiMethod) {
       PsiMethod psiMethod = (PsiMethod) element;
       if (refMethod.isConstructor()
           || refMethod.isAbstract()
           || refMethod.isStatic()
           || PsiModifier.PRIVATE.equals(refMethod.getAccessModifier())
           || refMethod.getOwnerClass().isAnonymous()
           || refMethod.getOwnerClass().isInterface()) {
         ((RefMethodImpl) refMethod).setFlag(false, CAN_BE_FINAL_MASK);
       }
       if (PsiModifier.PRIVATE.equals(refMethod.getAccessModifier())
           && refMethod.getOwner() != null
           && !(refMethod.getOwnerClass().getOwner() instanceof RefElement)) {
         ((RefMethodImpl) refMethod).setFlag(false, CAN_BE_FINAL_MASK);
       }
       for (PsiMethod psiSuperMethod : psiMethod.findSuperMethods()) {
         if (myManager.belongsToScope(psiSuperMethod)) {
           RefMethod refSuperMethod = (RefMethod) myManager.getReference(psiSuperMethod);
           if (refSuperMethod != null) {
             ((RefMethodImpl) refSuperMethod).setFlag(false, CAN_BE_FINAL_MASK);
           }
         }
       }
     }
   }
 }
  @Override
  public void onReferencesBuild(RefElement refElement) {
    if (refElement instanceof RefClass) {
      final PsiClass psiClass = (PsiClass) refElement.getElement();
      if (psiClass != null) {

        if (refElement.isEntry()) {
          ((RefClassImpl) refElement).setFlag(false, CAN_BE_FINAL_MASK);
        }

        PsiMethod[] psiMethods = psiClass.getMethods();
        PsiField[] psiFields = psiClass.getFields();

        HashSet<PsiVariable> allFields = new HashSet<PsiVariable>();
        ContainerUtil.addAll(allFields, psiFields);
        ArrayList<PsiVariable> instanceInitializerInitializedFields = new ArrayList<PsiVariable>();
        boolean hasInitializers = false;
        for (PsiClassInitializer initializer : psiClass.getInitializers()) {
          PsiCodeBlock body = initializer.getBody();
          hasInitializers = true;
          ControlFlow flow;
          try {
            flow =
                ControlFlowFactory.getInstance(body.getProject())
                    .getControlFlow(
                        body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
          } catch (AnalysisCanceledException e) {
            flow = ControlFlow.EMPTY;
          }
          Collection<PsiVariable> writtenVariables = new ArrayList<PsiVariable>();
          ControlFlowUtil.getWrittenVariables(flow, 0, flow.getSize(), false, writtenVariables);
          for (PsiVariable psiVariable : writtenVariables) {
            if (allFields.contains(psiVariable)) {
              if (instanceInitializerInitializedFields.contains(psiVariable)) {
                allFields.remove(psiVariable);
                instanceInitializerInitializedFields.remove(psiVariable);
              } else {
                instanceInitializerInitializedFields.add(psiVariable);
              }
            }
          }
          for (PsiVariable psiVariable : writtenVariables) {
            if (!instanceInitializerInitializedFields.contains(psiVariable)) {
              allFields.remove(psiVariable);
            }
          }
        }

        for (PsiMethod psiMethod : psiMethods) {
          if (psiMethod.isConstructor()) {
            PsiCodeBlock body = psiMethod.getBody();
            if (body != null) {
              hasInitializers = true;
              ControlFlow flow;
              try {
                flow =
                    ControlFlowFactory.getInstance(body.getProject())
                        .getControlFlow(
                            body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
              } catch (AnalysisCanceledException e) {
                flow = ControlFlow.EMPTY;
              }

              Collection<PsiVariable> writtenVariables =
                  ControlFlowUtil.getWrittenVariables(flow, 0, flow.getSize(), false);
              for (PsiVariable psiVariable : writtenVariables) {
                if (instanceInitializerInitializedFields.contains(psiVariable)) {
                  allFields.remove(psiVariable);
                  instanceInitializerInitializedFields.remove(psiVariable);
                }
              }
              List<PsiMethod> redirectedConstructors =
                  HighlightControlFlowUtil.getChainedConstructors(psiMethod);
              if (redirectedConstructors == null || redirectedConstructors.isEmpty()) {
                List<PsiVariable> ssaVariables = ControlFlowUtil.getSSAVariables(flow);
                ArrayList<PsiVariable> good = new ArrayList<PsiVariable>(ssaVariables);
                good.addAll(instanceInitializerInitializedFields);
                allFields.retainAll(good);
              } else {
                allFields.removeAll(writtenVariables);
              }
            }
          }
        }

        for (PsiField psiField : psiFields) {
          if ((!hasInitializers || !allFields.contains(psiField))
              && psiField.getInitializer() == null) {
            final RefFieldImpl refField = (RefFieldImpl) myManager.getReference(psiField);
            if (refField != null) {
              refField.setFlag(false, CAN_BE_FINAL_MASK);
            }
          }
        }
      }
    } else if (refElement instanceof RefMethod) {
      final RefMethod refMethod = (RefMethod) refElement;
      if (refMethod.isEntry()) {
        ((RefMethodImpl) refMethod).setFlag(false, CAN_BE_FINAL_MASK);
      }
    }
  }