Refactor: Improve code clarity in DelegationResolver
Filter out non-overridable descriptors earlier for possible optimization Report error to trace even if name identifier is null
This commit is contained in:
@@ -47,13 +47,14 @@ public final class DelegationResolver<T extends CallableMemberDescriptor> {
|
|||||||
@NotNull final BindingTrace trace,
|
@NotNull final BindingTrace trace,
|
||||||
@NotNull JetClassOrObject jetClassOrObject
|
@NotNull JetClassOrObject jetClassOrObject
|
||||||
) {
|
) {
|
||||||
Callback<CallableMemberDescriptor> eagerResolveCallback = new Callback<CallableMemberDescriptor>() {
|
TypeResolver eagerTypeResolver = new TypeResolver() {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public JetType getTypeByTypeReference(@NotNull JetTypeReference reference) {
|
public JetType resolve(@NotNull JetTypeReference reference) {
|
||||||
return trace.get(BindingContext.TYPE, reference);
|
return trace.get(BindingContext.TYPE, reference);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
MemberExtractor<CallableMemberDescriptor> eagerExtractor = new MemberExtractor<CallableMemberDescriptor>() {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<CallableMemberDescriptor> getMembersByType(@NotNull JetType type) {
|
public Collection<CallableMemberDescriptor> getMembersByType(@NotNull JetType type) {
|
||||||
@@ -64,7 +65,7 @@ public final class DelegationResolver<T extends CallableMemberDescriptor> {
|
|||||||
};
|
};
|
||||||
Set<CallableMemberDescriptor> existingMembers = classDescriptor.getAllCallableMembers();
|
Set<CallableMemberDescriptor> existingMembers = classDescriptor.getAllCallableMembers();
|
||||||
Collection<CallableMemberDescriptor> delegatedMembers =
|
Collection<CallableMemberDescriptor> delegatedMembers =
|
||||||
generateDelegatedMembers(jetClassOrObject, classDescriptor, existingMembers, trace, eagerResolveCallback);
|
generateDelegatedMembers(jetClassOrObject, classDescriptor, existingMembers, trace, eagerExtractor, eagerTypeResolver);
|
||||||
for (CallableMemberDescriptor descriptor : delegatedMembers) {
|
for (CallableMemberDescriptor descriptor : delegatedMembers) {
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
@@ -84,30 +85,35 @@ public final class DelegationResolver<T extends CallableMemberDescriptor> {
|
|||||||
@NotNull ClassDescriptor ownerDescriptor,
|
@NotNull ClassDescriptor ownerDescriptor,
|
||||||
@NotNull Collection<? extends CallableDescriptor> existingMembers,
|
@NotNull Collection<? extends CallableDescriptor> existingMembers,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull Callback<T> callback
|
@NotNull MemberExtractor<T> memberExtractor,
|
||||||
|
@NotNull TypeResolver typeResolver
|
||||||
) {
|
) {
|
||||||
return new DelegationResolver<T>(classOrObject, ownerDescriptor, existingMembers, trace, callback).generateDelegatedMembers();
|
return new DelegationResolver<T>(classOrObject, ownerDescriptor, existingMembers, trace, memberExtractor, typeResolver)
|
||||||
|
.generateDelegatedMembers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull private final JetClassOrObject classOrObject;
|
@NotNull private final JetClassOrObject classOrObject;
|
||||||
@NotNull private final ClassDescriptor ownerDescriptor;
|
@NotNull private final ClassDescriptor ownerDescriptor;
|
||||||
@NotNull private final Collection<? extends CallableDescriptor> existingMembers;
|
@NotNull private final Collection<? extends CallableDescriptor> existingMembers;
|
||||||
@NotNull private final BindingTrace trace;
|
@NotNull private final BindingTrace trace;
|
||||||
|
@NotNull private final MemberExtractor<T> memberExtractor;
|
||||||
@NotNull private final Callback<T> callback;
|
@NotNull private final TypeResolver typeResolver;
|
||||||
|
|
||||||
private DelegationResolver(
|
private DelegationResolver(
|
||||||
@NotNull JetClassOrObject classOrObject,
|
@NotNull JetClassOrObject classOrObject,
|
||||||
@NotNull ClassDescriptor ownerDescriptor,
|
@NotNull ClassDescriptor ownerDescriptor,
|
||||||
@NotNull Collection<? extends CallableDescriptor> existingMembers,
|
@NotNull Collection<? extends CallableDescriptor> existingMembers,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull Callback<T> callback
|
@NotNull MemberExtractor<T> extractor,
|
||||||
|
@NotNull TypeResolver resolver
|
||||||
) {
|
) {
|
||||||
|
|
||||||
this.classOrObject = classOrObject;
|
this.classOrObject = classOrObject;
|
||||||
this.ownerDescriptor = ownerDescriptor;
|
this.ownerDescriptor = ownerDescriptor;
|
||||||
this.existingMembers = existingMembers;
|
this.existingMembers = existingMembers;
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
this.callback = callback;
|
this.memberExtractor = extractor;
|
||||||
|
this.typeResolver = resolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -122,18 +128,18 @@ public final class DelegationResolver<T extends CallableMemberDescriptor> {
|
|||||||
if (typeReference == null) {
|
if (typeReference == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
JetType delegatedTraitType = callback.getTypeByTypeReference(typeReference);
|
JetType delegatedTraitType = typeResolver.resolve(typeReference);
|
||||||
if (delegatedTraitType == null) {
|
if (delegatedTraitType == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Collection<T> delegatesForTrait = generateDelegatesForOneTrait(delegatedMembers, delegatedTraitType);
|
Collection<T> delegatesForTrait = generateDelegatesForTrait(delegatedMembers, delegatedTraitType);
|
||||||
delegatedMembers.addAll(delegatesForTrait);
|
delegatedMembers.addAll(delegatesForTrait);
|
||||||
}
|
}
|
||||||
return delegatedMembers;
|
return delegatedMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Collection<T> generateDelegatesForOneTrait(
|
private Collection<T> generateDelegatesForTrait(
|
||||||
@NotNull Collection<T> existingDelegates,
|
@NotNull Collection<T> existingDelegates,
|
||||||
@NotNull JetType delegatedTraitType
|
@NotNull JetType delegatedTraitType
|
||||||
) {
|
) {
|
||||||
@@ -153,21 +159,18 @@ public final class DelegationResolver<T extends CallableMemberDescriptor> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkClashWithOtherDelegatedMember(
|
@NotNull
|
||||||
@NotNull Collection<T> delegatedMembers,
|
private Collection<T> generateDelegationCandidates(@NotNull JetType delegatedTraitType) {
|
||||||
@NotNull T candidate
|
Collection<T> descriptorsToDelegate = overridableMembersNotFromSuperClassOfTrait(delegatedTraitType);
|
||||||
) {
|
Collection<T> result = Lists.newArrayList();
|
||||||
for (CallableMemberDescriptor alreadyDelegatedMember : delegatedMembers) {
|
for (T memberDescriptor : descriptorsToDelegate) {
|
||||||
if (haveSameSignatures(alreadyDelegatedMember, candidate)) {
|
Modality modality = DescriptorUtils.convertModality(memberDescriptor.getModality(), true);
|
||||||
//trying to delegate to many traits with the same methods
|
@SuppressWarnings("unchecked")
|
||||||
PsiElement nameIdentifier = classOrObject.getNameIdentifier();
|
T copy = (T) memberDescriptor.copy(ownerDescriptor, modality, memberDescriptor.getVisibility(),
|
||||||
if (nameIdentifier != null) {
|
CallableMemberDescriptor.Kind.DELEGATION, false);
|
||||||
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, classOrObject, alreadyDelegatedMember));
|
result.add(copy);
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean existingMemberOverridesDelegatedMember(
|
private static boolean existingMemberOverridesDelegatedMember(
|
||||||
@@ -182,32 +185,33 @@ public final class DelegationResolver<T extends CallableMemberDescriptor> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private boolean checkClashWithOtherDelegatedMember(
|
||||||
private Collection<T> generateDelegationCandidates(@NotNull JetType delegatedTraitType) {
|
@NotNull Collection<T> delegatedMembers,
|
||||||
Collection<T> descriptorsToDelegate = filterMembersFromSuperClassOfDelegatedTrait(delegatedTraitType);
|
@NotNull T candidate
|
||||||
Collection<T> result = Lists.newArrayList();
|
) {
|
||||||
for (T memberDescriptor : descriptorsToDelegate) {
|
for (CallableMemberDescriptor alreadyDelegatedMember : delegatedMembers) {
|
||||||
if (memberDescriptor.getModality().isOverridable()) {
|
if (haveSameSignatures(alreadyDelegatedMember, candidate)) {
|
||||||
Modality modality = DescriptorUtils.convertModality(memberDescriptor.getModality(), true);
|
//trying to delegate to many traits with the same methods
|
||||||
@SuppressWarnings("unchecked")
|
PsiElement nameIdentifier = classOrObject.getNameIdentifier();
|
||||||
T copy = (T) memberDescriptor.copy(ownerDescriptor, modality, memberDescriptor.getVisibility(),
|
PsiElement element = nameIdentifier != null ? nameIdentifier : classOrObject;
|
||||||
CallableMemberDescriptor.Kind.DELEGATION, false);
|
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(element, classOrObject, alreadyDelegatedMember));
|
||||||
result.add(copy);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Collection<T> filterMembersFromSuperClassOfDelegatedTrait(
|
private Collection<T> overridableMembersNotFromSuperClassOfTrait(@NotNull JetType trait) {
|
||||||
@NotNull JetType delegatedTraitType
|
final Collection<T> membersToSkip = getMembersFromClassSupertypeOfTrait(trait);
|
||||||
) {
|
|
||||||
final Collection<T> membersToSkip = getMembersFromClassSupertypeOfTrait(delegatedTraitType);
|
|
||||||
return Collections2.filter(
|
return Collections2.filter(
|
||||||
callback.getMembersByType(delegatedTraitType),
|
memberExtractor.getMembersByType(trait),
|
||||||
new Predicate<CallableMemberDescriptor>() {
|
new Predicate<CallableMemberDescriptor>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(@Nullable CallableMemberDescriptor descriptor) {
|
public boolean apply(CallableMemberDescriptor descriptor) {
|
||||||
|
if (!descriptor.getModality().isOverridable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
for (CallableMemberDescriptor memberToSkip : membersToSkip) {
|
for (CallableMemberDescriptor memberToSkip : membersToSkip) {
|
||||||
if (haveSameSignatures(memberToSkip, descriptor)) {
|
if (haveSameSignatures(memberToSkip, descriptor)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -224,18 +228,18 @@ public final class DelegationResolver<T extends CallableMemberDescriptor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Collection<T> getMembersFromClassSupertypeOfTrait(@NotNull JetType delegateTraitType) {
|
private Collection<T> getMembersFromClassSupertypeOfTrait(@NotNull JetType traitType) {
|
||||||
JetType classSupertype = null;
|
JetType classSupertype = null;
|
||||||
for (JetType supertype : TypeUtils.getAllSupertypes(delegateTraitType)) {
|
for (JetType supertype : TypeUtils.getAllSupertypes(traitType)) {
|
||||||
if (isNotTrait(supertype.getConstructor().getDeclarationDescriptor())) {
|
if (isNotTrait(supertype.getConstructor().getDeclarationDescriptor())) {
|
||||||
classSupertype = supertype;
|
classSupertype = supertype;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return classSupertype != null ? callback.getMembersByType(classSupertype) : Collections.<T>emptyList();
|
return classSupertype != null ? memberExtractor.getMembersByType(classSupertype) : Collections.<T>emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isNotTrait(@NotNull DeclarationDescriptor descriptor) {
|
private static boolean isNotTrait(@Nullable DeclarationDescriptor descriptor) {
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
ClassKind kind = ((ClassDescriptor) descriptor).getKind();
|
ClassKind kind = ((ClassDescriptor) descriptor).getKind();
|
||||||
return kind != ClassKind.TRAIT;
|
return kind != ClassKind.TRAIT;
|
||||||
@@ -243,11 +247,13 @@ public final class DelegationResolver<T extends CallableMemberDescriptor> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Callback<T extends CallableMemberDescriptor> {
|
public interface MemberExtractor<T extends CallableMemberDescriptor> {
|
||||||
@Nullable
|
|
||||||
JetType getTypeByTypeReference(@NotNull JetTypeReference reference);
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
Collection<T> getMembersByType(@NotNull JetType type);
|
Collection<T> getMembersByType(@NotNull JetType type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface TypeResolver {
|
||||||
|
@Nullable
|
||||||
|
JetType resolve(@NotNull JetTypeReference reference);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+6
-4
@@ -266,17 +266,18 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
|
|||||||
if (thisDescriptor.getKind() == ClassKind.CLASS_OBJECT) {
|
if (thisDescriptor.getKind() == ClassKind.CLASS_OBJECT) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
DelegationResolver.Callback<T> lazyResolveCallback = new DelegationResolver.Callback<T>() {
|
DelegationResolver.TypeResolver lazyTypeResolver = new DelegationResolver.TypeResolver() {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public JetType getTypeByTypeReference(@NotNull JetTypeReference reference) {
|
public JetType resolve(@NotNull JetTypeReference reference) {
|
||||||
return resolveSession.getInjector().getTypeResolver().resolveType(
|
return resolveSession.getInjector().getTypeResolver().resolveType(
|
||||||
thisDescriptor.getScopeForClassHeaderResolution(),
|
thisDescriptor.getScopeForClassHeaderResolution(),
|
||||||
reference,
|
reference,
|
||||||
resolveSession.getTrace(),
|
resolveSession.getTrace(),
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
DelegationResolver.MemberExtractor<T> lazyMemberExtractor = new DelegationResolver.MemberExtractor<T>() {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<T> getMembersByType(@NotNull JetType type) {
|
public Collection<T> getMembersByType(@NotNull JetType type) {
|
||||||
@@ -285,7 +286,8 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
|
|||||||
};
|
};
|
||||||
JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
|
JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
|
||||||
assert classOrObject != null : "Should not be null for non class object class.";
|
assert classOrObject != null : "Should not be null for non class object class.";
|
||||||
return generateDelegatedMembers(classOrObject, thisDescriptor, existingDescriptors, resolveSession.getTrace(), lazyResolveCallback);
|
return generateDelegatedMembers(classOrObject, thisDescriptor, existingDescriptors, resolveSession.getTrace(), lazyMemberExtractor,
|
||||||
|
lazyTypeResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user