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

org.jetbrains.kotlin.resolve.DelegationResolver.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
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 org.jetbrains.kotlin.resolve

import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils

class DelegationResolver private constructor(
        private val classOrObject: KtClassOrObject,
        private val ownerDescriptor: ClassDescriptor,
        private val existingMembers: Collection,
        private val trace: BindingTrace,
        private val memberExtractor: DelegationResolver.MemberExtractor,
        private val typeResolver: DelegationResolver.TypeResolver
) {

    private fun generateDelegatedMembers(): Collection {
        val delegatedMembers = hashSetOf()
        for (delegationSpecifier in classOrObject.getSuperTypeListEntries()) {
            if (delegationSpecifier !is KtDelegatedSuperTypeEntry) {
                continue
            }
            val typeReference = delegationSpecifier.typeReference ?: continue
            val delegatedInterfaceType = typeResolver.resolve(typeReference)
            if (delegatedInterfaceType == null || delegatedInterfaceType.isError) {
                continue
            }
            val delegatesForInterface = generateDelegatesForInterface(delegatedMembers, delegatedInterfaceType)
            delegatedMembers.addAll(delegatesForInterface)
        }
        return delegatedMembers
    }

    private fun generateDelegatesForInterface(existingDelegates: Collection, delegatedInterfaceType: KotlinType): Collection =
            generateDelegationCandidates(delegatedInterfaceType).filter { candidate ->
                !isOverridingAnyOf(candidate, existingMembers) &&
                !checkClashWithOtherDelegatedMember(candidate, existingDelegates)
            }

    private fun generateDelegationCandidates(delegatedInterfaceType: KotlinType): Collection =
            getDelegatableMembers(delegatedInterfaceType).map { memberDescriptor ->
                val newModality = if (memberDescriptor.modality == Modality.ABSTRACT) Modality.OPEN else memberDescriptor.modality
                @Suppress("UNCHECKED_CAST")
                (memberDescriptor.copy(ownerDescriptor, newModality, Visibilities.INHERITED, DELEGATION, false) as T)
            }

    private fun checkClashWithOtherDelegatedMember(candidate: T, delegatedMembers: Collection): Boolean {
        val alreadyDelegated = delegatedMembers.firstOrNull { isOverridableBy(it, candidate) }
        if (alreadyDelegated != null) {
            trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(classOrObject, classOrObject, alreadyDelegated))
            return true;
        }
        return false;
    }


    private fun getDelegatableMembers(interfaceType: KotlinType): Collection {
        val classSupertypeMembers =
                TypeUtils.getAllSupertypes(interfaceType).firstOrNull {
                    val typeConstructor = it.constructor.declarationDescriptor
                    typeConstructor is ClassDescriptor && typeConstructor.kind != ClassKind.INTERFACE
                }?.let {
                    memberExtractor.getMembersByType(it)
                } ?: emptyList()
        return memberExtractor.getMembersByType(interfaceType).filter { descriptor ->
            descriptor.isOverridable && !classSupertypeMembers.any { isOverridableBy(it, descriptor)  }
        }
    }

    interface MemberExtractor {
        fun getMembersByType(type: KotlinType): Collection
    }

    interface TypeResolver {
        fun resolve(reference: KtTypeReference): KotlinType?
    }

    companion object {
        fun  generateDelegatedMembers(
                classOrObject: KtClassOrObject,
                ownerDescriptor: ClassDescriptor,
                existingMembers: Collection,
                trace: BindingTrace,
                memberExtractor: MemberExtractor,
                typeResolver: TypeResolver
        ): Collection =
                DelegationResolver(classOrObject, ownerDescriptor, existingMembers, trace, memberExtractor, typeResolver)
                        .generateDelegatedMembers()

        private fun isOverridingAnyOf(
                candidate: CallableMemberDescriptor,
                possiblyOverriddenBy: Collection
        ): Boolean =
                possiblyOverriddenBy.any { isOverridableBy(it, candidate) }

        private fun isOverridableBy(memberOne: CallableDescriptor, memberTwo: CallableDescriptor): Boolean =
                OverridingUtil.DEFAULT.isOverridableBy(memberOne, memberTwo, null).result == OVERRIDABLE

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy