diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java b/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java index 7b1ff34ce03c..3b493b4be40f 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java @@ -65,7 +65,13 @@ public class XmlStructuralSearchProfile extends StructuralSearchProfile { @NotNull @Override public NodeFilter getLexicalNodesFilter() { - return element -> element instanceof PsiWhiteSpace || element instanceof PsiErrorElement; + return element -> { + if (element instanceof XmlText) { + final PsiElement child = element.getFirstChild(); + return child == element.getLastChild() && child instanceof PsiWhiteSpace; + } + return element instanceof PsiWhiteSpace || element instanceof PsiErrorElement; + }; } @Override diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java index fa14c514f53d..7f385a312296 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java @@ -1,16 +1,26 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.structuralsearch.impl.matcher; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiWhiteSpace; -import com.intellij.psi.XmlElementVisitor; -import com.intellij.psi.util.PsiUtilCore; -import com.intellij.psi.xml.*; -import com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler; -import com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler; import com.intellij.dupLocator.iterators.ArrayBackedNodeIterator; - -import java.util.ArrayList; -import java.util.List; +import com.intellij.psi.PsiElement; +import com.intellij.psi.XmlElementVisitor; +import com.intellij.psi.xml.*; +import com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler; +import com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator; /** * @author Eugene.Kudelevsky @@ -40,8 +50,9 @@ public class XmlMatchingVisitor extends XmlElementVisitor { } if (myMatchingVisitor.getResult() && isTypedVar) { - MatchingHandler handler = myMatchingVisitor.getMatchContext().getPattern().getHandler(attribute.getName()); - myMatchingVisitor.setResult(((SubstitutionHandler)handler).handle(another, myMatchingVisitor.getMatchContext())); + final SubstitutionHandler handler = + (SubstitutionHandler)myMatchingVisitor.getMatchContext().getPattern().getHandler(attribute.getName()); + myMatchingVisitor.setResult(handler.handle(another, myMatchingVisitor.getMatchContext())); } } @@ -49,14 +60,11 @@ public class XmlMatchingVisitor extends XmlElementVisitor { final XmlAttributeValue another = (XmlAttributeValue)myMatchingVisitor.getElement(); final String text = value.getValue(); - final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(text); - MatchingHandler handler; - - if (isTypedVar && (handler = myMatchingVisitor.getMatchContext().getPattern().getHandler( text )) instanceof SubstitutionHandler) { - String text2 = another.getText(); - int offset = text2.length() > 0 && ( text2.charAt(0) == '"' || text2.charAt(0) == '\'') ? 1:0; - myMatchingVisitor.setResult(((SubstitutionHandler)handler).handle(another, offset, text2.length() - offset, - myMatchingVisitor.getMatchContext())); + if (myMatchingVisitor.getMatchContext().getPattern().isTypedVar(text)) { + final SubstitutionHandler handler = (SubstitutionHandler)myMatchingVisitor.getMatchContext().getPattern().getHandler(text); + final String text2 = another.getText(); + final int offset = text2.length() > 0 && (text2.charAt(0) == '"' || text2.charAt(0) == '\'') ? 1 : 0; + myMatchingVisitor.setResult(handler.handle(another, offset, text2.length() - offset, myMatchingVisitor.getMatchContext())); } else { myMatchingVisitor.setResult(matches(text, another.getValue())); } @@ -70,55 +78,33 @@ public class XmlMatchingVisitor extends XmlElementVisitor { myMatchingVisitor.matchInAnyOrder(tag.getAttributes(), another.getAttributes())); if(myMatchingVisitor.getResult()) { - final XmlTagChild[] contentChildren = tag.getValue().getChildren(); + final XmlTagChild[] children = tag.getValue().getChildren(); - if (contentChildren.length > 0) { - PsiElement[] patternNodes = contentChildren; - PsiElement[] matchedNodes = another.getValue().getChildren(); - - if (contentChildren.length != 1) { - patternNodes = filterOutWhitespace(patternNodes); - matchedNodes = filterOutWhitespace(matchedNodes); - } - - final boolean result = myMatchingVisitor.matchSequentially( - new ArrayBackedNodeIterator(patternNodes), - new ArrayBackedNodeIterator(matchedNodes) - ); - myMatchingVisitor.setResult(result); + final SsrFilteringNodeIterator patternNodes = new SsrFilteringNodeIterator(new ArrayBackedNodeIterator(children)); + if (patternNodes.current() != null) { + final SsrFilteringNodeIterator matchNodes = + new SsrFilteringNodeIterator(new ArrayBackedNodeIterator(another.getValue().getChildren())); + myMatchingVisitor.setResult(myMatchingVisitor.matchSequentially(patternNodes, matchNodes)); } } if (myMatchingVisitor.getResult() && isTypedVar) { final PsiElement[] children = another.getChildren(); if (children.length > 1) { - MatchingHandler handler = myMatchingVisitor.getMatchContext().getPattern().getHandler( tag.getName() ); - myMatchingVisitor.setResult(((SubstitutionHandler)handler).handle(children[1], myMatchingVisitor.getMatchContext())); + final SubstitutionHandler handler = (SubstitutionHandler)myMatchingVisitor.getMatchContext().getPattern().getHandler(tag.getName()); + myMatchingVisitor.setResult(handler.handle(children[1], myMatchingVisitor.getMatchContext())); } } } - private static PsiElement[] filterOutWhitespace(PsiElement[] children) { - final List result = new ArrayList<>(children.length); - for(PsiElement child : children) { - if (child instanceof XmlText) { - final PsiElement[] grandChildren = child.getChildren(); - if (grandChildren.length == 1 && grandChildren[0] instanceof PsiWhiteSpace) { - continue; - } - } - result.add(child); - } - return PsiUtilCore.toPsiElementArray(result); - } - @Override public void visitXmlText(XmlText text) { final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(text); final PsiElement element = myMatchingVisitor.getElement(); if (isTypedVar) { myMatchingVisitor.setResult(myMatchingVisitor.handleTypedElement(text, element)); - } else { - myMatchingVisitor.setResult(matches(text.getText(), element.getText())); + } + else { + myMatchingVisitor.setResult(element instanceof XmlText && matches(text.getText().trim(), element.getText().trim())); } }