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.JetType;
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 @Override
032 public boolean isOverridable(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
033 if (!(subDescriptor instanceof SimpleFunctionDescriptor)) {
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 (differentClasses(param2.getType(), param1.getType())) {
054 return false;
055 }
056 }
057 return true;
058 }
059
060 private static boolean differentClasses(@NotNull JetType type1, @NotNull JetType type2) {
061 DeclarationDescriptor declarationDescriptor1 = type1.getConstructor().getDeclarationDescriptor();
062 if (declarationDescriptor1 == null) return true; // No class, classes are not equal
063 DeclarationDescriptor declarationDescriptor2 = type2.getConstructor().getDeclarationDescriptor();
064 if (declarationDescriptor2 == null) return true; // Class of type1 is not null
065
066 if (declarationDescriptor1 instanceof TypeParameterDescriptor && declarationDescriptor2 instanceof TypeParameterDescriptor) {
067 // if type of value parameter is some generic parameter then their equality was checked by OverridingUtil before calling ExternalOverridabilityCondition
068 // Note that it's true unless we generate sam adapter for type parameter with SAM interface as upper bound:
069 // <K extends Runnable >void foo(K runnable) {}
070 return false;
071 }
072
073 return !declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal());
074 }
075
076 // if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters
077 @Nullable
078 private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) {
079 DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration();
080 if (!(containingDeclaration instanceof ClassDescriptor)) {
081 return null;
082 }
083 SamAdapterInfo declarationOrSynthesized =
084 getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType());
085
086 if (declarationOrSynthesized == null) {
087 return null;
088 }
089
090 SimpleFunctionDescriptorImpl fun = (SimpleFunctionDescriptorImpl) declarationOrSynthesized.samAdapter.getOriginal();
091 if (!(fun instanceof SamAdapterFunctionDescriptor)) {
092 return null;
093 }
094
095 SimpleFunctionDescriptor originalDeclarationOfSam = ((SamAdapterFunctionDescriptor) fun).getOriginForSam();
096
097 return ((SimpleFunctionDescriptor) originalDeclarationOfSam.substitute(TypeSubstitutor.create(declarationOrSynthesized.ownerType)));
098 }
099
100 @Nullable
101 private static SamAdapterInfo getNearestDeclarationOrSynthesized(
102 @NotNull SimpleFunctionDescriptor samAdapter,
103 @NotNull JetType ownerType
104 ) {
105 if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
106 return new SamAdapterInfo(samAdapter, ownerType);
107 }
108
109 for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) {
110 ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration();
111
112 for (JetType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) {
113 if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) {
114 continue;
115 }
116
117 SamAdapterInfo found = getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype);
118 if (found != null) {
119 return found;
120 }
121 }
122 }
123
124 return null;
125 }
126
127 private static class SamAdapterInfo {
128 private final SimpleFunctionDescriptor samAdapter;
129 private final JetType ownerType;
130
131 private SamAdapterInfo(@NotNull SimpleFunctionDescriptor samAdapter, @NotNull JetType ownerType) {
132 this.samAdapter = samAdapter;
133 this.ownerType = ownerType;
134 }
135 }
136 }