@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;
 }
Esempio n. 2
0
 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();
   }
 }
Esempio n. 3
0
 public ControlFlow findControlFlow(Node source, Node destination) {
   for (ControlFlow c : this.getControlFlows()) {
     if (c.getSource().equals(source) && c.getDestination().equals(destination)) {
       return c;
     }
   }
   return null;
 }
  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);
    }
  }
  public PsiStatement getExitStatementCopy(
      PsiElement returnStatement, final PsiElement[] elements) {
    PsiStatement exitStatementCopy = null;
    // replace all exit-statements such as break's or continue's with appropriate return
    for (PsiStatement exitStatement : myExitStatements) {
      if (exitStatement instanceof PsiReturnStatement) {
        if (!myGenerateConditionalExit) continue;
      } else if (exitStatement instanceof PsiBreakStatement) {
        PsiStatement statement = ((PsiBreakStatement) exitStatement).findExitedStatement();
        if (statement == null) continue;
        int startOffset = myControlFlow.getStartOffset(statement);
        int endOffset = myControlFlow.getEndOffset(statement);
        if (myFlowStart <= startOffset && endOffset <= myFlowEnd) continue;
      } else if (exitStatement instanceof PsiContinueStatement) {
        PsiStatement statement = ((PsiContinueStatement) exitStatement).findContinuedStatement();
        if (statement == null) continue;
        int startOffset = myControlFlow.getStartOffset(statement);
        int endOffset = myControlFlow.getEndOffset(statement);
        if (myFlowStart <= startOffset && endOffset <= myFlowEnd) continue;
      } else {
        LOG.error(String.valueOf(exitStatement));
        continue;
      }

      int index = -1;
      for (int j = 0; j < elements.length; j++) {
        if (exitStatement.equals(elements[j])) {
          index = j;
          break;
        }
      }
      if (exitStatementCopy == null) {
        if (needExitStatement(exitStatement)) {
          exitStatementCopy = (PsiStatement) exitStatement.copy();
        }
      }
      PsiElement result = exitStatement.replace(returnStatement);
      if (index >= 0) {
        elements[index] = result;
      }
    }
    return exitStatementCopy;
  }
 @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;
 }
 private boolean needExitStatement(final PsiStatement exitStatement) {
   if (exitStatement instanceof PsiContinueStatement) {
     // IDEADEV-11748
     PsiStatement statement = ((PsiContinueStatement) exitStatement).findContinuedStatement();
     if (statement == null) return true;
     if (statement instanceof PsiLoopStatement)
       statement = ((PsiLoopStatement) statement).getBody();
     int endOffset = myControlFlow.getEndOffset(statement);
     return endOffset > myFlowEnd;
   }
   return true;
 }
 @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 (!BitUtil.isSet(completionReasons, ControlFlowUtil.NORMAL_COMPLETION_REASON)) {
       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 removeParametersUsedInExitsOnly(
     PsiElement codeFragment, List<PsiVariable> inputVariables) {
   LocalSearchScope scope = new LocalSearchScope(codeFragment);
   Variables:
   for (Iterator<PsiVariable> iterator = inputVariables.iterator(); iterator.hasNext(); ) {
     PsiVariable variable = iterator.next();
     for (PsiReference ref : ReferencesSearch.search(variable, scope)) {
       PsiElement element = ref.getElement();
       int elementOffset = myControlFlow.getStartOffset(element);
       if (elementOffset == -1) {
         continue Variables;
       }
       if (elementOffset >= myFlowStart && elementOffset <= myFlowEnd) {
         if (!isInExitStatements(element, myExitStatements)) continue Variables;
       }
     }
     iterator.remove();
   }
 }
  public Collection<PsiStatement> prepareExitStatements(
      final @NotNull PsiElement[] elements, final @NotNull PsiElement enclosingCodeFragment)
      throws ExitStatementsNotSameException {
    myExitPoints = new IntArrayList();
    myExitStatements =
        ControlFlowUtil.findExitPointsAndStatements(
            myControlFlow,
            myFlowStart,
            myFlowEnd,
            myExitPoints,
            ControlFlowUtil.DEFAULT_EXIT_STATEMENTS_CLASSES);
    if (ControlFlowUtil.hasObservableThrowExitPoints(
        myControlFlow, myFlowStart, myFlowEnd, elements, enclosingCodeFragment)) {
      throw new ExitStatementsNotSameException();
    }
    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;
  }
Esempio n. 11
0
 /**
  * Can emulate the execution flow of multiple threads in a deterministic way so it is easy to
  * emulate race conditions or deadlocks just with the use of additional log messages inserted into
  * the code.
  *
  * <p>The best example showing usage of this method is real life test. Read <a
  * href="http://hg.netbeans.org/main/raw-file/tip/nbjunit/test/unit/src/org/netbeans/junit/FlowControlTest.java">FlowControlTest.java</a>
  * to know everything about the expected usage of this method.
  *
  * <p>The method does listen on output send to a logger <code>listenTo</code> by various threads
  * and either suspends them or wake them up trying as best as it can to mimic the log output
  * described in <code>order</code>. Of course, this may not always be possible, so there is the
  * <code>timeout</code> value which specifies the maximum time a thread can be suspended while
  * waiting for a single message. The information about the internal behaviour of the controlFlow
  * method can be send to <code>reportTo</code> logger, if provided, so in case of failure one can
  * analyse what went wrong.
  *
  * <p>The format of the order is a set of lines like:
  *
  * <pre>
  * THREAD:name_of_the_thread MSG:message_to_expect
  * </pre>
  *
  * which define the order saying that at this time a thread with a given name is expected to send
  * given message. Both the name of the thread and the message are regular expressions so one can
  * shorten them by using <q>.*</q> or any other trick. Btw. the format of the <code>order</code>
  * is similar to the one logged by the {@link Log#enable} or {@link NbTestCase#logLevel} methods,
  * so when one gets a test failure with enabled logging, it is enough to just delete the
  * unnecessary messages, replace too specific texts like <code>@574904</code> with <code>.*</code>
  * and the order is ready for use.
  *
  * @param listenTo the logger to listen to and guide the execution according to messages sent to
  *     it
  * @param reportTo the logger to report internal state to or <code>null</code> if the logging is
  *     not needed
  * @param order the string describing the expected execution order of threads
  * @param timeout the maximal wait time of each thread on given message, zero if the waiting shall
  *     be infinite
  * @author Jaroslav Tulach, invented during year 2005
  * @since 1.28
  */
 public static void controlFlow(Logger listenTo, Logger reportTo, String order, int timeout) {
   ControlFlow.registerSwitches(listenTo, reportTo, order, timeout);
 }
  public final RunnerResult analyzeMethod(
      @NotNull PsiElement psiBlock,
      InstructionVisitor visitor,
      boolean ignoreAssertions,
      @NotNull Collection<DfaMemoryState> initialStates) {
    try {
      prepareAnalysis(psiBlock, initialStates);

      final ControlFlow flow =
          createControlFlowAnalyzer().buildControlFlow(psiBlock, ignoreAssertions);
      if (flow == null) return RunnerResult.NOT_APPLICABLE;

      int endOffset = flow.getInstructionCount();
      myInstructions = flow.getInstructions();
      myFields = flow.getFields();
      myNestedClosures.clear();

      if (LOG.isDebugEnabled()) {
        LOG.debug("Analyzing code block: " + psiBlock.getText());
        for (int i = 0; i < myInstructions.length; i++) {
          Instruction instruction = myInstructions[i];
          LOG.debug(i + ": " + instruction.toString());
        }
      }

      Integer tooExpensiveHash = psiBlock.getUserData(TOO_EXPENSIVE_HASH);
      if (tooExpensiveHash != null && tooExpensiveHash == psiBlock.getText().hashCode()) {
        LOG.debug("Too complex because hasn't changed since being too complex already");
        return RunnerResult.TOO_COMPLEX;
      }

      final ArrayList<DfaInstructionState> queue = new ArrayList<DfaInstructionState>();
      for (final DfaMemoryState initialState : initialStates) {
        queue.add(new DfaInstructionState(myInstructions[0], initialState));
      }

      long timeLimit = ourTimeLimit;
      final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();
      WorkingTimeMeasurer measurer = new WorkingTimeMeasurer(timeLimit);
      int count = 0;
      while (!queue.isEmpty()) {
        if (count % 50 == 0 && !unitTestMode && measurer.isTimeOver()) {
          LOG.debug("Too complex because the analysis took too long");
          psiBlock.putUserData(TOO_EXPENSIVE_HASH, psiBlock.getText().hashCode());
          return RunnerResult.TOO_COMPLEX;
        }
        ProgressManager.checkCanceled();

        DfaInstructionState instructionState = queue.remove(0);
        if (LOG.isDebugEnabled()) {
          LOG.debug(instructionState.toString());
        }
        // System.out.println(instructionState.toString());

        Instruction instruction = instructionState.getInstruction();
        long distance = instructionState.getDistanceFromStart();

        if (instruction instanceof BranchingInstruction) {
          if (!instruction.setMemoryStateProcessed(
              instructionState.getMemoryState().createCopy())) {
            LOG.debug("Too complex because too many different possible states");
            return RunnerResult.TOO_COMPLEX; // Too complex :(
          }
        }

        DfaInstructionState[] after = acceptInstruction(visitor, instructionState);
        for (DfaInstructionState state : after) {
          Instruction nextInstruction = state.getInstruction();
          if ((!(nextInstruction instanceof BranchingInstruction)
                  || !nextInstruction.isMemoryStateProcessed(state.getMemoryState()))
              && instruction.getIndex() < endOffset) {
            state.setDistanceFromStart(distance + 1);
            queue.add(state);
          }
        }

        count++;
      }

      psiBlock.putUserData(TOO_EXPENSIVE_HASH, null);
      LOG.debug("Analysis ok");
      return RunnerResult.OK;
    } catch (ArrayIndexOutOfBoundsException e) {
      LOG.error(psiBlock.getText(), e); // TODO fix in better times
      return RunnerResult.ABORTED;
    } catch (EmptyStackException e) {
      if (LOG.isDebugEnabled()) {
        LOG.error(e); // TODO fix in better times
      }
      return RunnerResult.ABORTED;
    }
  }
 public Collection<ControlFlowUtil.VariableInfo> getInitializedTwice(int start) {
   return ControlFlowUtil.getInitializedTwice(myControlFlow, start, myControlFlow.getSize());
 }
 public List<PsiVariable> getUsedVariables(int start) {
   return getUsedVariables(start, myControlFlow.getSize());
 }
  @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);
      }
    }
  }
  @NotNull
  final RunnerResult analyzeMethod(
      @NotNull PsiElement psiBlock,
      @NotNull InstructionVisitor visitor,
      boolean ignoreAssertions,
      @NotNull Collection<DfaMemoryState> initialStates) {
    if (PsiTreeUtil.findChildOfType(psiBlock, OuterLanguageElement.class) != null)
      return RunnerResult.NOT_APPLICABLE;

    try {
      final ControlFlow flow =
          new ControlFlowAnalyzer(myValueFactory, psiBlock, ignoreAssertions).buildControlFlow();
      if (flow == null) return RunnerResult.NOT_APPLICABLE;
      int[] loopNumber = LoopAnalyzer.calcInLoop(flow);

      int endOffset = flow.getInstructionCount();
      myInstructions = flow.getInstructions();
      myNestedClosures.clear();

      Set<Instruction> joinInstructions = ContainerUtil.newHashSet();
      for (int index = 0; index < myInstructions.length; index++) {
        Instruction instruction = myInstructions[index];
        if (instruction instanceof GotoInstruction) {
          joinInstructions.add(myInstructions[((GotoInstruction) instruction).getOffset()]);
        } else if (instruction instanceof ConditionalGotoInstruction) {
          joinInstructions.add(
              myInstructions[((ConditionalGotoInstruction) instruction).getOffset()]);
        } else if (instruction instanceof MethodCallInstruction
            && !((MethodCallInstruction) instruction).getContracts().isEmpty()) {
          joinInstructions.add(myInstructions[index + 1]);
        }
      }

      if (LOG.isDebugEnabled()) {
        LOG.debug("Analyzing code block: " + psiBlock.getText());
        for (int i = 0; i < myInstructions.length; i++) {
          LOG.debug(i + ": " + myInstructions[i]);
        }
      }
      // for (int i = 0; i < myInstructions.length; i++) System.out.println(i + ": " +
      // myInstructions[i].toString());

      Integer tooExpensiveHash = psiBlock.getUserData(TOO_EXPENSIVE_HASH);
      if (tooExpensiveHash != null && tooExpensiveHash == psiBlock.getText().hashCode()) {
        LOG.debug("Too complex because hasn't changed since being too complex already");
        return RunnerResult.TOO_COMPLEX;
      }

      final StateQueue queue = new StateQueue();
      for (final DfaMemoryState initialState : initialStates) {
        queue.offer(new DfaInstructionState(myInstructions[0], initialState));
      }

      MultiMap<BranchingInstruction, DfaMemoryState> processedStates = MultiMap.createSet();
      MultiMap<BranchingInstruction, DfaMemoryState> incomingStates = MultiMap.createSet();

      long msLimit =
          shouldCheckTimeLimit()
              ? Registry.intValue("ide.dfa.time.limit.online")
              : Registry.intValue("ide.dfa.time.limit.offline");
      WorkingTimeMeasurer measurer = new WorkingTimeMeasurer(msLimit * 1000 * 1000);
      int count = 0;
      while (!queue.isEmpty()) {
        List<DfaInstructionState> states = queue.getNextInstructionStates(joinInstructions);
        for (DfaInstructionState instructionState : states) {
          if (count++ % 1024 == 0 && measurer.isTimeOver()) {
            LOG.debug("Too complex because the analysis took too long");
            psiBlock.putUserData(TOO_EXPENSIVE_HASH, psiBlock.getText().hashCode());
            return RunnerResult.TOO_COMPLEX;
          }
          ProgressManager.checkCanceled();

          if (LOG.isDebugEnabled()) {
            LOG.debug(instructionState.toString());
          }
          // System.out.println(instructionState.toString());

          Instruction instruction = instructionState.getInstruction();

          if (instruction instanceof BranchingInstruction) {
            BranchingInstruction branching = (BranchingInstruction) instruction;
            Collection<DfaMemoryState> processed = processedStates.get(branching);
            if (processed.contains(instructionState.getMemoryState())) {
              continue;
            }
            if (processed.size() > MAX_STATES_PER_BRANCH) {
              LOG.debug("Too complex because too many different possible states");
              return RunnerResult.TOO_COMPLEX; // Too complex :(
            }
            if (loopNumber[branching.getIndex()] != 0) {
              processedStates.putValue(branching, instructionState.getMemoryState().createCopy());
            }
          }

          DfaInstructionState[] after = acceptInstruction(visitor, instructionState);
          for (DfaInstructionState state : after) {
            Instruction nextInstruction = state.getInstruction();
            if (nextInstruction.getIndex() >= endOffset) {
              continue;
            }
            handleStepOutOfLoop(
                instruction,
                nextInstruction,
                loopNumber,
                processedStates,
                incomingStates,
                states,
                after,
                queue);
            if (nextInstruction instanceof BranchingInstruction) {
              BranchingInstruction branching = (BranchingInstruction) nextInstruction;
              if (processedStates.get(branching).contains(state.getMemoryState())
                  || incomingStates.get(branching).contains(state.getMemoryState())) {
                continue;
              }
              if (loopNumber[branching.getIndex()] != 0) {
                incomingStates.putValue(branching, state.getMemoryState().createCopy());
              }
            }
            queue.offer(state);
          }
        }
      }

      psiBlock.putUserData(TOO_EXPENSIVE_HASH, null);
      LOG.debug("Analysis ok");
      return RunnerResult.OK;
    } catch (ArrayIndexOutOfBoundsException e) {
      LOG.error(psiBlock.getText(), e);
      return RunnerResult.ABORTED;
    } catch (EmptyStackException e) {
      LOG.error(psiBlock.getText(), e);
      return RunnerResult.ABORTED;
    }
  }