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 = "\"alt\""; assertEquals(1, findMatchesCount(in, "", StdFileTypes.HTML)); + assertEquals(1, findMatchesCount(in, "", StdFileTypes.HTML)); + assertEquals(1, findMatchesCount(in, " '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)); + } }