blob: 29c3b755b5b104ac339f176d6c2809c3e9da91c4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ui.tests.refactoring;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.internal.corext.refactoring.structure.MoveInstanceMethodProcessor;
import org.eclipse.jdt.internal.corext.refactoring.structure.MoveInstanceMethodRefactoring;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
import org.eclipse.jdt.ui.tests.refactoring.infra.TextRangeUtil;
public class MoveInstanceMethodTests extends RefactoringTest {
private static final Class clazz= MoveInstanceMethodTests.class;
private static final int FIELD= 1;
private static final int PARAMETER= 0;
private static final String REFACTORING_PATH= "MoveInstanceMethod/";
private static void chooseNewTarget(MoveInstanceMethodRefactoring ref, int newTargetType, String newTargetName) {
IVariableBinding target= null;
IVariableBinding[] targets= ref.getMoveMethodProcessor().getPossibleTargets();
for (int i= 0; i < targets.length; i++) {
IVariableBinding candidate= targets[i];
if (candidate.getName().equals(newTargetName) && typeMatches(newTargetType, candidate)) {
target= candidate;
break;
}
}
assertNotNull("Expected new target not available.", target);
ref.getMoveMethodProcessor().setTarget(target);
}
private static IMethod getMethod(ICompilationUnit cu, ISourceRange sourceRange) throws JavaModelException {
IJavaElement[] jes= cu.codeSelect(sourceRange.getOffset(), sourceRange.getLength());
if (jes.length != 1 || !(jes[0] instanceof IMethod))
return null;
return (IMethod) jes[0];
}
public static Test setUpTest(Test someTest) {
return new Java15Setup(someTest);
}
public static Test suite() {
return new Java15Setup(new TestSuite(clazz));
}
private static boolean typeMatches(int newTargetType, IVariableBinding newTarget) {
return newTargetType == PARAMETER && !newTarget.isField() || newTargetType == FIELD && newTarget.isField();
}
private boolean toSucceed;
public MoveInstanceMethodTests(String name) {
super(name);
}
private ICompilationUnit[] createCUs(String[] qualifiedNames) throws Exception {
ICompilationUnit[] cus= new ICompilationUnit[qualifiedNames.length];
for (int i= 0; i < qualifiedNames.length; i++) {
Assert.isNotNull(qualifiedNames[i]);
cus[i]= createCUfromTestFile(getRoot().createPackageFragment(getQualifier(qualifiedNames[i]), true, null), getSimpleName(qualifiedNames[i]));
}
return cus;
}
private void failHelper1(String cuQName, int startLine, int startColumn, int endLine, int endColumn, int newReceiverType, String newReceiverName, boolean inlineDelegator, boolean removeDelegator) throws Exception {
failHelper1(new String[] { cuQName}, cuQName, startLine, startColumn, endLine, endColumn, newReceiverType, newReceiverName, inlineDelegator, removeDelegator);
}
private void failHelper1(String[] cuQNames, int selectionCuIndex, int startLine, int startColumn, int endLine, int endColumn, int newReceiverType, String newReceiverName, String newMethodName, String newTargetName, boolean inlineDelegator, boolean removeDelegator) throws Exception {
Assert.isTrue(0 <= selectionCuIndex && selectionCuIndex < cuQNames.length);
toSucceed= false;
ICompilationUnit[] cus= createCUs(cuQNames);
ICompilationUnit selectionCu= cus[selectionCuIndex];
ISourceRange selection= TextRangeUtil.getSelection(selectionCu, startLine, startColumn, endLine, endColumn);
IMethod method= getMethod(selectionCu, selection);
assertNotNull(method);
MoveInstanceMethodRefactoring ref= new MoveInstanceMethodRefactoring(new MoveInstanceMethodProcessor(method, JavaPreferencesSettings.getCodeGenerationSettings(selectionCu.getJavaProject())));
RefactoringStatus result= ref.checkInitialConditions(new NullProgressMonitor());
if (!result.isOK())
return;
else {
chooseNewTarget(ref, newReceiverType, newReceiverName);
MoveInstanceMethodProcessor processor= ref.getMoveMethodProcessor();
if (newTargetName != null)
processor.setTargetName(newTargetName);
processor.setInlineDelegator(inlineDelegator);
processor.setRemoveDelegator(removeDelegator);
processor.setDeprecateDelegates(false);
if (newMethodName != null)
processor.setMethodName(newMethodName);
result.merge(ref.checkFinalConditions(new NullProgressMonitor()));
assertTrue("precondition checking is expected to fail.", !result.isOK());
}
}
private void failHelper1(String[] cuQNames, String selectionCuQName, int startLine, int startColumn, int endLine, int endColumn, int newReceiverType, String newReceiverName, boolean inlineDelegator, boolean removeDelegator) throws Exception {
int selectionCuIndex= firstIndexOf(selectionCuQName, cuQNames);
Assert.isTrue(selectionCuIndex != -1, "parameter selectionCuQName must match some String in cuQNames.");
failHelper1(cuQNames, selectionCuIndex, startLine, startColumn, endLine, endColumn, newReceiverType, newReceiverName, null, null, inlineDelegator, removeDelegator);
}
private void failHelper2(String[] cuQNames, String selectionCuQName, int startLine, int startColumn, int endLine, int endColumn, int newReceiverType, String newReceiverName, String originalReceiverParameterName, boolean inlineDelegator, boolean removeDelegator) throws Exception {
int selectionCuIndex= firstIndexOf(selectionCuQName, cuQNames);
Assert.isTrue(selectionCuIndex != -1, "parameter selectionCuQName must match some String in cuQNames.");
failHelper1(cuQNames, selectionCuIndex, startLine, startColumn, endLine, endColumn, newReceiverType, newReceiverName, null, originalReceiverParameterName, inlineDelegator, removeDelegator);
}
private int firstIndexOf(String one, String[] others) {
for (int i= 0; i < others.length; i++)
if (one == null && others[i] == null || one.equals(others[i]))
return i;
return -1;
}
private String getQualifier(String qualifiedName) {
int dot= qualifiedName.lastIndexOf('.');
return qualifiedName.substring(0, dot != -1 ? dot : 0);
}
protected String getRefactoringPath() {
return REFACTORING_PATH + successPath();
}
private String getSimpleName(String qualifiedName) {
return qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
}
private void helper1(String[] cuQNames, int selectionCuIndex, int startLine, int startColumn, int endLine, int endColumn, int newTargetType, String newTargetName, String newMethodName, boolean inlineDelegator, boolean removeDelegator) throws Exception {
Assert.isTrue(0 <= selectionCuIndex && selectionCuIndex < cuQNames.length);
toSucceed= true;
ICompilationUnit[] cus= createCUs(cuQNames);
ICompilationUnit selectionCu= cus[selectionCuIndex];
ISourceRange selection= TextRangeUtil.getSelection(selectionCu, startLine, startColumn, endLine, endColumn);
IMethod method= getMethod(selectionCu, selection);
assertNotNull(method);
MoveInstanceMethodRefactoring ref= new MoveInstanceMethodRefactoring(new MoveInstanceMethodProcessor(method, JavaPreferencesSettings.getCodeGenerationSettings(selectionCu.getJavaProject())));
assertNotNull("refactoring should be created", ref);
RefactoringStatus preconditionResult= ref.checkInitialConditions(new NullProgressMonitor());
assertTrue("activation was supposed to be successful", preconditionResult.isOK());
chooseNewTarget(ref, newTargetType, newTargetName);
MoveInstanceMethodProcessor processor= ref.getMoveMethodProcessor();
processor.setInlineDelegator(inlineDelegator);
processor.setRemoveDelegator(removeDelegator);
processor.setDeprecateDelegates(false);
if (newMethodName != null)
processor.setMethodName(newMethodName);
preconditionResult.merge(ref.checkFinalConditions(new NullProgressMonitor()));
assertTrue("precondition was supposed to pass", !preconditionResult.hasError());
performChange(ref, false);
for (int i= 0; i < cus.length; i++) {
String outputTestFileName= getOutputTestFileName(getSimpleName(cuQNames[i]));
assertEqualLines("Incorrect inline in " + outputTestFileName, getFileContents(outputTestFileName), cus[i].getSource());
}
}
private void helper1(String[] cuQNames, int selectionCuIndex, int startLine, int startColumn, int endLine, int endColumn, int newTargetType, String newTargetName, String newMethodName, boolean inlineDelegator, boolean removeDelegator, boolean deprecate) throws Exception {
Assert.isTrue(0 <= selectionCuIndex && selectionCuIndex < cuQNames.length);
toSucceed= true;
ICompilationUnit[] cus= createCUs(cuQNames);
ICompilationUnit selectionCu= cus[selectionCuIndex];
ISourceRange selection= TextRangeUtil.getSelection(selectionCu, startLine, startColumn, endLine, endColumn);
IMethod method= getMethod(selectionCu, selection);
assertNotNull(method);
MoveInstanceMethodRefactoring ref= new MoveInstanceMethodRefactoring(new MoveInstanceMethodProcessor(method, JavaPreferencesSettings.getCodeGenerationSettings(selectionCu.getJavaProject())));
assertNotNull("refactoring should be created", ref);
RefactoringStatus preconditionResult= ref.checkInitialConditions(new NullProgressMonitor());
assertTrue("activation was supposed to be successful", preconditionResult.isOK());
chooseNewTarget(ref, newTargetType, newTargetName);
MoveInstanceMethodProcessor processor= ref.getMoveMethodProcessor();
processor.setInlineDelegator(inlineDelegator);
processor.setRemoveDelegator(removeDelegator);
processor.setDeprecateDelegates(deprecate);
if (newMethodName != null)
processor.setMethodName(newMethodName);
preconditionResult.merge(ref.checkFinalConditions(new NullProgressMonitor()));
assertTrue("precondition was supposed to pass", !preconditionResult.hasError());
performChange(ref, false);
for (int i= 0; i < cus.length; i++) {
String outputTestFileName= getOutputTestFileName(getSimpleName(cuQNames[i]));
assertEqualLines("Incorrect inline in " + outputTestFileName, getFileContents(outputTestFileName), cus[i].getSource());
}
}
private void helper1(String[] cuQNames, String selectionCuQName, int startLine, int startColumn, int endLine, int endColumn, int newReceiverType, String newReceiverName, boolean inlineDelegator, boolean removeDelegator) throws Exception {
int selectionCuIndex= firstIndexOf(selectionCuQName, cuQNames);
Assert.isTrue(selectionCuIndex != -1, "parameter selectionCuQName must match some String in cuQNames.");
helper1(cuQNames, selectionCuIndex, startLine, startColumn, endLine, endColumn, newReceiverType, newReceiverName, null, inlineDelegator, removeDelegator);
}
private void helper1(String[] cuQNames, String selectionCuQName, int startLine, int startColumn, int endLine, int endColumn, int newReceiverType, String newReceiverName, boolean inlineDelegator, boolean removeDelegator, boolean deprecate) throws Exception {
int selectionCuIndex= firstIndexOf(selectionCuQName, cuQNames);
Assert.isTrue(selectionCuIndex != -1, "parameter selectionCuQName must match some String in cuQNames.");
helper1(cuQNames, selectionCuIndex, startLine, startColumn, endLine, endColumn, newReceiverType, newReceiverName, null, inlineDelegator, removeDelegator, deprecate);
}
private String successPath() {
return toSucceed ? "/canMove/" : "/cannotMove/";
}
// --- TESTS
// Move mA1 to parameter b, do not inline delegator
public void test0() throws Exception {
helper1(new String[] { "p1.A", "p2.B", "p3.C"}, "p1.A", 11, 17, 11, 20, PARAMETER, "b", false, false);
}
// Move mA1 to parameter b, inline delegator
public void test1() throws Exception {
// printTestDisabledMessage("not implemented yet");
helper1(new String[] { "p1.A", "p2.B", "p3.C"}, "p1.A", 11, 17, 11, 20, PARAMETER, "b", true, false);
}
// multiple parameters, some left of new receiver parameter, some right of it,
// "this" is NOT passed as argument, (since it's not used in the method)
public void test10() throws Exception {
helper1(new String[] { "p1.A", "p2.B"}, "p1.A", 14, 17, 14, 17, PARAMETER, "b", false, false);
}
// move to field, method has parameters, choice of fields, some non-class type fields
// ("this" is passed as argument)
public void test11() throws Exception {
helper1(new String[] { "p1.A", "p2.B"}, "p1.A", 17, 17, 17, 17, FIELD, "fB", false, false);
}
// move to field - do not pass 'this' because it's unneeded
public void test12() throws Exception {
helper1(new String[] { "p1.A", "p2.B"}, "p1.A", 14, 17, 14, 20, FIELD, "fB", false, false);
}
// junit case
public void test13() throws Exception {
helper1(new String[] { "p1.TR", "p1.TC", "p1.P"}, "p1.TR", 9, 20, 9, 23, PARAMETER, "test", false, false);
}
// simplified junit case
public void test14() throws Exception {
helper1(new String[] { "p1.TR", "p1.TC"}, "p1.TR", 9, 20, 9, 23, PARAMETER, "test", false, false);
}
// move to type in same cu
public void test15() throws Exception {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=40120
helper1(new String[] { "p.A"}, "p.A", 17, 18, 17, 18, PARAMETER, "s", false, false);
}
// move to inner type in same cu
public void test16() throws Exception {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=40120
helper1(new String[] { "p.B"}, "p.B", 15, 17, 15, 22, PARAMETER, "s", false, false);
}
// don't generate parameter for unused field (bug 38310)
public void test17() throws Exception {
helper1(new String[] { "p.Shape", "p.Rectangle"}, "p.Shape", 11, 16, 11, 20, FIELD, "fBounds", false, false);
}
// generate parameter for used field (bug 38310)
public void test18() throws Exception {
helper1(new String[] { "p.Shape", "p.Rectangle"}, "p.Shape", 17, 22, 17, 22, FIELD, "fInnerBounds", false, false);
}
// generate parameter for used field (bug 38310)
public void test19() throws Exception {
helper1(new String[] { "p.Shape", "p.Rectangle"}, "p.Shape", 22, 20, 22, 33, PARAMETER, "rect", false, false);
}
// // Move mA1 to parameter b, inline delegator, remove delegator
public void test2() throws Exception {
// printTestDisabledMessage("not implemented yet");
helper1(new String[] { "p1.A", "p2.B", "p3.C"}, "p1.A", 12, 17, 12, 20, PARAMETER, "b", true, true);
}
// Can move if "super" is used in inner class
public void test20() throws Exception {
helper1(new String[] { "p.A", "p.B", "p.StarDecorator"}, "p.A", 14, 17, 14, 22, PARAMETER, "b", false, false);
}
// Arguments of method calls preserved in moved body (bug 41468)
public void test21() throws Exception {
helper1(new String[] { "p.A", "p.Second"}, "p.A", 5, 17, 5, 22, FIELD, "s", false, false);
}
// arguments of method calls preserved in moved body (bug 41468),
// use "this" instead of field (bug 38310)
public void test22() throws Exception {
helper1(new String[] { "p.A", "p.Second"}, "p.A", 5, 17, 5, 22, FIELD, "s", false, false);
}
// "this"-qualified field access: this.s -> this (bug 41597)
public void test23() throws Exception {
helper1(new String[] { "p.A", "p.Second"}, "p.A", 5, 17, 5, 22, FIELD, "s", false, false);
}
// move local class (41530)
public void test24() throws Exception {
helper1(new String[] { "p1.A", "p1.B", "p1.StarDecorator"}, "p1.A", 9, 17, 9, 22, PARAMETER, "b", false, false);
}
// extended junit case
public void test25() throws Exception {
helper1(new String[] { "p1.TR", "p1.TC", "p1.P"}, "p1.TR", 4, 20, 4, 23, PARAMETER, "test", false, false);
}
// extended junit case with generics (bug 77653)
public void test26() throws Exception {
helper1(new String[] { "p1.TR", "p1.TC", "p1.P"}, "p1.TR", 9, 20, 9, 23, PARAMETER, "test", false, false);
}
// extended junit case with generics and deprecation message
public void test27() throws Exception {
helper1(new String[] { "p1.TR", "p1.TC", "p1.P"}, "p1.TR", 9, 20, 9, 23, PARAMETER, "test", false, false, true);
}
// extended junit case with generics, enums and deprecation message
public void test28() throws Exception {
helper1(new String[] { "p1.TR", "p1.TC", "p1.P"}, "p1.TR", 9, 20, 9, 23, PARAMETER, "test", false, false, true);
}
// extended junit case with generics, enums and deprecation message
public void test29() throws Exception {
helper1(new String[] { "p1.TR", "p1.TC", "p1.P"}, "p1.TR", 9, 20, 9, 23, PARAMETER, "test", false, false, true);
}
// extended junit case with generics, enums, static imports and deprecation message
public void test30() throws Exception {
helper1(new String[] { "p1.TR", "p1.TC", "p1.P"}, "p1.TR", 10, 21, 10, 21, PARAMETER, "test", false, false, true);
}
// extended junit case with generics, enums, static imports and deprecation message
public void test31() throws Exception {
printTestDisabledMessage("disabled due to missing support for statically imported methods");
// helper1(new String[] { "p1.TR", "p1.TC", "p1.P"}, "p1.TR", 10, 21, 10, 21, PARAMETER, "test", false, false, true);
}
public void test32() throws Exception {
helper1(new String[] { "p1.A"}, "p1.A", 9, 25, 9, 26, PARAMETER, "p", true, true);
}
// Test visibility of a target field is not affected.
public void test33() throws Exception {
helper1(new String[] { "p.Foo", "p.Bar" }, "p.Foo", 6, 18, 6, 21, FIELD, "_bar", false, false);
}
// Test visibility of target field is changed to public
// in case a caller is in another package (bug 117465).
public void test34() throws Exception {
helper1(new String[] { "test1.TestTarget", "test1.Test1", "test2.Test2"}, "test1.Test1", 3, 21, 3, 33, FIELD, "target", true, true);
}
// Test visibility of target field is changed to default
// in case a caller is in the same package (bug 117465).
public void test35() throws Exception {
helper1(new String[] { "test1.TestTarget", "test1.Test1", "test1.Test2"}, "test1.Test1", 3, 21, 3, 33, FIELD, "target", true, true);
}
// Test search engine for secondary types (bug 108030).
public void test36() throws Exception {
helper1(new String[] { "p.A", "p.B" }, "p.A", 9, 17, 9, 27, FIELD, "fB", false, false);
}
// Move mA1 to field fB, do not inline delegator
public void test3() throws Exception {
helper1(new String[] { "p1.A", "p2.B", "p3.C"}, "p1.A", 9, 17, 9, 20, FIELD, "fB", false, false);
}
// // Move mA1 to field fB, inline delegator, remove delegator
public void test4() throws Exception {
// printTestDisabledMessage("not implemented yet");
helper1(new String[] { "p1.A", "p2.B", "p3.C"}, "p1.A", 9, 17, 9, 20, FIELD, "fB", true, true);
}
// Move mA1 to field fB, unqualified static member references are qualified
public void test5() throws Exception {
helper1(new String[] { "p1.A", "p2.B"}, "p1.A", 15, 19, 15, 19, FIELD, "fB", false, false);
}
// class qualify referenced type name to top level, original receiver not used in method
public void test6() throws Exception {
helper1(new String[] { "p1.Nestor", "p2.B"}, "p1.Nestor", 11, 17, 11, 17, PARAMETER, "b", false, false);
}
public void test7() throws Exception {
helper1(new String[] { "p1.A", "p2.B", "p3.N1"}, "p1.A", 8, 17, 8, 18, PARAMETER, "b", false, false);
}
// access to fields, non-void return type
public void test8() throws Exception {
helper1(new String[] { "p1.A", "p2.B"}, "p1.A", 15, 19, 15, 20, PARAMETER, "b", false, false);
}
// multiple parameters, some left of new receiver parameter, some right of it,
// "this" is passed as argument
public void test9() throws Exception {
helper1(new String[] { "p1.A", "p2.B"}, "p1.A", 6, 17, 6, 17, PARAMETER, "b", false, false);
}
// Cannot move interface method declaration
public void testFail0() throws Exception {
failHelper1("p1.IA", 5, 17, 5, 20, PARAMETER, "b", true, true);
}
// Cannot move abstract method declaration
public void testFail1() throws Exception {
failHelper1("p1.A", 5, 26, 5, 29, PARAMETER, "b", true, true);
}
// Cannot move method if there's no new potential receiver
public void testFail10() throws Exception {
failHelper1(new String[] { "p1.A", "p2.B", "p3.C"}, "p1.A", 8, 17, 8, 20, PARAMETER, "b", true, true);
}
// Cannot move method - parameter name conflict
public void testFail11() throws Exception {
failHelper2(new String[] { "p1.A", "p2.B"}, "p1.A", 7, 17, 7, 20, PARAMETER, "b", "a", true, true);
}
// Cannot move method if there's no new potential receiver (because of null bindings here)
public void testFail12() throws Exception {
// printTestDisabledMessage("bug 39871");
failHelper1(new String[] { "p1.A"}, "p1.A", 5, 10, 5, 16, PARAMETER, "b", true, true);
}
// Cannot move method - annotations are not supported
public void testFail13() throws Exception {
printTestDisabledMessage("disabled - jcore does not have elements for annotation members");
// failHelper2(new String[] { "p1.A", "p2.B"}, "p1.A", 5, 12, 5, 13, PARAMETER, "b", "a", true, true);
}
// Cannot move static method
public void testFail2() throws Exception {
failHelper1(new String[] { "p1.A", "p2.B"}, "p1.A", 6, 23, 6, 24, PARAMETER, "b", true, true);
}
// Cannot move native method
public void testFail3() throws Exception {
failHelper1(new String[] { "p1.A", "p2.B"}, "p1.A", 6, 23, 6, 24, PARAMETER, "b", true, true);
}
// Cannot move method that references "super"
public void testFail4() throws Exception {
failHelper1(new String[] { "p1.A", "p2.B"}, "p1.A", 11, 20, 11, 21, PARAMETER, "b", true, true);
}
// Cannot move method that references an enclosing instance
public void testFail5() throws Exception {
failHelper1(new String[] { "p1.A", "p2.B"}, "p1.A", 8, 21, 8, 21, PARAMETER, "b", true, true);
}
// Cannot move potentially directly recursive method
public void testFail6() throws Exception {
failHelper1(new String[] { "p1.A", "p2.B"}, "p1.A", 6, 16, 6, 17, PARAMETER, "b", true, true);
}
// Cannot move synchronized method
public void testFail8() throws Exception {
failHelper1(new String[] { "p1.A", "p2.B"}, "p1.A", 6, 29, 6, 29, PARAMETER, "b", true, true);
}
// Cannot move method if there's no new potential receiver
public void testFail9() throws Exception {
failHelper1(new String[] { "p1.A", "p2.B", "p3.C"}, "p1.A", 7, 17, 7, 20, PARAMETER, "b", true, true);
}
}