Make DescriptorVisibility delegate to Visibility

This commit is contained in:
Dmitriy Novozhilov
2020-09-01 17:01:33 +03:00
parent a05d6da43b
commit 696f089b3e
14 changed files with 206 additions and 227 deletions
@@ -33,12 +33,7 @@ import java.util.*;
public class DescriptorVisibilities {
@NotNull
public static final DescriptorVisibility PRIVATE = new DescriptorVisibility("private", false) {
@Override
public boolean mustCheckInImports() {
return true;
}
public static final DescriptorVisibility PRIVATE = new DelegatedDescriptorVisibility(Visibilities.Private.INSTANCE) {
private boolean hasContainingSourceFile(@NotNull DeclarationDescriptor descriptor) {
return DescriptorUtils.getContainingSourceFile(descriptor) != SourceFile.NO_SOURCE_FILE;
}
@@ -102,7 +97,7 @@ public class DescriptorVisibilities {
* }
*/
@NotNull
public static final DescriptorVisibility PRIVATE_TO_THIS = new DescriptorVisibility("private_to_this", false) {
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)) {
@@ -118,26 +113,10 @@ public class DescriptorVisibilities {
}
return false;
}
@Override
public boolean mustCheckInImports() {
return true;
}
@NotNull
@Override
public String getInternalDisplayName() {
return "private/*private to this*/";
}
};
@NotNull
public static final DescriptorVisibility PROTECTED = new DescriptorVisibility("protected", true) {
@Override
public boolean mustCheckInImports() {
return false;
}
public static final DescriptorVisibility PROTECTED = new DelegatedDescriptorVisibility(Visibilities.Protected.INSTANCE) {
@Override
public boolean isVisible(
@Nullable ReceiverValue receiver,
@@ -198,12 +177,7 @@ public class DescriptorVisibilities {
};
@NotNull
public static final DescriptorVisibility INTERNAL = new DescriptorVisibility("internal", false) {
@Override
public boolean mustCheckInImports() {
return true;
}
public static final DescriptorVisibility INTERNAL = new DelegatedDescriptorVisibility(Visibilities.Internal.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
ModuleDescriptor whatModule = DescriptorUtils.getContainingModule(what);
@@ -220,12 +194,7 @@ public class DescriptorVisibilities {
};
@NotNull
public static final DescriptorVisibility PUBLIC = new DescriptorVisibility("public", true) {
@Override
public boolean mustCheckInImports() {
return false;
}
public static final DescriptorVisibility PUBLIC = new DelegatedDescriptorVisibility(Visibilities.Public.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
return true;
@@ -233,12 +202,7 @@ public class DescriptorVisibilities {
};
@NotNull
public static final DescriptorVisibility LOCAL = new DescriptorVisibility("local", false) {
@Override
public boolean mustCheckInImports() {
return true;
}
public static final DescriptorVisibility LOCAL = new DelegatedDescriptorVisibility(Visibilities.Local.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
throw new IllegalStateException("This method shouldn't be invoked for LOCAL visibility");
@@ -246,12 +210,7 @@ public class DescriptorVisibilities {
};
@NotNull
public static final DescriptorVisibility INHERITED = new DescriptorVisibility("inherited", false) {
@Override
public boolean mustCheckInImports() {
throw new IllegalStateException("This method shouldn't be invoked for INHERITED visibility");
}
public static final DescriptorVisibility INHERITED = new DelegatedDescriptorVisibility(Visibilities.Inherited.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
throw new IllegalStateException("Visibility is unknown yet"); //This method shouldn't be invoked for INHERITED visibility
@@ -260,33 +219,17 @@ public class DescriptorVisibilities {
/* Visibility for fake override invisible members (they are created for better error reporting) */
@NotNull
public static final DescriptorVisibility INVISIBLE_FAKE = new DescriptorVisibility("invisible_fake", false) {
@Override
public boolean mustCheckInImports() {
return true;
}
public static final DescriptorVisibility INVISIBLE_FAKE = new DelegatedDescriptorVisibility(Visibilities.InvisibleFake.INSTANCE) {
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
return false;
}
@Override
@NotNull
public String getExternalDisplayName() {
return "invisible (private in a supertype)";
}
};
// Currently used as default visibility of FunctionDescriptor
// It's needed to prevent NPE when requesting non-nullable visibility of descriptor before `initialize` has been called
@NotNull
public static final DescriptorVisibility UNKNOWN = new DescriptorVisibility("unknown", false) {
@Override
public boolean mustCheckInImports() {
throw new IllegalStateException("This method shouldn't be invoked for UNKNOWN visibility");
}
public static final DescriptorVisibility UNKNOWN = new DelegatedDescriptorVisibility(Visibilities.Unknown.INSTANCE) {
@Override
public boolean isVisible(
@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from
@@ -473,4 +416,32 @@ public class DescriptorVisibilities {
Iterator<ModuleVisibilityHelper> iterator = ServiceLoader.load(ModuleVisibilityHelper.class, ModuleVisibilityHelper.class.getClassLoader()).iterator();
MODULE_VISIBILITY_HELPER = iterator.hasNext() ? iterator.next() : ModuleVisibilityHelper.EMPTY.INSTANCE;
}
@NotNull
private static final Map<Visibility, DescriptorVisibility> visibilitiesMapping = new HashMap<Visibility, DescriptorVisibility>();
private static void recordVisibilityMapping(DescriptorVisibility visibility) {
visibilitiesMapping.put(visibility.getDelegate(), visibility);
}
static {
recordVisibilityMapping(PRIVATE);
recordVisibilityMapping(PRIVATE_TO_THIS);
recordVisibilityMapping(PROTECTED);
recordVisibilityMapping(INTERNAL);
recordVisibilityMapping(PUBLIC);
recordVisibilityMapping(LOCAL);
recordVisibilityMapping(INHERITED);
recordVisibilityMapping(INVISIBLE_FAKE);
recordVisibilityMapping(UNKNOWN);
}
@NotNull
public static DescriptorVisibility toDescriptorVisibility(@NotNull Visibility visibility) {
DescriptorVisibility correspondingVisibility = visibilitiesMapping.get(visibility);
if (correspondingVisibility == null) {
throw new IllegalArgumentException("Inapplicable visibility: " + visibility);
}
return correspondingVisibility;
}
}
@@ -18,10 +18,15 @@ package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
abstract class DescriptorVisibility protected constructor(
val name: String,
abstract class DescriptorVisibility protected constructor() {
abstract val delegate: Visibility
val name: String
get() = delegate.name
val isPublicAPI: Boolean
) {
get() = delegate.isPublicAPI
/**
* @param receiver can be used to determine callee accessibility for some special receiver value
*
@@ -52,22 +57,36 @@ abstract class DescriptorVisibility protected constructor(
/**
* @return null if the answer is unknown
*/
protected open fun compareTo(visibility: DescriptorVisibility): Int? {
return DescriptorVisibilities.compareLocal(this, visibility)
fun compareTo(visibility: DescriptorVisibility): Int? {
return delegate.compareTo(visibility.delegate)
}
// internal representation for descriptors
open val internalDisplayName: String
get() = name
abstract val internalDisplayName: String
// external representation for diagnostics
open val externalDisplayName: String
get() = internalDisplayName
abstract val externalDisplayName: String
final override fun toString() = internalDisplayName
final override fun toString(): String = delegate.toString()
open fun normalize(): DescriptorVisibility = this
abstract fun normalize(): DescriptorVisibility
// Should be overloaded in Java visibilities
open fun customEffectiveVisibility(): EffectiveVisibility? = null
fun customEffectiveVisibility(): EffectiveVisibility? = delegate.customEffectiveVisibility()
}
abstract class DelegatedDescriptorVisibility(override val delegate: Visibility) : DescriptorVisibility() {
override fun mustCheckInImports(): Boolean {
return delegate.mustCheckInImports()
}
// internal representation for descriptors
override val internalDisplayName: String
get() = delegate.internalDisplayName
// external representation for diagnostics
override val externalDisplayName: String
get() = delegate.externalDisplayName
override fun normalize(): DescriptorVisibility = DescriptorVisibilities.toDescriptorVisibility(delegate.normalize())
}
@@ -1,241 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.descriptors.EffectiveVisibility.Permissiveness
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = false, val privateApi: Boolean = false) {
override fun toString() = name
// Public
// /--/ | \-------------\
// Protected(Base) | \
// | Protected(Other) Internal = PackagePrivate
// Protected(Derived) | / \
// | | / InternalProtected(Base)
// ProtectedBound / \
// \ / /InternalProtected(Derived)
// \InternalProtectedBound/
// |
// Private = Local
object Private : EffectiveVisibility("private", privateApi = true) {
override fun relation(other: EffectiveVisibility): Permissiveness =
if (this == other || Local == other) Permissiveness.SAME else Permissiveness.LESS
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.PRIVATE
}
// Effectively same as Private
object Local : EffectiveVisibility("local") {
override fun relation(other: EffectiveVisibility): Permissiveness =
if (this == other || Private == other) Permissiveness.SAME else Permissiveness.LESS
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.LOCAL
}
object Public : EffectiveVisibility("public", publicApi = true) {
override fun relation(other: EffectiveVisibility): Permissiveness =
if (this == other) Permissiveness.SAME else Permissiveness.MORE
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.PUBLIC
}
abstract class InternalOrPackage protected constructor(internal: Boolean) : EffectiveVisibility(
if (internal) "internal" else "public/*package*/"
) {
override fun relation(other: EffectiveVisibility): Permissiveness = when (other) {
Public -> Permissiveness.LESS
Private, Local, InternalProtectedBound, is InternalProtected -> Permissiveness.MORE
is InternalOrPackage -> Permissiveness.SAME
ProtectedBound, is Protected -> Permissiveness.UNKNOWN
}
override fun lowerBound(other: EffectiveVisibility) = when (other) {
Public -> this
Private, Local, InternalProtectedBound, is InternalOrPackage, is InternalProtected -> other
is Protected -> InternalProtected(other.containerTypeConstructor, other.typeContext)
ProtectedBound -> InternalProtectedBound
}
}
object Internal : InternalOrPackage(true) {
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.INTERNAL
}
object PackagePrivate : InternalOrPackage(false) {
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.PRIVATE
}
class Protected(
val containerTypeConstructor: TypeConstructorMarker?,
val typeContext: AbstractTypeCheckerContext
) : EffectiveVisibility("protected", publicApi = true) {
override fun equals(other: Any?) = (other is Protected && containerTypeConstructor == other.containerTypeConstructor)
override fun hashCode() = containerTypeConstructor?.hashCode() ?: 0
override fun toString() = "${super.toString()} (in ${containerTypeConstructor ?: '?'})"
override fun relation(other: EffectiveVisibility): Permissiveness = when (other) {
Public -> Permissiveness.LESS
Private, Local, ProtectedBound, InternalProtectedBound -> Permissiveness.MORE
is Protected -> containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeContext)
is InternalProtected -> when (containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeContext)) {
// Protected never can be less permissive than internal & protected
Permissiveness.SAME, Permissiveness.MORE -> Permissiveness.MORE
Permissiveness.UNKNOWN, Permissiveness.LESS -> Permissiveness.UNKNOWN
}
is InternalOrPackage -> Permissiveness.UNKNOWN
}
override fun lowerBound(other: EffectiveVisibility) = when (other) {
Public -> this
Private, Local, ProtectedBound, InternalProtectedBound -> other
is Protected -> when (relation(other)) {
Permissiveness.SAME, Permissiveness.MORE -> this
Permissiveness.LESS -> other
Permissiveness.UNKNOWN -> ProtectedBound
}
is InternalProtected -> when (relation(other)) {
Permissiveness.LESS -> other
else -> InternalProtectedBound
}
is InternalOrPackage -> InternalProtected(containerTypeConstructor, typeContext)
}
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.PROTECTED
}
// Lower bound for all protected visibilities
object ProtectedBound : EffectiveVisibility("protected (in different classes)", publicApi = true) {
override fun relation(other: EffectiveVisibility): Permissiveness = when (other) {
Public, is Protected -> Permissiveness.LESS
Private, Local, InternalProtectedBound -> Permissiveness.MORE
ProtectedBound -> Permissiveness.SAME
is InternalOrPackage, is InternalProtected -> Permissiveness.UNKNOWN
}
override fun lowerBound(other: EffectiveVisibility) = when (other) {
Public, is Protected -> this
Private, Local, ProtectedBound, InternalProtectedBound -> other
is InternalOrPackage, is InternalProtected -> InternalProtectedBound
}
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.PROTECTED
}
// Lower bound for internal and protected(C)
class InternalProtected(
val containerTypeConstructor: TypeConstructorMarker?,
val typeContext: AbstractTypeCheckerContext,
) : EffectiveVisibility("internal & protected") {
override fun equals(other: Any?) = (other is InternalProtected && containerTypeConstructor == other.containerTypeConstructor)
override fun hashCode() = containerTypeConstructor?.hashCode() ?: 0
override fun toString() = "${super.toString()} (in ${containerTypeConstructor ?: '?'})"
override fun relation(other: EffectiveVisibility): Permissiveness = when (other) {
Public, is InternalOrPackage -> Permissiveness.LESS
Private, Local, InternalProtectedBound -> Permissiveness.MORE
is InternalProtected -> containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeContext)
is Protected -> when (containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeContext)) {
// Internal & protected never can be more permissive than just protected
Permissiveness.SAME, Permissiveness.LESS -> Permissiveness.LESS
Permissiveness.UNKNOWN, Permissiveness.MORE -> Permissiveness.UNKNOWN
}
ProtectedBound -> Permissiveness.UNKNOWN
}
override fun lowerBound(other: EffectiveVisibility) = when (other) {
Public, is InternalOrPackage -> this
Private, Local, InternalProtectedBound -> other
is Protected, is InternalProtected -> when (relation(other)) {
Permissiveness.SAME, Permissiveness.MORE -> this
Permissiveness.LESS -> other
Permissiveness.UNKNOWN -> InternalProtectedBound
}
ProtectedBound -> InternalProtectedBound
}
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.PRIVATE
}
// Lower bound for internal and protected lower bound
object InternalProtectedBound : EffectiveVisibility("internal & protected (in different classes)") {
override fun relation(other: EffectiveVisibility): Permissiveness = when (other) {
Public, is Protected, is InternalProtected, ProtectedBound, is InternalOrPackage -> Permissiveness.LESS
Private, Local -> Permissiveness.MORE
InternalProtectedBound -> Permissiveness.SAME
}
override fun toVisibility(): DescriptorVisibility = DescriptorVisibilities.PRIVATE
}
enum class Permissiveness {
LESS,
SAME,
MORE,
UNKNOWN
}
abstract fun relation(other: EffectiveVisibility): Permissiveness
abstract fun toVisibility(): DescriptorVisibility
internal open fun lowerBound(other: EffectiveVisibility) = when (relation(other)) {
Permissiveness.SAME, Permissiveness.LESS -> this
Permissiveness.MORE -> other
Permissiveness.UNKNOWN -> Private
}
}
enum class RelationToType(val description: String) {
CONSTRUCTOR(""),
CONTAINER(" containing declaration"),
ARGUMENT(" argument"),
ARGUMENT_CONTAINER(" argument containing declaration");
fun containerRelation() = when (this) {
CONSTRUCTOR, CONTAINER -> CONTAINER
ARGUMENT, ARGUMENT_CONTAINER -> ARGUMENT_CONTAINER
}
override fun toString() = description
}
internal fun containerRelation(
first: TypeConstructorMarker?,
second: TypeConstructorMarker?,
typeContext: AbstractTypeCheckerContext
): Permissiveness {
return when {
first == null || second == null -> Permissiveness.UNKNOWN
first == second -> Permissiveness.SAME
AbstractTypeChecker.isSubtypeOfClass(typeContext, first, second) -> Permissiveness.LESS
AbstractTypeChecker.isSubtypeOfClass(typeContext, second, first) -> Permissiveness.MORE
else -> Permissiveness.UNKNOWN
}
}
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
fun EffectiveVisibility.toDescriptorVisibility(): DescriptorVisibility = DescriptorVisibilities.toDescriptorVisibility(toVisibility())
fun DescriptorVisibility.effectiveVisibility(
descriptor: DeclarationDescriptor,
checkPublishedApi: Boolean = false