All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.types.TypeUtils.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2016 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.kotlin.types.typeUtil

import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.inference.isCaptured
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import java.util.*

enum class TypeNullability {
    NOT_NULL,
    NULLABLE,
    FLEXIBLE
}

fun KotlinType.nullability(): TypeNullability {
    return when {
        isNullabilityFlexible() -> TypeNullability.FLEXIBLE
        TypeUtils.isNullableType(this) -> TypeNullability.NULLABLE
        else -> TypeNullability.NOT_NULL
    }
}

val KotlinType.builtIns: KotlinBuiltIns
    get() = constructor.builtIns

fun KotlinType.makeNullable() = TypeUtils.makeNullable(this)
fun KotlinType.makeNotNullable() = TypeUtils.makeNotNullable(this)

fun KotlinType.immediateSupertypes(): Collection = TypeUtils.getImmediateSupertypes(this)
fun KotlinType.supertypes(): Collection = TypeUtils.getAllSupertypes(this)

fun KotlinType.isNothing(): Boolean = KotlinBuiltIns.isNothing(this)
fun KotlinType.isNullableNothing(): Boolean = KotlinBuiltIns.isNullableNothing(this)
fun KotlinType.isUnit(): Boolean = KotlinBuiltIns.isUnit(this)
fun KotlinType.isAnyOrNullableAny(): Boolean = KotlinBuiltIns.isAnyOrNullableAny(this)
fun KotlinType.isNullableAny(): Boolean = KotlinBuiltIns.isNullableAny(this)
fun KotlinType.isBoolean(): Boolean = KotlinBuiltIns.isBoolean(this)
fun KotlinType.isPrimitiveNumberType(): Boolean = KotlinBuiltIns.isPrimitiveType(this) && !isBoolean()
fun KotlinType.isBooleanOrNullableBoolean(): Boolean = KotlinBuiltIns.isBooleanOrNullableBoolean(this)
fun KotlinType.isNotNullThrowable(): Boolean = KotlinBuiltIns.isThrowableOrNullableThrowable(this) && !isMarkedNullable

fun KotlinType.isTypeParameter(): Boolean = TypeUtils.isTypeParameter(this)

fun KotlinType.isInterface(): Boolean = (constructor.declarationDescriptor as? ClassDescriptor)?.kind == ClassKind.INTERFACE

fun KotlinType?.isArrayOfNothing(): Boolean {
    if (this == null || !KotlinBuiltIns.isArray(this)) return false

    val typeArg = arguments.firstOrNull()?.type
    return typeArg != null && KotlinBuiltIns.isNothingOrNullableNothing(typeArg)
}


fun KotlinType.isSubtypeOf(superType: KotlinType): Boolean = KotlinTypeChecker.DEFAULT.isSubtypeOf(this, superType)

fun isNullabilityMismatch(expected: KotlinType, actual: KotlinType) =
        !expected.isMarkedNullable && actual.isMarkedNullable && actual.isSubtypeOf(TypeUtils.makeNullable(expected))

fun KotlinType.cannotBeReified(): Boolean =
        KotlinBuiltIns.isNothingOrNullableNothing(this) || this.isDynamic() || this.isCaptured()

fun TypeProjection.substitute(doSubstitute: (KotlinType) -> KotlinType): TypeProjection {
    return if (isStarProjection)
        this
    else TypeProjectionImpl(projectionKind, doSubstitute(type))
}

fun KotlinType.replaceAnnotations(newAnnotations: Annotations): KotlinType {
    if (annotations.isEmpty() && newAnnotations.isEmpty()) return this
    return unwrap().replaceAnnotations(newAnnotations)
}

fun KotlinTypeChecker.equalTypesOrNulls(type1: KotlinType?, type2: KotlinType?): Boolean {
    if (type1 === type2) return true
    if (type1 == null || type2 == null) return false
    return equalTypes(type1, type2)
}

fun KotlinType.containsError() = ErrorUtils.containsErrorType(this)

fun List.defaultProjections(): List = map(::TypeProjectionImpl)

