J2K: DelegationResolver.kt: convert to Kotlin

This commit is contained in:
Dmitry Petrov
2015-12-01 14:46:49 +03:00
parent 8f5df45edc
commit 6e2d42daf9
2 changed files with 87 additions and 177 deletions
@@ -14,200 +14,108 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.resolve; package org.jetbrains.kotlin.resolve
import com.google.common.base.Predicate; import org.jetbrains.kotlin.descriptors.*
import com.google.common.collect.Collections2; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.psi.KtDelegatorByExpressionSpecifier
import org.jetbrains.kotlin.psi.KtClassOrObject; import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.psi.KtDelegationSpecifier; import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
import org.jetbrains.kotlin.psi.KtDelegatorByExpressionSpecifier; import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.psi.KtTypeReference; import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import java.util.ArrayList; class DelegationResolver<T : CallableMemberDescriptor> private constructor(
import java.util.Collection; private val classOrObject: KtClassOrObject,
import java.util.Collections; private val ownerDescriptor: ClassDescriptor,
import java.util.HashSet; private val existingMembers: Collection<CallableDescriptor>,
private val trace: BindingTrace,
private val memberExtractor: DelegationResolver.MemberExtractor<T>,
private val typeResolver: DelegationResolver.TypeResolver
) {
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION; private fun generateDelegatedMembers(): Collection<T> {
import static org.jetbrains.kotlin.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED; val delegatedMembers = hashSetOf<T>()
import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; for (delegationSpecifier in classOrObject.getDelegationSpecifiers()) {
if (delegationSpecifier !is KtDelegatorByExpressionSpecifier) {
public final class DelegationResolver<T extends CallableMemberDescriptor> { continue
@NotNull
public static <T extends CallableMemberDescriptor> Collection<T> generateDelegatedMembers(
@NotNull KtClassOrObject classOrObject,
@NotNull ClassDescriptor ownerDescriptor,
@NotNull Collection<? extends CallableDescriptor> existingMembers,
@NotNull BindingTrace trace,
@NotNull MemberExtractor<T> memberExtractor,
@NotNull TypeResolver typeResolver
) {
return new DelegationResolver<T>(classOrObject, ownerDescriptor, existingMembers, trace, memberExtractor, typeResolver)
.generateDelegatedMembers();
}
@NotNull private final KtClassOrObject classOrObject;
@NotNull private final ClassDescriptor ownerDescriptor;
@NotNull private final Collection<? extends CallableDescriptor> existingMembers;
@NotNull private final BindingTrace trace;
@NotNull private final MemberExtractor<T> memberExtractor;
@NotNull private final TypeResolver typeResolver;
private DelegationResolver(
@NotNull KtClassOrObject classOrObject,
@NotNull ClassDescriptor ownerDescriptor,
@NotNull Collection<? extends CallableDescriptor> existingMembers,
@NotNull BindingTrace trace,
@NotNull MemberExtractor<T> 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<T> generateDelegatedMembers() {
Collection<T> delegatedMembers = new HashSet<T>();
for (KtDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) {
if (!(delegationSpecifier instanceof KtDelegatorByExpressionSpecifier)) {
continue;
} }
KtDelegatorByExpressionSpecifier specifier = (KtDelegatorByExpressionSpecifier) delegationSpecifier; val typeReference = delegationSpecifier.typeReference ?: continue
KtTypeReference typeReference = specifier.getTypeReference(); val delegatedInterfaceType = typeResolver.resolve(typeReference)
if (typeReference == null) { if (delegatedInterfaceType == null || delegatedInterfaceType.isError) {
continue; continue
} }
KotlinType delegatedTraitType = typeResolver.resolve(typeReference); val delegatesForInterface = generateDelegatesForInterface(delegatedMembers, delegatedInterfaceType)
if (delegatedTraitType == null || delegatedTraitType.isError()) { delegatedMembers.addAll(delegatesForInterface)
continue;
}
Collection<T> delegatesForTrait = generateDelegatesForTrait(delegatedMembers, delegatedTraitType);
delegatedMembers.addAll(delegatesForTrait);
} }
return delegatedMembers; return delegatedMembers
} }
@NotNull private fun generateDelegatesForInterface(existingDelegates: Collection<T>, delegatedInterfaceType: KotlinType): Collection<T> =
private Collection<T> generateDelegatesForTrait( generateDelegationCandidates(delegatedInterfaceType).filter { candidate ->
@NotNull Collection<T> existingDelegates, !isOverridingAnyOf(candidate, existingMembers) &&
@NotNull KotlinType delegatedTraitType !checkClashWithOtherDelegatedMember(candidate, existingDelegates)
) {
Collection<T> result = new HashSet<T>();
Collection<T> candidates = generateDelegationCandidates(delegatedTraitType);
for (T candidate : candidates) {
if (existingMemberOverridesDelegatedMember(candidate, existingMembers)) {
continue;
}
//only leave the first delegated member
if (checkClashWithOtherDelegatedMember(existingDelegates, candidate)) {
continue;
} }
result.add(candidate); private fun generateDelegationCandidates(delegatedInterfaceType: KotlinType): Collection<T> =
} getDelegatableMembers(delegatedInterfaceType).map { memberDescriptor ->
return result; 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)
@NotNull
private Collection<T> generateDelegationCandidates(@NotNull KotlinType delegatedTraitType) {
Collection<T> descriptorsToDelegate = overridableMembersNotFromSuperClassOfTrait(delegatedTraitType);
Collection<T> result = new ArrayList<T>(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<? extends CallableDescriptor> existingMembers
) {
for (CallableDescriptor existingDescriptor : existingMembers) {
if (haveSameSignatures(existingDescriptor, candidate)) {
return true;
} }
private fun checkClashWithOtherDelegatedMember(candidate: T, delegatedMembers: Collection<T>): 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; return false;
} }
private boolean checkClashWithOtherDelegatedMember(@NotNull Collection<T> delegatedMembers, @NotNull T candidate) {
for (CallableMemberDescriptor alreadyDelegatedMember : delegatedMembers) { private fun getDelegatableMembers(interfaceType: KotlinType): Collection<T> {
if (haveSameSignatures(alreadyDelegatedMember, candidate)) { val classSupertypeMembers =
//trying to delegate to many traits with the same methods TypeUtils.getAllSupertypes(interfaceType).firstOrNull {
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(classOrObject, classOrObject, alreadyDelegatedMember)); val typeConstructor = it.constructor.declarationDescriptor
return true; typeConstructor is ClassDescriptor && typeConstructor.kind != ClassKind.INTERFACE
} }?.let {
memberExtractor.getMembersByType(it)
} ?: emptyList<CallableMemberDescriptor>()
return memberExtractor.getMembersByType(interfaceType).filter { descriptor ->
descriptor.modality.isOverridable && !classSupertypeMembers.any { isOverridableBy(it, descriptor) }
} }
return false;
} }
@NotNull interface MemberExtractor<T : CallableMemberDescriptor> {
private Collection<T> overridableMembersNotFromSuperClassOfTrait(@NotNull KotlinType trait) { fun getMembersByType(type: KotlinType): Collection<T>
final Collection<T> membersToSkip = getMembersFromClassSupertypeOfTrait(trait);
return Collections2.filter(
memberExtractor.getMembersByType(trait),
new Predicate<CallableMemberDescriptor>() {
@Override
public boolean apply(CallableMemberDescriptor descriptor) {
if (!descriptor.getModality().isOverridable()) {
return false;
}
for (CallableMemberDescriptor memberToSkip : membersToSkip) {
if (haveSameSignatures(memberToSkip, descriptor)) {
return false;
}
}
return true;
}
});
} }
private static boolean haveSameSignatures(@NotNull CallableDescriptor memberOne, @NotNull CallableDescriptor memberTwo) { interface TypeResolver {
//isOverridableBy ignores return types fun resolve(reference: KtTypeReference): KotlinType?
return OverridingUtil.DEFAULT.isOverridableBy(memberOne, memberTwo).getResult() == OVERRIDABLE;
} }
@NotNull companion object {
private Collection<T> getMembersFromClassSupertypeOfTrait(@NotNull KotlinType traitType) { fun <T : CallableMemberDescriptor> generateDelegatedMembers(
KotlinType classSupertype = null; classOrObject: KtClassOrObject,
for (KotlinType supertype : TypeUtils.getAllSupertypes(traitType)) { ownerDescriptor: ClassDescriptor,
if (isNotTrait(supertype.getConstructor().getDeclarationDescriptor())) { existingMembers: Collection<CallableDescriptor>,
classSupertype = supertype; trace: BindingTrace,
break; memberExtractor: MemberExtractor<T>,
} typeResolver: TypeResolver
} ): Collection<T> =
return classSupertype != null ? memberExtractor.getMembersByType(classSupertype) : Collections.<T>emptyList(); DelegationResolver(classOrObject, ownerDescriptor, existingMembers, trace, memberExtractor, typeResolver)
} .generateDelegatedMembers()
private static boolean isNotTrait(@Nullable DeclarationDescriptor descriptor) { private fun isOverridingAnyOf(
if (descriptor instanceof ClassDescriptor) { candidate: CallableMemberDescriptor,
ClassKind kind = ((ClassDescriptor) descriptor).getKind(); possiblyOverriddenBy: Collection<CallableDescriptor>
return kind != ClassKind.INTERFACE; ): Boolean =
} possiblyOverriddenBy.any { isOverridableBy(it, candidate) }
return false;
}
public interface MemberExtractor<T extends CallableMemberDescriptor> { private fun isOverridableBy(memberOne: CallableDescriptor, memberTwo: CallableDescriptor): Boolean =
@NotNull OverridingUtil.DEFAULT.isOverridableBy(memberOne, memberTwo).result == OVERRIDABLE
Collection<T> getMembersByType(@NotNull KotlinType type);
}
public interface TypeResolver {
@Nullable
KotlinType resolve(@NotNull KtTypeReference reference);
} }
} }
@@ -27,15 +27,15 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.* 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.createComponentName
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter 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.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker
import org.jetbrains.kotlin.storage.NotNullLazyValue import org.jetbrains.kotlin.storage.NotNullLazyValue
import org.jetbrains.kotlin.storage.NullableLazyValue import org.jetbrains.kotlin.storage.NullableLazyValue
@@ -231,13 +231,15 @@ public open class LazyClassMemberScope(
val classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject() val classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject()
?: return setOf() ?: return setOf()
val lazyTypeResolver = DelegationResolver.TypeResolver { reference -> val lazyTypeResolver = object : DelegationResolver.TypeResolver {
c.typeResolver.resolveType(thisDescriptor.getScopeForClassHeaderResolution(), reference, trace, false) override fun resolve(reference: KtTypeReference): KotlinType? =
c.typeResolver.resolveType(thisDescriptor.scopeForClassHeaderResolution, reference, trace, false)
} }
val lazyMemberExtractor = DelegationResolver.MemberExtractor<T> { val lazyMemberExtractor = object : DelegationResolver.MemberExtractor<T> {
type -> extractor.extract(type, name) override fun getMembersByType(type: KotlinType): Collection<T> =
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<DeclarationDescriptor>, location: LookupLocation) { private fun addDataClassMethods(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {