blob: 3ea2c761686f8cc7c3931a0a545022b4ae8f9d8d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.ltk.core.refactoring.CheckConditionsOperation;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.MoveRefactoring;
import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
import org.eclipse.jdt.core.refactoring.descriptors.MoveDescriptor;
import org.eclipse.jdt.core.refactoring.descriptors.MoveStaticMembersDescriptor;
import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext;
import org.eclipse.jdt.internal.corext.refactoring.code.InlineMethodRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
import org.eclipse.jdt.internal.corext.refactoring.structure.ChangeSignatureProcessor;
import org.eclipse.jdt.internal.corext.refactoring.structure.MoveInstanceMethodProcessor;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
public class BinaryReferencesTests extends TestCase {
private static BinaryReferencesTestSetup fgTestSetup;
public BinaryReferencesTests(String name) {
super(name);
}
public static Test suite() {
fgTestSetup= new BinaryReferencesTestSetup(new TestSuite(BinaryReferencesTests.class));
return fgTestSetup;
}
public static Test setUpTest(Test test) {
fgTestSetup= new BinaryReferencesTestSetup(test);
return fgTestSetup;
}
private static void assertContainsMatches(List matches, String[] expectedHandleIdentifiers) {
int matchCount= matches.size();
assertTrue("match count too small: " + matchCount, matchCount >= expectedHandleIdentifiers.length);
List actual= new ArrayList();
for (int i= 0; i < matchCount; i++) {
SearchMatch match= (SearchMatch) matches.get(i);
String handleIdentifier= ((IJavaElement) match.getElement()).getHandleIdentifier();
actual.add(handleIdentifier);
}
List expected= new ArrayList(Arrays.asList(expectedHandleIdentifiers));
expected.removeAll(actual);
if (expected.size() != 0)
assertEquals("not all expected matches", expected.toString(), actual.toString());
}
private static IType findType(String typeName) throws JavaModelException {
return fgTestSetup.getSourceProject().findType(typeName);
}
private static IMethod findMethod(IType type, String methodName) throws JavaModelException {
IMethod method= type.getMethod(methodName, new String[0]);
if (! method.exists()) {
IMethod[] methods= type.getMethods();
for (int i= 0; i < methods.length; i++) {
if (methods[i].getElementName().equals(methodName)) {
method= methods[i];
break;
}
}
}
return method;
}
private static List doRefactoring(JavaRefactoringDescriptor descriptor) throws CoreException {
RefactoringStatus status= new RefactoringStatus();
Refactoring refactoring= descriptor.createRefactoring(status);
assertTrue(status.isOK());
return doCheckConditions(refactoring);
}
private static List doCheckConditions(Refactoring refactoring) throws CoreException {
CheckConditionsOperation op= new CheckConditionsOperation(refactoring, CheckConditionsOperation.ALL_CONDITIONS);
op.run(null);
RefactoringStatus validationStatus= op.getStatus();
assertTrue(!validationStatus.hasFatalError());
assertTrue(validationStatus.hasError());
assertEquals(1, validationStatus.getEntries().length);
ReferencesInBinaryContext context= (ReferencesInBinaryContext) validationStatus.getEntryAt(0).getContext();
return context.getMatches();
}
public void testRenameType01() throws Exception {
RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_TYPE);
descriptor.setJavaElement(findType("source.BaseClass"));
descriptor.setNewName("RenamedBaseClass");
descriptor.setUpdateReferences(true);
List matches= doRefactoring(descriptor);
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass~compareTo~Lsource.BaseClass;"
});
}
public void testRenameType02() throws Exception {
RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_TYPE);
descriptor.setJavaElement(findType("source.Color"));
descriptor.setNewName("Colour");
descriptor.setUpdateSimilarDeclarations(true);
descriptor.setMatchStrategy(RenameJavaElementDescriptor.STRATEGY_SUFFIX);
descriptor.setUpdateReferences(true);
RefactoringStatus status= new RefactoringStatus();
Refactoring refactoring= descriptor.createRefactoring(status);
assertTrue(status.isOK());
CheckConditionsOperation op= new CheckConditionsOperation(refactoring, CheckConditionsOperation.ALL_CONDITIONS);
op.run(null);
RefactoringStatus validationStatus= op.getStatus();
assertTrue(!validationStatus.hasFatalError());
assertTrue(validationStatus.hasError());
assertEquals(2, validationStatus.getEntries().length);
ReferencesInBinaryContext context= (ReferencesInBinaryContext) validationStatus.getEntryAt(0).getContext();
List matches= context.getMatches();
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass~paintColor~Lsource.Color;"
});
context= (ReferencesInBinaryContext) validationStatus.getEntryAt(1).getContext();
matches= context.getMatches();
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
private static List doRenameMethod(String typeName, String methodName) throws CoreException {
RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_METHOD);
IMethod method= findMethod(findType(typeName), methodName);
descriptor.setJavaElement(method);
descriptor.setNewName("newName");
descriptor.setUpdateReferences(true);
return doRefactoring(descriptor);
}
public void testRenameVirtualMethod01() throws Exception {
List matches= doRenameMethod("source.BaseClass", "baseMethod");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass~baseMethod"
});
}
public void testRenameVirtualMethod02() throws Exception {
List matches= doRenameMethod("source.BaseClass", "compareTo");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass~compareTo~Lsource.BaseClass;"
});
}
public void testRenameVirtualMethod03() throws Exception {
List matches= doRenameMethod("source.BaseClass", "referencedVirtualMethod");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;",
"=BinaryReference/binary<ref(SubClass.class[SubClass~baseMethod"
});
}
public void testRenameNonVirtualMethod01() throws Exception {
List matches= doRenameMethod("source.BaseClass", "referencedMethod");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
public void testRenameNonVirtualMethod02() throws Exception {
List matches= doRenameMethod("source.BaseClass", "referencedStaticMethod");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
private static List doRenameField(String typeName, String fieldName) throws CoreException {
IField field= findType(typeName).getField(fieldName);
String refactoringID= field.isEnumConstant() ? IJavaRefactorings.RENAME_ENUM_CONSTANT : IJavaRefactorings.RENAME_FIELD;
RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(refactoringID);
descriptor.setJavaElement(field);
descriptor.setNewName(field.isEnumConstant() ? "BLA" : "newName");
descriptor.setUpdateReferences(true);
return doRefactoring(descriptor);
}
public void testRenameField01() throws Exception {
List matches= doRenameField("source.BaseClass", "fProtected");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass~SubClass~I"
});
}
public void testRenameField02() throws Exception {
List matches= doRenameField("source.BaseClass", "fPublic");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
public void testRenameField03() throws Exception {
List matches= doRenameField("source.Color", "RED");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
public void testRenameField04() throws Exception {
if (true) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=226660
return;
List matches= doRenameField("source.Color", "GREEN");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
public void testRenamePackage01() throws Exception {
RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_PACKAGE);
IPackageFragment pack= findType("source.BaseClass").getPackageFragment();
descriptor.setJavaElement(pack);
descriptor.setNewName("newName");
descriptor.setUpdateReferences(true);
descriptor.setUpdateHierarchy(false);
List matches= doRefactoring(descriptor);
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass",
});
}
public void testRenamePackage02() throws Exception {
RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_PACKAGE);
IPackageFragment pack= findType("source.BaseClass").getPackageFragment();
descriptor.setJavaElement(pack);
descriptor.setNewName("newName");
descriptor.setUpdateReferences(true);
descriptor.setUpdateHierarchy(true);
RefactoringStatus status= new RefactoringStatus();
Refactoring refactoring= descriptor.createRefactoring(status);
assertTrue(status.isOK());
CheckConditionsOperation op= new CheckConditionsOperation(refactoring, CheckConditionsOperation.ALL_CONDITIONS);
op.run(null);
RefactoringStatus validationStatus= op.getStatus();
assertTrue(!validationStatus.hasFatalError());
assertTrue(validationStatus.hasError());
assertEquals(2, validationStatus.getEntries().length);
ReferencesInBinaryContext context= (ReferencesInBinaryContext) validationStatus.getEntryAt(0).getContext();
List matches= context.getMatches();
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass",
});
context= (ReferencesInBinaryContext) validationStatus.getEntryAt(1).getContext();
matches= context.getMatches();
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;",
"=BinaryReference/binary<ref(SubClass.class[SubClass"
});
}
private static List doChangeSignature(String typeName, String methodName) throws JavaModelException, Exception, CoreException {
IMethod method= findMethod(findType(typeName), methodName);
ChangeSignatureProcessor processor= new ChangeSignatureProcessor(method);
String[] newNames= { "x" };
String[] newTypes= { "int" };
String[] newDefaultValues= { "0" };
ParameterInfo[] newParamInfos= ChangeSignatureTests.createNewParamInfos(newTypes, newNames, newDefaultValues);
int[] newIndices= { 0 };
ChangeSignatureTests.addInfos(processor.getParameterInfos(), newParamInfos, newIndices);
Refactoring refactoring= new ProcessorBasedRefactoring(processor);
return doCheckConditions(refactoring);
}
public void testChangeSignature01() throws Exception {
List matches= doChangeSignature("source.BaseClass", "baseMethod");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass~baseMethod",
"=BinaryReference/binary<ref(SubClass.class[SubClass~baseMethod"
});
}
public void testChangeSignature02() throws Exception {
List matches= doChangeSignature("source.BaseClass", "compareTo");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass~compareTo~Lsource.BaseClass;"
});
}
public void testChangeSignature03() throws Exception {
List matches= doChangeSignature("source.BaseClass", "referencedMethod");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
public void testChangeConstructorSignature01() throws Exception {
List matches= doChangeSignature("source.BaseClass", "BaseClass");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass~SubClass~I",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
private static List doInlineMethod(String typeName, String methodName) throws JavaModelException, Exception, CoreException {
IMethod method= findMethod(findType(typeName), methodName);
ICompilationUnit cu= method.getCompilationUnit();
CompilationUnit node= new RefactoringASTParser(AST.JLS3).parse(cu, true);
ISourceRange nameRange= method.getNameRange();
Refactoring refactoring= InlineMethodRefactoring.create(cu, node, nameRange.getOffset(), nameRange.getLength());
return doCheckConditions(refactoring);
}
public void testInlineMethod01() throws Exception {
List matches= doInlineMethod("source.BaseClass", "referencedMethod");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
public void testInlineMethod02() throws Exception {
// no error if inlining only selected reference from source
IMethod baseMethod= findMethod(findType("source.BaseClass"), "baseMethod");
ICompilationUnit cu= baseMethod.getCompilationUnit();
CompilationUnit node= new RefactoringASTParser(AST.JLS3).parse(cu, true);
MethodDeclaration baseDecl= ASTNodeSearchUtil.getMethodDeclarationNode(baseMethod, node);
ExpressionStatement methodStmt= (ExpressionStatement) baseDecl.getBody().statements().get(0);
Refactoring refactoring= InlineMethodRefactoring.create(cu, node, methodStmt.getStartPosition(), methodStmt.getLength());
CheckConditionsOperation op= new CheckConditionsOperation(refactoring, CheckConditionsOperation.ALL_CONDITIONS);
op.run(null);
RefactoringStatus validationStatus= op.getStatus();
assertTrue(!validationStatus.hasError());
}
private static List doMoveType(String typeName, String newPackageName) throws CoreException {
IType type= findType(typeName);
IPackageFragmentRoot root= JavaModelUtil.getPackageFragmentRoot(type);
MoveDescriptor descriptor= (MoveDescriptor) RefactoringCore.getRefactoringContribution(IJavaRefactorings.MOVE).createDescriptor();
descriptor.setMoveResources(new IFile[0], new IFolder[0], new ICompilationUnit[] { type.getCompilationUnit() });
descriptor.setDestination(root.getPackageFragment(newPackageName));
descriptor.setUpdateReferences(true);
return doRefactoring(descriptor);
}
public void testMoveType01() throws Exception {
List matches= doMoveType("source.BaseClass", "source.sub");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(SubClass.class[SubClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass",
"=BinaryReference/binary<ref(SubClass.class[SubClass~compareTo~Lsource.BaseClass;",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;", // + more of these...
});
}
private static List doMoveStaticMembers(IMember[] members, String targetTypeName) throws CoreException {
IType targetType= findType(targetTypeName);
MoveStaticMembersDescriptor descriptor= (MoveStaticMembersDescriptor) RefactoringCore.getRefactoringContribution(IJavaRefactorings.MOVE_STATIC_MEMBERS).createDescriptor();
descriptor.setDestinationType(targetType);
descriptor.setMembers(members);
return doRefactoring(descriptor);
}
public void testMoveStaticMember01() throws Exception {
IType type= findType("source.BaseClass");
IMethod method= findMethod(type, "referencedStaticMethod");
IField field= type.getField("CONST");
List matches= doMoveStaticMembers(new IMember[] { method, field }, "source.sub.InSubPack");
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;",
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
public void testMoveMethod01() throws Exception {
IType type= findType("source.BaseClass");
IMethod method= findMethod(type, "referencedMethod");
MoveInstanceMethodProcessor processor= new MoveInstanceMethodProcessor(method, JavaPreferencesSettings.getCodeGenerationSettings(method.getJavaProject()));
Refactoring ref= new MoveRefactoring(processor);
RefactoringStatus preconditionResult= ref.checkInitialConditions(new NullProgressMonitor());
assertTrue("activation was supposed to be successful", preconditionResult.isOK());
MoveInstanceMethodTests.chooseNewTarget(processor, MoveInstanceMethodTests.PARAMETER, "c");
List matches= doCheckConditions(ref);
assertContainsMatches(matches, new String[] {
"=BinaryReference/binary<ref(ReferenceClass.class[ReferenceClass~main~\\[Ljava.lang.String;"
});
}
}