diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt index 8d3ababed30..f53b00f5b73 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt @@ -9,23 +9,75 @@ import com.intellij.lang.LighterASTNode import com.intellij.openapi.util.Ref import com.intellij.psi.tree.IElementType import com.intellij.util.diff.FlyweightCapableTreeStructure +import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.builder.BaseFirBuilder +import org.jetbrains.kotlin.fir.builder.escapedStringToCharacter import org.jetbrains.kotlin.fir.types.impl.* import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression +import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName +import org.jetbrains.kotlin.name.Name open class BaseConverter( session: FirSession, private val tree: FlyweightCapableTreeStructure -) { - protected val implicitUnitType = FirImplicitUnitTypeRef(session, null) - protected val implicitAnyType = FirImplicitAnyTypeRef(session, null) - protected val implicitEnumType = FirImplicitEnumTypeRef(session, null) - protected val implicitAnnotationType = FirImplicitAnnotationTypeRef(session, null) +) : BaseFirBuilder(session) { protected val implicitType = FirImplicitTypeRefImpl(session, null) + override val LighterASTNode.elementType: IElementType + get() = this.tokenType + + override val LighterASTNode.asText: String + get() = this.toString() + + override val LighterASTNode.unescapedValue: String + get() { + val escape = this.asText + return escapedStringToCharacter(escape)?.toString() + ?: escape.replace("\\", "").replace("u", "\\u") + } + + override fun LighterASTNode.getReferencedNameAsName(): Name { + return this.asText.nameAsSafeName() + } + + override fun LighterASTNode.getLabelName(): String? { + this.forEachChildren { + when (it.tokenType) { + KtNodeTypes.LABEL_QUALIFIER -> return it.asText.replaceFirst("@", "") + } + } + + return null + } + + override fun LighterASTNode.getExpressionInParentheses(): LighterASTNode? { + this.forEachChildren { + if (it.isExpression()) return it + } + + return null + } + + override fun LighterASTNode.getChildNodeByType(type: IElementType): LighterASTNode? { + return this.getChildNodesByType(type).firstOrNull() + } + + override val LighterASTNode?.selectorExpression: LighterASTNode? + get() { + var isSelector = false + this?.forEachChildren { + when (it.tokenType) { + DOT, SAFE_ACCESS -> isSelector = true + else -> if (isSelector) return it + } + } + return null + } + fun LighterASTNode.getParent(): LighterASTNode? { return tree.getParent(this) } @@ -38,7 +90,7 @@ open class BaseConverter( } ?: listOf() } - fun LighterASTNode?.getChildrenAsArray(): Array { + fun LighterASTNode?.getChildrenAsArray(): Array { if (this == null) return arrayOf() val kidsRef = Ref>() @@ -46,14 +98,6 @@ open class BaseConverter( return kidsRef.get() } - fun LighterASTNode.getExpressionInParentheses(): LighterASTNode? { - this.forEachChildren { - if (it.isExpression()) return it - } - - return null - } - protected inline fun LighterASTNode.forEachChildren(vararg skipTokens: KtToken, f: (LighterASTNode) -> Unit) { val kidsArray = this.getChildrenAsArray() for (kid in kidsArray) { diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt index 99521bcff10..6cfe05dbf5c 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt @@ -62,10 +62,6 @@ object ConverterUtil { return this.toString().replace("`", "") } - fun LighterASTNode.getAsString(): String { - return this.toString() - } - fun LighterASTNode.isExpression(): Boolean { return when (this.tokenType) { is KtNodeType, @@ -76,59 +72,6 @@ object ConverterUtil { } } - fun toDelegatedSelfType(firClass: FirRegularClass): FirTypeRef { - val typeParameters = firClass.typeParameters.map { - FirTypeParameterImpl(firClass.session, it.psi, FirTypeParameterSymbol(), it.name, Variance.INVARIANT, false).apply { - this.bounds += it.bounds - } - } - return FirResolvedTypeRefImpl( - firClass.session, - null, - ConeClassTypeImpl( - firClass.symbol.toLookupTag(), - typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(), - false - ) - ) - } - - fun FirExpression.toReturn(labelName: String? = null): FirReturnExpression { - return FirReturnExpressionImpl( - session, - null, - this - ).apply { - target = FirFunctionTarget(labelName) - val lastFunction = FunctionUtil.firFunctions.lastOrNull() - if (labelName == null) { - if (lastFunction != null) { - target.bind(lastFunction) - } else { - target.bind(FirErrorFunction(session, psi, "Cannot bind unlabeled return to a function")) - } - } else { - for (firFunction in FunctionUtil.firFunctions.asReversed()) { - when (firFunction) { - is FirAnonymousFunction -> { - if (firFunction.label?.name == labelName) { - target.bind(firFunction) - return@apply - } - } - is FirNamedFunction -> { - if (firFunction.name.asString() == labelName) { - target.bind(firFunction) - return@apply - } - } - } - } - target.bind(FirErrorFunction(session, psi, "Cannot bind label $labelName to a function")) - } - } - } - fun FirTypeParameterContainer.joinTypeParameters(typeConstraints: List) { typeConstraints.forEach { typeConstraint -> this.typeParameters.forEach { typeParameter -> @@ -141,13 +84,6 @@ object ConverterUtil { } } - fun typeParametersFromSelfType(delegatedSelfTypeRef: FirTypeRef): List { - return delegatedSelfTypeRef.coneTypeSafe() - ?.typeArguments - ?.map { ((it as ConeTypeParameterType).lookupTag.symbol as FirTypeParameterSymbol).fir } - ?: emptyList() - } - fun T.extractArgumentsFrom(container: List, stubMode: Boolean): T { if (!stubMode || this is FirAnnotationCall) { this.arguments += container @@ -176,152 +112,3 @@ object ConverterUtil { return false } } - -object ClassNameUtil { - lateinit var packageFqName: FqName - - inline fun withChildClassName(name: Name, l: () -> T): T { - className = className.child(name) - val t = l() - className = className.parent() - return t - } - - val currentClassId - get() = ClassId( - packageFqName, - className, false - ) - - fun callableIdForName(name: Name, local: Boolean = false) = - when { - local -> CallableId(name) - className == FqName.ROOT -> CallableId(packageFqName, name) - else -> CallableId( - packageFqName, - className, name - ) - } - - fun callableIdForClassConstructor() = - if (className == FqName.ROOT) CallableId(packageFqName, Name.special("")) - else CallableId( - packageFqName, - className, className.shortName() - ) - - var className: FqName = FqName.ROOT -} - -object FunctionUtil { - val firFunctions = mutableListOf() - val firFunctionCalls = mutableListOf() - val firLabels = mutableListOf() - val firLoops = mutableListOf() - - fun MutableList.removeLast() { - removeAt(size - 1) - } - - fun MutableList.pop(): T? { - val result = lastOrNull() - if (result != null) { - removeAt(size - 1) - } - return result - } -} - -object DataClassUtil { - fun generateComponentFunctions( - session: FirSession, firClass: FirClassImpl, properties: List - ) { - var componentIndex = 1 - for (property in properties) { - if (!property.isVal && !property.isVar) continue - val name = Name.identifier("component$componentIndex") - componentIndex++ - val symbol = FirNamedFunctionSymbol( - CallableId( - ClassNameUtil.packageFqName, - ClassNameUtil.className, - name - ) - ) - firClass.addDeclaration( - FirMemberFunctionImpl( - session, null, symbol, name, - Visibilities.PUBLIC, Modality.FINAL, - isExpect = false, isActual = false, - isOverride = false, isOperator = false, - isInfix = false, isInline = false, - isTailRec = false, isExternal = false, - isSuspend = false, receiverTypeRef = null, - returnTypeRef = FirImplicitTypeRefImpl(session, null) - ).apply { - val componentFunction = this - body = FirSingleExpressionBlock( - session, - FirReturnExpressionImpl( - session, null, - FirQualifiedAccessExpressionImpl(session, null).apply { - val parameterName = property.name - calleeReference = FirResolvedCallableReferenceImpl( - session, null, - parameterName, property.symbol - ) - } - ).apply { - target = FirFunctionTarget(null) - target.bind(componentFunction) - } - ) - } - ) - } - } - - private val copyName = Name.identifier("copy") - - fun generateCopyFunction( - session: FirSession, firClass: FirClassImpl, - firPrimaryConstructor: FirConstructor, - properties: List - ) { - val symbol = FirNamedFunctionSymbol( - CallableId( - ClassNameUtil.packageFqName, - ClassNameUtil.className, - copyName - ) - ) - firClass.addDeclaration( - FirMemberFunctionImpl( - session, null, symbol, copyName, - Visibilities.PUBLIC, Modality.FINAL, - isExpect = false, isActual = false, - isOverride = false, isOperator = false, - isInfix = false, isInline = false, - isTailRec = false, isExternal = false, - isSuspend = false, receiverTypeRef = null, - returnTypeRef = firPrimaryConstructor.returnTypeRef//FirImplicitTypeRefImpl(session, this) - ).apply { - val copyFunction = this - for (property in properties) { - val name = property.name - valueParameters += FirValueParameterImpl( - session, null, name, - property.returnTypeRef, - FirQualifiedAccessExpressionImpl(session, null).apply { - calleeReference = FirResolvedCallableReferenceImpl(session, null, name, property.symbol) - }, - isCrossinline = false, isNoinline = false, isVararg = false - ) - } - - body = FirEmptyExpressionBlock(session) - } - ) - } -} - diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 825e95899d7..1b4791a795a 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -22,17 +22,11 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.* import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.joinTypeParameters import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toDelegatedSelfType -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isClassLocal -import org.jetbrains.kotlin.fir.lightTree.converter.DataClassUtil.generateComponentFunctions -import org.jetbrains.kotlin.fir.lightTree.converter.DataClassUtil.generateCopyFunction -import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast import org.jetbrains.kotlin.fir.lightTree.fir.* import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeModifier @@ -49,9 +43,11 @@ import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames +import org.jetbrains.kotlin.fir.builder.generateCopyFunction +import org.jetbrains.kotlin.fir.builder.generateComponentFunctions class DeclarationsConverter( - private val session: FirSession, + session: FirSession, private val stubMode: Boolean, tree: FlyweightCapableTreeStructure ) : BaseConverter(session, tree) { @@ -70,11 +66,11 @@ class DeclarationsConverter( val fileAnnotationList = mutableListOf() val importList = mutableListOf() val firDeclarationList = mutableListOf() - ClassNameUtil.packageFqName = FqName.ROOT + packageFqName = FqName.ROOT file.forEachChildren { when (it.tokenType) { FILE_ANNOTATION_LIST -> fileAnnotationList += convertFileAnnotationList(it) - PACKAGE_DIRECTIVE -> ClassNameUtil.packageFqName = convertPackageName(it) + PACKAGE_DIRECTIVE -> packageFqName = convertPackageName(it) IMPORT_LIST -> importList += convertImportDirectives(it) CLASS -> firDeclarationList += convertClass(it) FUN -> firDeclarationList += convertFunctionDeclaration(it) @@ -88,7 +84,7 @@ class DeclarationsConverter( session, null, fileName, - ClassNameUtil.packageFqName + packageFqName ) firFile.annotations += fileAnnotationList firFile.imports += importList @@ -141,7 +137,7 @@ class DeclarationsConverter( private fun convertImportAlias(importAlias: LighterASTNode): String? { importAlias.forEachChildren { when (it.tokenType) { - IDENTIFIER -> return it.getAsString() + IDENTIFIER -> return it.asText } } @@ -157,7 +153,7 @@ class DeclarationsConverter( var aliasName: String? = null importDirective.forEachChildren { when (it.tokenType) { - DOT_QUALIFIED_EXPRESSION, REFERENCE_EXPRESSION -> importedFqName = FqName(it.getAsString()) + DOT_QUALIFIED_EXPRESSION, REFERENCE_EXPRESSION -> importedFqName = FqName(it.asText) MUL -> isAllUnder = true IMPORT_ALIAS -> aliasName = convertImportAlias(it) } @@ -337,7 +333,7 @@ class DeclarationsConverter( CLASS_KEYWORD -> classKind = ClassKind.CLASS INTERFACE_KEYWORD -> classKind = ClassKind.INTERFACE OBJECT_KEYWORD -> classKind = ClassKind.OBJECT - IDENTIFIER -> identifier = it.getAsString() + IDENTIFIER -> identifier = it.asText TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it) PRIMARY_CONSTRUCTOR -> primaryConstructor = it SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).apply { @@ -368,11 +364,11 @@ class DeclarationsConverter( superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef } val isLocal = isClassLocal(classNode) { getParent() } - return ClassNameUtil.withChildClassName(className) { + return withChildClassName(className) { val firClass = FirClassImpl( session, null, - FirClassSymbol(ClassNameUtil.currentClassId), + FirClassSymbol(currentClassId), className, if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(), modifiers.getModality(), @@ -393,7 +389,7 @@ class DeclarationsConverter( session, className, modifiers, classKind, primaryConstructor != null, classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(), - toDelegatedSelfType(firClass), delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef, superTypeCallEntry + null.toDelegatedSelfType(firClass), delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef, superTypeCallEntry ) //parse primary constructor val primaryConstructorWrapper = convertPrimaryConstructor(primaryConstructor, classWrapper) @@ -405,7 +401,7 @@ class DeclarationsConverter( //parse properties properties += primaryConstructorWrapper.valueParameters .filter { it.hasValOrVar() } - .map { it.toFirProperty() } + .map { it.toFirProperty(callableIdForName(it.firValueParameter.name)) } firClass.addDeclarations(properties) } @@ -416,8 +412,9 @@ class DeclarationsConverter( //parse data class if (modifiers.isDataClass() && firPrimaryConstructor != null) { - generateComponentFunctions(session, firClass, properties) - generateCopyFunction(session, firClass, firPrimaryConstructor, properties) + val zippedParameters = MutableList(properties.size) { null }.zip(properties) + zippedParameters.generateComponentFunctions(session, firClass, packageFqName, Companion.className) + zippedParameters.generateCopyFunction(session, null, firClass, packageFqName, Companion.className, firPrimaryConstructor) // TODO: equals, hashCode, toString } @@ -488,7 +485,7 @@ class DeclarationsConverter( enumEntry.forEachChildren { when (it.tokenType) { MODIFIER_LIST -> modifiers = convertModifierList(it) - IDENTIFIER -> identifier = it.getAsString() + IDENTIFIER -> identifier = it.asText INITIALIZER_LIST -> { hasInitializerList = true enumSuperTypeCallEntry += convertInitializerList(it) @@ -498,11 +495,11 @@ class DeclarationsConverter( } val enumEntryName = identifier.nameAsSafeName() - return ClassNameUtil.withChildClassName(enumEntryName) { + return withChildClassName(enumEntryName) { val firEnumEntry = FirEnumEntryImpl( session, null, - FirClassSymbol(ClassNameUtil.currentClassId), + FirClassSymbol(currentClassId), enumEntryName ) firEnumEntry.annotations += modifiers.annotations @@ -517,7 +514,7 @@ class DeclarationsConverter( session, enumEntryName, modifiers, ClassKind.ENUM_ENTRY, hasPrimaryConstructor = true, hasSecondaryConstructor = classBodyNode.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(), - delegatedSelfTypeRef = toDelegatedSelfType(firEnumEntry), + delegatedSelfTypeRef = null.toDelegatedSelfType(firEnumEntry), delegatedSuperTypeRef = if (hasInitializerList) classWrapper.getFirUserTypeFromClassName() else defaultDelegatedSuperTypeRef, superTypeCallEntry = enumSuperTypeCallEntry ) @@ -594,7 +591,7 @@ class DeclarationsConverter( FirPrimaryConstructorImpl( session, null, - FirConstructorSymbol(ClassNameUtil.callableIdForClassConstructor()), + FirConstructorSymbol(callableIdForClassConstructor()), if (primaryConstructor != null) modifiers.getVisibility() else defaultVisibility, modifiers.hasExpect(), modifiers.hasActual(), @@ -602,7 +599,7 @@ class DeclarationsConverter( firDelegatedCall ).apply { annotations += modifiers.annotations - this.typeParameters += ConverterUtil.typeParametersFromSelfType(classWrapper.delegatedSelfTypeRef) + this.typeParameters += typeParametersFromSelfType(classWrapper.delegatedSelfTypeRef) this.valueParameters += valueParameters.map { it.firValueParameter } }, valueParameters ) @@ -652,7 +649,7 @@ class DeclarationsConverter( val firConstructor = FirConstructorImpl( session, null, - FirConstructorSymbol(ClassNameUtil.callableIdForClassConstructor()), + FirConstructorSymbol(callableIdForClassConstructor()), modifiers.getVisibility(), modifiers.hasExpect(), modifiers.hasActual(), @@ -660,12 +657,12 @@ class DeclarationsConverter( constructorDelegationCall ) - FunctionUtil.firFunctions += firConstructor + firFunctions += firConstructor firConstructor.annotations += modifiers.annotations - firConstructor.typeParameters += ConverterUtil.typeParametersFromSelfType(delegatedSelfTypeRef) + firConstructor.typeParameters += typeParametersFromSelfType(delegatedSelfTypeRef) firConstructor.valueParameters += firValueParameters.map { it.firValueParameter } firConstructor.body = convertFunctionBody(block, null) - FunctionUtil.firFunctions.removeLast() + firFunctions.removeLast() return firConstructor } @@ -681,12 +678,12 @@ class DeclarationsConverter( val firValueArguments = mutableListOf() constructorDelegationCall.forEachChildren { when (it.tokenType) { - CONSTRUCTOR_DELEGATION_REFERENCE -> if (it.getAsString() == "this") thisKeywordPresent = true + CONSTRUCTOR_DELEGATION_REFERENCE -> if (it.asText == "this") thisKeywordPresent = true VALUE_ARGUMENT_LIST -> firValueArguments += expressionConverter.convertValueArguments(it) } } - val isImplicit = constructorDelegationCall.getAsString().isEmpty() + val isImplicit = constructorDelegationCall.asText.isEmpty() val isThis = (isImplicit && classWrapper.hasPrimaryConstructor) || thisKeywordPresent val delegatedType = if (classWrapper.isObjectLiteral() || classWrapper.isInterface()) when { @@ -717,18 +714,18 @@ class DeclarationsConverter( typeAlias.forEachChildren { when (it.tokenType) { MODIFIER_LIST -> modifiers = convertModifierList(it) - IDENTIFIER -> identifier = it.getAsString() + IDENTIFIER -> identifier = it.asText TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it) TYPE_REFERENCE -> firType = convertType(it) } } val typeAliasName = identifier.nameAsSafeName() - return ClassNameUtil.withChildClassName(typeAliasName) { + return withChildClassName(typeAliasName) { return@withChildClassName FirTypeAliasImpl( session, null, - FirTypeAliasSymbol(ClassNameUtil.currentClassId), + FirTypeAliasSymbol(currentClassId), typeAliasName, modifiers.getVisibility(), modifiers.hasExpect(), @@ -760,7 +757,7 @@ class DeclarationsConverter( property.forEachChildren { when (it.tokenType) { MODIFIER_LIST -> modifiers = convertModifierList(it) - IDENTIFIER -> identifier = it.getAsString() + IDENTIFIER -> identifier = it.asText TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it) COLON -> isReturnType = true TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it) @@ -795,7 +792,7 @@ class DeclarationsConverter( FirMemberPropertyImpl( session, null, - FirPropertySymbol(ClassNameUtil.callableIdForName(propertyName)), + FirPropertySymbol(callableIdForName(propertyName)), propertyName, modifiers.getVisibility(), modifiers.getModality(), @@ -848,7 +845,7 @@ class DeclarationsConverter( entry.forEachChildren { when (it.tokenType) { MODIFIER_LIST -> modifiers = convertModifierList(it) - IDENTIFIER -> identifier = it.getAsString() + IDENTIFIER -> identifier = it.asText TYPE_REFERENCE -> firType = convertType(it) } } @@ -871,7 +868,7 @@ class DeclarationsConverter( var block: LighterASTNode? = null var expression: LighterASTNode? = null getterOrSetter.forEachChildren { - if (it.getAsString() == "set") isGetter = false + if (it.asText == "set") isGetter = false when (it.tokenType) { SET_KEYWORD -> isGetter = false MODIFIER_LIST -> modifiers = convertModifierList(it) @@ -889,7 +886,7 @@ class DeclarationsConverter( modifiers.getVisibility(), returnType ?: if (isGetter) propertyTypeRef else implicitUnitType ) - FunctionUtil.firFunctions += firAccessor + firFunctions += firAccessor firAccessor.annotations += modifiers.annotations if (!isGetter) { @@ -897,7 +894,7 @@ class DeclarationsConverter( } firAccessor.body = convertFunctionBody(block, expression) - FunctionUtil.firFunctions.removeLast() + firFunctions.removeLast() return firAccessor } @@ -949,7 +946,7 @@ class DeclarationsConverter( functionDeclaration.forEachChildren { when (it.tokenType) { MODIFIER_LIST -> modifiers = convertModifierList(it) - IDENTIFIER -> identifier = it.getAsString() + IDENTIFIER -> identifier = it.asText TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it) VALUE_PARAMETER_LIST -> valueParametersList = it //must convert later, because it can contains "return" COLON -> isReturnType = true @@ -976,7 +973,7 @@ class DeclarationsConverter( FirMemberFunctionImpl( session, null, - FirNamedFunctionSymbol(ClassNameUtil.callableIdForName(functionName, isLocal)), + FirNamedFunctionSymbol(callableIdForName(functionName, isLocal)), functionName, if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(), modifiers.getModality(), @@ -994,7 +991,7 @@ class DeclarationsConverter( ) } - FunctionUtil.firFunctions += firFunction + firFunctions += firFunction firFunction.annotations += modifiers.annotations if (firFunction is FirMemberFunctionImpl) { @@ -1004,7 +1001,7 @@ class DeclarationsConverter( valueParametersList?.let { firFunction.valueParameters += convertValueParameters(it).map { it.firValueParameter } } firFunction.body = convertFunctionBody(block, expression) - FunctionUtil.firFunctions.removeLast() + firFunctions.removeLast() return firFunction } @@ -1035,7 +1032,7 @@ class DeclarationsConverter( ) } return if (!stubMode) { - val blockTree = LightTree2Fir.buildLightTreeBlockExpression(block.getAsString()) + val blockTree = LightTree2Fir.buildLightTreeBlockExpression(block.asText) return DeclarationsConverter(session, stubMode, blockTree).convertBlockExpression(blockTree.root) } else { FirSingleExpressionBlock( @@ -1084,7 +1081,7 @@ class DeclarationsConverter( val firValueArguments = mutableListOf() constructorInvocation.forEachChildren { when (it.tokenType) { - CONSTRUCTOR_CALLEE -> if (it.getAsString().isNotEmpty()) firTypeRef = convertType(it) //is empty in enum entry constructor + CONSTRUCTOR_CALLEE -> if (it.asText.isNotEmpty()) firTypeRef = convertType(it) //is empty in enum entry constructor VALUE_ARGUMENT_LIST -> firValueArguments += expressionConverter.convertValueArguments(it) } } @@ -1149,7 +1146,7 @@ class DeclarationsConverter( when (it.tokenType) { //annotations will be saved later, on mapping stage with type parameters ANNOTATION, ANNOTATION_ENTRY -> annotations += convertAnnotation(it) - REFERENCE_EXPRESSION -> identifier = it.getAsString() + REFERENCE_EXPRESSION -> identifier = it.asText TYPE_REFERENCE -> firType = convertType(it) } } @@ -1167,7 +1164,7 @@ class DeclarationsConverter( typeParameter.forEachChildren { when (it.tokenType) { MODIFIER_LIST -> typeParameterModifiers = convertTypeParameterModifiers(it) - IDENTIFIER -> identifier = it.getAsString() + IDENTIFIER -> identifier = it.asText TYPE_REFERENCE -> firType = convertType(it) } } @@ -1190,7 +1187,7 @@ class DeclarationsConverter( * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRef */ fun convertType(type: LighterASTNode): FirTypeRef { - if (type.getAsString().isEmpty()) { + if (type.asText.isEmpty()) { return FirErrorTypeRefImpl(session, null, "Unwrapped type is null") } var typeModifiers = TypeModifier(session) //TODO what with suspend? @@ -1254,7 +1251,7 @@ class DeclarationsConverter( userType.forEachChildren { when (it.tokenType) { USER_TYPE -> simpleFirUserType = convertUserType(it) as? FirUserTypeRef //simple user type - REFERENCE_EXPRESSION -> identifier = it.getAsString() + REFERENCE_EXPRESSION -> identifier = it.asText TYPE_ARGUMENT_LIST -> firTypeArguments += convertTypeArguments(it) } } @@ -1363,7 +1360,7 @@ class DeclarationsConverter( MODIFIER_LIST -> modifiers = convertModifierList(it) VAL_KEYWORD -> isVal = true VAR_KEYWORD -> isVar = true - IDENTIFIER -> identifier = it.getAsString() + IDENTIFIER -> identifier = it.asText TYPE_REFERENCE -> firType = convertType(it) DESTRUCTURING_DECLARATION -> destructuringDeclaration = convertDestructingDeclaration(it) else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it, "Should have default value") diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index ba2d629e009..a89f610752d 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -21,14 +21,13 @@ import org.jetbrains.kotlin.fir.expressions.impl.* import org.jetbrains.kotlin.fir.labels.FirLabelImpl import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn -import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop -import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast -import org.jetbrains.kotlin.fir.lightTree.converter.utils.* +import org.jetbrains.kotlin.fir.lightTree.converter.utils.bangBangToWhen +import org.jetbrains.kotlin.fir.lightTree.converter.utils.generateDestructuringBlock +import org.jetbrains.kotlin.fir.lightTree.converter.utils.getOperationSymbol +import org.jetbrains.kotlin.fir.lightTree.converter.utils.qualifiedAccessTokens import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry import org.jetbrains.kotlin.fir.references.FirErrorNamedReference @@ -38,23 +37,25 @@ import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl -import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType -import org.jetbrains.kotlin.resolve.constants.evaluate.* import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions class ExpressionsConverter( - val session: FirSession, + session: FirSession, private val stubMode: Boolean, tree: FlyweightCapableTreeStructure, private val declarationsConverter: DeclarationsConverter ) : BaseConverter(session, tree) { + inline fun LighterASTNode?.toFirExpression(errorReason: String = ""): R { + return this?.let { convertExpression(it, errorReason) } as? R ?: (FirErrorExpressionImpl(session, null, errorReason) as R) + } + inline fun getAsFirExpression(expression: LighterASTNode?, errorReason: String = ""): R { return expression?.let { convertExpression(it, errorReason) } as? R ?: (FirErrorExpressionImpl(session, null, errorReason) as R) } @@ -64,7 +65,7 @@ class ExpressionsConverter( if (!stubMode) { return when (expression.tokenType) { LAMBDA_EXPRESSION -> { - val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.getAsString()) + val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.asText) ExpressionsConverter(session, stubMode, lambdaTree, declarationsConverter).convertLambdaExpression(lambdaTree.root) } BINARY_EXPRESSION -> convertBinaryExpression(expression) @@ -121,7 +122,7 @@ class ExpressionsConverter( } return FirAnonymousFunctionImpl(session, null, implicitType, implicitType).apply { - FunctionUtil.firFunctions += this + firFunctions += this var destructuringBlock: FirExpression? = null for (valueParameter in valueParameterList) { val multiDeclaration = valueParameter.destructuringDeclaration @@ -142,11 +143,11 @@ class ExpressionsConverter( valueParameter.firValueParameter } } - label = FunctionUtil.firLabels.pop() ?: FunctionUtil.firFunctionCalls.lastOrNull()?.calleeReference?.name?.let { + label = firLabels.pop() ?: firFunctionCalls.lastOrNull()?.calleeReference?.name?.let { FirLabelImpl(this@ExpressionsConverter.session, null, it.asString()) } val bodyExpression = block?.let { declarationsConverter.convertBlockExpression(it) } - ?: FirErrorExpressionImpl(session, null, "Lambda has no body") + ?: FirErrorExpressionImpl(this@ExpressionsConverter.session, null, "Lambda has no body") body = if (bodyExpression is FirBlockImpl) { if (bodyExpression.statements.isEmpty()) { bodyExpression.statements.add(FirUnitExpression(this@ExpressionsConverter.session, null)) @@ -161,7 +162,7 @@ class ExpressionsConverter( FirSingleExpressionBlock(this@ExpressionsConverter.session, bodyExpression.toReturn()) } - FunctionUtil.firFunctions.removeLast() + firFunctions.removeLast() } } @@ -178,7 +179,7 @@ class ExpressionsConverter( when (it.tokenType) { OPERATION_REFERENCE -> { isLeftArgument = false - operationTokenName = it.getAsString() + operationTokenName = it.asText } else -> if (it.isExpression()) { if (isLeftArgument) { @@ -218,7 +219,7 @@ class ExpressionsConverter( } else { val firOperation = operationToken.toFirOperation() if (firOperation in FirOperation.ASSIGNMENTS) { - return convertAssignment(leftArgNode, rightArgAsFir, firOperation) + return leftArgNode.generateAssignment(null, rightArgAsFir, firOperation) { toFirExpression() } } else { FirOperatorCallImpl(session, null, firOperation).apply { arguments += getAsFirExpression(leftArgNode, "No left operand") @@ -238,7 +239,7 @@ class ExpressionsConverter( lateinit var firType: FirTypeRef binaryExpression.forEachChildren { when (it.tokenType) { - OPERATION_REFERENCE -> operationTokenName = it.getAsString() + OPERATION_REFERENCE -> operationTokenName = it.asText TYPE_REFERENCE -> firType = declarationsConverter.convertType(it) else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand") } @@ -259,7 +260,7 @@ class ExpressionsConverter( lateinit var firType: FirTypeRef isExpression.forEachChildren { when (it.tokenType) { - OPERATION_REFERENCE -> operationTokenName = it.getAsString() + OPERATION_REFERENCE -> operationTokenName = it.asText TYPE_REFERENCE -> firType = declarationsConverter.convertType(it) else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand") } @@ -276,19 +277,19 @@ class ExpressionsConverter( * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitLabeledExpression */ private fun convertLabeledExpression(labeledExpression: LighterASTNode): FirElement { - val size = FunctionUtil.firLabels.size + val size = firLabels.size var firExpression: FirElement? = null labeledExpression.forEachChildren { when (it.tokenType) { - LABEL_QUALIFIER -> FunctionUtil.firLabels += FirLabelImpl(session, null, it.toString().replace("@", "")) + LABEL_QUALIFIER -> firLabels += FirLabelImpl(session, null, it.toString().replace("@", "")) BLOCK -> firExpression = declarationsConverter.convertBlock(it) PROPERTY -> firExpression = declarationsConverter.convertPropertyDeclaration(it) else -> if (it.isExpression()) firExpression = getAsFirExpression(it) } } - if (size != FunctionUtil.firLabels.size) { - FunctionUtil.firLabels.removeLast() + if (size != firLabels.size) { + firLabels.removeLast() //println("Unused label: ${labeledExpression.getAsString()}") } return firExpression ?: FirErrorExpressionImpl(session, null, "Empty label") @@ -304,7 +305,7 @@ class ExpressionsConverter( var argument: LighterASTNode? = null unaryExpression.forEachChildren { when (it.tokenType) { - OPERATION_REFERENCE -> operationTokenName = it.getAsString() + OPERATION_REFERENCE -> operationTokenName = it.asText else -> if (it.isExpression()) argument = it } } @@ -318,10 +319,11 @@ class ExpressionsConverter( return if (conventionCallName != null) { if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) { return generateIncrementOrDecrementBlock( + null, argument, callName = conventionCallName, prefix = unaryExpression.tokenType == PREFIX_EXPRESSION - ) + ) { toFirExpression() } } FirFunctionCallImpl(session, null).apply { calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, conventionCallName) @@ -440,7 +442,7 @@ class ExpressionsConverter( var additionalArgument: FirExpression? = null callSuffix.forEachChildren { when (it.tokenType) { - REFERENCE_EXPRESSION -> name = it.getAsString() + REFERENCE_EXPRESSION -> name = it.asText TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it) VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> valueArguments += it else -> if (it.tokenType != TokenType.ERROR_ELEMENT) additionalArgument = @@ -458,119 +460,33 @@ class ExpressionsConverter( else -> FirErrorNamedReference(this@ExpressionsConverter.session, null, "Call has no callee") } - FunctionUtil.firFunctionCalls += this + firFunctionCalls += this this.extractArgumentsFrom(valueArguments.flatMap { convertValueArguments(it) }, stubMode) typeArguments += firTypeArguments - FunctionUtil.firFunctionCalls.removeLast() + firFunctionCalls.removeLast() } } /** * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseStringTemplate - * @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.toInterpolatingCall */ private fun convertStringTemplate(stringTemplate: LighterASTNode): FirExpression { - val sb = StringBuilder() - var hasExpressions = false - var result: FirExpression? = null - var callCreated = false - stringTemplate.forEachChildren(OPEN_QUOTE, CLOSING_QUOTE) { - val nextArgument = when (it.tokenType) { - LITERAL_STRING_TEMPLATE_ENTRY -> { - sb.append(it.getAsString()) - FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsString()) - } - ESCAPE_STRING_TEMPLATE_ENTRY -> { - val escape = it.getAsString() - val unescaped = escapedStringToCharacter(escape)?.toString() - ?: escape.replace("\\", "").replace("u", "\\u") - sb.append(unescaped) - FirConstExpressionImpl(session, null, IrConstKind.String, unescaped) - } - SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> { - hasExpressions = true - convertShortOrLongStringTemplate(it) - } - else -> { - hasExpressions = true - FirErrorExpressionImpl(session, null, "Incorrect template entry: ${it.getAsString()}") - } - } - result = when { - result == null -> nextArgument - callCreated && result is FirStringConcatenationCallImpl -> (result as FirStringConcatenationCallImpl).apply { - //TODO smart cast to FirStringConcatenationCallImpl isn't working - arguments += nextArgument - } - else -> { - callCreated = true - FirStringConcatenationCallImpl(session, null).apply { - arguments += result!! - arguments += nextArgument - } - } - } - } - return if (hasExpressions) result!! else FirConstExpressionImpl(session, null, IrConstKind.String, sb.toString()) + return stringTemplate.getChildrenAsArray().toInterpolatingCall(null) { convertShortOrLongStringTemplate(it) } } - private fun convertShortOrLongStringTemplate(shortOrLongString: LighterASTNode): FirExpression { - var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Incorrect template argument") - shortOrLongString.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) { - firExpression = getAsFirExpression(it, "Incorrect template argument") + private fun LighterASTNode?.convertShortOrLongStringTemplate(errorReason: String): FirExpression { + var firExpression: FirExpression = FirErrorExpressionImpl(session, null, errorReason) + this?.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) { + firExpression = getAsFirExpression(it, errorReason) } return firExpression } /** * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseLiteralConstant - * @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.generateConstantExpressionByLiteral */ private fun convertConstantExpression(constantExpression: LighterASTNode): FirExpression { - val type = constantExpression.tokenType - val text: String = constantExpression.getAsString() - val convertedText: Any? = when (type) { - INTEGER_CONSTANT, FLOAT_CONSTANT -> parseNumericLiteral(text, type) - BOOLEAN_CONSTANT -> parseBoolean(text) - else -> null - } - - return when (type) { - INTEGER_CONSTANT -> - if (convertedText is Long && - (hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) || - convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE) - ) { - FirConstExpressionImpl( - session, null, IrConstKind.Long, convertedText, "Incorrect long: $text" - ) - } else if (convertedText is Number) { - // TODO: support byte / short - FirConstExpressionImpl(session, null, IrConstKind.Int, convertedText.toInt(), "Incorrect int: $text") - } else { - FirErrorExpressionImpl(session, null, reason = "Incorrect constant expression: $text") - } - FLOAT_CONSTANT -> - if (convertedText is Float) { - FirConstExpressionImpl( - session, null, IrConstKind.Float, convertedText, "Incorrect float: $text" - ) - } else { - FirConstExpressionImpl( - session, null, IrConstKind.Double, convertedText as Double, "Incorrect double: $text" - ) - } - CHARACTER_CONSTANT -> - FirConstExpressionImpl( - session, null, IrConstKind.Char, text.parseCharacter(), "Incorrect character: $text" - ) - BOOLEAN_CONSTANT -> - FirConstExpressionImpl(session, null, IrConstKind.Boolean, convertedText as Boolean) - NULL -> - FirConstExpressionImpl(session, null, IrConstKind.Null, null) - else -> - throw AssertionError("Unknown literal type: $type, $text") - } + return generateConstantExpressionByLiteral(constantExpression) } /** @@ -590,10 +506,10 @@ class ExpressionsConverter( ) } DESTRUCTURING_DECLARATION -> subjectExpression = - getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.getAsString()}") + getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.asText}") WHEN_ENTRY -> whenEntries += convertWhenEntry(it) else -> if (it.isExpression()) subjectExpression = - getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.getAsString()}") + getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.asText}") } } @@ -742,7 +658,7 @@ class ExpressionsConverter( private fun convertSimpleNameExpression(referenceExpression: LighterASTNode): FirQualifiedAccessExpression { return FirQualifiedAccessExpressionImpl(session, null).apply { calleeReference = - FirSimpleNamedReference(this@ExpressionsConverter.session, null, referenceExpression.getAsString().nameAsSafeName()) + FirSimpleNamedReference(this@ExpressionsConverter.session, null, referenceExpression.asText.nameAsSafeName()) } } @@ -963,13 +879,13 @@ class ExpressionsConverter( when (it.tokenType) { CONTINUE_KEYWORD -> isBreak = false //BREAK -> isBreak = true - LABEL_QUALIFIER -> labelName = it.getAsString().replace("@", "") + LABEL_QUALIFIER -> labelName = it.asText.replace("@", "") } } return (if (isBreak) FirBreakExpressionImpl(session, null) else FirContinueExpressionImpl(session, null)).apply { target = FirLoopTarget(labelName) - val lastLoop = FunctionUtil.firLoops.lastOrNull() + val lastLoop = firLoops.lastOrNull() if (labelName == null) { if (lastLoop != null) { target.bind(lastLoop) @@ -977,7 +893,7 @@ class ExpressionsConverter( target.bind(FirErrorLoop(this@ExpressionsConverter.session, null, "Cannot bind unlabeled jump to a loop")) } } else { - for (firLoop in FunctionUtil.firLoops.asReversed()) { + for (firLoop in firLoops.asReversed()) { if (firLoop.label?.name == labelName) { target.bind(firLoop) return this @@ -1002,7 +918,7 @@ class ExpressionsConverter( } } - return firExpression.toReturn(labelName) + return firExpression.toReturn(labelName = labelName) } /** @@ -1023,12 +939,7 @@ class ExpressionsConverter( * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitThisExpression */ private fun convertThisExpression(thisExpression: LighterASTNode): FirQualifiedAccessExpression { - var label: String? = null - thisExpression.forEachChildren { - when (it.tokenType) { - LABEL_QUALIFIER -> label = it.getAsString().replaceFirst("@", "") - } - } + val label: String? = thisExpression.getLabelName() return FirQualifiedAccessExpressionImpl(session, null).apply { calleeReference = FirExplicitThisReference(this@ExpressionsConverter.session, null, label) @@ -1076,7 +987,7 @@ class ExpressionsConverter( var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Argument is absent") valueArgument.forEachChildren { when (it.tokenType) { - VALUE_ARGUMENT_NAME -> identifier = it.getAsString() + VALUE_ARGUMENT_NAME -> identifier = it.asText MUL -> isSpread = true STRING_TEMPLATE -> firExpression = convertStringTemplate(it) is KtConstantExpressionElementType -> firExpression = convertConstantExpression(it) @@ -1089,22 +1000,4 @@ class ExpressionsConverter( else -> firExpression } } - - /** - * @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.initializeLValue - */ - fun convertLValue(leftArgNode: LighterASTNode?, container: FirModifiableQualifiedAccess<*>): FirReference { - return when (leftArgNode?.tokenType) { - null -> FirErrorNamedReference(session, null, "Unsupported LValue: ${leftArgNode?.tokenType}") - THIS_EXPRESSION -> convertThisExpression(leftArgNode).calleeReference - REFERENCE_EXPRESSION -> FirSimpleNamedReference(session, null, leftArgNode.getAsString().nameAsSafeName()) - in qualifiedAccessTokens -> (getAsFirExpression(leftArgNode) as? FirQualifiedAccess)?.let { firQualifiedAccess -> - container.explicitReceiver = firQualifiedAccess.explicitReceiver - container.safe = firQualifiedAccess.safe - return@let firQualifiedAccess.calleeReference - } ?: FirErrorNamedReference(session, null, "Unsupported qualified LValue: ${leftArgNode.getAsString()}") - PARENTHESIZED -> convertLValue(leftArgNode.getExpressionInParentheses(), container) - else -> FirErrorNamedReference(session, null, "Unsupported LValue: ${leftArgNode.tokenType}") - } - } } \ No newline at end of file diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt index 22e6bab74bc..3808c4c523b 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt @@ -5,29 +5,29 @@ package org.jetbrains.kotlin.fir.lightTree.converter.utils -import com.intellij.lang.LighterASTNode import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.TokenSet -import org.jetbrains.kotlin.KtNodeTypes.* +import org.jetbrains.kotlin.KtNodeTypes.DOT_QUALIFIED_EXPRESSION +import org.jetbrains.kotlin.KtNodeTypes.SAFE_ACCESS_EXPRESSION import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.builder.* +import org.jetbrains.kotlin.fir.builder.RawFirBuilder +import org.jetbrains.kotlin.fir.builder.generateNotNullOrOther +import org.jetbrains.kotlin.fir.builder.generateResolvedAccessExpression import org.jetbrains.kotlin.fir.declarations.impl.FirVariableImpl -import org.jetbrains.kotlin.fir.expressions.* -import org.jetbrains.kotlin.fir.expressions.impl.* -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName -import org.jetbrains.kotlin.fir.lightTree.converter.ExpressionsConverter -import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil -import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop -import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirVariable +import org.jetbrains.kotlin.fir.expressions.FirWhenExpression +import org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl +import org.jetbrains.kotlin.fir.expressions.impl.FirComponentCallImpl +import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl +import org.jetbrains.kotlin.fir.expressions.impl.FirThrowExpressionImpl import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.lexer.KtSingleValueToken -import org.jetbrains.kotlin.lexer.KtTokens.* -import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.lexer.KtTokens.AS_SAFE +import org.jetbrains.kotlin.lexer.KtTokens.IDENTIFIER import org.jetbrains.kotlin.parsing.KotlinExpressionParsing -import org.jetbrains.kotlin.util.OperatorNameConventions val qualifiedAccessTokens = TokenSet.create(DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION) @@ -39,118 +39,6 @@ fun String.getOperationSymbol(): IElementType { return IDENTIFIER } -fun ExpressionsConverter.convertAssignment( - leftArgNode: LighterASTNode?, - rightArgAsFir: FirExpression, - operation: FirOperation -): FirStatement { - if (leftArgNode != null && leftArgNode.tokenType == PARENTHESIZED) { - return convertAssignment(leftArgNode.getExpressionInParentheses(), rightArgAsFir, operation) - } - if (leftArgNode != null && leftArgNode.tokenType == ARRAY_ACCESS_EXPRESSION) { - val arrayAccessFunctionCall = getAsFirExpression(leftArgNode) as FirFunctionCall - val firArrayExpression = arrayAccessFunctionCall.explicitReceiver - ?: FirErrorExpressionImpl(session, null, "No array expression") - val arraySet = if (operation != FirOperation.ASSIGN) { - FirArraySetCallImpl(session, null, rightArgAsFir, operation).apply { - indexes += arrayAccessFunctionCall.arguments - } - } else { - return FirFunctionCallImpl(session, null).apply { - calleeReference = FirSimpleNamedReference(this@convertAssignment.session, null, OperatorNameConventions.SET) - explicitReceiver = firArrayExpression - arguments += arrayAccessFunctionCall.arguments - arguments += rightArgAsFir - } - } - if (leftArgNode.getChildNodesByType(REFERENCE_EXPRESSION).isNotEmpty()) { - return arraySet.apply { - lValue = (firArrayExpression as FirQualifiedAccess).calleeReference - } - } - return FirBlockImpl(this@convertAssignment.session, null).apply { - val name = Name.special("") - statements += generateTemporaryVariable(this@convertAssignment.session, null, name, firArrayExpression) - statements += arraySet.apply { lValue = FirSimpleNamedReference(this@convertAssignment.session, null, name) } - } - } - if (operation != FirOperation.ASSIGN && - leftArgNode?.tokenType != REFERENCE_EXPRESSION && leftArgNode?.tokenType != THIS_EXPRESSION && - (leftArgNode?.tokenType !in qualifiedAccessTokens || getSelectorType(leftArgNode.getChildrenAsArray()) != REFERENCE_EXPRESSION) - ) { - return FirBlockImpl(session, null).apply { - val name = Name.special("") - statements += generateTemporaryVariable( - this@convertAssignment.session, null, name, getAsFirExpression(leftArgNode, "No LValue in assignment") - ) - statements += FirVariableAssignmentImpl(this@convertAssignment.session, null, rightArgAsFir, operation).apply { - lValue = FirSimpleNamedReference(this@convertAssignment.session, null, name) - } - } - } - return FirVariableAssignmentImpl(session, null, rightArgAsFir, operation).apply { - lValue = convertLValue(leftArgNode, this) - } - -} - -fun ExpressionsConverter.generateIncrementOrDecrementBlock( - argument: LighterASTNode?, - callName: Name, - prefix: Boolean -): FirExpression { - if (argument == null) { - return FirErrorExpressionImpl(session, null, "Inc/dec without operand") - } - return FirBlockImpl(session, null).apply { - val tempName = Name.special("") - val temporaryVariable = generateTemporaryVariable( - this@generateIncrementOrDecrementBlock.session, null, tempName, getAsFirExpression(argument, "Incorrect expression inside inc/dec") - ) - statements += temporaryVariable - val resultName = Name.special("") - val resultInitializer = FirFunctionCallImpl(this@generateIncrementOrDecrementBlock.session, null).apply { - this.calleeReference = FirSimpleNamedReference(this@generateIncrementOrDecrementBlock.session, null, callName) - this.explicitReceiver = generateResolvedAccessExpression( - this@generateIncrementOrDecrementBlock.session, null, temporaryVariable - ) - } - val resultVar = generateTemporaryVariable(this@generateIncrementOrDecrementBlock.session, null, resultName, resultInitializer) - val assignment = convertAssignment( - argument, - if (prefix && argument.tokenType != REFERENCE_EXPRESSION) - generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, resultVar) - else - resultInitializer, - FirOperation.ASSIGN - ) - - fun appendAssignment() { - if (assignment is FirBlock) { - statements += assignment.statements - } else { - statements += assignment - } - } - - if (prefix) { - if (argument.tokenType != REFERENCE_EXPRESSION) { - statements += resultVar - appendAssignment() - statements += generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, resultVar) - } else { - appendAssignment() - statements += generateAccessExpression( - this@generateIncrementOrDecrementBlock.session, null, argument.getAsString().nameAsSafeName() - ) - } - } else { - appendAssignment() - statements += generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, temporaryVariable) - } - } -} - fun generateDestructuringBlock( session: FirSession, multiDeclaration: DestructuringDeclaration, @@ -186,23 +74,3 @@ fun bangBangToWhen(session: FirSession, baseExpression: FirExpression): FirWhenE ), "bangbang", null ) } - -private fun getSelectorType(qualifiedAccessChildren: Array): IElementType? { - var isSelector = false - qualifiedAccessChildren.forEach { - if (it == null) return null - when (it.tokenType) { - DOT, SAFE_ACCESS -> isSelector = true - else -> if (isSelector) return it.tokenType - } - } - return null -} - -fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop { - label = FunctionUtil.firLabels.pop() - FunctionUtil.firLoops += this - block = generateBlock() - FunctionUtil.firLoops.removeLast() - return this -} \ No newline at end of file diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt index 6b1ee9f9d52..a060218e03e 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt @@ -13,9 +13,9 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirMemberPropertyImpl import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl -import org.jetbrains.kotlin.fir.lightTree.converter.ClassNameUtil import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier import org.jetbrains.kotlin.fir.references.FirPropertyFromParameterCallableReference +import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.types.FirErrorTypeRef import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef @@ -32,7 +32,7 @@ class ValueParameter( return isVal || isVar } - fun toFirProperty(): FirProperty { + fun toFirProperty(callableId: CallableId): FirProperty { val name = this.firValueParameter.name var type = this.firValueParameter.returnTypeRef if (type is FirImplicitTypeRef) { @@ -42,7 +42,7 @@ class ValueParameter( return FirMemberPropertyImpl( this.firValueParameter.session, null, - FirPropertySymbol(ClassNameUtil.callableIdForName(name)), + FirPropertySymbol(callableId), name, modifiers.getVisibility(), modifiers.getModality(), diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt new file mode 100644 index 00000000000..5db90cf47b2 --- /dev/null +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -0,0 +1,441 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.builder + +import com.intellij.psi.PsiElement +import com.intellij.psi.tree.IElementType +import org.jetbrains.kotlin.KtNodeTypes.* +import org.jetbrains.kotlin.fir.FirFunctionTarget +import org.jetbrains.kotlin.fir.FirLabel +import org.jetbrains.kotlin.fir.FirReference +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.impl.FirErrorFunction +import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.* +import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirExplicitThisReference +import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.ConeTypeParameterType +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.coneTypeSafe +import org.jetbrains.kotlin.fir.types.impl.* +import org.jetbrains.kotlin.ir.expressions.IrConstKind +import org.jetbrains.kotlin.lexer.KtTokens.CLOSING_QUOTE +import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.constants.evaluate.* +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.util.OperatorNameConventions + +//T can be either PsiElement, or LighterASTNode +abstract class BaseFirBuilder(val session: FirSession) { + + protected val implicitUnitType = FirImplicitUnitTypeRef(session, null) + protected val implicitAnyType = FirImplicitAnyTypeRef(session, null) + protected val implicitEnumType = FirImplicitEnumTypeRef(session, null) + protected val implicitAnnotationType = FirImplicitAnnotationTypeRef(session, null) + + abstract val T.elementType: IElementType + abstract val T.asText: String + abstract val T.unescapedValue: String + abstract fun T.getReferencedNameAsName(): Name + abstract fun T.getLabelName(): String? + abstract fun T.getExpressionInParentheses(): T? + abstract fun T.getChildNodeByType(type: IElementType): T? + abstract val T?.selectorExpression: T? + + /**** Class name utils ****/ +// var packageFqName: FqName = FqName.ROOT +// var className: FqName = FqName.ROOT +// val currentClassId get() = ClassId(packageFqName, className, false) + + inline fun withChildClassName(name: Name, l: () -> T): T { + className = className.child(name) + val t = l() + className = className.parent() + return t + } + + fun callableIdForName(name: Name, local: Boolean = false) = + when { + local -> CallableId(name) + className == FqName.ROOT -> CallableId(packageFqName, name) + else -> CallableId(packageFqName, className, name) + } + + fun callableIdForClassConstructor() = + if (className == FqName.ROOT) CallableId(packageFqName, Name.special("")) + else CallableId(packageFqName, className, className.shortName()) + + + /**** Function utils ****/ + companion object { + val firFunctions = mutableListOf() + val firFunctionCalls = mutableListOf() + val firLabels = mutableListOf() + val firLoops = mutableListOf() + + lateinit var packageFqName: FqName + var className: FqName = FqName.ROOT + val currentClassId get() = ClassId(packageFqName, className, false) + } + + fun MutableList.removeLast() { + removeAt(size - 1) + } + + fun MutableList.pop(): T? { + val result = lastOrNull() + if (result != null) { + removeAt(size - 1) + } + return result + } + + /**** Common utils ****/ + fun FirExpression.toReturn(basePsi: PsiElement? = psi, labelName: String? = null): FirReturnExpression { + return FirReturnExpressionImpl( + this@BaseFirBuilder.session, + basePsi, + this + ).apply { + target = FirFunctionTarget(labelName) + val lastFunction = firFunctions.lastOrNull() + if (labelName == null) { + if (lastFunction != null) { + target.bind(lastFunction) + } else { + target.bind(FirErrorFunction(this@BaseFirBuilder.session, psi, "Cannot bind unlabeled return to a function")) + } + } else { + for (firFunction in firFunctions.asReversed()) { + when (firFunction) { + is FirAnonymousFunction -> { + if (firFunction.label?.name == labelName) { + target.bind(firFunction) + return@apply + } + } + is FirNamedFunction -> { + if (firFunction.name.asString() == labelName) { + target.bind(firFunction) + return@apply + } + } + } + } + target.bind(FirErrorFunction(this@BaseFirBuilder.session, psi, "Cannot bind label $labelName to a function")) + } + } + } + + fun KtClassOrObject?.toDelegatedSelfType(firClass: FirRegularClass): FirTypeRef { + val typeParameters = firClass.typeParameters.map { + FirTypeParameterImpl(session, it.psi, FirTypeParameterSymbol(), it.name, Variance.INVARIANT, false).apply { + this.bounds += it.bounds + } + } + return FirResolvedTypeRefImpl( + session, + this, + ConeClassTypeImpl( + firClass.symbol.toLookupTag(), + typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(), + false + ) + ) + } + + fun typeParametersFromSelfType(delegatedSelfTypeRef: FirTypeRef): List { + return delegatedSelfTypeRef.coneTypeSafe() + ?.typeArguments + ?.map { ((it as ConeTypeParameterType).lookupTag.symbol as FirTypeParameterSymbol).fir } + ?: emptyList() + } + + fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop { + label = firLabels.pop() + firLoops += this + block = generateBlock() + firLoops.removeLast() + return this + } + + /**** Conversion utils ****/ + private fun T.getPsiOrNull(): PsiElement? { + return if (this is PsiElement) this else null + } + + fun generateConstantExpressionByLiteral(expression: T): FirExpression { + val type = expression.elementType + val text: String = expression.asText + val convertedText: Any? = when (type) { + INTEGER_CONSTANT, FLOAT_CONSTANT -> parseNumericLiteral(text, type) + BOOLEAN_CONSTANT -> parseBoolean(text) + else -> null + } + return when (type) { + INTEGER_CONSTANT -> + if (convertedText is Long && + (hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) || + convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE) + ) { + FirConstExpressionImpl( + session, expression.getPsiOrNull(), IrConstKind.Long, convertedText, "Incorrect long: $text" + ) + } else if (convertedText is Number) { + // TODO: support byte / short + FirConstExpressionImpl(session, expression.getPsiOrNull(), IrConstKind.Int, convertedText.toInt(), "Incorrect int: $text") + } else { + FirErrorExpressionImpl(session, expression.getPsiOrNull(), reason = "Incorrect constant expression: $text") + } + FLOAT_CONSTANT -> + if (convertedText is Float) { + FirConstExpressionImpl( + session, expression.getPsiOrNull(), IrConstKind.Float, convertedText, "Incorrect float: $text" + ) + } else { + FirConstExpressionImpl( + session, expression.getPsiOrNull(), IrConstKind.Double, convertedText as Double, "Incorrect double: $text" + ) + } + CHARACTER_CONSTANT -> + FirConstExpressionImpl( + session, expression.getPsiOrNull(), IrConstKind.Char, text.parseCharacter(), "Incorrect character: $text" + ) + BOOLEAN_CONSTANT -> + FirConstExpressionImpl(session, expression.getPsiOrNull(), IrConstKind.Boolean, convertedText as Boolean) + NULL -> + FirConstExpressionImpl(session, expression.getPsiOrNull(), IrConstKind.Null, null) + else -> + throw AssertionError("Unknown literal type: $type, $text") + } + + } + + fun Array.toInterpolatingCall( + base: KtStringTemplateExpression?, + convertTemplateEntry: T?.(String) -> FirExpression + ): FirExpression { + val sb = StringBuilder() + var hasExpressions = false + var result: FirExpression? = null + var callCreated = false + L@ for (entry in this) { + if (entry == null) continue + val nextArgument = when (entry.elementType) { + OPEN_QUOTE, CLOSING_QUOTE -> continue@L + LITERAL_STRING_TEMPLATE_ENTRY -> { + sb.append(entry.asText) + FirConstExpressionImpl(session, entry.getPsiOrNull(), IrConstKind.String, entry.asText) + } + ESCAPE_STRING_TEMPLATE_ENTRY -> { + sb.append(entry.unescapedValue) + FirConstExpressionImpl(session, entry.getPsiOrNull(), IrConstKind.String, entry.unescapedValue) + } + SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> { + hasExpressions = true + entry.convertTemplateEntry("Incorrect template argument") + } + else -> { + hasExpressions = true + FirErrorExpressionImpl( + session, entry.getPsiOrNull(), "Incorrect template entry: ${entry.asText}" + ) + } + } + result = when { + result == null -> nextArgument + callCreated && result is FirStringConcatenationCallImpl -> result.apply { + arguments += nextArgument + } + else -> { + callCreated = true + FirStringConcatenationCallImpl(session, base).apply { + arguments += result!! + arguments += nextArgument + } + } + } + } + return if (hasExpressions) result!! else FirConstExpressionImpl(session, base, IrConstKind.String, sb.toString()) + } + + /** + * given: + * argument++ + * + * result: + * { + * val = argument + * argument = .inc() + * ^ + * } + * + * given: + * ++argument + * + * result: + * { + * val = argument + * argument = .inc() + * ^argument + * } + * + */ + + // TODO: Refactor, support receiver capturing in case of a.b + fun generateIncrementOrDecrementBlock( + baseExpression: KtUnaryExpression?, + argument: T?, + callName: Name, + prefix: Boolean, + convert: T.() -> FirExpression + ): FirExpression { + if (argument == null) { + return FirErrorExpressionImpl(session, argument, "Inc/dec without operand") + } + return FirBlockImpl(session, baseExpression).apply { + val tempName = Name.special("") + val temporaryVariable = generateTemporaryVariable(this@BaseFirBuilder.session, baseExpression, tempName, argument.convert()) + statements += temporaryVariable + val resultName = Name.special("") + val resultInitializer = FirFunctionCallImpl(this@BaseFirBuilder.session, baseExpression).apply { + this.calleeReference = FirSimpleNamedReference(this@BaseFirBuilder.session, baseExpression?.operationReference, callName) + this.explicitReceiver = generateResolvedAccessExpression(this@BaseFirBuilder.session, baseExpression, temporaryVariable) + } + val resultVar = generateTemporaryVariable(this@BaseFirBuilder.session, baseExpression, resultName, resultInitializer) + val assignment = argument.generateAssignment( + baseExpression, + if (prefix && argument.elementType != REFERENCE_EXPRESSION) + generateResolvedAccessExpression(this@BaseFirBuilder.session, baseExpression, resultVar) + else + resultInitializer, + FirOperation.ASSIGN, convert + ) + + fun appendAssignment() { + if (assignment is FirBlock) { + statements += assignment.statements + } else { + statements += assignment + } + } + + if (prefix) { + if (argument.elementType != REFERENCE_EXPRESSION) { + statements += resultVar + appendAssignment() + statements += generateResolvedAccessExpression(this@BaseFirBuilder.session, baseExpression, resultVar) + } else { + appendAssignment() + statements += generateAccessExpression(this@BaseFirBuilder.session, baseExpression, argument.getReferencedNameAsName()) + } + } else { + appendAssignment() + statements += generateResolvedAccessExpression(this@BaseFirBuilder.session, baseExpression, temporaryVariable) + } + } + } + + fun FirModifiableQualifiedAccess<*>.initializeLValue( + left: T?, + convertQualified: T.() -> FirQualifiedAccess? + ): FirReference { + val tokenType = left?.elementType + if (left != null) { + when (tokenType) { + REFERENCE_EXPRESSION -> { + return FirSimpleNamedReference(this@BaseFirBuilder.session, left.getPsiOrNull(), left.getReferencedNameAsName()) + } + THIS_EXPRESSION -> { + return FirExplicitThisReference(this@BaseFirBuilder.session, left.getPsiOrNull(), left.getLabelName()) + } + DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION -> { + val firMemberAccess = left.convertQualified() + return if (firMemberAccess != null) { + explicitReceiver = firMemberAccess.explicitReceiver + safe = firMemberAccess.safe + firMemberAccess.calleeReference + } else { + FirErrorNamedReference( + this@BaseFirBuilder.session, left.getPsiOrNull(), "Unsupported qualified LValue: ${left.asText}" + ) + } + } + PARENTHESIZED -> { + return initializeLValue(left.getExpressionInParentheses(), convertQualified) + } + } + } + return FirErrorNamedReference(this@BaseFirBuilder.session, left.getPsiOrNull(), "Unsupported LValue: $tokenType") + } + + fun T?.generateAssignment( + psi: PsiElement?, + value: FirExpression, + operation: FirOperation, + convert: T.() -> FirExpression + ): FirStatement { + val tokenType = this?.elementType + if (tokenType == PARENTHESIZED) { + return this!!.getExpressionInParentheses().generateAssignment(psi, value, operation, convert) + } + if (tokenType == ARRAY_ACCESS_EXPRESSION) { + val firArrayAccess = this!!.convert() as FirFunctionCallImpl + val arraySet = if (operation != FirOperation.ASSIGN) { + FirArraySetCallImpl(session, psi, value, operation).apply { + indexes += firArrayAccess.arguments + } + } else { + return firArrayAccess.apply { + calleeReference = FirSimpleNamedReference(this@BaseFirBuilder.session, psi, OperatorNameConventions.SET) + arguments += value + } + } + val arrayExpression = this.getChildNodeByType(REFERENCE_EXPRESSION) + if (arrayExpression != null) { + return arraySet.apply { + lValue = initializeLValue(arrayExpression) { convert() as? FirQualifiedAccess } + } + } + return FirBlockImpl(session, arrayExpression).apply { + val name = Name.special("") + statements += generateTemporaryVariable( + this@BaseFirBuilder.session, this@generateAssignment.getPsiOrNull(), name, firArrayAccess.explicitReceiver!! + ) + statements += arraySet.apply { lValue = FirSimpleNamedReference(this@BaseFirBuilder.session, arrayExpression, name) } + } + } + if (operation != FirOperation.ASSIGN && + tokenType != REFERENCE_EXPRESSION && tokenType != THIS_EXPRESSION && + ((tokenType != DOT_QUALIFIED_EXPRESSION && tokenType != SAFE_ACCESS_EXPRESSION) || this.selectorExpression?.elementType != REFERENCE_EXPRESSION) + ) { + return FirBlockImpl(session, this.getPsiOrNull()).apply { + val name = Name.special("") + statements += generateTemporaryVariable( + this@BaseFirBuilder.session, this@generateAssignment.getPsiOrNull(), name, + this@generateAssignment?.convert() + ?: FirErrorExpressionImpl(this@BaseFirBuilder.session, this.getPsiOrNull(), "No LValue in assignment") + ) + statements += FirVariableAssignmentImpl(this@BaseFirBuilder.session, psi, value, operation).apply { + lValue = FirSimpleNamedReference(this@BaseFirBuilder.session, this.getPsiOrNull(), name) + } + } + } + return FirVariableAssignmentImpl(session, psi, value, operation).apply { + lValue = initializeLValue(this@generateAssignment) { convert() as? FirQualifiedAccess } + } + } +} \ No newline at end of file diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 12f38922adf..254921849d2 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -102,53 +102,6 @@ internal fun translateEscape(c: Char): Char? = else -> null } -internal fun generateConstantExpressionByLiteral(expression: KtConstantExpression): FirExpression { - val type = expression.node.elementType - val text: String = expression.text - val convertedText: Any? = when (type) { - KtNodeTypes.INTEGER_CONSTANT, KtNodeTypes.FLOAT_CONSTANT -> parseNumericLiteral(text, type) - KtNodeTypes.BOOLEAN_CONSTANT -> parseBoolean(text) - else -> null - } - return when (type) { - KtNodeTypes.INTEGER_CONSTANT -> - if (convertedText is Long && - (hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) || - convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE) - ) { - FirConstExpressionImpl( - expression, IrConstKind.Long, convertedText, "Incorrect long: $text" - ) - } else if (convertedText is Number) { - // TODO: support byte / short - FirConstExpressionImpl(expression, IrConstKind.Int, convertedText.toInt(), "Incorrect int: $text") - } else { - FirErrorExpressionImpl(expression, reason = "Incorrect constant expression: $text") - } - KtNodeTypes.FLOAT_CONSTANT -> - if (convertedText is Float) { - FirConstExpressionImpl( - expression, IrConstKind.Float, convertedText, "Incorrect float: $text" - ) - } else { - FirConstExpressionImpl( - expression, IrConstKind.Double, convertedText as Double, "Incorrect double: $text" - ) - } - KtNodeTypes.CHARACTER_CONSTANT -> - FirConstExpressionImpl( - expression, IrConstKind.Char, text.parseCharacter(), "Incorrect character: $text" - ) - KtNodeTypes.BOOLEAN_CONSTANT -> - FirConstExpressionImpl(expression, IrConstKind.Boolean, convertedText as Boolean) - KtNodeTypes.NULL -> - FirConstExpressionImpl(expression, IrConstKind.Null, null) - else -> - throw AssertionError("Unknown literal type: $type, $text") - } - -} - fun IElementType.toBinaryName(): Name? { return OperatorConventions.BINARY_OPERATION_NAMES[this] } @@ -281,53 +234,6 @@ internal fun Array.toFirWhenCondition( return firCondition!! } -internal fun Array.toInterpolatingCall( - base: KtStringTemplateExpression, - convert: KtExpression?.(String) -> FirExpression -): FirExpression { - val sb = StringBuilder() - var hasExpressions = false - var result: FirExpression? = null - var callCreated = false - for (entry in this) { - val nextArgument = when (entry) { - is KtLiteralStringTemplateEntry -> { - sb.append(entry.text) - FirConstExpressionImpl(entry, IrConstKind.String, entry.text) - } - is KtEscapeStringTemplateEntry -> { - sb.append(entry.unescapedValue) - FirConstExpressionImpl(entry, IrConstKind.String, entry.unescapedValue) - } - is KtStringTemplateEntryWithExpression -> { - val innerExpression = entry.expression - hasExpressions = true - innerExpression.convert("Incorrect template argument") - } - else -> { - hasExpressions = true - FirErrorExpressionImpl( - entry, "Incorrect template entry: ${entry.text}" - ) - } - } - result = when { - result == null -> nextArgument - callCreated && result is FirStringConcatenationCallImpl -> result.apply { - arguments += nextArgument - } - else -> { - callCreated = true - FirStringConcatenationCallImpl(base).apply { - arguments += result!! - arguments += nextArgument - } - } - } - } - return if (hasExpressions) result!! else FirConstExpressionImpl(base, IrConstKind.String, sb.toString()) -} - fun FirExpression.generateContainsOperation( argument: FirExpression, inverted: Boolean, @@ -346,85 +252,6 @@ fun FirExpression.generateContainsOperation( } } - -/** - * given: - * argument++ - * - * result: - * { - * val = argument - * argument = .inc() - * ^ - * } - * - * given: - * ++argument - * - * result: - * { - * val = argument - * argument = .inc() - * ^argument - * } - * - */ - -// TODO: Refactor, support receiver capturing in case of a.b -internal fun generateIncrementOrDecrementBlock( - session: FirSession, - baseExpression: KtUnaryExpression, - argument: KtExpression?, - callName: Name, - prefix: Boolean, - convert: KtExpression.() -> FirExpression -): FirExpression { - if (argument == null) { - return FirErrorExpressionImpl(argument, "Inc/dec without operand") - } - return FirBlockImpl(baseExpression).apply { - val tempName = Name.special("") - val temporaryVariable = generateTemporaryVariable(session, baseExpression, tempName, argument.convert()) - statements += temporaryVariable - val resultName = Name.special("") - val resultInitializer = FirFunctionCallImpl(baseExpression).apply { - this.calleeReference = FirSimpleNamedReference(baseExpression.operationReference, callName) - this.explicitReceiver = generateResolvedAccessExpression(baseExpression, temporaryVariable) - } - val resultVar = generateTemporaryVariable(session, baseExpression, resultName, resultInitializer) - val assignment = argument.generateAssignment( - session, baseExpression, - if (prefix && argument !is KtSimpleNameExpression) - generateResolvedAccessExpression(baseExpression, resultVar) - else - resultInitializer, - FirOperation.ASSIGN, convert - ) - - fun appendAssignment() { - if (assignment is FirBlock) { - statements += assignment.statements - } else { - statements += assignment - } - } - - if (prefix) { - if (argument !is KtSimpleNameExpression) { - statements += resultVar - appendAssignment() - statements += generateResolvedAccessExpression(baseExpression, resultVar) - } else { - appendAssignment() - statements += generateAccessExpression(baseExpression, argument.getReferencedNameAsName()) - } - } else { - appendAssignment() - statements += generateResolvedAccessExpression(baseExpression, temporaryVariable) - } - } -} - fun generateAccessExpression(psi: PsiElement?, name: Name): FirQualifiedAccessExpression = FirQualifiedAccessExpressionImpl(psi).apply { calleeReference = FirSimpleNamedReference(psi, name) @@ -472,164 +299,3 @@ fun generateTemporaryVariable( fun generateTemporaryVariable( session: FirSession, psi: PsiElement?, specialName: String, initializer: FirExpression ): FirVariable<*> = generateTemporaryVariable(session, psi, Name.special("<$specialName>"), initializer) - -private fun FirModifiableQualifiedAccess<*>.initializeLValue( - left: KtExpression?, - convertQualified: KtQualifiedExpression.() -> FirQualifiedAccess? -): FirReference { - return when (left) { - is KtSimpleNameExpression -> { - FirSimpleNamedReference(left, left.getReferencedNameAsName()) - } - is KtThisExpression -> { - FirExplicitThisReference(left, left.getLabelName()) - } - is KtQualifiedExpression -> { - val firMemberAccess = left.convertQualified() - if (firMemberAccess != null) { - explicitReceiver = firMemberAccess.explicitReceiver - safe = firMemberAccess.safe - firMemberAccess.calleeReference - } else { - FirErrorNamedReference(left, "Unsupported qualified LValue: ${left.text}") - } - } - is KtParenthesizedExpression -> { - initializeLValue(left.expression, convertQualified) - } - else -> { - FirErrorNamedReference(left, "Unsupported LValue: ${left?.javaClass}") - } - } -} - -internal fun KtExpression?.generateAssignment( - session: FirSession, - psi: PsiElement?, - value: FirExpression, - operation: FirOperation, - convert: KtExpression.() -> FirExpression -): FirStatement { - if (this is KtParenthesizedExpression) { - return expression.generateAssignment(session, psi, value, operation, convert) - } - if (this is KtArrayAccessExpression) { - val arrayExpression = this.arrayExpression - val firArrayExpression = arrayExpression?.convert() ?: FirErrorExpressionImpl(arrayExpression, "No array expression") - val arraySet = if (operation != FirOperation.ASSIGN) { - FirArraySetCallImpl(psi, value, operation).apply { - for (indexExpression in indexExpressions) { - indexes += indexExpression.convert() - } - } - } else { - return FirFunctionCallImpl(psi).apply { - calleeReference = FirSimpleNamedReference(psi, OperatorNameConventions.SET) - explicitReceiver = firArrayExpression - for (indexExpression in indexExpressions) { - arguments += indexExpression.convert() - } - arguments += value - } - } - if (arrayExpression is KtSimpleNameExpression) { - return arraySet.apply { - lValue = initializeLValue(arrayExpression) { convert() as? FirQualifiedAccess } - } - } - return FirBlockImpl(arrayExpression).apply { - val name = Name.special("") - statements += generateTemporaryVariable(session, this@generateAssignment, name, firArrayExpression) - statements += arraySet.apply { lValue = FirSimpleNamedReference(arrayExpression, name) } - } - } - if (operation != FirOperation.ASSIGN && - this !is KtSimpleNameExpression && this !is KtThisExpression && - (this !is KtQualifiedExpression || selectorExpression !is KtSimpleNameExpression) - ) { - return FirBlockImpl(this).apply { - val name = Name.special("") - statements += generateTemporaryVariable( - session, this@generateAssignment, name, - this@generateAssignment?.convert() ?: FirErrorExpressionImpl(this@generateAssignment, "No LValue in assignment") - ) - statements += FirVariableAssignmentImpl(psi, value, operation).apply { - lValue = FirSimpleNamedReference(this@generateAssignment, name) - } - } - } - return FirVariableAssignmentImpl(psi, value, operation).apply { - lValue = initializeLValue(this@generateAssignment) { convert() as? FirQualifiedAccess } - } -} - -internal fun FirModifiableAccessorsOwner.generateAccessorsByDelegate(session: FirSession, member: Boolean, stubMode: Boolean) { - val variable = this as FirVariable<*> - val delegateFieldSymbol = delegateFieldSymbol ?: return - val delegate = delegate as? FirWrappedDelegateExpressionImpl ?: return - fun delegateAccess() = FirQualifiedAccessExpressionImpl(null).apply { - calleeReference = FirDelegateFieldReferenceImpl(null, delegateFieldSymbol) - } - - fun thisRef() = - if (member) FirQualifiedAccessExpressionImpl(null).apply { - calleeReference = FirExplicitThisReference(null, null) - } - else FirConstExpressionImpl(null, IrConstKind.Null, null) - - fun propertyRef() = FirCallableReferenceAccessImpl(null).apply { - calleeReference = FirResolvedCallableReferenceImpl(null, variable.name, variable.symbol) - typeRef = FirImplicitKPropertyTypeRef(null, ConeStarProjection) - } - - delegate.delegateProvider = if (stubMode) FirExpressionStub(null) else FirFunctionCallImpl(null).apply { - explicitReceiver = delegate.expression - calleeReference = FirSimpleNamedReference(null, PROVIDE_DELEGATE) - arguments += thisRef() - arguments += propertyRef() - } - if (stubMode) return - getter = (getter as? FirPropertyAccessorImpl) - ?: FirPropertyAccessorImpl(session, null, true, Visibilities.UNKNOWN, FirImplicitTypeRefImpl(null)).apply Accessor@{ - body = FirSingleExpressionBlock( - FirReturnExpressionImpl( - null, - FirFunctionCallImpl(null).apply { - explicitReceiver = delegateAccess() - calleeReference = FirSimpleNamedReference(null, GET_VALUE) - arguments += thisRef() - arguments += propertyRef() - } - ).apply { - target = FirFunctionTarget(null) - target.bind(this@Accessor) - } - ) - } - setter = (setter as? FirPropertyAccessorImpl) - ?: FirPropertyAccessorImpl(session, null, false, Visibilities.UNKNOWN, FirImplicitUnitTypeRef(null)).apply { - val parameter = FirValueParameterImpl( - session, null, DELEGATED_SETTER_PARAM, - FirImplicitTypeRefImpl(null), - defaultValue = null, isCrossinline = false, - isNoinline = false, isVararg = false - ) - valueParameters += parameter - body = FirSingleExpressionBlock( - FirFunctionCallImpl(null).apply { - explicitReceiver = delegateAccess() - calleeReference = FirSimpleNamedReference(null, SET_VALUE) - arguments += thisRef() - arguments += propertyRef() - arguments += FirQualifiedAccessExpressionImpl(null).apply { - calleeReference = FirResolvedCallableReferenceImpl(psi, DELEGATED_SETTER_PARAM, parameter.symbol) - } - } - ) - } -} - -private val GET_VALUE = Name.identifier("getValue") -private val SET_VALUE = Name.identifier("setValue") -private val PROVIDE_DELEGATE = Name.identifier("provideDelegate") -private val DELEGATED_SETTER_PARAM = Name.special("") \ No newline at end of file diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/DataClassUtils.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/DataClassUtils.kt index 2d6fb7eab18..2b15718346b 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/DataClassUtils.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/DataClassUtils.kt @@ -23,16 +23,15 @@ import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtTypeReference -internal fun KtClassOrObject.generateComponentFunctions( +fun List>.generateComponentFunctions( session: FirSession, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName ) { var componentIndex = 1 - val zippedParameters = - primaryConstructorParameters.zip(firClass.declarations.filterIsInstance()) - for ((ktParameter, firProperty) in zippedParameters) { - if (!ktParameter.hasValOrVar()) continue + for ((ktParameter, firProperty) in this) { + if (!firProperty.isVal && !firProperty.isVar) continue val name = Name.identifier("component$componentIndex") componentIndex++ val symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, name)) @@ -52,7 +51,7 @@ internal fun KtClassOrObject.generateComponentFunctions( FirReturnExpressionImpl( ktParameter, FirQualifiedAccessExpressionImpl(ktParameter).apply { - val parameterName = ktParameter.nameAsSafeName + val parameterName = firProperty.name calleeReference = FirResolvedCallableReferenceImpl( ktParameter, parameterName, firProperty.symbol @@ -70,15 +69,14 @@ internal fun KtClassOrObject.generateComponentFunctions( private val copyName = Name.identifier("copy") -internal fun KtClassOrObject.generateCopyFunction( - session: FirSession, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName, - firPrimaryConstructor: FirConstructor, - toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef +fun List>.generateCopyFunction( + session: FirSession, classOrObject: KtClassOrObject?, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName, + firPrimaryConstructor: FirConstructor ) { val symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName)) firClass.addDeclaration( FirMemberFunctionImpl( - session, this, symbol, copyName, + session, classOrObject, symbol, copyName, Visibilities.PUBLIC, Modality.FINAL, isExpect = false, isActual = false, isOverride = false, isOperator = false, @@ -88,13 +86,11 @@ internal fun KtClassOrObject.generateCopyFunction( returnTypeRef = firPrimaryConstructor.returnTypeRef//FirImplicitTypeRefImpl(session, this) ).apply { val copyFunction = this - val zippedParameters = - primaryConstructorParameters.zip(firClass.declarations.filterIsInstance()) - for ((ktParameter, firProperty) in zippedParameters) { - val name = ktParameter.nameAsSafeName + for ((ktParameter, firProperty) in this@generateCopyFunction) { + val name = firProperty.name valueParameters += FirValueParameterImpl( session, ktParameter, name, - ktParameter.typeReference.toFirOrErrorTypeRef(), + firProperty.returnTypeRef, FirQualifiedAccessExpressionImpl(ktParameter).apply { calleeReference = FirResolvedCallableReferenceImpl(ktParameter, name, firProperty.symbol) }, diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index c47f6c46d4a..0427c65c14c 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.builder import com.intellij.psi.PsiElement +import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -33,20 +34,40 @@ import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions -class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { - - private val implicitUnitType = FirImplicitUnitTypeRef(null) - - private val implicitAnyType = FirImplicitAnyTypeRef(null) - - private val implicitEnumType = FirImplicitEnumTypeRef(null) - - private val implicitAnnotationType = FirImplicitAnnotationTypeRef(null) +class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder(session) { fun buildFirFile(file: KtFile): FirFile { return file.accept(Visitor(), Unit) as FirFile } + override val PsiElement.elementType: IElementType + get() = node.elementType + + override val PsiElement.asText: String + get() = text + + override val PsiElement.unescapedValue: String + get() = (this as KtEscapeStringTemplateEntry).unescapedValue + + override fun PsiElement.getChildNodeByType(type: IElementType): PsiElement? { + return children.firstOrNull { it.node.elementType == type } + } + + override fun PsiElement.getReferencedNameAsName(): Name { + return (this as KtSimpleNameExpression).getReferencedNameAsName() + } + + override fun PsiElement.getLabelName(): String? { + return (this as KtExpressionWithLabel).getLabelName() + } + + override fun PsiElement.getExpressionInParentheses(): PsiElement? { + return (this as KtParenthesizedExpression).expression + } + + override val PsiElement?.selectorExpression: PsiElement? + get() = (this as? KtQualifiedExpression)?.selectorExpression + private val KtModifierListOwner.visibility: Visibility get() = with(modifierList) { when { @@ -126,38 +147,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { FirSingleExpressionBlock(convert()) } - private fun FirExpression.toReturn(basePsi: PsiElement? = psi, labelName: String? = null): FirReturnExpression { - return FirReturnExpressionImpl(basePsi, this).apply { - target = FirFunctionTarget(labelName) - val lastFunction = firFunctions.lastOrNull() - if (labelName == null) { - if (lastFunction != null) { - target.bind(lastFunction) - } else { - target.bind(FirErrorFunction(this@RawFirBuilder.session, psi, "Cannot bind unlabeled return to a function")) - } - } else { - for (firFunction in firFunctions.asReversed()) { - when (firFunction) { - is FirAnonymousFunction -> { - if (firFunction.label?.name == labelName) { - target.bind(firFunction) - return@apply - } - } - is FirNamedFunction -> { - if (firFunction.name.asString() == labelName) { - target.bind(firFunction) - return@apply - } - } - } - } - target.bind(FirErrorFunction(this@RawFirBuilder.session, psi, "Cannot bind label $labelName to a function")) - } - } - } - private fun KtDeclarationWithBody.buildFirBody(): FirBlock? = when { !hasBody() -> @@ -404,8 +393,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { return firConstructor } - lateinit var packageFqName: FqName - override fun visitKtFile(file: KtFile, data: Unit): FirElement { packageFqName = file.packageFqName val firFile = FirFileImpl(session, file, file.name, packageFqName) @@ -426,29 +413,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { return firFile } - private fun KtClassOrObject.toDelegatedSelfType(firClass: FirRegularClass): FirTypeRef { - val typeParameters = firClass.typeParameters.map { - FirTypeParameterImpl(session, it.psi, FirTypeParameterSymbol(), it.name, Variance.INVARIANT, false).apply { - this.bounds += it.bounds - addDefaultBoundIfNecessary() - } - } - return FirResolvedTypeRefImpl( - this, - ConeClassTypeImpl( - firClass.symbol.toLookupTag(), - typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(), - false - ) - ) - } - - private fun FirTypeParameterImpl.addDefaultBoundIfNecessary() { - if (bounds.isEmpty()) { - bounds += FirImplicitNullableAnyTypeRef(null) - } - } - override fun visitEnumEntry(enumEntry: KtEnumEntry, data: Unit): FirElement { return withChildClassName(enumEntry.nameAsSafeName) { val firEnumEntry = FirEnumEntryImpl( @@ -471,28 +435,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { } } - inline fun withChildClassName(name: Name, l: () -> T): T { - className = className.child(name) - val t = l() - className = className.parent() - return t - } - - val currentClassId get() = ClassId(packageFqName, className, false) - - fun callableIdForName(name: Name, local: Boolean = false) = - when { - local -> CallableId(name) - className == FqName.ROOT -> CallableId(packageFqName, name) - else -> CallableId(packageFqName, className, name) - } - - fun callableIdForClassConstructor() = - if (className == FqName.ROOT) CallableId(packageFqName, Name.special("")) - else CallableId(packageFqName, className, className.shortName()) - - var className: FqName = FqName.ROOT - override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Unit): FirElement { return withChildClassName(classOrObject.nameAsSafeName) { @@ -544,10 +486,11 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { } if (classOrObject.hasModifier(DATA_KEYWORD) && firPrimaryConstructor != null) { - classOrObject.generateComponentFunctions(session, firClass, packageFqName, className) - classOrObject.generateCopyFunction(session, firClass, packageFqName, className, firPrimaryConstructor) { - toFirOrErrorType() - } + val zippedParameters = classOrObject.primaryConstructorParameters.zip( + firClass.declarations.filterIsInstance() + ) + zippedParameters.generateComponentFunctions(session, firClass, packageFqName, className) + zippedParameters.generateCopyFunction(session, classOrObject, firClass, packageFqName, className, firPrimaryConstructor) // TODO: equals, hashCode, toString } @@ -589,20 +532,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { } } - private val firFunctions = mutableListOf() - - private fun MutableList.removeLast() { - removeAt(size - 1) - } - - private fun MutableList.pop(): T? { - val result = lastOrNull() - if (result != null) { - removeAt(size - 1) - } - return result - } - override fun visitNamedFunction(function: KtNamedFunction, data: Unit): FirElement { val typeReference = function.typeReference val returnType = if (function.hasBlockBody()) { @@ -722,13 +651,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { return firConstructor } - private fun typeParametersFromSelfType(delegatedSelfTypeRef: FirTypeRef): List { - return delegatedSelfTypeRef.coneTypeSafe() - ?.typeArguments - ?.map { ((it as ConeTypeParameterType).lookupTag.symbol as FirTypeParameterSymbol).fir } - ?: emptyList() - } - private fun KtConstructorDelegationCall.convert( delegatedSuperTypeRef: FirTypeRef?, delegatedSelfTypeRef: FirTypeRef, @@ -956,7 +878,9 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { generateConstantExpressionByLiteral(expression) override fun visitStringTemplateExpression(expression: KtStringTemplateExpression, data: Unit): FirElement { - return expression.entries.toInterpolatingCall(expression) { toFirExpression(it) } + return expression.entries.toInterpolatingCall(expression) { + (this as KtStringTemplateEntryWithExpression).expression.toFirExpression(it) + } } override fun visitReturnExpression(expression: KtReturnExpression, data: Unit): FirElement { @@ -1037,16 +961,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { } } - private val firLoops = mutableListOf() - - private fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop { - label = firLabels.pop() - firLoops += this - block = generateBlock() - firLoops.removeLast() - return this - } - override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Unit): FirElement { return FirDoWhileLoopImpl( expression, expression.condition.toFirExpression("No condition in do-while loop") @@ -1187,8 +1101,8 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { } else { val firOperation = operationToken.toFirOperation() if (firOperation in FirOperation.ASSIGNMENTS) { - return expression.left.generateAssignment(session, expression, rightArgument, firOperation) { - toFirExpression("Incorrect expression in assignment: ${expression.text}") + return expression.left.generateAssignment(expression, rightArgument, firOperation) { + (this as KtExpression).toFirExpression("Incorrect expression in assignment: ${expression.text}") } } else { FirOperatorCallImpl(expression, firOperation).apply { @@ -1227,10 +1141,10 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { return if (conventionCallName != null) { if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) { return generateIncrementOrDecrementBlock( - session, expression, argument, + expression, argument, callName = conventionCallName, prefix = expression is KtPrefixExpression - ) { toFirExpression("Incorrect expression inside inc/dec") } + ) { (this as KtExpression).toFirExpression("Incorrect expression inside inc/dec") } } FirFunctionCallImpl(expression).apply { calleeReference = FirSimpleNamedReference( @@ -1246,8 +1160,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { } } - private val firFunctionCalls = mutableListOf() - override fun visitCallExpression(expression: KtCallExpression, data: Unit): FirElement { val calleeExpression = expression.calleeExpression return FirFunctionCallImpl(expression).apply { @@ -1315,8 +1227,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { return expression.expression?.accept(this, data) ?: FirErrorExpressionImpl(expression, "Empty parentheses") } - private val firLabels = mutableListOf() - override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): FirElement { val labelName = expression.getLabelName() val size = firLabels.size