001 /*
002 * Copyright 2010-2015 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.kotlin.load.java.sam;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.kotlin.descriptors.*;
022 import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
023 import org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition;
024 import org.jetbrains.kotlin.resolve.OverridingUtil;
025 import org.jetbrains.kotlin.types.KotlinType;
026 import org.jetbrains.kotlin.types.TypeSubstitutor;
027 import org.jetbrains.kotlin.types.TypeUtils;
028
029 import java.util.List;
030
031 public class SamAdapterOverridabilityCondition implements ExternalOverridabilityCondition {
032 @NotNull
033 @Override
034 public Result isOverridable(
035 @NotNull CallableDescriptor superDescriptor,
036 @NotNull CallableDescriptor subDescriptor,
037 @Nullable ClassDescriptor subClassDescriptor
038 ) {
039 if (!(subDescriptor instanceof SimpleFunctionDescriptor) || !(superDescriptor instanceof SimpleFunctionDescriptor)) {
040 return Result.UNKNOWN;
041 }
042
043 SimpleFunctionDescriptor superOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) superDescriptor);
044 SimpleFunctionDescriptor subOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) subDescriptor);
045 if (superOriginal == null || subOriginal == null) { // super or sub is/overrides DECLARATION
046 return subOriginal == null ? Result.UNKNOWN : Result.INCOMPATIBLE; // DECLARATION can override anything
047 }
048
049 OverridingUtil.OverrideCompatibilityInfo basicResult = OverridingUtil.DEFAULT
050 .isOverridableByWithoutExternalConditions(superDescriptor, subDescriptor, /* checkReturnType = */ false);
051
052 if (basicResult.getResult() != OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) return Result.UNKNOWN;
053
054 // inheritor if SYNTHESIZED can override inheritor of SYNTHESIZED if their originals have same erasure
055 return equalErasure(superOriginal, subOriginal) ? Result.UNKNOWN : Result.INCOMPATIBLE;
056 }
057
058 private static boolean equalErasure(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) {
059 List<ValueParameterDescriptor> parameters1 = fun1.getValueParameters();
060 List<ValueParameterDescriptor> parameters2 = fun2.getValueParameters();
061
062 for (ValueParameterDescriptor param1 : parameters1) {
063 ValueParameterDescriptor param2 = parameters2.get(param1.getIndex());
064 if (differentClasses(param2.getType(), param1.getType())) {
065 return false;
066 }
067 }
068 return true;
069 }
070
071 private static boolean differentClasses(@NotNull KotlinType type1, @NotNull KotlinType type2) {
072 DeclarationDescriptor declarationDescriptor1 = type1.getConstructor().getDeclarationDescriptor();
073 if (declarationDescriptor1 == null) return true; // No class, classes are not equal
074 DeclarationDescriptor declarationDescriptor2 = type2.getConstructor().getDeclarationDescriptor();
075 if (declarationDescriptor2 == null) return true; // Class of type1 is not null
076
077 if (declarationDescriptor1 instanceof TypeParameterDescriptor && declarationDescriptor2 instanceof TypeParameterDescriptor) {
078 // if type of value parameter is some generic parameter then their equality was checked by OverridingUtil before calling ExternalOverridabilityCondition
079 // Note that it's true unless we generate sam adapter for type parameter with SAM interface as upper bound:
080 // <K extends Runnable >void foo(K runnable) {}
081 return false;
082 }
083
084 return !declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal());
085 }
086
087 // if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters
088 @Nullable
089 private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) {
090 DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration();
091 if (!(containingDeclaration instanceof ClassDescriptor)) {
092 return null;
093 }
094 SamAdapterInfo declarationOrSynthesized =
095 getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType());
096
097 if (declarationOrSynthesized == null) {
098 return null;
099 }
100
101 SimpleFunctionDescriptorImpl fun = (SimpleFunctionDescriptorImpl) declarationOrSynthesized.samAdapter.getOriginal();
102 if (!(fun instanceof SamAdapterFunctionDescriptor)) {
103 return null;
104 }
105
106 SimpleFunctionDescriptor originalDeclarationOfSam = ((SamAdapterFunctionDescriptor) fun).getOriginForSam();
107
108 return ((SimpleFunctionDescriptor) originalDeclarationOfSam.substitute(TypeSubstitutor.create(declarationOrSynthesized.ownerType)));
109 }
110
111 @Nullable
112 private static SamAdapterInfo getNearestDeclarationOrSynthesized(
113 @NotNull SimpleFunctionDescriptor samAdapter,
114 @NotNull KotlinType ownerType
115 ) {
116 if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
117 return new SamAdapterInfo(samAdapter, ownerType);
118 }
119
120 for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) {
121 ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration();
122
123 for (KotlinType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) {
124 if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) {
125 continue;
126 }
127
128 SamAdapterInfo found = getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype);
129 if (found != null) {
130 return found;
131 }
132 }
133 }
134
135 return null;
136 }
137
138 private static class SamAdapterInfo {
139 private final SimpleFunctionDescriptor samAdapter;
140 private final KotlinType ownerType;
141
142 private SamAdapterInfo(@NotNull SimpleFunctionDescriptor samAdapter, @NotNull KotlinType ownerType) {
143 this.samAdapter = samAdapter;
144 this.ownerType = ownerType;
145 }
146 }
147 }