diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/XPathAnnotator.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/XPathAnnotator.java index 404e0e84d771..c9f6603590e1 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/XPathAnnotator.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/XPathAnnotator.java @@ -26,6 +26,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiTreeUtil; import org.intellij.lang.xpath.XPath2TokenTypes; +import org.intellij.lang.xpath.XPathElementType; import org.intellij.lang.xpath.XPathFileType; import org.intellij.lang.xpath.context.functions.Function; import org.jetbrains.annotations.NotNull; @@ -104,9 +105,18 @@ public final class XPathAnnotator extends XPath2ElementVisitor implements Annota @Override public void visitXPathBinaryExpression(final XPathBinaryExpression o) { - if (XPath2TokenTypes.COMP_OPS.contains(o.getOperator())) { - if (o.getContainingFile().getLanguage() == XPathFileType.XPATH2.getLanguage()) { - final XPathExpression operand = o.getLOperand(); + if (o.getContainingFile().getLanguage() == XPathFileType.XPATH2.getLanguage()) { + final XPathExpression operand = o.getLOperand(); + final XPathElementType operator = o.getOperator(); + if (operand instanceof XPathNumber) { + if (operator != XPathTokenTypes.STAR && XPath2TokenTypes.KEYWORDS.contains(operator)) { + final String op = o.getOperationSign(); + if (o.getText().startsWith(operand.getText() + op)) { + myHolder.createErrorAnnotation(o, "Number literal must be followed by whitespace in XPath 2"); + } + } + } + if (XPath2TokenTypes.COMP_OPS.contains(operator)) { if (operand instanceof XPathBinaryExpression && XPath2TokenTypes.COMP_OPS.contains(((XPathBinaryExpression)operand).getOperator())) { final Annotation annotation = myHolder.createErrorAnnotation(o, "Consecutive comparison is not allowed in XPath 2"); diff --git a/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/XPath2HighlightingTest.java b/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/XPath2HighlightingTest.java index 7cd5225cf271..766a731f799f 100644 --- a/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/XPath2HighlightingTest.java +++ b/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/XPath2HighlightingTest.java @@ -29,6 +29,10 @@ public class XPath2HighlightingTest extends XPath2HighlightingTestBase { doXPathHighlighting(); } + public void testNumberFollowedByToken() throws Throwable { + doXPathHighlighting(); + } + @Override protected String getSubPath() { return "xpath/highlighting"; diff --git a/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/XPathHighlightingTest.java b/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/XPathHighlightingTest.java index 01fe9c1a4676..dea011861e52 100644 --- a/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/XPathHighlightingTest.java +++ b/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/XPathHighlightingTest.java @@ -56,6 +56,10 @@ public class XPathHighlightingTest extends TestBase { doXPathHighlighting(); } + public void testNumberFollowedByToken() throws Throwable { + doXPathHighlighting(); + } + private void doXPathHighlighting(String... moreFiles) throws Throwable { final String name = getTestFileName(); myFixture.testHighlighting(true, false, false, ArrayUtil.append(moreFiles, name + ".xpath")); diff --git a/plugins/xpath/xpath-lang/testData/xpath/highlighting/numberFollowedByToken.xpath b/plugins/xpath/xpath-lang/testData/xpath/highlighting/numberFollowedByToken.xpath new file mode 100644 index 000000000000..6e39817a4ac8 --- /dev/null +++ b/plugins/xpath/xpath-lang/testData/xpath/highlighting/numberFollowedByToken.xpath @@ -0,0 +1 @@ +10div 2 + 3 mod 2 \ No newline at end of file diff --git a/plugins/xpath/xpath-lang/testData/xpath/highlighting/numberFollowedByToken.xpath2 b/plugins/xpath/xpath-lang/testData/xpath/highlighting/numberFollowedByToken.xpath2 new file mode 100644 index 000000000000..f67dd96a57ce --- /dev/null +++ b/plugins/xpath/xpath-lang/testData/xpath/highlighting/numberFollowedByToken.xpath2 @@ -0,0 +1 @@ +10div 2 + 3 mod 2 \ No newline at end of file