[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() isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual() isActual = modifiers.hasActual()
isInner = classWrapper.isInner() isInner = classWrapper.isInner()
isFromSealedClass = classWrapper.isSealed()
isFromEnumClass = classWrapper.isEnum()
} }
return PrimaryConstructor( return PrimaryConstructor(
@@ -713,6 +715,8 @@ class DeclarationsConverter(
isExpect = modifiers.hasExpect() isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual() isActual = modifiers.hasActual()
isInner = classWrapper.isInner() isInner = classWrapper.isInner()
isFromSealedClass = classWrapper.isSealed()
isFromEnumClass = classWrapper.isEnum()
} }
val target = FirFunctionTarget(labelName = null, isLambda = false) val target = FirFunctionTarget(labelName = null, isLambda = false)
@@ -40,11 +40,11 @@ class ClassWrapper(
return classKind == ClassKind.OBJECT return classKind == ClassKind.OBJECT
} }
private fun isSealed(): Boolean { fun isSealed(): Boolean {
return modifiers.hasModality(Modality.SEALED) return modifiers.hasModality(Modality.SEALED)
} }
private fun isEnum(): Boolean { fun isEnum(): Boolean {
return modifiers.isEnum() return modifiers.isEnum()
} }
@@ -472,6 +472,8 @@ class RawFirBuilder(session: FirSession, val baseScopeProvider: FirScopeProvider
isExpect = this@toFirConstructor?.hasExpectModifier() ?: false isExpect = this@toFirConstructor?.hasExpectModifier() ?: false
isActual = this@toFirConstructor?.hasActualModifier() ?: false isActual = this@toFirConstructor?.hasActualModifier() ?: false
isInner = owner.hasModifier(INNER_KEYWORD) isInner = owner.hasModifier(INNER_KEYWORD)
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD)
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
} }
return buildPrimaryConstructor { return buildPrimaryConstructor {
source = constructorSource source = constructorSource
@@ -842,6 +844,8 @@ class RawFirBuilder(session: FirSession, val baseScopeProvider: FirScopeProvider
isExpect = hasExpectModifier() isExpect = hasExpectModifier()
isActual = hasActualModifier() isActual = hasActualModifier()
isInner = owner.hasModifier(INNER_KEYWORD) isInner = owner.hasModifier(INNER_KEYWORD)
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD)
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
} }
symbol = FirConstructorSymbol(callableIdForClassConstructor()) symbol = FirConstructorSymbol(callableIdForClassConstructor())
delegatedConstructor = getDelegationCall().convert(delegatedSuperTypeRef, delegatedSelfTypeRef, hasPrimaryConstructor) delegatedConstructor = getDelegationCall().convert(delegatedSuperTypeRef, delegatedSelfTypeRef, hasPrimaryConstructor)
@@ -421,7 +421,7 @@ internal object CheckVisibility : CheckerStage() {
} }
Visibilities.PRIVATE, Visibilities.PRIVATE_TO_THIS -> { Visibilities.PRIVATE, Visibilities.PRIVATE_TO_THIS -> {
if (declaration.session == callInfo.session) { if (declaration.session == callInfo.session) {
if (ownerId == null) { if (ownerId == null || declaration is FirConstructor && declaration.status.isFromSealedClass) {
// Top-level: visible in file // Top-level: visible in file
candidateFile == useSiteFile candidateFile == useSiteFile
} else { } 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"); 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") @TestMetadata("simpleClass.kt")
public void testSimpleClass() throws Exception { public void testSimpleClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/simpleClass.kt"); 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"); 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") @TestMetadata("simpleClass.kt")
public void testSimpleClass() throws Exception { public void testSimpleClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/simpleClass.kt"); runTest("compiler/fir/resolve/testData/resolve/simpleClass.kt");
@@ -35,6 +35,8 @@ interface FirDeclarationStatus : FirElement {
val isData: Boolean val isData: Boolean
val isSuspend: Boolean val isSuspend: Boolean
val isStatic: 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) 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 isData: Boolean
override val isSuspend: Boolean override val isSuspend: Boolean
override val isStatic: 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) 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 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) { private enum class Modifier(val mask: Int) {
EXPECT(0x1), EXPECT(0x1),
ACTUAL(0x2), ACTUAL(0x2),
@@ -136,7 +148,9 @@ open class FirDeclarationStatusImpl(
COMPANION(0x800), COMPANION(0x800),
DATA(0x1000), DATA(0x1000),
SUSPEND(0x2000), SUSPEND(0x2000),
STATIC(0x4000) STATIC(0x4000),
FROM_SEALED(0x8000),
FROM_ENUM(0x10000)
} }
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {} override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
@@ -296,7 +296,8 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+modality +modality
generateBooleanFields( generateBooleanFields(
"expect", "actual", "override", "operator", "infix", "inline", "tailRec", "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 // TARGET_BACKEND: JVM
// WITH_RUNTIME // WITH_RUNTIME
@@ -60,7 +60,7 @@ FILE fqName:<root> fileName:/expectedSealedClass.kt
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Add $this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Add
CONSTRUCTOR visibility:public <> () returnType:<root>.Add [primary] CONSTRUCTOR visibility:public <> () returnType:<root>.Add [primary]
BLOCK_BODY 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]' 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] FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden: overridden: