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 @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 KotlinType type1, @NotNull KotlinType 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 KotlinType 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 (KotlinType 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 KotlinType ownerType; 130 131 private SamAdapterInfo(@NotNull SimpleFunctionDescriptor samAdapter, @NotNull KotlinType ownerType) { 132 this.samAdapter = samAdapter; 133 this.ownerType = ownerType; 134 } 135 } 136 }