inline parameter: conflict for write access (IDEA-40733); exceptions are thrown if they are found in initializer (IDEA-40732 )

This commit is contained in:
anna
2010-02-02 19:49:02 +03:00
parent 5a60b9500f
commit 9b271b5bd7
5 changed files with 119 additions and 0 deletions
@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.inline;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInspection.sameParameterValue.SameParameterValueInspection;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
@@ -223,11 +224,39 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor
}
}
});
final UsageInfo[] usages = refUsages.get();
final Set<PsiVariable> vars = new HashSet<PsiVariable>();
for (UsageInfo usageInfo : usages) {
if (usageInfo instanceof LocalReplacementUsageInfo) {
final PsiVariable var = ((LocalReplacementUsageInfo)usageInfo).getVariable();
if (var != null) {
vars.add(var);
}
}
}
for (PsiVariable var : vars) {
for (PsiReference ref : ReferencesSearch.search(var)) {
final PsiElement element = ref.getElement();
if (element instanceof PsiExpression && isAccessedForWriting((PsiExpression)element)) {
conflicts.putValue(element, "Parameter initializer depends on value which is not available inside method and cannot be inlined");
break;
}
}
}
return showConflicts(conflicts);
}
private static boolean isAccessedForWriting (PsiExpression expr) {
while (expr.getParent() instanceof PsiArrayAccessExpression) {
expr = (PsiExpression)expr.getParent();
}
return PsiUtil.isAccessedForWriting(expr);
}
@Override
protected void performRefactoring(UsageInfo[] usages) {
final List<PsiClassType> thrownExceptions = ExceptionUtil.getThrownCheckedExceptions(new PsiElement[]{myInitializer});
final Set<PsiVariable> varsUsedInInitializer = new HashSet<PsiVariable>();
final Set<PsiJavaCodeReferenceElement> paramRefsToInline = new HashSet<PsiJavaCodeReferenceElement>();
final Map<PsiElement, PsiElement> replacements = new HashMap<PsiElement, PsiElement>();
@@ -274,6 +303,15 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor
}
SameParameterValueInspection.InlineParameterValueFix.removeParameter(myMethod, myParameter);
if (!thrownExceptions.isEmpty()) {
for (PsiClassType exception : thrownExceptions) {
PsiClass exceptionClass = exception.resolve();
if (exceptionClass != null) {
PsiUtil.addException(myMethod, exceptionClass);
}
}
}
}
private static class LocalReplacementUsageInfo extends UsageInfo {
@@ -0,0 +1,26 @@
import java.io.*;
public class Subject {
private int myInt;
public void withClass(Object <caret>o) {
myInt += o.hashCode();
}
}
class User {
private void oper() throws IOException {
Subject subj = new Subject();
subj.withClass(new ThirdParty(false));
}
}
class ThirdParty {
public ThirdParty() {
}
public ThirdParty(boolean b) throws IOException {
if (b) {
throw new IOException();
}
}
}
@@ -0,0 +1,26 @@
import java.io.*;
public class Subject {
private int myInt;
public void withClass() throws IOException {
myInt += new ThirdParty(false).hashCode();
}
}
class User {
private void oper() throws IOException {
Subject subj = new Subject();
subj.withClass();
}
}
class ThirdParty {
public ThirdParty() {
}
public ThirdParty(boolean b) throws IOException {
if (b) {
throw new IOException();
}
}
}
@@ -0,0 +1,16 @@
public class Subject {
private int myInt;
public void withArray(int[] <caret>pia) {
myInt += pia[0];
}
}
class User {
private void oper() {
Subject subj = new Subject();
int[] ia = new int[]{0, 1};
ia[0] = 2;
subj.withArray(ia);
}
}
@@ -139,6 +139,19 @@ public class InlineParameterTest extends LightCodeInsightTestCase {
}
}
public void testRefArrayAccess() throws Exception {
try {
doTest(false);
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
assertEquals("Parameter initializer depends on value which is not available inside method and cannot be inlined", e.getMessage());
}
}
public void testHandleExceptions() throws Exception {
doTest(false);
}
private void doTestCannotFindInitializer() throws Exception {
try {
doTest(false);