Search in sources :

Example 1 with HierarchyNodeIterator

use of com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator in project intellij-community by JetBrains.

the class JavaMatchingVisitor method compareClasses.

private boolean compareClasses(final PsiClass clazz, final PsiClass clazz2) {
    final PsiClass saveClazz = this.myClazz;
    final MatchContext.MatchedElementsListener oldListener = myMatchingVisitor.getMatchContext().getMatchedElementsListener();
    this.myClazz = clazz2;
    final CompiledPattern pattern = myMatchingVisitor.getMatchContext().getPattern();
    assert pattern instanceof JavaCompiledPattern;
    final JavaCompiledPattern javaPattern = (JavaCompiledPattern) pattern;
    MatchContext.MatchedElementsListener listener = new MatchContext.MatchedElementsListener() {

        private Set<PsiElement> myMatchedElements;

        @Override
        public void matchedElements(Collection<PsiElement> matchedElements) {
            if (matchedElements == null)
                return;
            if (myMatchedElements == null) {
                myMatchedElements = new HashSet<>(matchedElements);
            } else {
                myMatchedElements.addAll(matchedElements);
            }
        }

        @Override
        public void commitUnmatched() {
            final List<PsiMember> members = PsiTreeUtil.getChildrenOfTypeAsList(clazz2, PsiMember.class);
            final List<PsiMember> unmatchedElements = ContainerUtil.filter(members, a -> myMatchedElements == null || !myMatchedElements.contains(a));
            MatchingHandler unmatchedSubstitutionHandler = null;
            for (PsiElement element = clazz.getFirstChild(); element != null; element = element.getNextSibling()) {
                if (element instanceof PsiTypeElement && element.getNextSibling() instanceof PsiErrorElement) {
                    unmatchedSubstitutionHandler = pattern.getHandler(element);
                    break;
                }
            }
            if (unmatchedSubstitutionHandler instanceof SubstitutionHandler) {
                final SubstitutionHandler handler = (SubstitutionHandler) unmatchedSubstitutionHandler;
                for (PsiMember element : unmatchedElements) {
                    handler.handle(element, myMatchingVisitor.getMatchContext());
                }
            } else {
                clazz2.putUserData(GlobalMatchingVisitor.UNMATCHED_ELEMENTS_KEY, unmatchedElements);
            }
        }
    };
    myMatchingVisitor.getMatchContext().setMatchedElementsListener(listener);
    boolean result = false;
    try {
        final boolean templateIsInterface = clazz.isInterface();
        if (templateIsInterface != clazz2.isInterface())
            return false;
        if (templateIsInterface && clazz.isAnnotationType() && !clazz2.isAnnotationType())
            return false;
        if (clazz.isEnum() && !clazz2.isEnum())
            return false;
        if (!matchInAnyOrder(clazz.getExtendsList(), clazz2.getExtendsList())) {
            return false;
        }
        // check if implements is in extended classes implements
        final PsiReferenceList implementsList = clazz.getImplementsList();
        if (implementsList != null) {
            if (!matchInAnyOrder(implementsList, clazz2.getImplementsList())) {
                final PsiReferenceList anotherExtendsList = clazz2.getExtendsList();
                final PsiJavaCodeReferenceElement[] referenceElements = implementsList.getReferenceElements();
                boolean accepted = false;
                if (referenceElements.length > 0 && anotherExtendsList != null) {
                    final HierarchyNodeIterator iterator = new HierarchyNodeIterator(clazz2, true, true, false);
                    accepted = myMatchingVisitor.matchInAnyOrder(new ArrayBackedNodeIterator(referenceElements), iterator);
                }
                if (!accepted)
                    return false;
            }
        }
        final PsiField[] fields = clazz.getFields();
        if (fields.length > 0) {
            final PsiField[] fields2 = javaPattern.isRequestsSuperFields() ? clazz2.getAllFields() : clazz2.getFields();
            if (!myMatchingVisitor.matchInAnyOrder(fields, fields2)) {
                return false;
            }
        }
        final PsiMethod[] methods = clazz.getMethods();
        if (methods.length > 0) {
            final PsiMethod[] methods2 = javaPattern.isRequestsSuperMethods() ? clazz2.getAllMethods() : clazz2.getMethods();
            if (!myMatchingVisitor.matchInAnyOrder(methods, methods2)) {
                return false;
            }
        }
        final PsiClass[] nestedClasses = clazz.getInnerClasses();
        if (nestedClasses.length > 0) {
            final PsiClass[] nestedClasses2 = javaPattern.isRequestsSuperInners() ? clazz2.getAllInnerClasses() : clazz2.getInnerClasses();
            if (!myMatchingVisitor.matchInAnyOrder(nestedClasses, nestedClasses2)) {
                return false;
            }
        }
        final PsiClassInitializer[] initializers = clazz.getInitializers();
        if (initializers.length > 0) {
            final PsiClassInitializer[] initializers2 = clazz2.getInitializers();
            if (!myMatchingVisitor.matchInAnyOrder(initializers, initializers2)) {
                return false;
            }
        }
        result = true;
        return true;
    } finally {
        if (result)
            listener.commitUnmatched();
        this.myClazz = saveClazz;
        myMatchingVisitor.getMatchContext().setMatchedElementsListener(oldListener);
    }
}
Also used : MatchingHandler(com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler) HierarchyNodeIterator(com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator) SubstitutionHandler(com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler) ArrayBackedNodeIterator(com.intellij.dupLocator.iterators.ArrayBackedNodeIterator)

