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 }