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:
Pavel V. Talanov
2013-09-30 15:13:18 +04:00
parent 9eeda58747
commit fa8ca4e781
2 changed files with 65 additions and 57 deletions
@@ -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);
}
} }
@@ -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