public @Nullable SwitchOnReferenceCandidate findCandidate() {
      Exprent instance = mySwitchSelector.getInstance();
      if (instance == null) {
        return null;
      }
      if (myRootSwitchStatement.getHeadExprent() == null) {
        return null;
      }

      if (myRootSwitchStatement.getCaseValues().size() != myRootSwitchStatement.getCaseEdges().size() ||
          myRootSwitchStatement.getCaseValues().size() != myRootSwitchStatement.getCaseStatements().size()) {
        return null;
      }

      if (!(instance instanceof VarExprent instanceVarExprent)) return null;
      if (!isBootstrapSwitch(myRootSwitchStatement.getHeadExprent())) return null;
      if (checkBootstrap()) return null;

      List<Exprent> parameters = mySwitchSelector.getParameters();
      if (!instance.equals(parameters.get(0))) {
        return null;
      }
      Exprent typeVar = parameters.get(1);
      Root root = getRoot();
      if (root == null) return null;

      if (root.firstExprents() == null) {
        return null;
      }

      if (myVarTracker != null) {
        processAtLeastOneBlock(myVarTracker, root.firstStatement());
      }

      Initializer initializer = findInitializer(root, typeVar);

      if (initializer.initVar2() == null) {
        return null;
      }

      Set<AssignmentExprent> usedTypeVarAssignments = new HashSet<>();
      usedTypeVarAssignments.add(initializer.initVar2());
      myTypeVars.add(typeVar);

      Map<Statement, List<PatternVariableCandidate>> candidates =
        collectPatterns(instanceVarExprent, root.doParentStatement(), usedTypeVarAssignments);
      if (candidates == null) {
        return null;
      }
      candidates.values()
        .stream()
        .flatMap(t -> t.stream())
        .forEach(candidate -> myTempVarAssignments.addAll(candidate.getTempAssignments()));
      PatternContainer patternContainer = collectGuards(candidates, typeVar, root.doParentStatement(), usedTypeVarAssignments);
      if (root.doParentStatement() != null) {
        if (checkReinitVar(typeVar, root.doParentStatement(), usedTypeVarAssignments)) {
          return null;
        }
      }
      else {
        if (checkReinitVar(typeVar, myRootSwitchStatement, usedTypeVarAssignments)) {
          return null;
        }
      }


      List<FullCase> resortedCases = resortForSwitchBootstrap(myRootSwitchStatement);
      if (resortedCases == null) {
        return null;
      }

      List<Exprent> finalFirstExprents = root.firstExprents();
      Exprent finalNonNullCheck = initializer.nonNullCheck();

      return new SwitchOnReferenceCandidate(myRootSwitchStatement, mySwitchSelector, initializer.instance(), resortedCases,
                                            patternContainer,
                                            myTempVarAssignments, myUsedSwitch,
                                            usedTypeVarAssignments, root.doParentStatement(),
                                            initializer.nonNullCheck() != null, () -> {
        if (finalNonNullCheck != null) {
          finalFirstExprents.remove(finalNonNullCheck);
        }
      });
    }
public @Nullable SwitchOnReferenceCandidate findCandidate()