private boolean _canContainTag(String localName, String namespace, XmlTag tag, XmlElement context, Set<XmlTag> visited,
                                 CurrentContextInfo info, boolean restriction) {
    if (visited.contains(tag)) return false;
    visited.add(tag);

    if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "any")) {
      if (!restriction) {
        myHasAnyInContentModel = true;
      }
      if (OTHER_NAMESPACE_ATTR_VALUE.equals(tag.getAttributeValue("namespace"))) {
        return namespace == null || !namespace.equals(info.expectedDefaultNs);
      }
      return true;
    }
    else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "group")) {
      String ref = tag.getAttributeValue(REF_ATTR_NAME);

      if (ref != null) {
        XmlTag groupTag = info.documentDescriptor.findGroup(ref);
        if (groupTag != null) {
          if (_canContainTag(localName, namespace, groupTag, context, visited, getContextInfo(info, ref), restriction))  return true;
        }
      }
    }
    else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, RESTRICTION_TAG_NAME) ||
             XmlNSDescriptorImpl.equalsToSchemaName(tag, EXTENSION_TAG_NAME)) {
      String base = tag.getAttributeValue(BASE_ATTR_NAME);

      if (base != null) {
        TypeDescriptor descriptor = info.documentDescriptor.findTypeDescriptor(base);

        if (descriptor instanceof ComplexTypeDescriptor complexTypeDescriptor) {
          if (complexTypeDescriptor._canContainTag(localName, namespace, complexTypeDescriptor.myTag, context, visited,
                                                   getContextInfo(info, base), restriction || XmlNSDescriptorImpl.equalsToSchemaName(tag,
                                                                                                                      RESTRICTION_TAG_NAME))) {
            myHasAnyInContentModel |= complexTypeDescriptor.myHasAnyInContentModel;
            return true;
          }
        }
      }
    } else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
      final XmlAttribute ref = tag.getAttribute(REF_ATTR_NAME);
      XmlTag descriptorTag = tag;

      if (ref != null) {
        XmlAttributeValue element = ref.getValueElement();
        final PsiElement psiElement;
        if (element != null) {
          psiElement = SchemaReferencesProvider.createTypeOrElementOrAttributeReference(element).resolve();
          if (psiElement instanceof XmlTag) descriptorTag = (XmlTag)psiElement;
        }
      }

      if (TRUE_ATTR_VALUE.equals(descriptorTag.getAttributeValue("abstract"))) {

        XmlNSDescriptor _nsDescriptor = tag.getNSDescriptor(namespace, true);
        if (_nsDescriptor == null && context instanceof XmlTag) {
          _nsDescriptor = ((XmlTag)context).getNSDescriptor(namespace, true);
        }
        final XmlNSDescriptorImpl nsDescriptor = _nsDescriptor instanceof XmlNSDescriptorImpl ? (XmlNSDescriptorImpl)_nsDescriptor:null;
        final XmlElementDescriptor descriptor = nsDescriptor != null ? nsDescriptor.getElementDescriptor(localName, namespace):null;
        final String name = descriptorTag.getAttributeValue(NAME_ATTR_NAME);

        if (descriptor != null && name != null) {
          final String substitutionValue = ((XmlTag)descriptor.getDeclaration()).getAttributeValue("substitutionGroup");

          if (substitutionValue != null && name.equals(XmlUtil.findLocalNameByQualifiedName(substitutionValue))) {
            return true; // could be more parent-child relation complex!!!
          }
        }
    }
    }

    for (XmlTag subTag : tag.getSubTags()) {
      if (_canContainTag(localName, namespace, subTag, context, visited, info, restriction)) return true;
    }

    return false;
  }
private boolean _canContainTag(String localName, String namespace, XmlTag tag, XmlElement context, Set<XmlTag> visited,
                                 CurrentContextInfo info, boolean restriction)