IDEA-77486 Java smart complete statement: Don't leave code block on non-final statement

This commit is contained in:
Denis.Zhdanov
2011-11-23 18:57:35 +03:00
parent 63e5d06ecf
commit 8c2d94cd56
11 changed files with 141 additions and 74 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,8 +56,8 @@ public class LeaveCodeBlockEnterProcessor implements EnterProcessor {
if (node != null && CONTROL_FLOW_ELEMENT_TYPES.contains(node.getElementType())) {
return false;
}
boolean leaveCodeBlock = isControlFlowBreak(psiElement) || isValidStatementInsideControlFlowOperator(psiElement, isModified);
boolean leaveCodeBlock = isControlFlowBreak(psiElement);
if (!leaveCodeBlock) {
return false;
}
@@ -110,26 +110,4 @@ public class LeaveCodeBlockEnterProcessor implements EnterProcessor {
private static boolean isControlFlowBreak(@Nullable PsiElement element) {
return element instanceof PsiReturnStatement || element instanceof PsiThrowStatement;
}
private static boolean isValidStatementInsideControlFlowOperator(final @Nullable PsiElement element, boolean modified) {
if (modified || element == null || PsiTreeUtil.hasErrorElements(element)) {
return false;
}
for (PsiElement e = element; e != null; e = e.getParent()) {
final ASTNode node = e.getNode();
if (node == null) {
return false;
}
if (node.getElementType() == JavaElementType.METHOD) {
return false;
}
if (CONTROL_FLOW_ELEMENT_TYPES.contains(node.getElementType())) {
return true;
}
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ import org.jetbrains.annotations.Nullable;
public class PlainEnterProcessor implements EnterProcessor {
public boolean doEnter(Editor editor, PsiElement psiElement, boolean isModified) {
PsiCodeBlock block = getControlStatementBlock(editor.getCaretModel().getOffset(), psiElement);
if (processExistingBlankLine(editor, block)) {
if (processExistingBlankLine(editor, block, psiElement)) {
return true;
}
EditorActionHandler enterHandler = getEnterHandler(IdeActions.ACTION_EDITOR_START_NEW_LINE);
@@ -114,30 +114,42 @@ public class PlainEnterProcessor implements EnterProcessor {
*
* @param editor target editor
* @param codeBlock target code block to which new empty line is going to be inserted
* @param element target element under caret
* @return <code>true</code> if it was found out that the given code block starts with the empty line and caret
* is pointed to correct position there, i.e. no additional processing is required;
* <code>false</code> otherwise
*/
private static boolean processExistingBlankLine(@NotNull Editor editor, @Nullable PsiCodeBlock codeBlock) {
private static boolean processExistingBlankLine(@NotNull Editor editor, @Nullable PsiCodeBlock codeBlock, @Nullable PsiElement element) {
PsiWhiteSpace whiteSpace = null;
if (codeBlock == null) {
return false;
if (element != null) {
final PsiElement next = PsiTreeUtil.nextLeaf(element);
if (next instanceof PsiWhiteSpace) {
whiteSpace = (PsiWhiteSpace)next;
}
}
}
else {
whiteSpace = PsiTreeUtil.findChildOfType(codeBlock, PsiWhiteSpace.class);
if (whiteSpace == null) {
return false;
}
PsiElement lbraceCandidate = whiteSpace.getPrevSibling();
if (lbraceCandidate == null) {
return false;
}
ASTNode node = lbraceCandidate.getNode();
if (node == null || node.getElementType() != JavaTokenType.LBRACE) {
return false;
}
}
PsiWhiteSpace whiteSpace = PsiTreeUtil.findChildOfType(codeBlock, PsiWhiteSpace.class);
if (whiteSpace == null) {
return false;
}
PsiElement lbraceCandidate = whiteSpace.getPrevSibling();
if (lbraceCandidate == null) {
return false;
}
ASTNode node = lbraceCandidate.getNode();
if (node == null || node.getElementType() != JavaTokenType.LBRACE) {
return false;
}
final TextRange textRange = whiteSpace.getTextRange();
final Document document = editor.getDocument();
final CharSequence whiteSpaceText = document.getCharsSequence().subSequence(textRange.getStartOffset(), textRange.getEndOffset());
@@ -147,7 +159,9 @@ public class PlainEnterProcessor implements EnterProcessor {
int i = CharArrayUtil.shiftForward(whiteSpaceText, 0, " \t");
if (i >= whiteSpaceText.length() - 1) {
assert false : String.format("code block: %s, white space: %s", codeBlock.getTextRange(), whiteSpace.getTextRange());
assert false : String.format("code block: %s, white space: %s",
codeBlock == null ? "undefined" : codeBlock.getTextRange(),
whiteSpace.getTextRange());
return false;
}

View File

@@ -1,7 +0,0 @@
public class Foo {
void test(int i) {
if (i > 1) {
i <caret>= 1;
}
}
}

View File

@@ -1,8 +0,0 @@
public class Foo {
void test(int i) {
while (i-- > 1) {
i <caret>= 1;
}
}
}

View File

@@ -1,8 +0,0 @@
public class Foo {
void test(int i) {
while (i-- > 1) {
i = 1;
}
<caret>
}
}

View File

@@ -1,8 +0,0 @@
public class Foo {
void test(int i) {
if (i > 1) {
i = 1;
}
<caret>
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Foo {
void test(int i) {
if (i > 1) {
i <caret>= 1;
}
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Foo {
void test(int i) {
while (i-- > 1) {
i <caret>= 1;
}
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Foo {
void test(int i) {
while (i-- > 1) {
i = 1;
<caret>
}
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Foo {
void test(int i) {
if (i > 1) {
i = 1;
<caret>
}
}
}

View File

@@ -1,3 +1,18 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight;
import com.intellij.JavaTestUtil;
@@ -216,9 +231,9 @@ public class CompleteStatementTest extends EditorActionTestCase {
public void testForUpdateGeneration() throws Exception { doTest(); }
public void testLeaveValidCodeBlock() throws Exception { doTest(); }
public void testValidCodeBlock() throws Exception { doTest(); }
public void testLeaveValidCodeBlockWithEmptyLineAfterIt() throws Exception { doTest(); }
public void testValidCodeBlockWithEmptyLineAfterIt() throws Exception { doTest(); }
public void testFromJavadocParameterDescriptionEndToNextParameter() throws Exception { doTest(); }