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