@Override
  protected boolean doMatchInAnyOrder(@NotNull NodeIterator it1, @NotNull NodeIterator it2) {
    final List<PsiElement> elements1 = new ArrayList<>();
    final List<PsiElement> elements2 = new ArrayList<>();

    while (it1.hasNext()) {
      final PsiElement element = it1.current();
      if (element != null) {
        elements1.add(element);
      }
      it1.advance();
    }

    while (it2.hasNext()) {
      final PsiElement element = it2.current();
      if (element != null) {
        elements2.add(element);
      }
      it2.advance();
    }

    if (elements1.size() != elements2.size()) {
      return false;
    }

    Int2ObjectMap<List<PsiElement>> hashToElement = new Int2ObjectOpenHashMap<>(elements1.size());
    for (PsiElement element : elements1) {
      TreeHashResult result = myTreeHasher.hash(element, null, myNodeSpecificHasher);
      if (result != null) {
        hashToElement.computeIfAbsent(result.getHash(), __ -> new ArrayList<>()).add(element);
      }
    }

    for (PsiElement element : elements2) {
      TreeHashResult result = myTreeHasher.hash(element, null, myNodeSpecificHasher);
      if (result != null) {
        int hash = result.getHash();
        List<PsiElement> list = hashToElement.get(hash);
        if (list == null) {
          return false;
        }

        boolean found = false;
        for (Iterator<PsiElement> it = list.iterator(); it.hasNext();) {
          if (match(element, it.next())) {
            it.remove();
            found = true;
          }
        }

        if (!found) {
          return false;
        }

        if (list.size() == 0) {
          hashToElement.remove(hash);
        }
      }
    }

    return hashToElement.size() == 0;
  }
@Override
  protected boolean doMatchInAnyOrder(@NotNull NodeIterator it1, @NotNull NodeIterator it2)