001 /*
002 * Copyright 2010-2014 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.java.sam;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.descriptors.*;
022 import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
023 import org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition;
024 import org.jetbrains.jet.lang.types.JetType;
025 import org.jetbrains.jet.lang.types.TypeSubstitutor;
026 import org.jetbrains.jet.lang.types.TypeUtils;
027
028 import java.util.List;
029
030 public class SamAdapterOverridabilityCondition implements ExternalOverridabilityCondition {
031 @Override
032 public boolean isOverridable(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
033 if (subDescriptor instanceof PropertyDescriptor) {
034 return true;
035 }
036
037 SimpleFunctionDescriptor superOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) superDescriptor);
038 SimpleFunctionDescriptor subOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) subDescriptor);
039 if (superOriginal == null || subOriginal == null) { // super or sub is/overrides DECLARATION
040 return subOriginal == null; // DECLARATION can override anything
041 }
042
043 // inheritor if SYNTHESIZED can override inheritor of SYNTHESIZED if their originals have same erasure
044 return equalErasure(superOriginal, subOriginal);
045 }
046
047 private static boolean equalErasure(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) {
048 List<ValueParameterDescriptor> parameters1 = fun1.getValueParameters();
049 List<ValueParameterDescriptor> parameters2 = fun2.getValueParameters();
050
051 for (ValueParameterDescriptor param1 : parameters1) {
052 ValueParameterDescriptor param2 = parameters2.get(param1.getIndex());
053 if (!equalClasses(param2.getType(), param1.getType())) {
054 return false;
055 }
056 }
057 return true;
058 }
059
060 private static boolean equalClasses(@NotNull JetType type1, @NotNull JetType type2) {
061 DeclarationDescriptor declarationDescriptor1 = type1.getConstructor().getDeclarationDescriptor();
062 if (declarationDescriptor1 == null) return false; // No class, classes are not equal
063 DeclarationDescriptor declarationDescriptor2 = type2.getConstructor().getDeclarationDescriptor();
064 if (declarationDescriptor2 == null) return false; // Class of type1 is not null
065 return declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal());
066 }
067
068 // if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters
069 @Nullable
070 private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) {
071 DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration();
072 if (!(containingDeclaration instanceof ClassDescriptor)) {
073 return null;
074 }
075 SamAdapterInfo declarationOrSynthesized =
076 getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType());
077
078 if (declarationOrSynthesized == null) {
079 return null;
080 }
081
082 SimpleFunctionDescriptorImpl fun = (SimpleFunctionDescriptorImpl) declarationOrSynthesized.samAdapter.getOriginal();
083 if (!(fun instanceof SamAdapterFunctionDescriptor)) {
084 return null;
085 }
086
087 SimpleFunctionDescriptor originalDeclarationOfSam = ((SamAdapterFunctionDescriptor) fun).getOriginForSam();
088
089 return ((SimpleFunctionDescriptor) originalDeclarationOfSam.substitute(TypeSubstitutor.create(declarationOrSynthesized.ownerType)));
090 }
091
092 @Nullable
093 private static SamAdapterInfo getNearestDeclarationOrSynthesized(
094 @NotNull SimpleFunctionDescriptor samAdapter,
095 @NotNull JetType ownerType
096 ) {
097 if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
098 return new SamAdapterInfo(samAdapter, ownerType);
099 }
100
101 for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) {
102 ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration();
103
104 for (JetType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) {
105 if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) {
106 continue;
107 }
108
109 SamAdapterInfo found = getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype);
110 if (found != null) {
111 return found;
112 }
113 }
114 }
115
116 return null;
117 }
118
119 private static class SamAdapterInfo {
120 private final SimpleFunctionDescriptor samAdapter;
121 private final JetType ownerType;
122
123 private SamAdapterInfo(@NotNull SimpleFunctionDescriptor samAdapter, @NotNull JetType ownerType) {
124 this.samAdapter = samAdapter;
125 this.ownerType = ownerType;
126 }
127 }
128 }