[FIR] Inherit expect modifier from outer classes

This commit is contained in:
Dmitriy Novozhilov
2021-06-01 12:23:54 +03:00
committed by teamcityserver
parent 18af4155b8
commit 3b2df7ade3
5 changed files with 60 additions and 42 deletions
@@ -51,7 +51,6 @@ import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.utils.addToStdlib.runIf
class DeclarationsConverter(
@@ -403,13 +402,14 @@ class DeclarationsConverter(
val className = identifier.nameAsSafeName(if (modifiers.isCompanion()) "Companion" else "")
val isLocal = isClassLocal(classNode) { getParent() }
val classIsExpect = modifiers.hasExpect() || context.containerIsExpect
return withChildClassName(className, isLocal) {
return withChildClassName(className, isExpect = classIsExpect, isLocal) {
val status = FirDeclarationStatusImpl(
if (isLocal) Visibilities.Local else modifiers.getVisibility(),
modifiers.getModality(isClassOrObject = true)
).apply {
isExpect = modifiers.hasExpect()
isExpect = classIsExpect
isActual = modifiers.hasActual()
isInner = modifiers.isInner()
isCompanion = modifiers.isCompanion() && classKind == ClassKind.OBJECT
@@ -489,7 +489,11 @@ class DeclarationsConverter(
)
//parse primary constructor
val primaryConstructorWrapper = convertPrimaryConstructor(
primaryConstructor, selfType.source, classWrapper, delegatedConstructorSource
primaryConstructor,
selfType.source,
classWrapper,
delegatedConstructorSource,
containingClassIsExpectClass = status.isExpect
)
val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
firPrimaryConstructor?.let { declarations += it }
@@ -557,7 +561,7 @@ class DeclarationsConverter(
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitObjectLiteralExpression
*/
fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement {
return withChildClassName(ANONYMOUS_OBJECT_NAME) {
return withChildClassName(ANONYMOUS_OBJECT_NAME, isExpect = false) {
buildAnonymousObjectExpression {
val objectDeclaration = objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first()
val sourceElement = objectDeclaration.toFirSourceElement()
@@ -619,7 +623,7 @@ class DeclarationsConverter(
)
//parse primary constructor
convertPrimaryConstructor(
primaryConstructor, delegatedSelfType.source, classWrapper, delegatedConstructorSource
primaryConstructor, delegatedSelfType.source, classWrapper, delegatedConstructorSource, containingClassIsExpectClass = false
)?.let { this.declarations += it.firConstructor }
delegateFields?.let { this.declarations += it }
@@ -665,7 +669,7 @@ class DeclarationsConverter(
symbol = FirEnumEntrySymbol(CallableId(context.currentClassId, enumEntryName))
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply {
isStatic = true
isExpect = classWrapper.hasExpect()
isExpect = classWrapper.hasExpect() || context.containerIsExpect
}
if (classWrapper.hasDefaultConstructor && enumEntry.getChildNodeByType(INITIALIZER_LIST) == null &&
modifiers.annotations.isEmpty() && classBodyNode == null
@@ -673,7 +677,7 @@ class DeclarationsConverter(
return@buildEnumEntry
}
annotations += modifiers.annotations
initializer = withChildClassName(enumEntryName) {
initializer = withChildClassName(enumEntryName, isExpect = false) {
buildAnonymousObjectExpression {
val entrySource = enumEntry.toFirSourceElement(FirFakeSourceElementKind.EnumInitializer)
source = entrySource
@@ -705,11 +709,12 @@ class DeclarationsConverter(
enumEntry.toFirSourceElement(),
enumClassWrapper,
superTypeCallEntry?.toFirSourceElement(),
isEnumEntry = true
isEnumEntry = true,
containingClassIsExpectClass = false
)?.let { declarations += it.firConstructor }
classBodyNode?.also {
// Use ANONYMOUS_OBJECT_NAME for the owner class id of enum entry declarations
withChildClassName(ANONYMOUS_OBJECT_NAME, forceLocalContext = true) {
withChildClassName(ANONYMOUS_OBJECT_NAME, forceLocalContext = true, isExpect = false) {
declarations += convertClassBody(it, enumClassWrapper)
}
}
@@ -746,7 +751,7 @@ class DeclarationsConverter(
when (node.tokenType) {
ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper)
CLASS -> container += convertClass(node)
FUN -> container += convertFunctionDeclaration(node, classWrapper) as FirDeclaration
FUN -> container += convertFunctionDeclaration(node) as FirDeclaration
PROPERTY -> container += convertPropertyDeclaration(node, classWrapper)
TYPEALIAS -> container += convertTypeAlias(node)
OBJECT_DECLARATION -> container += convertClass(node)
@@ -765,11 +770,12 @@ class DeclarationsConverter(
selfTypeSource: FirSourceElement?,
classWrapper: ClassWrapper,
delegatedConstructorSource: FirLightSourceElement?,
isEnumEntry: Boolean = false
isEnumEntry: Boolean = false,
containingClassIsExpectClass: Boolean
): PrimaryConstructor? {
if (primaryConstructor == null && !classWrapper.isEnumEntry() && classWrapper.hasSecondaryConstructor) return null
val classKind = classWrapper.classBuilder.classKind
if (primaryConstructor == null && (classWrapper.hasExpect() && classKind == ClassKind.ENUM_CLASS)) return null
if (primaryConstructor == null && (containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS)) return null
if (classWrapper.isInterface()) return null
var modifiers = Modifier()
@@ -808,7 +814,7 @@ class DeclarationsConverter(
modifiers.getVisibility().takeUnless { it == Visibilities.Unknown }
}
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility, Modality.FINAL).apply {
isExpect = modifiers.hasExpect() || classWrapper.hasExpect()
isExpect = modifiers.hasExpect() || context.containerIsExpect
isActual = modifiers.hasActual()
isInner = classWrapper.isInner()
isFromSealedClass = classWrapper.isSealed() && explicitVisibility !== Visibilities.Private
@@ -877,7 +883,7 @@ class DeclarationsConverter(
val explicitVisibility = modifiers.getVisibility()
val status = FirDeclarationStatusImpl(explicitVisibility, Modality.FINAL).apply {
isExpect = modifiers.hasExpect() || classWrapper.hasExpect()
isExpect = modifiers.hasExpect() || context.containerIsExpect
isActual = modifiers.hasActual()
isInner = classWrapper.isInner()
isFromSealedClass = classWrapper.isSealed() && explicitVisibility !== Visibilities.Private
@@ -976,7 +982,8 @@ class DeclarationsConverter(
}
val typeAliasName = identifier.nameAsSafeName()
return withChildClassName(typeAliasName) {
val typeAliasIsExpect = modifiers.hasExpect() || context.containerIsExpect
return withChildClassName(typeAliasName, isExpect = typeAliasIsExpect) {
val classSymbol = FirTypeAliasSymbol(context.currentClassId)
val firTypeParameters = mutableListOf<FirTypeParameter>()
@@ -985,14 +992,13 @@ class DeclarationsConverter(
firTypeParameters += convertTypeParameters(it, emptyList(), classSymbol)
}
}
return@withChildClassName buildTypeAlias {
source = typeAlias.toFirSourceElement()
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
name = typeAliasName
status = FirDeclarationStatusImpl(modifiers.getVisibility(), Modality.FINAL).apply {
isExpect = modifiers.hasExpect()
isExpect = typeAliasIsExpect
isActual = modifiers.hasActual()
}
symbol = classSymbol
@@ -1128,7 +1134,7 @@ class DeclarationsConverter(
} else null
status = FirDeclarationStatusImpl(propertyVisibility, modifiers.getModality(isClassOrObject = false)).apply {
isExpect = modifiers.hasExpect() || classWrapper?.hasExpect() == true
isExpect = modifiers.hasExpect() || context.containerIsExpect
isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride()
isConst = modifiers.isConst()
@@ -1366,7 +1372,7 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseFunction
*/
fun convertFunctionDeclaration(functionDeclaration: LighterASTNode, classWrapper: ClassWrapper? = null): FirStatement {
fun convertFunctionDeclaration(functionDeclaration: LighterASTNode): FirStatement {
var modifiers = Modifier()
var identifier: String? = null
var valueParametersList: LighterASTNode? = null
@@ -1429,7 +1435,7 @@ class DeclarationsConverter(
if (isLocal) Visibilities.Local else modifiers.getVisibility(),
modifiers.getModality(isClassOrObject = false)
).apply {
isExpect = modifiers.hasExpect() || classWrapper?.hasExpect() == true
isExpect = modifiers.hasExpect() || context.containerIsExpect
isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride()
isOperator = modifiers.hasOperator()
@@ -462,11 +462,11 @@ open class RawFirBuilder(
}
}
private fun KtParameter.toFirProperty(firParameter: FirValueParameter, isExpect: Boolean): FirProperty {
private fun KtParameter.toFirProperty(firParameter: FirValueParameter): FirProperty {
require(hasValOrVar())
val type = typeReference.toFirOrErrorType()
val status = FirDeclarationStatusImpl(visibility, modality).apply {
this.isExpect = isExpect
isExpect = hasExpectModifier() || this@RawFirBuilder.context.containerIsExpect
isActual = hasActualModifier()
isOverride = hasModifier(OVERRIDE_KEYWORD)
isConst = hasModifier(CONST_KEYWORD)
@@ -630,7 +630,8 @@ open class RawFirBuilder(
delegatedSelfTypeRef: FirTypeRef?,
delegatedEnumSuperTypeRef: FirTypeRef?,
classKind: ClassKind,
containerTypeParameters: List<FirTypeParameterRef>
containerTypeParameters: List<FirTypeParameterRef>,
containingClassIsExpectClass: Boolean
): FirTypeRef {
var superTypeCallEntry: KtSuperTypeCallEntry? = null
var delegatedSuperTypeRef: FirTypeRef? = null
@@ -708,7 +709,7 @@ open class RawFirBuilder(
// it may be not possible to determine delegated super type right here
delegatedSuperTypeRef = delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef
val shouldNotGenerateImplicitPrimaryConstructor = hasExplicitPrimaryConstructor() || hasSecondaryConstructors() ||
(hasExpectModifier() && classKind != ClassKind.ENUM_CLASS)
(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS)
if ((this !is KtClass || !this.isInterface()) && (primaryConstructor != null || !shouldNotGenerateImplicitPrimaryConstructor)) {
val firPrimaryConstructor = primaryConstructor.toFirConstructor(
@@ -759,7 +760,7 @@ open class RawFirBuilder(
val explicitVisibility = this?.visibility?.takeUnless { it == Visibilities.Unknown }
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility(), Modality.FINAL).apply {
isExpect = this@toFirConstructor?.hasExpectModifier() == true || owner.hasExpectModifier()
isExpect = this@toFirConstructor?.hasExpectModifier() == true || this@RawFirBuilder.context.containerIsExpect
isActual = this@toFirConstructor?.hasActualModifier() == true
isInner = owner.hasModifier(INNER_KEYWORD)
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.Private
@@ -823,7 +824,7 @@ open class RawFirBuilder(
name = nameAsSafeName
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply {
isStatic = true
isExpect = containingClassOrObject?.hasExpectModifier() == true
isExpect = hasExpectModifier() || this@RawFirBuilder.context.containerIsExpect
}
symbol = FirEnumEntrySymbol(callableIdForName(nameAsSafeName))
if (ownerClassHasDefaultConstructor && ktEnumEntry.initializerList == null &&
@@ -832,7 +833,7 @@ open class RawFirBuilder(
return@buildEnumEntry
}
extractAnnotationsTo(this)
initializer = withChildClassName(nameAsSafeName) {
initializer = withChildClassName(nameAsSafeName, isExpect = false) {
buildAnonymousObjectExpression {
val enumEntrySource = toFirSourceElement(FirFakeSourceElementKind.EnumInitializer)
source = enumEntrySource
@@ -864,7 +865,7 @@ open class RawFirBuilder(
typeParameters
)
// Use ANONYMOUS_OBJECT_NAME for the owner class id for enum entry declarations (see KT-42351)
withChildClassName(ANONYMOUS_OBJECT_NAME, forceLocalContext = true) {
withChildClassName(ANONYMOUS_OBJECT_NAME, forceLocalContext = true, isExpect = false) {
for (declaration in ktEnumEntry.declarations) {
declarations += declaration.toFirDeclaration(
correctedEnumSelfTypeRef,
@@ -892,8 +893,10 @@ open class RawFirBuilder(
override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Unit): FirElement {
// NB: enum entry nested classes are considered local by FIR design (see discussion in KT-45115)
val isLocal = classOrObject.isLocal || classOrObject.getStrictParentOfType<KtEnumEntry>() != null
val classIsExpect = classOrObject.hasExpectModifier() || context.containerIsExpect
return withChildClassName(
classOrObject.nameAsSafeName,
isExpect = classIsExpect,
forceLocalContext = isLocal
) {
val classKind = when (classOrObject) {
@@ -910,7 +913,7 @@ open class RawFirBuilder(
if (isLocal) Visibilities.Local else classOrObject.visibility,
classOrObject.modality,
).apply {
isExpect = classOrObject.hasExpectModifier()
isExpect = classIsExpect
isActual = classOrObject.hasActualModifier()
isInner = classOrObject.hasModifier(INNER_KEYWORD)
isCompanion = (classOrObject as? KtObjectDeclaration)?.isCompanion() == true
@@ -950,7 +953,8 @@ open class RawFirBuilder(
delegatedSelfType,
null,
classKind,
typeParameters
typeParameters,
containingClassIsExpectClass = classIsExpect
)
val primaryConstructor = classOrObject.primaryConstructor
@@ -960,7 +964,7 @@ open class RawFirBuilder(
firPrimaryConstructor.valueParameters
).forEach { (ktParameter, firParameter) ->
if (ktParameter.hasValOrVar()) {
addDeclaration(ktParameter.toFirProperty(firParameter, classOrObject.hasExpectModifier()))
addDeclaration(ktParameter.toFirProperty(firParameter))
}
}
}
@@ -1002,11 +1006,11 @@ open class RawFirBuilder(
baseModuleData,
context.packageFqName,
context.className,
classOrObject.hasExpectModifier()
classIsExpect
)
generateValueOfFunction(
baseModuleData, context.packageFqName, context.className,
classOrObject.hasExpectModifier()
classIsExpect
)
}
@@ -1021,7 +1025,7 @@ open class RawFirBuilder(
override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression, data: Unit): FirElement {
val objectDeclaration = expression.objectDeclaration
return withChildClassName(ANONYMOUS_OBJECT_NAME, forceLocalContext = true) {
return withChildClassName(ANONYMOUS_OBJECT_NAME, forceLocalContext = true, isExpect = false) {
buildAnonymousObjectExpression {
val sourceElement = objectDeclaration.toFirSourceElement()
source = sourceElement
@@ -1043,7 +1047,8 @@ open class RawFirBuilder(
delegatedSelfType,
null,
ClassKind.CLASS,
containerTypeParameters = emptyList()
containerTypeParameters = emptyList(),
containingClassIsExpectClass = false
)
for (declaration in objectDeclaration.declarations) {
@@ -1061,14 +1066,15 @@ open class RawFirBuilder(
}
override fun visitTypeAlias(typeAlias: KtTypeAlias, data: Unit): FirElement {
return withChildClassName(typeAlias.nameAsSafeName) {
val typeAliasIsExpect = typeAlias.hasExpectModifier() || context.containerIsExpect
return withChildClassName(typeAlias.nameAsSafeName, isExpect = typeAliasIsExpect) {
buildTypeAlias {
source = typeAlias.toFirSourceElement()
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
name = typeAlias.nameAsSafeName
status = FirDeclarationStatusImpl(typeAlias.visibility, Modality.FINAL).apply {
isExpect = typeAlias.hasExpectModifier()
isExpect = typeAliasIsExpect
isActual = typeAlias.hasActualModifier()
}
symbol = FirTypeAliasSymbol(context.currentClassId)
@@ -1108,7 +1114,7 @@ open class RawFirBuilder(
if (function.isLocal) Visibilities.Local else function.visibility,
function.modality,
).apply {
isExpect = function.hasExpectModifier() || function.containingClassOrObject?.hasExpectModifier() == true
isExpect = function.hasExpectModifier() || context.containerIsExpect
isActual = function.hasActualModifier()
isOverride = function.hasModifier(OVERRIDE_KEYWORD)
isOperator = function.hasModifier(OPERATOR_KEYWORD)
@@ -1293,7 +1299,7 @@ open class RawFirBuilder(
returnTypeRef = delegatedSelfTypeRef
val explicitVisibility = visibility
status = FirDeclarationStatusImpl(explicitVisibility, Modality.FINAL).apply {
isExpect = hasExpectModifier() || owner.hasExpectModifier()
isExpect = hasExpectModifier() || this@RawFirBuilder.context.containerIsExpect
isActual = hasActualModifier()
isInner = owner.hasModifier(INNER_KEYWORD)
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.Private
@@ -1436,7 +1442,7 @@ open class RawFirBuilder(
setter = this@toFirProperty.setter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = false)
status = FirDeclarationStatusImpl(visibility, modality).apply {
isExpect = hasExpectModifier() || containingClassOrObject?.hasExpectModifier() == true
isExpect = hasExpectModifier() || this@RawFirBuilder.context.containerIsExpect
isActual = hasActualModifier()
isOverride = hasModifier(OVERRIDE_KEYWORD)
isConst = hasModifier(CONST_KEYWORD)
@@ -66,12 +66,15 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
/**** Class name utils ****/
inline fun <T> withChildClassName(
name: Name,
isExpect: Boolean,
forceLocalContext: Boolean = false,
l: () -> T
): T {
context.className = context.className.child(name)
val oldForcedLocalContext = context.forcedLocalContext
context.forcedLocalContext = forceLocalContext || context.forcedLocalContext
val previousIsExpect = context.containerIsExpect
context.containerIsExpect = previousIsExpect || isExpect
val dispatchReceiversNumber = context.dispatchReceiverTypesStack.size
return try {
l()
@@ -86,6 +89,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
context.className = context.className.parent()
context.forcedLocalContext = oldForcedLocalContext
context.containerIsExpect = previousIsExpect
}
}
@@ -33,6 +33,7 @@ class Context<T> {
var forcedElementSourceKind: FirSourceElementKind? = null
val dispatchReceiverTypesStack = mutableListOf<ConeClassLikeType>()
var containerIsExpect: Boolean = false
fun pushFirTypeParameters(notNested: Boolean, parameters: List<FirTypeParameterRef>) {
capturedTypeParameters.add(StatusFirTypeParameterSymbolList(notNested, parameters.map { it.symbol }))
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
internal class RawFirNonLocalDeclarationBuilder private constructor(
session: FirSession,
@@ -123,7 +124,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
val classOrObject = parent.psi
check(classOrObject is KtClassOrObject)
withChildClassName(classOrObject.nameAsSafeName, false) {
withChildClassName(classOrObject.nameAsSafeName, isExpect = classOrObject.hasExpectModifier() || context.containerIsExpect) {
withCapturedTypeParameters(parent.isInner, parent.typeParameters.subList(0, classOrObject.typeParameters.size)) {
registerSelfType(classOrObject.toDelegatedSelfType(parent))
return moveNext(iterator, parent)