highlight sibling continue/break (IDEA-117109)

This commit is contained in:
Anna Kozlova
2018-06-15 12:08:04 +03:00
parent da3832e331
commit b5a41bc285
3 changed files with 40 additions and 4 deletions
@@ -3,8 +3,12 @@ package com.intellij.codeInsight.highlighting;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.util.Consumer;
import com.intellij.util.containers.IntArrayList;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -33,20 +37,46 @@ public class HighlightBreakOutsHandler extends HighlightUsagesHandlerBase<PsiEle
PsiStatement statement = ((PsiContinueStatement)parent).findContinuedStatement();
if (statement instanceof PsiLoopStatement) {
highlightLoopDeclaration((PsiLoopStatement)statement);
PsiStatement body = ((PsiLoopStatement)statement).getBody();
if (body instanceof PsiBlockStatement) {
collectSiblings((PsiStatement)parent, statement, ((PsiBlockStatement)body).getCodeBlock());
}
}
}
else if (parent instanceof PsiBreakStatement) {
PsiStatement exitedStatement = ((PsiBreakStatement)parent).findExitedStatement();
if (exitedStatement instanceof PsiLoopStatement) {
highlightLoopDeclaration((PsiLoopStatement)exitedStatement);
PsiStatement body = ((PsiLoopStatement)exitedStatement).getBody();
if (body instanceof PsiBlockStatement) {
collectSiblings((PsiStatement)parent, exitedStatement, ((PsiBlockStatement)body).getCodeBlock());
}
}
else if (exitedStatement instanceof PsiSwitchStatement) {
addOccurrence(exitedStatement.getFirstChild());
collectSiblings((PsiStatement)parent, exitedStatement, exitedStatement);
}
}
addOccurrence(myTarget);
}
private void collectSiblings(PsiStatement currentStatement, PsiStatement container, @NotNull PsiElement block) {
try {
ControlFlow controlFlow =
ControlFlowFactory.getInstance(block.getProject()).getControlFlow(block, new LocalsControlFlowPolicy(block), false, false);
Collection<PsiStatement> statements = ControlFlowUtil
.findExitPointsAndStatements(controlFlow, 0, controlFlow.getSize(), new IntArrayList(), ControlFlowUtil.DEFAULT_EXIT_STATEMENTS_CLASSES);
for (PsiStatement psiStatement: statements) {
if (currentStatement == psiStatement) continue;
if (psiStatement instanceof PsiContinueStatement && ((PsiContinueStatement)psiStatement).findContinuedStatement() == container ||
psiStatement instanceof PsiBreakStatement && ((PsiBreakStatement)psiStatement).findExitedStatement() == container) {
addOccurrence(psiStatement.getFirstChild());
}
}
}
catch (AnalysisCanceledException ignored) { }
}
private void highlightLoopDeclaration(PsiLoopStatement statement) {
if (statement instanceof PsiDoWhileStatement) {
@@ -1,7 +1,13 @@
class Main {
public static void main(String[] args) {
do {
if (true) br<caret>eak;
} while (args != null);
lbl:
while (true) {
int i = 0;
do {
if (i++ > 7) br<caret>eak;
if (i % 2 == 0) continue;
if (--i > 8) continue lbl;
} while (args != null);
}
}
}
@@ -108,7 +108,7 @@ class HighlightUsagesHandlerTest extends LightCodeInsightFixtureTestCase {
void testBreakInDoWhile() {
configureFile()
ctrlShiftF7()
assertRangeText 'break', 'while'
assertRangeText 'break', 'continue', 'while'
checkUnselect()
}