From b20bff7c87cd8eccb6d224cd9f7b3e48d0413eda Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 1 Nov 2018 17:31:33 +0300 Subject: [PATCH] highlight brace after even if there's a non-whitespace (WEB-35454) --- .../BraceHighlightingHandler.java | 29 ++++----- .../editor/braceHighlighter/afterLBrace.java | 3 + .../editor/braceHighlighter/afterRBrace.java | 3 + .../editor/braceHighlighter/beforeLBrace.java | 3 + .../editor/braceHighlighter/beforeRBrace.java | 3 + .../braceHighlighter/doubleAfterSecond.java | 5 ++ .../braceHighlighter/doubleBeforeFirst.java | 5 ++ .../editor/braceHighlighter/doubleMiddle.java | 5 ++ .../editor/braceHighlighter/inTheMiddle.java | 3 + .../BraceHighlightingHandlerTest.java | 61 +++++++++++++++++++ 10 files changed, 103 insertions(+), 17 deletions(-) create mode 100644 platform/lang-impl/testData/editor/braceHighlighter/afterLBrace.java create mode 100644 platform/lang-impl/testData/editor/braceHighlighter/afterRBrace.java create mode 100644 platform/lang-impl/testData/editor/braceHighlighter/beforeLBrace.java create mode 100644 platform/lang-impl/testData/editor/braceHighlighter/beforeRBrace.java create mode 100644 platform/lang-impl/testData/editor/braceHighlighter/doubleAfterSecond.java create mode 100644 platform/lang-impl/testData/editor/braceHighlighter/doubleBeforeFirst.java create mode 100644 platform/lang-impl/testData/editor/braceHighlighter/doubleMiddle.java create mode 100644 platform/lang-impl/testData/editor/braceHighlighter/inTheMiddle.java create mode 100644 platform/lang-impl/testSources/com/intellij/codeInsight/highlighting/BraceHighlightingHandlerTest.java diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java index 908e4026d3d2..aac20b38c24f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java @@ -59,6 +59,7 @@ public class BraceHighlightingHandler { private static final Key LINE_MARKER_IN_EDITOR_KEY = Key.create("BraceHighlighter.LINE_MARKER_IN_EDITOR_KEY"); private static final Key HINT_IN_EDITOR_KEY = Key.create("BraceHighlighter.HINT_IN_EDITOR_KEY"); private static final Key PROCESSED = Key.create("BraceHighlighter.PROCESSED"); + static final int LAYER = HighlighterLayer.LAST + 1; @NotNull private final Project myProject; @NotNull private final EditorEx myEditor; @@ -68,7 +69,7 @@ public class BraceHighlightingHandler { private final PsiFile myPsiFile; private final CodeInsightSettings myCodeInsightSettings; - private BraceHighlightingHandler(@NotNull Project project, @NotNull EditorEx editor, @NotNull Alarm alarm, PsiFile psiFile) { + BraceHighlightingHandler(@NotNull Project project, @NotNull EditorEx editor, @NotNull Alarm alarm, PsiFile psiFile) { myProject = project; myEditor = editor; @@ -251,10 +252,7 @@ public class BraceHighlightingHandler { if (iterator.atEnd()) { offset--; } - else if (BraceMatchingUtil.isRBraceToken(iterator, chars, fileType)) { - offset--; - } - else if (!BraceMatchingUtil.isLBraceToken(iterator, chars, fileType)) { + else if (!BraceMatchingUtil.isRBraceToken(iterator, chars, fileType) && !BraceMatchingUtil.isLBraceToken(iterator, chars, fileType)) { offset--; if (offset >= 0) { @@ -286,17 +284,14 @@ public class BraceHighlightingHandler { boolean searchForward = c != '\n'; // Try to find matched brace backwards. - if (offset >= originalOffset && (c == ' ' || c == '\t' || c == '\n')) { - int backwardNonWsOffset = CharArrayUtil.shiftBackward(chars, offset - 1, "\t "); - if (backwardNonWsOffset >= 0) { - iterator = highlighter.createIterator(backwardNonWsOffset); - FileType newFileType = getFileTypeByIterator(iterator); - if (BraceMatchingUtil.isLBraceToken(iterator, chars, newFileType) || - BraceMatchingUtil.isRBraceToken(iterator, chars, newFileType)) { - offset = backwardNonWsOffset; - searchForward = false; - doHighlight(backwardNonWsOffset, originalOffset, newFileType); - } + if (offset >= originalOffset) { + iterator = highlighter.createIterator(offset - 1); + FileType newFileType = getFileTypeByIterator(iterator); + if (BraceMatchingUtil.isLBraceToken(iterator, chars, newFileType) || + BraceMatchingUtil.isRBraceToken(iterator, chars, newFileType)) { + offset--; + searchForward = false; + doHighlight(offset, originalOffset, newFileType); } } @@ -446,7 +441,7 @@ public class BraceHighlightingHandler { RangeHighlighter rbraceHighlighter = myEditor.getMarkupModel().addRangeHighlighter( - braceRange.getStartOffset(), braceRange.getEndOffset(), HighlighterLayer.LAST + 1, attributes, HighlighterTargetArea.EXACT_RANGE); + braceRange.getStartOffset(), braceRange.getEndOffset(), LAYER, attributes, HighlighterTargetArea.EXACT_RANGE); rbraceHighlighter.setGreedyToLeft(false); rbraceHighlighter.setGreedyToRight(false); registerHighlighter(rbraceHighlighter); diff --git a/platform/lang-impl/testData/editor/braceHighlighter/afterLBrace.java b/platform/lang-impl/testData/editor/braceHighlighter/afterLBrace.java new file mode 100644 index 000000000000..9d6d7d1362f2 --- /dev/null +++ b/platform/lang-impl/testData/editor/braceHighlighter/afterLBrace.java @@ -0,0 +1,3 @@ +class Foo { + int field; +} \ No newline at end of file diff --git a/platform/lang-impl/testData/editor/braceHighlighter/afterRBrace.java b/platform/lang-impl/testData/editor/braceHighlighter/afterRBrace.java new file mode 100644 index 000000000000..e7ae650c523f --- /dev/null +++ b/platform/lang-impl/testData/editor/braceHighlighter/afterRBrace.java @@ -0,0 +1,3 @@ +class Foo { + int field; +} \ No newline at end of file diff --git a/platform/lang-impl/testData/editor/braceHighlighter/beforeLBrace.java b/platform/lang-impl/testData/editor/braceHighlighter/beforeLBrace.java new file mode 100644 index 000000000000..f3b4a85d28a8 --- /dev/null +++ b/platform/lang-impl/testData/editor/braceHighlighter/beforeLBrace.java @@ -0,0 +1,3 @@ +class Foo { + int field; +} \ No newline at end of file diff --git a/platform/lang-impl/testData/editor/braceHighlighter/beforeRBrace.java b/platform/lang-impl/testData/editor/braceHighlighter/beforeRBrace.java new file mode 100644 index 000000000000..9e5dd4731bac --- /dev/null +++ b/platform/lang-impl/testData/editor/braceHighlighter/beforeRBrace.java @@ -0,0 +1,3 @@ +class Foo { + int field; +} \ No newline at end of file diff --git a/platform/lang-impl/testData/editor/braceHighlighter/doubleAfterSecond.java b/platform/lang-impl/testData/editor/braceHighlighter/doubleAfterSecond.java new file mode 100644 index 000000000000..58fc206522c4 --- /dev/null +++ b/platform/lang-impl/testData/editor/braceHighlighter/doubleAfterSecond.java @@ -0,0 +1,5 @@ +class Foo { + void foo() { + call({}); + } +} \ No newline at end of file diff --git a/platform/lang-impl/testData/editor/braceHighlighter/doubleBeforeFirst.java b/platform/lang-impl/testData/editor/braceHighlighter/doubleBeforeFirst.java new file mode 100644 index 000000000000..ddb66abb8d3f --- /dev/null +++ b/platform/lang-impl/testData/editor/braceHighlighter/doubleBeforeFirst.java @@ -0,0 +1,5 @@ +class Foo { + void foo() { + call({}); + } +} \ No newline at end of file diff --git a/platform/lang-impl/testData/editor/braceHighlighter/doubleMiddle.java b/platform/lang-impl/testData/editor/braceHighlighter/doubleMiddle.java new file mode 100644 index 000000000000..c243586cf624 --- /dev/null +++ b/platform/lang-impl/testData/editor/braceHighlighter/doubleMiddle.java @@ -0,0 +1,5 @@ +class Foo { + void foo() { + call({}); + } +} \ No newline at end of file diff --git a/platform/lang-impl/testData/editor/braceHighlighter/inTheMiddle.java b/platform/lang-impl/testData/editor/braceHighlighter/inTheMiddle.java new file mode 100644 index 000000000000..34099fd2a4d2 --- /dev/null +++ b/platform/lang-impl/testData/editor/braceHighlighter/inTheMiddle.java @@ -0,0 +1,3 @@ +class Foo { + int field; +} \ No newline at end of file diff --git a/platform/lang-impl/testSources/com/intellij/codeInsight/highlighting/BraceHighlightingHandlerTest.java b/platform/lang-impl/testSources/com/intellij/codeInsight/highlighting/BraceHighlightingHandlerTest.java new file mode 100644 index 000000000000..c00710a9ae02 --- /dev/null +++ b/platform/lang-impl/testSources/com/intellij/codeInsight/highlighting/BraceHighlightingHandlerTest.java @@ -0,0 +1,61 @@ +// 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.codeInsight.highlighting; + +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.testFramework.FileBasedTestCaseHelper; +import com.intellij.testFramework.LightPlatformCodeInsightTestCase; +import com.intellij.testFramework.TestDataPath; +import com.intellij.util.Alarm; +import org.jetbrains.annotations.Nullable; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static com.intellij.testFramework.EdtTestUtil.runInEdtAndWait; + +@RunWith(com.intellij.testFramework.Parameterized.class) +@TestDataPath("/testData/../../../platform/lang-impl/testData/editor/braceHighlighter/") +public class BraceHighlightingHandlerTest extends LightPlatformCodeInsightTestCase implements FileBasedTestCaseHelper { + private static final String PAIR_MARKER = ""; + + @Test + public void testAction() { + runInEdtAndWait(() -> { + configureByFile(myFileSuffix); + Editor editor = getEditor(); + final Document document = editor.getDocument(); + int second = document.getText().indexOf(PAIR_MARKER); + if (second >= 0) { + WriteCommandAction.runWriteCommandAction(null, () -> document.replaceString(second, second + PAIR_MARKER.length(), "")); + } + int first; + int firstBraceCandidate = document.getText().indexOf(PAIR_MARKER); + if (firstBraceCandidate >= 0) { + WriteCommandAction.runWriteCommandAction(null, () -> document.replaceString(firstBraceCandidate, firstBraceCandidate + PAIR_MARKER.length(), "")); + first = firstBraceCandidate; + } else { + first = editor.getCaretModel().getOffset(); + } + + new BraceHighlightingHandler(getProject(), (EditorEx)editor, new Alarm(), getFile()).updateBraces(); + RangeHighlighter[] highlighters = editor.getMarkupModel().getAllHighlighters(); + int braceHighlighters = 0; + for (RangeHighlighter highlighter : highlighters) { + if (highlighter.getLayer() == BraceHighlightingHandler.LAYER) { + braceHighlighters++; + assertTrue(first == highlighter.getStartOffset() || second == highlighter.getStartOffset()); + } + } + assertEquals(second >= 0 ? 2 : 0, braceHighlighters); + }); + } + + @Nullable + @Override + public String getFileSuffix(String fileName) { + return fileName.contains("-after.") ? null : fileName; + } +} \ No newline at end of file