private List<ProducedType> getSatisfiedTypes() { List<ProducedType> satisfiedTypes = new ArrayList<ProducedType>(); for (ProducedType st : getDeclaration().getSatisfiedTypes()) { satisfiedTypes.add(st.substitute(getTypeArguments())); } return satisfiedTypes; }
public String getProducedTypeQualifiedName() { if (getDeclaration() == null) { // unknown type return null; } String producedTypeName = ""; if (getDeclaration().isMember()) { producedTypeName += getQualifyingType().getProducedTypeQualifiedName(); producedTypeName += "."; } producedTypeName += getDeclaration().getQualifiedNameString(); if (!getTypeArgumentList().isEmpty()) { producedTypeName += "<"; for (ProducedType t : getTypeArgumentList()) { if (t == null) { producedTypeName += "?,"; } else { producedTypeName += t.getProducedTypeQualifiedName() + ","; } } producedTypeName += ">"; producedTypeName = producedTypeName.replace(",>", ">"); } return producedTypeName; }
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); } }
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; }
public ProducedType getElementType(ProducedType pt) { ProducedType st = getNonemptySequenceType(pt); if (st != null && st.getTypeArguments().size() == 1) { return st.getTypeArgumentList().get(0); } else { return null; } }
public ProducedType getIteratedType(ProducedType type) { ProducedType st = type.getSupertype(getIterableDeclaration()); if (st != null && st.getTypeArguments().size() == 1) { return st.getTypeArgumentList().get(0); } else { return null; } }
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 ClassOrInterface getExtendedTypeDeclaration() { ProducedType et = getExtendedType(); if (et == null || !(et.getDeclaration() instanceof ClassOrInterface)) { return null; } else { return (ClassOrInterface) et.getDeclaration(); } }
public ProducedType getValueType(ProducedType type) { ProducedType st = type.getSupertype(getEntryDeclaration()); if (st != null && st.getTypeArguments().size() == 2) { return st.getTypeArgumentList().get(1); } else { return null; } }
/** Is the type welldefined? Are any of its arguments garbage unknown types? */ public boolean isWellDefined() { for (ProducedType at : getTypeArgumentList()) { if (at == null || !at.isWellDefined()) { return false; } } return true; }
/** * A member type of the type with actual type arguments to the receiving type and invocation. * * @param member the declaration of a member type of this type * @param typeArguments the type arguments of the invocation */ public ProducedType getTypeMember(TypeDeclaration member, List<ProducedType> typeArguments) { ProducedType declaringType = getSupertype((TypeDeclaration) member.getContainer()); ProducedType pt = new ProducedType(); pt.setDeclaration(member); pt.setQualifyingType(declaringType); Map<TypeParameter, ProducedType> map = arguments(member, declaringType, typeArguments); // map.putAll(sub(map)); pt.setTypeArguments(map); return pt; }
/** * Determine if this is a decidable supertype, i.e. if it obeys the restriction that types with * contravariant type parameters may only appear in covariant positions. * * @return a list of type parameters which appear in illegal positions */ public List<TypeDeclaration> checkDecidability() { List<TypeDeclaration> errors = new ArrayList<TypeDeclaration>(); for (TypeParameter tp : getDeclaration().getTypeParameters()) { ProducedType pt = getTypeArguments().get(tp); if (pt != null) { pt.checkDecidability(tp.isCovariant(), tp.isContravariant(), errors); } } return errors; }
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); }
private List<ProducedType> getCaseTypes() { if (getDeclaration().getCaseTypes() == null) { return null; } else { List<ProducedType> caseTypes = new ArrayList<ProducedType>(); for (ProducedType ct : getDeclaration().getCaseTypes()) { caseTypes.add(ct.substitute(getTypeArguments())); } return caseTypes; } }
/** * Get a produced type for this declaration by binding explicit or inferred type arguments and * type arguments of the type of which this declaration is a member, in the case that this is a * nested type. * * @param qualifyingType the qualifying produced type or null if this is not a nested type dec * @param typeArguments arguments to the type parameters of this declaration */ public ProducedType getProducedType( ProducedType qualifyingType, List<ProducedType> typeArguments) { if (qualifyingType != null && qualifyingType.isNothing()) { return qualifyingType; } ProducedType pt = new ProducedType(); pt.setDeclaration(this); pt.setQualifyingType(qualifyingType); pt.setTypeArguments(getTypeArgumentMap(this, qualifyingType, typeArguments)); return pt; }
@Override public ProducedType getReference() { ProducedType pt = new ProducedType(); if (isMember()) { pt.setQualifyingType(((ClassOrInterface) getContainer()).getType()); } pt.setDeclaration(this); pt.setTypeArguments( getTypeArgumentMap(this, pt.getQualifyingType(), Collections.<ProducedType>emptyList())); return pt; }
private ProducedType substitutedType( Declaration dec, ProducedType pt, Map<TypeParameter, ProducedType> substitutions) { ProducedType type = new ProducedType(); type.setDeclaration(dec); ProducedType qt = pt.getQualifyingType(); if (qt != null) { type.setQualifyingType(substitute(qt, substitutions)); } type.setTypeArguments(substitutedTypeArguments(pt, substitutions)); return type; }
@Test public void testPackageQualified() { ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("unknown.b", null); Assert.assertNotNull(type); TypeDeclaration declaration = type.getDeclaration(); Assert.assertNotNull(declaration); Assert.assertTrue(declaration instanceof Class); Assert.assertEquals("unknown.b", declaration.getName()); Assert.assertNull(type.getQualifyingType()); }
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; } }
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); }
@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); }
/** * Eliminate the given type from the union type. (Performs a set complement operation.) Note that * this operation is not robust and only works if this is a union of the given type with some * other types that don't involve the given type. */ public ProducedType minus(ClassOrInterface ci) { if (getDeclaration().equals(ci)) { return new BottomType(getDeclaration().getUnit()).getType(); } else if (getDeclaration() instanceof UnionType) { List<ProducedType> types = new ArrayList<ProducedType>(); for (ProducedType ct : getCaseTypes()) { if (ct.getSupertype(ci) == null) { addToUnion(types, ct.minus(ci)); } } UnionType ut = new UnionType(getDeclaration().getUnit()); ut.setCaseTypes(types); return ut.getType(); } else { return this; } }
public JCNewClass build() { // Generate a subclass of Callable ListBuffer<JCTree> classBody = new ListBuffer<JCTree>(); int numParams = paramLists.getParameters().size(); int minimumParams = 0; for (Parameter p : paramLists.getParameters()) { if (p.isDefaulted() || p.isSequenced()) break; minimumParams++; } boolean isVariadic = minimumParams != numParams; if (parameterListTree != null) { // generate a method for each defaulted param for (Tree.Parameter p : parameterListTree.getParameters()) { if (p.getDefaultArgument() != null || p.getDeclarationModel().isSequenced()) { MethodDefinitionBuilder methodBuilder = gen.classGen().makeParamDefaultValueMethod(false, null, parameterListTree, p); classBody.append(methodBuilder.build()); } } } // collect each parameter type from the callable type model rather than the declarations to get // them all bound java.util.List<ProducedType> parameterTypes = new ArrayList<ProducedType>(numParams); if (forwardCallTo != null) { for (int i = 0; i < numParams; i++) parameterTypes.add(gen.getParameterTypeOfCallable(typeModel, i)); } else { // get them from our declaration for (Parameter p : paramLists.getParameters()) parameterTypes.add(p.getType()); } // now generate a method for each supported minimum number of parameters below 4 // which delegates to the $call$typed method if required for (int i = minimumParams, max = Math.min(numParams, 4); i < max; i++) { classBody.append(makeDefaultedCall(i, isVariadic, parameterTypes)); } // generate the $call method for the max number of parameters, // which delegates to the $call$typed method if required classBody.append(makeDefaultedCall(numParams, isVariadic, parameterTypes)); // generate the $call$typed method if required if (isVariadic && forwardCallTo == null) classBody.append(makeCallTypedMethod(body, parameterTypes)); JCClassDecl classDef = gen.make().AnonymousClassDef(gen.make().Modifiers(0), classBody.toList()); JCNewClass instance = gen.make() .NewClass( null, null, gen.makeJavaType(typeModel, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>of(gen.make().Literal(typeModel.getProducedTypeName(true))), classDef); return instance; }
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 void checkVariance( boolean covariant, boolean contravariant, Declaration declaration, List<TypeParameter> errors) { // TODO: fix this to allow reporting multiple errors! if (getDeclaration() instanceof TypeParameter) { TypeParameter tp = (TypeParameter) getDeclaration(); boolean ok = tp.getDeclaration().equals(declaration) || ((covariant || !tp.isCovariant()) && (contravariant || !tp.isContravariant())); if (!ok) { // a covariant type parameter appears in a contravariant location, or // a contravariant type parameter appears in a covariant location. errors.add(tp); } } else if (getDeclaration() instanceof UnionType) { for (ProducedType ct : getCaseTypes()) { ct.checkVariance(covariant, contravariant, declaration, errors); } } else if (getDeclaration() instanceof IntersectionType) { for (ProducedType ct : getSatisfiedTypes()) { ct.checkVariance(covariant, contravariant, declaration, errors); } } else { for (TypeParameter tp : getDeclaration().getTypeParameters()) { ProducedType pt = getTypeArguments().get(tp); if (pt != null) { if (tp.isCovariant()) { pt.checkVariance(covariant, contravariant, declaration, errors); } else if (tp.isContravariant()) { if (covariant | contravariant) { pt.checkVariance(!covariant, !contravariant, declaration, errors); } else { // else if we are in a nonvariant position, it stays nonvariant pt.checkVariance(covariant, contravariant, declaration, errors); } } else { pt.checkVariance(false, false, declaration, errors); } } } } }
public String getProducedTypeName(boolean abbreviate) { if (getDeclaration() == null) { // unknown type return null; } if (abbreviate && getDeclaration() instanceof UnionType) { UnionType ut = (UnionType) getDeclaration(); if (ut.getCaseTypes().size() == 2) { Unit unit = getDeclaration().getUnit(); if (Util.isElementOfUnion(ut, unit.getNothingDeclaration())) { return unit.getDefiniteType(this).getProducedTypeName() + "?"; } if (Util.isElementOfUnion(ut, unit.getEmptyDeclaration()) && Util.isElementOfUnion(ut, unit.getSequenceDeclaration())) { return unit.getElementType(this).getProducedTypeName() + "[]"; } } } String producedTypeName = ""; if (getDeclaration().isMember()) { producedTypeName += getQualifyingType().getProducedTypeName(abbreviate); producedTypeName += "."; } producedTypeName += getDeclaration().getName(); if (!getTypeArgumentList().isEmpty()) { producedTypeName += "<"; for (ProducedType t : getTypeArgumentList()) { if (t == null) { producedTypeName += "unknown,"; } else { producedTypeName += t.getProducedTypeName(abbreviate) + ","; } } producedTypeName += ">"; producedTypeName = producedTypeName.replace(",>", ">"); } return producedTypeName; }
private static String type(Tree.Type type) { if (type == null) { return "<Unknown>"; } else { ProducedType tm = type.getTypeModel(); if (tm == null) { return "<Unknown>"; } else { boolean sequenced = type instanceof Tree.SequencedType; if (sequenced) { tm = type.getUnit().getIteratedType(tm); if (tm == null) { return "<Unknown>"; } } String tn = tm.getProducedTypeName(); if (sequenced) { tn += "..."; } return tn; } } }
private Map<TypeParameter, ProducedType> substitutedTypeArguments( ProducedType pt, Map<TypeParameter, ProducedType> substitutions) { Map<TypeParameter, ProducedType> map = new HashMap<TypeParameter, ProducedType>(); for (Map.Entry<TypeParameter, ProducedType> e : pt.getTypeArguments().entrySet()) { if (e.getValue() != null) { map.put(e.getKey(), substitute(e.getValue(), substitutions)); } } /*ProducedType dt = pt.getDeclaringType(); if (dt!=null) { map.putAll(substituted(dt, substitutions)); }*/ return map; }
@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); }
private void checkDecidability( boolean covariant, boolean contravariant, List<TypeDeclaration> errors) { if (getDeclaration() instanceof TypeParameter) { // nothing to do } else if (getDeclaration() instanceof UnionType) { for (ProducedType ct : getCaseTypes()) { ct.checkDecidability(covariant, contravariant, errors); } } else if (getDeclaration() instanceof IntersectionType) { for (ProducedType ct : getSatisfiedTypes()) { ct.checkDecidability(covariant, contravariant, errors); } } else { for (TypeParameter tp : getDeclaration().getTypeParameters()) { if (!covariant && tp.isContravariant()) { // a type with contravariant parameters appears at // a contravariant location in satisfies / extends errors.add(getDeclaration()); } ProducedType pt = getTypeArguments().get(tp); if (pt != null) { if (tp.isCovariant()) { pt.checkDecidability(covariant, contravariant, errors); } else if (tp.isContravariant()) { if (covariant | contravariant) { pt.checkDecidability(!covariant, !contravariant, errors); } else { // else if we are in a nonvariant position, it stays nonvariant pt.checkDecidability(covariant, contravariant, errors); } } else { pt.checkDecidability(false, false, errors); } } } } }