[FIR] Make enum entry initializer lazy in RawFirBuilder

Third step for KT-52615

Merge-request: KT-MR-7769
Merged-by: Egor Kulikov <Egor.Kulikov@jetbrains.com>
This commit is contained in:
Egor Kulikov
2022-11-23 18:55:21 +00:00
committed by Space Team
parent 194d1cfccf
commit 3e8f7b8ee4
16 changed files with 328 additions and 176 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
@@ -118,6 +119,20 @@ internal object FirLazyBodiesCalculator {
}
}
fun calculateLazyInitializerForEnumEntry(designation: FirDeclarationDesignation) {
val enumEntry = designation.declaration as FirEnumEntry
require(enumEntry.initializer is FirLazyExpression)
val newEntry = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = enumEntry.moduleData.session,
scopeProvider = enumEntry.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = enumEntry.psi as KtEnumEntry,
) as FirEnumEntry
enumEntry.apply {
replaceInitializer(newEntry.initializer)
}
}
fun needCalculatingLazyBodyForProperty(firProperty: FirProperty): Boolean =
firProperty.getter?.body is FirLazyBlock
|| firProperty.setter?.body is FirLazyBlock
@@ -179,4 +194,12 @@ private object FirLazyBodiesCalculatorTransformer : FirTransformer<PersistentLis
override fun transformPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: PersistentList<FirDeclaration>): FirStatement {
return propertyAccessor.also { transformProperty(it.propertySymbol.fir, data) }
}
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: PersistentList<FirDeclaration>): FirStatement {
if (enumEntry.initializer is FirLazyExpression) {
val designation = FirDeclarationDesignation(data, enumEntry)
FirLazyBodiesCalculator.calculateLazyInitializerForEnumEntry(designation)
}
return enumEntry
}
}
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.BodyBuildingMode
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
@@ -31,7 +33,6 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
private val functionsToRebind: Set<FirFunction>? = null,
private val replacementApplier: RawFirReplacement.Applier? = null
) : RawFirBuilder(session, baseScopeProvider, bodyBuildingMode = BodyBuildingMode.NORMAL) {
companion object {
fun buildWithReplacement(
session: FirSession,
@@ -95,7 +96,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
}
}
private inner class VisitorWithReplacement : Visitor() {
private inner class VisitorWithReplacement(private val containingClass: FirRegularClass?) : Visitor() {
override fun convertElement(element: KtElement): FirElement? =
super.convertElement(replacementApplier?.tryReplace(element) ?: element)
@@ -130,11 +131,27 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
additionalAnnotations = additionalAnnotations
)
}
override fun visitEnumEntry(enumEntry: KtEnumEntry, data: Unit?): FirElement {
val owner = containingClass ?: buildErrorWithAttachment("Enum entry outside of class") {
withPsiEntry("enumEntry", enumEntry)
}
val classOrObject = owner.psi as KtClassOrObject
val primaryConstructor = classOrObject.primaryConstructor
val ownerClassHasDefaultConstructor =
primaryConstructor?.valueParameters?.isEmpty() ?: classOrObject.secondaryConstructors.let { constructors ->
constructors.isEmpty() || constructors.any { it.valueParameters.isEmpty() }
}
val typeParameters = mutableListOf<FirTypeParameterRef>()
context.appendOuterTypeParameters(ignoreLastLevel = false, typeParameters)
val selfType = classOrObject.toDelegatedSelfType(typeParameters, owner.symbol)
return enumEntry.toFirEnumEntry(selfType, ownerClassHasDefaultConstructor)
}
}
private fun moveNext(iterator: Iterator<FirDeclaration>, containingClass: FirRegularClass?): FirDeclaration {
if (!iterator.hasNext()) {
val visitor = VisitorWithReplacement()
val visitor = VisitorWithReplacement(containingClass)
return when (declarationToBuild) {
is KtProperty -> {
val ownerSymbol = containingClass?.symbol
@@ -105,6 +105,12 @@ public class FirLazyBodiesCalculatorTestGenerated extends AbstractFirLazyBodiesC
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums2.kt");
}
@Test
@TestMetadata("enums3.kt")
public void testEnums3() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums3.kt");
}
@Test
@TestMetadata("expectActual.kt")
public void testExpectActual() throws Exception {
@@ -101,6 +101,11 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums2.kt");
}
@TestMetadata("enums3.kt")
public void testEnums3() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums3.kt");
}
@TestMetadata("expectActual.kt")
public void testExpectActual() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/expectActual.kt");
@@ -306,9 +306,7 @@ open class RawFirBuilder(
primaryConstructor?.valueParameters?.isEmpty() ?: owner.secondaryConstructors.let { constructors ->
constructors.isEmpty() || constructors.any { it.valueParameters.isEmpty() }
}
disabledLazyMode {
toFirEnumEntry(delegatedSelfType, ownerClassHasDefaultConstructor)
}
toFirEnumEntry(delegatedSelfType, ownerClassHasDefaultConstructor)
}
is KtProperty -> {
convertProperty(
@@ -1003,7 +1001,7 @@ open class RawFirBuilder(
}
}
private fun KtEnumEntry.toFirEnumEntry(
protected fun KtEnumEntry.toFirEnumEntry(
delegatedEnumSelfTypeRef: FirResolvedTypeRef,
ownerClassHasDefaultConstructor: Boolean
): FirDeclaration {
@@ -1026,49 +1024,55 @@ open class RawFirBuilder(
return@buildEnumEntry
}
extractAnnotationsTo(this)
initializer = withChildClassName(nameAsSafeName, isExpect = false) {
buildAnonymousObjectExpression {
val enumEntrySource = toFirSourceElement(KtFakeSourceElementKind.EnumInitializer)
source = enumEntrySource
anonymousObject = buildAnonymousObject {
initializer = buildOrLazyExpression(toFirSourceElement(KtFakeSourceElementKind.EnumInitializer)) {
withChildClassName(nameAsSafeName, isExpect = false) {
buildAnonymousObjectExpression {
val enumEntrySource = toFirSourceElement(KtFakeSourceElementKind.EnumInitializer)
source = enumEntrySource
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
classKind = ClassKind.ENUM_ENTRY
scopeProvider = this@RawFirBuilder.baseScopeProvider
symbol = FirAnonymousObjectSymbol()
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
anonymousObject = buildAnonymousObject {
source = enumEntrySource
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
classKind = ClassKind.ENUM_ENTRY
scopeProvider = this@RawFirBuilder.baseScopeProvider
symbol = FirAnonymousObjectSymbol()
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
val delegatedEntrySelfType = buildResolvedTypeRef {
type =
ConeClassLikeTypeImpl(this@buildAnonymousObject.symbol.toLookupTag(), emptyArray(), isNullable = false)
}
registerSelfType(delegatedEntrySelfType)
val delegatedEntrySelfType = buildResolvedTypeRef {
type =
ConeClassLikeTypeImpl(
this@buildAnonymousObject.symbol.toLookupTag(),
emptyArray(),
isNullable = false
)
}
registerSelfType(delegatedEntrySelfType)
superTypeRefs += delegatedEnumSelfTypeRef
val superTypeCallEntry = superTypeListEntries.firstIsInstanceOrNull<KtSuperTypeCallEntry>()
val correctedEnumSelfTypeRef = buildResolvedTypeRef {
source = superTypeCallEntry?.calleeExpression?.typeReference?.toFirSourceElement()
type = delegatedEnumSelfTypeRef.type
}
declarations += primaryConstructor.toFirConstructor(
superTypeCallEntry,
correctedEnumSelfTypeRef,
delegatedEntrySelfType,
owner = ktEnumEntry,
typeParameters,
containingClassIsExpectClass
)
// Use ANONYMOUS_OBJECT_NAME for the owner class id for enum entry declarations (see KT-42351)
withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) {
for (declaration in ktEnumEntry.declarations) {
declarations += declaration.toFirDeclaration(
correctedEnumSelfTypeRef,
delegatedSelfType = delegatedEntrySelfType,
ktEnumEntry,
ownerClassBuilder = this,
ownerTypeParameters = emptyList()
)
superTypeRefs += delegatedEnumSelfTypeRef
val superTypeCallEntry = superTypeListEntries.firstIsInstanceOrNull<KtSuperTypeCallEntry>()
val correctedEnumSelfTypeRef = buildResolvedTypeRef {
source = superTypeCallEntry?.calleeExpression?.typeReference?.toFirSourceElement()
type = delegatedEnumSelfTypeRef.type
}
declarations += primaryConstructor.toFirConstructor(
superTypeCallEntry,
correctedEnumSelfTypeRef,
delegatedEntrySelfType,
owner = ktEnumEntry,
typeParameters,
containingClassIsExpectClass
)
// Use ANONYMOUS_OBJECT_NAME for the owner class id for enum entry declarations (see KT-42351)
withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) {
for (declaration in ktEnumEntry.declarations) {
declarations += declaration.toFirDeclaration(
correctedEnumSelfTypeRef,
delegatedSelfType = delegatedEntrySelfType,
ktEnumEntry,
ownerClassBuilder = this,
ownerTypeParameters = emptyList()
)
}
}
}
}
@@ -29,20 +29,8 @@ FILE: annotation.kt
super<R|kotlin/Enum<My>|>()
}
@base() public final static enum entry FIRST: R|My| = object : R|My| {
private constructor(): R|<anonymous>| {
super<R|My|>()
}
}
@base() public final static enum entry SECOND: R|My| = object : R|My| {
private constructor(): R|<anonymous>| {
super<R|My|>()
}
}
@base() public final static enum entry FIRST: R|My| = LAZY_EXPRESSION
@base() public final static enum entry SECOND: R|My| = LAZY_EXPRESSION
public final static fun values(): R|kotlin/Array<My>| {
}
@@ -13,17 +13,7 @@ FILE: constructorInObject.kt
super<R|kotlin/Enum<B>|>()
}
public final static enum entry X: R|B| = object : R|B| {
private constructor(): R|<anonymous>| {
super<R|B|>()
}
public? constructor(): R|<anonymous>| {
super<R|B|>()
}
}
public final static enum entry X: R|B| = LAZY_EXPRESSION
public final static fun values(): R|kotlin/Array<B>| {
}
@@ -28,39 +28,9 @@ FILE: enums.kt
internal final? val r: Double = R|<local>/r|
internal get(): Double
public final static enum entry MERCURY: R|Planet| = object : R|Planet| {
private constructor(): R|<anonymous>| {
super<R|Planet|>(Double(1.0), Double(2.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Hello!!!))
}
}
public final static enum entry VENERA: R|Planet| = object : R|Planet| {
private constructor(): R|<anonymous>| {
super<R|Planet|>(Double(3.0), Double(4.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Ola!!!))
}
}
public final static enum entry EARTH: R|Planet| = object : R|Planet| {
private constructor(): R|<anonymous>| {
super<R|Planet|>(Double(5.0), Double(6.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Privet!!!))
}
}
public final static enum entry MERCURY: R|Planet| = LAZY_EXPRESSION
public final static enum entry VENERA: R|Planet| = LAZY_EXPRESSION
public final static enum entry EARTH: R|Planet| = LAZY_EXPRESSION
public? final? val g: Double = LAZY_EXPRESSION
public? get(): Double
@@ -94,55 +64,13 @@ FILE: enums.kt
public? final? val signature: String = R|<local>/signature|
public? get(): String
public final static enum entry FIX_STACK_BEFORE_JUMP: R|PseudoInsn| = object : R|PseudoInsn| {
private constructor(): R|<anonymous>| {
super<R|PseudoInsn|>()
}
}
public final static enum entry FAKE_ALWAYS_TRUE_IFEQ: R|PseudoInsn| = object : R|PseudoInsn| {
private constructor(): R|<anonymous>| {
super<R|PseudoInsn|>(String(()I))
}
}
public final static enum entry FAKE_ALWAYS_FALSE_IFEQ: R|PseudoInsn| = object : R|PseudoInsn| {
private constructor(): R|<anonymous>| {
super<R|PseudoInsn|>(String(()I))
}
}
public final static enum entry SAVE_STACK_BEFORE_TRY: R|PseudoInsn| = object : R|PseudoInsn| {
private constructor(): R|<anonymous>| {
super<R|PseudoInsn|>()
}
}
public final static enum entry RESTORE_STACK_IN_TRY_CATCH: R|PseudoInsn| = object : R|PseudoInsn| {
private constructor(): R|<anonymous>| {
super<R|PseudoInsn|>()
}
}
public final static enum entry STORE_NOT_NULL: R|PseudoInsn| = object : R|PseudoInsn| {
private constructor(): R|<anonymous>| {
super<R|PseudoInsn|>()
}
}
public final static enum entry AS_NOT_NULL: R|PseudoInsn| = object : R|PseudoInsn| {
private constructor(): R|<anonymous>| {
super<R|PseudoInsn|>(String((Ljava/lang/Object;)Ljava/lang/Object;))
}
}
public final static enum entry FIX_STACK_BEFORE_JUMP: R|PseudoInsn| = LAZY_EXPRESSION
public final static enum entry FAKE_ALWAYS_TRUE_IFEQ: R|PseudoInsn| = LAZY_EXPRESSION
public final static enum entry FAKE_ALWAYS_FALSE_IFEQ: R|PseudoInsn| = LAZY_EXPRESSION
public final static enum entry SAVE_STACK_BEFORE_TRY: R|PseudoInsn| = LAZY_EXPRESSION
public final static enum entry RESTORE_STACK_IN_TRY_CATCH: R|PseudoInsn| = LAZY_EXPRESSION
public final static enum entry STORE_NOT_NULL: R|PseudoInsn| = LAZY_EXPRESSION
public final static enum entry AS_NOT_NULL: R|PseudoInsn| = LAZY_EXPRESSION
public? final? fun emit(): R|kotlin/Unit| { LAZY_BLOCK }
public final static fun values(): R|kotlin/Array<PseudoInsn>| {
@@ -21,28 +21,8 @@ FILE: enums2.kt
public? final? val x: Some = R|<local>/x|
public? get(): Some
public final static enum entry FIRST: R|SomeEnum| = object : R|SomeEnum| {
private constructor(): R|<anonymous>| {
super<R|SomeEnum|>(O1#)
}
public? open? override fun check(y: Some): Boolean {
^check Boolean(true)
}
}
public final static enum entry SECOND: R|SomeEnum| = object : R|SomeEnum| {
private constructor(): R|<anonymous>| {
super<R|SomeEnum|>(O2#)
}
public? open? override fun check(y: Some): Boolean {
^check ==(y#, O2#)
}
}
public final static enum entry FIRST: R|SomeEnum| = LAZY_EXPRESSION
public final static enum entry SECOND: R|SomeEnum| = LAZY_EXPRESSION
public? abstract fun check(y: Some): Boolean
public final static fun values(): R|kotlin/Array<SomeEnum>| {
@@ -0,0 +1,29 @@
class C {
init {
enum class Planet(val m: Double, internal val r: Double) {
MERCURY(1.0, 2.0) {
override fun sayHello() {
println("Hello!!!")
}
},
VENERA(3.0, 4.0) {
override fun sayHello() {
println("Ola!!!")
}
},
EARTH(5.0, 6.0) {
override fun sayHello() {
println("Privet!!!")
}
};
val g: Double = G * m / (r * r)
abstract fun sayHello()
companion object {
const val G = 6.67e-11
}
}
}
}
@@ -0,0 +1,80 @@
FILE: enums3.kt
public? final? class C : R|kotlin/Any| {
public? constructor(): R|C| {
super<R|kotlin/Any|>()
}
init {
local final? enum class Planet : R|kotlin/Enum<C.Planet>| {
private constructor(m: Double, r: Double): R|C.Planet| {
super<R|kotlin/Enum<C.Planet>|>()
}
public? final? val m: Double = R|<local>/m|
public? get(): Double
internal final? val r: Double = R|<local>/r|
internal get(): Double
public final static enum entry MERCURY: R|C.Planet| = object : R|C.Planet| {
private constructor(): R|<anonymous>| {
super<R|C.Planet|>(Double(1.0), Double(2.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Hello!!!))
}
}
public final static enum entry VENERA: R|C.Planet| = object : R|C.Planet| {
private constructor(): R|<anonymous>| {
super<R|C.Planet|>(Double(3.0), Double(4.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Ola!!!))
}
}
public final static enum entry EARTH: R|C.Planet| = object : R|C.Planet| {
private constructor(): R|<anonymous>| {
super<R|C.Planet|>(Double(5.0), Double(6.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Privet!!!))
}
}
public? final? val g: Double = G#.times#(m#).div#(r#.times#(r#))
public? get(): Double
public? abstract fun sayHello(): R|kotlin/Unit|
local final? companion object Companion : R|kotlin/Any| {
private constructor(): R|C.Planet.Companion| {
super<R|kotlin/Any|>()
}
public? final? const val G: <implicit> = Double(6.67E-11)
public? get(): <implicit>
}
public final static fun values(): R|kotlin/Array<C.Planet>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|C.Planet| {
}
public final static val entries: R|kotlin/enums/EnumEntries<C.Planet>|
public get(): R|kotlin/enums/EnumEntries<C.Planet>|
}
}
}
@@ -0,0 +1,80 @@
FILE: enums3.kt
public? final? class C : R|kotlin/Any| {
public? [ContainingClassKey=C] constructor(): R|C| {
super<R|kotlin/Any|>()
}
init {
local final? [ContainingClassKey=C] enum class Planet : R|kotlin/Enum<C.Planet>| {
private [ContainingClassKey=Planet] constructor([CorrespondingProperty=<local>/m] m: Double, [CorrespondingProperty=<local>/r] r: Double): R|C.Planet| {
super<R|kotlin/Enum<C.Planet>|>()
}
public? final? [IsFromPrimaryConstructor=true] val m: Double = R|<local>/m|
public? [ContainingClassKey=Planet] get(): Double
internal final? [IsFromPrimaryConstructor=true] val r: Double = R|<local>/r|
internal [ContainingClassKey=Planet] get(): Double
public final static [ContainingClassKey=Planet] enum entry MERCURY: R|C.Planet| = object : R|C.Planet| {
private [ContainingClassKey=<anonymous>] constructor(): R|<anonymous>| {
super<R|C.Planet|>(Double(1.0), Double(2.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Hello!!!))
}
}
public final static [ContainingClassKey=Planet] enum entry VENERA: R|C.Planet| = object : R|C.Planet| {
private [ContainingClassKey=<anonymous>] constructor(): R|<anonymous>| {
super<R|C.Planet|>(Double(3.0), Double(4.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Ola!!!))
}
}
public final static [ContainingClassKey=Planet] enum entry EARTH: R|C.Planet| = object : R|C.Planet| {
private [ContainingClassKey=<anonymous>] constructor(): R|<anonymous>| {
super<R|C.Planet|>(Double(5.0), Double(6.0))
}
public? open? override fun sayHello(): R|kotlin/Unit| {
println#(String(Privet!!!))
}
}
public? final? val g: Double = G#.times#(m#).div#(r#.times#(r#))
public? [ContainingClassKey=Planet] get(): Double
public? abstract fun sayHello(): R|kotlin/Unit|
local final? companion [ContainingClassKey=Planet] object Companion : R|kotlin/Any| {
private [ContainingClassKey=Companion] constructor(): R|C.Planet.Companion| {
super<R|kotlin/Any|>()
}
public? final? const val G: <implicit> = Double(6.67E-11)
public? [ContainingClassKey=Companion] get(): <implicit>
}
public final static [ContainingClassKey=Planet] fun values(): R|kotlin/Array<C.Planet>| {
}
public final static [ContainingClassKey=Planet] fun valueOf(value: R|kotlin/String|): R|C.Planet| {
}
public final static [ContainingClassKey=Planet] val entries: R|kotlin/enums/EnumEntries<C.Planet>|
public get(): R|kotlin/enums/EnumEntries<C.Planet>|
}
}
}
@@ -101,6 +101,11 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums2.kt");
}
@TestMetadata("enums3.kt")
public void testEnums3() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums3.kt");
}
@TestMetadata("expectActual.kt")
public void testExpectActual() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/expectActual.kt");
@@ -101,6 +101,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums2.kt");
}
@TestMetadata("enums3.kt")
public void testEnums3() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums3.kt");
}
@TestMetadata("expectActual.kt")
public void testExpectActual() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/expectActual.kt");
@@ -105,6 +105,12 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizerTe
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums2.kt");
}
@Test
@TestMetadata("enums3.kt")
public void testEnums3() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums3.kt");
}
@Test
@TestMetadata("expectActual.kt")
public void testExpectActual() throws Exception {
@@ -105,6 +105,12 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizerTe
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums2.kt");
}
@Test
@TestMetadata("enums3.kt")
public void testEnums3() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/enums3.kt");
}
@Test
@TestMetadata("expectActual.kt")
public void testExpectActual() throws Exception {