J2K: DelegationResolver.kt: convert to Kotlin
This commit is contained in:
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-7
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user