Search in sources :

Example 6 with SubstitutionHandler

use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.

the class PatternCompiler method doCompile.

private static List<PsiElement> doCompile(Project project, MatchOptions options, CompiledPattern result, PrefixProvider prefixProvider, CompileContext context) {
    result.clearHandlers();
    context.init(result, options, project, options.getScope() instanceof GlobalSearchScope);
    final StringBuilder buf = new StringBuilder();
    Template template = TemplateManager.getInstance(project).createTemplate("", "", options.getSearchPattern());
    int segmentsCount = template.getSegmentsCount();
    String text = template.getTemplateText();
    buf.setLength(0);
    int prevOffset = 0;
    for (int i = 0; i < segmentsCount; ++i) {
        final int offset = template.getSegmentOffset(i);
        final String name = template.getSegmentName(i);
        final String prefix = prefixProvider.getPrefix(i);
        if (prefix == null) {
            throw new MalformedPatternException();
        }
        buf.append(text.substring(prevOffset, offset));
        buf.append(prefix);
        buf.append(name);
        MatchVariableConstraint constraint = options.getVariableConstraint(name);
        if (constraint == null) {
            // we do not edited the constraints
            constraint = new MatchVariableConstraint();
            constraint.setName(name);
            options.addVariableConstraint(constraint);
        }
        SubstitutionHandler handler = result.createSubstitutionHandler(name, prefix + name, constraint.isPartOfSearchResults(), constraint.getMinCount(), constraint.getMaxCount(), constraint.isGreedy());
        if (constraint.isWithinHierarchy()) {
            handler.setSubtype(true);
        }
        if (constraint.isStrictlyWithinHierarchy()) {
            handler.setStrictSubtype(true);
        }
        MatchPredicate predicate;
        if (!StringUtil.isEmptyOrSpaces(constraint.getRegExp())) {
            predicate = new RegExpPredicate(constraint.getRegExp(), options.isCaseSensitiveMatch(), name, constraint.isWholeWordsOnly(), constraint.isPartOfSearchResults());
            if (constraint.isInvertRegExp()) {
                predicate = new NotPredicate(predicate);
            }
            addPredicate(handler, predicate);
        }
        if (constraint.isReference()) {
            predicate = new ReferencePredicate(constraint.getNameOfReferenceVar());
            if (constraint.isInvertReference()) {
                predicate = new NotPredicate(predicate);
            }
            addPredicate(handler, predicate);
        }
        addExtensionPredicates(options, constraint, handler);
        addScriptConstraint(project, name, constraint, handler);
        if (!StringUtil.isEmptyOrSpaces(constraint.getContainsConstraint())) {
            predicate = new ContainsPredicate(name, constraint.getContainsConstraint());
            if (constraint.isInvertContainsConstraint()) {
                predicate = new NotPredicate(predicate);
            }
            addPredicate(handler, predicate);
        }
        if (!StringUtil.isEmptyOrSpaces(constraint.getWithinConstraint())) {
            assert false;
        }
        prevOffset = offset;
    }
    MatchVariableConstraint constraint = options.getVariableConstraint(Configuration.CONTEXT_VAR_NAME);
    if (constraint != null) {
        SubstitutionHandler handler = result.createSubstitutionHandler(Configuration.CONTEXT_VAR_NAME, Configuration.CONTEXT_VAR_NAME, constraint.isPartOfSearchResults(), constraint.getMinCount(), constraint.getMaxCount(), constraint.isGreedy());
        if (!StringUtil.isEmptyOrSpaces(constraint.getWithinConstraint())) {
            MatchPredicate predicate = new WithinPredicate(Configuration.CONTEXT_VAR_NAME, constraint.getWithinConstraint(), options.getFileType(), project);
            if (constraint.isInvertWithinConstraint()) {
                predicate = new NotPredicate(predicate);
            }
            addPredicate(handler, predicate);
        }
        addExtensionPredicates(options, constraint, handler);
        addScriptConstraint(project, Configuration.CONTEXT_VAR_NAME, constraint, handler);
    }
    buf.append(text.substring(prevOffset, text.length()));
    PsiElement[] matchStatements;
    try {
        matchStatements = MatcherImplUtil.createTreeFromText(buf.toString(), PatternTreeContext.Block, options.getFileType(), options.getDialect(), options.getPatternContext(), project, false);
        if (matchStatements.length == 0)
            throw new MalformedPatternException();
    } catch (IncorrectOperationException e) {
        throw new MalformedPatternException(e.getMessage());
    }
    NodeFilter filter = LexicalNodesFilter.getInstance();
    GlobalCompilingVisitor compilingVisitor = new GlobalCompilingVisitor();
    compilingVisitor.compile(matchStatements, context);
    ArrayList<PsiElement> elements = new ArrayList<>();
    for (PsiElement matchStatement : matchStatements) {
        if (!filter.accepts(matchStatement)) {
            elements.add(matchStatement);
        }
    }
    new DeleteNodesAction(compilingVisitor.getLexicalNodes()).run();
    return elements;
}
Also used : TIntArrayList(gnu.trove.TIntArrayList) MatchPredicate(com.intellij.structuralsearch.impl.matcher.handlers.MatchPredicate) Template(com.intellij.codeInsight.template.Template) SubstitutionHandler(com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) IncorrectOperationException(com.intellij.util.IncorrectOperationException) NodeFilter(com.intellij.dupLocator.util.NodeFilter)

