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
017 package org.jetbrains.jet.lang.resolve;
018
019 import com.google.common.base.Predicate;
020 import com.google.common.base.Predicates;
021 import com.google.common.collect.Collections2;
022 import com.google.common.collect.Lists;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
027 import org.jetbrains.jet.lang.psi.JetClassOrObject;
028 import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
029 import org.jetbrains.jet.lang.psi.JetDelegatorByExpressionSpecifier;
030 import org.jetbrains.jet.lang.types.JetType;
031 import org.jetbrains.jet.lang.types.TypeUtils;
032
033 import java.util.Collection;
034 import java.util.Collections;
035
036 import static org.jetbrains.jet.lang.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED;
037
038 public 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 }