extend insert declaration/add cast intentions for the one line ref statement (IDEA-90448)

This commit is contained in:
Anna Kozlova
2012-08-24 12:26:41 +04:00
parent dacf72eac2
commit 899e8dccfa
8 changed files with 134 additions and 16 deletions

View File

@@ -22,6 +22,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,15 +51,14 @@ public class CreateCastExpressionFromInstanceofAction extends CreateLocalVarFrom
PsiInstanceOfExpression instanceOfExpression = getInstanceOfExpressionAtCaret(editor, file);
assert instanceOfExpression.getContainingFile() == file : instanceOfExpression.getContainingFile() + "; file="+file;
PsiElement decl = createAndInsertCast(instanceOfExpression);
PsiElement decl = createAndInsertCast(instanceOfExpression, editor, file);
if (decl == null) return;
decl = CodeStyleManager.getInstance(project).reformat(decl);
CaretModel caretModel = editor.getCaretModel();
caretModel.moveToOffset(decl.getTextRange().getEndOffset());
decl = CodeStyleManager.getInstance(project).reformat(CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(decl));
editor.getCaretModel().moveToOffset(decl.getTextRange().getEndOffset());
}
@Nullable
private static PsiElement createAndInsertCast(final PsiInstanceOfExpression instanceOfExpression) throws IncorrectOperationException {
private static PsiElement createAndInsertCast(final PsiInstanceOfExpression instanceOfExpression, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiElementFactory factory = JavaPsiFacade.getInstance(instanceOfExpression.getProject()).getElementFactory();
PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText("((a)b)", instanceOfExpression);
@@ -68,8 +68,13 @@ public class CreateCastExpressionFromInstanceofAction extends CreateLocalVarFrom
cast.getCastType().replace(factory.createTypeElement(castType));
cast.getOperand().replace(instanceOfExpression.getOperand());
PsiElement element = insertAtAnchor(instanceOfExpression, statement);
return CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(element);
final PsiStatement statementInside = isNegated(instanceOfExpression) ? null : getExpressionStatementInside(file, editor);
if (statementInside != null) {
return statementInside.replace(statement);
}
else {
return insertAtAnchor(instanceOfExpression, statement);
}
}
@Override

View File

@@ -140,7 +140,7 @@ public class CreateLocalVarFromInstanceofAction extends BaseIntentionAction {
PsiStatement statement,
PsiExpression condition) {
if (condition instanceof PsiInstanceOfExpression) {
if (atSameLine(condition, editor) || insideEmptyBlockOfStatement(statement, element)) {
if (atSameLine(condition, editor) || insideEmptyBlockOrRef(statement, element, (PsiInstanceOfExpression)condition)) {
return (PsiInstanceOfExpression)condition;
}
} else if (condition instanceof PsiPolyadicExpression) {
@@ -156,7 +156,7 @@ public class CreateLocalVarFromInstanceofAction extends BaseIntentionAction {
expr = (PsiInstanceOfExpression)operand;
}
}
if (expr != null && insideEmptyBlockOfStatement(statement, element)) {
if (expr != null && insideEmptyBlockOrRef(statement, element, expr)) {
return expr;
}
}
@@ -164,9 +164,29 @@ public class CreateLocalVarFromInstanceofAction extends BaseIntentionAction {
return null;
}
private static boolean insideEmptyBlockOfStatement(PsiStatement stmt, PsiElement elementAtCaret) {
private static boolean insideEmptyBlockOrRef(PsiStatement stmt, PsiElement elementAtCaret, PsiInstanceOfExpression instanceOfExpression) {
PsiBlockStatement block = PsiTreeUtil.getParentOfType(elementAtCaret, PsiBlockStatement.class);
return block != null && block.getParent() == stmt && block.getCodeBlock().getStatements().length == 0;
if (block != null && block.getParent() == stmt) {
final PsiStatement[] statements = block.getCodeBlock().getStatements();
if (statements.length == 0) {
return true;
}
if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
return replaceReference(instanceOfExpression, (PsiExpressionStatement)statements[0]);
}
}
return false;
}
private static boolean replaceReference(PsiInstanceOfExpression instanceOfExpression, PsiExpressionStatement statement) {
if (isNegated(instanceOfExpression)) return false;
final PsiExpression expression = statement.getExpression();
final PsiExpression operand = instanceOfExpression.getOperand();
if (operand instanceof PsiReferenceExpression && expression instanceof PsiReferenceExpression &&
((PsiReferenceExpression)operand).resolve() == ((PsiReferenceExpression)expression).resolve()){
return true;
}
return false;
}
private static boolean atSameLine(final PsiExpression condition, final Editor editor) {
@@ -181,8 +201,10 @@ public class CreateLocalVarFromInstanceofAction extends BaseIntentionAction {
PsiInstanceOfExpression instanceOfExpression = getInstanceOfExpressionAtCaret(editor, file);
assert instanceOfExpression.getContainingFile() == file : instanceOfExpression.getContainingFile() + "; file="+file;
try {
final PsiDeclarationStatement decl = createLocalVariableDeclaration(instanceOfExpression);
final PsiStatement statementInside = isNegated(instanceOfExpression) ? null : getExpressionStatementInside(file, editor);
PsiDeclarationStatement decl = createLocalVariableDeclaration(instanceOfExpression, statementInside);
if (decl == null) return;
decl = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(decl);
PsiLocalVariable localVariable = (PsiLocalVariable)decl.getDeclaredElements()[0];
TemplateBuilderImpl builder = new TemplateBuilderImpl(localVariable);
@@ -220,7 +242,40 @@ public class CreateLocalVarFromInstanceofAction extends BaseIntentionAction {
}
@Nullable
private static PsiDeclarationStatement createLocalVariableDeclaration(final PsiInstanceOfExpression instanceOfExpression) throws IncorrectOperationException {
protected static PsiStatement getExpressionStatementInside(PsiFile file, Editor editor) {
PsiElement elementAt = file.findElementAt(editor.getCaretModel().getOffset());
PsiBlockStatement blockStatement = PsiTreeUtil.getParentOfType(elementAt, PsiBlockStatement.class);
if (blockStatement == null) {
final PsiIfStatement ifStm = PsiTreeUtil.getParentOfType(elementAt, PsiIfStatement.class);
if (ifStm != null) {
final PsiStatement thenBranch = ifStm.getThenBranch();
if (thenBranch instanceof PsiBlockStatement) {
blockStatement = (PsiBlockStatement)thenBranch;
}
} else {
final PsiWhileStatement whileStatement = PsiTreeUtil.getParentOfType(elementAt, PsiWhileStatement.class);
if (whileStatement != null) {
final PsiStatement body = whileStatement.getBody();
if (body instanceof PsiBlockStatement) {
blockStatement = (PsiBlockStatement)body;
}
}
}
}
if (blockStatement != null) {
final PsiStatement[] statements = blockStatement.getCodeBlock().getStatements();
if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
return statements[0];
}
}
return null;
}
@Nullable
private static PsiDeclarationStatement createLocalVariableDeclaration(final PsiInstanceOfExpression instanceOfExpression,
final PsiStatement statementInside) throws IncorrectOperationException {
PsiElementFactory factory = JavaPsiFacade.getInstance(instanceOfExpression.getProject()).getElementFactory();
PsiTypeCastExpression cast = (PsiTypeCastExpression)factory.createExpressionFromText("(a)b", instanceOfExpression);
PsiType castType = instanceOfExpression.getCheckType().getType();
@@ -236,8 +291,11 @@ public class CreateLocalVarFromInstanceofAction extends BaseIntentionAction {
LOG.assertTrue(modifierList != null);
modifierList.setModifierProperty(PsiModifier.FINAL, createFinals.booleanValue());
}
PsiDeclarationStatement element = (PsiDeclarationStatement)insertAtAnchor(instanceOfExpression, decl);
return CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(element);
if (statementInside != null) {
return (PsiDeclarationStatement)statementInside.replace(decl);
} else {
return (PsiDeclarationStatement)insertAtAnchor(instanceOfExpression, decl);
}
}
@Nullable
@@ -319,7 +377,7 @@ public class CreateLocalVarFromInstanceofAction extends BaseIntentionAction {
end.getTextRange().getStartOffset());
}
private static boolean isNegated(final PsiInstanceOfExpression instanceOfExpression) {
protected static boolean isNegated(final PsiInstanceOfExpression instanceOfExpression) {
PsiElement element = instanceOfExpression.getParent();
while (element instanceof PsiParenthesizedExpression) {
element = element.getParent();

View File

@@ -0,0 +1,9 @@
// "Cast to 'Runnable'" "true"
class C {
void f(Object o) {
if (o instanceof Runnable) {
((Runnable) o)<caret>
}
}
}

View File

@@ -0,0 +1,9 @@
// "Cast to 'Runnable'" "false"
class C {
void f(Object o) {
if (!(o instanceof Runnable)) {
o<caret>
}
}
}

View File

@@ -0,0 +1,9 @@
// "Cast to 'Runnable'" "true"
class C {
void f(Object o) {
if (o instanceof Runnable) {
o<caret>
}
}
}

View File

@@ -0,0 +1,10 @@
// "Insert '(Runnable)o' declaration" "true"
class C {
void f(Object o) {
if (o instanceof Runnable) {
Runnable runnable = (Runnable) o;
<caret>
}
}
}

View File

@@ -0,0 +1,9 @@
// "Insert '(Runnable)o' declaration" "false"
class C {
void f(Object o) {
if (!(o instanceof Runnable)) {
o<caret>
}
}
}

View File

@@ -0,0 +1,9 @@
// "Insert '(Runnable)o' declaration" "true"
class C {
void f(Object o) {
if (o instanceof Runnable) {
o<caret>
}
}
}