diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java index 4fa3bb4f4eb8..6d96d2df8554 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java @@ -36,19 +36,6 @@ public class JavaAwareCompletionData extends CompletionData{ static TailType analyzeItem(final Object completion, final PsiElement position) { if(completion instanceof PsiKeyword){ final String text = ((PsiKeyword)completion).getText(); - if(PsiKeyword.BREAK.equals(text) || PsiKeyword.CONTINUE.equals(text)) { - PsiElement scope = position; - while(true){ - if (scope instanceof PsiFile || scope instanceof PsiMethod || scope instanceof PsiClassInitializer){ - return TailType.SEMICOLON; - } - - if (scope instanceof PsiLabeledStatement){ - return TailType.NONE; - } - scope = scope.getParent(); - } - } if(PsiKeyword.RETURN.equals(text)){ PsiElement scope = position; while(true){ diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index 4ec737110c59..9bd72b07cd9b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -112,6 +112,19 @@ public class JavaCompletionData extends JavaAwareCompletionData{ static final AndFilter START_SWITCH = new AndFilter(END_OF_BLOCK, new LeftNeighbour( new AndFilter(new TextFilter("{"), new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 2)))); + private static final OrFilter INSIDE_SWITCH = new OrFilter(START_SWITCH, + new AndFilter( + END_OF_BLOCK, + new NotFilter(START_SWITCH), + new OrFilter( + new ParentElementFilter(new ClassFilter(PsiSwitchLabelStatement.class)), + new LeftNeighbour(new OrFilter( + new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 2), + new AndFilter(new TextFilter(";", ":"), new ParentElementFilter( + new ClassFilter(PsiSwitchStatement.class), 3)), + new AndFilter(new TextFilter("}"), new ParentElementFilter( + new ClassFilter(PsiSwitchStatement.class), 4)) + ))))); private static final ElementPattern SUPER_OR_THIS_PATTERN = and(JavaSmartCompletionContributor.INSIDE_EXPRESSION, @@ -444,57 +457,12 @@ public class JavaCompletionData extends JavaAwareCompletionData{ } { -// break completion - final CompletionVariant variant = new CompletionVariant(new AndFilter(END_OF_BLOCK, new OrFilter( - new ScopeFilter(new ClassFilter(PsiSwitchStatement.class)), - new InsideElementFilter(new ClassFilter(PsiBlockStatement.class))))); - - variant.includeScopeClass(PsiForStatement.class, false); - variant.includeScopeClass(PsiForeachStatement.class, false); - variant.includeScopeClass(PsiWhileStatement.class, false); - variant.includeScopeClass(PsiDoWhileStatement.class, false); - variant.includeScopeClass(PsiSwitchStatement.class, false); - variant.addCompletion(PsiKeyword.BREAK); - registerVariant(variant); - } - { -// continue completion - final CompletionVariant variant = new CompletionVariant(new AndFilter(END_OF_BLOCK, new InsideElementFilter(new ClassFilter(PsiBlockStatement.class)))); - variant.includeScopeClass(PsiForeachStatement.class, false); - variant.includeScopeClass(PsiForStatement.class, false); - variant.includeScopeClass(PsiWhileStatement.class, false); - variant.includeScopeClass(PsiDoWhileStatement.class, false); - - variant.addCompletion(PsiKeyword.CONTINUE); - registerVariant(variant); - } - - { - final CompletionVariant variant = new CompletionVariant( - new AndFilter( - END_OF_BLOCK, - new NotFilter(START_SWITCH), - new OrFilter( - new ParentElementFilter(new ClassFilter(PsiSwitchLabelStatement.class)), - new LeftNeighbour(new OrFilter( - new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 2), - new AndFilter(new TextFilter(";", ":"),new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 3)), - new AndFilter(new TextFilter("}"), new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 4)) - ))))); - variant.includeScopeClass(PsiElement.class, false); - variant.addCompletion(PsiKeyword.CASE, TailType.SPACE); - variant.addCompletion(PsiKeyword.DEFAULT, TailType.CASE_COLON); - registerVariant(variant); - } - - { - final CompletionVariant variant = new CompletionVariant(START_SWITCH); + final CompletionVariant variant = new CompletionVariant(INSIDE_SWITCH); variant.includeScopeClass(PsiElement.class, true); variant.addCompletion(PsiKeyword.CASE, TailType.SPACE); variant.addCompletion(PsiKeyword.DEFAULT, TailType.CASE_COLON); registerVariant(variant); } - } private static void addPrimitiveTypes(CompletionVariant variant){ @@ -535,6 +503,10 @@ public class JavaCompletionData extends JavaAwareCompletionData{ result.addElement(createKeyword(position, PsiKeyword.FINAL)); } } + + if (isStatementPosition(position) && !INSIDE_SWITCH.isAcceptable(position, position)) { + addBreakContinue(result, position); + } if (SUPER_OR_THIS_PATTERN.accepts(position)) { if (!AFTER_DOT.accepts(position) || isInsideQualifierClass(position)) { @@ -626,6 +598,43 @@ public class JavaCompletionData extends JavaAwareCompletionData{ } } + private static void addBreakContinue(CompletionResultSet result, PsiElement position) { + PsiLoopStatement loop = PsiTreeUtil.getParentOfType(position, PsiLoopStatement.class); + + LookupElement br = createKeyword(position, PsiKeyword.BREAK); + LookupElement cont = createKeyword(position, PsiKeyword.CONTINUE); + if (!psiElement().insideSequence(true, psiElement(PsiLabeledStatement.class), + or(psiElement(PsiFile.class), psiElement(PsiMethod.class), + psiElement(PsiClassInitializer.class))).accepts(position)) { + br = TailTypeDecorator.withTail(br, TailType.SEMICOLON); + cont = TailTypeDecorator.withTail(cont, TailType.SEMICOLON); + } + + if (loop != null && new InsideElementFilter(new ClassFilter(PsiStatement.class)).isAcceptable(position, loop)) { + result.addElement(br); + result.addElement(cont); + } + if (psiElement().inside(PsiSwitchStatement.class).accepts(position)) { + result.addElement(br); + } + } + + private static boolean isStatementPosition(PsiElement position) { + if (END_OF_BLOCK.isAcceptable(position, position)) { + return true; + } + + if (psiElement().withParents(PsiReferenceExpression.class, PsiExpressionStatement.class, PsiIfStatement.class).accepts(position)) { + PsiElement stmt = position.getParent().getParent(); + PsiIfStatement ifStatement = (PsiIfStatement)stmt.getParent(); + if (ifStatement.getElseBranch() == stmt || ifStatement.getThenBranch() == stmt) { + return true; + } + } + + return false; + } + private static LookupElement createKeyword(PsiElement position, String keyword) { return BasicExpressionCompletionContributor.createKeywordLookupItem(position, keyword); } diff --git a/java/java-tests/testData/codeInsight/completion/normal/BreakInIfCondition.java b/java/java-tests/testData/codeInsight/completion/normal/BreakInIfCondition.java new file mode 100644 index 000000000000..b1cdf5040de1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/BreakInIfCondition.java @@ -0,0 +1,6 @@ +public class Main { + { + while(true) + if (cond) br + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/BreakInIfCondition_after.java b/java/java-tests/testData/codeInsight/completion/normal/BreakInIfCondition_after.java new file mode 100644 index 000000000000..18da0c31aaca --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/BreakInIfCondition_after.java @@ -0,0 +1,6 @@ +public class Main { + { + while(true) + if (cond) break; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 6368592acdef..440fc8b366ba 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -441,6 +441,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { doTest(); } + public void testBreakInIfCondition() throws Throwable { doTest(); } + public void testNoThisInComment() throws Throwable { doAntiTest() } public void testLastExpressionInFor() throws Throwable { doTest(); }