[FIR] Check visibility correctly for sealed class in file

This commit is contained in:
Mikhail Glukhikh
2020-02-19 12:02:47 +03:00
parent ace259314b
commit 14fd1d3c9f
14 changed files with 62 additions and 7 deletions
@@ -645,6 +645,8 @@ class DeclarationsConverter(
isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual()
isInner = classWrapper.isInner()
isFromSealedClass = classWrapper.isSealed()
isFromEnumClass = classWrapper.isEnum()
}
return PrimaryConstructor(
@@ -713,6 +715,8 @@ class DeclarationsConverter(
isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual()
isInner = classWrapper.isInner()
isFromSealedClass = classWrapper.isSealed()
isFromEnumClass = classWrapper.isEnum()
}
val target = FirFunctionTarget(labelName = null, isLambda = false)
@@ -40,11 +40,11 @@ class ClassWrapper(
return classKind == ClassKind.OBJECT
}
private fun isSealed(): Boolean {
fun isSealed(): Boolean {
return modifiers.hasModality(Modality.SEALED)
}
private fun isEnum(): Boolean {
fun isEnum(): Boolean {
return modifiers.isEnum()
}
@@ -472,6 +472,8 @@ class RawFirBuilder(session: FirSession, val baseScopeProvider: FirScopeProvider
isExpect = this@toFirConstructor?.hasExpectModifier() ?: false
isActual = this@toFirConstructor?.hasActualModifier() ?: false
isInner = owner.hasModifier(INNER_KEYWORD)
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD)
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
}
return buildPrimaryConstructor {
source = constructorSource
@@ -842,6 +844,8 @@ class RawFirBuilder(session: FirSession, val baseScopeProvider: FirScopeProvider
isExpect = hasExpectModifier()
isActual = hasActualModifier()
isInner = owner.hasModifier(INNER_KEYWORD)
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD)
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
}
symbol = FirConstructorSymbol(callableIdForClassConstructor())
delegatedConstructor = getDelegationCall().convert(delegatedSuperTypeRef, delegatedSelfTypeRef, hasPrimaryConstructor)
@@ -421,7 +421,7 @@ internal object CheckVisibility : CheckerStage() {
}
Visibilities.PRIVATE, Visibilities.PRIVATE_TO_THIS -> {
if (declaration.session == callInfo.session) {
if (ownerId == null) {
if (ownerId == null || declaration is FirConstructor && declaration.status.isFromSealedClass) {
// Top-level: visible in file
candidateFile == useSiteFile
} else {
+3
View File
@@ -0,0 +1,3 @@
sealed class Foo(val value: String)
class Bar : Foo("OK")
+16
View File
@@ -0,0 +1,16 @@
FILE: sealedClass.kt
public sealed class Foo : R|kotlin/Any| {
private constructor(value: R|kotlin/String|): R|Foo| {
super<R|kotlin/Any|>()
}
public final val value: R|kotlin/String| = R|<local>/value|
public get(): R|kotlin/String|
}
public final class Bar : R|Foo| {
public constructor(): R|Bar| {
super<R|Foo|>(String(OK))
}
}
@@ -263,6 +263,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/recursiveCallOnWhenWithSealedClass.kt");
}
@TestMetadata("sealedClass.kt")
public void testSealedClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/sealedClass.kt");
}
@TestMetadata("simpleClass.kt")
public void testSimpleClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/simpleClass.kt");
@@ -263,6 +263,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/recursiveCallOnWhenWithSealedClass.kt");
}
@TestMetadata("sealedClass.kt")
public void testSealedClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/sealedClass.kt");
}
@TestMetadata("simpleClass.kt")
public void testSimpleClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/simpleClass.kt");
@@ -35,6 +35,8 @@ interface FirDeclarationStatus : FirElement {
val isData: Boolean
val isSuspend: Boolean
val isStatic: Boolean
val isFromSealedClass: Boolean
val isFromEnumClass: Boolean
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDeclarationStatus(this, data)
}
@@ -34,6 +34,8 @@ interface FirResolvedDeclarationStatus : FirDeclarationStatus {
override val isData: Boolean
override val isSuspend: Boolean
override val isStatic: Boolean
override val isFromSealedClass: Boolean
override val isFromEnumClass: Boolean
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedDeclarationStatus(this, data)
}
@@ -121,6 +121,18 @@ open class FirDeclarationStatusImpl(
this[STATIC] = value
}
override var isFromSealedClass: Boolean
get() = this[FROM_SEALED]
set(value) {
this[FROM_SEALED] = value
}
override var isFromEnumClass: Boolean
get() = this[FROM_ENUM]
set(value) {
this[FROM_ENUM] = value
}
private enum class Modifier(val mask: Int) {
EXPECT(0x1),
ACTUAL(0x2),
@@ -136,7 +148,9 @@ open class FirDeclarationStatusImpl(
COMPANION(0x800),
DATA(0x1000),
SUSPEND(0x2000),
STATIC(0x4000)
STATIC(0x4000),
FROM_SEALED(0x8000),
FROM_ENUM(0x10000)
}
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
@@ -296,7 +296,8 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+modality
generateBooleanFields(
"expect", "actual", "override", "operator", "infix", "inline", "tailRec",
"external", "const", "lateInit", "inner", "companion", "data", "suspend", "static"
"external", "const", "lateInit", "inner", "companion", "data", "suspend", "static",
"fromSealedClass", "fromEnumClass"
)
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -60,7 +60,7 @@ FILE fqName:<root> fileName:/expectedSealedClass.kt
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Add
CONSTRUCTOR visibility:public <> () returnType:<root>.Add [primary]
BLOCK_BODY
ERROR_CALL 'Cannot find delegated constructor call' type=<root>.Add
DELEGATING_CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.Ops'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[<root>.Ops]'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden: