diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index b8123871bd1..443afa533b0 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -24,6 +24,8 @@ import org.jetbrains.kotlin.fir.types.impl.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier +import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.psi.psiUtil.modalityModifierType import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType import org.jetbrains.kotlin.types.Variance @@ -58,6 +60,15 @@ class RawFirBuilder(val session: FirSession) { } } + private val KtDeclaration.platformStatus: FirMemberPlatformStatus + get() { + return when { + hasExpectModifier() -> FirMemberPlatformStatus.EXPECT + hasActualModifier() -> FirMemberPlatformStatus.ACTUAL + else -> FirMemberPlatformStatus.DEFAULT + } + } + private inner class Visitor : KtVisitor() { @Suppress("UNCHECKED_CAST") private fun KtElement?.convertSafe(): R? = @@ -252,6 +263,7 @@ class RawFirBuilder(val session: FirSession) { classOrObject.nameAsSafeName, classOrObject.visibility, classOrObject.modality, + classOrObject.platformStatus, classKind, isInner = classOrObject.hasModifier(KtTokens.INNER_KEYWORD), isCompanion = (classOrObject as? KtObjectDeclaration)?.isCompanion() == true, @@ -272,6 +284,7 @@ class RawFirBuilder(val session: FirSession) { typeAlias, typeAlias.nameAsSafeName, typeAlias.visibility, + typeAlias.platformStatus, typeAlias.getTypeReference().toFirOrErrorType() ) typeAlias.extractAnnotationsTo(firTypeAlias) @@ -291,6 +304,7 @@ class RawFirBuilder(val session: FirSession) { function.nameAsSafeName, function.visibility, function.modality, + function.platformStatus, function.hasModifier(KtTokens.OVERRIDE_KEYWORD), function.hasModifier(KtTokens.OPERATOR_KEYWORD), function.hasModifier(KtTokens.INFIX_KEYWORD), @@ -349,6 +363,7 @@ class RawFirBuilder(val session: FirSession) { property.nameAsSafeName, property.visibility, property.modality, + property.platformStatus, property.hasModifier(KtTokens.OVERRIDE_KEYWORD), property.hasModifier(KtTokens.CONST_KEYWORD), property.receiverTypeReference.convertSafe(), diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index 60d76a9ebe4..7f0e3d452f2 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -121,6 +121,14 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() { } } + private fun FirMemberPlatformStatus.asString(): String { + return when (this) { + FirMemberPlatformStatus.DEFAULT -> "" + FirMemberPlatformStatus.EXPECT -> "expect " + FirMemberPlatformStatus.ACTUAL -> "actual " + } + } + override fun visitMemberDeclaration(memberDeclaration: FirMemberDeclaration) { memberDeclaration.annotations.renderAnnotations() if (memberDeclaration.typeParameters.isNotEmpty()) { @@ -129,6 +137,7 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() { print("> ") } print(memberDeclaration.visibility.asString() + " " + memberDeclaration.modalityAsString() + " ") + print(memberDeclaration.platformStatus.asString()) if (memberDeclaration is FirCallableMember && memberDeclaration.isOverride) { print("override ") } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirMemberDeclaration.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirMemberDeclaration.kt index 4521ba2a042..1b646954af4 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirMemberDeclaration.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirMemberDeclaration.kt @@ -15,6 +15,12 @@ interface FirMemberDeclaration : FirTypeParameterContainer, FirNamedDeclaration, val modality: Modality? + val platformStatus: FirMemberPlatformStatus + + val isExpect: Boolean get() = platformStatus == FirMemberPlatformStatus.EXPECT + + val isActual: Boolean get() = platformStatus == FirMemberPlatformStatus.ACTUAL + override fun accept(visitor: FirVisitor, data: D): R = visitor.visitMemberDeclaration(this, data) @@ -25,4 +31,10 @@ interface FirMemberDeclaration : FirTypeParameterContainer, FirNamedDeclaration, } super.acceptChildren(visitor, data) } +} + +enum class FirMemberPlatformStatus { + DEFAULT, + EXPECT, + ACTUAL } \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirAbstractCallableMember.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirAbstractCallableMember.kt index dc51b4a9667..fb489f242a9 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirAbstractCallableMember.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirAbstractCallableMember.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirCallableMember +import org.jetbrains.kotlin.fir.declarations.FirMemberPlatformStatus import org.jetbrains.kotlin.fir.transformSingle import org.jetbrains.kotlin.fir.types.FirType import org.jetbrains.kotlin.fir.visitors.FirTransformer @@ -22,10 +23,11 @@ abstract class FirAbstractCallableMember( name: Name, visibility: Visibility, modality: Modality?, + platformStatus: FirMemberPlatformStatus, final override val isOverride: Boolean, final override var receiverType: FirType?, final override var returnType: FirType -) : FirAbstractMemberDeclaration(session, psi, name, visibility, modality), FirCallableMember { +) : FirAbstractMemberDeclaration(session, psi, name, visibility, modality, platformStatus), FirCallableMember { override fun transformChildren(transformer: FirTransformer, data: D): FirElement { receiverType = receiverType?.transformSingle(transformer, data) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirAbstractMemberDeclaration.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirAbstractMemberDeclaration.kt index ac47ff33605..5d957e8ce9e 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirAbstractMemberDeclaration.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirAbstractMemberDeclaration.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.FirMemberPlatformStatus import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.name.Name @@ -18,7 +19,8 @@ abstract class FirAbstractMemberDeclaration( psi: PsiElement?, name: Name, final override val visibility: Visibility, - final override val modality: Modality? + final override val modality: Modality?, + override val platformStatus: FirMemberPlatformStatus ) : FirAbstractNamedAnnotatedDeclaration(session, psi, name), FirMemberDeclaration { final override val typeParameters = mutableListOf() } \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt index 850156fb9f6..cb5c572b995 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirMemberPlatformStatus import org.jetbrains.kotlin.fir.transformInplace import org.jetbrains.kotlin.fir.types.FirType import org.jetbrains.kotlin.name.Name @@ -23,11 +24,12 @@ open class FirClassImpl( name: Name, visibility: Visibility, modality: Modality?, + platformStatus: FirMemberPlatformStatus, final override val classKind: ClassKind, final override val isInner: Boolean, final override val isCompanion: Boolean, final override val isData: Boolean -) : FirAbstractMemberDeclaration(session, psi, name, visibility, modality), FirClass { +) : FirAbstractMemberDeclaration(session, psi, name, visibility, modality, platformStatus), FirClass { override val superTypes = mutableListOf() override val declarations = mutableListOf() diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirEnumEntryImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirEnumEntryImpl.kt index e1f3d75e043..0a5c060f690 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirEnumEntryImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirEnumEntryImpl.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirEnumEntry +import org.jetbrains.kotlin.fir.declarations.FirMemberPlatformStatus import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.name.Name @@ -24,6 +25,7 @@ class FirEnumEntryImpl( name, visibility = Visibilities.UNKNOWN, modality = Modality.FINAL, + platformStatus = FirMemberPlatformStatus.DEFAULT, classKind = ClassKind.ENUM_ENTRY, isInner = false, isCompanion = false, diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirMemberFunctionImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirMemberFunctionImpl.kt index 7e2c7f64436..cb21f7c58f4 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirMemberFunctionImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirMemberFunctionImpl.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirMemberPlatformStatus import org.jetbrains.kotlin.fir.declarations.FirNamedFunction import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.FirBody @@ -24,6 +25,7 @@ class FirMemberFunctionImpl( name: Name, visibility: Visibility, modality: Modality?, + platformStatus: FirMemberPlatformStatus, isOverride: Boolean, override val isOperator: Boolean, override val isInfix: Boolean, @@ -33,7 +35,7 @@ class FirMemberFunctionImpl( receiverType: FirType?, returnType: FirType, override val body: FirBody? -) : FirAbstractCallableMember(session, psi, name, visibility, modality, isOverride, receiverType, returnType), +) : FirAbstractCallableMember(session, psi, name, visibility, modality, platformStatus, isOverride, receiverType, returnType), FirNamedFunction { override val valueParameters = mutableListOf() diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirMemberPropertyImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirMemberPropertyImpl.kt index 0e7d06e74d1..a5c468bb440 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirMemberPropertyImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirMemberPropertyImpl.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirMemberPlatformStatus import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.expressions.FirExpression @@ -24,6 +25,7 @@ class FirMemberPropertyImpl( name: Name, visibility: Visibility, modality: Modality?, + platformStatus: FirMemberPlatformStatus, isOverride: Boolean, override val isConst: Boolean, receiverType: FirType?, @@ -33,7 +35,7 @@ class FirMemberPropertyImpl( override var getter: FirPropertyAccessor, override var setter: FirPropertyAccessor, override val delegate: FirExpression? -) : FirAbstractCallableMember(session, psi, name, visibility, modality, isOverride, receiverType, returnType), +) : FirAbstractCallableMember(session, psi, name, visibility, modality, platformStatus, isOverride, receiverType, returnType), FirProperty { override fun transformChildren(transformer: FirTransformer, data: D): FirElement { getter = getter.transformSingle(transformer, data) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt index bf7833409f5..d717156b704 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirMemberPlatformStatus import org.jetbrains.kotlin.fir.declarations.FirTypeAlias import org.jetbrains.kotlin.fir.transformInplace import org.jetbrains.kotlin.fir.transformSingle @@ -22,8 +23,9 @@ class FirTypeAliasImpl( psi: PsiElement?, name: Name, visibility: Visibility, + platformStatus: FirMemberPlatformStatus, override var expandedType: FirType -) : FirAbstractMemberDeclaration(session, psi, name, visibility, Modality.FINAL), FirTypeAlias { +) : FirAbstractMemberDeclaration(session, psi, name, visibility, Modality.FINAL, platformStatus), FirTypeAlias { override fun transformChildren(transformer: FirTransformer, data: D): FirElement { typeParameters.transformInplace(transformer, data) expandedType = expandedType.transformSingle(transformer, data) diff --git a/compiler/testData/fir/rawBuilder/declarations/expectActual.kt b/compiler/testData/fir/rawBuilder/declarations/expectActual.kt new file mode 100644 index 00000000000..7163676cf55 --- /dev/null +++ b/compiler/testData/fir/rawBuilder/declarations/expectActual.kt @@ -0,0 +1,11 @@ +expect class MyClass + +expect fun foo(): String + +expect val x: Int + +actual class MyClass + +actual fun foo() = "Hello" + +actual val x = 42 \ No newline at end of file diff --git a/compiler/testData/fir/rawBuilder/declarations/expectActual.txt b/compiler/testData/fir/rawBuilder/declarations/expectActual.txt new file mode 100644 index 00000000000..829aacef364 --- /dev/null +++ b/compiler/testData/fir/rawBuilder/declarations/expectActual.txt @@ -0,0 +1,13 @@ +FILE: expectActual.kt + public? final? expect class MyClass() { + } + public? final? expect function foo(): String + public? final? expect property x(val): Int + public? get(): Int + public? final? actual class MyClass() { + } + public? final? actual function foo(): { + STUB + } + public? final? actual property x(val): = STUB + public? get(): diff --git a/compiler/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java index e9aa9dacbf3..4d5a856b22f 100644 --- a/compiler/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java @@ -61,6 +61,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas runTest("compiler/testData/fir/rawBuilder/declarations/enums2.kt"); } + @TestMetadata("expectActual.kt") + public void testExpectActual() throws Exception { + runTest("compiler/testData/fir/rawBuilder/declarations/expectActual.kt"); + } + @TestMetadata("F.kt") public void testF() throws Exception { runTest("compiler/testData/fir/rawBuilder/declarations/F.kt");