Example 2 with HierarchyNodeIterator

use of com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator in project intellij-community by JetBrains.

the class JavaMatchingVisitor method checkMatchWithinHierarchy.

private boolean checkMatchWithinHierarchy(PsiElement el2, SubstitutionHandler handler, PsiElement context) {
    boolean includeInterfaces = true;
    boolean includeClasses = true;
    final PsiElement contextParent = context.getParent();
    if (contextParent instanceof PsiReferenceList) {
        final PsiElement grandParentContext = contextParent.getParent();
        if (grandParentContext instanceof PsiClass) {
            final PsiClass psiClass = (PsiClass) grandParentContext;
            if (contextParent == psiClass.getExtendsList()) {
                includeInterfaces = psiClass.isInterface();
            } else if (contextParent == psiClass.getImplementsList()) {
                includeClasses = false;
            }
        }
    }
    // is type2 is (strict) subtype of type
    final NodeIterator node = new HierarchyNodeIterator(el2, includeClasses, includeInterfaces);
    if (handler.isStrictSubtype()) {
        node.advance();
    }
    final boolean notPredicate = handler.getPredicate() instanceof NotPredicate;
    while (node.hasNext() && !handler.validate(node.current(), 0, -1, myMatchingVisitor.getMatchContext())) {
        if (notPredicate)
            return false;
        node.advance();
    }
    if (node.hasNext()) {
        handler.addResult(el2, 0, -1, myMatchingVisitor.getMatchContext());
        return true;
    } else {
        return false;
    }
}
Also used : NodeIterator(com.intellij.dupLocator.iterators.NodeIterator) ArrayBackedNodeIterator(com.intellij.dupLocator.iterators.ArrayBackedNodeIterator) HierarchyNodeIterator(com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator) HierarchyNodeIterator(com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator) NotPredicate(com.intellij.structuralsearch.impl.matcher.predicates.NotPredicate)

Aggregations

ArrayBackedNodeIterator (com.intellij.dupLocator.iterators.ArrayBackedNodeIterator)2 HierarchyNodeIterator (com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator)2 NodeIterator (com.intellij.dupLocator.iterators.NodeIterator)1 MatchingHandler (com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler)1 SubstitutionHandler (com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler)1 NotPredicate (com.intellij.structuralsearch.impl.matcher.predicates.NotPredicate)1