Example 7 with SubstitutionHandler

use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.

the class JavaMatchingVisitor method matchType.

private boolean matchType(final PsiElement patternType, final PsiElement matchedType) {
    PsiElement patternElement = getInnermostComponent(patternType);
    PsiElement matchedElement = getInnermostComponent(matchedType);
    PsiElement[] typeParameters = null;
    if (matchedElement instanceof PsiJavaCodeReferenceElement) {
        final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) matchedElement;
        typeParameters = getTypeParameters(referenceElement, !hasDiamondTypeParameter(patternElement));
    } else if (matchedElement instanceof PsiTypeParameter) {
        matchedElement = ((PsiTypeParameter) matchedElement).getNameIdentifier();
    } else if (matchedElement instanceof PsiClass && ((PsiClass) matchedElement).hasTypeParameters()) {
        typeParameters = ((PsiClass) matchedElement).getTypeParameters();
        matchedElement = ((PsiClass) matchedElement).getNameIdentifier();
    } else if (matchedElement instanceof PsiMethod && ((PsiMethod) matchedElement).hasTypeParameters()) {
        typeParameters = ((PsiMethod) matchedType).getTypeParameters();
        matchedElement = ((PsiMethod) matchedType).getNameIdentifier();
    }
    if (patternElement instanceof PsiJavaCodeReferenceElement) {
        final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) patternElement;
        final PsiReferenceParameterList list = referenceElement.getParameterList();
        if (list != null) {
            final PsiTypeElement[] elements = list.getTypeParameterElements();
            if (elements.length > 0 && (typeParameters == null || !myMatchingVisitor.matchSequentially(elements, typeParameters))) {
                return false;
            }
        }
        patternElement = referenceElement.getReferenceNameElement();
    }
    final int matchedArrayDimensions = getArrayDimensions(matchedType);
    final int patternArrayDimensions = getArrayDimensions(patternType);
    if (myMatchingVisitor.getMatchContext().getPattern().isTypedVar(patternElement)) {
        final SubstitutionHandler handler = (SubstitutionHandler) myMatchingVisitor.getMatchContext().getPattern().getHandler(patternElement);
        RegExpPredicate regExpPredicate = null;
        if (patternArrayDimensions != 0) {
            if (patternArrayDimensions != matchedArrayDimensions) {
                return false;
            }
        } else if (matchedArrayDimensions != 0) {
            regExpPredicate = MatchingHandler.getSimpleRegExpPredicate(handler);
            if (regExpPredicate != null) {
                regExpPredicate.setNodeTextGenerator(new RegExpPredicate.NodeTextGenerator() {

                    public String getText(PsiElement element) {
                        StringBuilder builder = new StringBuilder(RegExpPredicate.getMeaningfulText(element));
                        for (int i = 0; i < matchedArrayDimensions; ++i) builder.append("[]");
                        return builder.toString();
                    }
                });
            }
        }
        try {
            if (handler.isSubtype() || handler.isStrictSubtype()) {
                return checkMatchWithinHierarchy(matchedElement, handler, patternElement);
            } else {
                return handler.handle(matchedElement, myMatchingVisitor.getMatchContext());
            }
        } finally {
            if (regExpPredicate != null)
                regExpPredicate.setNodeTextGenerator(null);
        }
    }
    if (matchedArrayDimensions != patternArrayDimensions) {
        return false;
    }
    if (patternElement instanceof PsiIdentifier) {
        final PsiElement parent = patternElement.getParent();
        if (parent instanceof PsiJavaCodeReferenceElement) {
            patternElement = parent;
        }
    }
    if (matchedElement instanceof PsiIdentifier) {
        final PsiElement parent = matchedElement.getParent();
        if (parent instanceof PsiJavaCodeReferenceElement) {
            matchedElement = parent;
        }
    }
    final String text = getText(patternElement);
    final String text2 = getText(matchedElement);
    final boolean caseSensitive = myMatchingVisitor.getMatchContext().getOptions().isCaseSensitiveMatch();
    final boolean equalsIgnorePackage = MatchUtils.compareWithNoDifferenceToPackage(text, text2, !caseSensitive);
    if (equalsIgnorePackage || !(matchedElement instanceof PsiJavaReference)) {
        return equalsIgnorePackage;
    } else {
        final PsiElement element2 = ((PsiJavaReference) matchedElement).resolve();
        if (!(element2 instanceof PsiClass)) {
            return false;
        }
        final String name = ((PsiClass) element2).getQualifiedName();
        return caseSensitive ? text.equals(name) : text.equalsIgnoreCase(name);
    }
}
Also used : RegExpPredicate(com.intellij.structuralsearch.impl.matcher.predicates.RegExpPredicate) SubstitutionHandler(com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler)

