Make DescriptorVisibility delegate to Visibility
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
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(): Visibility = Visibilities.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(): Visibility = Visibilities.Local
|
||||
}
|
||||
|
||||
object Public : EffectiveVisibility("public", publicApi = true) {
|
||||
override fun relation(other: EffectiveVisibility): Permissiveness =
|
||||
if (this == other) Permissiveness.SAME else Permissiveness.MORE
|
||||
|
||||
override fun toVisibility(): Visibility = Visibilities.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(): Visibility = Visibilities.Internal
|
||||
}
|
||||
|
||||
object PackagePrivate : InternalOrPackage(false) {
|
||||
override fun toVisibility(): Visibility = Visibilities.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(): Visibility = Visibilities.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(): Visibility = Visibilities.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(): Visibility = Visibilities.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(): Visibility = Visibilities.Private
|
||||
}
|
||||
|
||||
enum class Permissiveness {
|
||||
LESS,
|
||||
SAME,
|
||||
MORE,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
abstract fun relation(other: EffectiveVisibility): Permissiveness
|
||||
|
||||
abstract fun toVisibility(): Visibility
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,19 +6,51 @@
|
||||
package org.jetbrains.kotlin.descriptors
|
||||
|
||||
object Visibilities {
|
||||
object Private : Visibility("private", isPublicAPI = false)
|
||||
object Private : Visibility("private", isPublicAPI = false) {
|
||||
override fun mustCheckInImports(): Boolean = true
|
||||
}
|
||||
|
||||
object PrivateToThis : Visibility("private_to_this", isPublicAPI = false) {
|
||||
override val internalDisplayName: String
|
||||
get() = "private/*private to this*/"
|
||||
|
||||
override fun mustCheckInImports(): Boolean = true
|
||||
}
|
||||
|
||||
object Protected : Visibility("protected", isPublicAPI = true)
|
||||
object Internal : Visibility("internal", isPublicAPI = false)
|
||||
object Public : Visibility("public", isPublicAPI = true)
|
||||
object Local : Visibility("local", isPublicAPI = false)
|
||||
object InvisibleFake : Visibility("invisible_fake", isPublicAPI = false)
|
||||
object Unknown : Visibility("unknown", isPublicAPI = false)
|
||||
object Protected : Visibility("protected", isPublicAPI = true) {
|
||||
override fun mustCheckInImports(): Boolean = false
|
||||
}
|
||||
|
||||
object Internal : Visibility("internal", isPublicAPI = false) {
|
||||
override fun mustCheckInImports(): Boolean = true
|
||||
}
|
||||
|
||||
object Public : Visibility("public", isPublicAPI = true) {
|
||||
override fun mustCheckInImports(): Boolean = false
|
||||
}
|
||||
|
||||
object Local : Visibility("local", isPublicAPI = false) {
|
||||
override fun mustCheckInImports(): Boolean = true
|
||||
}
|
||||
|
||||
object Inherited : Visibility("inherited", isPublicAPI = false) {
|
||||
override fun mustCheckInImports(): Boolean {
|
||||
throw IllegalStateException("This method shouldn't be invoked for INHERITED visibility")
|
||||
}
|
||||
}
|
||||
|
||||
object InvisibleFake : Visibility("invisible_fake", isPublicAPI = false) {
|
||||
override fun mustCheckInImports(): Boolean = true
|
||||
|
||||
override val externalDisplayName: String
|
||||
get() = "invisible (private in a supertype)"
|
||||
}
|
||||
|
||||
object Unknown : Visibility("unknown", isPublicAPI = false) {
|
||||
override fun mustCheckInImports(): Boolean {
|
||||
throw IllegalStateException("This method shouldn't be invoked for UNKNOWN visibility")
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private val ORDERED_VISIBILITIES: Map<Visibility, Int> = buildMap {
|
||||
|
||||
@@ -12,11 +12,19 @@ abstract class Visibility protected constructor(
|
||||
open val internalDisplayName: String
|
||||
get() = name
|
||||
|
||||
final override fun toString() = internalDisplayName
|
||||
open val externalDisplayName: String
|
||||
get() = internalDisplayName
|
||||
|
||||
abstract fun mustCheckInImports(): Boolean
|
||||
|
||||
open fun compareTo(visibility: Visibility): Int? {
|
||||
return Visibilities.compareLocal(this, visibility)
|
||||
}
|
||||
|
||||
final override fun toString() = internalDisplayName
|
||||
|
||||
open fun normalize(): Visibility = this
|
||||
|
||||
// Should be overloaded in Java visibilities
|
||||
open fun customEffectiveVisibility(): EffectiveVisibility? = null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user