diff --git a/RegExpSupport/src/org/intellij/lang/regexp/inspection/ShredManager.java b/RegExpSupport/src/org/intellij/lang/regexp/inspection/ShredManager.java index 2f156a749eb0..6715d1238ac0 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/inspection/ShredManager.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/inspection/ShredManager.java @@ -3,6 +3,7 @@ package org.intellij.lang.regexp.inspection; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.PsiLiteralValue; @@ -97,20 +98,20 @@ class ShredManager { @Override public boolean hasNext() { - return myShredIndex != -1 && extractShredText(myShreds.get(myShredIndex)) != null; + return myShredIndex != -1 && findFirstNonEmptyShredIndex() != -1; } @Override @NotNull public ShredInfo next() { - if (myShredIndex == -1) throw new IllegalStateException("Iterator doesn't contain any elements"); + if (myShredIndex == -1) throw new IllegalStateException("Iterator doesn't contain any shreds"); + myShredIndex = findFirstNonEmptyShredIndex(); + if (myShredIndex == -1) throw new IllegalStateException("Iterator doesn't contain non-empty shreds"); if (myShredText == null) { myShredText = extractShredText(myShreds.get(myShredIndex)); - if (myShredText == null) throw new IllegalStateException("Iterator#hasNext() must be called before Iterator#next()"); - if (myShredText.length() > 0) { - mySymbolIndex = 0; - } + if (StringUtil.isEmpty(myShredText)) throw new IllegalStateException("Current shred text is empty"); + mySymbolIndex = 0; } int shredIndex = myShredIndex; char shredSymbol = myShredText.charAt(mySymbolIndex); @@ -120,14 +121,21 @@ class ShredManager { return new ShredInfo(shredIndex, shredSymbol, symbolIndex, shred.getHost()); } + private int findFirstNonEmptyShredIndex() { + for (int shredIndex = myShredIndex; shredIndex < myShreds.size(); shredIndex++) { + String shredText = extractShredText(myShreds.get(shredIndex)); + if (!StringUtil.isEmpty(shredText)) return shredIndex; + } + return -1; + } + private void updateIndexes() { if (mySymbolIndex < myShredText.length() - 1) { mySymbolIndex++; } else if (myShredIndex < myShreds.size() - 1) { - mySymbolIndex = 0; myShredIndex++; - myShredText = extractShredText(myShreds.get(myShredIndex)); + myShredText = null; } else { myShredIndex = -1; diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/RegExpHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/RegExpHighlightingTest.java index d7ac6ad0611a..6a0182e39275 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/RegExpHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/RegExpHighlightingTest.java @@ -242,32 +242,37 @@ public class RegExpHighlightingTest extends LightJavaCodeInsightFixtureTestCase } public void testConditionalExprNegative1() { - doTestConditionalExpr("c ? \"^Hello$\" : \"^World$\""); + doTestUnexpectedAnchor("c ? \"^Hello$\" : \"^World$\""); } public void testBinaryExprPositive1() { - doTestConditionalExpr("\"^good" + warningMarker('$') + "\" + \"" + warningMarker('^') + "luck$\""); + doTestUnexpectedAnchor("\"^good" + warningMarker('$') + "\" + \"" + warningMarker('^') + "luck$\""); } public void testConditionalExprPositive1() { - doTestConditionalExpr("c ? \" " + warningMarker('^') + "Hello" + warningMarker('$') + " \" " + - ": \" " + warningMarker('^') + "World" + warningMarker('$') + " \""); + doTestUnexpectedAnchor("c ? \" " + warningMarker('^') + "Hello" + warningMarker('$') + " \" " + + ": \" " + warningMarker('^') + "World" + warningMarker('$') + " \""); } public void testConditionalExprPositive2() { - doTestConditionalExpr("c ? \" " + warningMarker('^') + "Hello$\" " + - ": \"^Have" + warningMarker('$') + "\" + \"" + warningMarker('^') + "Fun$\""); + doTestUnexpectedAnchor("c ? \" " + warningMarker('^') + "Hello$\" " + + ": \"^Have" + warningMarker('$') + "\" + \"" + warningMarker('^') + "Fun$\""); } public void testConditionalExprPositive3() { - doTestConditionalExpr("c ? (c ? (c ? \"^go$\" : \"^od" + warningMarker('$') + "\" + \"" + warningMarker('^') + "lu$\") : \"^ck$\") " + - ": (c ? \"^and" + warningMarker('$') + "\" + \"" + warningMarker('^') + - "ha" + warningMarker('$') + "\" + \"" + warningMarker('^') + "ve$\" : \"^fun$\")"); + doTestUnexpectedAnchor("c ? (c ? (c ? \"^go$\" : \"^od" + warningMarker('$') + "\" + \"" + warningMarker('^') + "lu$\") : \"^ck$\") " + + ": (c ? \"^and" + warningMarker('$') + "\" + \"" + warningMarker('^') + + "ha" + warningMarker('$') + "\" + \"" + warningMarker('^') + "ve$\" : \"^fun$\")"); } public void testConditionalExprPositive4() { - doTestConditionalExpr("c ? \"^hello" + warningMarker('$') + "\" + getStr() + \"" + warningMarker('^') + "world$\" " + - ": getStr() + \"" + warningMarker('^') + "yeah" + warningMarker('$') + " \""); + doTestUnexpectedAnchor("c ? \"^hello" + warningMarker('$') + "\" + getStr() + \"" + warningMarker('^') + "world$\" " + + ": getStr() + \"" + warningMarker('^') + "yeah" + warningMarker('$') + " \""); + } + + public void testConcatenationWithEmptyStrings() { + // "" + " ^" + "" + "$ " + doTestUnexpectedAnchor("\"\" +" + "\" " + warningMarker('^') + "\" + " + "\"\" + " + "\"" + warningMarker('$') + " \""); } private void doTest(@NonNls String code) { @@ -276,7 +281,7 @@ public class RegExpHighlightingTest extends LightJavaCodeInsightFixtureTestCase myFixture.testHighlighting(); } - private void doTestConditionalExpr(@NonNls String code) { + private void doTestUnexpectedAnchor(@NonNls String code) { myFixture.enableInspections(new UnexpectedAnchorInspection()); myFixture.configureByText(JavaFileType.INSTANCE, "class X {" + " void test(boolean c) {" +