/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.engine.internal.type; import com.google.dart.engine.EngineTestCase; import com.google.dart.engine.element.ClassElement; import com.google.dart.engine.element.CompilationUnitElement; import com.google.dart.engine.element.ElementFactory; import com.google.dart.engine.element.MethodElement; import com.google.dart.engine.element.PropertyAccessorElement; import com.google.dart.engine.internal.element.ClassElementImpl; import com.google.dart.engine.internal.element.CompilationUnitElementImpl; import com.google.dart.engine.internal.element.FunctionElementImpl; import com.google.dart.engine.internal.element.LibraryElementImpl; import com.google.dart.engine.internal.element.MethodElementImpl; import com.google.dart.engine.internal.element.TypeParameterElementImpl; import com.google.dart.engine.internal.resolver.TestTypeProvider; import com.google.dart.engine.type.FunctionType; import com.google.dart.engine.type.InterfaceType; import com.google.dart.engine.type.Type; import com.google.dart.engine.type.TypeParameterType; import static com.google.dart.engine.ast.AstFactory.identifier; import static com.google.dart.engine.element.ElementFactory.classElement; import static com.google.dart.engine.element.ElementFactory.functionElement; import static com.google.dart.engine.element.ElementFactory.getterElement; import static com.google.dart.engine.element.ElementFactory.library; import static com.google.dart.engine.element.ElementFactory.methodElement; import static com.google.dart.engine.element.ElementFactory.setterElement; import java.util.Set; public class InterfaceTypeImplTest extends EngineTestCase { /** * The type provider used to access the types. */ private TestTypeProvider typeProvider; @Override public void setUp() throws Exception { typeProvider = new TestTypeProvider(); } public void test_computeLongestInheritancePathToObject_multipleInterfacePaths() { // // Object // | // A // / \ // B C // | | // | D // \ / // E // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); ClassElementImpl classD = classElement("D"); ClassElementImpl classE = classElement("E"); classB.setInterfaces(new InterfaceType[] {classA.getType()}); classC.setInterfaces(new InterfaceType[] {classA.getType()}); classD.setInterfaces(new InterfaceType[] {classC.getType()}); classE.setInterfaces(new InterfaceType[] {classB.getType(), classD.getType()}); // assertion: even though the longest path to Object for typeB is 2, and typeE implements typeB, // the longest path for typeE is 4 since it also implements typeD assertEquals(2, InterfaceTypeImpl.computeLongestInheritancePathToObject(classB.getType())); assertEquals(4, InterfaceTypeImpl.computeLongestInheritancePathToObject(classE.getType())); } public void test_computeLongestInheritancePathToObject_multipleSuperclassPaths() { // // Object // | // A // / \ // B C // | | // | D // \ / // E // ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElement classC = classElement("C", classA.getType()); ClassElement classD = classElement("D", classC.getType()); ClassElementImpl classE = classElement("E", classB.getType()); classE.setInterfaces(new InterfaceType[] {classD.getType()}); // assertion: even though the longest path to Object for typeB is 2, and typeE extends typeB, // the longest path for typeE is 4 since it also implements typeD assertEquals(2, InterfaceTypeImpl.computeLongestInheritancePathToObject(classB.getType())); assertEquals(4, InterfaceTypeImpl.computeLongestInheritancePathToObject(classE.getType())); } public void test_computeLongestInheritancePathToObject_object() { // // Object // | // A // ClassElement classA = classElement("A"); InterfaceType object = classA.getSupertype(); assertEquals(0, InterfaceTypeImpl.computeLongestInheritancePathToObject(object)); } public void test_computeLongestInheritancePathToObject_recursion() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); classA.setSupertype(classB.getType()); assertEquals(2, InterfaceTypeImpl.computeLongestInheritancePathToObject(classA.getType())); } public void test_computeLongestInheritancePathToObject_singleInterfacePath() { // // Object // | // A // | // B // | // C // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); classB.setInterfaces(new InterfaceType[] {classA.getType()}); classC.setInterfaces(new InterfaceType[] {classB.getType()}); assertEquals(1, InterfaceTypeImpl.computeLongestInheritancePathToObject(classA.getType())); assertEquals(2, InterfaceTypeImpl.computeLongestInheritancePathToObject(classB.getType())); assertEquals(3, InterfaceTypeImpl.computeLongestInheritancePathToObject(classC.getType())); } public void test_computeLongestInheritancePathToObject_singleSuperclassPath() { // // Object // | // A // | // B // | // C // ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElement classC = classElement("C", classB.getType()); assertEquals(1, InterfaceTypeImpl.computeLongestInheritancePathToObject(classA.getType())); assertEquals(2, InterfaceTypeImpl.computeLongestInheritancePathToObject(classB.getType())); assertEquals(3, InterfaceTypeImpl.computeLongestInheritancePathToObject(classC.getType())); } public void test_computeSuperinterfaceSet_genericInterfacePath() { // // A // | implements // B<T> // | implements // C<T> // // D // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", "T"); ClassElementImpl classC = classElement("C", "T"); ClassElement classD = classElement("D"); InterfaceType typeA = classA.getType(); classB.setInterfaces(new InterfaceType[] {typeA}); InterfaceTypeImpl typeBT = new InterfaceTypeImpl(classB); Type typeT = classC.getType().getTypeArguments()[0]; typeBT.setTypeArguments(new Type[] {typeT}); classC.setInterfaces(new InterfaceType[] {typeBT}); // A Set<InterfaceType> superinterfacesOfA = InterfaceTypeImpl.computeSuperinterfaceSet(typeA); assertSizeOfSet(1, superinterfacesOfA); InterfaceType typeObject = ElementFactory.getObject().getType(); assertTrue(superinterfacesOfA.contains(typeObject)); // B<D> InterfaceTypeImpl typeBD = new InterfaceTypeImpl(classB); typeBD.setTypeArguments(new Type[] {classD.getType()}); Set<InterfaceType> superinterfacesOfBD = InterfaceTypeImpl.computeSuperinterfaceSet(typeBD); assertSizeOfSet(2, superinterfacesOfBD); assertTrue(superinterfacesOfBD.contains(typeObject)); assertTrue(superinterfacesOfBD.contains(typeA)); // C<D> InterfaceTypeImpl typeCD = new InterfaceTypeImpl(classC); typeCD.setTypeArguments(new Type[] {classD.getType()}); Set<InterfaceType> superinterfacesOfCD = InterfaceTypeImpl.computeSuperinterfaceSet(typeCD); assertSizeOfSet(3, superinterfacesOfCD); assertTrue(superinterfacesOfCD.contains(typeObject)); assertTrue(superinterfacesOfCD.contains(typeA)); assertTrue(superinterfacesOfCD.contains(typeBD)); } public void test_computeSuperinterfaceSet_genericSuperclassPath() { // // A // | // B<T> // | // C<T> // // D // ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); ClassElement classB = classElement("B", typeA, "T"); ClassElementImpl classC = classElement("C", "T"); InterfaceTypeImpl typeBT = new InterfaceTypeImpl(classB); Type typeT = classC.getType().getTypeArguments()[0]; typeBT.setTypeArguments(new Type[] {typeT}); classC.setSupertype(typeBT); ClassElement classD = classElement("D"); // A Set<InterfaceType> superinterfacesOfA = InterfaceTypeImpl.computeSuperinterfaceSet(typeA); assertSizeOfSet(1, superinterfacesOfA); InterfaceType typeObject = ElementFactory.getObject().getType(); assertTrue(superinterfacesOfA.contains(typeObject)); // B<D> InterfaceTypeImpl typeBD = new InterfaceTypeImpl(classB); typeBD.setTypeArguments(new Type[] {classD.getType()}); Set<InterfaceType> superinterfacesOfBD = InterfaceTypeImpl.computeSuperinterfaceSet(typeBD); assertSizeOfSet(2, superinterfacesOfBD); assertTrue(superinterfacesOfBD.contains(typeObject)); assertTrue(superinterfacesOfBD.contains(typeA)); // C<D> InterfaceTypeImpl typeCD = new InterfaceTypeImpl(classC); typeCD.setTypeArguments(new Type[] {classD.getType()}); Set<InterfaceType> superinterfacesOfCD = InterfaceTypeImpl.computeSuperinterfaceSet(typeCD); assertSizeOfSet(3, superinterfacesOfCD); assertTrue(superinterfacesOfCD.contains(typeObject)); assertTrue(superinterfacesOfCD.contains(typeA)); assertTrue(superinterfacesOfCD.contains(typeBD)); } public void test_computeSuperinterfaceSet_multipleInterfacePaths() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); ClassElementImpl classD = classElement("D"); ClassElementImpl classE = classElement("E"); classB.setInterfaces(new InterfaceType[] {classA.getType()}); classC.setInterfaces(new InterfaceType[] {classA.getType()}); classD.setInterfaces(new InterfaceType[] {classC.getType()}); classE.setInterfaces(new InterfaceType[] {classB.getType(), classD.getType()}); // D Set<InterfaceType> superinterfacesOfD = InterfaceTypeImpl.computeSuperinterfaceSet(classD.getType()); assertSizeOfSet(3, superinterfacesOfD); assertTrue(superinterfacesOfD.contains(ElementFactory.getObject().getType())); assertTrue(superinterfacesOfD.contains(classA.getType())); assertTrue(superinterfacesOfD.contains(classC.getType())); // E Set<InterfaceType> superinterfacesOfE = InterfaceTypeImpl.computeSuperinterfaceSet(classE.getType()); assertSizeOfSet(5, superinterfacesOfE); assertTrue(superinterfacesOfE.contains(ElementFactory.getObject().getType())); assertTrue(superinterfacesOfE.contains(classA.getType())); assertTrue(superinterfacesOfE.contains(classB.getType())); assertTrue(superinterfacesOfE.contains(classC.getType())); assertTrue(superinterfacesOfE.contains(classD.getType())); } public void test_computeSuperinterfaceSet_multipleSuperclassPaths() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElement classC = classElement("C", classA.getType()); ClassElement classD = classElement("D", classC.getType()); ClassElementImpl classE = classElement("E", classB.getType()); classE.setInterfaces(new InterfaceType[] {classD.getType()}); // D Set<InterfaceType> superinterfacesOfD = InterfaceTypeImpl.computeSuperinterfaceSet(classD.getType()); assertSizeOfSet(3, superinterfacesOfD); assertTrue(superinterfacesOfD.contains(ElementFactory.getObject().getType())); assertTrue(superinterfacesOfD.contains(classA.getType())); assertTrue(superinterfacesOfD.contains(classC.getType())); // E Set<InterfaceType> superinterfacesOfE = InterfaceTypeImpl.computeSuperinterfaceSet(classE.getType()); assertSizeOfSet(5, superinterfacesOfE); assertTrue(superinterfacesOfE.contains(ElementFactory.getObject().getType())); assertTrue(superinterfacesOfE.contains(classA.getType())); assertTrue(superinterfacesOfE.contains(classB.getType())); assertTrue(superinterfacesOfE.contains(classC.getType())); assertTrue(superinterfacesOfE.contains(classD.getType())); } public void test_computeSuperinterfaceSet_recursion() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); classA.setSupertype(classB.getType()); Set<InterfaceType> superinterfacesOfB = InterfaceTypeImpl.computeSuperinterfaceSet(classB.getType()); assertSizeOfSet(2, superinterfacesOfB); } public void test_computeSuperinterfaceSet_singleInterfacePath() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); classB.setInterfaces(new InterfaceType[] {classA.getType()}); classC.setInterfaces(new InterfaceType[] {classB.getType()}); // A Set<InterfaceType> superinterfacesOfA = InterfaceTypeImpl.computeSuperinterfaceSet(classA.getType()); assertSizeOfSet(1, superinterfacesOfA); assertTrue(superinterfacesOfA.contains(ElementFactory.getObject().getType())); // B Set<InterfaceType> superinterfacesOfB = InterfaceTypeImpl.computeSuperinterfaceSet(classB.getType()); assertSizeOfSet(2, superinterfacesOfB); assertTrue(superinterfacesOfB.contains(ElementFactory.getObject().getType())); assertTrue(superinterfacesOfB.contains(classA.getType())); // C Set<InterfaceType> superinterfacesOfC = InterfaceTypeImpl.computeSuperinterfaceSet(classC.getType()); assertSizeOfSet(3, superinterfacesOfC); assertTrue(superinterfacesOfC.contains(ElementFactory.getObject().getType())); assertTrue(superinterfacesOfC.contains(classA.getType())); assertTrue(superinterfacesOfC.contains(classB.getType())); } public void test_computeSuperinterfaceSet_singleSuperclassPath() { // // A // | // B // | // C // ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElement classC = classElement("C", classB.getType()); // A Set<InterfaceType> superinterfacesOfA = InterfaceTypeImpl.computeSuperinterfaceSet(classA.getType()); assertSizeOfSet(1, superinterfacesOfA); assertTrue(superinterfacesOfA.contains(ElementFactory.getObject().getType())); // B Set<InterfaceType> superinterfacesOfB = InterfaceTypeImpl.computeSuperinterfaceSet(classB.getType()); assertSizeOfSet(2, superinterfacesOfB); assertTrue(superinterfacesOfB.contains(ElementFactory.getObject().getType())); assertTrue(superinterfacesOfB.contains(classA.getType())); // C Set<InterfaceType> superinterfacesOfC = InterfaceTypeImpl.computeSuperinterfaceSet(classC.getType()); assertSizeOfSet(3, superinterfacesOfC); assertTrue(superinterfacesOfC.contains(ElementFactory.getObject().getType())); assertTrue(superinterfacesOfC.contains(classA.getType())); assertTrue(superinterfacesOfC.contains(classB.getType())); } public void test_creation() { assertNotNull(new InterfaceTypeImpl(classElement("A"))); } public void test_getAccessors() { ClassElementImpl typeElement = classElement("A"); PropertyAccessorElement getterG = getterElement("g", false, null); PropertyAccessorElement getterH = getterElement("h", false, null); typeElement.setAccessors(new PropertyAccessorElement[] {getterG, getterH}); InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement); assertEquals(2, type.getAccessors().length); } public void test_getAccessors_empty() { ClassElementImpl typeElement = classElement("A"); InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement); assertEquals(0, type.getAccessors().length); } public void test_getElement() { ClassElementImpl typeElement = classElement("A"); InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement); assertEquals(typeElement, type.getElement()); } public void test_getGetter_implemented() { // // class A { g {} } // ClassElementImpl classA = classElement("A"); String getterName = "g"; PropertyAccessorElement getterG = getterElement(getterName, false, null); classA.setAccessors(new PropertyAccessorElement[] {getterG}); InterfaceType typeA = classA.getType(); assertSame(getterG, typeA.getGetter(getterName)); } public void test_getGetter_parameterized() { // // class A<E> { E get g {} } // ClassElementImpl classA = classElement("A", "E"); Type typeE = classA.getType().getTypeArguments()[0]; String getterName = "g"; PropertyAccessorElement getterG = getterElement(getterName, false, typeE); classA.setAccessors(new PropertyAccessorElement[] {getterG}); ((FunctionTypeImpl) getterG.getType()).setTypeArguments(classA.getType().getTypeArguments()); // // A<I> // InterfaceType typeI = classElement("I").getType(); InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA); typeAI.setTypeArguments(new Type[] {typeI}); PropertyAccessorElement getter = typeAI.getGetter(getterName); assertNotNull(getter); FunctionType getterType = getter.getType(); assertSame(typeI, getterType.getReturnType()); } public void test_getGetter_unimplemented() { // // class A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); assertNull(typeA.getGetter("g")); } public void test_getInterfaces_nonParameterized() { // // class C implements A, B // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); ClassElementImpl classB = classElement("B"); InterfaceType typeB = classB.getType(); ClassElementImpl classC = classElement("C"); classC.setInterfaces(new InterfaceType[] {typeA, typeB}); InterfaceType[] interfaces = classC.getType().getInterfaces(); assertLength(2, interfaces); if (interfaces[0] == typeA) { assertSame(typeB, interfaces[1]); } else { assertSame(typeB, interfaces[0]); assertSame(typeA, interfaces[1]); } } public void test_getInterfaces_parameterized() { // // class A<E> // class B<F> implements A<F> // ClassElementImpl classA = classElement("A", "E"); ClassElementImpl classB = classElement("B", "F"); InterfaceType typeB = classB.getType(); InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA); typeAF.setTypeArguments(new Type[] {typeB.getTypeArguments()[0]}); classB.setInterfaces(new InterfaceType[] {typeAF}); // // B<I> // InterfaceType typeI = classElement("I").getType(); InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB); typeBI.setTypeArguments(new Type[] {typeI}); InterfaceType[] interfaces = typeBI.getInterfaces(); assertLength(1, interfaces); InterfaceType result = interfaces[0]; assertSame(classA, result.getElement()); assertSame(typeI, result.getTypeArguments()[0]); } public void test_getLeastUpperBound_directInterfaceCase() { // // class A // class B implements A // class C implements B // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); classB.setInterfaces(new InterfaceType[] {typeA}); classC.setInterfaces(new InterfaceType[] {typeB}); assertEquals(typeB, typeB.getLeastUpperBound(typeC)); assertEquals(typeB, typeC.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_directSubclassCase() { // // class A // class B extends A // class C extends B // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C", classB.getType()); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); assertEquals(typeB, typeB.getLeastUpperBound(typeC)); assertEquals(typeB, typeC.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_functionType() { Type interfaceType = classElement("A").getType(); FunctionTypeImpl functionType = new FunctionTypeImpl(new FunctionElementImpl(identifier("f"))); assertNull(interfaceType.getLeastUpperBound(functionType)); } public void test_getLeastUpperBound_mixinCase() { // // class A // class B extends A // class C extends A // class D extends B with M, N, O, P // ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElement classC = classElement("C", classA.getType()); ClassElementImpl classD = classElement("D", classB.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); InterfaceType typeD = classD.getType(); classD.setMixins(new InterfaceType[] { classElement("M").getType(), classElement("N").getType(), classElement("O").getType(), classElement("P").getType()}); assertEquals(typeA, typeD.getLeastUpperBound(typeC)); assertEquals(typeA, typeC.getLeastUpperBound(typeD)); } public void test_getLeastUpperBound_null() { Type interfaceType = classElement("A").getType(); assertNull(interfaceType.getLeastUpperBound(null)); } public void test_getLeastUpperBound_object() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); Type typeObject = typeA.getElement().getSupertype(); // assert that object does not have a super type assertNull(((ClassElement) typeObject.getElement()).getSupertype()); // assert that both A and B have the same super type of Object assertEquals(typeObject, typeB.getElement().getSupertype()); // finally, assert that the only least upper bound of A and B is Object assertEquals(typeObject, typeA.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_self() { ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); assertEquals(typeA, typeA.getLeastUpperBound(typeA)); } public void test_getLeastUpperBound_sharedSuperclass1() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C", classA.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); assertEquals(typeA, typeB.getLeastUpperBound(typeC)); assertEquals(typeA, typeC.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_sharedSuperclass2() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C", classA.getType()); ClassElementImpl classD = classElement("D", classC.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeD = classD.getType(); assertEquals(typeA, typeB.getLeastUpperBound(typeD)); assertEquals(typeA, typeD.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_sharedSuperclass3() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C", classB.getType()); ClassElementImpl classD = classElement("D", classB.getType()); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); InterfaceType typeD = classD.getType(); assertEquals(typeB, typeC.getLeastUpperBound(typeD)); assertEquals(typeB, typeD.getLeastUpperBound(typeC)); } public void test_getLeastUpperBound_sharedSuperclass4() { ClassElement classA = classElement("A"); ClassElement classA2 = classElement("A2"); ClassElement classA3 = classElement("A3"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C", classA.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeA2 = classA2.getType(); InterfaceType typeA3 = classA3.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); classB.setInterfaces(new InterfaceType[] {typeA2}); classC.setInterfaces(new InterfaceType[] {typeA3}); assertEquals(typeA, typeB.getLeastUpperBound(typeC)); assertEquals(typeA, typeC.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_sharedSuperinterface1() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); classB.setInterfaces(new InterfaceType[] {typeA}); classC.setInterfaces(new InterfaceType[] {typeA}); assertEquals(typeA, typeB.getLeastUpperBound(typeC)); assertEquals(typeA, typeC.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_sharedSuperinterface2() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); ClassElementImpl classD = classElement("D"); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); InterfaceType typeD = classD.getType(); classB.setInterfaces(new InterfaceType[] {typeA}); classC.setInterfaces(new InterfaceType[] {typeA}); classD.setInterfaces(new InterfaceType[] {typeC}); assertEquals(typeA, typeB.getLeastUpperBound(typeD)); assertEquals(typeA, typeD.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_sharedSuperinterface3() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); ClassElementImpl classD = classElement("D"); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); InterfaceType typeD = classD.getType(); classB.setInterfaces(new InterfaceType[] {typeA}); classC.setInterfaces(new InterfaceType[] {typeB}); classD.setInterfaces(new InterfaceType[] {typeB}); assertEquals(typeB, typeC.getLeastUpperBound(typeD)); assertEquals(typeB, typeD.getLeastUpperBound(typeC)); } public void test_getLeastUpperBound_sharedSuperinterface4() { ClassElement classA = classElement("A"); ClassElement classA2 = classElement("A2"); ClassElement classA3 = classElement("A3"); ClassElementImpl classB = classElement("B"); ClassElementImpl classC = classElement("C"); InterfaceType typeA = classA.getType(); InterfaceType typeA2 = classA2.getType(); InterfaceType typeA3 = classA3.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); classB.setInterfaces(new InterfaceType[] {typeA, typeA2}); classC.setInterfaces(new InterfaceType[] {typeA, typeA3}); assertEquals(typeA, typeB.getLeastUpperBound(typeC)); assertEquals(typeA, typeC.getLeastUpperBound(typeB)); } public void test_getLeastUpperBound_twoComparables() { InterfaceType string = typeProvider.getStringType(); InterfaceType num = typeProvider.getNumType(); assertEquals(typeProvider.getObjectType(), string.getLeastUpperBound(num)); } public void test_getLeastUpperBound_typeParameters_different() { // // class List<int> // class List<double> // InterfaceType listType = typeProvider.getListType(); InterfaceType intType = typeProvider.getIntType(); InterfaceType doubleType = typeProvider.getDoubleType(); InterfaceType listOfIntType = listType.substitute(new Type[] {intType}); InterfaceType listOfDoubleType = listType.substitute(new Type[] {doubleType}); assertEquals(typeProvider.getObjectType(), listOfIntType.getLeastUpperBound(listOfDoubleType)); } public void test_getLeastUpperBound_typeParameters_same() { // // List<int> // List<int> // InterfaceType listType = typeProvider.getListType(); InterfaceType intType = typeProvider.getIntType(); InterfaceType listOfIntType = listType.substitute(new Type[] {intType}); assertEquals(listOfIntType, listOfIntType.getLeastUpperBound(listOfIntType)); } public void test_getMethod_implemented() { // // class A { m() {} } // ClassElementImpl classA = classElement("A"); String methodName = "m"; MethodElementImpl methodM = methodElement(methodName, null); classA.setMethods(new MethodElement[] {methodM}); InterfaceType typeA = classA.getType(); assertSame(methodM, typeA.getMethod(methodName)); } public void test_getMethod_parameterized() { // // class A<E> { E m(E p) {} } // ClassElementImpl classA = classElement("A", "E"); Type typeE = classA.getType().getTypeArguments()[0]; String methodName = "m"; MethodElementImpl methodM = methodElement(methodName, typeE, typeE); classA.setMethods(new MethodElement[] {methodM}); ((FunctionTypeImpl) methodM.getType()).setTypeArguments(classA.getType().getTypeArguments()); // // A<I> // InterfaceType typeI = classElement("I").getType(); InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA); typeAI.setTypeArguments(new Type[] {typeI}); MethodElement method = typeAI.getMethod(methodName); assertNotNull(method); FunctionType methodType = method.getType(); assertSame(typeI, methodType.getReturnType()); Type[] parameterTypes = methodType.getNormalParameterTypes(); assertLength(1, parameterTypes); assertSame(typeI, parameterTypes[0]); } public void test_getMethod_unimplemented() { // // class A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); assertNull(typeA.getMethod("m")); } public void test_getMethods() { ClassElementImpl typeElement = classElement("A"); MethodElementImpl methodOne = methodElement("one", null); MethodElementImpl methodTwo = methodElement("two", null); typeElement.setMethods(new MethodElement[] {methodOne, methodTwo}); InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement); assertEquals(2, type.getMethods().length); } public void test_getMethods_empty() { ClassElementImpl typeElement = classElement("A"); InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement); assertEquals(0, type.getMethods().length); } public void test_getMixins_nonParameterized() { // // class C extends Object with A, B // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); ClassElementImpl classB = classElement("B"); InterfaceType typeB = classB.getType(); ClassElementImpl classC = classElement("C"); classC.setMixins(new InterfaceType[] {typeA, typeB}); InterfaceType[] interfaces = classC.getType().getMixins(); assertLength(2, interfaces); if (interfaces[0] == typeA) { assertSame(typeB, interfaces[1]); } else { assertSame(typeB, interfaces[0]); assertSame(typeA, interfaces[1]); } } public void test_getMixins_parameterized() { // // class A<E> // class B<F> extends Object with A<F> // ClassElementImpl classA = classElement("A", "E"); ClassElementImpl classB = classElement("B", "F"); InterfaceType typeB = classB.getType(); InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA); typeAF.setTypeArguments(new Type[] {typeB.getTypeArguments()[0]}); classB.setMixins(new InterfaceType[] {typeAF}); // // B<I> // InterfaceType typeI = classElement("I").getType(); InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB); typeBI.setTypeArguments(new Type[] {typeI}); InterfaceType[] interfaces = typeBI.getMixins(); assertLength(1, interfaces); InterfaceType result = interfaces[0]; assertSame(classA, result.getElement()); assertSame(typeI, result.getTypeArguments()[0]); } public void test_getSetter_implemented() { // // class A { s() {} } // ClassElementImpl classA = classElement("A"); String setterName = "s"; PropertyAccessorElement setterS = setterElement(setterName, false, null); classA.setAccessors(new PropertyAccessorElement[] {setterS}); InterfaceType typeA = classA.getType(); assertSame(setterS, typeA.getSetter(setterName)); } public void test_getSetter_parameterized() { // // class A<E> { set s(E p) {} } // ClassElementImpl classA = classElement("A", "E"); Type typeE = classA.getType().getTypeArguments()[0]; String setterName = "s"; PropertyAccessorElement setterS = setterElement(setterName, false, typeE); classA.setAccessors(new PropertyAccessorElement[] {setterS}); ((FunctionTypeImpl) setterS.getType()).setTypeArguments(classA.getType().getTypeArguments()); // // A<I> // InterfaceType typeI = classElement("I").getType(); InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA); typeAI.setTypeArguments(new Type[] {typeI}); PropertyAccessorElement setter = typeAI.getSetter(setterName); assertNotNull(setter); FunctionType setterType = setter.getType(); Type[] parameterTypes = setterType.getNormalParameterTypes(); assertLength(1, parameterTypes); assertSame(typeI, parameterTypes[0]); } public void test_getSetter_unimplemented() { // // class A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); assertNull(typeA.getSetter("s")); } public void test_getSuperclass_nonParameterized() { // // class B extends A // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); ClassElementImpl classB = classElement("B", typeA); InterfaceType typeB = classB.getType(); assertSame(typeA, typeB.getSuperclass()); } public void test_getSuperclass_parameterized() { // // class A<E> // class B<F> extends A<F> // ClassElementImpl classA = classElement("A", "E"); ClassElementImpl classB = classElement("B", "F"); InterfaceType typeB = classB.getType(); InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA); typeAF.setTypeArguments(new Type[] {typeB.getTypeArguments()[0]}); classB.setSupertype(typeAF); // // B<I> // InterfaceType typeI = classElement("I").getType(); InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB); typeBI.setTypeArguments(new Type[] {typeI}); InterfaceType superclass = typeBI.getSuperclass(); assertSame(classA, superclass.getElement()); assertSame(typeI, superclass.getTypeArguments()[0]); } public void test_getTypeArguments_empty() { InterfaceType type = classElement("A").getType(); assertLength(0, type.getTypeArguments()); } public void test_hashCode() { ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); assertFalse(0 == typeA.hashCode()); } public void test_isAssignableTo_typeVariables() { // // class A<E> {} // class B<F, G> { // A<F> af; // f (A<G> ag) { // af = ag; // } // } // ClassElement classA = classElement("A", "E"); ClassElement classB = classElement("B", "F", "G"); InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA); typeAF.setTypeArguments(new Type[] {classB.getTypeParameters()[0].getType()}); InterfaceTypeImpl typeAG = new InterfaceTypeImpl(classA); typeAG.setTypeArguments(new Type[] {classB.getTypeParameters()[1].getType()}); assertFalse(typeAG.isAssignableTo(typeAF)); } public void test_isAssignableTo_void() { assertFalse(VoidTypeImpl.getInstance().isAssignableTo(typeProvider.getIntType())); } public void test_isDirectSupertypeOf_extends() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); assertTrue(typeA.isDirectSupertypeOf(typeB)); } public void test_isDirectSupertypeOf_false() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B"); ClassElement classC = classElement("C", classB.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); assertFalse(typeA.isDirectSupertypeOf(typeC)); } public void test_isDirectSupertypeOf_implements() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); classB.setInterfaces(new InterfaceType[] {typeA}); assertTrue(typeA.isDirectSupertypeOf(typeB)); } public void test_isDirectSupertypeOf_with() { ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B"); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); classB.setMixins(new InterfaceType[] {typeA}); assertTrue(typeA.isDirectSupertypeOf(typeB)); } public void test_isMoreSpecificThan_bottom() { Type type = classElement("A").getType(); assertTrue(BottomTypeImpl.getInstance().isMoreSpecificThan(type)); } public void test_isMoreSpecificThan_covariance() { ClassElement classA = classElement("A", "E"); ClassElement classI = classElement("I"); ClassElement classJ = classElement("J", classI.getType()); InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA); InterfaceTypeImpl typeAJ = new InterfaceTypeImpl(classA); typeAI.setTypeArguments(new Type[] {classI.getType()}); typeAJ.setTypeArguments(new Type[] {classJ.getType()}); assertTrue(typeAJ.isMoreSpecificThan(typeAI)); assertFalse(typeAI.isMoreSpecificThan(typeAJ)); } public void test_isMoreSpecificThan_directSupertype() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); assertTrue(typeB.isMoreSpecificThan(typeA)); // the opposite test tests a different branch in isMoreSpecificThan() assertFalse(typeA.isMoreSpecificThan(typeB)); } public void test_isMoreSpecificThan_dynamic() { InterfaceType type = classElement("A").getType(); assertTrue(type.isMoreSpecificThan(DynamicTypeImpl.getInstance())); } public void test_isMoreSpecificThan_generic() { ClassElement classA = classElement("A", "E"); ClassElement classB = classElement("B"); Type dynamicType = DynamicTypeImpl.getInstance(); InterfaceType typeAOfDynamic = classA.getType().substitute(new Type[] {dynamicType}); InterfaceType typeAOfB = classA.getType().substitute(new Type[] {classB.getType()}); assertFalse(typeAOfDynamic.isMoreSpecificThan(typeAOfB)); assertTrue(typeAOfB.isMoreSpecificThan(typeAOfDynamic)); } public void test_isMoreSpecificThan_self() { InterfaceType type = classElement("A").getType(); assertTrue(type.isMoreSpecificThan(type)); } public void test_isMoreSpecificThan_transitive_interface() { // // class A {} // class B extends A {} // class C implements B {} // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C"); classC.setInterfaces(new InterfaceType[] {classB.getType()}); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); assertTrue(typeC.isMoreSpecificThan(typeA)); } public void test_isMoreSpecificThan_transitive_mixin() { // // class A {} // class B extends A {} // class C with B {} // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C"); classC.setMixins(new InterfaceType[] {classB.getType()}); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); assertTrue(typeC.isMoreSpecificThan(typeA)); } public void test_isMoreSpecificThan_transitive_recursive() { // // class A extends B {} // class B extends A {} // class C {} // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C"); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); classA.setSupertype(classB.getType()); assertFalse(typeA.isMoreSpecificThan(typeC)); } public void test_isMoreSpecificThan_transitive_superclass() { // // class A {} // class B extends A {} // class C extends B {} // ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElement classC = classElement("C", classB.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); assertTrue(typeC.isMoreSpecificThan(typeA)); } public void test_isMoreSpecificThan_typeParameterType() { // // class A<E> {} // ClassElement classA = classElement("A", "E"); InterfaceType typeA = classA.getType(); TypeParameterType parameterType = classA.getTypeParameters()[0].getType(); Type objectType = typeProvider.getObjectType(); assertTrue(parameterType.isMoreSpecificThan(objectType)); assertFalse(parameterType.isMoreSpecificThan(typeA)); } public void test_isMoreSpecificThan_typeParameterType_withBound() { // // class A {} // class B<E extends A> {} // ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); ClassElementImpl classB = classElement("B"); TypeParameterElementImpl parameterEA = new TypeParameterElementImpl(identifier("E")); TypeParameterType parameterAEType = new TypeParameterTypeImpl(parameterEA); parameterEA.setBound(typeA); parameterEA.setType(parameterAEType); classB.setTypeParameters(new TypeParameterElementImpl[] {parameterEA}); assertTrue(parameterAEType.isMoreSpecificThan(typeA)); } public void test_isSubtypeOf_directSubtype() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); assertTrue(typeB.isSubtypeOf(typeA)); assertFalse(typeA.isSubtypeOf(typeB)); } public void test_isSubtypeOf_dynamic() { ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); Type dynamicType = DynamicTypeImpl.getInstance(); assertTrue(dynamicType.isSubtypeOf(typeA)); assertTrue(typeA.isSubtypeOf(dynamicType)); } public void test_isSubtypeOf_function() throws Exception { // // void f(String s) {} // class A { // void call(String s) {} // } // InterfaceType stringType = typeProvider.getStringType(); ClassElementImpl classA = classElement("A"); classA.setMethods(new MethodElement[] {methodElement( "call", VoidTypeImpl.getInstance(), stringType)}); FunctionType functionType = functionElement("f", new ClassElement[] {stringType.getElement()}).getType(); assertTrue(classA.getType().isSubtypeOf(functionType)); } public void test_isSubtypeOf_generic() { ClassElement classA = classElement("A", "E"); ClassElement classB = classElement("B"); Type dynamicType = DynamicTypeImpl.getInstance(); InterfaceType typeAOfDynamic = classA.getType().substitute(new Type[] {dynamicType}); InterfaceType typeAOfB = classA.getType().substitute(new Type[] {classB.getType()}); assertTrue(typeAOfDynamic.isSubtypeOf(typeAOfB)); assertTrue(typeAOfB.isSubtypeOf(typeAOfDynamic)); } public void test_isSubtypeOf_interface() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C"); InterfaceType typeObject = classA.getSupertype(); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); classC.setInterfaces(new InterfaceType[] {typeB}); assertTrue(typeC.isSubtypeOf(typeB)); assertTrue(typeC.isSubtypeOf(typeObject)); assertTrue(typeC.isSubtypeOf(typeA)); assertFalse(typeA.isSubtypeOf(typeC)); } public void test_isSubtypeOf_mixins() { // // class A {} // class B extends A {} // class C with B {} // ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C"); InterfaceType typeObject = classA.getSupertype(); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); classC.setMixins(new InterfaceType[] {typeB}); assertTrue(typeC.isSubtypeOf(typeB)); assertTrue(typeC.isSubtypeOf(typeObject)); assertTrue(typeC.isSubtypeOf(typeA)); assertFalse(typeA.isSubtypeOf(typeC)); } public void test_isSubtypeOf_object() { ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); InterfaceType typeObject = classA.getSupertype(); assertTrue(typeA.isSubtypeOf(typeObject)); assertFalse(typeObject.isSubtypeOf(typeA)); } public void test_isSubtypeOf_self() { ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); assertTrue(typeA.isSubtypeOf(typeA)); } public void test_isSubtypeOf_transitive_recursive() { // // class A extends B {} // class B extends A {} // class C {} // ClassElementImpl classA = classElement("A"); ClassElementImpl classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C"); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); classA.setSupertype(classB.getType()); assertFalse(typeA.isSubtypeOf(typeC)); } public void test_isSubtypeOf_transitive_superclass() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElement classC = classElement("C", classB.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); assertTrue(typeC.isSubtypeOf(typeA)); assertFalse(typeA.isSubtypeOf(typeC)); } public void test_isSubtypeOf_typeArguments() { Type dynamicType = DynamicTypeImpl.getInstance(); ClassElement classA = classElement("A", "E"); ClassElement classI = classElement("I"); ClassElement classJ = classElement("J", classI.getType()); ClassElement classK = classElement("K"); InterfaceType typeA = classA.getType(); InterfaceType typeA_dynamic = typeA.substitute(new Type[] {dynamicType}); InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA); InterfaceTypeImpl typeAJ = new InterfaceTypeImpl(classA); InterfaceTypeImpl typeAK = new InterfaceTypeImpl(classA); typeAI.setTypeArguments(new Type[] {classI.getType()}); typeAJ.setTypeArguments(new Type[] {classJ.getType()}); typeAK.setTypeArguments(new Type[] {classK.getType()}); // A<J> <: A<I> since J <: I assertTrue(typeAJ.isSubtypeOf(typeAI)); assertFalse(typeAI.isSubtypeOf(typeAJ)); // A<I> <: A<I> since I <: I assertTrue(typeAI.isSubtypeOf(typeAI)); // A <: A<I> and A <: A<J> assertTrue(typeA_dynamic.isSubtypeOf(typeAI)); assertTrue(typeA_dynamic.isSubtypeOf(typeAJ)); // A<I> <: A and A<J> <: A assertTrue(typeAI.isSubtypeOf(typeA_dynamic)); assertTrue(typeAJ.isSubtypeOf(typeA_dynamic)); // A<I> !<: A<K> and A<K> !<: A<I> assertFalse(typeAI.isSubtypeOf(typeAK)); assertFalse(typeAK.isSubtypeOf(typeAI)); } public void test_isSubtypeOf_typeParameter() { // // class A<E> {} // ClassElement classA = classElement("A", "E"); InterfaceType typeA = classA.getType(); TypeParameterType parameterType = classA.getTypeParameters()[0].getType(); assertFalse(typeA.isSubtypeOf(parameterType)); } public void test_isSupertypeOf_directSupertype() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); assertFalse(typeB.isSupertypeOf(typeA)); assertTrue(typeA.isSupertypeOf(typeB)); } public void test_isSupertypeOf_dynamic() { ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); Type dynamicType = DynamicTypeImpl.getInstance(); assertTrue(dynamicType.isSupertypeOf(typeA)); assertTrue(typeA.isSupertypeOf(dynamicType)); } public void test_isSupertypeOf_indirectSupertype() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElement classC = classElement("C", classB.getType()); InterfaceType typeA = classA.getType(); InterfaceType typeC = classC.getType(); assertFalse(typeC.isSupertypeOf(typeA)); assertTrue(typeA.isSupertypeOf(typeC)); } public void test_isSupertypeOf_interface() { ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C"); InterfaceType typeObject = classA.getSupertype(); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); classC.setInterfaces(new InterfaceType[] {typeB}); assertTrue(typeB.isSupertypeOf(typeC)); assertTrue(typeObject.isSupertypeOf(typeC)); assertTrue(typeA.isSupertypeOf(typeC)); assertFalse(typeC.isSupertypeOf(typeA)); } public void test_isSupertypeOf_mixins() { // // class A {} // class B extends A {} // class C with B {} // ClassElement classA = classElement("A"); ClassElement classB = classElement("B", classA.getType()); ClassElementImpl classC = classElement("C"); InterfaceType typeObject = classA.getSupertype(); InterfaceType typeA = classA.getType(); InterfaceType typeB = classB.getType(); InterfaceType typeC = classC.getType(); classC.setMixins(new InterfaceType[] {typeB}); assertTrue(typeB.isSupertypeOf(typeC)); assertTrue(typeObject.isSupertypeOf(typeC)); assertTrue(typeA.isSupertypeOf(typeC)); assertFalse(typeC.isSupertypeOf(typeA)); } public void test_isSupertypeOf_object() { ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); InterfaceType typeObject = classA.getSupertype(); assertFalse(typeA.isSupertypeOf(typeObject)); assertTrue(typeObject.isSupertypeOf(typeA)); } public void test_isSupertypeOf_self() { ClassElement classA = classElement("A"); InterfaceType typeA = classA.getType(); assertTrue(typeA.isSupertypeOf(typeA)); } public void test_lookUpGetter_implemented() { // // class A { g {} } // ClassElementImpl classA = classElement("A"); String getterName = "g"; PropertyAccessorElement getterG = getterElement(getterName, false, null); classA.setAccessors(new PropertyAccessorElement[] {getterG}); InterfaceType typeA = classA.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA}); assertSame(getterG, typeA.lookUpGetter(getterName, library)); } public void test_lookUpGetter_inherited() { // // class A { g {} } // class B extends A {} // ClassElementImpl classA = classElement("A"); String getterName = "g"; PropertyAccessorElement getterG = getterElement(getterName, false, null); classA.setAccessors(new PropertyAccessorElement[] {getterG}); ClassElementImpl classB = classElement("B", classA.getType()); InterfaceType typeB = classB.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA, classB}); assertSame(getterG, typeB.lookUpGetter(getterName, library)); } public void test_lookUpGetter_recursive() { // // class A extends B {} // class B extends A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); ClassElementImpl classB = classElement("B", typeA); classA.setSupertype(classB.getType()); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA, classB}); assertNull(typeA.lookUpGetter("g", library)); } public void test_lookUpGetter_unimplemented() { // // class A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA}); assertNull(typeA.lookUpGetter("g", library)); } public void test_lookUpMethod_implemented() { // // class A { m() {} } // ClassElementImpl classA = classElement("A"); String methodName = "m"; MethodElementImpl methodM = methodElement(methodName, null); classA.setMethods(new MethodElement[] {methodM}); InterfaceType typeA = classA.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA}); assertSame(methodM, typeA.lookUpMethod(methodName, library)); } public void test_lookUpMethod_inherited() { // // class A { m() {} } // class B extends A {} // ClassElementImpl classA = classElement("A"); String methodName = "m"; MethodElementImpl methodM = methodElement(methodName, null); classA.setMethods(new MethodElement[] {methodM}); ClassElementImpl classB = classElement("B", classA.getType()); InterfaceType typeB = classB.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA, classB}); assertSame(methodM, typeB.lookUpMethod(methodName, library)); } public void test_lookUpMethod_parameterized() { // // class A<E> { E m(E p) {} } // class B<F> extends A<F> {} // ClassElementImpl classA = classElement("A", "E"); Type typeE = classA.getType().getTypeArguments()[0]; String methodName = "m"; MethodElementImpl methodM = methodElement(methodName, typeE, typeE); classA.setMethods(new MethodElement[] {methodM}); ((FunctionTypeImpl) methodM.getType()).setTypeArguments(classA.getType().getTypeArguments()); ClassElementImpl classB = classElement("B", "F"); InterfaceType typeB = classB.getType(); InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA); typeAF.setTypeArguments(new Type[] {typeB.getTypeArguments()[0]}); classB.setSupertype(typeAF); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA}); // // B<I> // InterfaceType typeI = classElement("I").getType(); InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB); typeBI.setTypeArguments(new Type[] {typeI}); MethodElement method = typeBI.lookUpMethod(methodName, library); assertNotNull(method); FunctionType methodType = method.getType(); assertSame(typeI, methodType.getReturnType()); Type[] parameterTypes = methodType.getNormalParameterTypes(); assertLength(1, parameterTypes); assertSame(typeI, parameterTypes[0]); } public void test_lookUpMethod_recursive() { // // class A extends B {} // class B extends A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); ClassElementImpl classB = classElement("B", typeA); classA.setSupertype(classB.getType()); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA, classB}); assertNull(typeA.lookUpMethod("m", library)); } public void test_lookUpMethod_unimplemented() { // // class A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA}); assertNull(typeA.lookUpMethod("m", library)); } public void test_lookUpSetter_implemented() { // // class A { s(x) {} } // ClassElementImpl classA = classElement("A"); String setterName = "s"; PropertyAccessorElement setterS = setterElement(setterName, false, null); classA.setAccessors(new PropertyAccessorElement[] {setterS}); InterfaceType typeA = classA.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA}); assertSame(setterS, typeA.lookUpSetter(setterName, library)); } public void test_lookUpSetter_inherited() { // // class A { s(x) {} } // class B extends A {} // ClassElementImpl classA = classElement("A"); String setterName = "g"; PropertyAccessorElement setterS = setterElement(setterName, false, null); classA.setAccessors(new PropertyAccessorElement[] {setterS}); ClassElementImpl classB = classElement("B", classA.getType()); InterfaceType typeB = classB.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA, classB}); assertSame(setterS, typeB.lookUpSetter(setterName, library)); } public void test_lookUpSetter_recursive() { // // class A extends B {} // class B extends A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); ClassElementImpl classB = classElement("B", typeA); classA.setSupertype(classB.getType()); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA, classB}); assertNull(typeA.lookUpSetter("s", library)); } public void test_lookUpSetter_unimplemented() { // // class A {} // ClassElementImpl classA = classElement("A"); InterfaceType typeA = classA.getType(); LibraryElementImpl library = library(createAnalysisContext(), "lib"); CompilationUnitElement unit = library.getDefiningCompilationUnit(); ((CompilationUnitElementImpl) unit).setTypes(new ClassElement[] {classA}); assertNull(typeA.lookUpSetter("s", library)); } public void test_setTypeArguments() { InterfaceTypeImpl type = (InterfaceTypeImpl) classElement("A").getType(); Type[] typeArguments = new Type[] {classElement("B").getType(), classElement("C").getType()}; type.setTypeArguments(typeArguments); assertEquals(typeArguments, type.getTypeArguments()); } public void test_substitute_equal() { ClassElement classAE = classElement("A", "E"); InterfaceType typeAE = classAE.getType(); InterfaceType argumentType = classElement("B").getType(); Type[] args = {argumentType}; Type[] params = {classAE.getTypeParameters()[0].getType()}; InterfaceType typeAESubbed = typeAE.substitute(args, params); assertEquals(classAE, typeAESubbed.getElement()); Type[] resultArguments = typeAESubbed.getTypeArguments(); assertLength(1, resultArguments); assertEquals(argumentType, resultArguments[0]); } public void test_substitute_exception() { try { ClassElementImpl classA = classElement("A"); InterfaceTypeImpl type = new InterfaceTypeImpl(classA); InterfaceType argumentType = classElement("B").getType(); type.substitute(new Type[] {argumentType}, new Type[] {}); fail("Expected to encounter exception, argument and parameter type array lengths not equal."); } catch (Exception e) { // Expected result } } public void test_substitute_notEqual() { // The [test_substitute_equals] above has a slightly higher level implementation. ClassElementImpl classA = classElement("A"); TypeParameterElementImpl parameterElement = new TypeParameterElementImpl(identifier("E")); InterfaceTypeImpl type = new InterfaceTypeImpl(classA); TypeParameterTypeImpl parameter = new TypeParameterTypeImpl(parameterElement); type.setTypeArguments(new Type[] {parameter}); InterfaceType argumentType = classElement("B").getType(); TypeParameterTypeImpl parameterType = new TypeParameterTypeImpl(new TypeParameterElementImpl( identifier("F"))); InterfaceType result = type.substitute(new Type[] {argumentType}, new Type[] {parameterType}); assertEquals(classA, result.getElement()); Type[] resultArguments = result.getTypeArguments(); assertLength(1, resultArguments); assertEquals(parameter, resultArguments[0]); } }