fun KotlinType.isDefaultBound(): Boolean = KotlinBuiltIns.isDefaultBound(getSupertypeRepresentative())

fun createProjection(type: KotlinType, projectionKind: Variance, typeParameterDescriptor: TypeParameterDescriptor?): TypeProjection =
        TypeProjectionImpl(if (typeParameterDescriptor?.variance == projectionKind) Variance.INVARIANT else projectionKind, type)

fun Collection.closure(f: (KotlinType) -> Collection): Collection {
    if (size == 0) return this

    val result = HashSet(this)
    var elementsToCheck = result
    var oldSize = 0
    while (result.size > oldSize) {
        oldSize = result.size
        val toAdd = hashSetOf()
        elementsToCheck.forEach { toAdd.addAll(f(it)) }
        result.addAll(toAdd)
        elementsToCheck = toAdd
    }

    return result
}

fun boundClosure(types: Collection): Collection =
        types.closure { type -> TypeUtils.getTypeParameterDescriptorOrNull(type)?.upperBounds ?: emptySet() }

fun constituentTypes(types: Collection): Collection {
    val result = hashSetOf()
    constituentTypes(result, types)
    return result
}

fun KotlinType.constituentTypes(): Collection =
        constituentTypes(listOf(this))

private fun constituentTypes(result: MutableSet, types: Collection) {
    result.addAll(types)
    for (type in types) {
        if (type.isFlexible()) {
            with (type.asFlexibleType()) { constituentTypes(result, setOf(lowerBound, upperBound)) }
        }
        else {
            constituentTypes(result, type.arguments.mapNotNull { if (!it.isStarProjection) it.type else null })
        }
    }
}

fun KotlinType.getImmediateSuperclassNotAny(): KotlinType? {
    val superclasses = constructor.supertypes.filter {
        DescriptorUtils.isClassOrEnumClass(it.constructor.declarationDescriptor) && !KotlinBuiltIns.isAnyOrNullableAny(it)
    }
    return superclasses.singleOrNull()?.let {
        TypeUtils.createSubstitutedSupertype(this, it, TypeSubstitutor.create(this))
    }
}

fun KotlinType.asTypeProjection(): TypeProjection = TypeProjectionImpl(this)
fun KotlinType.contains(predicate: (UnwrappedType) -> Boolean) = TypeUtils.contains(this, predicate)

fun KotlinType.replaceArgumentsWithStarProjections(): KotlinType {
    val unwrapped = unwrap()
    return when (unwrapped) {
        is FlexibleType -> KotlinTypeFactory.flexibleType(
                unwrapped.lowerBound.replaceArgumentsWithStarProjections(),
                unwrapped.upperBound.replaceArgumentsWithStarProjections()
        )
        is SimpleType -> unwrapped.replaceArgumentsWithStarProjections()
    }
}

private fun SimpleType.replaceArgumentsWithStarProjections(): SimpleType {
    if (constructor.parameters.isEmpty() || constructor.declarationDescriptor == null) return this

    val newArguments = constructor.parameters.map(::StarProjectionImpl)

    return replace(newArguments)
}

fun KotlinType.containsTypeAliasParameters(): Boolean =
        contains {
            it.constructor.declarationDescriptor?.isTypeAliasParameter() ?: false
        }

fun KotlinType.containsTypeAliases(): Boolean =
        contains {
            it.constructor.declarationDescriptor is TypeAliasDescriptor
        }

fun ClassifierDescriptor.isTypeAliasParameter(): Boolean =
        this is TypeParameterDescriptor && containingDeclaration is TypeAliasDescriptor

fun KotlinType.requiresTypeAliasExpansion(): Boolean =
        contains {
            it.constructor.declarationDescriptor?.let {
                it is TypeAliasDescriptor || it is TypeParameterDescriptor
            } ?: false
        }

fun KotlinType.containsTypeProjectionsInTopLevelArguments(): Boolean {
    if (isError) return false
    val possiblyInnerType = buildPossiblyInnerType() ?: return false
    return possiblyInnerType.arguments.any { it.isStarProjection || it.projectionKind != Variance.INVARIANT }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy