public static List<PsiSwitchLabelStatementBase> createMissingBranches(@NotNull PsiSwitchBlock switchBlock,
                                                                        @NotNull List<String> allNames,
                                                                        @NotNull Collection<String> missingNames,
                                                                        @NotNull Function<? super PsiSwitchLabelStatementBase, ? extends List<String>> caseExtractor) {
    final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(switchBlock.getProject());
    boolean isRuleBasedFormat = SwitchUtils.isRuleFormatSwitch(switchBlock);
    final PsiCodeBlock body = switchBlock.getBody();
    final PsiExpression switchExpression = switchBlock.getExpression();
    PsiClass selectorClass = PsiUtil.resolveClassInClassTypeOnly(switchExpression != null ? switchExpression.getType() : null);
    boolean hasSealedClass = selectorClass != null &&
                             (selectorClass.hasModifierProperty(PsiModifier.SEALED) ||
                              selectorClass.getPermitsList() != null ||
                              (selectorClass instanceof PsiTypeParameter typeParameter &&
                               ContainerUtil.exists(typeParameter.getExtendsListTypes(), extType -> {
                                 PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(extType);
                                 return psiClass != null &&
                                        (psiClass.hasModifierProperty(PsiModifier.SEALED) ||
                                         psiClass.getPermitsList() != null);
                               })));
    boolean isPatternsGenerated = selectorClass != null && !selectorClass.isEnum() && hasSealedClass;
    if (body == null) {
      // replace entire switch statement if no code block is present
      final @NonNls StringBuilder newStatementText = new StringBuilder();
      CommentTracker commentTracker = new CommentTracker();
      newStatementText.append("switch(").append(switchExpression == null ? "" : commentTracker.text(switchExpression)).append("){");
      for (String missingName : missingNames) {
        newStatementText.append(String.join("", generateStatements(missingName, switchBlock, isRuleBasedFormat, isPatternsGenerated)));
      }
      newStatementText.append('}');
      PsiSwitchBlock block = (PsiSwitchBlock)commentTracker.replaceAndRestoreComments(switchBlock, newStatementText.toString());
      javaCodeStyleManager.shortenClassReferences(block);
      return PsiTreeUtil.getChildrenOfTypeAsList(block.getBody(), PsiSwitchLabelStatementBase.class);
    }
    Map<String, String> prevToNext = StreamEx.of(allNames).pairMap(Couple::of).toMap(c -> c.getFirst(), c -> c.getSecond());
    List<String> missingLabels = ContainerUtil.filter(allNames, missingNames::contains);
    String nextLabel = getNextLabel(prevToNext, missingLabels);
    PsiElement bodyElement = body.getFirstBodyElement();
    List<PsiSwitchLabelStatementBase> addedLabels = new ArrayList<>();
    if (bodyElement instanceof PsiWhiteSpace && bodyElement == body.getLastBodyElement()) {
      bodyElement.delete();
      bodyElement = null;
    }
    while (bodyElement != null) {
      PsiSwitchLabelStatementBase label = ObjectUtils.tryCast(bodyElement, PsiSwitchLabelStatementBase.class);
      if (label != null) {
        List<String> caseLabelNames = caseExtractor.apply(label);
        while (nextLabel != null && caseLabelNames.contains(nextLabel)) {
          addedLabels.add(addSwitchLabelStatementBefore(missingLabels.get(0), bodyElement, switchBlock, isRuleBasedFormat, isPatternsGenerated));
          missingLabels = missingLabels.subList(1, missingLabels.size());
          if (missingLabels.isEmpty()) {
            break;
          }
          nextLabel = getNextLabel(prevToNext, missingLabels);
        }
        if (SwitchUtils.isDefaultLabel(label)) {
          for (String missingElement : missingLabels) {
            addedLabels.add(addSwitchLabelStatementBefore(missingElement, bodyElement, switchBlock, isRuleBasedFormat, isPatternsGenerated));
          }
          missingLabels = Collections.emptyList();
          break;
        }
      }
      bodyElement = bodyElement.getNextSibling();
    }
    if (!missingLabels.isEmpty()) {
      final PsiElement lastChild = body.getLastChild();
      for (String missingElement : missingLabels) {
        addedLabels.add(addSwitchLabelStatementBefore(missingElement, lastChild, switchBlock, isRuleBasedFormat, isPatternsGenerated));
      }
    }
    addedLabels.replaceAll(label -> (PsiSwitchLabelStatementBase)javaCodeStyleManager.shortenClassReferences(label));
    return addedLabels;
  }
public static List<PsiSwitchLabelStatementBase> createMissingBranches(@NotNull PsiSwitchBlock switchBlock,
                                                                        @NotNull List<String> allNames,
                                                                        @NotNull Collection<String> missingNames,
                                                                        @NotNull Function<? super PsiSwitchLabelStatementBase, ? extends List<String>> caseExtractor)