diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java b/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java
index 38d4b6666dfe..e85c4b0b1d5a 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java
@@ -51,6 +51,12 @@ public class XmlStructuralSearchProfile extends StructuralSearchProfile {
return element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_NAME;
}
+ @NotNull
+ @Override
+ public String getTypedVarString(PsiElement element) {
+ return element instanceof XmlText ? element.getText().trim() : super.getTypedVarString(element);
+ }
+
@NotNull
@Override
public NodeFilter getLexicalNodesFilter() {
@@ -85,8 +91,8 @@ public class XmlStructuralSearchProfile extends StructuralSearchProfile {
boolean physical) {
final String ext = extension != null ? extension : fileType.getDefaultExtension();
String text1 = context == PatternTreeContext.File ? text : "" + text + "";
- final PsiFile fileFromText = PsiFileFactory.getInstance(project)
- .createFileFromText("dummy." + ext, fileType, text1, LocalTimeCounter.currentTime(), physical, true);
+ final PsiFile fileFromText =
+ PsiFileFactory.getInstance(project).createFileFromText("dummy." + ext, fileType, text1, LocalTimeCounter.currentTime(), physical, true);
final XmlDocument document = HtmlUtil.getRealXmlDocument(((XmlFile)fileFromText).getDocument());
if (context == PatternTreeContext.File) {
@@ -147,13 +153,13 @@ public class XmlStructuralSearchProfile extends StructuralSearchProfile {
@Override
public StructuralReplaceHandler getReplaceHandler(@NotNull ReplacementContext context) {
- return new MyReplaceHandler(context);
+ return new XmlReplaceHandler(context);
}
- private static class MyReplaceHandler extends StructuralReplaceHandler {
+ private static class XmlReplaceHandler extends StructuralReplaceHandler {
private final ReplacementContext myContext;
- MyReplaceHandler(ReplacementContext context) {
+ XmlReplaceHandler(ReplacementContext context) {
myContext = context;
}
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlCompiledPattern.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlCompiledPattern.java
index 0c9f4945e3a5..832156528112 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlCompiledPattern.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlCompiledPattern.java
@@ -1,3 +1,4 @@
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.impl.matcher;
import com.intellij.structuralsearch.impl.matcher.strategies.XmlMatchingStrategy;
@@ -17,6 +18,6 @@ public class XmlCompiledPattern extends CompiledPattern {
}
public boolean isTypedVar(final String str) {
- return str.startsWith(XML_TYPED_VAR_PREFIX);
+ return str.trim().startsWith(XML_TYPED_VAR_PREFIX);
}
}
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 4a997b9f6502..3cbc167f2c29 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java
@@ -8,6 +8,7 @@ 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;
+import com.intellij.xml.util.XmlUtil;
/**
* @author Eugene.Kudelevsky
@@ -21,16 +22,15 @@ public class XmlMatchingVisitor extends XmlElementVisitor {
@Override public void visitXmlAttribute(XmlAttribute attribute) {
final XmlAttribute another = (XmlAttribute)myMatchingVisitor.getElement();
- final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(attribute.getName());
-
- if (!myMatchingVisitor.setResult(isTypedVar || myMatchingVisitor.matchText(attribute.getName(), another.getName()))) return;
- final XmlAttributeValue valueElement = attribute.getValueElement();
- if (valueElement != null && !myMatchingVisitor.setResult(myMatchingVisitor.match(valueElement, another.getValueElement()))) return;
-
- if (isTypedVar) {
- final SubstitutionHandler handler =
- (SubstitutionHandler)myMatchingVisitor.getMatchContext().getPattern().getHandler(attribute.getName());
- myMatchingVisitor.setResult(handler.handle(another, myMatchingVisitor.getMatchContext()));
+ myMatchingVisitor.getMatchContext().pushResult();
+ final XmlElement name = attribute.getNameElement();
+ final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(name);
+ try {
+ if (!myMatchingVisitor.setResult(isTypedVar || myMatchingVisitor.matchText(name, another.getNameElement()))) return;
+ final XmlAttributeValue valueElement = attribute.getValueElement();
+ myMatchingVisitor.setResult(valueElement == null || myMatchingVisitor.matchSingle(valueElement, another.getValueElement()));
+ } finally {
+ myMatchingVisitor.scopeMatch(name, isTypedVar, another);
}
}
@@ -50,7 +50,9 @@ public class XmlMatchingVisitor extends XmlElementVisitor {
@Override public void visitXmlTag(XmlTag tag) {
final XmlTag another = (XmlTag)myMatchingVisitor.getElement();
- final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(tag.getName());
+ final CompiledPattern pattern = myMatchingVisitor.getMatchContext().getPattern();
+ final XmlToken name = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_NAME);
+ final boolean isTypedVar = pattern.isTypedVar(name);
if (!myMatchingVisitor.setResult((isTypedVar || myMatchingVisitor.matchText(tag.getName(), another.getName())) &&
myMatchingVisitor.matchInAnyOrder(tag.getAttributes(), another.getAttributes()))) return;
@@ -63,11 +65,9 @@ public class XmlMatchingVisitor extends XmlElementVisitor {
}
if (isTypedVar) {
- final PsiElement[] children = another.getChildren();
- if (children.length > 1) {
- final SubstitutionHandler handler = (SubstitutionHandler)myMatchingVisitor.getMatchContext().getPattern().getHandler(tag.getName());
- myMatchingVisitor.setResult(handler.handle(children[1], myMatchingVisitor.getMatchContext()));
- }
+ final SubstitutionHandler handler = (SubstitutionHandler)pattern.getHandler(name);
+ myMatchingVisitor.setResult(handler.handle(XmlUtil.getTokenOfType(another, XmlTokenType.XML_NAME),
+ myMatchingVisitor.getMatchContext()));
}
}
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java
index 5d1e3f24174d..93aa04994831 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java
@@ -1,13 +1,10 @@
-// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.impl.matcher.compiler;
import com.intellij.psi.PsiElement;
import com.intellij.psi.XmlRecursiveElementVisitor;
import com.intellij.psi.XmlRecursiveElementWalkingVisitor;
-import com.intellij.psi.xml.XmlAttribute;
-import com.intellij.psi.xml.XmlTag;
-import com.intellij.psi.xml.XmlText;
-import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.*;
import com.intellij.structuralsearch.impl.matcher.CompiledPattern;
import com.intellij.structuralsearch.impl.matcher.filters.TagValueFilter;
import com.intellij.structuralsearch.impl.matcher.handlers.TopLevelMatchingHandler;
@@ -59,13 +56,16 @@ public class XmlCompilingVisitor extends XmlRecursiveElementVisitor {
}
}
- @Override public void visitElement(PsiElement element) {
+ @Override
+ public void visitElement(PsiElement element) {
myCompilingVisitor.handle(element);
super.visitElement(element);
}
@Override
- public void visitXmlToken(XmlToken token) {}
+ public void visitXmlToken(XmlToken token) {
+ if (token.getTokenType() == XmlTokenType.XML_NAME) super.visitXmlToken(token);
+ }
@Override
public void visitXmlText(XmlText text) {
diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/XmlStructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/XmlStructuralSearchTest.java
index 4eba22f3d659..412a537aca82 100644
--- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/XmlStructuralSearchTest.java
+++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/XmlStructuralSearchTest.java
@@ -39,6 +39,14 @@ public class XmlStructuralSearchTest extends StructuralSearchTestCase {
String in = "
";
assertEquals(1, findMatchesCount(in, "
", StdFileTypes.HTML));
+ assertEquals(1, findMatchesCount(in, "
", StdFileTypes.HTML));
+ assertEquals(1, findMatchesCount(in, "
", StdFileTypes.HTML));
+
+ String in2 = "" +
+ "" +
+ "";
+ assertEquals("should find tags without any attributes without value", 1, findMatchesCount(in2, "", StdFileTypes.HTML));
+ assertEquals("should find tags with any attributes without value", 2, findMatchesCount(in2, "", StdFileTypes.HTML));
}
public void testHtmlSearchCaseInsensitive() {
@@ -161,10 +169,10 @@ public class XmlStructuralSearchTest extends StructuralSearchTestCase {
return PlatformTestUtil.getCommunityPath() + "/platform/structuralsearch/testData/html/";
}
- //public void testXmlSearch2() {
- // String s1 = "
AAA
ZZZ
";
- // String s2 = " 'content?
";
- //
- // assertEquals(5,findMatchesCount(s1,s2,false,StdFileTypes.XML));
- //}
+ public void testXmlSearch2() {
+ String s1 = " AAA
ZZZ
";
+ String s2 = " 'content?
";
+
+ assertEquals(5, findMatchesCount(s1, s2, StdFileTypes.XML));
+ }
}