blob: 796e2a0aa75f3fdc247a3cbdf4074fcd0851dad1 [file] [log] [blame]
package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.util.containers.HashSet;
import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Set;
/**
* @author ven
*/
public class ChangeSignaturePropagationTest extends LightRefactoringTestCase {
public void testParamSimple() throws Exception {
parameterPropagationTest();
}
public void testParamWithOverriding() throws Exception {
parameterPropagationTest();
}
public void testParamTypeSubst() throws Exception {
final PsiMethod method = getPrimaryMethod();
final HashSet<PsiMethod> methods = new HashSet<PsiMethod>();
for (PsiReference reference : ReferencesSearch.search(method)) {
final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(reference.getElement(), PsiMethod.class);
if (psiMethod != null) {
methods.add(psiMethod);
}
}
parameterPropagationTest(method, methods, JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("T"));
}
public void testExceptionSimple() throws Exception {
exceptionPropagationTest();
}
public void testExceptionWithOverriding() throws Exception {
exceptionPropagationTest();
}
public void testParamWithNoConstructor() throws Exception {
final PsiMethod method = getPrimaryMethod();
parameterPropagationTest(method, collectNonPhysicalMethodsToPropagate(method), JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("java.lang.Class", GlobalSearchScope.allScope(getProject())));
}
public void testExceptionWithNoConstructor() throws Exception {
final PsiMethod method = getPrimaryMethod();
exceptionPropagationTest(method, collectNonPhysicalMethodsToPropagate(method));
}
private static HashSet<PsiMethod> collectNonPhysicalMethodsToPropagate(PsiMethod method) {
final HashSet<PsiMethod> methodsToPropagate = new HashSet<PsiMethod>();
final PsiReference[] references =
MethodReferencesSearch.search(method, GlobalSearchScope.allScope(getProject()), true).toArray(PsiReference.EMPTY_ARRAY);
for (PsiReference reference : references) {
final PsiElement element = reference.getElement();
Assert.assertTrue(element instanceof PsiClass);
PsiClass containingClass = (PsiClass)element;
methodsToPropagate.add(JavaPsiFacade.getElementFactory(getProject()).createMethodFromText(containingClass.getName() + "(){}", containingClass));
}
return methodsToPropagate;
}
public void testParamWithImplicitConstructor() throws Exception {
final PsiMethod method = getPrimaryMethod();
parameterPropagationTest(method, collectDefaultConstructorsToPropagate(method), JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("java.lang.Class", GlobalSearchScope.allScope(getProject())));
}
public void testParamWithImplicitConstructors() throws Exception {
final PsiMethod method = getPrimaryMethod();
parameterPropagationTest(method, collectDefaultConstructorsToPropagate(method), JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("java.lang.Class", GlobalSearchScope.allScope(getProject())));
}
public void testExceptionWithImplicitConstructor() throws Exception {
final PsiMethod method = getPrimaryMethod();
exceptionPropagationTest(method, collectDefaultConstructorsToPropagate(method));
}
private static HashSet<PsiMethod> collectDefaultConstructorsToPropagate(PsiMethod method) {
final HashSet<PsiMethod> methodsToPropagate = new HashSet<PsiMethod>();
for (PsiClass inheritor : ClassInheritorsSearch.search(method.getContainingClass())) {
methodsToPropagate.add(inheritor.getConstructors()[0]);
}
return methodsToPropagate;
}
private void parameterPropagationTest() throws Exception {
parameterPropagationTest(JavaPsiFacade.getElementFactory(getProject())
.createTypeByFQClassName("java.lang.Class", GlobalSearchScope.allScope(getProject())));
}
private void parameterPropagationTest(final PsiClassType paramType) throws Exception {
final PsiMethod method = getPrimaryMethod();
parameterPropagationTest(method, new HashSet<PsiMethod>(Arrays.asList(method.getContainingClass().getMethods())),
paramType);
}
private void parameterPropagationTest(final PsiMethod method, final HashSet<PsiMethod> psiMethods, final PsiType paramType) throws Exception {
final ParameterInfoImpl[] newParameters = new ParameterInfoImpl[]{new ParameterInfoImpl(-1, "clazz", paramType, "null")};
doTest(newParameters, new ThrownExceptionInfo[0], psiMethods, null, method);
}
private void exceptionPropagationTest() throws Exception {
final PsiMethod method = getPrimaryMethod();
exceptionPropagationTest(method, new HashSet<PsiMethod>(Arrays.asList(method.getContainingClass().getMethods())));
}
private void exceptionPropagationTest(final PsiMethod method, final Set<PsiMethod> methodsToPropagateExceptions) throws Exception {
PsiClassType newExceptionType = JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("java.lang.Exception", GlobalSearchScope.allScope(getProject()));
final ThrownExceptionInfo[] newExceptions = new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, newExceptionType)};
doTest(new ParameterInfoImpl[0], newExceptions, null, methodsToPropagateExceptions, method);
}
private void doTest(ParameterInfoImpl[] newParameters,
final ThrownExceptionInfo[] newExceptions,
Set<PsiMethod> methodsToPropagateParameterChanges,
Set<PsiMethod> methodsToPropagateExceptionChanges,
PsiMethod primaryMethod) throws Exception {
final String filePath = getBasePath() + getTestName(false) + ".java";
final PsiType returnType = primaryMethod.getReturnType();
final CanonicalTypes.Type type = returnType == null ? null : CanonicalTypes.createTypeWrapper(returnType);
new ChangeSignatureProcessor(getProject(), primaryMethod, false, null,
primaryMethod.getName(),
type,
generateParameterInfos(primaryMethod, newParameters),
generateExceptionInfos(primaryMethod, newExceptions),
methodsToPropagateParameterChanges,
methodsToPropagateExceptionChanges).run();
checkResultByFile(filePath + ".after");
}
private PsiMethod getPrimaryMethod() throws Exception {
final String filePath = getBasePath() + getTestName(false) + ".java";
configureByFile(filePath);
final PsiElement targetElement = TargetElementUtilBase.findTargetElement(myEditor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
assertTrue("<caret> is not on method name", targetElement instanceof PsiMethod);
return (PsiMethod) targetElement;
}
private static String getBasePath() {
return "/refactoring/changeSignaturePropagation/";
}
private static ParameterInfoImpl[] generateParameterInfos (PsiMethod method, ParameterInfoImpl[] newParameters) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
ParameterInfoImpl[] result = new ParameterInfoImpl[parameters.length + newParameters.length];
for (int i = 0; i < parameters.length; i++) {
result[i] = new ParameterInfoImpl(i);
}
System.arraycopy(newParameters, 0, result, parameters.length, newParameters.length);
return result;
}
private static ThrownExceptionInfo[] generateExceptionInfos (PsiMethod method, ThrownExceptionInfo[] newExceptions) {
final PsiClassType[] exceptions = method.getThrowsList().getReferencedTypes();
ThrownExceptionInfo[] result = new ThrownExceptionInfo[exceptions.length + newExceptions.length];
for (int i = 0; i < exceptions.length; i++) {
result[i] = new JavaThrownExceptionInfo(i);
}
System.arraycopy(newExceptions, 0, result, exceptions.length, newExceptions.length);
return result;
}
@NotNull
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath();
}
}