private static List<XmlElementDescriptor> computeRequiredSubTags(XmlElementsGroup group) {

    if (group.getMinOccurs() < 1) return Collections.emptyList();
    switch (group.getGroupType()) {
      case LEAF -> {
        XmlElementDescriptor descriptor = group.getLeafDescriptor();
        
        if (descriptor == null) return Collections.emptyList();
        
        PsiElement declaration = descriptor.getDeclaration();
        // don't add abstract elements to required sub tags list
        if (declaration instanceof XmlTag) {
          XmlTag tag = (XmlTag)descriptor.getDeclaration();
          String abstractValue = tag.getAttributeValue("abstract", XMLConstants.W3C_XML_SCHEMA_NS_URI);
          if ("true".equals(abstractValue)) {
            return Collections.emptyList();
          }
        }
        
        return Collections.singletonList(descriptor);
      }
      case CHOICE -> {
        LinkedHashSet<XmlElementDescriptor> set = null;
        for (XmlElementsGroup subGroup : group.getSubGroups()) {
          List<XmlElementDescriptor> descriptors = computeRequiredSubTags(subGroup);
          if (set == null) {
            set = new LinkedHashSet<>(descriptors);
          }
          else {
            set.retainAll(descriptors);
          }
        }
        if (set == null || set.isEmpty()) {
          return Collections.singletonList(null); // placeholder for smart completion
        }
        return new ArrayList<>(set);
      }
      default -> {
        ArrayList<XmlElementDescriptor> list = new ArrayList<>();
        for (XmlElementsGroup subGroup : group.getSubGroups()) {
          list.addAll(computeRequiredSubTags(subGroup));
        }
        return list;
      }
    }
  }
private static List<XmlElementDescriptor> computeRequiredSubTags(XmlElementsGroup group)