diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt index a307ceb4259..67b0f23403a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt @@ -14,200 +14,108 @@ * limitations under the License. */ -package org.jetbrains.kotlin.resolve; +package org.jetbrains.kotlin.resolve -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.psi.KtClassOrObject; -import org.jetbrains.kotlin.psi.KtDelegationSpecifier; -import org.jetbrains.kotlin.psi.KtDelegatorByExpressionSpecifier; -import org.jetbrains.kotlin.psi.KtTypeReference; -import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.TypeUtils; +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.KtDelegatorByExpressionSpecifier +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 -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; +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 +) { -import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION; -import static org.jetbrains.kotlin.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED; -import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; - -public final class DelegationResolver { - - @NotNull - public static Collection generateDelegatedMembers( - @NotNull KtClassOrObject classOrObject, - @NotNull ClassDescriptor ownerDescriptor, - @NotNull Collection existingMembers, - @NotNull BindingTrace trace, - @NotNull MemberExtractor memberExtractor, - @NotNull TypeResolver typeResolver - ) { - return new DelegationResolver(classOrObject, ownerDescriptor, existingMembers, trace, memberExtractor, typeResolver) - .generateDelegatedMembers(); - } - - @NotNull private final KtClassOrObject classOrObject; - @NotNull private final ClassDescriptor ownerDescriptor; - @NotNull private final Collection existingMembers; - @NotNull private final BindingTrace trace; - @NotNull private final MemberExtractor memberExtractor; - @NotNull private final TypeResolver typeResolver; - - private DelegationResolver( - @NotNull KtClassOrObject classOrObject, - @NotNull ClassDescriptor ownerDescriptor, - @NotNull Collection existingMembers, - @NotNull BindingTrace trace, - @NotNull MemberExtractor extractor, - @NotNull TypeResolver resolver - ) { - - this.classOrObject = classOrObject; - this.ownerDescriptor = ownerDescriptor; - this.existingMembers = existingMembers; - this.trace = trace; - this.memberExtractor = extractor; - this.typeResolver = resolver; - } - - @NotNull - private Collection generateDelegatedMembers() { - Collection delegatedMembers = new HashSet(); - for (KtDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) { - if (!(delegationSpecifier instanceof KtDelegatorByExpressionSpecifier)) { - continue; + private fun generateDelegatedMembers(): Collection { + val delegatedMembers = hashSetOf() + for (delegationSpecifier in classOrObject.getDelegationSpecifiers()) { + if (delegationSpecifier !is KtDelegatorByExpressionSpecifier) { + continue } - KtDelegatorByExpressionSpecifier specifier = (KtDelegatorByExpressionSpecifier) delegationSpecifier; - KtTypeReference typeReference = specifier.getTypeReference(); - if (typeReference == null) { - continue; + val typeReference = delegationSpecifier.typeReference ?: continue + val delegatedInterfaceType = typeResolver.resolve(typeReference) + if (delegatedInterfaceType == null || delegatedInterfaceType.isError) { + continue } - KotlinType delegatedTraitType = typeResolver.resolve(typeReference); - if (delegatedTraitType == null || delegatedTraitType.isError()) { - continue; - } - Collection delegatesForTrait = generateDelegatesForTrait(delegatedMembers, delegatedTraitType); - delegatedMembers.addAll(delegatesForTrait); + val delegatesForInterface = generateDelegatesForInterface(delegatedMembers, delegatedInterfaceType) + delegatedMembers.addAll(delegatesForInterface) } - return delegatedMembers; + return delegatedMembers } - @NotNull - private Collection generateDelegatesForTrait( - @NotNull Collection existingDelegates, - @NotNull KotlinType delegatedTraitType - ) { - Collection result = new HashSet(); - Collection candidates = generateDelegationCandidates(delegatedTraitType); - for (T candidate : candidates) { - if (existingMemberOverridesDelegatedMember(candidate, existingMembers)) { - continue; - } - //only leave the first delegated member - if (checkClashWithOtherDelegatedMember(existingDelegates, candidate)) { - continue; + private fun generateDelegatesForInterface(existingDelegates: Collection, delegatedInterfaceType: KotlinType): Collection = + generateDelegationCandidates(delegatedInterfaceType).filter { candidate -> + !isOverridingAnyOf(candidate, existingMembers) && + !checkClashWithOtherDelegatedMember(candidate, existingDelegates) } - result.add(candidate); - } - return result; - } - - @NotNull - private Collection generateDelegationCandidates(@NotNull KotlinType delegatedTraitType) { - Collection descriptorsToDelegate = overridableMembersNotFromSuperClassOfTrait(delegatedTraitType); - Collection result = new ArrayList(descriptorsToDelegate.size()); - for (T memberDescriptor : descriptorsToDelegate) { - Modality newModality = memberDescriptor.getModality() == Modality.ABSTRACT ? Modality.OPEN : memberDescriptor.getModality(); - @SuppressWarnings("unchecked") - T copy = (T) memberDescriptor.copy(ownerDescriptor, newModality, Visibilities.INHERITED, DELEGATION, false); - result.add(copy); - } - return result; - } - - private static boolean existingMemberOverridesDelegatedMember( - @NotNull CallableMemberDescriptor candidate, - @NotNull Collection existingMembers - ) { - for (CallableDescriptor existingDescriptor : existingMembers) { - if (haveSameSignatures(existingDescriptor, candidate)) { - return true; + 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 boolean checkClashWithOtherDelegatedMember(@NotNull Collection delegatedMembers, @NotNull T candidate) { - for (CallableMemberDescriptor alreadyDelegatedMember : delegatedMembers) { - if (haveSameSignatures(alreadyDelegatedMember, candidate)) { - //trying to delegate to many traits with the same methods - trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(classOrObject, classOrObject, alreadyDelegatedMember)); - return true; - } + + 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.modality.isOverridable && !classSupertypeMembers.any { isOverridableBy(it, descriptor) } } - return false; } - @NotNull - private Collection overridableMembersNotFromSuperClassOfTrait(@NotNull KotlinType trait) { - final Collection membersToSkip = getMembersFromClassSupertypeOfTrait(trait); - return Collections2.filter( - memberExtractor.getMembersByType(trait), - new Predicate() { - @Override - public boolean apply(CallableMemberDescriptor descriptor) { - if (!descriptor.getModality().isOverridable()) { - return false; - } - for (CallableMemberDescriptor memberToSkip : membersToSkip) { - if (haveSameSignatures(memberToSkip, descriptor)) { - return false; - } - } - return true; - } - }); + interface MemberExtractor { + fun getMembersByType(type: KotlinType): Collection } - private static boolean haveSameSignatures(@NotNull CallableDescriptor memberOne, @NotNull CallableDescriptor memberTwo) { - //isOverridableBy ignores return types - return OverridingUtil.DEFAULT.isOverridableBy(memberOne, memberTwo).getResult() == OVERRIDABLE; + interface TypeResolver { + fun resolve(reference: KtTypeReference): KotlinType? } - @NotNull - private Collection getMembersFromClassSupertypeOfTrait(@NotNull KotlinType traitType) { - KotlinType classSupertype = null; - for (KotlinType supertype : TypeUtils.getAllSupertypes(traitType)) { - if (isNotTrait(supertype.getConstructor().getDeclarationDescriptor())) { - classSupertype = supertype; - break; - } - } - return classSupertype != null ? memberExtractor.getMembersByType(classSupertype) : Collections.emptyList(); - } + 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 static boolean isNotTrait(@Nullable DeclarationDescriptor descriptor) { - if (descriptor instanceof ClassDescriptor) { - ClassKind kind = ((ClassDescriptor) descriptor).getKind(); - return kind != ClassKind.INTERFACE; - } - return false; - } + private fun isOverridingAnyOf( + candidate: CallableMemberDescriptor, + possiblyOverriddenBy: Collection + ): Boolean = + possiblyOverriddenBy.any { isOverridableBy(it, candidate) } - public interface MemberExtractor { - @NotNull - Collection getMembersByType(@NotNull KotlinType type); - } + private fun isOverridableBy(memberOne: CallableDescriptor, memberTwo: CallableDescriptor): Boolean = + OverridingUtil.DEFAULT.isOverridableBy(memberOne, memberTwo).result == OVERRIDABLE - public interface TypeResolver { - @Nullable - KotlinType resolve(@NotNull KtTypeReference reference); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt index 0d41874b503..796c29ff850 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt @@ -27,15 +27,15 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.DelegationResolver.generateDelegatedMembers import org.jetbrains.kotlin.resolve.dataClassUtils.createComponentName import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike import org.jetbrains.kotlin.resolve.lazy.LazyClassContext import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope +import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker import org.jetbrains.kotlin.storage.NotNullLazyValue import org.jetbrains.kotlin.storage.NullableLazyValue @@ -231,13 +231,15 @@ public open class LazyClassMemberScope( val classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject() ?: return setOf() - val lazyTypeResolver = DelegationResolver.TypeResolver { reference -> - c.typeResolver.resolveType(thisDescriptor.getScopeForClassHeaderResolution(), reference, trace, false) + val lazyTypeResolver = object : DelegationResolver.TypeResolver { + override fun resolve(reference: KtTypeReference): KotlinType? = + c.typeResolver.resolveType(thisDescriptor.scopeForClassHeaderResolution, reference, trace, false) } - val lazyMemberExtractor = DelegationResolver.MemberExtractor { - type -> extractor.extract(type, name) + val lazyMemberExtractor = object : DelegationResolver.MemberExtractor { + override fun getMembersByType(type: KotlinType): Collection = + extractor.extract(type, name) } - return generateDelegatedMembers(classOrObject, thisDescriptor, existingDescriptors, trace, lazyMemberExtractor, lazyTypeResolver) + return DelegationResolver.generateDelegatedMembers(classOrObject, thisDescriptor, existingDescriptors, trace, lazyMemberExtractor, lazyTypeResolver) } private fun addDataClassMethods(result: MutableCollection, location: LookupLocation) {