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

kotlin.reflect.jvm.internal.impl.resolve.DescriptorUtils.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-RC
Show newest version
/*
 * Copyright 2010-2015 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 kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil

import kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns
import kotlin.reflect.jvm.internal.impl.descriptors.*
import kotlin.reflect.jvm.internal.impl.descriptors.ClassKind.*
import kotlin.reflect.jvm.internal.impl.descriptors.annotations.Annotated
import kotlin.reflect.jvm.internal.impl.descriptors.annotations.KotlinRetention
import kotlin.reflect.jvm.internal.impl.incremental.components.LookupLocation
import kotlin.reflect.jvm.internal.impl.name.ClassId
import kotlin.reflect.jvm.internal.impl.name.FqName
import kotlin.reflect.jvm.internal.impl.name.FqNameUnsafe
import kotlin.reflect.jvm.internal.impl.resolve.DescriptorUtils
import kotlin.reflect.jvm.internal.impl.resolve.constants.EnumValue
import kotlin.reflect.jvm.internal.impl.types.*
import kotlin.reflect.jvm.internal.impl.types.checker.KotlinTypeChecker
import kotlin.reflect.jvm.internal.impl.types.typeUtil.isAnyOrNullableAny
import kotlin.reflect.jvm.internal.impl.utils.DFS
import kotlin.reflect.jvm.internal.impl.utils.SmartList
import kotlin.reflect.jvm.internal.impl.utils.addToStdlib.check

fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = companionObjectDescriptor ?: this

fun DeclarationDescriptor.getImportableDescriptor(): DeclarationDescriptor {
    return when {
        this is ConstructorDescriptor -> containingDeclaration
        this is PropertyAccessorDescriptor -> correspondingProperty
        else -> this
    }
}

val DeclarationDescriptor.fqNameUnsafe: FqNameUnsafe
    get() = DescriptorUtils.getFqName(this)

val DeclarationDescriptor.fqNameSafe: FqName
    get() = DescriptorUtils.getFqNameSafe(this)

val DeclarationDescriptor.isExtension: Boolean
    get() = this is CallableDescriptor && extensionReceiverParameter != null

val DeclarationDescriptor.module: ModuleDescriptor
    get() = DescriptorUtils.getContainingModule(this)

fun ModuleDescriptor.resolveTopLevelClass(topLevelClassFqName: FqName, location: LookupLocation): ClassDescriptor? {
    assert(!topLevelClassFqName.isRoot)
    return getPackage(topLevelClassFqName.parent()).memberScope.getContributedClassifier(topLevelClassFqName.shortName(), location) as? ClassDescriptor
}

val ClassDescriptor.classId: ClassId
    get() {
        val owner = containingDeclaration
        if (owner is PackageFragmentDescriptor) {
            return ClassId(owner.fqName, name)
        }
        else if (owner is ClassDescriptor) {
            return owner.classId.createNestedClassId(name)
        }
        throw IllegalStateException("Illegal container: $owner")
    }

val ClassDescriptor.hasCompanionObject: Boolean get() = companionObjectDescriptor != null

val ClassDescriptor.hasClassValueDescriptor: Boolean get() = classValueDescriptor != null

val ClassDescriptor.classValueDescriptor: ClassDescriptor?
    get() = if (kind.isSingleton) this else companionObjectDescriptor

val ClassDescriptor.classValueTypeDescriptor: ClassDescriptor?
    get() = when (kind) {
        OBJECT -> this
        ENUM_ENTRY -> {
            // enum entry has the type of enum class
            val container = this.containingDeclaration
            assert(container is ClassDescriptor && container.kind == ENUM_CLASS)
            container as ClassDescriptor
        }
        else -> companionObjectDescriptor
    }

/** If a literal of this class can be used as a value, returns the type of this value */
val ClassDescriptor.classValueType: KotlinType?
    get() = classValueTypeDescriptor?.defaultType

val DeclarationDescriptorWithVisibility.isEffectivelyPublicApi: Boolean
    get() = effectiveVisibility().publicApi

val DeclarationDescriptorWithVisibility.isEffectivelyPrivateApi: Boolean
    get() = effectiveVisibility().privateApi


val DeclarationDescriptor.isInsidePrivateClass: Boolean
    get() {
        var parent = containingDeclaration as? ClassDescriptor
        return parent != null && Visibilities.isPrivate(parent.visibility)
    }


fun ClassDescriptor.getSuperClassNotAny(): ClassDescriptor? {
    for (supertype in defaultType.constructor.supertypes) {
        if (!KotlinBuiltIns.isAnyOrNullableAny(supertype)) {
            val superClassifier = supertype.constructor.declarationDescriptor
            if (DescriptorUtils.isClassOrEnumClass(superClassifier)) {
                return superClassifier as ClassDescriptor
            }
        }
    }
    return null
}

fun ClassDescriptor.getSuperClassOrAny(): ClassDescriptor = getSuperClassNotAny() ?: builtIns.any

val ClassDescriptor.secondaryConstructors: List
    get() = constructors.filterNot { it.isPrimary }

val DeclarationDescriptor.builtIns: KotlinBuiltIns
    get() = module.builtIns

/**
 * Returns containing declaration of dispatch receiver for callable adjusted to fake-overridden cases
 *
 * open class A {
 *   fun foo() = 1
 * }
 * class B : A()
 *
 * for A.foo -> returns A (dispatch receiver parameter is A)
 * for B.foo -> returns B (dispatch receiver parameter is still A, but it's fake-overridden in B, so it's containing declaration is B)
 *
 * class Outer {
 *   inner class Inner()
 * }
 *
 * for constructor of Outer.Inner -> returns Outer (dispatch receiver parameter is Outer, but it's containing declaration is Inner)
 *
 */
fun CallableDescriptor.getOwnerForEffectiveDispatchReceiverParameter(): DeclarationDescriptor? {
    if (this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
        return getContainingDeclaration()
    }
    return dispatchReceiverParameter?.containingDeclaration
}

/**
 * @return `true` iff the parameter has a default value, i.e. declares it or inherits by overriding a parameter which has a default value.
 */
fun ValueParameterDescriptor.hasDefaultValue(): Boolean {
    return DFS.ifAny(
            listOf(this),
            DFS.Neighbors { current ->
                current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal)
            },
            ValueParameterDescriptor::declaresDefaultValue
    )
}

fun Annotated.isRepeatableAnnotation(): Boolean =
        annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.repeatable) != null

fun Annotated.isDocumentedAnnotation(): Boolean =
        annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.mustBeDocumented) != null

fun Annotated.getAnnotationRetention(): KotlinRetention? {
    val annotationEntryDescriptor = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.retention) ?: return null
    val retentionArgumentValue = annotationEntryDescriptor.allValueArguments.entries.firstOrNull {
        it.key.name.asString() == "value"
    }?.value as? EnumValue ?: return null
    return KotlinRetention.valueOf(retentionArgumentValue.value.name.asString())
}

val DeclarationDescriptor.parentsWithSelf: Sequence
    get() = generateSequence(this, { it.containingDeclaration })

val DeclarationDescriptor.parents: Sequence
    get() = parentsWithSelf.drop(1)

val CallableMemberDescriptor.propertyIfAccessor: CallableMemberDescriptor
    get() = if (this is PropertyAccessorDescriptor) correspondingProperty else this

fun CallableDescriptor.fqNameOrNull(): FqName? = fqNameUnsafe.check { it.isSafe }?.toSafe()

fun CallableMemberDescriptor.firstOverridden(
        useOriginal: Boolean = false,
        predicate: (CallableMemberDescriptor) -> Boolean
): CallableMemberDescriptor? {
    var result: CallableMemberDescriptor? = null
    return DFS.dfs(listOf(this),
                   { current ->
                       val descriptor = if (useOriginal) current?.original else current
                       descriptor?.overriddenDescriptors ?: emptyList()
                   },
                   object : DFS.AbstractNodeHandler() {
                       override fun beforeChildren(current: CallableMemberDescriptor) = result == null
                       override fun afterChildren(current: CallableMemberDescriptor) {
                           if (result == null && predicate(current)) {
                               result = current
                           }
                       }
                       override fun result(): CallableMemberDescriptor? = result
                   }
    )
}