Example 8 with SubstitutionHandler

use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.

the class JavaMatchingVisitor method visitTypeParameter.

@Override
public void visitTypeParameter(PsiTypeParameter psiTypeParameter) {
    final PsiTypeParameter parameter = (PsiTypeParameter) myMatchingVisitor.getElement();
    final PsiIdentifier identifier = psiTypeParameter.getNameIdentifier();
    final PsiIdentifier identifier2 = parameter.getNameIdentifier();
    final MatchingHandler handler = myMatchingVisitor.getMatchContext().getPattern().getHandler(identifier);
    if (handler instanceof SubstitutionHandler) {
        myMatchingVisitor.setResult(((SubstitutionHandler) handler).handle(identifier2, myMatchingVisitor.getMatchContext()));
    } else {
        myMatchingVisitor.setResult(myMatchingVisitor.matchText(identifier, identifier2));
    }
    if (myMatchingVisitor.getResult()) {
        myMatchingVisitor.setResult(matchInAnyOrder(psiTypeParameter.getExtendsList(), parameter.getExtendsList()));
    }
    if (myMatchingVisitor.getResult()) {
        myMatchingVisitor.setResult(myMatchingVisitor.matchInAnyOrder(psiTypeParameter.getAnnotations(), parameter.getAnnotations()));
    }
}
Also used : SubstitutionHandler(com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler) MatchingHandler(com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler)

Example 9 with SubstitutionHandler

use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler 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 10 with SubstitutionHandler

use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.

the class JavaMatchingVisitor method matchImplicitQualifier.

private void matchImplicitQualifier(MatchingHandler matchingHandler, PsiElement target, MatchContext context) {
    if (!(matchingHandler instanceof SubstitutionHandler)) {
        myMatchingVisitor.setResult(false);
        return;
    }
    final SubstitutionHandler substitutionHandler = (SubstitutionHandler) matchingHandler;
    final MatchPredicate predicate = substitutionHandler.getPredicate();
    if (substitutionHandler.getMinOccurs() != 0) {
        myMatchingVisitor.setResult(false);
        return;
    }
    if (predicate == null) {
        myMatchingVisitor.setResult(true);
        return;
    }
    if (target == null) {
        myMatchingVisitor.setResult(false);
        return;
    }
    if (target instanceof PsiModifierListOwner && ((PsiModifierListOwner) target).hasModifierProperty(PsiModifier.STATIC)) {
        myMatchingVisitor.setResult(predicate.match(null, PsiTreeUtil.getParentOfType(target, PsiClass.class), context));
    } else {
        final PsiElementFactory factory = JavaPsiFacade.getElementFactory(target.getProject());
        final PsiExpression implicitReference = factory.createExpressionFromText("this", target);
        myMatchingVisitor.setResult(predicate.match(null, implicitReference, context));
    }
}
Also used : SubstitutionHandler(com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler) MatchPredicate(com.intellij.structuralsearch.impl.matcher.handlers.MatchPredicate)

Aggregations

SubstitutionHandler (com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler)15 MatchingHandler (com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler)8 MatchPredicate (com.intellij.structuralsearch.impl.matcher.handlers.MatchPredicate)3 LiteralWithSubstitutionHandler (com.intellij.structuralsearch.impl.matcher.handlers.LiteralWithSubstitutionHandler)2 RegExpPredicate (com.intellij.structuralsearch.impl.matcher.predicates.RegExpPredicate)2 Template (com.intellij.codeInsight.template.Template)1 ArrayBackedNodeIterator (com.intellij.dupLocator.iterators.ArrayBackedNodeIterator)1 NodeFilter (com.intellij.dupLocator.util.NodeFilter)1 GlobalSearchScope (com.intellij.psi.search.GlobalSearchScope)1 LexicalNodesFilter (com.intellij.structuralsearch.impl.matcher.filters.LexicalNodesFilter)1 DelegatingHandler (com.intellij.structuralsearch.impl.matcher.handlers.DelegatingHandler)1 HierarchyNodeIterator (com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator)1 IncorrectOperationException (com.intellij.util.IncorrectOperationException)1 TIntArrayList (gnu.trove.TIntArrayList)1 Matcher (java.util.regex.Matcher)1 NonNls (org.jetbrains.annotations.NonNls)1 Nullable (org.jetbrains.annotations.Nullable)1