IDEA-69653 Complete Current Statement: Correct completion of 'init' section of 'for' statement

'Space after semicolon' code style property value is preserved during smart completion now
This commit is contained in:
Denis Zhdanov
2011-05-16 12:15:11 +04:00
parent bae2266f33
commit dd5c166257
8 changed files with 93 additions and 7 deletions
@@ -15,10 +15,15 @@
*/
package com.intellij.codeInsight.editorActions.smartEnter;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
/**
* {@link Fixer} that handles use-cases like below:
@@ -67,12 +72,42 @@ public class ForStatementFixer implements Fixer {
final PsiExpression condition = forStatement.getCondition();
if (condition == null) {
processor.registerUnresolvedError(initialization.getTextRange().getEndOffset());
registerErrorOffset(editor, processor, initialization, forStatement);
return;
}
if (forStatement.getUpdate() == null) {
processor.registerUnresolvedError(condition.getTextRange().getEndOffset());
registerErrorOffset(editor, processor, condition, forStatement);
}
}
/**
* {@link JavaSmartEnterProcessor#registerUnresolvedError(int) registers target offset} taking care of the situation when
* current code style implies white space after 'for' part's semicolon.
*
* @param editor target editor
* @param processor target smart enter processor
* @param lastValidForPart last valid element of the target 'for' loop
* @param forStatement PSI element for the target 'for' loop
*/
private static void registerErrorOffset(@NotNull Editor editor, @NotNull JavaSmartEnterProcessor processor,
@NotNull PsiElement lastValidForPart, @NotNull PsiForStatement forStatement)
{
final Project project = editor.getProject();
int offset = lastValidForPart.getTextRange().getEndOffset();
if (project != null && CodeStyleSettingsManager.getSettings(project).SPACE_AFTER_COMMA) {
for (PsiElement element = lastValidForPart.getNextSibling();
element != null && element != forStatement.getRParenth() && element.getParent() == forStatement;
element = element.getNextSibling())
{
final ASTNode node = element.getNode();
if (node != null && ElementType.WHITE_SPACE_BIT_SET.contains(node.getElementType()) && element.getTextLength() > 0) {
offset++;
break;
}
}
}
processor.registerUnresolvedError(offset);
}
}
@@ -18,8 +18,10 @@ package com.intellij.codeInsight.editorActions.smartEnter;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.util.PsiTreeUtil;
@@ -64,7 +66,7 @@ public class SemicolonFixer implements Fixer {
int tailLength = 0;
ASTNode leaf = TreeUtil.findLastLeaf(psiElement.getNode());
while (ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(leaf.getElementType())) {
while (leaf != null && ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(leaf.getElementType())) {
tailLength += leaf.getTextLength();
leaf = TreeUtil.prevLeaf(leaf);
}
@@ -73,6 +75,9 @@ public class SemicolonFixer implements Fixer {
text = text.substring(0, text.length() - tailLength);
}
if (leaf == null) {
return;
}
int insertionOffset = leaf.getTextRange().getEndOffset();
Document doc = editor.getDocument();
if (psiElement instanceof PsiField && ((PsiField) psiElement).hasModifierProperty(PsiModifier.ABSTRACT)) {
@@ -83,10 +88,20 @@ public class SemicolonFixer implements Fixer {
if (!StringUtil.endsWithChar(text, ';')) {
final PsiElement parent = psiElement.getParent();
if (parent instanceof PsiForStatement && ((PsiForStatement) parent).getUpdate() == psiElement) {
return;
String toInsert = ";";
if (parent instanceof PsiForStatement) {
if (((PsiForStatement)parent).getUpdate() == psiElement) {
return;
}
else {
final Project project = editor.getProject();
if (project != null && CodeStyleSettingsManager.getSettings(project).SPACE_AFTER_SEMICOLON) {
toInsert += " ";
}
}
}
doc.insertString(insertionOffset, ";");
doc.insertString(insertionOffset, toInsert);
}
}
}
@@ -1176,7 +1176,9 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
else {
ASTNode prev = FormattingAstUtil.getPrevNonWhiteSpaceNode(myChild2);
if (prev != null && prev.getElementType() == JavaTokenType.SEMICOLON) {
if (prev != null && (prev.getElementType() == JavaTokenType.SEMICOLON || prev == statement.getInitialization()
|| prev == statement.getCondition()))
{
// Handle empty 'condition' section.
createSpaceInCode(mySettings.SPACE_AFTER_SEMICOLON);
}
@@ -0,0 +1,6 @@
public class Foo {
void test(int i) {
for (int j = 1<caret>) {
}
}
}
@@ -0,0 +1,6 @@
public class Foo {
void test(int i) {
for (int j = 1;<caret>) {
}
}
}
@@ -0,0 +1,6 @@
public class Foo {
void test(int i) {
for (int j = 1<caret>) {
}
}
}
@@ -0,0 +1,6 @@
public class Foo {
void test(int i) {
for (int j = 1; <caret>) {
}
}
}
@@ -203,6 +203,16 @@ public class CompleteStatementTest extends EditorActionTestCase {
public void testNoUnnecessaryEmptyLineAtCodeBlock() throws Exception { doTest(); }
public void testForStatementGeneration() throws Exception { doTest(); }
public void testSpaceAfterSemicolon() throws Exception {
CodeStyleSettingsManager.getSettings(getProject()).SPACE_AFTER_SEMICOLON = true;
doTest();
}
public void testNoSpaceAfterSemicolon() throws Exception {
CodeStyleSettingsManager.getSettings(getProject()).SPACE_AFTER_SEMICOLON = false;
doTest();
}
private void doTestBracesNextLineStyle() throws Exception {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());