@Nullable
    private Map<Statement, List<PatternVariableCandidate>> collectPatterns(@NotNull VarExprent instance,
                                                                           @Nullable DoStatement doStatement,
                                                                           @NotNull Set<AssignmentExprent> assignmentExprents) {

      Map<Statement, List<PatternVariableCandidate>> candidates = new HashMap<>();
      List<PooledConstant> bootstrapArguments = mySwitchSelector.getBootstrapArguments();
      Map<Integer, String> mapCaseClasses = getMapCaseClasses(bootstrapArguments);
      @NotNull List<List<@Nullable Exprent>> values = myRootSwitchStatement.getCaseValues();
      for (int caseIndex = 0; caseIndex < values.size(); caseIndex++) {
        List<Exprent> caseValues = values.get(caseIndex);
        for (int valueIndex = 0; valueIndex < caseValues.size(); valueIndex++) {
          Exprent caseValue = caseValues.get(valueIndex);
          if (!(caseValue instanceof ConstExprent constCaseValue)) {
            continue;
          }
          int expectedValue = constCaseValue.getIntValue();
          String className = mapCaseClasses.get(expectedValue);
          //if it doesn't have className, it is not a pattern (enum or literal), and can be processed during transformation
          if (className == null) {
            continue;
          }

          Statement caseStatement = myRootSwitchStatement.getCaseStatements().get(caseIndex);

          VarTracker currentVarTracker = myVarTracker;
          if (currentVarTracker == null) {
            RecordVarExprent recordVarExprent = new RecordVarExprent(instance);
            currentVarTracker = new VarTracker(recordVarExprent);
            currentVarTracker.put(instance, recordVarExprent, myRootSwitchStatement);
          }

          ConstExprent checkType = new ConstExprent(new VarType(className), null, null);
          currentVarTracker = currentVarTracker.copy();
          if (currentVarTracker == null) {
            continue;
          }

          PatternVariableCandidate candidate = null;

          //example:
          // some blocks
          // var2 = 2 // here var2 is second initializer
          // break
          //'break' breaks graph for inner statements, that's why it is needed to be excluded temporary
          if (caseStatement instanceof SequenceStatement sequenceStatement && !sequenceStatement.getStats().isEmpty()) {
            VBStyleCollection<Statement, Integer> sequenceStatementStats = sequenceStatement.getStats();
            Statement last = sequenceStatementStats.get(sequenceStatementStats.size() - 1);
            if (last instanceof BasicBlockStatement && last.getExprents() != null && last.getExprents().size() == 1) {
              Exprent exprent = last.getExprents().get(0);
              if (exprent instanceof AssignmentExprent assignmentExprent &&
                  assignmentExprent.getLeft() instanceof VarExprent left && myTypeVars.contains(left)) {
                //new sequence without break
                SequenceStatement newSequence = new SequenceStatement(sequenceStatementStats.subList(0, sequenceStatementStats.size() - 1));
                Map<Statement, Statement> previousParents = new HashMap<>();
                for (Statement currentStat : newSequence.getStats()) {
                  previousParents.put(currentStat, currentStat.getParent());
                  currentStat.setParent(newSequence);
                }
                newSequence.setParent(sequenceStatement.getParent());
                candidate = findNextPatternVarCandidate(newSequence, instance, checkType, currentVarTracker, newSequence);
                //'last' is not added here, because it must be processed in guards

                //return 'break' back
                for (Statement currentStat : newSequence.getStats()) {
                  Statement currentParent = previousParents.get(currentStat);
                  if (currentParent != null) {
                    currentStat.setParent(currentParent);
                  }
                }

                //candidate.nextStatement has broken edge here, it refers to 'last' (break)
                //it is expected if it has a guard
                if (candidate != null) {
                  candidate =
                    normalizeCandidateWithBrokenEdges(candidate, newSequence, sequenceStatement, last, doStatement, assignmentExprents,
                                                      assignmentExprent);
                  //it is impossible to normalize
                  if (candidate == null) {
                    return null;
                  }
                }
              }
            }
          }

          if (candidate == null) {
            candidate = findNextPatternVarCandidate(caseStatement, instance, checkType, currentVarTracker, caseStatement);
          }

          if (candidate != null) {
            List<PatternVariableCandidate> nestedSwitches =
              tryToFindNestedSwitch(candidate, caseStatement, assignmentExprents, currentVarTracker);
            if (nestedSwitches == null || nestedSwitches.isEmpty()) {
              //something broken
              return null;
            }
            candidates.put(caseStatement, nestedSwitches);
          }
          //there are no patterns for JAVA_LANG_OBJECT, add them as is
          else if (JAVA_LANG_OBJECT.equals(className)) {
            List<PatternVariableCandidate> value = new ArrayList<>();
            value.add(
              new PatternVariableCandidate(createDefaultPatternVal(className), caseStatement, new HashSet<>(), new ArrayList<>(), () -> {
              }));
            candidates.put(caseStatement, value);
          }
        }
        //collect from default case
        if (myRootSwitchStatement.getCaseEdges().get(caseIndex).contains(myRootSwitchStatement.getDefaultEdge())) {
          Statement defaultStatement = myRootSwitchStatement.getCaseStatements().get(caseIndex);
          if (defaultStatement instanceof BasicBlockStatement && defaultStatement.getExprents() != null &&
              defaultStatement.getExprents().size() == 1 &&
              defaultStatement.getExprents().get(0) instanceof AssignmentExprent assignmentExprent &&
              myTypeVars.contains(assignmentExprent.getLeft())) {
            assignmentExprents.add(assignmentExprent);
          }
        }
      }
      return candidates;
    }
@Nullable
    private Map<Statement, List<PatternVariableCandidate>> collectPatterns(@NotNull VarExprent instance,
                                                                           @Nullable DoStatement doStatement,
                                                                           @NotNull Set<AssignmentExprent> assignmentExprents)