001 package org.jetbrains.jet.lang.resolve.java.sam;
002
003 import org.jetbrains.annotations.NotNull;
004 import org.jetbrains.annotations.Nullable;
005 import org.jetbrains.jet.lang.descriptors.*;
006 import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
007 import org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition;
008 import org.jetbrains.jet.lang.types.JetType;
009 import org.jetbrains.jet.lang.types.TypeSubstitutor;
010 import org.jetbrains.jet.lang.types.TypeUtils;
011
012 import java.util.List;
013
014 public class SamAdapterOverridabilityCondition implements ExternalOverridabilityCondition {
015 @Override
016 public boolean isOverridable(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
017 if (subDescriptor instanceof PropertyDescriptor) {
018 return true;
019 }
020
021 SimpleFunctionDescriptor superOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) superDescriptor);
022 SimpleFunctionDescriptor subOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) subDescriptor);
023 if (superOriginal == null || subOriginal == null) { // super or sub is/overrides DECLARATION
024 return subOriginal == null; // DECLARATION can override anything
025 }
026
027 // inheritor if SYNTHESIZED can override inheritor of SYNTHESIZED if their originals have same erasure
028 return equalErasure(superOriginal, subOriginal);
029 }
030
031 private static boolean equalErasure(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) {
032 List<ValueParameterDescriptor> parameters1 = fun1.getValueParameters();
033 List<ValueParameterDescriptor> parameters2 = fun2.getValueParameters();
034
035 for (ValueParameterDescriptor param1 : parameters1) {
036 ValueParameterDescriptor param2 = parameters2.get(param1.getIndex());
037 if (!TypeUtils.equalClasses(param2.getType(), param1.getType())) {
038 return false;
039 }
040 }
041 return true;
042 }
043
044 // if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters
045 @Nullable
046 private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) {
047 DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration();
048 if (!(containingDeclaration instanceof ClassDescriptor)) {
049 return null;
050 }
051 SamAdapterInfo declarationOrSynthesized =
052 getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType());
053
054 if (declarationOrSynthesized == null) {
055 return null;
056 }
057
058 SimpleFunctionDescriptorImpl fun = (SimpleFunctionDescriptorImpl) declarationOrSynthesized.samAdapter.getOriginal();
059 if (!(fun instanceof SamAdapterFunctionDescriptor)) {
060 return null;
061 }
062
063 SimpleFunctionDescriptor originalDeclarationOfSam = ((SamAdapterFunctionDescriptor) fun).getBaseForSynthesized();
064
065 return ((SimpleFunctionDescriptor) originalDeclarationOfSam.substitute(TypeSubstitutor.create(declarationOrSynthesized.ownerType)));
066 }
067
068 @Nullable
069 private static SamAdapterInfo getNearestDeclarationOrSynthesized(
070 @NotNull SimpleFunctionDescriptor samAdapter,
071 @NotNull JetType ownerType
072 ) {
073 if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
074 return new SamAdapterInfo(samAdapter, ownerType);
075 }
076
077 for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) {
078 ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration();
079
080 for (JetType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) {
081 if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) {
082 continue;
083 }
084
085 SamAdapterInfo found = getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype);
086 if (found != null) {
087 return found;
088 }
089 }
090 }
091
092 return null;
093 }
094
095 private static class SamAdapterInfo {
096 private final SimpleFunctionDescriptor samAdapter;
097 private final JetType ownerType;
098
099 private SamAdapterInfo(@NotNull SimpleFunctionDescriptor samAdapter, @NotNull JetType ownerType) {
100 this.samAdapter = samAdapter;
101 this.ownerType = ownerType;
102 }
103 }
104 }