@Override
  public @Nullable XmlElementDescriptor getElementDescriptor(String localName, String namespace, Set<? super XmlNSDescriptorImpl> visited, boolean reference) {
    if(visited.contains(this)) return null;

    final QNameKey pair = new QNameKey(namespace, localName);
    final CachedValue<XmlElementDescriptor> descriptor = myDescriptorsMap.get(pair);
    if(descriptor != null) {
      final XmlElementDescriptor value = descriptor.getValue();
      if (value == null || value.getDeclaration().isValid()) return value;
    }

    final XmlTag rootTag = myTag;
    if (rootTag == null) return null;
    XmlTag[] tags = rootTag.getSubTags();
    visited.add( this );

    LOG.assertTrue(rootTag.isValid());
    for (final XmlTag tag : tags) {
      if (equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
        String name = tag.getAttributeValue("name");

        if (name != null) {
          if (checkElementNameEquivalence(localName, namespace, name, tag)) {
            final CachedValue<XmlElementDescriptor> cachedValue = CachedValuesManager.getManager(tag.getProject()).createCachedValue(() -> {
              final String name1 = tag.getAttributeValue("name");

              if (name1 != null && !name1.equals(pair.second)) {
                myDescriptorsMap.remove(pair);
                return new CachedValueProvider.Result<>(null, PsiModificationTracker.MODIFICATION_COUNT);
              }
              final XmlElementDescriptor xmlElementDescriptor = createElementDescriptor(tag);
              return new CachedValueProvider.Result<>(xmlElementDescriptor, xmlElementDescriptor.getDependencies());
            }, false);
            myDescriptorsMap.put(pair, cachedValue);
            return cachedValue.getValue();
          }
        }
      }
      else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
               (reference &&
                equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
                ( namespace.equals(tag.getAttributeValue("namespace")) ||
                  namespace.length() == 0 && tag.getAttributeValue("namespace") == null
                )
               )
        ) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");
        if (schemaLocation != null) {
          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation);
          if (xmlFile != null) {
            final XmlDocument includedDocument = xmlFile.getDocument();
            if (includedDocument != null) {
              final PsiMetaData data = includedDocument.getMetaData();
              if (data instanceof XmlNSDescriptorImpl) {
                final XmlElementDescriptor elementDescriptor =
                  ((XmlNSDescriptorImpl)data).getElementDescriptor(localName, namespace, visited, reference);
                if (elementDescriptor != null) {
                  return elementDescriptor;
                }
              }
            }
          }
        }
      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
        if (nsDescriptor != null) {
          final XmlElementDescriptor xmlElementDescriptor = nsDescriptor.getElementDescriptor(localName, namespace, visited, reference);
          if (xmlElementDescriptor instanceof XmlElementDescriptorImpl) {
            return new RedefinedElementDescriptor((XmlElementDescriptorImpl)xmlElementDescriptor, this, nsDescriptor);
          }
        }
      }
    }

    return null;
  }
@Override
  public @Nullable XmlElementDescriptor getElementDescriptor(String localName, String namespace, Set<? super XmlNSDescriptorImpl> visited, boolean reference)