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 PropertyDescriptor) { 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 (!equalClasses(param2.getType(), param1.getType())) { 054 return false; 055 } 056 } 057 return true; 058 } 059 060 private static boolean equalClasses(@NotNull JetType type1, @NotNull JetType type2) { 061 DeclarationDescriptor declarationDescriptor1 = type1.getConstructor().getDeclarationDescriptor(); 062 if (declarationDescriptor1 == null) return false; // No class, classes are not equal 063 DeclarationDescriptor declarationDescriptor2 = type2.getConstructor().getDeclarationDescriptor(); 064 if (declarationDescriptor2 == null) return false; // Class of type1 is not null 065 return declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal()); 066 } 067 068 // if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters 069 @Nullable 070 private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) { 071 DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration(); 072 if (!(containingDeclaration instanceof ClassDescriptor)) { 073 return null; 074 } 075 SamAdapterInfo declarationOrSynthesized = 076 getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType()); 077 078 if (declarationOrSynthesized == null) { 079 return null; 080 } 081 082 SimpleFunctionDescriptorImpl fun = (SimpleFunctionDescriptorImpl) declarationOrSynthesized.samAdapter.getOriginal(); 083 if (!(fun instanceof SamAdapterFunctionDescriptor)) { 084 return null; 085 } 086 087 SimpleFunctionDescriptor originalDeclarationOfSam = ((SamAdapterFunctionDescriptor) fun).getOriginForSam(); 088 089 return ((SimpleFunctionDescriptor) originalDeclarationOfSam.substitute(TypeSubstitutor.create(declarationOrSynthesized.ownerType))); 090 } 091 092 @Nullable 093 private static SamAdapterInfo getNearestDeclarationOrSynthesized( 094 @NotNull SimpleFunctionDescriptor samAdapter, 095 @NotNull JetType ownerType 096 ) { 097 if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 098 return new SamAdapterInfo(samAdapter, ownerType); 099 } 100 101 for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) { 102 ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration(); 103 104 for (JetType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) { 105 if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) { 106 continue; 107 } 108 109 SamAdapterInfo found = getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype); 110 if (found != null) { 111 return found; 112 } 113 } 114 } 115 116 return null; 117 } 118 119 private static class SamAdapterInfo { 120 private final SimpleFunctionDescriptor samAdapter; 121 private final JetType ownerType; 122 123 private SamAdapterInfo(@NotNull SimpleFunctionDescriptor samAdapter, @NotNull JetType ownerType) { 124 this.samAdapter = samAdapter; 125 this.ownerType = ownerType; 126 } 127 } 128 }