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 }