From 797b58669bec970b4e8cbfd6672e1866e1e529e0 Mon Sep 17 00:00:00 2001 From: "simon.ogorodnik" Date: Mon, 6 Apr 2020 23:34:22 +0300 Subject: [PATCH] [FIR] Support captured type parameters in lightTree2fir --- .../kotlin/fir/builder/BaseFirBuilder.kt | 45 +-- .../converter/DeclarationsConverter.kt | 293 ++++++++++-------- .../kotlin/fir/lightTree/fir/ClassWrapper.kt | 2 +- 3 files changed, 172 insertions(+), 168 deletions(-) diff --git a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index 6733aa5b4c5..2d891ae4909 100644 --- a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -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(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(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 { - return delegatedSelfTypeRef.coneTypeSafe() - ?.typeArguments - ?.map { - buildConstructedClassTypeParameterRef { - symbol = ((it as ConeTypeParameterType).lookupTag.symbol as FirTypeParameterSymbol) - } - } - ?: emptyList() - } - fun constructorTypeParametersFromConstructedClass(ownerTypeParameters: List): List { return ownerTypeParameters.mapNotNull { val declaredTypeParameter = (it as? FirTypeParameter) ?: return@mapNotNull null diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index f37fe2005b2..08a4ff9a868 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -334,14 +334,11 @@ class DeclarationsConverter( var identifier: String? = null val firTypeParameters = mutableListOf() var primaryConstructor: LighterASTNode? = null - val superTypeRefs = mutableListOf() - val superTypeCallEntry = mutableListOf() - var delegatedSuperTypeRef: FirTypeRef? = null val typeConstraints = mutableListOf() 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() + + 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() + 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() - 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() - var getter: FirPropertyAccessor? = null - var setter: FirPropertyAccessor? = null + val accessors = mutableListOf() 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(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(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) diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt index 31a0e86ee5e..3f58c11fddd 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt @@ -27,7 +27,7 @@ class ClassWrapper( val hasDefaultConstructor: Boolean, val delegatedSelfTypeRef: FirTypeRef, val delegatedSuperTypeRef: FirTypeRef, - val superTypeCallEntry: MutableList, + val superTypeCallEntry: List, ) { fun isObjectLiteral(): Boolean { return className == SpecialNames.NO_NAME_PROVIDED && isObject()