From 5d4e60721316c9fd90b355467b8b690a6fb5b02f Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 28 Jul 2014 11:31:53 +0200 Subject: [PATCH] Prevent markers from overlapping after whitespace balancing (WEB-12693) [a=Roman Shevchenko, r=Maxim.Mossienko] --- .../intellij/lang/impl/PsiBuilderImpl.java | 8 ++++++- .../intellij/lang/PsiBuilderQuickTest.java | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index 1013565eaba5..b68fa936af23 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -1154,6 +1154,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { private void balanceWhiteSpaces() { RelativeTokenTypesView wsTokens = new RelativeTokenTypesView(); RelativeTokenTextView tokenTextGetter = new RelativeTokenTextView(); + int lastIndex = 0; for (int i = 1, size = myProduction.size() - 1; i < size; i++) { ProductionMarker item = myProduction.get(i); @@ -1162,7 +1163,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex; - int wsStartIndex = item.myLexemeIndex; + int wsStartIndex = Math.max(item.myLexemeIndex, lastIndex); while (wsStartIndex > prevProductionLexIndex && whitespaceOrComment(myLexTypes[wsStartIndex - 1])) wsStartIndex--; int wsEndIndex = item.myLexemeIndex; while (wsEndIndex < myLexemeCount && whitespaceOrComment(myLexTypes[wsEndIndex])) wsEndIndex++; @@ -1173,6 +1174,11 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { boolean atEnd = wsStartIndex == 0 || wsEndIndex == myLexemeCount; item.myLexemeIndex = wsStartIndex + item.myEdgeTokenBinder.getEdgePosition(wsTokens, atEnd, tokenTextGetter); } + else if (item.myLexemeIndex < wsStartIndex) { + item.myLexemeIndex = wsStartIndex; + } + + lastIndex = item.myLexemeIndex; } } diff --git a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java index 5390ee8eb228..db833c2d8f3e 100644 --- a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java +++ b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java @@ -461,6 +461,27 @@ public class PsiBuilderQuickTest extends LightPlatformLangTestCase { " PsiElement(OTHER)('}')\n"); } + public void testEndMarkersOverlapping() { + doTest("a ", + new Parser() { + @Override + public void parse(PsiBuilder builder) { + PsiBuilder.Marker e1 = builder.mark(); + PsiBuilder.Marker e2 = builder.mark(); + builder.advanceLexer(); + e2.done(OTHER); + e2.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER); + e1.done(OTHER); + e1.setCustomEdgeTokenBinders(null, WhitespacesBinders.DEFAULT_RIGHT_BINDER); + assertTrue(builder.eof()); + } + }, + "Element(ROOT)\n" + + " Element(OTHER)\n" + + " Element(OTHER)\n" + + " PsiElement(LETTER)('a')\n" + + " PsiWhiteSpace(' ')\n"); + } private interface Parser { void parse(PsiBuilder builder);