diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt index 63702b6ff03..a55440b496f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt @@ -183,7 +183,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics( descriptor.getParentJavaStaticClassScope()?.run { getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) .filter { - it is FunctionDescriptor && Visibilities.isVisibleWithIrrelevantReceiver(it, descriptor) + it is FunctionDescriptor && Visibilities.isVisibleIgnoringReceiver(it, descriptor) } .forEach(::processMember) } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaTypeAccessibilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaTypeAccessibilityChecker.kt index 4aad3ec2fc4..215bf5292a9 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaTypeAccessibilityChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaTypeAccessibilityChecker.kt @@ -74,7 +74,7 @@ class JavaTypeAccessibilityChecker : AdditionalTypeChecker { if (visitedTypeConstructors.contains(typeConstructor)) return visitedTypeConstructors.add(typeConstructor) - if (typeConstructor is JavaClassDescriptor && !Visibilities.isVisibleWithIrrelevantReceiver(typeConstructor, scopeOwner)) { + if (typeConstructor is JavaClassDescriptor && !Visibilities.isVisibleIgnoringReceiver(typeConstructor, scopeOwner)) { inaccessibleTypes.add(type) } for (typeProjection in type.arguments) { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt index bdba8b386d0..874094c251b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt @@ -36,7 +36,7 @@ fun syntheticExtensionVisibility(originalDescriptor: DeclarationDescriptorWithVi else -> object : Visibility(originalVisibility.name, originalVisibility.isPublicAPI) { override fun isVisible(receiver: ReceiverValue?, what: DeclarationDescriptorWithVisibility, from: DeclarationDescriptor) - = originalVisibility.isVisible(receiver, originalDescriptor, from) + = originalVisibility.isVisible(Visibilities.ALWAYS_SUITABLE_RECEIVER, originalDescriptor, from) override fun mustCheckInImports() = throw UnsupportedOperationException("Should never be called for this visibility") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java index 20469d4a161..4d17abf0189 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java @@ -1027,7 +1027,7 @@ public class OverrideResolver { all.addAll((Collection) supertype.getMemberScope().getContributedVariables(declared.getName(), NoLookupLocation.WHEN_CHECK_OVERRIDES)); for (CallableMemberDescriptor fromSuper : all) { if (OverridingUtil.DEFAULT.isOverridableBy(fromSuper, declared, null).getResult() == OVERRIDABLE) { - if (Visibilities.isVisibleWithIrrelevantReceiver(fromSuper, declared)) { + if (Visibilities.isVisibleIgnoringReceiver(fromSuper, declared)) { throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared + " and visible but does not appear in its getOverriddenDescriptors()"); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt index f02072a82ee..40b2fb0c122 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt @@ -609,7 +609,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator if (Visibilities.isPrivate(visibility)) return false if (!visibility.mustCheckInImports()) return true } - return Visibilities.isVisibleWithIrrelevantReceiver(descriptor, shouldBeVisibleFrom) + return Visibilities.isVisibleIgnoringReceiver(descriptor, shouldBeVisibleFrom) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeProviderImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeProviderImpl.kt index f3c85f292dc..437228dd5f8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeProviderImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeProviderImpl.kt @@ -160,7 +160,7 @@ open class FileScopeProviderImpl( override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? { if (name in excludedNames) return null val classifier = scope.getContributedClassifier(name, location) ?: return null - val visible = Visibilities.isVisibleWithIrrelevantReceiver(classifier as ClassDescriptor, fromDescriptor) + val visible = Visibilities.isVisibleIgnoringReceiver(classifier as ClassDescriptor, fromDescriptor) return classifier.check { filteringKind == if (visible) FilteringKind.VISIBLE_CLASSES else FilteringKind.INVISIBLE_CLASSES } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt index a5e557fb7ae..f69081cf362 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt @@ -180,7 +180,7 @@ class LazyImportScope( val visibility = descriptor.visibility val includeVisible = filteringKind == FilteringKind.VISIBLE_CLASSES if (!visibility.mustCheckInImports()) return includeVisible - return Visibilities.isVisibleWithIrrelevantReceiver(descriptor, importResolver.moduleDescriptor) == includeVisible + return Visibilities.isVisibleIgnoringReceiver(descriptor, importResolver.moduleDescriptor) == includeVisible } override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibilities.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibilities.java index 4204ac3545c..f323d445b37 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibilities.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibilities.java @@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver; +import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.util.ModuleVisibilityHelper; import org.jetbrains.kotlin.utils.CollectionsKt; @@ -88,6 +89,10 @@ public class Visibilities { @Override public boolean isVisible(@Nullable ReceiverValue thisObject, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) { if (PRIVATE.isVisible(thisObject, what, from)) { + // See Visibility.isVisible contract + if (thisObject == ALWAYS_SUITABLE_RECEIVER) return true; + if (thisObject == IRRELEVANT_RECEIVER) return false; + DeclarationDescriptor classDescriptor = DescriptorUtils.getParentOfType(what, ClassDescriptor.class); if (classDescriptor != null && thisObject instanceof ThisClassReceiver) { @@ -223,13 +228,21 @@ public class Visibilities { } /** - * Receiver used only for visibility PRIVATE_TO_THIS. - * For all other visibilities this method give correct result. + * @see Visibility.isVisible contract */ - public static boolean isVisibleWithIrrelevantReceiver(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) { - return findInvisibleMember(null, what, from) == null; + public static boolean isVisibleIgnoringReceiver(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) { + return findInvisibleMember(ALWAYS_SUITABLE_RECEIVER, what, from) == null; } + /** + * @see Visibility.isVisible contract + * @see Visibilities.RECEIVER_DOES_NOT_EXIST + */ + public static boolean isVisibleWithAnyReceiver(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) { + return findInvisibleMember(IRRELEVANT_RECEIVER, what, from) == null; + } + + @Nullable public static DeclarationDescriptorWithVisibility findInvisibleMember( @Nullable ReceiverValue receiver, @@ -285,6 +298,30 @@ public class Visibilities { public static final Visibility DEFAULT_VISIBILITY = PUBLIC; + /** + * This value should be used for receiverValue parameter of Visibility.isVisible + * iff there is intention to determine if member is visible for any receiver. + */ + private static final ReceiverValue IRRELEVANT_RECEIVER = new ReceiverValue() { + @NotNull + @Override + public KotlinType getType() { + throw new IllegalStateException("This method should not be called"); + } + }; + + /** + * This value should be used for receiverValue parameter of Visibility.isVisible + * iff there is intention to determine if member is visible without receiver related checks being performed. + */ + public static final ReceiverValue ALWAYS_SUITABLE_RECEIVER = new ReceiverValue() { + @NotNull + @Override + public KotlinType getType() { + throw new IllegalStateException("This method should not be called"); + } + }; + public static boolean isPrivate(@NotNull Visibility visibility) { return visibility == PRIVATE || visibility == PRIVATE_TO_THIS; } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibility.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibility.kt index ab3ddd1367c..096cd7c055b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibility.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibility.kt @@ -22,6 +22,19 @@ abstract class Visibility protected constructor( val name: String, val isPublicAPI: Boolean ) { + /** + * @param receiver can be used to determine callee accessibility for some special receiver value + * + * 'null'-value basically means that receiver is absent in current call + * + * In case if it's needed to perform basic checks ignoring ones considering receiver (e.g. when checks happen beyond any call), + * special value Visibilities.ALWAYS_SUITABLE_RECEIVER should be used. + * If it's needed to determine whether visibility accepts any receiver, Visibilities.IRRELEVANT_RECEIVER should be used. + * + * NB: Currently Visibilities.IRRELEVANT_RECEIVER has the same effect as 'null' + * + * 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 /** diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java index a45c1e772ce..2d01941100d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java @@ -337,7 +337,7 @@ public class OverridingUtil { for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) { OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent, current).getResult(); - boolean isVisible = Visibilities.isVisibleWithIrrelevantReceiver(fromSupertype, current); + boolean isVisible = Visibilities.isVisibleIgnoringReceiver(fromSupertype, current); switch (result) { case OVERRIDABLE: if (isVisible) { @@ -567,7 +567,7 @@ public class OverridingUtil { public Boolean invoke(CallableMemberDescriptor descriptor) { //nested class could capture private member, so check for private visibility added return !Visibilities.isPrivate(descriptor.getVisibility()) && - Visibilities.isVisibleWithIrrelevantReceiver(descriptor, current); + Visibilities.isVisibleIgnoringReceiver(descriptor, current); } }); } 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 7bb8184e1a6..cc01d53f900 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 @@ -54,7 +54,7 @@ private fun DeclarationDescriptorWithVisibility.isVisible( bindingContext: BindingContext? = null, resolutionScope: LexicalScope? = null ): Boolean { - if (Visibilities.isVisibleWithIrrelevantReceiver(this, from)) return true + if (Visibilities.isVisibleWithAnyReceiver(this, from)) return true if (bindingContext == null || resolutionScope == null) return false diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt index 101b6c7e84b..b77aa2111fb 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt @@ -242,8 +242,8 @@ class MoveKotlinDeclarationsProcessor( fun DeclarationDescriptor.isVisibleIn(where: DeclarationDescriptor): Boolean { return when { this !is DeclarationDescriptorWithVisibility -> true - !Visibilities.isVisibleWithIrrelevantReceiver(this, where) -> false - this is ConstructorDescriptor -> Visibilities.isVisibleWithIrrelevantReceiver(containingDeclaration, where) + !Visibilities.isVisibleIgnoringReceiver(this, where) -> false + this is ConstructorDescriptor -> Visibilities.isVisibleIgnoringReceiver(containingDeclaration, where) else -> true } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/pullUpConflictsUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/pullUpConflictsUtils.kt index dddaf0917ac..c3c3a7684a2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/pullUpConflictsUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/pullUpConflictsUtils.kt @@ -150,7 +150,7 @@ private fun KotlinPullUpData.checkVisibility( if (targetDescriptor in memberDescriptors.values) return val target = (targetDescriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() ?: return if (targetDescriptor is DeclarationDescriptorWithVisibility - && !Visibilities.isVisibleWithIrrelevantReceiver(targetDescriptor, targetClassDescriptor)) { + && !Visibilities.isVisibleIgnoringReceiver(targetDescriptor, targetClassDescriptor)) { val message = RefactoringBundle.message( "0.uses.1.which.is.not.accessible.from.the.superclass", memberDescriptor.renderForConflicts(), diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/pushDown/pushDownConflictsUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/pushDown/pushDownConflictsUtils.kt index eed4fbacb10..6364e8813db 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/pushDown/pushDownConflictsUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/pushDown/pushDownConflictsUtils.kt @@ -196,7 +196,7 @@ private fun checkVisibility( fun reportConflictIfAny(targetDescriptor: DeclarationDescriptor) { val target = (targetDescriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() ?: return if (targetDescriptor is DeclarationDescriptorWithVisibility - && !Visibilities.isVisibleWithIrrelevantReceiver(targetDescriptor, targetClassDescriptor)) { + && !Visibilities.isVisibleIgnoringReceiver(targetDescriptor, targetClassDescriptor)) { val message = "${context.memberDescriptors[member]!!.renderForConflicts()} " + "uses ${targetDescriptor.renderForConflicts()}, " + "which is not accessible from the ${targetClassDescriptor.renderForConflicts()}" diff --git a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt index beb2fcb66fe..8e0aaf9253a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt +++ b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt @@ -253,7 +253,7 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper( fun isVisible(descriptor: DeclarationDescriptor): Boolean { if (descriptor !is DeclarationDescriptorWithVisibility) return true val visibility = descriptor.visibility - return !visibility.mustCheckInImports() || Visibilities.isVisibleWithIrrelevantReceiver(descriptor, filePackage) + return !visibility.mustCheckInImports() || Visibilities.isVisibleIgnoringReceiver(descriptor, filePackage) } val classNamesToImport = scopeToImport