IDEA-68563 complete current statement generates invalid cod

Corrected completion of 'return' expression inside non-void method
This commit is contained in:
Denis Zhdanov
2011-07-14 13:10:11 +04:00
parent 7e7773d3c8
commit 9ec2ec69b9
5 changed files with 98 additions and 18 deletions
@@ -86,6 +86,7 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor {
}
private int myFirstErrorOffset = Integer.MAX_VALUE;
private boolean mySkipEnter;
private static final int MAX_ATTEMPTS = 20;
private static final Key<Long> SMART_ENTER_TIMESTAMP = Key.create("smartEnterOriginalTimestamp");
@@ -99,6 +100,7 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor {
try {
editor.putUserData(SMART_ENTER_TIMESTAMP, editor.getDocument().getModificationStamp());
myFirstErrorOffset = Integer.MAX_VALUE;
mySkipEnter = false;
process(project, editor, psiFile, 0);
}
catch (TooManyAttemptsException e) {
@@ -191,6 +193,10 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor {
reformat(atCaret);
commit(editor);
if (mySkipEnter) {
return;
}
atCaret = CodeInsightUtil.findElementInRange(psiFile, rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), atCaret.getClass());
for (EnterProcessor processor : ourEnterProcessors) {
if(atCaret == null){
@@ -292,6 +298,10 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor {
}
}
public void setSkipEnter(boolean skipEnter) {
mySkipEnter = skipEnter;
}
protected static void plainEnter(@NotNull final Editor editor) {
getEnterHandler().execute(editor, ((EditorEx) editor).getDataContext());
}
@@ -19,6 +19,8 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
@@ -29,31 +31,83 @@ import com.intellij.util.IncorrectOperationException;
*/
@SuppressWarnings({"HardCodedStringLiteral"})
public class MissingReturnExpressionFixer implements Fixer {
public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement)
throws IncorrectOperationException {
if (psiElement instanceof PsiReturnStatement) {
PsiReturnStatement retStatement = (PsiReturnStatement) psiElement;
PsiExpression returnValue = retStatement.getReturnValue();
if (returnValue != null &&
lineNumber(editor, editor.getCaretModel().getOffset()) == lineNumber(editor, returnValue.getTextRange().getStartOffset())) {
return;
}
public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
if (!(psiElement instanceof PsiReturnStatement)) {
return;
}
if (!PsiTreeUtil.hasErrorElements(psiElement)) {
return;
}
PsiReturnStatement retStatement = (PsiReturnStatement)psiElement;
if (fixMethodCallWithoutTrailingSemicolon(retStatement, editor, processor)) {
return;
}
PsiElement parent = PsiTreeUtil.getParentOfType(psiElement, PsiClassInitializer.class, PsiMethod.class);
if (parent instanceof PsiMethod) {
final PsiType returnType = ((PsiMethod) parent).getReturnType();
if (returnType != null && returnType != PsiType.VOID) {
final int startOffset = retStatement.getTextRange().getStartOffset();
if (returnValue != null) {
editor.getDocument().insertString(startOffset + "return".length(), ";");
}
PsiExpression returnValue = retStatement.getReturnValue();
if (returnValue != null
&& lineNumber(editor, editor.getCaretModel().getOffset()) == lineNumber(editor, returnValue.getTextRange().getStartOffset()))
{
return;
}
processor.registerUnresolvedError(startOffset + "return".length());
PsiElement parent = PsiTreeUtil.getParentOfType(psiElement, PsiClassInitializer.class, PsiMethod.class);
if (parent instanceof PsiMethod) {
final PsiType returnType = ((PsiMethod)parent).getReturnType();
if (returnType != null && returnType != PsiType.VOID) {
final int startOffset = retStatement.getTextRange().getStartOffset();
if (returnValue != null) {
editor.getDocument().insertString(startOffset + "return".length(), ";");
}
processor.registerUnresolvedError(startOffset + "return".length());
}
}
}
private static boolean fixMethodCallWithoutTrailingSemicolon(@Nullable PsiReturnStatement returnStatement, @NotNull Editor editor,
@NotNull JavaSmartEnterProcessor processor)
{
if (returnStatement == null) {
return false;
}
final PsiElement lastChild = returnStatement.getLastChild();
if (!(lastChild instanceof PsiErrorElement)) {
return false;
}
PsiElement prev = lastChild.getPrevSibling();
if (prev instanceof PsiWhiteSpace) {
prev = prev.getPrevSibling();
}
if (!(prev instanceof PsiJavaToken)) {
int offset = returnStatement.getTextRange().getEndOffset();
final PsiMethod method = PsiTreeUtil.getParentOfType(returnStatement, PsiMethod.class);
if (method != null && method.getReturnType() == PsiType.VOID) {
offset = returnStatement.getTextRange().getStartOffset() + "return".length();
}
editor.getDocument().insertString(offset, ";");
//processor.setSkipEnter(true);
return true;
}
PsiJavaToken prevToken = (PsiJavaToken)prev;
if (prevToken.getTokenType() == JavaTokenType.SEMICOLON) {
return false;
}
final int offset = returnStatement.getTextRange().getEndOffset();
editor.getDocument().insertString(offset, ";");
if (prevToken.getTokenType() == JavaTokenType.RETURN_KEYWORD) {
final PsiMethod method = PsiTreeUtil.getParentOfType(returnStatement, PsiMethod.class);
if (method != null && method.getReturnType() != PsiType.VOID) {
editor.getCaretModel().moveToOffset(offset);
processor.setSkipEnter(true);
}
}
return true;
}
private static int lineNumber(Editor editor, int offset) {
return editor.getDocument().getLineNumber(offset);
}
@@ -0,0 +1,7 @@
public class Foo {
public String foo() {
return String.valueOf(
1<caret>
)
}
}
@@ -0,0 +1,7 @@
public class Foo {
public String foo() {
return String.valueOf(
1
);<caret>
}
}
@@ -228,6 +228,8 @@ public class CompleteStatementTest extends EditorActionTestCase {
public void testLastJavadocParameterDescriptionToReturn() throws Exception { doTest(); }
public void testCompleteMethodCallAtReturn() throws Exception { doTest(); }
private void doTestBracesNextLineStyle() throws Exception {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;