From 822c42603ff311abda0fcb842f3c2eab0f9a1780 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Wed, 10 Jul 2013 18:06:59 +0400 Subject: [PATCH] Created extension point for overridability checks. --- ...ng.resolve.ExternalOverridabilityCondition | 1 + .../SamAdapterOverridabilityCondition.java | 100 ++++++++++++++++++ .../ExternalOverridabilityCondition.java | 8 ++ .../jet/lang/resolve/OverridingUtil.java | 94 ++-------------- 4 files changed, 116 insertions(+), 87 deletions(-) create mode 100644 compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SamAdapterOverridabilityCondition.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/ExternalOverridabilityCondition.java diff --git a/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition b/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition new file mode 100644 index 00000000000..6953a3b18db --- /dev/null +++ b/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition @@ -0,0 +1 @@ +org.jetbrains.jet.lang.resolve.java.sam.SamAdapterOverridabilityCondition diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SamAdapterOverridabilityCondition.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SamAdapterOverridabilityCondition.java new file mode 100644 index 00000000000..c86cbbd7746 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SamAdapterOverridabilityCondition.java @@ -0,0 +1,100 @@ +package org.jetbrains.jet.lang.resolve.java.sam; + +import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; +import org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeSubstitutor; +import org.jetbrains.jet.lang.types.TypeUtils; + +import java.util.List; + +public class SamAdapterOverridabilityCondition implements ExternalOverridabilityCondition { + @Override + public boolean isOverridable(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { + if (subDescriptor instanceof PropertyDescriptor) { + return true; + } + + SimpleFunctionDescriptor superOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) superDescriptor); + SimpleFunctionDescriptor subOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) subDescriptor); + if (superOriginal == null || subOriginal == null) { // super or sub is/overrides DECLARATION + return subOriginal == null; // DECLARATION can override anything + } + + // inheritor if SYNTHESIZED can override inheritor of SYNTHESIZED if their originals have same erasure + return equalErasure(superOriginal, subOriginal); + } + + private static boolean equalErasure(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) { + List parameters1 = fun1.getValueParameters(); + List parameters2 = fun2.getValueParameters(); + + for (ValueParameterDescriptor param1 : parameters1) { + ValueParameterDescriptor param2 = parameters2.get(param1.getIndex()); + if (!TypeUtils.equalClasses(param2.getType(), param1.getType())) { + return false; + } + } + return true; + } + + // if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters + @Nullable + private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) { + DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration(); + if (!(containingDeclaration instanceof ClassDescriptor)) { + return null; + } + Pair declarationOrSynthesized = + getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType()); + + if (declarationOrSynthesized == null) { + return null; + } + + SimpleFunctionDescriptor fun = declarationOrSynthesized.first; + if (fun.getKind() != CallableMemberDescriptor.Kind.SYNTHESIZED) { + return null; + } + + SimpleFunctionDescriptor originalOfSynthesized = ((SimpleFunctionDescriptorImpl) fun.getOriginal()) + .getOriginalOfSynthesized(); + if (originalOfSynthesized == null) { + return null; + } + + return ((SimpleFunctionDescriptor) originalOfSynthesized.substitute(TypeSubstitutor.create(declarationOrSynthesized.second))); + } + + @Nullable + private static Pair getNearestDeclarationOrSynthesized( + @NotNull SimpleFunctionDescriptor samAdapter, + @NotNull JetType ownerType + ) { + if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + return Pair.create(samAdapter, ownerType); + } + for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) { + ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration(); + + for (JetType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) { + if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) { + continue; + } + + Pair found = + getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype); + if (found != null) { + return found; + } + } + + } + return null; + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ExternalOverridabilityCondition.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ExternalOverridabilityCondition.java new file mode 100644 index 00000000000..17dd911ba1b --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ExternalOverridabilityCondition.java @@ -0,0 +1,8 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; + +public interface ExternalOverridabilityCondition { + boolean isOverridable(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index d353d1f1ecf..de97895f30b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -185,8 +185,11 @@ public class OverridingUtil { } } - if (!isOverridableSynthesized(superDescriptor, subDescriptor)) { - return OverrideCompatibilityInfo.synthesizedAndDeclarationIncompatible(); + for (ExternalOverridabilityCondition externalCondition : ServiceLoader + .load(ExternalOverridabilityCondition.class)) { + if (!externalCondition.isOverridable(superDescriptor, subDescriptor)) { + return OverrideCompatibilityInfo.externalConditionFailed(externalCondition.getClass()); + } } } else { @@ -301,89 +304,6 @@ public class OverridingUtil { } } - private static boolean isOverridableSynthesized(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { - if (subDescriptor instanceof PropertyDescriptor) { - return true; - } - - SimpleFunctionDescriptor superOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) superDescriptor); - SimpleFunctionDescriptor subOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) subDescriptor); - if (superOriginal == null || subOriginal == null) { // super or sub is/overrides DECLARATION - return subOriginal == null; // DECLARATION can override anything - } - - // inheritor if SYNTHESIZED can override inheritor of SYNTHESIZED if their originals have same erasure - return equalErasure(superOriginal, subOriginal); - } - - private static boolean equalErasure(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) { - List parameters1 = fun1.getValueParameters(); - List parameters2 = fun2.getValueParameters(); - - for (ValueParameterDescriptor param1 : parameters1) { - ValueParameterDescriptor param2 = parameters2.get(param1.getIndex()); - if (!TypeUtils.equalClasses(param2.getType(), param1.getType())) { - return false; - } - } - return true; - } - - // if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters - @Nullable - private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) { - DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration(); - if (!(containingDeclaration instanceof ClassDescriptor)) { - return null; - } - Pair declarationOrSynthesized = - getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType()); - - if (declarationOrSynthesized == null) { - return null; - } - - SimpleFunctionDescriptor fun = declarationOrSynthesized.first; - if (fun.getKind() != CallableMemberDescriptor.Kind.SYNTHESIZED) { - return null; - } - - SimpleFunctionDescriptor originalOfSynthesized = ((SimpleFunctionDescriptorImpl) fun.getOriginal()) - .getOriginalOfSynthesized(); - if (originalOfSynthesized == null) { - return null; - } - - return ((SimpleFunctionDescriptor) originalOfSynthesized.substitute(TypeSubstitutor.create(declarationOrSynthesized.second))); - } - - @Nullable - private static Pair getNearestDeclarationOrSynthesized( - @NotNull SimpleFunctionDescriptor samAdapter, - @NotNull JetType ownerType - ) { - if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { - return Pair.create(samAdapter, ownerType); - } - for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) { - ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration(); - - for (JetType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) { - if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) { - continue; - } - - Pair found = - getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype); - if (found != null) { - return found; - } - } - - } - return null; - } - public static class OverrideCompatibilityInfo { public enum Result { @@ -445,8 +365,8 @@ public class OverridingUtil { } @NotNull - public static OverrideCompatibilityInfo synthesizedAndDeclarationIncompatible() { - return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "synthesizedAndDeclarationIncompatible"); // TODO + public static OverrideCompatibilityInfo externalConditionFailed(Class conditionClass) { + return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "externalConditionFailed: " + conditionClass.getName()); // TODO } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////