blob: f432aadf9abecf8edc43d5d0186d05f432c9d70b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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.typeconstraints;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeEnvironment;
import org.eclipse.jdt.ui.tests.refactoring.RefactoringTestSetup;
import org.eclipse.jdt.ui.tests.refactoring.infra.AbstractCUTestCase;
import org.eclipse.jdt.ui.tests.refactoring.infra.RefactoringTestPlugin;
public class TypeEnvironmentTests extends AbstractCUTestCase {
private static final boolean BUG_83616_core_wildcard_assignments= true;
private static class MyTestSetup extends RefactoringTestSetup {
private static IPackageFragment fSignaturePackage;
private static IPackageFragment fGenericPackage;
public MyTestSetup(Test test) {
super(test);
}
protected void setUp() throws Exception {
super.setUp();
fSignaturePackage= getDefaultSourceFolder().createPackageFragment("signature", true, null);
fGenericPackage= getDefaultSourceFolder().createPackageFragment("generic", true, null);
}
public static IPackageFragment getSignaturePackage() {
return fSignaturePackage;
}
public static IPackageFragment getGenericPackage() {
return fGenericPackage;
}
}
private static class CreationChecker extends HierarchicalASTVisitor {
private TypeEnvironment fTypeEnvironment;
public CreationChecker() {
fTypeEnvironment= new TypeEnvironment();
}
public boolean visit(SimpleName node) {
IBinding binding= node.resolveBinding();
if (!(binding instanceof ITypeBinding))
return true;
checkTypeBinding(binding);
return true;
}
private void checkTypeBinding(IBinding binding) {
ITypeBinding type= (ITypeBinding)binding;
if (!(type.isPrimitive() && type.getName().equals("void"))) {
TType refType= fTypeEnvironment.create(type);
assertNotNull("Refactoring type is null", refType);
assertEquals("Not same name", type.getName(), refType.getName());
assertEquals("Not same signature", PrettySignatures.get(type), refType.getPrettySignature());
assertTrue("Not same type", refType == fTypeEnvironment.create(type));
}
}
public boolean visit(org.eclipse.jdt.core.dom.Type node) {
checkTypeBinding(node.resolveBinding());
return true;
}
}
private static class TypeBindingCollector extends ASTVisitor {
private List fResult= new ArrayList();
private List fWildcards= new ArrayList();
public boolean visit(FieldDeclaration node) {
VariableDeclarationFragment fragment= (VariableDeclarationFragment)node.fragments().get(0);
if (fragment.getName().getIdentifier().equals("NullType")) {
fResult.add(fragment.getInitializer().resolveTypeBinding());
} else {
fResult.add(fragment.resolveBinding().getType());
}
return false;
}
public void endVisit(CompilationUnit node) {
for (Iterator iter= fResult.iterator(); iter.hasNext();) {
ITypeBinding binding= (ITypeBinding)iter.next();
if (binding.isParameterizedType()) {
ITypeBinding[] args= binding.getTypeArguments();
for (int i= 0; i < args.length; i++) {
if (args[i].isWildcardType()) {
fWildcards.add(args[i]);
}
}
}
}
}
public ITypeBinding[] getResult() {
return (ITypeBinding[])fResult.toArray(new ITypeBinding[fResult.size()]);
}
public ITypeBinding[] getWildcards() {
return (ITypeBinding[])fWildcards.toArray(new ITypeBinding[fWildcards.size()]);
}
}
private static class CaptureTypeBindingCollector extends ASTVisitor {
private List fResult= new ArrayList();
public boolean visit(Assignment node) {
Expression expression= node.getRightHandSide();
ITypeBinding typeBinding= expression.resolveTypeBinding();
fResult.add(typeBinding);
collectTypeArgumentBindings(typeBinding, fResult);
return false;
}
private void collectTypeArgumentBindings(ITypeBinding typeBinding, List result) {
if (! typeBinding.isParameterizedType())
return;
ITypeBinding[] typeArguments= typeBinding.getTypeArguments();
for (int i= 0; i < typeArguments.length; i++) {
ITypeBinding typeArgument= typeArguments[i];
if (BUG_83616_core_wildcard_assignments && typeArgument.isParameterizedType() && typeArgument.getTypeArguments()[0].isWildcardType())
continue;
result.add(typeArgument);
collectTypeArgumentBindings(typeArgument, result);
}
}
public ITypeBinding[] getResult() {
return (ITypeBinding[])fResult.toArray(new ITypeBinding[fResult.size()]);
}
}
public TypeEnvironmentTests(String name) {
super(name);
}
public static Test suite() {
return new MyTestSetup(new TestSuite(TypeEnvironmentTests.class));
}
public static Test setUpTest(Test someTest) {
return new MyTestSetup(someTest);
}
protected InputStream getFileInputStream(String fileName) throws IOException {
return RefactoringTestPlugin.getDefault().getTestResourceStream(fileName);
}
protected String getResourceLocation() {
return "TypeEnvironment/TestProject/";
}
protected String adaptName(String name) {
return Character.toUpperCase(name.charAt(0)) + name.substring(1) + ".java";
}
private ASTNode createAST(IPackageFragment pack) throws Exception {
IJavaProject project= pack.getJavaProject();
ASTParser parser= ASTParser.newParser(AST.JLS3);
parser.setProject(project);
parser.setResolveBindings(true);
ICompilationUnit unit= createCU(pack, getName());
parser.setSource(unit);
return parser.createAST(null);
}
//---- creation ----------------------------------------------------------
private void performCreationTest() throws Exception {
createAST(MyTestSetup.getSignaturePackage()).accept(new CreationChecker());
}
public void testArrays() throws Exception {
performCreationTest();
}
public void testStandardTypes() throws Exception {
performCreationTest();
}
public void testRawTypes() throws Exception {
performCreationTest();
}
public void testGenericTypes() throws Exception {
performCreationTest();
}
public void testWildcardTypes() throws Exception {
performCreationTest();
}
public void testPrimitiveTypes() throws Exception {
performCreationTest();
}
public void testTypeVariables() throws Exception {
performCreationTest();
}
//---- generic assigment test ----------------------------------------------
private void performGenericAssignmentTest() throws Exception {
ASTNode node= createAST(MyTestSetup.getGenericPackage());
TypeBindingCollector collector= new TypeBindingCollector();
node.accept(collector);
testBindings(collector.getResult());
testAssignment(collector.getWildcards());
}
private void testBindings(ITypeBinding[] bindings) throws Exception {
TType[] types= new TType[bindings.length];
TypeEnvironment environment= new TypeEnvironment();
for (int i= 0; i < bindings.length; i++) {
types[i]= environment.create(bindings[i]);
assertEquals("Not same name", bindings[i].getName(), types[i].getName());
assertEquals("Not same signature", PrettySignatures.get(bindings[i]), types[i].getPrettySignature());
assertEquals("Not same modifiers", bindings[i].getModifiers(), types[i].getModifiers());
testFlags(bindings[i], types[i]);
assertTrue("Not same erasure", types[i].getErasure().isEqualTo(bindings[i].getErasure()));
assertTrue("Not same type declaration", types[i].getTypeDeclaration().isEqualTo(bindings[i].getTypeDeclaration()));
assertTrue("Not same type", types[i] == environment.create(bindings[i]));
}
for (int o= 0; o < bindings.length; o++) {
for (int i= 0; i < bindings.length; i++) {
checkCanAssignTo(bindings[o], bindings[i], types[o], types[i]);
}
}
TypeEnvironment secondEnvironment= new TypeEnvironment();
for (int i= 0; i < bindings.length; i++) {
assertTrue("Equal to second environment", types[i].equals(secondEnvironment.create(bindings[i])));
}
ITypeBinding[] restoredBindings= TypeEnvironment.createTypeBindings(types, RefactoringTestSetup.getProject());
assertEquals("Not same length", restoredBindings.length, bindings.length);
for (int i= 0; i < restoredBindings.length; i++) {
assertTrue("Not same binding", bindings[i].isEqualTo(restoredBindings[i]));
}
}
private void checkCanAssignTo(ITypeBinding rhsBinding, ITypeBinding lhsBinding, TType rhs, TType lhs) {
boolean coreResult= rhsBinding.isAssignmentCompatible(lhsBinding);
boolean uiResult= rhs.canAssignTo(lhs);
if (coreResult != uiResult) {
if (lhs.isCaptureType() || rhs.isCaptureType()) { // see bug 93082
System.out.println("Different assignment rule(" +
PrettySignatures.get(lhsBinding) + "= " + PrettySignatures.get(rhsBinding) +
"): Bindings<" + coreResult +
"> TType<" + uiResult + ">");
return;
}
}
assertEquals("Different assignment rule(" +
PrettySignatures.get(lhsBinding) + "= " + PrettySignatures.get(rhsBinding) +
"): ", coreResult, uiResult);
}
private void testAssignment(ITypeBinding[] bindings) {
TType[] types= new TType[bindings.length];
TypeEnvironment environment= new TypeEnvironment();
for (int i= 0; i < bindings.length; i++) {
types[i]= environment.create(bindings[i]);
}
for (int o= 0; o < bindings.length; o++) {
for (int i= 0; i < bindings.length; i++) {
ITypeBinding oBinding= bindings[o];
ITypeBinding iBinding= bindings[i];
boolean coreResult= oBinding.isAssignmentCompatible(iBinding);
TType oType= types[o];
TType iType= types[i];
boolean uiResult= oType.canAssignTo(iType);
if (coreResult != uiResult && !oType.isWildcardType() && ! BUG_83616_core_wildcard_assignments) { // see bug 83616
System.out.println("Different assignment rule(" +
PrettySignatures.get(iBinding) + "= " + PrettySignatures.get(oBinding) +
"): Bindings<" + coreResult +
"> TType<" + uiResult + ">");
}
}
}
}
private void testFlags(ITypeBinding binding, TType type) {
assertEquals("Different class flag", binding.isClass(), type.isClass());
assertEquals("Different enum flag", binding.isEnum(), type.isEnum());
assertEquals("Different interface flag", binding.isInterface(), type.isInterface());
assertEquals("Different annotation flag", binding.isAnnotation(), type.isAnnotation());
assertEquals("Different top level flag", binding.isTopLevel(), type.isTopLevel());
assertEquals("Different nested flag", binding.isNested(), type.isNested());
assertEquals("Different local flag", binding.isLocal(), type.isLocal());
assertEquals("Different member flag", binding.isMember(), type.isMember());
assertEquals("Different anonymous flag", binding.isAnonymous(), type.isAnonymous());
}
public void testStandardAssignments() throws Exception {
performGenericAssignmentTest();
}
public void testWildcardAssignments() throws Exception {
performGenericAssignmentTest();
}
public void testTypeVariableAssignments() throws Exception {
performGenericAssignmentTest();
}
public void testCaptureAssignments() throws Exception {
ASTNode node= createAST(MyTestSetup.getGenericPackage());
CaptureTypeBindingCollector collector= new CaptureTypeBindingCollector();
node.accept(collector);
testBindings(collector.getResult());
}
public void _testAssignment() throws Exception {
ASTNode node= createAST(MyTestSetup.getGenericPackage());
TypeBindingCollector collector= new TypeBindingCollector();
node.accept(collector);
ITypeBinding[] bindings= collector.getResult();
TType[] types= new TType[bindings.length];
TypeEnvironment environment= new TypeEnvironment();
for (int i= 0; i < bindings.length; i++) {
types[i]= environment.create(bindings[i]);
}
System.out.println(PrettySignatures.get(bindings[0]) + "= " + PrettySignatures.get(bindings[1]) +
": " + bindings[1].isAssignmentCompatible(bindings[0]));
// types[1].canAssignTo(types[0]);
}
public void _testParameterizedToGeneric() throws Exception {
ASTNode node= createAST(MyTestSetup.getGenericPackage());
TypeBindingCollector collector= new TypeBindingCollector();
node.accept(collector);
ITypeBinding[] bindings= collector.getResult();
bindings[0]= bindings[0].getTypeDeclaration();
System.out.println(PrettySignatures.get(bindings[0]) + "= " + PrettySignatures.get(bindings[1]) +
": " + bindings[1].isAssignmentCompatible(bindings[0]));
System.out.println(PrettySignatures.get(bindings[0]) + "= " + PrettySignatures.get(bindings[0]) +
": " + bindings[0].isAssignmentCompatible(bindings[0]));
bindings[1]= bindings[1].getTypeDeclaration();
System.out.println(PrettySignatures.get(bindings[0]) + "= " + PrettySignatures.get(bindings[1]) +
": " + bindings[1].isAssignmentCompatible(bindings[0]));
}
}