Search in sources :

Example 1 with ArrayBackedNodeIterator

use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator in project intellij-community by JetBrains.

the class DeclarationStatementHandler method match.

@Override
public boolean match(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
    if (patternNode instanceof PsiComment) {
        return myCommentHandler.match(patternNode, matchedNode, context);
    }
    if (!super.match(patternNode, matchedNode, context))
        return false;
    final PsiDeclarationStatement dcl = (PsiDeclarationStatement) patternNode;
    if (matchedNode instanceof PsiDeclarationStatement) {
        return context.getMatcher().matchSequentially(new SsrFilteringNodeIterator(patternNode.getFirstChild()), new SsrFilteringNodeIterator(matchedNode.getFirstChild()));
    }
    final PsiElement[] declared = dcl.getDeclaredElements();
    // declaration statement could wrap class or dcl
    if (declared.length > 0 && !(matchedNode.getParent() instanceof PsiDeclarationStatement)) /* skip twice matching for child*/
    {
        if (!(matchedNode instanceof PsiField)) {
            return context.getMatcher().matchSequentially(new ArrayBackedNodeIterator(declared), new CountingNodeIterator(declared.length, new SsrFilteringNodeIterator(matchedNode)));
        }
        // special handling for multiple fields in single declaration
        final PsiElement sibling = PsiTreeUtil.skipSiblingsBackward(matchedNode, PsiWhiteSpace.class);
        if (PsiUtil.isJavaToken(sibling, JavaTokenType.COMMA)) {
            return false;
        }
        final List<PsiElement> matchNodes = new ArrayList<>();
        matchNodes.add(matchedNode);
        PsiElement node = matchedNode;
        node = PsiTreeUtil.skipSiblingsForward(node, PsiWhiteSpace.class);
        while (PsiUtil.isJavaToken(node, JavaTokenType.COMMA)) {
            node = PsiTreeUtil.skipSiblingsForward(node, PsiWhiteSpace.class);
            if (node instanceof PsiField) {
                matchNodes.add(node);
            }
            node = PsiTreeUtil.skipSiblingsForward(node, PsiWhiteSpace.class);
        }
        boolean result = context.getMatcher().matchSequentially(new ArrayBackedNodeIterator(declared), new ArrayBackedNodeIterator(matchNodes.toArray(new PsiElement[matchNodes.size()])));
        if (result && declared[0] instanceof PsiVariable) {
            // we may have comments behind to match!
            final PsiElement lastChild = dcl.getLastChild();
            if (lastChild instanceof PsiComment) {
                final PsiElement[] fieldChildren = matchedNode.getChildren();
                result = context.getPattern().getHandler(lastChild).match(lastChild, fieldChildren[fieldChildren.length - 1], context);
            }
        }
        return result;
    }
    return false;
}
Also used : ArrayList(java.util.ArrayList) CountingNodeIterator(com.intellij.dupLocator.iterators.CountingNodeIterator) SsrFilteringNodeIterator(com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator) ArrayBackedNodeIterator(com.intellij.dupLocator.iterators.ArrayBackedNodeIterator)

Example 2 with ArrayBackedNodeIterator

use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator in project intellij-community by JetBrains.

the class CompiledPattern method setNodes.

public void setNodes(List<PsiElement> elements) {
    this.nodes = new ArrayBackedNodeIterator(PsiUtilCore.toPsiElementArray(elements));
    this.nodeCount = elements.size();
}
Also used : ArrayBackedNodeIterator(com.intellij.dupLocator.iterators.ArrayBackedNodeIterator)

Example 3 with ArrayBackedNodeIterator

use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator 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 4 with ArrayBackedNodeIterator

use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator in project intellij-community by JetBrains.

the class MatcherImpl method match.

// Initiates the matching process for given element
// @param element the current search tree element
void match(PsiElement element, final Language language) {
    final MatchingStrategy strategy = matchContext.getPattern().getStrategy();
    final Language elementLanguage = element.getLanguage();
    if (strategy.continueMatching(element) && elementLanguage.isKindOf(language)) {
        visitor.matchContext(new ArrayBackedNodeIterator(new PsiElement[] { element }));
        return;
    }
    for (PsiElement el = element.getFirstChild(); el != null; el = el.getNextSibling()) {
        match(el, language);
    }
    if (element instanceof PsiLanguageInjectionHost) {
        InjectedLanguageUtil.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() {

            @Override
            public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
                match(injectedPsi, language);
            }
        });
    }
}
Also used : Language(com.intellij.lang.Language) MatchingStrategy(com.intellij.structuralsearch.impl.matcher.strategies.MatchingStrategy) ArrayBackedNodeIterator(com.intellij.dupLocator.iterators.ArrayBackedNodeIterator)

Example 5 with ArrayBackedNodeIterator

use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator in project intellij-community by JetBrains.

the class MatcherImpl method findMatches.

/**
   * Finds the matches of given pattern starting from given tree element.
   * @throws MalformedPatternException
   * @throws UnsupportedPatternException
   */
protected void findMatches(MatchResultSink sink, final MatchOptions options) throws MalformedPatternException, UnsupportedPatternException {
    CompiledPattern compiledPattern = prepareMatching(sink, options);
    if (compiledPattern == null) {
        return;
    }
    matchContext.getSink().setMatchingProcess(scheduler);
    scheduler.init();
    progress = matchContext.getSink().getProgressIndicator();
    if (isTesting) {
        // testing mode;
        final PsiElement[] elements = ((LocalSearchScope) options.getScope()).getScope();
        PsiElement parent = elements[0].getParent();
        if (elements.length > 0 && matchContext.getPattern().getStrategy().continueMatching(parent != null ? parent : elements[0])) {
            visitor.matchContext(new SsrFilteringNodeIterator(new ArrayBackedNodeIterator(elements)));
        } else {
            final LanguageFileType fileType = (LanguageFileType) matchContext.getOptions().getFileType();
            final Language language = fileType.getLanguage();
            for (PsiElement element : elements) {
                match(element, language);
            }
        }
        matchContext.getSink().matchingFinished();
        return;
    }
    if (!findMatches(options, compiledPattern)) {
        return;
    }
    if (scheduler.getTaskQueueEndAction() == null) {
        scheduler.setTaskQueueEndAction(() -> matchContext.getSink().matchingFinished());
    }
    scheduler.executeNext();
}
Also used : LocalSearchScope(com.intellij.psi.search.LocalSearchScope) LanguageFileType(com.intellij.openapi.fileTypes.LanguageFileType) Language(com.intellij.lang.Language) SsrFilteringNodeIterator(com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator) ArrayBackedNodeIterator(com.intellij.dupLocator.iterators.ArrayBackedNodeIterator)

Aggregations

ArrayBackedNodeIterator (com.intellij.dupLocator.iterators.ArrayBackedNodeIterator)6 Language (com.intellij.lang.Language)2 MatchingHandler (com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler)2 SsrFilteringNodeIterator (com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator)2 CountingNodeIterator (com.intellij.dupLocator.iterators.CountingNodeIterator)1 LanguageFileType (com.intellij.openapi.fileTypes.LanguageFileType)1 PsiElement (com.intellij.psi.PsiElement)1 LocalSearchScope (com.intellij.psi.search.LocalSearchScope)1 SubstitutionHandler (com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler)1 HierarchyNodeIterator (com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator)1 MatchingStrategy (com.intellij.structuralsearch.impl.matcher.strategies.MatchingStrategy)1 ArrayList (java.util.ArrayList)1