fun CallableMemberDescriptor.setSingleOverridden(overridden: CallableMemberDescriptor) {
    overriddenDescriptors = listOf(overridden)
}

fun CallableMemberDescriptor.overriddenTreeAsSequence(useOriginal: Boolean): Sequence =
    with(if (useOriginal) original else this) {
        sequenceOf(this) + overriddenDescriptors.asSequence().flatMap { it.overriddenTreeAsSequence(useOriginal) }
    }

fun  D.overriddenTreeUniqueAsSequence(useOriginal: Boolean): Sequence {
    val set = hashSetOf()

    @Suppress("UNCHECKED_CAST")
    fun D.doBuildOverriddenTreeAsSequence(): Sequence {
        return with(if (useOriginal) original as D else this) {
            if (original in set)
                emptySequence()
            else {
                set += original as D
                sequenceOf(this) + (overriddenDescriptors as Collection).asSequence().flatMap { it.doBuildOverriddenTreeAsSequence() }
            }
        }
    }

    return doBuildOverriddenTreeAsSequence()
}

/**
 * When `Inner` is used as type outside of `Outer` class all type arguments should be specified, e.g. `Outer.Inner`
 * However, it's not necessary inside Outer's members, only the last one should be specified there.
 * So this function return a list of arguments that should be used if relevant arguments weren't specified explicitly inside the [scopeOwner].
 *
 * Examples:
 * for `Outer` class the map will contain: Outer -> (X, Y) (i.e. defaultType mapping)
 * for `Derived` class the map will contain: Derived -> (E), Outer -> (E, String)
 * for `A.B` class the map will contain: B -> (), Outer -> (Int, CharSequence), A -> ()
 *
 * open class Outer {
 *  inner class Inner
 * }
 *
 * class Derived : Outer()
 *
 * class A : Outer() {
 *   inner class B : Outer()
 * }
 */

fun findImplicitOuterClassArguments(
        scopeOwner: ClassDescriptor,
        outerClass: ClassDescriptor,
        // this parameter must be removed after 1.0.5 release
        preserveCompatibility: Boolean
): List? {
    for (current in scopeOwner.classesFromInnerToOuter()) {
        val typesToConsider =
                if (preserveCompatibility)
                    listOf(current.defaultType)
                else
                    current.getAllSuperClassesTypesIncludeItself()

        for (supertype in typesToConsider) {
            val classDescriptor = supertype.constructor.declarationDescriptor as ClassDescriptor
            if (classDescriptor == outerClass) return supertype.arguments
        }
    }

    return null
}

private fun ClassDescriptor.classesFromInnerToOuter() = generateSequence(this) {
    if (it.isInner)
        it.containingDeclaration.original as? ClassDescriptor
    else
        null
}

private fun ClassDescriptor.getAllSuperClassesTypesIncludeItself(): List {
    val result = arrayListOf()
    var current: KotlinType = defaultType

    while (!current.isAnyOrNullableAny()) {
        result.add(current)
        val next = DescriptorUtils.getSuperClassType(current.constructor.declarationDescriptor as ClassDescriptor)
        current = TypeSubstitutor.create(current).substitute(next, Variance.INVARIANT) ?: break
    }

    return result
}

fun ClassDescriptor.getAllSuperclassesWithoutAny() =
        generateSequence(getSuperClassNotAny(), ClassDescriptor::getSuperClassNotAny).toCollection(SmartList())

fun FunctionDescriptor.isEnumValueOfMethod(): Boolean {
    val methodTypeParameters = valueParameters
    val nullableString = TypeUtils.makeNullable(builtIns.stringType)
    return DescriptorUtils.ENUM_VALUE_OF == name
           && methodTypeParameters.size == 1
           && KotlinTypeChecker.DEFAULT.isSubtypeOf(methodTypeParameters[0].type, nullableString)
}

val DeclarationDescriptor.isExtensionProperty: Boolean
    get() = this is PropertyDescriptor && extensionReceiverParameter != null




© 2015 - 2025 Weber Informatics LLC | Privacy Policy