private void reportCyclicInheritanceHierarchyError( @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor, @NotNull ClassDescriptor superclass) { PsiElement psiElement = DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor); PsiElement elementToMark = null; if (psiElement instanceof KtClassOrObject) { KtClassOrObject classOrObject = (KtClassOrObject) psiElement; for (KtSuperTypeListEntry delegationSpecifier : classOrObject.getSuperTypeListEntries()) { KtTypeReference typeReference = delegationSpecifier.getTypeReference(); if (typeReference == null) continue; KotlinType supertype = trace.get(TYPE, typeReference); if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) { elementToMark = typeReference; } } } if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) { PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement; PsiElement nameIdentifier = namedElement.getNameIdentifier(); if (nameIdentifier != null) { elementToMark = nameIdentifier; } } if (elementToMark != null) { trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark)); } }
private static boolean areTypesEquivalent( @NotNull KotlinType typeInSuper, @NotNull KotlinType typeInSub, @NotNull KotlinTypeChecker typeChecker) { boolean bothErrors = typeInSuper.isError() && typeInSub.isError(); return bothErrors || typeChecker.equalTypes(typeInSuper, typeInSub); }
@NotNull public OverrideCompatibilityInfo isOverridableByWithoutExternalConditions( @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor, boolean checkReturnType) { OverrideCompatibilityInfo basicOverridability = getBasicOverridabilityProblem(superDescriptor, subDescriptor); if (basicOverridability != null) return basicOverridability; List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor); List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor); List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters(); List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters(); if (superTypeParameters.size() != subTypeParameters.size()) { for (int i = 0; i < superValueParameters.size(); ++i) { // TODO: compare erasure if (!KotlinTypeChecker.DEFAULT.equalTypes( superValueParameters.get(i), subValueParameters.get(i))) { return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch"); } } return OverrideCompatibilityInfo.conflict("Type parameter number mismatch"); } KotlinTypeChecker typeChecker = createTypeChecker(superTypeParameters, subTypeParameters); for (int i = 0; i < superTypeParameters.size(); i++) { if (!areTypeParametersEquivalent( superTypeParameters.get(i), subTypeParameters.get(i), typeChecker)) { return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch"); } } for (int i = 0; i < superValueParameters.size(); i++) { if (!areTypesEquivalent( superValueParameters.get(i), subValueParameters.get(i), typeChecker)) { return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch"); } } if (checkReturnType) { KotlinType superReturnType = superDescriptor.getReturnType(); KotlinType subReturnType = subDescriptor.getReturnType(); if (superReturnType != null && subReturnType != null) { boolean bothErrors = subReturnType.isError() && superReturnType.isError(); if (!bothErrors && !typeChecker.isSubtypeOf(subReturnType, superReturnType)) { return OverrideCompatibilityInfo.conflict("Return type mismatch"); } } } return OverrideCompatibilityInfo.success(); }
@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; }
@Override protected void reportSupertypeLoopError(@NotNull KotlinType type) { ClassifierDescriptor supertypeDescriptor = type.getConstructor().getDeclarationDescriptor(); if (supertypeDescriptor instanceof ClassDescriptor) { ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor; reportCyclicInheritanceHierarchyError(c.getTrace(), LazyClassDescriptor.this, superclass); } }
public static boolean isExtensionFunctionType(@NotNull KotlinType type) { if (isExactExtensionFunctionType(type)) return true; for (KotlinType superType : type.getConstructor().getSupertypes()) { if (isExtensionFunctionType(superType)) return true; } return false; }
@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; }
private static boolean isConstructedFromGivenClass( @NotNull KotlinType type, @NotNull FqNameUnsafe fqName) { ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); return descriptor != null && /* quick check to avoid creation of full FqName instance */ descriptor .getName() .equals(fqName.shortName()) && fqName.equals(getFqName(descriptor)); }
public static boolean isSubtypeOfClass( @NotNull KotlinType type, @NotNull DeclarationDescriptor superClass) { if (isSameClass(type, superClass)) return true; for (KotlinType superType : type.getConstructor().getSupertypes()) { if (isSubtypeOfClass(superType, superClass)) { return true; } } return false; }
public static boolean shouldRecordInitializerForProperty( @NotNull VariableDescriptor variable, @NotNull KotlinType type) { if (variable.isVar() || type.isError()) return false; if (TypeUtils.acceptsNullable(type)) return true; KotlinBuiltIns builtIns = getBuiltIns(variable); return KotlinBuiltIns.isPrimitiveType(type) || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getStringType(), type) || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getNumber().getDefaultType(), type) || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type); }
@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; }
private static boolean isSameClass( @NotNull KotlinType type, @NotNull DeclarationDescriptor other) { DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); if (descriptor != null) { DeclarationDescriptor originalDescriptor = descriptor.getOriginal(); if (originalDescriptor instanceof ClassifierDescriptor && other instanceof ClassifierDescriptor && ((ClassifierDescriptor) other) .getTypeConstructor() .equals(((ClassifierDescriptor) originalDescriptor).getTypeConstructor())) { return true; } } return false; }
@NotNull private static KtProperty createProperty( @NotNull KtProperty property, @NotNull KotlinType propertyType, @Nullable String initializer) { KtTypeReference typeRef = property.getTypeReference(); String typeString = null; if (typeRef != null) { typeString = typeRef.getText(); } else if (!propertyType.isError()) { typeString = IdeDescriptorRenderers.SOURCE_CODE.renderType(propertyType); } return KtPsiFactoryKt.KtPsiFactory(property) .createProperty(property.getName(), typeString, property.isVar(), initializer); }
@Override public boolean apply(KotlinType type) { assert !type.isError() : "Error types must be filtered out in DescriptorResolver"; return TypeUtils.getClassDescriptor(type) != null; }
public static boolean isPrimitiveType(@NotNull KotlinType type) { ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); return !type.isMarkedNullable() && descriptor instanceof ClassDescriptor && isPrimitiveClass((ClassDescriptor) descriptor); }
public static boolean isNullableNothing(@NotNull KotlinType type) { return isNothingOrNullableNothing(type) && type.isMarkedNullable(); }
@NotNull public static ClassDescriptor getClassDescriptorForType(@NotNull KotlinType type) { return getClassDescriptorForTypeConstructor(type.getConstructor()); }
public static boolean isNullableAny(@NotNull KotlinType type) { return isAnyOrNullableAny(type) && type.isMarkedNullable(); }
private static boolean isNotNullConstructedFromGivenClass( @NotNull KotlinType type, @NotNull FqNameUnsafe fqName) { return !type.isMarkedNullable() && isConstructedFromGivenClass(type, fqName); }
private static boolean isTypeAnnotatedWithExtension(@NotNull KotlinType type) { return type.getAnnotations().findAnnotation(FQ_NAMES.extensionFunctionType) != null || type.getAnnotations().findAnnotation(FQ_NAMES.deprecatedExtensionAnnotation) != null; }
@NotNull public static KotlinType getReturnTypeFromFunctionType(@NotNull KotlinType type) { assert isFunctionOrExtensionFunctionType(type); List<TypeProjection> arguments = type.getArguments(); return arguments.get(arguments.size() - 1).getType(); }
public static boolean isPrimitiveArray(@NotNull KotlinType type) { ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); return descriptor != null && getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null; }
public static boolean isExactFunctionOrExtensionFunctionType(@NotNull KotlinType type) { ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); return descriptor != null && isNumberedFunctionClassFqName(getFqName(descriptor)); }
@NotNull public OverrideCompatibilityInfo isOverridableByWithoutExternalConditions( @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor, boolean checkReturnType) { if (superDescriptor instanceof FunctionDescriptor && !(subDescriptor instanceof FunctionDescriptor) || superDescriptor instanceof PropertyDescriptor && !(subDescriptor instanceof PropertyDescriptor)) { return OverrideCompatibilityInfo.incompatible("Member kind mismatch"); } if (!(superDescriptor instanceof FunctionDescriptor) && !(superDescriptor instanceof PropertyDescriptor)) { throw new IllegalArgumentException( "This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor); } // TODO: check outside of this method if (!superDescriptor.getName().equals(subDescriptor.getName())) { return OverrideCompatibilityInfo.incompatible("Name mismatch"); } OverrideCompatibilityInfo receiverAndParameterResult = checkReceiverAndParameterCount(superDescriptor, subDescriptor); if (receiverAndParameterResult != null) { return receiverAndParameterResult; } List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor); List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor); List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters(); List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters(); if (superTypeParameters.size() != subTypeParameters.size()) { for (int i = 0; i < superValueParameters.size(); ++i) { // TODO: compare erasure if (!KotlinTypeChecker.DEFAULT.equalTypes( superValueParameters.get(i), subValueParameters.get(i))) { return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch"); } } return OverrideCompatibilityInfo.conflict("Type parameter number mismatch"); } KotlinTypeChecker typeChecker = createTypeChecker(superTypeParameters, subTypeParameters); for (int i = 0; i < superTypeParameters.size(); i++) { if (!areTypeParametersEquivalent( superTypeParameters.get(i), subTypeParameters.get(i), typeChecker)) { return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch"); } } for (int i = 0; i < superValueParameters.size(); i++) { if (!areTypesEquivalent( superValueParameters.get(i), subValueParameters.get(i), typeChecker)) { return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch"); } } if (checkReturnType) { KotlinType superReturnType = superDescriptor.getReturnType(); KotlinType subReturnType = subDescriptor.getReturnType(); if (superReturnType != null && subReturnType != null) { boolean bothErrors = subReturnType.isError() && superReturnType.isError(); if (!bothErrors && !typeChecker.isSubtypeOf(subReturnType, superReturnType)) { return OverrideCompatibilityInfo.conflict("Return type mismatch"); } } } return OverrideCompatibilityInfo.success(); }