From effbdcaa4cc60a774acf6d6308a37a4071304cb4 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 21 Aug 2013 19:29:02 +0400 Subject: [PATCH] Move utilities out of OverrideResolver --- .../FakeOverrideVisibilityResolverImpl.java | 4 +- .../DeserializedClassDescriptor.java | 8 +- .../jet/lang/resolve/OverrideResolver.java | 268 +----------------- .../jet/lang/resolve/OverridingUtil.java | 267 ++++++++++++++++- .../descriptors/LazyClassMemberScope.java | 13 +- .../resolver/DescriptorResolverUtils.java | 6 +- 6 files changed, 289 insertions(+), 277 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FakeOverrideVisibilityResolverImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FakeOverrideVisibilityResolverImpl.java index 6a2a4c7e850..32cb806c301 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FakeOverrideVisibilityResolverImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FakeOverrideVisibilityResolverImpl.java @@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.resolve.java.resolver; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.OverrideResolver; +import org.jetbrains.jet.lang.resolve.OverridingUtil; import javax.inject.Inject; @@ -17,6 +17,6 @@ public class FakeOverrideVisibilityResolverImpl implements FakeOverrideVisibilit @Override public void resolveUnknownVisibilityForMember(@NotNull CallableMemberDescriptor descriptor) { - OverrideResolver.resolveUnknownVisibilityForMember(null, descriptor, trace); + OverridingUtil.resolveUnknownVisibilityForMember(null, descriptor, trace); } } diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java index b5c6cd36ac9..5e731c42b55 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java @@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.*; import org.jetbrains.jet.lang.resolve.DescriptorResolver; -import org.jetbrains.jet.lang.resolve.OverrideResolver; +import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.resolve.TraceUtil; import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNullable; import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue; @@ -420,15 +420,15 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements @NotNull final Collection result ) { List fromCurrent = new ArrayList(result); - OverrideResolver.generateOverridesInFunctionGroup( + OverridingUtil.generateOverridesInFunctionGroup( name, fromSupertypes, fromCurrent, classDescriptor, - new OverrideResolver.DescriptorSink() { + new OverridingUtil.DescriptorSink() { @Override public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) { - OverrideResolver.resolveUnknownVisibilityForMember(null, fakeOverride, TraceUtil.TRACE_STUB); + OverridingUtil.resolveUnknownVisibilityForMember(null, fakeOverride, TraceUtil.TRACE_STUB); //noinspection unchecked result.add((D) fakeOverride); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index b26c09a6a6f..0f9f68f23ef 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -16,18 +16,20 @@ package org.jetbrains.jet.lang.resolve; -import com.google.common.base.Predicate; -import com.google.common.collect.*; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.LinkedMultiMap; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.descriptors.impl.*; +import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; +import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; @@ -43,7 +45,6 @@ import javax.inject.Inject; import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT; import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; public class OverrideResolver { @@ -134,12 +135,12 @@ public class OverrideResolver { Collection fromSupertypes = membersFromSupertypesByName.get(memberName); Collection fromCurrent = membersFromCurrentByName.get(memberName); - generateOverridesInFunctionGroup( + OverridingUtil.generateOverridesInFunctionGroup( memberName, fromSupertypes, fromCurrent, classDescriptor, - new DescriptorSink() { + new OverridingUtil.DescriptorSink() { @Override public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) { if (fakeOverride instanceof PropertyDescriptor) { @@ -175,189 +176,10 @@ public class OverrideResolver { declaration = (JetDeclaration) element; } } - resolveUnknownVisibilityForMember(declaration, memberDescriptor, trace); + OverridingUtil.resolveUnknownVisibilityForMember(declaration, memberDescriptor, trace); } } - public interface DescriptorSink { - void addToScope(@NotNull CallableMemberDescriptor fakeOverride); - - void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent); - } - - public static void generateOverridesInFunctionGroup( - @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name - @NotNull Collection membersFromSupertypes, - @NotNull Collection membersFromCurrent, - @NotNull ClassDescriptor current, - @NotNull DescriptorSink sink - ) { - Collection notOverridden = Sets.newLinkedHashSet(membersFromSupertypes); - - for (CallableMemberDescriptor fromCurrent : membersFromCurrent) { - Collection bound = - extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink); - notOverridden.removeAll(bound); - } - - createAndBindFakeOverrides(current, notOverridden, sink); - } - - private static Collection extractAndBindOverridesForMember( - @NotNull CallableMemberDescriptor fromCurrent, - @NotNull Collection descriptorsFromSuper, - @NotNull ClassDescriptor current, - @NotNull DescriptorSink sink - ) { - Collection bound = Lists.newArrayList(); - for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) { - OverridingUtil.OverrideCompatibilityInfo.Result result = - OverridingUtil.isOverridableBy(fromSupertype, fromCurrent).getResult(); - - boolean isVisible = Visibilities.isVisible(fromSupertype, current); - switch (result) { - case OVERRIDABLE: - if (isVisible) { - OverridingUtil.bindOverride(fromCurrent, fromSupertype); - } - bound.add(fromSupertype); - break; - case CONFLICT: - if (isVisible) { - sink.conflict(fromSupertype, fromCurrent); - } - bound.add(fromSupertype); - break; - case INCOMPATIBLE: - break; - } - } - return bound; - } - - private static void createAndBindFakeOverrides( - @NotNull ClassDescriptor current, - @NotNull Collection notOverridden, - @NotNull DescriptorSink sink - ) { - Queue fromSuperQueue = new LinkedList(notOverridden); - while (!fromSuperQueue.isEmpty()) { - CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtil.findMemberWithMaxVisibility(fromSuperQueue); - Collection overridables = extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, - sink); - createAndBindFakeOverride(overridables, current, sink); - } - } - - private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) { - if (a instanceof SimpleFunctionDescriptor) { - assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass(); - - JetType aReturnType = a.getReturnType(); - assert aReturnType != null; - JetType bReturnType = b.getReturnType(); - assert bReturnType != null; - - return JetTypeChecker.INSTANCE.isSubtypeOf(aReturnType, bReturnType); - } - if (a instanceof PropertyDescriptor) { - assert b instanceof PropertyDescriptor : "b is " + b.getClass(); - - if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) { - return ((PropertyDescriptor) a).isVar(); - } - - // both vals - return JetTypeChecker.INSTANCE.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType()); - } - throw new IllegalArgumentException("Unexpected callable: " + a.getClass()); - } - - private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection overridables) { - CallableMemberDescriptor result = null; - for (CallableMemberDescriptor overridable : overridables) { - if (result == null || isMoreSpecific(overridable, result)) { - result = overridable; - } - } - return result; - } - - private static void createAndBindFakeOverride( - @NotNull Collection overridables, - @NotNull ClassDescriptor current, - @NotNull DescriptorSink sink - ) { - Collection visibleOverridables = filterVisibleFakeOverrides(current, overridables); - Modality modality = getMinimalModality(visibleOverridables); - boolean allInvisible = visibleOverridables.isEmpty(); - Collection effectiveOverridden = allInvisible ? overridables : visibleOverridables; - Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; - CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden); - CallableMemberDescriptor fakeOverride = - mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); - for (CallableMemberDescriptor descriptor : effectiveOverridden) { - OverridingUtil.bindOverride(fakeOverride, descriptor); - } - sink.addToScope(fakeOverride); - } - - @NotNull - private static Modality getMinimalModality(@NotNull Collection descriptors) { - Modality modality = Modality.ABSTRACT; - for (CallableMemberDescriptor descriptor : descriptors) { - if (descriptor.getModality().compareTo(modality) < 0) { - modality = descriptor.getModality(); - } - } - return modality; - } - - @NotNull - private static Collection filterVisibleFakeOverrides( - @NotNull final ClassDescriptor current, - @NotNull Collection toFilter - ) { - return Collections2.filter(toFilter, new Predicate() { - @Override - public boolean apply(@Nullable CallableMemberDescriptor descriptor) { - //nested class could capture private member, so check for private visibility added - return descriptor.getVisibility() != Visibilities.PRIVATE && Visibilities.isVisible(descriptor, current); - } - }); - } - - @NotNull - private static Collection extractMembersOverridableInBothWays( - @NotNull CallableMemberDescriptor overrider, - @NotNull Queue extractFrom, - @NotNull DescriptorSink sink - ) { - Collection overridable = Lists.newArrayList(); - overridable.add(overrider); - for (Iterator iterator = extractFrom.iterator(); iterator.hasNext(); ) { - CallableMemberDescriptor candidate = iterator.next(); - if (overrider == candidate) { - iterator.remove(); - continue; - } - - OverridingUtil.OverrideCompatibilityInfo.Result result1 = - OverridingUtil.isOverridableBy(candidate, overrider).getResult(); - OverridingUtil.OverrideCompatibilityInfo.Result result2 = - OverridingUtil.isOverridableBy(overrider, candidate).getResult(); - if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) { - overridable.add(candidate); - iterator.remove(); - } - else if (result1 == CONFLICT || result2 == CONFLICT) { - sink.conflict(overrider, candidate); - iterator.remove(); - } - } - return overridable; - } - private static MultiMap groupDescriptorsByName(Collection properties) { MultiMap r = new LinkedMultiMap(); for (T property : properties) { @@ -893,78 +715,6 @@ public class OverrideResolver { return false; } - public static void resolveUnknownVisibilityForMember(@Nullable JetDeclaration member, @NotNull CallableMemberDescriptor memberDescriptor, @NotNull BindingTrace trace) { - resolveUnknownVisibilityForOverriddenDescriptors(memberDescriptor.getOverriddenDescriptors(), trace); - if (memberDescriptor.getVisibility() != Visibilities.INHERITED) { - return; - } - - Visibility visibility = findMaxVisibility(memberDescriptor.getOverriddenDescriptors()); - if (visibility == null) { - if (member != null) { - trace.report(CANNOT_INFER_VISIBILITY.on(member)); - } - visibility = Visibilities.PUBLIC; - } - - if (memberDescriptor instanceof PropertyDescriptorImpl) { - ((PropertyDescriptorImpl)memberDescriptor).setVisibility(visibility.normalize()); - for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) { - resolveUnknownVisibilityForMember(null, accessor, trace); - } - } - else if (memberDescriptor instanceof FunctionDescriptorImpl) { - ((FunctionDescriptorImpl)memberDescriptor).setVisibility(visibility.normalize()); - } - else { - assert memberDescriptor instanceof PropertyAccessorDescriptorImpl; - ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibility.normalize()); - } - } - - private static void resolveUnknownVisibilityForOverriddenDescriptors(@NotNull Collection descriptors, @NotNull BindingTrace trace) { - for (CallableMemberDescriptor descriptor : descriptors) { - if (descriptor.getVisibility() == Visibilities.INHERITED) { - PsiElement element = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor); - JetDeclaration declaration = (element instanceof JetDeclaration) ? (JetDeclaration) element : null; - resolveUnknownVisibilityForMember(declaration, descriptor, trace); - } - } - } - - @Nullable - private static Visibility findMaxVisibility(@NotNull Collection descriptors) { - if (descriptors.isEmpty()) { - return Visibilities.INTERNAL; - } - Visibility maxVisibility = null; - for (CallableMemberDescriptor descriptor : descriptors) { - Visibility visibility = descriptor.getVisibility(); - assert visibility != Visibilities.INHERITED; - if (maxVisibility == null) { - maxVisibility = visibility; - continue; - } - Integer compareResult = Visibilities.compare(visibility, maxVisibility); - if (compareResult == null) { - maxVisibility = null; - } - else if (compareResult > 0) { - maxVisibility = visibility; - } - } - if (maxVisibility == null) { - return null; - } - for (CallableMemberDescriptor descriptor : descriptors) { - Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); - if (compareResult == null || compareResult < 0) { - return null; - } - } - return maxVisibility; - } - private void checkVisibility() { for (Map.Entry entry : context.getMembers().entrySet()) { checkVisibilityForMember(entry.getKey(), entry.getValue()); 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 ec6a001deed..26e51d42f57 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -16,20 +16,28 @@ package org.jetbrains.jet.lang.resolve; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; +import com.google.common.base.Predicate; +import com.google.common.collect.*; +import com.intellij.psi.PsiElement; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.impl.PropertyAccessorDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import java.util.*; +import static org.jetbrains.jet.lang.diagnostics.Errors.CANNOT_INFER_VISIBILITY; +import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT; +import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; + public class OverridingUtil { private static final List EXTERNAL_CONDITIONS = @@ -308,6 +316,257 @@ public class OverridingUtil { } } + public static void generateOverridesInFunctionGroup( + @SuppressWarnings("UnusedParameters") + @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name + @NotNull Collection membersFromSupertypes, + @NotNull Collection membersFromCurrent, + @NotNull ClassDescriptor current, + @NotNull DescriptorSink sink + ) { + Collection notOverridden = Sets.newLinkedHashSet(membersFromSupertypes); + + for (CallableMemberDescriptor fromCurrent : membersFromCurrent) { + Collection bound = + extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink); + notOverridden.removeAll(bound); + } + + createAndBindFakeOverrides(current, notOverridden, sink); + } + + private static Collection extractAndBindOverridesForMember( + @NotNull CallableMemberDescriptor fromCurrent, + @NotNull Collection descriptorsFromSuper, + @NotNull ClassDescriptor current, + @NotNull DescriptorSink sink + ) { + Collection bound = Lists.newArrayList(); + for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) { + OverrideCompatibilityInfo.Result result = isOverridableBy(fromSupertype, fromCurrent).getResult(); + + boolean isVisible = Visibilities.isVisible(fromSupertype, current); + switch (result) { + case OVERRIDABLE: + if (isVisible) { + bindOverride(fromCurrent, fromSupertype); + } + bound.add(fromSupertype); + break; + case CONFLICT: + if (isVisible) { + sink.conflict(fromSupertype, fromCurrent); + } + bound.add(fromSupertype); + break; + case INCOMPATIBLE: + break; + } + } + return bound; + } + + private static void createAndBindFakeOverrides( + @NotNull ClassDescriptor current, + @NotNull Collection notOverridden, + @NotNull DescriptorSink sink + ) { + Queue fromSuperQueue = new LinkedList(notOverridden); + while (!fromSuperQueue.isEmpty()) { + CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtil.findMemberWithMaxVisibility(fromSuperQueue); + Collection overridables = + extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, sink); + createAndBindFakeOverride(overridables, current, sink); + } + } + + private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) { + if (a instanceof SimpleFunctionDescriptor) { + assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass(); + + JetType aReturnType = a.getReturnType(); + assert aReturnType != null; + JetType bReturnType = b.getReturnType(); + assert bReturnType != null; + + return JetTypeChecker.INSTANCE.isSubtypeOf(aReturnType, bReturnType); + } + if (a instanceof PropertyDescriptor) { + assert b instanceof PropertyDescriptor : "b is " + b.getClass(); + + if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) { + return ((PropertyDescriptor) a).isVar(); + } + + // both vals + return JetTypeChecker.INSTANCE.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType()); + } + throw new IllegalArgumentException("Unexpected callable: " + a.getClass()); + } + + private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection overridables) { + CallableMemberDescriptor result = null; + for (CallableMemberDescriptor overridable : overridables) { + if (result == null || isMoreSpecific(overridable, result)) { + result = overridable; + } + } + return result; + } + + private static void createAndBindFakeOverride( + @NotNull Collection overridables, + @NotNull ClassDescriptor current, + @NotNull DescriptorSink sink + ) { + Collection visibleOverridables = filterVisibleFakeOverrides(current, overridables); + Modality modality = getMinimalModality(visibleOverridables); + boolean allInvisible = visibleOverridables.isEmpty(); + Collection effectiveOverridden = allInvisible ? overridables : visibleOverridables; + Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; + CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden); + CallableMemberDescriptor fakeOverride = + mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); + for (CallableMemberDescriptor descriptor : effectiveOverridden) { + bindOverride(fakeOverride, descriptor); + } + sink.addToScope(fakeOverride); + } + + @NotNull + private static Modality getMinimalModality(@NotNull Collection descriptors) { + Modality modality = Modality.ABSTRACT; + for (CallableMemberDescriptor descriptor : descriptors) { + if (descriptor.getModality().compareTo(modality) < 0) { + modality = descriptor.getModality(); + } + } + return modality; + } + + @NotNull + private static Collection filterVisibleFakeOverrides( + @NotNull final ClassDescriptor current, + @NotNull Collection toFilter + ) { + return Collections2.filter(toFilter, new Predicate() { + @Override + public boolean apply(@Nullable CallableMemberDescriptor descriptor) { + //nested class could capture private member, so check for private visibility added + return descriptor != null && + descriptor.getVisibility() != Visibilities.PRIVATE && + Visibilities.isVisible(descriptor, current); + } + }); + } + + @NotNull + private static Collection extractMembersOverridableInBothWays( + @NotNull CallableMemberDescriptor overrider, + @NotNull Queue extractFrom, + @NotNull DescriptorSink sink + ) { + Collection overridable = Lists.newArrayList(); + overridable.add(overrider); + for (Iterator iterator = extractFrom.iterator(); iterator.hasNext(); ) { + CallableMemberDescriptor candidate = iterator.next(); + if (overrider == candidate) { + iterator.remove(); + continue; + } + + OverrideCompatibilityInfo.Result result1 = isOverridableBy(candidate, overrider).getResult(); + OverrideCompatibilityInfo.Result result2 = isOverridableBy(overrider, candidate).getResult(); + if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) { + overridable.add(candidate); + iterator.remove(); + } + else if (result1 == CONFLICT || result2 == CONFLICT) { + sink.conflict(overrider, candidate); + iterator.remove(); + } + } + return overridable; + } + + public static void resolveUnknownVisibilityForMember(@Nullable JetDeclaration member, @NotNull CallableMemberDescriptor memberDescriptor, @NotNull BindingTrace trace) { + resolveUnknownVisibilityForOverriddenDescriptors(memberDescriptor.getOverriddenDescriptors(), trace); + if (memberDescriptor.getVisibility() != Visibilities.INHERITED) { + return; + } + + Visibility visibility = findMaxVisibility(memberDescriptor.getOverriddenDescriptors()); + if (visibility == null) { + if (member != null) { + trace.report(CANNOT_INFER_VISIBILITY.on(member)); + } + visibility = Visibilities.PUBLIC; + } + + if (memberDescriptor instanceof PropertyDescriptorImpl) { + ((PropertyDescriptorImpl)memberDescriptor).setVisibility(visibility.normalize()); + for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) { + resolveUnknownVisibilityForMember(null, accessor, trace); + } + } + else if (memberDescriptor instanceof FunctionDescriptorImpl) { + ((FunctionDescriptorImpl)memberDescriptor).setVisibility(visibility.normalize()); + } + else { + assert memberDescriptor instanceof PropertyAccessorDescriptorImpl; + ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibility.normalize()); + } + } + + private static void resolveUnknownVisibilityForOverriddenDescriptors(@NotNull Collection descriptors, @NotNull BindingTrace trace) { + for (CallableMemberDescriptor descriptor : descriptors) { + if (descriptor.getVisibility() == Visibilities.INHERITED) { + PsiElement element = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor); + JetDeclaration declaration = (element instanceof JetDeclaration) ? (JetDeclaration) element : null; + resolveUnknownVisibilityForMember(declaration, descriptor, trace); + } + } + } + + @Nullable + private static Visibility findMaxVisibility(@NotNull Collection descriptors) { + if (descriptors.isEmpty()) { + return Visibilities.INTERNAL; + } + Visibility maxVisibility = null; + for (CallableMemberDescriptor descriptor : descriptors) { + Visibility visibility = descriptor.getVisibility(); + assert visibility != Visibilities.INHERITED; + if (maxVisibility == null) { + maxVisibility = visibility; + continue; + } + Integer compareResult = Visibilities.compare(visibility, maxVisibility); + if (compareResult == null) { + maxVisibility = null; + } + else if (compareResult > 0) { + maxVisibility = visibility; + } + } + if (maxVisibility == null) { + return null; + } + for (CallableMemberDescriptor descriptor : descriptors) { + Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); + if (compareResult == null || compareResult < 0) { + return null; + } + } + return maxVisibility; + } + + public interface DescriptorSink { + void addToScope(@NotNull CallableMemberDescriptor fakeOverride); + + void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent); + } + public static class OverrideCompatibilityInfo { public enum Result { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.java index 90843cb75ad..34883df5f2f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.java @@ -39,7 +39,10 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.util.lazy.RecursionIntolerantLazyValue; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; public class LazyClassMemberScope extends AbstractLazyMemberScope { @@ -101,12 +104,12 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope result, @NotNull final Class exactDescriptorClass ) { - OverrideResolver.generateOverridesInFunctionGroup( + OverridingUtil.generateOverridesInFunctionGroup( name, fromSupertypes, Lists.newArrayList(result), thisDescriptor, - new OverrideResolver.DescriptorSink() { + new OverridingUtil.DescriptorSink() { @Override public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) { assert exactDescriptorClass.isInstance(fakeOverride) : "Wrong descriptor type in an override: " + @@ -140,7 +143,7 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope result = new HashSet(); - OverrideResolver.generateOverridesInFunctionGroup( + OverridingUtil.generateOverridesInFunctionGroup( name, membersFromSupertypes, membersFromCurrent, classDescriptor, - new OverrideResolver.DescriptorSink() { + new OverridingUtil.DescriptorSink() { @Override @SuppressWarnings("unchecked") public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {