[FIR] Support captured type parameters in lightTree2fir

This commit is contained in:
simon.ogorodnik
2020-04-06 23:34:22 +03:00
parent 9db69c0b08
commit 797b58669b
3 changed files with 172 additions and 168 deletions
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.builder
import com.intellij.psi.tree.IElementType
import kotlinx.collections.immutable.mutate
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -22,11 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.builder.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.ANONYMOUS_CLASS_ID
import org.jetbrains.kotlin.fir.symbols.impl.FirErrorFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
@@ -81,6 +76,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
context.capturedTypeParameters.addAll(0, typeParameters.map { typeParameter -> typeParameter.symbol })
}
fun clearCapturedTypeParameters() {
context.capturedTypeParameters = context.capturedTypeParameters.clear()
}
fun callableIdForName(name: Name, local: Boolean = false) =
when {
local -> CallableId(name)
@@ -145,41 +144,23 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
}
fun T?.toDelegatedSelfType(firClass: AbstractFirRegularClassBuilder): FirResolvedTypeRef {
fun T?.toDelegatedSelfType(firClass: AbstractFirRegularClassBuilder): FirResolvedTypeRef =
toDelegatedSelfType(firClass, firClass.symbol)
fun T?.toDelegatedSelfType(firObject: FirAnonymousObjectBuilder): FirResolvedTypeRef =
toDelegatedSelfType(firObject, firObject.symbol)
private fun T?.toDelegatedSelfType(firClass: FirClassBuilder, symbol: FirClassLikeSymbol<*>): FirResolvedTypeRef {
return buildResolvedTypeRef {
source = this@toDelegatedSelfType?.toFirSourceElement()
type = ConeClassLikeTypeImpl(
firClass.symbol.toLookupTag(),
symbol.toLookupTag(),
firClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
false
)
}
}
fun T?.toDelegatedSelfType(firObject: FirAnonymousObjectBuilder): FirResolvedTypeRef {
return buildResolvedTypeRef {
source = this@toDelegatedSelfType?.toFirSourceElement()
type = ConeClassLikeTypeImpl(
firObject.symbol.toLookupTag(),
firObject.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
false
)
}
}
fun typeParametersFromSelfType(
delegatedSelfTypeRef: FirTypeRef
): List<FirTypeParameterRef> {
return delegatedSelfTypeRef.coneTypeSafe<ConeKotlinType>()
?.typeArguments
?.map {
buildConstructedClassTypeParameterRef {
symbol = ((it as ConeTypeParameterType).lookupTag.symbol as FirTypeParameterSymbol)
}
}
?: emptyList()
}
fun constructorTypeParametersFromConstructedClass(ownerTypeParameters: List<FirTypeParameterRef>): List<FirTypeParameterRef> {
return ownerTypeParameters.mapNotNull {
val declaredTypeParameter = (it as? FirTypeParameter) ?: return@mapNotNull null
@@ -334,14 +334,11 @@ class DeclarationsConverter(
var identifier: String? = null
val firTypeParameters = mutableListOf<FirTypeParameter>()
var primaryConstructor: LighterASTNode? = null
val superTypeRefs = mutableListOf<FirTypeRef>()
val superTypeCallEntry = mutableListOf<FirExpression>()
var delegatedSuperTypeRef: FirTypeRef? = null
val typeConstraints = mutableListOf<TypeConstraint>()
var classBody: LighterASTNode? = null
var superTypeList: LighterASTNode? = null
var typeParameterList: LighterASTNode? = null
var delegatedConstructorSource: FirLightSourceElement? = null
classNode.forEachChildren {
when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it)
@@ -351,12 +348,7 @@ class DeclarationsConverter(
IDENTIFIER -> identifier = it.asText
TYPE_PARAMETER_LIST -> typeParameterList = it
PRIMARY_CONSTRUCTOR -> primaryConstructor = it
SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).let {
delegatedSuperTypeRef = it.delegatedSuperTypeRef
superTypeRefs += it.superTypesRef
superTypeCallEntry += it.delegatedConstructorArguments
delegatedConstructorSource = it.delegatedConstructorSource
}
SUPER_TYPE_LIST -> superTypeList = it
TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
CLASS_BODY -> classBody = it
}
@@ -375,104 +367,121 @@ class DeclarationsConverter(
val isLocal = isClassLocal(classNode) { getParent() }
return withChildClassName(className) {
val status = FirDeclarationStatusImpl(
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
modifiers.getModality()
).apply {
isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual()
isInner = modifiers.isInner()
isCompanion = modifiers.isCompanion() && classKind == ClassKind.OBJECT
isData = modifiers.isDataClass() && classKind != ClassKind.OBJECT
isInline = modifiers.hasInline()
}
withCapturedTypeParameters {
val status = FirDeclarationStatusImpl(
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
modifiers.getModality()
).apply {
isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual()
isInner = modifiers.isInner()
isCompanion = modifiers.isCompanion() && classKind == ClassKind.OBJECT
isData = modifiers.isDataClass() && classKind != ClassKind.OBJECT
isInline = modifiers.hasInline()
}
val classBuilder = if (status.modality == Modality.SEALED) {
FirSealedClassBuilder()
} else {
FirClassImplBuilder()
}
val classBuilder = if (status.modality == Modality.SEALED) {
FirSealedClassBuilder()
} else {
FirClassImplBuilder()
}
classBuilder.apply {
source = classNode.toFirSourceElement()
session = baseSession
name = className
this.status = status
this.classKind = classKind
scopeProvider = baseScopeProvider
symbol = FirRegularClassSymbol(context.currentClassId)
annotations += modifiers.annotations
typeParameters += firTypeParameters
classBuilder.apply {
source = classNode.toFirSourceElement()
session = baseSession
name = className
this.status = status
this.classKind = classKind
scopeProvider = baseScopeProvider
symbol = FirRegularClassSymbol(context.currentClassId)
annotations += modifiers.annotations
typeParameters += firTypeParameters
val selfType = classNode.toDelegatedSelfType(this)
if (!status.isInner) clearCapturedTypeParameters()
typeParameters += context.capturedTypeParameters.map { buildOuterClassTypeParameterRef { symbol = it } }
addCapturedTypeParameters(firTypeParameters)
when {
modifiers.isEnum() && (classKind == ClassKind.ENUM_CLASS) -> {
delegatedSuperTypeRef = buildResolvedTypeRef {
type = ConeClassLikeTypeImpl(
implicitEnumType.type.lookupTag,
arrayOf(selfType.coneTypeUnsafe()),
isNullable = false
)
val selfType = classNode.toDelegatedSelfType(this)
val delegationSpecifiers = superTypeList?.let { convertDelegationSpecifiers(it) }
var delegatedSuperTypeRef: FirTypeRef? = delegationSpecifiers?.delegatedSuperTypeRef
val delegatedConstructorSource: FirLightSourceElement? = delegationSpecifiers?.delegatedConstructorSource
val superTypeCallEntry = delegationSpecifiers?.delegatedConstructorArguments.orEmpty()
val superTypeRefs = mutableListOf<FirTypeRef>()
delegationSpecifiers?.let { superTypeRefs += it.superTypesRef }
when {
modifiers.isEnum() && (classKind == ClassKind.ENUM_CLASS) -> {
delegatedSuperTypeRef = buildResolvedTypeRef {
type = ConeClassLikeTypeImpl(
implicitEnumType.type.lookupTag,
arrayOf(selfType.coneTypeUnsafe()),
isNullable = false
)
}
superTypeRefs += delegatedSuperTypeRef
}
modifiers.isAnnotation() && (classKind == ClassKind.ANNOTATION_CLASS) -> {
superTypeRefs += implicitAnnotationType
}
superTypeRefs += delegatedSuperTypeRef!!
}
modifiers.isAnnotation() && (classKind == ClassKind.ANNOTATION_CLASS) -> {
superTypeRefs += implicitAnnotationType
val defaultDelegatedSuperTypeRef = implicitAnyType
superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef }
this.superTypeRefs += superTypeRefs
val secondaryConstructors = classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR)
val classWrapper = ClassWrapper(
className, modifiers, classKind, classBuilder,
hasPrimaryConstructor = primaryConstructor != null,
hasSecondaryConstructor = secondaryConstructors.isNotEmpty(),
hasDefaultConstructor = if (primaryConstructor != null) !primaryConstructor!!.hasValueParameters()
else secondaryConstructors.isEmpty() || secondaryConstructors.any { !it.hasValueParameters() },
delegatedSelfTypeRef = selfType,
delegatedSuperTypeRef = delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef,
superTypeCallEntry = superTypeCallEntry
)
//parse primary constructor
val primaryConstructorWrapper = convertPrimaryConstructor(primaryConstructor, classWrapper, delegatedConstructorSource)
val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
firPrimaryConstructor?.let { declarations += it }
val properties = mutableListOf<FirProperty>()
if (primaryConstructor != null && firPrimaryConstructor != null) {
//parse properties
properties += primaryConstructorWrapper.valueParameters
.filter { it.hasValOrVar() }
.map { it.toFirProperty(baseSession, callableIdForName(it.firValueParameter.name)) }
addDeclarations(properties)
}
}
val defaultDelegatedSuperTypeRef = implicitAnyType
superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef }
//parse declarations
classBody?.let {
addDeclarations(convertClassBody(it, classWrapper))
}
this.superTypeRefs += superTypeRefs
//parse data class
if (modifiers.isDataClass() && firPrimaryConstructor != null) {
val zippedParameters = properties.map { it.source?.lightNode!! to it }
zippedParameters.generateComponentFunctions(
baseSession, this, context.packageFqName, context.className, firPrimaryConstructor
)
zippedParameters.generateCopyFunction(
baseSession, classNode, this, context.packageFqName, context.className, firPrimaryConstructor
)
// TODO: equals, hashCode, toString
}
val secondaryConstructors = classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR)
val classWrapper = ClassWrapper(
className, modifiers, classKind, classBuilder,
hasPrimaryConstructor = primaryConstructor != null,
hasSecondaryConstructor = secondaryConstructors.isNotEmpty(),
hasDefaultConstructor = if (primaryConstructor != null) !primaryConstructor!!.hasValueParameters()
else secondaryConstructors.isEmpty() || secondaryConstructors.any { !it.hasValueParameters() },
delegatedSelfTypeRef = selfType,
delegatedSuperTypeRef = delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef, superTypeCallEntry = superTypeCallEntry
)
//parse primary constructor
val primaryConstructorWrapper = convertPrimaryConstructor(primaryConstructor, classWrapper, delegatedConstructorSource)
val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
firPrimaryConstructor?.let { declarations += it }
val properties = mutableListOf<FirProperty>()
if (primaryConstructor != null && firPrimaryConstructor != null) {
//parse properties
properties += primaryConstructorWrapper.valueParameters
.filter { it.hasValOrVar() }
.map { it.toFirProperty(baseSession, callableIdForName(it.firValueParameter.name)) }
addDeclarations(properties)
}
//parse declarations
classBody?.let {
addDeclarations(convertClassBody(it, classWrapper))
}
//parse data class
if (modifiers.isDataClass() && firPrimaryConstructor != null) {
val zippedParameters = properties.map { it.source?.lightNode!! to it }
zippedParameters.generateComponentFunctions(
baseSession, this, context.packageFqName, context.className, firPrimaryConstructor
)
zippedParameters.generateCopyFunction(
baseSession, classNode, this, context.packageFqName, context.className, firPrimaryConstructor
)
// TODO: equals, hashCode, toString
}
if (modifiers.isEnum()) {
generateValuesFunction(baseSession, context.packageFqName, context.className)
generateValueOfFunction(baseSession, context.packageFqName, context.className)
}
}.build()
if (modifiers.isEnum()) {
generateValuesFunction(baseSession, context.packageFqName, context.className)
generateValueOfFunction(baseSession, context.packageFqName, context.className)
}
}.build()
}
}
}
@@ -512,6 +521,7 @@ class DeclarationsConverter(
classKind = ClassKind.OBJECT
scopeProvider = baseScopeProvider
symbol = FirAnonymousObjectSymbol()
typeParameters += context.capturedTypeParameters.map { buildOuterClassTypeParameterRef { symbol = it } }
val delegatedSelfType = objectLiteral.toDelegatedSelfType(this)
annotations += modifiers.annotations
this.superTypeRefs += superTypeRefs
@@ -527,7 +537,8 @@ class DeclarationsConverter(
superTypeCallEntry = superTypeCallEntry
)
//parse primary constructor
convertPrimaryConstructor(primaryConstructor, classWrapper, delegatedConstructorSource)?.let { this.declarations += it.firConstructor }
convertPrimaryConstructor(primaryConstructor, classWrapper, delegatedConstructorSource)
?.let { this.declarations += it.firConstructor }
//parse declarations
classBody?.let {
@@ -677,7 +688,7 @@ class DeclarationsConverter(
this.status = status
symbol = FirConstructorSymbol(callableIdForClassConstructor())
annotations += modifiers.annotations
typeParameters += typeParametersFromSelfType(classWrapper.delegatedSelfTypeRef)
typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters)
this.valueParameters += valueParameters.map { it.firValueParameter }
delegatedConstructor = firDelegatedCall
}, valueParameters
@@ -743,7 +754,7 @@ class DeclarationsConverter(
context.firFunctionTargets += target
annotations += modifiers.annotations
typeParameters += typeParametersFromSelfType(delegatedSelfTypeRef)
typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters)
valueParameters += firValueParameters.map { it.firValueParameter }
body = convertFunctionBody(block, null)
context.firFunctionTargets.removeLast()
@@ -833,8 +844,7 @@ class DeclarationsConverter(
var receiverType: FirTypeRef? = null
var returnType: FirTypeRef = implicitType
val typeConstraints = mutableListOf<TypeConstraint>()
var getter: FirPropertyAccessor? = null
var setter: FirPropertyAccessor? = null
val accessors = mutableListOf<LighterASTNode>()
var propertyInitializer: FirExpression? = null
var typeParameterList: LighterASTNode? = null
property.forEachChildren {
@@ -848,8 +858,7 @@ class DeclarationsConverter(
PROPERTY_DELEGATE -> delegateExpression = it
VAR_KEYWORD -> isVar = true
PROPERTY_ACCESSOR -> {
val propertyAccessor = convertGetterOrSetter(it, returnType)
if (propertyAccessor.isGetter) getter = propertyAccessor else setter = propertyAccessor
accessors += it
}
else -> if (it.isExpression()) propertyInitializer = expressionConverter.getAsFirExpression(it, "Should have initializer")
}
@@ -899,35 +908,47 @@ class DeclarationsConverter(
this.isLocal = false
receiverTypeRef = receiverType
symbol = FirPropertySymbol(callableIdForName(propertyName))
val delegateBuilder = delegateExpression?.let {
FirWrappedDelegateExpressionBuilder().apply {
source = it.toFirSourceElement()
expression = expressionConverter.getAsFirExpression(it, "Should have delegate")
withCapturedTypeParameters {
typeParameters += firTypeParameters
addCapturedTypeParameters(firTypeParameters)
val delegateBuilder = delegateExpression?.let {
FirWrappedDelegateExpressionBuilder().apply {
source = it.toFirSourceElement()
expression = expressionConverter.getAsFirExpression(it, "Should have delegate")
}
}
}
status = FirDeclarationStatusImpl(modifiers.getVisibility(), modifiers.getModality()).apply {
isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride()
isConst = modifiers.isConst()
isLateInit = modifiers.hasLateinit()
}
typeParameters += firTypeParameters
this.getter = getter ?: FirDefaultPropertyGetter(null, session, returnType, modifiers.getVisibility())
this.setter = if (isVar) setter ?: FirDefaultPropertySetter(null, session, returnType, modifiers.getVisibility()) else null
status = FirDeclarationStatusImpl(modifiers.getVisibility(), modifiers.getModality()).apply {
isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride()
isConst = modifiers.isConst()
isLateInit = modifiers.hasLateinit()
}
val receiver = delegateExpression?.let {
expressionConverter.getAsFirExpression<FirExpression>(it, "Should have delegate")
val convertedAccessors = accessors.map { convertGetterOrSetter(it, returnType) }
this.getter = convertedAccessors.find { it.isGetter }
?: FirDefaultPropertyGetter(null, session, returnType, modifiers.getVisibility())
this.setter =
if (isVar) {
convertedAccessors.find { it.isSetter }
?: FirDefaultPropertySetter(null, session, returnType, modifiers.getVisibility())
} else null
val receiver = delegateExpression?.let {
expressionConverter.getAsFirExpression<FirExpression>(it, "Should have delegate")
}
generateAccessorsByDelegate(
delegateBuilder,
classWrapper?.classBuilder,
baseSession,
isExtension = receiverType != null,
stubMode,
receiver
)
}
generateAccessorsByDelegate(
delegateBuilder,
classWrapper?.classBuilder,
baseSession,
isExtension = receiverType != null,
stubMode,
receiver
)
}
annotations += modifiers.annotations
}
@@ -1150,12 +1171,14 @@ class DeclarationsConverter(
context.firFunctionTargets += target
annotations += modifiers.annotations
if (this is FirSimpleFunctionBuilder) {
typeParameters += firTypeParameters
withCapturedTypeParameters {
if (this is FirSimpleFunctionBuilder) {
typeParameters += firTypeParameters
addCapturedTypeParameters(typeParameters)
}
valueParametersList?.let { list -> valueParameters += convertValueParameters(list).map { it.firValueParameter } }
body = convertFunctionBody(block, expression)
}
valueParametersList?.let { list -> valueParameters += convertValueParameters(list).map { it.firValueParameter } }
body = convertFunctionBody(block, expression)
context.firFunctionTargets.removeLast()
}.build().also {
target.bind(it)
@@ -27,7 +27,7 @@ class ClassWrapper(
val hasDefaultConstructor: Boolean,
val delegatedSelfTypeRef: FirTypeRef,
val delegatedSuperTypeRef: FirTypeRef,
val superTypeCallEntry: MutableList<FirExpression>,
val superTypeCallEntry: List<FirExpression>,
) {
fun isObjectLiteral(): Boolean {
return className == SpecialNames.NO_NAME_PROVIDED && isObject()