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