inline parameter: allow to inline as local for methods with usages (IDEA-65536) ; respect write access for parameters with constant values ( IDEA-65535)

This commit is contained in:
anna
2011-02-16 09:48:39 +01:00
parent 87e7f6aa02
commit 27ec83e3d7
6 changed files with 105 additions and 24 deletions
@@ -251,7 +251,8 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor
initializer.replace(localVarInitializer);
final PsiCodeBlock body = myMethod.getBody();
if (body != null) {
body.addAfter(localDeclaration, body.getLBrace());
PsiElement anchor = findAnchorForLocalVariableDeclaration(body);
body.addAfter(localDeclaration, anchor);
}
} else {
for (PsiJavaCodeReferenceElement paramRef : paramRefsToInline) {
@@ -280,6 +281,24 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor
}
}
@Nullable
private PsiElement findAnchorForLocalVariableDeclaration(PsiCodeBlock body) {
PsiElement anchor = body.getLBrace();
if (myMethod.isConstructor()) {
final PsiStatement[] statements = body.getStatements();
if (statements.length > 0 && statements[0] instanceof PsiExpressionStatement) {
final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
if (expression instanceof PsiMethodCallExpression) {
final String referenceName = ((PsiMethodCallExpression)expression).getMethodExpression().getReferenceName();
if (PsiKeyword.SUPER.equals(referenceName) || PsiKeyword.THIS.equals(referenceName)) {
anchor = statements[0];
}
}
}
}
return anchor;
}
private static class LocalReplacementUsageInfo extends UsageInfo {
private final PsiElement myReplacement;
private final PsiVariable myVariable;
@@ -108,35 +108,35 @@ public class InlineParameterHandler extends JavaInlineActionHandler {
return true;
}
});
if (occurrences.isEmpty()) {
final int offset = editor.getCaretModel().getOffset();
final PsiElement refExpr = psiElement.getContainingFile().findElementAt(offset);
final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(refExpr, PsiCodeBlock.class);
if (codeBlock != null) {
final PsiElement[] defs = DefUseUtil.getDefs(codeBlock, psiParameter, refExpr);
if (defs.length == 1) {
final PsiElement def = defs[0];
if (def instanceof PsiReferenceExpression && PsiUtil.isOnAssignmentLeftHand((PsiExpression)def)) {
final PsiExpression rExpr = ((PsiAssignmentExpression)def.getParent()).getRExpression();
if (rExpr != null) {
final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, psiParameter, refExpr);
final int offset = editor.getCaretModel().getOffset();
final PsiElement refExpr = psiElement.getContainingFile().findElementAt(offset);
final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(refExpr, PsiCodeBlock.class);
if (codeBlock != null) {
final PsiElement[] defs = DefUseUtil.getDefs(codeBlock, psiParameter, refExpr);
if (defs.length == 1) {
final PsiElement def = defs[0];
if (def instanceof PsiReferenceExpression && PsiUtil.isOnAssignmentLeftHand((PsiExpression)def)) {
final PsiExpression rExpr = ((PsiAssignmentExpression)def.getParent()).getRExpression();
if (rExpr != null) {
final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, psiParameter, refExpr);
if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs) == null) {
new WriteCommandAction(project) {
@Override
protected void run(Result result) throws Throwable {
for (final PsiElement ref : refs) {
InlineUtil.inlineVariable(psiParameter, rExpr, (PsiJavaCodeReferenceElement)ref);
}
def.getParent().delete();
if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs) == null) {
new WriteCommandAction(project) {
@Override
protected void run(Result result) throws Throwable {
for (final PsiElement ref : refs) {
InlineUtil.inlineVariable(psiParameter, rExpr, (PsiJavaCodeReferenceElement)ref);
}
}.execute();
return;
}
def.getParent().delete();
}
}.execute();
return;
}
}
}
}
}
if (occurrences.isEmpty()) {
CommonRefactoringUtil
.showErrorHint(project, editor, "Method has no usages", RefactoringBundle.message("inline.parameter.refactoring"), null);
return;
@@ -182,6 +182,14 @@ public class InlineParameterHandler extends JavaInlineActionHandler {
return;
}
for (PsiReference psiReference : ReferencesSearch.search(psiParameter)) {
final PsiElement element = psiReference.getElement();
if (element instanceof PsiExpression && PsiUtil.isAccessedForWriting((PsiExpression)element)) {
CommonRefactoringUtil.showErrorHint(project, editor, "Inline parameter which has write usages is not supported", RefactoringBundle.message("inline.parameter.refactoring"), null);
return;
}
}
if (!ApplicationManager.getApplication().isUnitTestMode()) {
String occurencesString = RefactoringBundle.message("occurences.string", occurrences.size());
String question = RefactoringBundle.message("inline.parameter.confirmation", psiParameter.getName(),
@@ -0,0 +1,15 @@
class Base {
public Base() {
}
}
class Inheritor extends Base {
public Inheritor(String b<caret>ar) {
super();
System.out.println(bar);
}
public static void main(String[] args) {
new Inheritor("bar".toString());
}
}
@@ -0,0 +1,16 @@
class Base {
public Base() {
}
}
class Inheritor extends Base {
public Inheritor() {
super();
String bar = "bar".toString();
System.out.println(bar);
}
public static void main(String[] args) {
new Inheritor();
}
}
@@ -0,0 +1,10 @@
class Clazz {
public Clazz(String b<caret>ar) {
bar = bar + bar;
System.out.println(bar);
}
public static void main(String[] args) {
new Clazz("bar");
}
}
@@ -135,6 +135,19 @@ public class InlineParameterTest extends LightCodeInsightTestCase {
doTest(false);
}
public void testLocalVarDeclarationInConstructor() throws Exception {
doTest(true);
}
public void testParameterWithWriteAccess() throws Exception {
try {
doTest(false);
}
catch (CommonRefactoringUtil.RefactoringErrorHintException e) {
assertEquals("Inline parameter which has write usages is not supported", e.getMessage());
}
}
public void testRefNewInnerFromMethod() throws Exception {
try {
doTest(false);