001/* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.jetbrains.jet.lang.resolve; 018 019import com.google.common.base.Predicate; 020import com.google.common.base.Predicates; 021import com.google.common.collect.Collections2; 022import com.google.common.collect.Lists; 023import org.jetbrains.annotations.NotNull; 024import org.jetbrains.annotations.Nullable; 025import org.jetbrains.jet.lang.descriptors.*; 026import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; 027import org.jetbrains.jet.lang.psi.JetClassOrObject; 028import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; 029import org.jetbrains.jet.lang.psi.JetDelegatorByExpressionSpecifier; 030import org.jetbrains.jet.lang.types.JetType; 031import org.jetbrains.jet.lang.types.TypeUtils; 032 033import java.util.Collection; 034import java.util.Collections; 035 036import static org.jetbrains.jet.lang.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED; 037 038public class DelegationResolver { 039 040 private DelegationResolver() {} 041 042 public static void addDelegatedMembers(@NotNull BindingTrace trace, @NotNull JetClassOrObject jetClass, @NotNull MutableClassDescriptor classDescriptor) { 043 for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) { 044 if (delegationSpecifier instanceof JetDelegatorByExpressionSpecifier) { 045 JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier; 046 JetType type = trace.get(BindingContext.TYPE, specifier.getTypeReference()); 047 if (type != null) { 048 final Collection<CallableMemberDescriptor> membersToSkip = getMembersFromClassSupertype(type); 049 Collection<CallableMemberDescriptor> descriptorsToDelegate = Collections2.filter(extractCallableMembers(type), 050 new Predicate<CallableMemberDescriptor>() { 051 @Override 052 public boolean apply(@Nullable CallableMemberDescriptor descriptor) { 053 for (CallableMemberDescriptor memberToSkip : membersToSkip) { 054 if (haveSameSignatures(memberToSkip, descriptor)) { 055 return false; 056 } 057 } 058 return true; 059 } 060 }); 061 062 Collection<CallableMemberDescriptor> generatedDescriptors = generateDelegatedMembers(classDescriptor, descriptorsToDelegate); 063 outer: 064 for (CallableMemberDescriptor descriptor : generatedDescriptors) { 065 for (CallableMemberDescriptor existingDescriptor : classDescriptor.getAllCallableMembers()) { 066 if (OverridingUtil.isOverridableBy(existingDescriptor, descriptor).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) { 067 if (existingDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) { 068 //trying to delegate to many traits with the same methods 069 trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(jetClass.getNameIdentifier(), jetClass, existingDescriptor)); 070 } 071 continue outer; 072 } 073 } 074 075 if (descriptor instanceof PropertyDescriptor) { 076 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 077 classDescriptor.getBuilder().addPropertyDescriptor(propertyDescriptor); 078 } 079 else if (descriptor instanceof SimpleFunctionDescriptor) { 080 SimpleFunctionDescriptor functionDescriptor = (SimpleFunctionDescriptor) descriptor; 081 classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor); 082 } 083 } 084 } 085 } 086 } 087 } 088 089 private static boolean haveSameSignatures(CallableDescriptor memberOne, CallableDescriptor memberTwo) { 090 return OverridingUtil.isOverridableBy(memberOne, memberTwo).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; 091 } 092 093 private static Collection<CallableMemberDescriptor> getMembersFromClassSupertype(JetType type) { 094 JetType classSupertype = null; 095 for (JetType supertype : TypeUtils.getAllSupertypes(type)) { 096 if (isNotTrait(supertype.getConstructor().getDeclarationDescriptor())) { 097 classSupertype = supertype; 098 break; 099 } 100 } 101 102 return classSupertype != null ? extractCallableMembers(classSupertype) : Collections.<CallableMemberDescriptor>emptyList(); 103 } 104 105 @SuppressWarnings("unchecked") 106 private static Collection<CallableMemberDescriptor> extractCallableMembers(JetType type) { 107 return (Collection) Collections2.filter(type.getMemberScope().getAllDescriptors(), 108 Predicates.instanceOf(CallableMemberDescriptor.class)); 109 } 110 111 private static boolean isNotTrait(DeclarationDescriptor descriptor) { 112 if (descriptor instanceof ClassDescriptor) { 113 ClassKind kind = ((ClassDescriptor) descriptor).getKind(); 114 return kind != ClassKind.TRAIT; 115 } 116 return false; 117 } 118 119 public static <T extends CallableMemberDescriptor> Collection<T> generateDelegatedMembers(DeclarationDescriptor newOwner, Collection<T> delegatedDescriptors) { 120 Collection<CallableMemberDescriptor> result = Lists.newArrayList(); 121 for (CallableMemberDescriptor memberDescriptor : delegatedDescriptors) { 122 if (memberDescriptor.getModality().isOverridable()) { 123 Modality modality = DescriptorUtils.convertModality(memberDescriptor.getModality(), true); 124 CallableMemberDescriptor copy = 125 memberDescriptor.copy(newOwner, modality, memberDescriptor.getVisibility(), CallableMemberDescriptor.Kind.DELEGATION, false); 126 result.add(copy); 127 } 128 } 129 //noinspection unchecked 130 return (Collection) result; 131 } 132}