public ClassOrInterface getExtendedTypeDeclaration() { ProducedType et = getExtendedType(); if (et == null || !(et.getDeclaration() instanceof ClassOrInterface)) { return null; } else { return (ClassOrInterface) et.getDeclaration(); } }
ProducedType substitute(ProducedType pt, Map<TypeParameter, ProducedType> substitutions) { Declaration dec; if (pt.getDeclaration() instanceof UnionType) { UnionType ut = new UnionType(pt.getDeclaration().getUnit()); List<ProducedType> types = new ArrayList<ProducedType>(); for (ProducedType ct : pt.getDeclaration().getCaseTypes()) { addTypeToUnion(ct, substitutions, types); } ut.setCaseTypes(types); dec = ut; } else if (pt.getDeclaration() instanceof IntersectionType) { IntersectionType it = new IntersectionType(pt.getDeclaration().getUnit()); List<ProducedType> types = new ArrayList<ProducedType>(); for (ProducedType ct : pt.getDeclaration().getSatisfiedTypes()) { addTypeToIntersection(ct, substitutions, types); } it.setSatisfiedTypes(types); dec = it.canonicalize(); } else { if (pt.getDeclaration() instanceof TypeParameter) { ProducedType sub = substitutions.get(pt.getDeclaration()); if (sub != null) { return sub; } } dec = pt.getDeclaration(); } return substitutedType(dec, pt, substitutions); }
protected void init() { com.redhat.ceylon.compiler.typechecker.model.ClassOrInterface decl = (com.redhat.ceylon.compiler.typechecker.model.ClassOrInterface) producedType.getDeclaration(); this.declaration = (FreeClassOrInterface) Metamodel.getOrCreateMetamodel(decl); java.util.Map< ceylon.language.meta.declaration.TypeParameter, ceylon.language.meta.declaration.OpenType> typeArguments = new LinkedHashMap< ceylon.language.meta.declaration.TypeParameter, ceylon.language.meta.declaration.OpenType>(); Iterator<? extends ceylon.language.meta.declaration.TypeParameter> typeParameters = declaration.getTypeParameterDeclarations().iterator(); Object it; java.util.Map< com.redhat.ceylon.compiler.typechecker.model.TypeParameter, com.redhat.ceylon.compiler.typechecker.model.ProducedType> ptArguments = producedType.getTypeArguments(); while ((it = typeParameters.next()) != finished_.$get()) { com.redhat.ceylon.compiler.java.runtime.metamodel.FreeTypeParameter tp = (com.redhat.ceylon.compiler.java.runtime.metamodel.FreeTypeParameter) it; com.redhat.ceylon.compiler.typechecker.model.TypeParameter tpDecl = (com.redhat.ceylon.compiler.typechecker.model.TypeParameter) tp.declaration; com.redhat.ceylon.compiler.typechecker.model.ProducedType ptArg = ptArguments.get(tpDecl); OpenType ptArgWrapped = Metamodel.getMetamodel(ptArg); typeArguments.put(tp, ptArgWrapped); } this.typeArguments = new InternalMap< ceylon.language.meta.declaration.TypeParameter, ceylon.language.meta.declaration.OpenType>( ceylon.language.meta.declaration.TypeParameter.$TypeDescriptor, ceylon.language.meta.declaration.OpenType.$TypeDescriptor, typeArguments); com.redhat.ceylon.compiler.typechecker.model.ProducedType superType = decl.getExtendedType(); if (superType != null) { com.redhat.ceylon.compiler.typechecker.model.ProducedType superTypeResolved = superType.substitute(producedType.getTypeArguments()); this.superclass = (ceylon.language.meta.declaration.OpenClassType) Metamodel.getMetamodel(superTypeResolved); } List<com.redhat.ceylon.compiler.typechecker.model.ProducedType> satisfiedTypes = decl.getSatisfiedTypes(); ceylon.language.meta.declaration.OpenInterfaceType[] interfaces = new ceylon.language.meta.declaration.OpenInterfaceType[satisfiedTypes.size()]; int i = 0; for (com.redhat.ceylon.compiler.typechecker.model.ProducedType pt : satisfiedTypes) { com.redhat.ceylon.compiler.typechecker.model.ProducedType resolvedPt = pt.substitute(producedType.getTypeArguments()); interfaces[i++] = (ceylon.language.meta.declaration.OpenInterfaceType) Metamodel.getMetamodel(resolvedPt); } this.interfaces = Util.sequentialInstance( ceylon.language.meta.declaration.OpenInterfaceType.$TypeDescriptor, interfaces); }
private CollectionLiteralAnnotationTerm startCollection(Tree.Term t) { Unit unit = t.getUnit(); // Continue the visit to collect the elements ProducedType iteratedType = unit.getIteratedType(parameter().getType()); TypeDeclaration declaration = iteratedType.getDeclaration(); LiteralAnnotationTerm factory; if (unit.getStringDeclaration().equals(declaration)) { factory = StringLiteralAnnotationTerm.FACTORY; } else if (unit.getIntegerDeclaration().equals(declaration)) { factory = IntegerLiteralAnnotationTerm.FACTORY; } else if (unit.getCharacterDeclaration().equals(declaration)) { factory = CharacterLiteralAnnotationTerm.FACTORY; } else if (unit.getBooleanDeclaration().equals(declaration)) { factory = BooleanLiteralAnnotationTerm.FACTORY; } else if (unit.getFloatDeclaration().equals(declaration)) { factory = FloatLiteralAnnotationTerm.FACTORY; } else if (Decl.isEnumeratedTypeWithAnonCases(iteratedType)) { factory = ObjectLiteralAnnotationTerm.FACTORY; } else if (Decl.isAnnotationClass(declaration)) { t.addError( "compiler bug: iterables of annotation classes or annotation constructors not supported as literal " + (checkingDefaults ? "defaulted parameters" : "arguments")); return null; } else if (iteratedType.isSubtypeOf( ((TypeDeclaration) unit.getLanguageModuleDeclarationDeclaration("Declaration")) .getType())) { factory = DeclarationLiteralAnnotationTerm.FACTORY; } else { throw new RuntimeException(); } CollectionLiteralAnnotationTerm result = this.elements; this.elements = new CollectionLiteralAnnotationTerm(factory); return result; }
private void addLocalType( Declaration dec, ProducedType type, List<TypeDeclaration> localTypes, List<ProducedType> visited) { if (visited.contains(type)) { return; } else { visited.add(type); } TypeDeclaration td = type.getDeclaration(); if (td.getContainer() == dec) { boolean found = false; for (TypeDeclaration typeDeclaration : localTypes) { if (typeDeclaration == td) { found = true; break; } } if (!found) { localTypes.add(td); } } for (ProducedType pt : td.getSatisfiedTypes()) { addLocalType(dec, pt, localTypes, visited); } for (ProducedType pt : type.getTypeArgumentList()) { addLocalType(dec, pt, localTypes, visited); } }
@Test public void testQualified() { ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("a.b", null); Assert.assertNotNull(type); TypeDeclaration declaration = type.getDeclaration(); Assert.assertNotNull(declaration); Assert.assertTrue(declaration instanceof Class); Assert.assertEquals("a.b", declaration.getName()); ProducedType qualifyingType = type.getQualifyingType(); Assert.assertNotNull(qualifyingType); TypeDeclaration qualifyingDeclaration = qualifyingType.getDeclaration(); Assert.assertNotNull(qualifyingDeclaration); Assert.assertTrue(qualifyingDeclaration instanceof Class); Assert.assertEquals("a", qualifyingDeclaration.getName()); }
public List<TypeDeclaration> getSatisfiedTypeDeclarations() { List<ProducedType> sts = getSatisfiedTypes(); List<TypeDeclaration> list = new ArrayList<TypeDeclaration>(sts.size()); for (ProducedType pt : sts) { list.add(pt == null ? null : pt.getDeclaration()); } return list; }
public List<TypeDeclaration> getCaseTypeDeclarations() { List<ProducedType> caseTypes = getCaseTypes(); if (caseTypes == null) { return null; } else { List<TypeDeclaration> list = new ArrayList<TypeDeclaration>(caseTypes.size()); for (ProducedType pt : caseTypes) { list.add(pt == null ? null : pt.getDeclaration()); } return list; } }
@Test public void testQualifiedAndParameterised() { ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("t2<a,b>.t2<c,d>", null); Assert.assertNotNull(type); TypeDeclaration declaration = type.getDeclaration(); Assert.assertNotNull(declaration); Assert.assertTrue(declaration instanceof Class); Assert.assertEquals("t2.t2", declaration.getName()); Assert.assertEquals(2, type.getTypeArgumentList().size()); // c ProducedType c = type.getTypeArgumentList().get(0); Assert.assertEquals("c", c.getDeclaration().getName()); Assert.assertTrue(c.getDeclaration() instanceof Class); // d ProducedType d = type.getTypeArgumentList().get(1); Assert.assertEquals("d", d.getDeclaration().getName()); Assert.assertTrue(d.getDeclaration() instanceof Class); ProducedType qualifyingType = type.getQualifyingType(); Assert.assertNotNull(qualifyingType); TypeDeclaration qualifyingDeclaration = qualifyingType.getDeclaration(); Assert.assertNotNull(qualifyingDeclaration); Assert.assertTrue(qualifyingDeclaration instanceof Class); Assert.assertEquals("t2", qualifyingDeclaration.getName()); Assert.assertEquals(2, qualifyingType.getTypeArgumentList().size()); // a ProducedType a = qualifyingType.getTypeArgumentList().get(0); Assert.assertEquals("a", a.getDeclaration().getName()); Assert.assertTrue(a.getDeclaration() instanceof Class); // b ProducedType b = qualifyingType.getTypeArgumentList().get(1); Assert.assertEquals("b", b.getDeclaration().getName()); Assert.assertTrue(b.getDeclaration() instanceof Class); }
@Test public void testParams() { ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("t2<b,c>", null); Assert.assertNotNull(type); TypeDeclaration declaration = type.getDeclaration(); Assert.assertNotNull(declaration); Assert.assertTrue(declaration instanceof Class); Assert.assertEquals("t2", declaration.getName()); Assert.assertEquals(2, type.getTypeArgumentList().size()); Assert.assertEquals("b", type.getTypeArgumentList().get(0).getDeclaration().getName()); Assert.assertTrue(type.getTypeArgumentList().get(0).getDeclaration() instanceof Class); Assert.assertEquals("c", type.getTypeArgumentList().get(1).getDeclaration().getName()); Assert.assertTrue(type.getTypeArgumentList().get(1).getDeclaration() instanceof Class); }
@Test public void testIntersection() { ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("a&b&c", null); Assert.assertNotNull(type); TypeDeclaration declaration = type.getDeclaration(); Assert.assertNotNull(declaration); Assert.assertTrue(declaration instanceof IntersectionType); IntersectionType intersection = (IntersectionType) declaration; List<ProducedType> types = intersection.getSatisfiedTypes(); Assert.assertEquals(3, types.size()); Assert.assertEquals("a", types.get(0).getDeclaration().getName()); Assert.assertTrue(types.get(0).getDeclaration() instanceof Class); Assert.assertEquals("b", types.get(1).getDeclaration().getName()); Assert.assertTrue(types.get(1).getDeclaration() instanceof Class); Assert.assertEquals("c", types.get(2).getDeclaration().getName()); Assert.assertTrue(types.get(2).getDeclaration() instanceof Class); }
private boolean isConstantValue(Declaration d) { if (d instanceof Value) { Value value = (Value) d; if (value.isShared() && !value.isVariable()) { Unit unit = value.getUnit(); TypeDeclaration type = value.getTypeDeclaration(); if (type == unit.getSequentialDeclaration()) { ProducedType elementType = unit.getIteratedType(value.getType()); type = elementType.getDeclaration(); } if (unit.getStringDeclaration().equals(type) || unit.getIntegerDeclaration().equals(type) || unit.getFloatDeclaration().equals(type) || unit.getCharacterDeclaration().equals(type)) { return true; } } } return false; }
private List<ProducedType> getSupertypes(List<ProducedType> list) { if (isWellDefined() && Util.addToSupertypes(list, this)) { ProducedType extendedType = getExtendedType(); if (extendedType != null) { extendedType.getSupertypes(list); } for (ProducedType dst : getSatisfiedTypes()) { dst.getSupertypes(list); } ProducedType selfType = getSelfType(); if (selfType != null) { if (!(selfType.getDeclaration() instanceof TypeParameter)) { // TODO: is this really correct??? selfType.getSupertypes(list); } } List<ProducedType> caseTypes = getCaseTypes(); if (caseTypes != null /*&& !getDeclaration().getCaseTypes().isEmpty()*/) { for (ProducedType t : caseTypes) { List<ProducedType> candidates = t.getSupertypes(); for (ProducedType st : candidates) { boolean include = true; for (ProducedType ct : getDeclaration().getCaseTypes()) { if (!ct.isSubtypeOf(st)) { include = false; break; } } if (include) { Util.addToSupertypes(list, st); } } } } } return list; }
/** Search for the most-specialized supertype satisfying the given predicate. */ private ProducedType getSupertype( final Criteria c, List<ProducedType> list, final TypeDeclaration ignoringSelfType) { if (c.satisfies(getDeclaration())) { return qualifiedByDeclaringType(); } if (isWellDefined() && Util.addToSupertypes(list, this)) { // search for the most-specific supertype // for the given declaration ProducedType result = null; ProducedType extendedType = getInternalExtendedType(); if (extendedType != null) { ProducedType possibleResult = extendedType.getSupertype(c, list, ignoringSelfType); if (possibleResult != null) { result = possibleResult; } } for (ProducedType dst : getInternalSatisfiedTypes()) { ProducedType possibleResult = dst.getSupertype(c, list, ignoringSelfType); if (possibleResult != null && (result == null || possibleResult.isSubtypeOf(result, ignoringSelfType))) { result = possibleResult; } } if (!getDeclaration().equals(ignoringSelfType)) { ProducedType selfType = getInternalSelfType(); if (selfType != null) { ProducedType possibleResult = selfType.getSupertype(c, list, ignoringSelfType); if (possibleResult != null && (result == null || possibleResult.isSubtypeOf(result, ignoringSelfType))) { result = possibleResult; } } } final List<ProducedType> caseTypes = getInternalCaseTypes(); if (caseTypes != null && !caseTypes.isEmpty()) { // first find a common superclass or superinterface // declaration that satisfies the criteria, ignoring // type arguments for now Criteria c2 = new Criteria() { @Override public boolean satisfies(TypeDeclaration type) { if (c.satisfies(type)) { for (ProducedType ct : caseTypes) { if (ct.getSupertype(type, ignoringSelfType) == null) { return false; } } return true; } else { return false; } } }; ProducedType stc = caseTypes.get(0).getSupertype(c2, list, ignoringSelfType); if (stc != null) { // we found the declaration, now try to construct a // produced type that is a true common supertype ProducedType candidateResult = getCommonSupertype(caseTypes, stc.getDeclaration(), ignoringSelfType); if (candidateResult != null && (result == null || candidateResult.isSubtypeOf(result, ignoringSelfType))) { result = candidateResult; } } } return result; } else { return null; } }
/** Is this type exactly the same type as the given type? */ public boolean isExactly(ProducedType type) { if (getDeclaration() instanceof BottomType) { return type.getDeclaration() instanceof BottomType; } else if (getDeclaration() instanceof UnionType) { List<ProducedType> cases = getCaseTypes(); if (type.getDeclaration() instanceof UnionType) { List<ProducedType> otherCases = type.getCaseTypes(); if (cases.size() != otherCases.size()) { return false; } else { for (ProducedType c : cases) { boolean found = false; for (ProducedType oc : otherCases) { if (c.isExactly(oc)) { found = true; break; } } if (!found) { return false; } } return true; } } else if (cases.size() == 1) { ProducedType st = cases.get(0); return st.isExactly(type); } else { return false; } } else if (getDeclaration() instanceof IntersectionType) { List<ProducedType> types = getSatisfiedTypes(); if (type.getDeclaration() instanceof IntersectionType) { List<ProducedType> otherTypes = type.getSatisfiedTypes(); if (types.size() != otherTypes.size()) { return false; } else { for (ProducedType c : types) { boolean found = false; for (ProducedType oc : otherTypes) { if (c.isExactly(oc)) { found = true; break; } } if (!found) { return false; } } return true; } } else if (types.size() == 1) { ProducedType st = types.get(0); return st.isExactly(type); } else { return false; } } else if (type.getDeclaration() instanceof UnionType) { List<ProducedType> otherCases = type.getCaseTypes(); if (otherCases.size() == 1) { ProducedType st = otherCases.get(0); return this.isExactly(st); } else { return false; } } else if (type.getDeclaration() instanceof IntersectionType) { List<ProducedType> otherTypes = type.getSatisfiedTypes(); if (otherTypes.size() == 1) { ProducedType st = otherTypes.get(0); return this.isExactly(st); } else { return false; } } else { if (!type.getDeclaration().equals(getDeclaration())) { return false; } else { ProducedType qt = getQualifyingType(); ProducedType tqt = type.getQualifyingType(); if (qt == null) { if (tqt != null) { return false; } } else { if (tqt == null) { return false; } else { TypeDeclaration totd = (TypeDeclaration) type.getDeclaration().getContainer(); ProducedType tqts = tqt.getSupertype(totd); TypeDeclaration otd = (TypeDeclaration) getDeclaration().getContainer(); ProducedType qts = qt.getSupertype(otd); if (!qts.isExactly(tqts)) { return false; } } } for (TypeParameter p : getDeclaration().getTypeParameters()) { ProducedType arg = getTypeArguments().get(p); ProducedType otherArg = type.getTypeArguments().get(p); if (arg == null || otherArg == null) { return false; /*throw new RuntimeException( "Missing type argument for: " + p.getName() + " of " + getDeclaration().getName());*/ } else if (!arg.isExactly(otherArg)) { return false; } } return true; } } }
/** Is this type a subtype of the given type? Ignore a certain self type constraint. */ public boolean isSubtypeOf(ProducedType type, TypeDeclaration selfTypeToIgnore) { if (getDeclaration() instanceof BottomType) { return true; } else if (type.getDeclaration() instanceof BottomType) { return false; } else if (getDeclaration() instanceof UnionType) { for (ProducedType ct : getInternalCaseTypes()) { if (ct == null || !ct.isSubtypeOf(type, selfTypeToIgnore)) { return false; } } return true; } else if (type.getDeclaration() instanceof UnionType) { for (ProducedType ct : type.getInternalCaseTypes()) { if (ct != null && isSubtypeOf(ct, selfTypeToIgnore)) { return true; } } return false; } else if (type.getDeclaration() instanceof IntersectionType) { for (ProducedType ct : type.getInternalSatisfiedTypes()) { if (ct != null && !isSubtypeOf(ct, selfTypeToIgnore)) { return false; } } return true; } else if (getDeclaration() instanceof IntersectionType) { for (ProducedType ct : getInternalSatisfiedTypes()) { if (ct == null || ct.isSubtypeOf(type, selfTypeToIgnore)) { return true; } } return false; } else { ProducedType st = getSupertype(type.getDeclaration(), selfTypeToIgnore); if (st == null) { return false; } else { ProducedType stqt = st.getQualifyingType(); ProducedType tqt = type.getQualifyingType(); if (stqt == null) { if (tqt != null) { // probably extraneous! return false; } } else { if (tqt == null) { // probably extraneous! return false; } else { // note that the qualifying type of the // given type may be an invariant subtype // of the type that declares the member // type, as long as it doesn't refine the // member type TypeDeclaration totd = (TypeDeclaration) type.getDeclaration().getContainer(); ProducedType tqts = tqt.getSupertype(totd); if (!stqt.isSubtypeOf(tqts)) { return false; } } } for (TypeParameter p : type.getDeclaration().getTypeParameters()) { ProducedType arg = st.getTypeArguments().get(p); ProducedType otherArg = type.getTypeArguments().get(p); if (arg == null || otherArg == null) { /*throw new RuntimeException("Missing type argument for type parameter: " + p.getName() + " of " + type.getDeclaration().getName());*/ return false; } else if (p.isCovariant()) { if (!arg.isSubtypeOf(otherArg)) { return false; } } else if (p.isContravariant()) { if (!otherArg.isSubtypeOf(arg)) { return false; } } else { if (!arg.isExactly(otherArg)) { return false; } } } return true; } } }
/** * Get the supertype which defines the most-refined member with the given name. * * @param signature */ private SupertypeDeclaration getSupertypeDeclaration( final String name, final List<ProducedType> signature, final boolean variadic) { class ExactCriteria implements ProducedType.Criteria { @Override public boolean satisfies(TypeDeclaration type) { // do not look in ourselves if (type == TypeDeclaration.this) return false; Declaration d = type.getDirectMember(name, signature, variadic); if (d != null && d.isShared() && isResolvable(d)) { // only accept abstractions if we don't have a signature return !isAbstraction(d) || signature == null; } else { return false; } } @Override public boolean isMemberLookup() { return true; } }; class LooseCriteria implements ProducedType.Criteria { @Override public boolean satisfies(TypeDeclaration type) { // do not look in ourselves if (type == TypeDeclaration.this) return false; Declaration d = type.getDirectMember(name, null, false); if (d != null && d.isShared() && isResolvable(d)) { // only accept abstractions return isAbstraction(d); } else { return false; } } @Override public boolean isMemberLookup() { return true; } }; // this works by finding the most-specialized supertype // that defines the member ProducedType st = getType().getSupertype(new ExactCriteria()); if (st == null) { // try again, ignoring the given signature st = getType().getSupertype(new LooseCriteria()); } if (st == null) { // no such member return new SupertypeDeclaration(null, false); } else if (st.getDeclaration() instanceof UnknownType) { // we're dealing with an ambiguous member of an // intersection type // TODO: this is pretty fragile - it depends upon // the fact that getSupertype() just happens // to return an UnknownType instead of null // in this case return new SupertypeDeclaration(null, true); } else { // we got exactly one uniquely-defined member Declaration member = st.getDeclaration().getDirectMember(name, signature, variadic); return new SupertypeDeclaration(member, false); } }
public boolean isOptionalType(ProducedType pt) { return getNothingDeclaration().getType().isSubtypeOf(pt) && !pt.getDeclaration().equals(getVoidDeclaration()); }
@Test public void testUnionParams() { ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("a|t2<b|c,t2<d,e|f>>", null); Assert.assertNotNull(type); TypeDeclaration declaration = type.getDeclaration(); Assert.assertNotNull(declaration); Assert.assertTrue(declaration instanceof UnionType); UnionType union = (UnionType) declaration; List<ProducedType> caseTypes = union.getCaseTypes(); Assert.assertEquals(2, caseTypes.size()); // a Assert.assertEquals("a", caseTypes.get(0).getDeclaration().getName()); Assert.assertTrue(caseTypes.get(0).getDeclaration() instanceof Class); // first t2 ProducedType firstT2 = caseTypes.get(1); TypeDeclaration firstT2Declaration = firstT2.getDeclaration(); Assert.assertNotNull(firstT2Declaration); Assert.assertTrue(firstT2Declaration instanceof Class); Assert.assertEquals("t2", firstT2Declaration.getName()); Assert.assertEquals(2, firstT2.getTypeArgumentList().size()); // b|c ProducedType bc = firstT2.getTypeArgumentList().get(0); Assert.assertTrue(bc.getDeclaration() instanceof UnionType); Assert.assertEquals(2, bc.getDeclaration().getCaseTypes().size()); // b ProducedType b = bc.getDeclaration().getCaseTypes().get(0); Assert.assertEquals("b", b.getDeclaration().getName()); Assert.assertTrue(b.getDeclaration() instanceof Class); // c ProducedType c = bc.getDeclaration().getCaseTypes().get(1); Assert.assertEquals("c", c.getDeclaration().getName()); Assert.assertTrue(c.getDeclaration() instanceof Class); // second t2 ProducedType secondT2 = firstT2.getTypeArgumentList().get(1); TypeDeclaration secondT2Declaration = firstT2.getDeclaration(); Assert.assertNotNull(secondT2Declaration); Assert.assertTrue(secondT2Declaration instanceof Class); Assert.assertEquals("t2", secondT2Declaration.getName()); Assert.assertEquals(2, secondT2.getTypeArgumentList().size()); // d ProducedType d = secondT2.getTypeArgumentList().get(0); Assert.assertEquals("d", d.getDeclaration().getName()); Assert.assertTrue(d.getDeclaration() instanceof Class); // e|f ProducedType ef = secondT2.getTypeArgumentList().get(1); Assert.assertTrue(ef.getDeclaration() instanceof UnionType); Assert.assertEquals(2, ef.getDeclaration().getCaseTypes().size()); // e ProducedType e = ef.getDeclaration().getCaseTypes().get(0); Assert.assertEquals("e", e.getDeclaration().getName()); Assert.assertTrue(e.getDeclaration() instanceof Class); // f ProducedType f = ef.getDeclaration().getCaseTypes().get(1); Assert.assertEquals("f", f.getDeclaration().getName()); Assert.assertTrue(f.getDeclaration() instanceof Class); }