[FE 1.0] Resolve private constructors of sealed classes same as for regular classes

^KT-44866
^KT-49729
This commit is contained in:
Dmitriy Novozhilov
2021-11-16 16:57:51 +03:00
parent e2d68fd239
commit 93378b1a04
31 changed files with 294 additions and 113 deletions
@@ -33,7 +33,12 @@ public class JavaDescriptorVisibilities {
@NotNull
public static final DescriptorVisibility PACKAGE_VISIBILITY = new DelegatedDescriptorVisibility(JavaVisibilities.PackageVisibility.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return areInSamePackage(what, from);
}
};
@@ -41,7 +46,12 @@ public class JavaDescriptorVisibilities {
@NotNull
public static final DescriptorVisibility PROTECTED_STATIC_VISIBILITY = new DelegatedDescriptorVisibility(JavaVisibilities.ProtectedStaticVisibility.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return isVisibleForProtectedAndPackage(receiver, what, from);
}
};
@@ -49,7 +59,12 @@ public class JavaDescriptorVisibilities {
@NotNull
public static final DescriptorVisibility PROTECTED_AND_PACKAGE = new DelegatedDescriptorVisibility(JavaVisibilities.ProtectedAndPackage.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return isVisibleForProtectedAndPackage(receiver, what, from);
}
};
@@ -63,7 +78,7 @@ public class JavaDescriptorVisibilities {
return true;
}
return DescriptorVisibilities.PROTECTED.isVisible(receiver, what, from);
return DescriptorVisibilities.PROTECTED.isVisible(receiver, what, from, false);
}
private static boolean areInSamePackage(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
@@ -39,14 +39,20 @@ public class DescriptorVisibilities {
}
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
if (DescriptorUtils.isTopLevelDeclaration(what) && hasContainingSourceFile(from)) {
return inSameFile(what, from);
}
if (what instanceof ConstructorDescriptor) {
ClassifierDescriptorWithTypeParameters classDescriptor = ((ConstructorDescriptor) what).getContainingDeclaration();
if (DescriptorUtils.isSealedClass(classDescriptor)
if (useSpecialRulesForPrivateSealedConstructors
&& DescriptorUtils.isSealedClass(classDescriptor)
&& DescriptorUtils.isTopLevelDeclaration(classDescriptor)
&& from instanceof ConstructorDescriptor
&& DescriptorUtils.isTopLevelDeclaration(from.getContainingDeclaration())
@@ -99,8 +105,13 @@ public class DescriptorVisibilities {
@NotNull
public static final DescriptorVisibility PRIVATE_TO_THIS = new DelegatedDescriptorVisibility(Visibilities.PrivateToThis.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue thisObject, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
if (PRIVATE.isVisible(thisObject, what, from)) {
public boolean isVisible(
@Nullable ReceiverValue thisObject,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
if (PRIVATE.isVisible(thisObject, what, from, useSpecialRulesForPrivateSealedConstructors)) {
// See Visibility.isVisible contract
if (thisObject == ALWAYS_SUITABLE_RECEIVER) return true;
if (thisObject == IRRELEVANT_RECEIVER) return false;
@@ -121,7 +132,8 @@ public class DescriptorVisibilities {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
ClassDescriptor givenDescriptorContainingClass = DescriptorUtils.getParentOfType(what, ClassDescriptor.class);
ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
@@ -148,7 +160,7 @@ public class DescriptorVisibilities {
return true;
}
return isVisible(receiver, what, fromClass.getContainingDeclaration());
return isVisible(receiver, what, fromClass.getContainingDeclaration(), useSpecialRulesForPrivateSealedConstructors);
}
private boolean doesReceiverFitForProtectedVisibility(
@@ -179,7 +191,12 @@ public class DescriptorVisibilities {
@NotNull
public static final DescriptorVisibility INTERNAL = new DelegatedDescriptorVisibility(Visibilities.Internal.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
ModuleDescriptor whatModule = DescriptorUtils.getContainingModule(what);
ModuleDescriptor fromModule = DescriptorUtils.getContainingModule(from);
@@ -196,7 +213,12 @@ public class DescriptorVisibilities {
@NotNull
public static final DescriptorVisibility PUBLIC = new DelegatedDescriptorVisibility(Visibilities.Public.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return true;
}
};
@@ -204,7 +226,12 @@ public class DescriptorVisibilities {
@NotNull
public static final DescriptorVisibility LOCAL = new DelegatedDescriptorVisibility(Visibilities.Local.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
throw new IllegalStateException("This method shouldn't be invoked for LOCAL visibility");
}
};
@@ -212,7 +239,12 @@ public class DescriptorVisibilities {
@NotNull
public static final DescriptorVisibility INHERITED = new DelegatedDescriptorVisibility(Visibilities.Inherited.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
throw new IllegalStateException("Visibility is unknown yet"); //This method shouldn't be invoked for INHERITED visibility
}
};
@@ -221,7 +253,12 @@ public class DescriptorVisibilities {
@NotNull
public static final DescriptorVisibility INVISIBLE_FAKE = new DelegatedDescriptorVisibility(Visibilities.InvisibleFake.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
public boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return false;
}
};
@@ -232,7 +269,8 @@ public class DescriptorVisibilities {
public static final DescriptorVisibility UNKNOWN = new DelegatedDescriptorVisibility(Visibilities.Unknown.INSTANCE) {
@Override
public boolean isVisible(
@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from
@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return false;
}
@@ -244,23 +282,36 @@ public class DescriptorVisibilities {
private DescriptorVisibilities() {
}
public static boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
return findInvisibleMember(receiver, what, from) == null;
public static boolean isVisible(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return findInvisibleMember(receiver, what, from, useSpecialRulesForPrivateSealedConstructors) == null;
}
/**
* @see DescriptorVisibility.isVisible contract
*/
public static boolean isVisibleIgnoringReceiver(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
return findInvisibleMember(ALWAYS_SUITABLE_RECEIVER, what, from) == null;
public static boolean isVisibleIgnoringReceiver(
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return findInvisibleMember(ALWAYS_SUITABLE_RECEIVER, what, from, useSpecialRulesForPrivateSealedConstructors) == null;
}
/**
* @see DescriptorVisibility.isVisible contract
* @see DescriptorVisibilities.RECEIVER_DOES_NOT_EXIST
*/
public static boolean isVisibleWithAnyReceiver(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
return findInvisibleMember(IRRELEVANT_RECEIVER, what, from) == null;
public static boolean isVisibleWithAnyReceiver(
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return findInvisibleMember(IRRELEVANT_RECEIVER, what, from, useSpecialRulesForPrivateSealedConstructors) == null;
}
// Note that this method returns false if `from` declaration is `init` initializer
@@ -277,11 +328,12 @@ public class DescriptorVisibilities {
public static DeclarationDescriptorWithVisibility findInvisibleMember(
@Nullable ReceiverValue receiver,
@NotNull DeclarationDescriptorWithVisibility what,
@NotNull DeclarationDescriptor from
@NotNull DeclarationDescriptor from,
boolean useSpecialRulesForPrivateSealedConstructors
) {
DeclarationDescriptorWithVisibility parent = (DeclarationDescriptorWithVisibility) what.getOriginal();
while (parent != null && parent.getVisibility() != LOCAL) {
if (!parent.getVisibility().isVisible(receiver, parent, from)) {
if (!parent.getVisibility().isVisible(receiver, parent, from, useSpecialRulesForPrivateSealedConstructors)) {
return parent;
}
parent = DescriptorUtils.getParentOfType(parent, DeclarationDescriptorWithVisibility.class);
@@ -289,7 +341,12 @@ public class DescriptorVisibilities {
if (what instanceof TypeAliasConstructorDescriptor) {
DeclarationDescriptorWithVisibility invisibleUnderlying =
findInvisibleMember(receiver, ((TypeAliasConstructorDescriptor) what).getUnderlyingConstructorDescriptor(), from);
findInvisibleMember(
receiver,
((TypeAliasConstructorDescriptor) what).getUnderlyingConstructorDescriptor(),
from,
useSpecialRulesForPrivateSealedConstructors
);
if (invisibleUnderlying != null) return invisibleUnderlying;
}
@@ -40,7 +40,12 @@ abstract class DescriptorVisibility protected constructor() {
*
* Also it's important that implementation that take receiver into account do aware about these special values.
*/
abstract fun isVisible(receiver: ReceiverValue?, what: DeclarationDescriptorWithVisibility, from: DeclarationDescriptor): Boolean
abstract fun isVisible(
receiver: ReceiverValue?,
what: DeclarationDescriptorWithVisibility,
from: DeclarationDescriptor,
useSpecialRulesForPrivateSealedConstructors: Boolean
): Boolean
/**
* True, if it makes sense to check this visibility in imports and not import inaccessible declarations with such visibility.
@@ -504,9 +504,13 @@ public class OverridingUtil {
createAndBindFakeOverrides(current, notOverridden, strategy);
}
public static boolean isVisibleForOverride(@NotNull MemberDescriptor overriding, @NotNull MemberDescriptor fromSuper) {
public static boolean isVisibleForOverride(
@NotNull MemberDescriptor overriding,
@NotNull MemberDescriptor fromSuper,
boolean useSpecialRulesForPrivateSealedConstructors
) {
return !DescriptorVisibilities.isPrivate(fromSuper.getVisibility()) &&
DescriptorVisibilities.isVisibleIgnoringReceiver(fromSuper, overriding);
DescriptorVisibilities.isVisibleIgnoringReceiver(fromSuper, overriding, useSpecialRulesForPrivateSealedConstructors);
}
private Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
@@ -520,7 +524,7 @@ public class OverridingUtil {
for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
OverrideCompatibilityInfo.Result result = isOverridableBy(fromSupertype, fromCurrent, current).getResult();
boolean isVisibleForOverride = isVisibleForOverride(fromCurrent, fromSupertype);
boolean isVisibleForOverride = isVisibleForOverride(fromCurrent, fromSupertype, false);
switch (result) {
case OVERRIDABLE:
@@ -810,7 +814,7 @@ public class OverridingUtil {
public Boolean invoke(CallableMemberDescriptor descriptor) {
//nested class could capture private member, so check for private visibility added
return !DescriptorVisibilities.isPrivate(descriptor.getVisibility()) &&
DescriptorVisibilities.isVisibleIgnoringReceiver(descriptor, current);
DescriptorVisibilities.isVisibleIgnoringReceiver(descriptor, current, false);
}
});
}