boolean (@Nullable PsiElement patternElement, PsiElement matchElement, SubstitutionHandler handler) { boolean includeInterfaces = true; boolean includeClasses = true; if (patternElement != null) { patternElement = StructuralSearchUtil.getParentIfIdentifier(patternElement); final PsiElement patternParent = patternElement.getParent(); if (patternParent instanceof PsiReferenceList && patternParent.getParent() instanceof PsiClass psiClass) { if (patternParent == psiClass.getExtendsList()) { includeInterfaces = psiClass.isInterface(); } else if (patternParent == psiClass.getImplementsList()) { includeClasses = false; } } } final NodeIterator nodes = new HierarchyNodeIterator(matchElement, includeClasses, includeInterfaces); if (!includeClasses) { nodes.advance(); } if (handler.isStrictSubtype()) { nodes.advance(); } final boolean negated = handler.getPredicate() instanceof NotPredicate; while (nodes.hasNext() && negated == handler.validate(nodes.current(), myMatchingVisitor.getMatchContext())) { nodes.advance(); } return negated != nodes.hasNext(); }