From d945c33d5e2d511a181fbb4ce02d0854cfda08b2 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 22 Jul 2016 13:41:35 +0300 Subject: [PATCH] Move some members from OverrideResolver to OverridingUtil --- .../kotlin/backend/common/bridges/impl.kt | 8 +- .../kotlin/resolve/OverrideResolver.java | 93 +------------------ .../results/ResolutionResultsHandler.java | 4 +- .../DescriptorEquivalenceForOverrides.kt | 0 .../kotlin/resolve/OverridingUtil.java | 86 +++++++++++++++++ .../kotlin/idea/search/usagesSearch/utils.kt | 4 +- .../KotlinStructureElementPresentation.java | 2 +- .../kotlin/idea/core/descriptorUtils.kt | 4 +- .../kotlin/js/patterns/PatternBuilder.java | 6 +- 9 files changed, 103 insertions(+), 104 deletions(-) rename {compiler/frontend => core/descriptors}/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt (100%) diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt index 5961a927336..40ef15ec804 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.OverrideResolver +import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized fun generateBridgesForFunctionDescriptor( @@ -108,8 +108,8 @@ fun findInterfaceImplementation(descriptor: CallableMemberDescriptor): CallableM * that should be called when the given fake override is called. */ fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? { - val overridden = OverrideResolver.getOverriddenDeclarations(descriptor) - val filtered = OverrideResolver.filterOutOverridden(overridden) + val overridden = OverridingUtil.getOverriddenDeclarations(descriptor) + val filtered = OverridingUtil.filterOutOverridden(overridden) val result = filtered.firstOrNull { it.modality != Modality.ABSTRACT } ?: return null @@ -129,6 +129,6 @@ fun firstSuperMethodFromKotlin( ): CallableMemberDescriptor? { return descriptor.overriddenDescriptors.firstOrNull { overridden -> overridden.modality != Modality.ABSTRACT && - (overridden == implementation || OverrideResolver.overrides(overridden, implementation)) + (overridden == implementation || OverridingUtil.overrides(overridden, implementation)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java index 94ef2e84170..a4edc630715 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java @@ -38,7 +38,6 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt; import org.jetbrains.kotlin.resolve.dataClassUtils.DataClassUtilsKt; import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; -import org.jetbrains.kotlin.utils.FunctionsKt; import java.util.*; @@ -95,63 +94,6 @@ public class OverrideResolver { }; } - /** - * Given a set of descriptors, returns a set containing all the given descriptors except those which _are overridden_ by at least - * one other descriptor from the original set. - */ - @NotNull - @SuppressWarnings("unchecked") - public static Set filterOutOverridden(@NotNull Set candidateSet) { - return filterOverrides(candidateSet, FunctionsKt.identity()); - } - - @NotNull - public static Set filterOverrides( - @NotNull Set candidateSet, - @NotNull Function1 transform - ) { - if (candidateSet.size() <= 1) return candidateSet; - - Set result = new LinkedHashSet(); - outerLoop: - for (D meD : candidateSet) { - CallableDescriptor me = transform.invoke(meD); - for (Iterator iterator = result.iterator(); iterator.hasNext(); ) { - D otherD = iterator.next(); - CallableDescriptor other = transform.invoke(otherD); - if (overrides(me, other)) { - iterator.remove(); - } - else if (overrides(other, me)) { - continue outerLoop; - } - } - result.add(meD); - } - - assert !result.isEmpty() : "All candidates filtered out from " + candidateSet; - - return result; - } - - /** - * @return whether f overrides g - */ - public static boolean overrides(@NotNull D f, @NotNull D g) { - // In a multi-module project different "copies" of the same class may be present in different libraries, - // that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides). - // This first check cover the case of duplicate classes in different modules: - // when B is defined in modules m1 and m2, and C (indirectly) inherits from both versions, - // we'll be getting sets of members that do not override each other, but are structurally equivalent. - // As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary - if (!f.equals(g) && DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(f.getOriginal(), g.getOriginal())) return true; - CallableDescriptor originalG = g.getOriginal(); - for (D overriddenFunction : DescriptorUtils.getAllOverriddenDescriptors(f)) { - if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(originalG, overriddenFunction.getOriginal())) return true; - } - return false; - } - private void checkOverrides(@NotNull TopDownAnalysisContext c) { for (Map.Entry entry : c.getDeclaredClasses().entrySet()) { @@ -399,7 +341,7 @@ public class OverrideResolver { Map> overriddenDeclarationsByDirectParent = collectOverriddenDeclarations(directOverridden); List allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values()); - Set allFilteredOverriddenDeclarations = filterOutOverridden( + Set allFilteredOverriddenDeclarations = OverridingUtil.filterOutOverridden( Sets.newLinkedHashSet(allOverriddenDeclarations)); Set relevantDirectlyOverridden = @@ -623,42 +565,13 @@ public class OverrideResolver { ) { Map> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap(); for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) { - Set overriddenDeclarations = getOverriddenDeclarations(descriptor); - Set filteredOverrides = filterOutOverridden(overriddenDeclarations); + Set overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor); + Set filteredOverrides = OverridingUtil.filterOutOverridden(overriddenDeclarations); overriddenDeclarationsByDirectParent.put(descriptor, new LinkedHashSet(filteredOverrides)); } return overriddenDeclarationsByDirectParent; } - /** - * @return overridden real descriptors (not fake overrides). Note that most usages of this method should be followed by calling - * {@link #filterOutOverridden(Set)}, because some of the declarations can override the other. - * TODO: merge this method with filterOutOverridden - */ - @NotNull - public static Set getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) { - Set result = new LinkedHashSet(); - getOverriddenDeclarations(descriptor, result); - return result; - } - - private static void getOverriddenDeclarations( - @NotNull CallableMemberDescriptor descriptor, - @NotNull Set result - ) { - if (descriptor.getKind().isReal()) { - result.add(descriptor); - } - else { - if (descriptor.getOverriddenDescriptors().isEmpty()) { - throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor); - } - for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) { - getOverriddenDeclarations(overridden, result); - } - } - } - private interface CheckOverrideReportStrategy { void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden); void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java index edeb21df04c..62c50766f19 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; -import org.jetbrains.kotlin.resolve.OverrideResolver; +import org.jetbrains.kotlin.resolve.OverridingUtil; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext; import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode; @@ -241,7 +241,7 @@ public class ResolutionResultsHandler { Set> noEquivalentCalls = filterOutEquivalentCalls(candidates); Set> noOverrides = - OverrideResolver.filterOverrides(noEquivalentCalls, MAP_RESOLVED_CALL_TO_RESULTING_DESCRIPTOR); + OverridingUtil.filterOverrides(noEquivalentCalls, MAP_RESOLVED_CALL_TO_RESULTING_DESCRIPTOR); if (noOverrides.size() == 1) { return OverloadResolutionResultsImpl.success(noOverrides.iterator().next()); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt similarity index 100% rename from compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt rename to core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java index 577c7ee0a7c..b17773c6bfe 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.TypeConstructor; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import org.jetbrains.kotlin.types.checker.KotlinTypeCheckerImpl; +import org.jetbrains.kotlin.utils.FunctionsKt; import org.jetbrains.kotlin.utils.SmartSet; import java.util.*; @@ -64,6 +65,91 @@ public class OverridingUtil { equalityAxioms = axioms; } + /** + * Given a set of descriptors, returns a set containing all the given descriptors except those which _are overridden_ by at least + * one other descriptor from the original set. + */ + @NotNull + @SuppressWarnings("unchecked") + public static Set filterOutOverridden(@NotNull Set candidateSet) { + return filterOverrides(candidateSet, FunctionsKt.identity()); + } + + @NotNull + public static Set filterOverrides( + @NotNull Set candidateSet, + @NotNull Function1 transform + ) { + if (candidateSet.size() <= 1) return candidateSet; + + Set result = new LinkedHashSet(); + outerLoop: + for (D meD : candidateSet) { + CallableDescriptor me = transform.invoke(meD); + for (Iterator iterator = result.iterator(); iterator.hasNext(); ) { + D otherD = iterator.next(); + CallableDescriptor other = transform.invoke(otherD); + if (overrides(me, other)) { + iterator.remove(); + } + else if (overrides(other, me)) { + continue outerLoop; + } + } + result.add(meD); + } + + assert !result.isEmpty() : "All candidates filtered out from " + candidateSet; + + return result; + } + + /** + * @return whether f overrides g + */ + public static boolean overrides(@NotNull D f, @NotNull D g) { + // In a multi-module project different "copies" of the same class may be present in different libraries, + // that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides). + // This first check cover the case of duplicate classes in different modules: + // when B is defined in modules m1 and m2, and C (indirectly) inherits from both versions, + // we'll be getting sets of members that do not override each other, but are structurally equivalent. + // As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary + if (!f.equals(g) && DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(f.getOriginal(), g.getOriginal())) return true; + CallableDescriptor originalG = g.getOriginal(); + for (D overriddenFunction : DescriptorUtils.getAllOverriddenDescriptors(f)) { + if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(originalG, overriddenFunction.getOriginal())) return true; + } + return false; + } + + /** + * @return overridden real descriptors (not fake overrides). Note that most usages of this method should be followed by calling + * {@link #filterOutOverridden(Set)}, because some of the declarations can override the other. + */ + @NotNull + public static Set getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) { + Set result = new LinkedHashSet(); + collectOverriddenDeclarations(descriptor, result); + return result; + } + + private static void collectOverriddenDeclarations( + @NotNull CallableMemberDescriptor descriptor, + @NotNull Set result + ) { + if (descriptor.getKind().isReal()) { + result.add(descriptor); + } + else { + if (descriptor.getOverriddenDescriptors().isEmpty()) { + throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor); + } + for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) { + collectOverriddenDeclarations(overridden, result); + } + } + } + @NotNull public OverrideCompatibilityInfo isOverridableBy( @NotNull CallableDescriptor superDescriptor, diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt index 39d82b9df15..5e6fe12e0f3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt @@ -38,7 +38,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.OverrideResolver +import org.jetbrains.kotlin.resolve.OverridingUtil val KtDeclaration.descriptor: DeclarationDescriptor? get() = this.analyze().get(BindingContext.DECLARATION_TO_DESCRIPTOR, this) @@ -227,7 +227,7 @@ fun PsiReference.isCallableOverrideUsage(declaration: KtNamedDeclaration): Boole when (it) { is KtDeclaration -> { val usageDescriptor = toDescriptor(it) - usageDescriptor != null && OverrideResolver.overrides(usageDescriptor, targetDescriptor) + usageDescriptor != null && OverridingUtil.overrides(usageDescriptor, targetDescriptor) } is PsiMethod -> { declaration.toLightMethods().any { superMethod -> MethodSignatureUtil.isSuperMethod(superMethod, it) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/structureView/KotlinStructureElementPresentation.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/structureView/KotlinStructureElementPresentation.java index 6ca1d693a93..5eefa5b6e79 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/structureView/KotlinStructureElementPresentation.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/structureView/KotlinStructureElementPresentation.java @@ -40,7 +40,7 @@ import java.util.Set; import static org.jetbrains.kotlin.renderer.DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES; import static org.jetbrains.kotlin.resolve.DescriptorUtils.getAllOverriddenDeclarations; -import static org.jetbrains.kotlin.resolve.OverrideResolver.filterOutOverridden; +import static org.jetbrains.kotlin.resolve.OverridingUtil.filterOutOverridden; class KotlinStructureElementPresentation implements ColoredItemPresentation, LocationPresentation { private final TextAttributesKey attributesKey; diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt index 006df6863b3..6832071a666 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.OverrideResolver +import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver @@ -142,7 +142,7 @@ fun D.getDirectlyOverriddenDeclarations(): Collec else -> throw AssertionError("Unexpected callable kind ${overriddenDescriptor.kind}: $overriddenDescriptor") } } - return OverrideResolver.filterOutOverridden(result) + return OverridingUtil.filterOutOverridden(result) } fun D.getDeepestSuperDeclarations(): Collection { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/patterns/PatternBuilder.java b/js/js.frontend/src/org/jetbrains/kotlin/js/patterns/PatternBuilder.java index 1bcf62aa2e4..2954d19296c 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/patterns/PatternBuilder.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/patterns/PatternBuilder.java @@ -20,11 +20,11 @@ import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.idea.KotlinLanguage; import org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt; import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.idea.KotlinLanguage; import org.jetbrains.kotlin.resolve.DescriptorUtils; -import org.jetbrains.kotlin.resolve.OverrideResolver; +import org.jetbrains.kotlin.resolve.OverridingUtil; import java.util.Arrays; import java.util.List; @@ -249,7 +249,7 @@ public final class PatternBuilder { return matches(functionDescriptor); } - for (CallableMemberDescriptor real : OverrideResolver.getOverriddenDeclarations(functionDescriptor)) { + for (CallableMemberDescriptor real : OverridingUtil.getOverriddenDeclarations(functionDescriptor)) { if (matches(real)) { return true; }