@NotNull public KotlinType getArrayElementType(@NotNull KotlinType arrayType) { if (isArray(arrayType)) { if (arrayType.getArguments().size() != 1) { throw new IllegalStateException(); } return arrayType.getArguments().get(0).getType(); } KotlinType primitiveType = kotlinArrayTypeToPrimitiveKotlinType.get(TypeUtils.makeNotNullable(arrayType)); if (primitiveType == null) { throw new IllegalStateException("not array: " + arrayType); } return primitiveType; }
@Nullable public static KotlinType getReceiverType(@NotNull KotlinType type) { assert isFunctionOrExtensionFunctionType(type) : type; if (isExtensionFunctionType(type)) { // TODO: this is incorrect when a class extends from an extension function and swaps type // arguments return type.getArguments().get(0).getType(); } return null; }
public static boolean dependsOnTypeConstructors( @NotNull KotlinType type, @NotNull Collection<TypeConstructor> typeParameterConstructors) { if (typeParameterConstructors.contains(type.getConstructor())) return true; for (TypeProjection typeProjection : type.getArguments()) { if (!typeProjection.isStarProjection() && dependsOnTypeConstructors(typeProjection.getType(), typeParameterConstructors)) { return true; } } return false; }
@NotNull public static List<TypeProjection> getParameterTypeProjectionsFromFunctionType( @NotNull KotlinType type) { assert isFunctionOrExtensionFunctionType(type); List<TypeProjection> arguments = type.getArguments(); int first = isExtensionFunctionType(type) ? 1 : 0; int last = arguments.size() - 2; // TODO: fix bugs associated with this here and in neighboring methods, see KT-9820 assert first <= last + 1 : "Not an exact function type: " + type; List<TypeProjection> parameterTypes = new ArrayList<TypeProjection>(last - first + 1); for (int i = first; i <= last; i++) { parameterTypes.add(arguments.get(i)); } return parameterTypes; }
public static boolean contains( @Nullable KotlinType type, @NotNull Function1<KotlinType, Boolean> isSpecialType) { if (type == null) return false; if (isSpecialType.invoke(type)) return true; Flexibility flexibility = type.getCapability(Flexibility.class); if (flexibility != null && (contains(flexibility.getLowerBound(), isSpecialType) || contains(flexibility.getUpperBound(), isSpecialType))) { return true; } for (TypeProjection projection : type.getArguments()) { if (!projection.isStarProjection() && contains(projection.getType(), isSpecialType)) return true; } return false; }
@NotNull public static KotlinType getReturnTypeFromFunctionType(@NotNull KotlinType type) { assert isFunctionOrExtensionFunctionType(type); List<TypeProjection> arguments = type.getArguments(); return arguments.get(arguments.size() - 1).getType(); }
@Override @NotNull public List<TypeProjection> getArguments() { return delegate.getArguments(); }
public static boolean canHaveSubtypes(KotlinTypeChecker typeChecker, @NotNull KotlinType type) { if (type.isMarkedNullable()) { return true; } if (!type.getConstructor().isFinal()) { return true; } List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters(); List<TypeProjection> arguments = type.getArguments(); for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) { TypeParameterDescriptor parameterDescriptor = parameters.get(i); TypeProjection typeProjection = arguments.get(i); if (typeProjection.isStarProjection()) return true; Variance projectionKind = typeProjection.getProjectionKind(); KotlinType argument = typeProjection.getType(); switch (parameterDescriptor.getVariance()) { case INVARIANT: switch (projectionKind) { case INVARIANT: if (lowerThanBound(typeChecker, argument, parameterDescriptor) || canHaveSubtypes(typeChecker, argument)) { return true; } break; case IN_VARIANCE: if (lowerThanBound(typeChecker, argument, parameterDescriptor)) { return true; } break; case OUT_VARIANCE: if (canHaveSubtypes(typeChecker, argument)) { return true; } break; } break; case IN_VARIANCE: if (projectionKind != Variance.OUT_VARIANCE) { if (lowerThanBound(typeChecker, argument, parameterDescriptor)) { return true; } } else { if (canHaveSubtypes(typeChecker, argument)) { return true; } } break; case OUT_VARIANCE: if (projectionKind != Variance.IN_VARIANCE) { if (canHaveSubtypes(typeChecker, argument)) { return true; } } else { if (lowerThanBound(typeChecker, argument, parameterDescriptor)) { return true; } } break; } } return false; }