convert to instance method: warn about new visibility

This commit is contained in:
anna
2012-11-29 11:53:01 +01:00
parent a22fe193ab
commit 135a4dec53
3 changed files with 29 additions and 45 deletions
@@ -24,7 +24,6 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
@@ -138,8 +137,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
final Set<PsiMember> methods = Collections.singleton((PsiMember)myMethod);
if (!myTargetClass.isInterface()) {
final String original = VisibilityUtil.getVisibilityModifier(myMethod.getModifierList());
RefactoringConflictsUtil.analyzeAccessibilityConflicts(methods, myTargetClass, conflicts, original);
RefactoringConflictsUtil.analyzeAccessibilityConflicts(methods, myTargetClass, conflicts, myNewVisibility);
}
else {
for (final UsageInfo usage : usagesIn) {
@@ -168,50 +166,9 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
}
}
try {
addInaccessibilityConflicts(usagesIn, conflicts);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
return showConflicts(conflicts, usagesIn);
}
private void addInaccessibilityConflicts(final UsageInfo[] usages, final MultiMap<PsiElement, String> conflicts) throws IncorrectOperationException {
final PsiModifierList copy = (PsiModifierList)myMethod.getModifierList().copy();
if (myNewVisibility != null) {
if (myNewVisibility.equals(VisibilityUtil.ESCALATE_VISIBILITY)) {
VisibilityUtil.setVisibility(copy, PsiModifier.PUBLIC);
}
else {
VisibilityUtil.setVisibility(copy, myNewVisibility);
}
}
for (UsageInfo usage : usages) {
if (usage instanceof MethodCallUsageInfo) {
final PsiMethodCallExpression call = ((MethodCallUsageInfo)usage).getMethodCall();
final PsiExpression[] arguments = call.getArgumentList().getExpressions();
final int index = myMethod.getParameterList().getParameterIndex(myTargetParameter);
LOG.assertTrue(index >= 0);
PsiClass accessObjectClass = null;
if (index < arguments.length) {
final PsiExpression argument = arguments[index];
final PsiType argumentType = argument.getType();
if (argumentType instanceof PsiClassType) accessObjectClass = ((PsiClassType)argumentType).resolve();
}
if (!JavaResolveUtil.isAccessible(myMethod, myTargetClass, copy, call, accessObjectClass, null)) {
final String newVisibility = myNewVisibility == null ? VisibilityUtil.getVisibilityStringToDisplay(myMethod) : myNewVisibility;
String message = RefactoringBundle.message("0.with.1.visibility.is.not.accessible.from.2",
RefactoringUIUtil.getDescription(myMethod, true), newVisibility,
RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(call), true));
conflicts.putValue(myMethod, message);
}
}
}
}
protected void performRefactoring(UsageInfo[] usages) {
if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, myTargetClass)) return;
LocalHistoryAction a = LocalHistory.getInstance().startAction(getCommandName());
@@ -0,0 +1,11 @@
class Test {
{
foo(new Bar());
}
private static void <caret>foo(Bar b){}
}
class Bar {
}
@@ -4,6 +4,8 @@ import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.LightRefactoringTestCase;
import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.NotNull;
@@ -33,15 +35,29 @@ public class ConvertToInstanceMethodTest extends LightRefactoringTestCase {
public void testInterfaceTypeParameter() throws Exception { doTest(0); }
public void testJavadocParameter() throws Exception { doTest(0); }
public void testVisibilityConflict() throws Exception {
try {
doTest(0, PsiModifier.PRIVATE);
fail("Conflict was not detected");
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
assertEquals("Method <b><code>Test.foo(Bar)</code></b> is private and will not be accessible from instance initializer of class class <b><code>Test</code></b>.", e.getMessage());
}
}
private void doTest(final int targetParameter) throws Exception {
doTest(targetParameter, VisibilityUtil.ESCALATE_VISIBILITY);
}
private void doTest(final int targetParameter, final String visibility) throws Exception {
final String filePath = "/refactoring/convertToInstanceMethod/" + getTestName(false) + ".java";
configureByFile(filePath);
final PsiElement targetElement = TargetElementUtilBase.findTargetElement(getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
assertTrue("<caret> is not on method name", targetElement instanceof PsiMethod);
PsiMethod method = (PsiMethod) targetElement;
new ConvertToInstanceMethodProcessor(getProject(),
method, method.getParameterList().getParameters()[targetParameter], VisibilityUtil.ESCALATE_VISIBILITY).run();
method, method.getParameterList().getParameters()[targetParameter],
visibility).run();
checkResultByFile(filePath + ".after");
}