@NotNull
 private static ControlFlow getControlFlow(@NotNull PsiElement context)
     throws AnalysisCanceledException {
   LocalsOrMyInstanceFieldsControlFlowPolicy policy =
       LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance();
   return ControlFlowFactory.getInstance(context.getProject()).getControlFlow(context, policy);
 }
 @Override
 public boolean isValueCompatible() {
   final PsiElement body = getBody();
   if (body != null) {
     try {
       final ControlFlow controlFlow =
           ControlFlowFactory.getInstance(getProject())
               .getControlFlow(
                   body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
       if (ControlFlowUtil.findExitPointsAndStatements(
               controlFlow,
               0,
               controlFlow.getSize(),
               new IntArrayList(),
               PsiReturnStatement.class,
               PsiThrowStatement.class)
           .isEmpty()) {
         return false;
       }
     } catch (AnalysisCanceledException e) {
       return true;
     }
   }
   return true;
 }
 private static void checkCodeBlock(
     final PsiCodeBlock body, final Set<PsiField> candidates, Set<PsiField> usedFields) {
   try {
     final ControlFlow controlFlow =
         ControlFlowFactory.getInstance(body.getProject())
             .getControlFlow(body, AllVariablesControlFlowPolicy.getInstance());
     final List<PsiVariable> usedVars =
         ControlFlowUtil.getUsedVariables(controlFlow, 0, controlFlow.getSize());
     for (PsiVariable usedVariable : usedVars) {
       if (usedVariable instanceof PsiField) {
         final PsiField usedField = (PsiField) usedVariable;
         if (!usedFields.add(usedField)) {
           candidates.remove(usedField); // used in more than one code block
         }
       }
     }
     final List<PsiReferenceExpression> readBeforeWrites =
         ControlFlowUtil.getReadBeforeWrite(controlFlow);
     for (final PsiReferenceExpression readBeforeWrite : readBeforeWrites) {
       final PsiElement resolved = readBeforeWrite.resolve();
       if (resolved instanceof PsiField) {
         final PsiField field = (PsiField) resolved;
         PsiElement parent = body.getParent();
         if (!(parent instanceof PsiMethod)
             || !((PsiMethod) parent).isConstructor()
             || field.getInitializer() == null
             || field.hasModifierProperty(PsiModifier.STATIC)) {
           candidates.remove(field);
         }
       }
     }
   } catch (AnalysisCanceledException e) {
     candidates.clear();
   }
 }
 @NotNull
 public static ControlFlow getControlFlowNoConstantEvaluate(@NotNull PsiElement body)
     throws AnalysisCanceledException {
   LocalsOrMyInstanceFieldsControlFlowPolicy policy =
       LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance();
   return ControlFlowFactory.getInstance(body.getProject())
       .getControlFlow(body, policy, false, false);
 }
  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;
 }
 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 | IndexNotReadyException e) {
     // incomplete code
   }
   return null;
 }
  @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);
      }
    }
  }