[FIR] Make expect class members also expect

This commit is contained in:
Mikhail Glukhikh
2020-06-24 15:25:52 +03:00
parent 2fefa682b7
commit c1609ed490
20 changed files with 124 additions and 85 deletions
@@ -2,7 +2,7 @@ FILE: B.kt
public abstract expect interface Other : R|kotlin/Any| { public abstract expect interface Other : R|kotlin/Any| {
} }
public final expect class Another : R|kotlin/Any| { public final expect class Another : R|kotlin/Any| {
public constructor(): R|b/d/Another| { public expect constructor(): R|b/d/Another| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
@@ -1,10 +1,10 @@
FILE: common.kt FILE: common.kt
public open expect class A<T> : R|kotlin/Any| { public open expect class A<T> : R|kotlin/Any| {
public constructor<T>(): R|A<T>| { public expect constructor<T>(): R|A<T>| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
public open fun foo(arg: R|T|): R|kotlin/Unit| public open expect fun foo(arg: R|T|): R|kotlin/Unit|
} }
public open class B : R|A<kotlin/String>| { public open class B : R|A<kotlin/String>| {
@@ -1,10 +1,10 @@
FILE: common.kt FILE: common.kt
public final expect class MyList : R|kotlin/Any| { public final expect class MyList : R|kotlin/Any| {
public constructor(): R|MyList| { public expect constructor(): R|MyList| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
public final fun get(i: R|kotlin/Int|): R|kotlin/Int| public final expect fun get(i: R|kotlin/Int|): R|kotlin/Int|
} }
public open class Wrapper : R|kotlin/Any| { public open class Wrapper : R|kotlin/Any| {
@@ -4,6 +4,8 @@
expect open class A() { expect open class A() {
fun foo() fun foo()
val x: Int
} }
open class B : A() open class B : A()
@@ -15,12 +17,15 @@ actual open class A {
actual fun foo() {} actual fun foo() {}
fun bar() {} fun bar() {}
actual val x = 42
} }
class C : B() { class C : B() {
fun test() { fun test() {
foo() foo()
bar() bar()
x + x
} }
} }
@@ -28,5 +33,6 @@ class D : A() {
fun test() { fun test() {
foo() foo()
bar() bar()
x + x
} }
} }
@@ -1,10 +1,13 @@
FILE: common.kt FILE: common.kt
public open expect class A : R|kotlin/Any| { public open expect class A : R|kotlin/Any| {
public constructor(): R|A| { public expect constructor(): R|A| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
public final fun foo(): R|kotlin/Unit| public final expect fun foo(): R|kotlin/Unit|
public final expect val x: R|kotlin/Int|
public get(): R|kotlin/Int|
} }
public open class B : R|A| { public open class B : R|A| {
@@ -25,6 +28,9 @@ FILE: jvm.kt
public final fun bar(): R|kotlin/Unit| { public final fun bar(): R|kotlin/Unit| {
} }
public final actual val x: R|kotlin/Int| = Int(42)
public get(): R|kotlin/Int|
} }
public final class C : R|B| { public final class C : R|B| {
public constructor(): R|C| { public constructor(): R|C| {
@@ -34,6 +40,7 @@ FILE: jvm.kt
public final fun test(): R|kotlin/Unit| { public final fun test(): R|kotlin/Unit| {
this@R|/C|.R|/A.foo|() this@R|/C|.R|/A.foo|()
this@R|/C|.R|/A.bar|() this@R|/C|.R|/A.bar|()
this@R|/C|.R|/A.x|.R|kotlin/Int.plus|(this@R|/C|.R|/A.x|)
} }
} }
@@ -45,6 +52,7 @@ FILE: jvm.kt
public final fun test(): R|kotlin/Unit| { public final fun test(): R|kotlin/Unit| {
this@R|/D|.R|/A.foo|() this@R|/D|.R|/A.foo|()
this@R|/D|.R|/A.bar|() this@R|/D|.R|/A.bar|()
this@R|/D|.R|/A.x|.R|kotlin/Int.plus|(this@R|/D|.R|/A.x|)
} }
} }
@@ -1,10 +1,10 @@
FILE: common.kt FILE: common.kt
public open expect class A : R|kotlin/Any| { public open expect class A : R|kotlin/Any| {
public constructor(): R|A| { public expect constructor(): R|A| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
public final fun foo(): R|kotlin/Unit| public final expect fun foo(): R|kotlin/Unit|
} }
public open class B : R|A| { public open class B : R|A| {
@@ -465,7 +465,7 @@ class Fir2IrDeclarationStorage(
startOffset, endOffset, origin, symbol, startOffset, endOffset, origin, symbol,
Name.special("<init>"), constructor.visibility, Name.special("<init>"), constructor.visibility,
constructor.returnTypeRef.toIrType(), constructor.returnTypeRef.toIrType(),
isInline = false, isExternal = false, isPrimary = isPrimary, isExpect = false isInline = false, isExternal = false, isPrimary = isPrimary, isExpect = constructor.isExpect
).apply { ).apply {
metadata = FirMetadataSource.Function(constructor) metadata = FirMetadataSource.Function(constructor)
enterScope(this) enterScope(this)
@@ -109,7 +109,7 @@ internal class ClassMemberGenerator(
} }
annotationGenerator.generate(irFunction, firFunction) annotationGenerator.generate(irFunction, firFunction)
} }
if (firFunction is FirConstructor && irFunction is IrConstructor && !parentAsClass.isAnnotationClass) { if (firFunction is FirConstructor && irFunction is IrConstructor && !parentAsClass.isAnnotationClass && !firFunction.isExpect) {
val body = IrBlockBodyImpl(startOffset, endOffset) val body = IrBlockBodyImpl(startOffset, endOffset)
val delegatedConstructor = firFunction.delegatedConstructor val delegatedConstructor = firFunction.delegatedConstructor
if (delegatedConstructor != null) { if (delegatedConstructor != null) {
@@ -129,7 +129,7 @@ internal class ClassMemberGenerator(
if (body.statements.isNotEmpty()) { if (body.statements.isNotEmpty()) {
irFunction.body = body irFunction.body = body
} }
} else if (irFunction !is IrConstructor) { } else if (irFunction !is IrConstructor && !irFunction.isExpect) {
when { when {
irFunction.origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> { irFunction.origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> {
val kind = Fir2IrDeclarationStorage.ENUM_SYNTHETIC_NAMES.getValue(irFunction.name) val kind = Fir2IrDeclarationStorage.ENUM_SYNTHETIC_NAMES.getValue(irFunction.name)
@@ -95,7 +95,9 @@ class FakeOverrideGenerator(
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalFunction.allowsToHaveFakeOverrideIn(klass)) { } else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalFunction.allowsToHaveFakeOverrideIn(klass)) {
// Trivial fake override case // Trivial fake override case
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction( val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction(
session, originalFunction, baseSymbol, derivedClassId = klass.symbol.classId session, originalFunction, baseSymbol,
derivedClassId = klass.symbol.classId,
isExpect = (klass as? FirRegularClass)?.isExpect == true
) )
val fakeOverrideFunction = fakeOverrideSymbol.fir val fakeOverrideFunction = fakeOverrideSymbol.fir
@@ -137,7 +139,9 @@ class FakeOverrideGenerator(
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) { } else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) {
// Trivial fake override case // Trivial fake override case
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideProperty( val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideProperty(
session, originalProperty, baseSymbol, derivedClassId = klass.symbol.classId session, originalProperty, baseSymbol,
derivedClassId = klass.symbol.classId,
isExpect = (klass as? FirRegularClass)?.isExpect == true
) )
val fakeOverrideProperty = fakeOverrideSymbol.fir val fakeOverrideProperty = fakeOverrideSymbol.fir
@@ -458,7 +458,7 @@ class DeclarationsConverter(
//parse properties //parse properties
properties += primaryConstructorWrapper.valueParameters properties += primaryConstructorWrapper.valueParameters
.filter { it.hasValOrVar() } .filter { it.hasValOrVar() }
.map { it.toFirProperty(baseSession, callableIdForName(it.firValueParameter.name)) } .map { it.toFirProperty(baseSession, callableIdForName(it.firValueParameter.name), classWrapper.hasExpect()) }
addDeclarations(properties) addDeclarations(properties)
} }
@@ -482,8 +482,8 @@ class DeclarationsConverter(
} }
if (modifiers.isEnum()) { if (modifiers.isEnum()) {
generateValuesFunction(baseSession, context.packageFqName, context.className) generateValuesFunction(baseSession, context.packageFqName, context.className, modifiers.hasExpect())
generateValueOfFunction(baseSession, context.packageFqName, context.className) generateValueOfFunction(baseSession, context.packageFqName, context.className, modifiers.hasExpect())
} }
} }
} }
@@ -584,6 +584,7 @@ class DeclarationsConverter(
symbol = FirVariableSymbol(CallableId(context.currentClassId, enumEntryName)) symbol = FirVariableSymbol(CallableId(context.currentClassId, enumEntryName))
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply { status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply {
isStatic = true isStatic = true
isExpect = classWrapper.hasExpect()
} }
if (classWrapper.hasDefaultConstructor && enumEntry.getChildNodeByType(INITIALIZER_LIST) == null && if (classWrapper.hasDefaultConstructor && enumEntry.getChildNodeByType(INITIALIZER_LIST) == null &&
modifiers.annotations.isEmpty() && classBodyNode == null modifiers.annotations.isEmpty() && classBodyNode == null
@@ -647,7 +648,7 @@ class DeclarationsConverter(
when (node.tokenType) { when (node.tokenType) {
ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper) ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper)
CLASS -> container += convertClass(node) CLASS -> container += convertClass(node)
FUN -> container += convertFunctionDeclaration(node) FUN -> container += convertFunctionDeclaration(node, classWrapper)
PROPERTY -> container += convertPropertyDeclaration(node, classWrapper) PROPERTY -> container += convertPropertyDeclaration(node, classWrapper)
TYPEALIAS -> container += convertTypeAlias(node) TYPEALIAS -> container += convertTypeAlias(node)
OBJECT_DECLARATION -> container += convertClass(node) OBJECT_DECLARATION -> container += convertClass(node)
@@ -688,7 +689,7 @@ class DeclarationsConverter(
val explicitVisibility = if (primaryConstructor != null) modifiers.getVisibility() else null val explicitVisibility = if (primaryConstructor != null) modifiers.getVisibility() else null
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility, Modality.FINAL).apply { val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility, Modality.FINAL).apply {
isExpect = modifiers.hasExpect() isExpect = modifiers.hasExpect() || classWrapper.hasExpect()
isActual = modifiers.hasActual() isActual = modifiers.hasActual()
isInner = classWrapper.isInner() isInner = classWrapper.isInner()
isFromSealedClass = classWrapper.isSealed() && explicitVisibility !== Visibilities.PRIVATE isFromSealedClass = classWrapper.isSealed() && explicitVisibility !== Visibilities.PRIVATE
@@ -753,7 +754,7 @@ class DeclarationsConverter(
val explicitVisibility = modifiers.getVisibility() val explicitVisibility = modifiers.getVisibility()
val status = FirDeclarationStatusImpl(explicitVisibility, Modality.FINAL).apply { val status = FirDeclarationStatusImpl(explicitVisibility, Modality.FINAL).apply {
isExpect = modifiers.hasExpect() isExpect = modifiers.hasExpect() || classWrapper.hasExpect()
isActual = modifiers.hasActual() isActual = modifiers.hasActual()
isInner = classWrapper.isInner() isInner = classWrapper.isInner()
isFromSealedClass = classWrapper.isSealed() && explicitVisibility !== Visibilities.PRIVATE isFromSealedClass = classWrapper.isSealed() && explicitVisibility !== Visibilities.PRIVATE
@@ -955,7 +956,7 @@ class DeclarationsConverter(
// Note that, depending on `var` or `val`, checking setter's modifiers should be careful: for `val`, setter doesn't // Note that, depending on `var` or `val`, checking setter's modifiers should be careful: for `val`, setter doesn't
// exist (null); for `var`, the retrieval of the specific modifier is supposed to be `true` // exist (null); for `var`, the retrieval of the specific modifier is supposed to be `true`
status = FirDeclarationStatusImpl(propertyVisibility, modifiers.getModality()).apply { status = FirDeclarationStatusImpl(propertyVisibility, modifiers.getModality()).apply {
isExpect = modifiers.hasExpect() isExpect = modifiers.hasExpect() || classWrapper?.hasExpect() == true
isActual = modifiers.hasActual() isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride() isOverride = modifiers.hasOverride()
isConst = modifiers.isConst() isConst = modifiers.isConst()
@@ -1150,7 +1151,7 @@ class DeclarationsConverter(
/** /**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseFunction * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseFunction
*/ */
fun convertFunctionDeclaration(functionDeclaration: LighterASTNode): FirDeclaration { fun convertFunctionDeclaration(functionDeclaration: LighterASTNode, classWrapper: ClassWrapper? = null): FirDeclaration {
var modifiers = Modifier() var modifiers = Modifier()
var identifier: String? = null var identifier: String? = null
val firTypeParameters = mutableListOf<FirTypeParameter>() val firTypeParameters = mutableListOf<FirTypeParameter>()
@@ -1208,7 +1209,7 @@ class DeclarationsConverter(
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(), if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
modifiers.getModality() modifiers.getModality()
).apply { ).apply {
isExpect = modifiers.hasExpect() isExpect = modifiers.hasExpect() || classWrapper?.hasExpect() == true
isActual = modifiers.hasActual() isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride() isOverride = modifiers.hasOverride()
isOperator = modifiers.hasOperator() isOperator = modifiers.hasOperator()
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.declarations.builder.FirClassBuilder import org.jetbrains.kotlin.fir.declarations.builder.FirClassBuilder
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
@@ -57,6 +56,10 @@ class ClassWrapper(
return modifiers.isInner() return modifiers.isInner()
} }
fun hasExpect(): Boolean {
return modifiers.hasExpect()
}
// See DescriptorUtils#getDefaultConstructorVisibility in core.descriptors // See DescriptorUtils#getDefaultConstructorVisibility in core.descriptors
fun defaultConstructorVisibility(): Visibility { fun defaultConstructorVisibility(): Visibility {
return when { return when {
@@ -35,7 +35,7 @@ class ValueParameter(
return isVal || isVar return isVal || isVar
} }
fun toFirProperty(session: FirSession, callableId: CallableId): FirProperty { fun toFirProperty(session: FirSession, callableId: CallableId, isExpect: Boolean): FirProperty {
val name = this.firValueParameter.name val name = this.firValueParameter.name
var type = this.firValueParameter.returnTypeRef var type = this.firValueParameter.returnTypeRef
if (type is FirImplicitTypeRef) { if (type is FirImplicitTypeRef) {
@@ -58,7 +58,7 @@ class ValueParameter(
symbol = FirPropertySymbol(callableId) symbol = FirPropertySymbol(callableId)
isLocal = false isLocal = false
status = FirDeclarationStatusImpl(modifiers.getVisibility(), modifiers.getModality()).apply { status = FirDeclarationStatusImpl(modifiers.getVisibility(), modifiers.getModality()).apply {
isExpect = modifiers.hasExpect() this.isExpect = isExpect
isActual = modifiers.hasActual() isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride() isOverride = modifiers.hasOverride()
isConst = false isConst = false
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
@@ -348,11 +349,11 @@ class RawFirBuilder(
} }
} }
private fun KtParameter.toFirProperty(firParameter: FirValueParameter): FirProperty { private fun KtParameter.toFirProperty(firParameter: FirValueParameter, isExpect: Boolean): FirProperty {
require(hasValOrVar()) require(hasValOrVar())
var type = typeReference.toFirOrErrorType() val type = typeReference.toFirOrErrorType()
val status = FirDeclarationStatusImpl(visibility, modality).apply { val status = FirDeclarationStatusImpl(visibility, modality).apply {
isExpect = hasExpectModifier() this.isExpect = isExpect
isActual = hasActualModifier() isActual = hasActualModifier()
isOverride = hasModifier(OVERRIDE_KEYWORD) isOverride = hasModifier(OVERRIDE_KEYWORD)
isConst = false isConst = false
@@ -554,8 +555,8 @@ class RawFirBuilder(
val explicitVisibility = this?.visibility val explicitVisibility = this?.visibility
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility(), Modality.FINAL).apply { val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility(), Modality.FINAL).apply {
isExpect = this@toFirConstructor?.hasExpectModifier() ?: false isExpect = this@toFirConstructor?.hasExpectModifier() == true || owner.hasExpectModifier()
isActual = this@toFirConstructor?.hasActualModifier() ?: false isActual = this@toFirConstructor?.hasActualModifier() == true
isInner = owner.hasModifier(INNER_KEYWORD) isInner = owner.hasModifier(INNER_KEYWORD)
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.PRIVATE isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.PRIVATE
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD) isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
@@ -612,6 +613,7 @@ class RawFirBuilder(
name = nameAsSafeName name = nameAsSafeName
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply { status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply {
isStatic = true isStatic = true
isExpect = containingClassOrObject?.hasExpectModifier() == true
} }
symbol = FirVariableSymbol(callableIdForName(nameAsSafeName)) symbol = FirVariableSymbol(callableIdForName(nameAsSafeName))
// NB: not sure should annotations be on enum entry itself, or on its corresponding object // NB: not sure should annotations be on enum entry itself, or on its corresponding object
@@ -718,7 +720,7 @@ class RawFirBuilder(
firPrimaryConstructor.valueParameters firPrimaryConstructor.valueParameters
).forEach { (ktParameter, firParameter) -> ).forEach { (ktParameter, firParameter) ->
if (ktParameter.hasValOrVar()) { if (ktParameter.hasValOrVar()) {
addDeclaration(ktParameter.toFirProperty(firParameter)) addDeclaration(ktParameter.toFirProperty(firParameter, classOrObject.hasExpectModifier()))
} }
} }
} }
@@ -751,8 +753,12 @@ class RawFirBuilder(
} }
if (classOrObject.hasModifier(ENUM_KEYWORD)) { if (classOrObject.hasModifier(ENUM_KEYWORD)) {
generateValuesFunction(baseSession, context.packageFqName, context.className) generateValuesFunction(
generateValueOfFunction(baseSession, context.packageFqName, context.className) baseSession, context.packageFqName, context.className, classOrObject.hasExpectModifier()
)
generateValueOfFunction(
baseSession, context.packageFqName, context.className, classOrObject.hasExpectModifier()
)
} }
} }
} }
@@ -843,7 +849,7 @@ class RawFirBuilder(
if (function.isLocal) Visibilities.LOCAL else function.visibility, if (function.isLocal) Visibilities.LOCAL else function.visibility,
function.modality, function.modality,
).apply { ).apply {
isExpect = function.hasExpectModifier() isExpect = function.hasExpectModifier() || function.containingClassOrObject?.hasExpectModifier() == true
isActual = function.hasActualModifier() isActual = function.hasActualModifier()
isOverride = function.hasModifier(OVERRIDE_KEYWORD) isOverride = function.hasModifier(OVERRIDE_KEYWORD)
isOperator = function.hasModifier(OPERATOR_KEYWORD) isOperator = function.hasModifier(OPERATOR_KEYWORD)
@@ -994,7 +1000,7 @@ class RawFirBuilder(
returnTypeRef = delegatedSelfTypeRef returnTypeRef = delegatedSelfTypeRef
val explicitVisibility = visibility val explicitVisibility = visibility
status = FirDeclarationStatusImpl(explicitVisibility, Modality.FINAL).apply { status = FirDeclarationStatusImpl(explicitVisibility, Modality.FINAL).apply {
isExpect = hasExpectModifier() isExpect = hasExpectModifier() || owner.hasExpectModifier()
isActual = hasActualModifier() isActual = hasActualModifier()
isInner = owner.hasModifier(INNER_KEYWORD) isInner = owner.hasModifier(INNER_KEYWORD)
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.PRIVATE isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.PRIVATE
@@ -1098,7 +1104,7 @@ class RawFirBuilder(
// Note that, depending on `var` or `val`, checking setter's modifiers should be careful: for `val`, setter doesn't // Note that, depending on `var` or `val`, checking setter's modifiers should be careful: for `val`, setter doesn't
// exist (null); for `var`, the retrieval of the specific modifier is supposed to be `true` // exist (null); for `var`, the retrieval of the specific modifier is supposed to be `true`
status = FirDeclarationStatusImpl(visibility, modality).apply { status = FirDeclarationStatusImpl(visibility, modality).apply {
isExpect = hasExpectModifier() isExpect = hasExpectModifier() || containingClassOrObject?.hasExpectModifier() == true
isActual = hasActualModifier() isActual = hasActualModifier()
isOverride = hasModifier(OVERRIDE_KEYWORD) isOverride = hasModifier(OVERRIDE_KEYWORD)
isConst = hasModifier(CONST_KEYWORD) isConst = hasModifier(CONST_KEYWORD)
@@ -1,6 +1,6 @@
FILE: expectActual.kt FILE: expectActual.kt
public? final? expect class MyClass : R|kotlin/Any| { public? final? expect class MyClass : R|kotlin/Any| {
public? constructor(): R|MyClass| { public? expect constructor(): R|MyClass| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
@@ -323,6 +324,16 @@ class FirClassSubstitutionScope(
} }
} }
private fun FirDeclarationStatus.withExpect(isExpect: Boolean): FirDeclarationStatus {
return if (this.isExpect == isExpect) {
this
} else {
FirResolvedDeclarationStatusImpl(visibility, effectiveVisibility, modality!!).apply {
this.isExpect = isExpect
}
}
}
private fun createFakeOverrideFunction( private fun createFakeOverrideFunction(
fakeOverrideSymbol: FirFunctionSymbol<FirSimpleFunction>, fakeOverrideSymbol: FirFunctionSymbol<FirSimpleFunction>,
session: FirSession, session: FirSession,
@@ -330,7 +341,8 @@ class FirClassSubstitutionScope(
newReceiverType: ConeKotlinType? = null, newReceiverType: ConeKotlinType? = null,
newReturnType: ConeKotlinType? = null, newReturnType: ConeKotlinType? = null,
newParameterTypes: List<ConeKotlinType?>? = null, newParameterTypes: List<ConeKotlinType?>? = null,
newTypeParameters: List<FirTypeParameter>? = null newTypeParameters: List<FirTypeParameter>? = null,
isExpect: Boolean = baseFunction.isExpect
): FirSimpleFunction { ): FirSimpleFunction {
// TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl
// As second alternative, we can invent some light-weight kind of FirRegularClass // As second alternative, we can invent some light-weight kind of FirRegularClass
@@ -342,7 +354,7 @@ class FirClassSubstitutionScope(
returnTypeRef = baseFunction.returnTypeRef.withReplacedReturnType(newReturnType) returnTypeRef = baseFunction.returnTypeRef.withReplacedReturnType(newReturnType)
receiverTypeRef = baseFunction.receiverTypeRef?.withReplacedConeType(newReceiverType) receiverTypeRef = baseFunction.receiverTypeRef?.withReplacedConeType(newReceiverType)
name = baseFunction.name name = baseFunction.name
status = baseFunction.status.withLocalEffectiveVisibility(isLocal) status = baseFunction.status.withLocalEffectiveVisibility(isLocal).withExpect(isExpect)
symbol = fakeOverrideSymbol symbol = fakeOverrideSymbol
resolvePhase = baseFunction.resolvePhase resolvePhase = baseFunction.resolvePhase
configureAnnotationsAndParameters(session, baseFunction, newParameterTypes) configureAnnotationsAndParameters(session, baseFunction, newParameterTypes)
@@ -365,14 +377,15 @@ class FirClassSubstitutionScope(
newReturnType: ConeKotlinType? = null, newReturnType: ConeKotlinType? = null,
newParameterTypes: List<ConeKotlinType?>? = null, newParameterTypes: List<ConeKotlinType?>? = null,
newTypeParameters: List<FirTypeParameter>? = null, newTypeParameters: List<FirTypeParameter>? = null,
derivedClassId: ClassId? = null derivedClassId: ClassId? = null,
isExpect: Boolean = baseFunction.isExpect
): FirNamedFunctionSymbol { ): FirNamedFunctionSymbol {
val symbol = FirNamedFunctionSymbol( val symbol = FirNamedFunctionSymbol(
CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseFunction.name), CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseFunction.name),
isFakeOverride = true, overriddenSymbol = baseSymbol isFakeOverride = true, overriddenSymbol = baseSymbol
) )
createFakeOverrideFunction( createFakeOverrideFunction(
symbol, session, baseFunction, newReceiverType, newReturnType, newParameterTypes, newTypeParameters symbol, session, baseFunction, newReceiverType, newReturnType, newParameterTypes, newTypeParameters, isExpect
) )
return symbol return symbol
} }
@@ -384,7 +397,8 @@ class FirClassSubstitutionScope(
newReceiverType: ConeKotlinType? = null, newReceiverType: ConeKotlinType? = null,
newReturnType: ConeKotlinType? = null, newReturnType: ConeKotlinType? = null,
newTypeParameters: List<FirTypeParameter>? = null, newTypeParameters: List<FirTypeParameter>? = null,
derivedClassId: ClassId? = null derivedClassId: ClassId? = null,
isExpect: Boolean = baseProperty.isExpect
): FirPropertySymbol { ): FirPropertySymbol {
val symbol = FirPropertySymbol( val symbol = FirPropertySymbol(
CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseProperty.name), CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseProperty.name),
@@ -400,7 +414,7 @@ class FirClassSubstitutionScope(
isVar = baseProperty.isVar isVar = baseProperty.isVar
this.symbol = symbol this.symbol = symbol
isLocal = false isLocal = false
status = baseProperty.status.withLocalEffectiveVisibility(isLocal) status = baseProperty.status.withLocalEffectiveVisibility(isLocal).withExpect(isExpect)
resolvePhase = baseProperty.resolvePhase resolvePhase = baseProperty.resolvePhase
annotations += baseProperty.annotations annotations += baseProperty.annotations
if (newTypeParameters != null) { if (newTypeParameters != null) {
@@ -29,7 +29,9 @@ private val ENUM_VALUES = Name.identifier("values")
private val ENUM_VALUE_OF = Name.identifier("valueOf") private val ENUM_VALUE_OF = Name.identifier("valueOf")
private val VALUE = Name.identifier("value") private val VALUE = Name.identifier("value")
fun FirRegularClassBuilder.generateValuesFunction(session: FirSession, packageFqName: FqName, classFqName: FqName) { fun FirRegularClassBuilder.generateValuesFunction(
session: FirSession, packageFqName: FqName, classFqName: FqName, makeExpect: Boolean = false
) {
declarations += buildSimpleFunction { declarations += buildSimpleFunction {
source = this@generateValuesFunction.source source = this@generateValuesFunction.source
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
@@ -47,6 +49,7 @@ fun FirRegularClassBuilder.generateValuesFunction(session: FirSession, packageFq
name = ENUM_VALUES name = ENUM_VALUES
this.status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply { this.status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply {
isStatic = true isStatic = true
isExpect = makeExpect
} }
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUES)) symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUES))
resolvePhase = FirResolvePhase.BODY_RESOLVE resolvePhase = FirResolvePhase.BODY_RESOLVE
@@ -54,7 +57,9 @@ fun FirRegularClassBuilder.generateValuesFunction(session: FirSession, packageFq
} }
} }
fun FirRegularClassBuilder.generateValueOfFunction(session: FirSession, packageFqName: FqName, classFqName: FqName) { fun FirRegularClassBuilder.generateValueOfFunction(
session: FirSession, packageFqName: FqName, classFqName: FqName, makeExpect: Boolean = false
) {
declarations += buildSimpleFunction { declarations += buildSimpleFunction {
source = this@generateValueOfFunction.source source = this@generateValueOfFunction.source
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
@@ -70,6 +75,7 @@ fun FirRegularClassBuilder.generateValueOfFunction(session: FirSession, packageF
name = ENUM_VALUE_OF name = ENUM_VALUE_OF
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply { status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply {
isStatic = true isStatic = true
isExpect = makeExpect
} }
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUE_OF)) symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUE_OF))
valueParameters += buildValueParameter vp@{ valueParameters += buildValueParameter vp@{
@@ -402,7 +402,14 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
override fun visitConstructor(constructor: FirConstructor) { override fun visitConstructor(constructor: FirConstructor) {
constructor.annotations.renderAnnotations() constructor.annotations.renderAnnotations()
print(constructor.visibility.asString(constructor.effectiveVisibility) + " constructor") print(constructor.visibility.asString(constructor.effectiveVisibility) + " ")
if (constructor.isExpect) {
print("expect ")
}
if (constructor.isActual) {
print("actual ")
}
print("constructor")
constructor.typeParameters.renderTypeParameters() constructor.typeParameters.renderTypeParameters()
constructor.valueParameters.renderParameters() constructor.valueParameters.renderParameters()
print(": ") print(": ")
@@ -1,47 +1,41 @@
FILE fqName:<root> fileName:/expectClassInherited.kt FILE fqName:<root> fileName:/expectClassInherited.kt
CLASS CLASS name:A modality:ABSTRACT visibility:public [expect] superTypes:[kotlin.Any] CLASS CLASS name:A modality:ABSTRACT visibility:public [expect] superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.A $this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.A
CONSTRUCTOR visibility:protected <> () returnType:<root>.A [primary] CONSTRUCTOR visibility:protected <> () returnType:<root>.A [primary,expect]
BLOCK_BODY FUN name:foo visibility:public modality:ABSTRACT <> ($this:<root>.A) returnType:kotlin.Unit [expect]
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:A modality:ABSTRACT visibility:public [expect] superTypes:[kotlin.Any]'
FUN name:foo visibility:public modality:ABSTRACT <> ($this:<root>.A) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.A $this: VALUE_PARAMETER name:<this> type:<root>.A
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 [expect,fake_override]
overridden: overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any? VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [expect,fake_override]
overridden: overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [expect,fake_override]
overridden: overridden:
public open fun toString (): kotlin.String declared in kotlin.Any public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS CLASS name:B modality:OPEN visibility:public [expect] superTypes:[<root>.A] CLASS CLASS name:B modality:OPEN visibility:public [expect] superTypes:[<root>.A]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.B $this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.B
CONSTRUCTOR visibility:public <> (i:kotlin.Int) returnType:<root>.B [primary] CONSTRUCTOR visibility:public <> (i:kotlin.Int) returnType:<root>.B [primary,expect]
VALUE_PARAMETER name:i index:0 type:kotlin.Int VALUE_PARAMETER name:i index:0 type:kotlin.Int
BLOCK_BODY FUN name:foo visibility:public modality:OPEN <> ($this:<root>.B) returnType:kotlin.Unit [expect]
DELEGATING_CONSTRUCTOR_CALL 'protected constructor <init> () [primary] declared in <root>.A'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:B modality:OPEN visibility:public [expect] superTypes:[<root>.A]'
FUN name:foo visibility:public modality:OPEN <> ($this:<root>.B) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.B $this: VALUE_PARAMETER name:<this> type:<root>.B
FUN name:bar visibility:public modality:OPEN <> ($this:<root>.B, s:kotlin.String) returnType:kotlin.Unit FUN name:bar visibility:public modality:OPEN <> ($this:<root>.B, s:kotlin.String) returnType:kotlin.Unit [expect]
$this: VALUE_PARAMETER name:<this> type:<root>.B $this: VALUE_PARAMETER name:<this> type:<root>.B
VALUE_PARAMETER name:s index:0 type:kotlin.String VALUE_PARAMETER name:s index:0 type:kotlin.String
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 [expect,fake_override]
overridden: overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any? VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [expect,fake_override]
overridden: overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [expect,fake_override]
overridden: overridden:
public open fun toString (): kotlin.String declared in kotlin.Any public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
@@ -1,17 +1,13 @@
FILE fqName:<root> fileName:/expectedEnumClass.kt FILE fqName:<root> fileName:/expectedEnumClass.kt
CLASS ENUM_CLASS name:MyEnum modality:FINAL visibility:public [expect] superTypes:[kotlin.Enum<<root>.MyEnum>] CLASS ENUM_CLASS name:MyEnum modality:FINAL visibility:public [expect] superTypes:[kotlin.Enum<<root>.MyEnum>]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.MyEnum $this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.MyEnum
CONSTRUCTOR visibility:private <> () returnType:<root>.MyEnum [primary] CONSTRUCTOR visibility:private <> () returnType:<root>.MyEnum [primary,expect]
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'public constructor <init> (name: kotlin.String, ordinal: kotlin.Int) [primary] declared in kotlin.Enum'
<E>: <root>.MyEnum
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_CLASS name:MyEnum modality:FINAL visibility:public [expect] superTypes:[kotlin.Enum<<root>.MyEnum>]'
ENUM_ENTRY name:FOO ENUM_ENTRY name:FOO
init: EXPRESSION_BODY init: EXPRESSION_BODY
ENUM_CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.MyEnum' ENUM_CONSTRUCTOR_CALL 'private constructor <init> () [primary,expect] declared in <root>.MyEnum'
ENUM_ENTRY name:BAR ENUM_ENTRY name:BAR
init: EXPRESSION_BODY init: EXPRESSION_BODY
ENUM_CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.MyEnum' ENUM_CONSTRUCTOR_CALL 'private constructor <init> () [primary,expect] declared in <root>.MyEnum'
FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<<root>.MyEnum> FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<<root>.MyEnum>
SYNTHETIC_BODY kind=ENUM_VALUES SYNTHETIC_BODY kind=ENUM_VALUES
FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:<root>.MyEnum FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:<root>.MyEnum
@@ -1,39 +1,33 @@
FILE fqName:<root> fileName:/expectedSealedClass.kt FILE fqName:<root> fileName:/expectedSealedClass.kt
CLASS CLASS name:Ops modality:SEALED visibility:public [expect] superTypes:[kotlin.Any] CLASS CLASS name:Ops modality:SEALED visibility:public [expect] superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Ops $this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Ops
CONSTRUCTOR visibility:private <> () returnType:<root>.Ops [primary] CONSTRUCTOR visibility:private <> () returnType:<root>.Ops [primary,expect]
BLOCK_BODY FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [expect,fake_override]
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Ops modality:SEALED visibility:public [expect] superTypes:[kotlin.Any]'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden: overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any? VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [expect,fake_override]
overridden: overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [expect,fake_override]
overridden: overridden:
public open fun toString (): kotlin.String declared in kotlin.Any public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS CLASS name:Add modality:FINAL visibility:public [expect] superTypes:[<root>.Ops] CLASS CLASS name:Add modality:FINAL visibility:public [expect] superTypes:[<root>.Ops]
$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,expect]
BLOCK_BODY FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [expect,fake_override]
DELEGATING_CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.Ops'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Add modality:FINAL visibility:public [expect] 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: overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any? VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [expect,fake_override]
overridden: overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [expect,fake_override]
overridden: overridden:
public open fun toString (): kotlin.String declared in kotlin.Any public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any