@Override public LightweightTypeReference enhance(ParameterizedTypeReference reference) { reference.addTypeArgument(owner.newWildcardTypeReference()); return reference; } });
protected void copyTypeArguments(ParameterizedTypeReference result, ITypeReferenceOwner owner) { if (typeArguments != null && !typeArguments.isEmpty()) { for(LightweightTypeReference typeArgument: typeArguments) { result.addTypeArgument(typeArgument.copyInto(owner)); } } }
@Override public LightweightTypeReference enhance(ParameterizedTypeReference ref) { ref.addTypeArgument(owner.newReferenceTo(ArrayList.class, new TypeReferenceInitializer<ParameterizedTypeReference>(){ @Override public LightweightTypeReference enhance(ParameterizedTypeReference keyType) { keyType.addTypeArgument(owner.newWildcardExtendsObject()); return keyType; } })); ref.addTypeArgument(owner.toLightweightTypeReference(createOperation.getReturnType())); return ref; } });
protected void setUnboundCollectionType(XCollectionLiteral literal, JvmGenericType collectionType, ITypeExpectation expectation, LightweightTypeReference elementTypeExpectation, ITypeComputationState state) { ParameterizedTypeReference unboundCollectionType = state.getReferenceOwner().newParameterizedTypeReference(collectionType); if (elementTypeExpectation != null) { unboundCollectionType.addTypeArgument(elementTypeExpectation); } else { UnboundTypeReference unboundTypeArgument = expectation.createUnboundTypeReference(literal, collectionType.getTypeParameters().get(0)); unboundCollectionType.addTypeArgument(unboundTypeArgument); } expectation.acceptActualType(unboundCollectionType, ConformanceFlags.UNCHECKED); }
/** * @param type the type of the reference. May be used by subtypes. */ protected LightweightTypeReference enhanceParameterizedTypeReference(ParameterizedTypeReference origin, JvmType type, ParameterizedTypeReference result, Visiting visiting) { for(LightweightTypeReference argument: origin.getTypeArguments()) { result.addTypeArgument(visitTypeArgument(argument, visiting)); } return result; }
@Override public LightweightTypeReference enhance(ParameterizedTypeReference reference) { LightweightTypeReference componentType = type.getComponentType(); LightweightTypeReference wrapper = componentType.getWrapperTypeIfPrimitive(); reference.addTypeArgument(wrapper); return reference; } });
@Override protected LightweightTypeReference enhanceParameterizedTypeReference(ParameterizedTypeReference origin, JvmType type, ParameterizedTypeReference result, ConstraintVisitingInfo visiting) { for(int i = 0; i < origin.getTypeArguments().size(); i++) { LightweightTypeReference argument = origin.getTypeArguments().get(i); visiting.pushInfo(type instanceof JvmTypeParameterDeclarator ? (JvmTypeParameterDeclarator) type : null, i); LightweightTypeReference visitedArgument = visitTypeArgument(argument, visiting); result.addTypeArgument(visitedArgument); } return result; }
@Override protected void doVisitParameterizedTypeReference(ParameterizedTypeReference reference) { JvmType rawType = reference.getType(); if (rawType.eClass() == TypesPackage.Literals.JVM_GENERIC_TYPE) { List<JvmTypeParameter> typeParameters = ((JvmTypeParameterDeclarator) rawType).getTypeParameters(); for(int i = 0, size = typeParameters.size(); i < size; i++) { JvmTypeParameter typeParameter = typeParameters.get(i); reference.addTypeArgument(owner.newParameterizedTypeReference(typeParameter)); } } } });
/** * Creates a list of collection type references from the element types of a collection literal. */ protected List<LightweightTypeReference> computeCollectionTypeCandidates(XCollectionLiteral literal, JvmGenericType collectionType, LightweightTypeReference elementTypeExpectation, ITypeComputationState state) { List<XExpression> elements = literal.getElements(); if(!elements.isEmpty()) { List<LightweightTypeReference> elementTypes = Lists.newArrayListWithCapacity(elements.size()); for(XExpression element: elements) { ITypeComputationResult elementType = computeTypes(element, elementTypeExpectation, state); LightweightTypeReference actualType = elementType.getActualExpressionType(); if(actualType != null && !actualType.isAny()) { ParameterizedTypeReference collectionTypeCandidate = state.getReferenceOwner().newParameterizedTypeReference(collectionType); collectionTypeCandidate.addTypeArgument(actualType.getWrapperTypeIfPrimitive()); elementTypes.add(collectionTypeCandidate); } } return elementTypes; } return Collections.emptyList(); }
@Override public LightweightTypeReference enhance(ParameterizedTypeReference reference) { LightweightTypeReference argumentType = owner.newParameterizedTypeReference((JvmType) feature); if (argumentType.isPrimitiveVoid()) { argumentType = owner.newReferenceTo(Void.class); } else { argumentType = argumentType.getWrapperTypeIfPrimitive(); } reference.addTypeArgument(argumentType); return reference; } });
/** * Creates a new {@link JvmTypeReference} pointing to the given class and containing the given type arguments. * * @param type * the type the reference shall point to. * @param typeArgs * type arguments * @return the newly created {@link JvmTypeReference} */ public JvmTypeReference typeRef(JvmType type, JvmTypeReference... typeArgs) { int typeParams = 0; if (type instanceof JvmGenericType) { typeParams = ((JvmGenericType) type).getTypeParameters().size(); } if (typeParams < typeArgs.length) { throw new IllegalArgumentException("The type "+type.getIdentifier()+" only declares "+typeParams+" type parameters. You passed "+typeArgs.length+"."); } LightweightTypeReference reference = typeReferenceOwner.toPlainTypeReference(type); for (JvmTypeReference jvmTypeReference : typeArgs) { ((ParameterizedTypeReference)reference).addTypeArgument(typeReferenceOwner.toLightweightTypeReference(jvmTypeReference)); } return reference.toJavaCompliantTypeReference(); }
/** * The map type may be constructed from different pairs, e.g. the pair's type arguments don't need to be as strict * as the map suggests. The pair's expectation is adjusted accordingly. */ protected LightweightTypeReference createNormalizedPairType(LightweightTypeReference pairType, LightweightTypeReference mapType, ITypeReferenceOwner owner) { ParameterizedTypeReference result = new ParameterizedTypeReference(owner, pairType.getType()); LightweightTypeReference keyType = mapType.getTypeArguments().get(0); if (keyType.getKind() != LightweightTypeReference.KIND_WILDCARD_TYPE_REFERENCE) { WildcardTypeReference wc = new WildcardTypeReference(owner); wc.addUpperBound(keyType); keyType = wc; } LightweightTypeReference valueType = mapType.getTypeArguments().get(1); if (valueType.getKind() != LightweightTypeReference.KIND_WILDCARD_TYPE_REFERENCE) { WildcardTypeReference wc = new WildcardTypeReference(owner); wc.addUpperBound(valueType); valueType = wc; } result.addTypeArgument(keyType); result.addTypeArgument(valueType); return result; }
@Override protected LightweightTypeReference enhanceParameterizedTypeReference(ParameterizedTypeReference reference, JvmType type, ParameterizedTypeReference result, ConstraintVisitingInfo visiting) { boolean convertToWildcard = false; for(int i = 0; i < reference.getTypeArguments().size(); i++) { wasCapturedWildcard = false; LightweightTypeReference argument = reference.getTypeArguments().get(i); visiting.pushInfo(type instanceof JvmTypeParameterDeclarator ? (JvmTypeParameterDeclarator) type : null, i); LightweightTypeReference visitedArgument = argument.accept(this, visiting); if (wasCapturedWildcard) convertToWildcard = true; wasCapturedWildcard = false; result.addTypeArgument(visitedArgument); } if (convertToWildcard) { WildcardTypeReference wildcard = result.getOwner().newWildcardTypeReference(); wildcard.addUpperBound(result); return wildcard; } return result; }
/** * Creates a map type reference that comes as close as possible / necessary to its expected type. */ protected LightweightTypeReference createMapTypeReference(JvmGenericType mapType, LightweightTypeReference pairType, LightweightTypeReference expectation, ITypeReferenceOwner owner) { List<LightweightTypeReference> leftAndRight = pairType.getTypeArguments(); LightweightTypeReference left = leftAndRight.get(0).getInvariantBoundSubstitute(); LightweightTypeReference right = leftAndRight.get(1).getInvariantBoundSubstitute(); LightweightTypeReference mapExpectation = getMapExpectation(expectation); if (mapExpectation != null) { List<LightweightTypeReference> typeArguments = expectation.getTypeArguments(); left = doNormalizeElementType(left, typeArguments.get(0)); right = doNormalizeElementType(right, typeArguments.get(1)); } ParameterizedTypeReference result = owner.newParameterizedTypeReference(mapType); result.addTypeArgument(left.copyInto(owner)); result.addTypeArgument(right.copyInto(owner)); if (mapExpectation != null && !expectation.isAssignableFrom(result)) { // expectation does not match the computed type, but looks good according to the element types: // use expected type if (matchesExpectation(left, mapExpectation.getTypeArguments().get(0)) && matchesExpectation(right, mapExpectation.getTypeArguments().get(1))) { return expectation; } } return result; }
/** * Returns a projection of this type to the instance level. That is, type arguments will * be replaced by their invariant bounds. * * The instance projection of <code>ArrayList<? extends Iterable<? extends String>></code> * is <code>ArrayList<Iterable<? extends String>></code> since it is possible to create instances * of <code>ArrayList<Iterable<? extends String>></code>. */ public ParameterizedTypeReference toInstanceTypeReference() { ParameterizedTypeReference result = getOwner().newParameterizedTypeReference(getType()); for(LightweightTypeReference typeArgument: getTypeArguments()) { result.addTypeArgument(typeArgument.getInvariantBoundSubstitute()); } return result; } }
@Override protected void applyType() { JvmType type = (JvmType) getFeature(); if (type == null || type.eIsProxy()) { throw new IllegalStateException(); } ITypeReferenceOwner referenceOwner = getResolvedTypes().getReferenceOwner(); ParameterizedTypeReference result = referenceOwner.newParameterizedTypeReference(type); for(LightweightTypeReference typeArgument: getTypeArguments()) { result.addTypeArgument(typeArgument); } getState().acceptActualType(result); }
/** * A function type reference may be known to have the type argument {@link Number} but still use a more * specific return type {@link Integer}. Normalization converts such a reference to the return type {@link Number}. */ protected LightweightTypeReference normalizeFunctionTypeReference(LightweightTypeReference type) { if (type.getKind() == LightweightTypeReference.KIND_FUNCTION_TYPE_REFERENCE) { ParameterizedTypeReference parameterized = new ParameterizedTypeReference(type.getOwner(), type.getType()); for(LightweightTypeReference argument: type.getTypeArguments()) { parameterized.addTypeArgument(argument); } type = parameterized.tryConvertToFunctionTypeReference(false); } return type; }
@Override public LightweightTypeReference doVisitParameterizedTypeReference(JvmParameterizedTypeReference reference) { JvmType type = getType(reference); if (type == null || type.eIsProxy()) { return createUnknownTypeReference(reference); } ParameterizedTypeReference result = owner.newParameterizedTypeReference(type); for(JvmTypeReference argument: reference.getArguments()) { result.addTypeArgument(visit(argument).getWrapperTypeIfPrimitive()); } return result; }
@Override protected LightweightTypeReference doVisitInnerTypeReference(InnerTypeReference reference, Visiting visiting) { if (reference.isResolved() && reference.isOwnedBy(getOwner())) return reference; LightweightTypeReference outer = reference.getOuter().accept(this, visiting); ParameterizedTypeReference result = getOwner().newParameterizedTypeReference(outer, reference.getType()); for(LightweightTypeReference argument: reference.getTypeArguments()) { result.addTypeArgument(visitTypeArgument(argument, visiting)); } return result; }
/** * Creates a collection type reference that comes as close as possible / necessary to its expected type. */ protected LightweightTypeReference createCollectionTypeReference(JvmGenericType collectionType, LightweightTypeReference elementType, LightweightTypeReference expectedType, ITypeReferenceOwner owner) { ParameterizedTypeReference result = new ParameterizedTypeReference(owner, collectionType); result.addTypeArgument(elementType); if (isIterableExpectation(expectedType) && !expectedType.isAssignableFrom(result)) { // avoid to assign a set literal to a list and viceversa: // at least the raw types must be assignable // https://bugs.eclipse.org/bugs/show_bug.cgi?id=498779 if (expectedType.getRawTypeReference().isAssignableFrom(result.getRawTypeReference())) { LightweightTypeReference expectedElementType = getElementOrComponentType(expectedType, owner); if (matchesExpectation(elementType, expectedElementType)) { return expectedType; } } } return result; }