public static boolean match(@NotNull EquivalenceDescriptor descriptor1,
                              @NotNull EquivalenceDescriptor descriptor2,
                              @NotNull AbstractMatchingVisitor g,
                              @NotNull Set<PsiElementRole> skippedRoles,
                              @Nullable DuplicatesProfile profile) {

    if (descriptor1.getSingleChildDescriptors().size() != descriptor2.getSingleChildDescriptors().size()) {
      return false;
    }

    if (descriptor1.getMultiChildDescriptors().size() != descriptor2.getMultiChildDescriptors().size()) {
      return false;
    }

    if (descriptor1.getCodeBlocks().size() != descriptor2.getCodeBlocks().size()) {
      return false;
    }

    if (descriptor1.getConstants().size() != descriptor2.getConstants().size()) {
      return false;
    }

    for (int i = 0, n = descriptor1.getConstants().size(); i < n; i++) {
      Object childDescriptor1 = descriptor1.getConstants().get(i);
      Object childDescriptor2 = descriptor2.getConstants().get(i);

      if (!Comparing.equal(childDescriptor1, childDescriptor2)) {
        return false;
      }
    }

    for (int i = 0, n = descriptor1.getSingleChildDescriptors().size(); i < n; i++) {
      SingleChildDescriptor childDescriptor1 = descriptor1.getSingleChildDescriptors().get(i);
      SingleChildDescriptor childDescriptor2 = descriptor2.getSingleChildDescriptors().get(i);

      if (!match(childDescriptor1, childDescriptor2, g, skippedRoles, profile)) {
        return false;
      }
    }

    for (int i = 0, n = descriptor1.getMultiChildDescriptors().size(); i < n; i++) {
      MultiChildDescriptor childDescriptor1 = descriptor1.getMultiChildDescriptors().get(i);
      MultiChildDescriptor childDescriptor2 = descriptor2.getMultiChildDescriptors().get(i);

      if (!match(childDescriptor1, childDescriptor2, g)) {
        return false;
      }
    }

    for (int i = 0, n = descriptor1.getCodeBlocks().size(); i < n; i++) {
      final PsiElement[] codeBlock1 = descriptor1.getCodeBlocks().get(i);
      final PsiElement[] codeBlock2 = descriptor2.getCodeBlocks().get(i);

      if (!g.matchSequentially(codeBlock1, codeBlock2)) {
        return false;
      }
    }

    return true;
  }
public static boolean match(@NotNull EquivalenceDescriptor descriptor1,
                              @NotNull EquivalenceDescriptor descriptor2,
                              @NotNull AbstractMatchingVisitor g,
                              @NotNull Set<PsiElementRole> skippedRoles,
                              @Nullable DuplicatesProfile profile)