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 c76670e8185..9c594c5164b 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 @@ -64,10 +64,6 @@ object ConverterUtil { return this.toString() } - fun LighterASTNode.getAsStringUnescapedValue(): String { - return this.toString().replaceFirst("\\", "") - } - fun LighterASTNode.isExpression(): Boolean { return when (this.tokenType) { is KtNodeType, @@ -157,9 +153,15 @@ object ConverterUtil { return this } - fun FirValueParameter.toFirExpression(stubMode: Boolean): FirExpression { - return if (stubMode) FirExpressionStub(this.session, null) - else TODO("not implemeted") + inline fun isClassLocal(classNode: LighterASTNode, getParent: LighterASTNode.() -> LighterASTNode?): Boolean { + var currentNode: LighterASTNode? = classNode + while (currentNode != null) { + if (currentNode.tokenType == KtNodeTypes.BLOCK) { + return true + } + currentNode = currentNode.getParent() + } + return false } } 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 f9c40a2cba5..8629520f158 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 @@ -10,8 +10,10 @@ import com.intellij.psi.tree.IFileElementType import com.intellij.util.diff.FlyweightCapableTreeStructure import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.* @@ -26,6 +28,7 @@ import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.joinTypeParame 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 @@ -46,6 +49,7 @@ import org.jetbrains.kotlin.fir.types.impl.* import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.SpecialNames class DeclarationsConverter( private val session: FirSession, @@ -59,8 +63,7 @@ class DeclarationsConverter( * [org.jetbrains.kotlin.parsing.KotlinParsing.parsePreamble] */ fun convertFile(file: LighterASTNode, fileName: String = ""): FirFile { - val tokenType = file.tokenType - if (tokenType !is IFileElementType) { + if (file.tokenType != KT_FILE) { //TODO throw error throw Exception() } @@ -327,7 +330,7 @@ class DeclarationsConverter( /** * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseClassOrObject */ - fun convertClass(classNode: LighterASTNode): FirDeclaration { + private fun convertClass(classNode: LighterASTNode): FirDeclaration { var modifiers = Modifier(session) lateinit var classKind: ClassKind var identifier: String? = null @@ -370,6 +373,7 @@ class DeclarationsConverter( val className = identifier.nameAsSafeName(if (modifiers.isCompanion()) "Companion" else "") superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef } + val isLocal = isClassLocal(classNode) { getParent() } return ClassNameUtil.withChildClassName(className) { val firClass = FirClassImpl( @@ -377,7 +381,7 @@ class DeclarationsConverter( null, FirClassSymbol(ClassNameUtil.currentClassId), className, - if (classNode.getParent()?.tokenType == BLOCK) Visibilities.LOCAL else modifiers.getVisibility(), + if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(), modifiers.getModality(), modifiers.hasExpect(), modifiers.hasActual(), @@ -426,6 +430,57 @@ class DeclarationsConverter( } } + /** + * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseObjectLiteral + * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitObjectLiteralExpression + */ + fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement { + var modifiers = Modifier(session) + var primaryConstructor: LighterASTNode? = null + val superTypeRefs = mutableListOf() + val superTypeCallEntry = mutableListOf() + var delegatedSuperTypeRef: FirTypeRef? = null + var classBody: LighterASTNode? = null + objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first().forEachChildren { + when (it.tokenType) { + MODIFIER_LIST -> modifiers = convertModifierList(it) + PRIMARY_CONSTRUCTOR -> primaryConstructor = it + SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).apply { + delegatedSuperTypeRef = first + superTypeRefs += second + superTypeCallEntry += third + } + CLASS_BODY -> classBody = it + } + } + + superTypeRefs.ifEmpty { superTypeRefs += implicitAnyType } + val delegatedType = delegatedSuperTypeRef ?: implicitAnyType + + return FirAnonymousObjectImpl(session, null).apply { + annotations += modifiers.annotations + this.superTypeRefs += superTypeRefs + this.typeRef = superTypeRefs.first() + + val classWrapper = ClassWrapper( + this@DeclarationsConverter.session, SpecialNames.NO_NAME_PROVIDED, modifiers, ClassKind.OBJECT, + hasPrimaryConstructor = false, + hasSecondaryConstructor = false, + delegatedSelfTypeRef = delegatedType, + delegatedSuperTypeRef = delegatedType, + superTypeCallEntry = superTypeCallEntry + ) + //parse primary constructor + val firPrimaryConstructor = convertPrimaryConstructor(primaryConstructor, classWrapper) + firPrimaryConstructor?.let { this.declarations += it } + + //parse declarations + classBody?.let { + this.declarations += convertClassBody(it, classWrapper) + } + } + } + /** * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumEntry */ @@ -709,8 +764,9 @@ class DeclarationsConverter( val propertyName = identifier.nameAsSafeName() - val parentType = property.getParent()?.tokenType - return if (parentType == BLOCK || parentType == WHEN) { + val parentNode = property.getParent() + val isLocal = !(parentNode?.tokenType == KT_FILE || parentNode?.tokenType == CLASS_BODY) + return if (isLocal) { FirVariableImpl( session, null, @@ -799,7 +855,7 @@ class DeclarationsConverter( var returnType: FirTypeRef? = null var firValueParameters: FirValueParameter = FirDefaultSetterValueParameter(session, null, propertyTypeRef) var block: LighterASTNode? = null - var firExpression: FirExpression? = null + var expression: LighterASTNode? = null getterOrSetter.forEachChildren { if (it.getAsString() == "set") isGetter = false when (it.tokenType) { @@ -808,7 +864,7 @@ class DeclarationsConverter( TYPE_REFERENCE -> returnType = convertType(it) VALUE_PARAMETER_LIST -> firValueParameters = convertSetterParameter(it, propertyTypeRef) BLOCK -> block = it - else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) + else -> if (it.isExpression()) expression = it } } @@ -826,7 +882,7 @@ class DeclarationsConverter( firAccessor.valueParameters += firValueParameters } - firAccessor.body = convertFunctionBody(block, firExpression) + firAccessor.body = convertFunctionBody(block, expression?.let { expressionConverter.getAsFirExpression(it) }) FunctionUtil.firFunctions.removeLast() return firAccessor } @@ -874,7 +930,7 @@ class DeclarationsConverter( var returnType: FirTypeRef? = null val typeConstraints = mutableListOf() var block: LighterASTNode? = null - var firExpression: FirExpression? = null + var expression: LighterASTNode? = null functionDeclaration.forEachChildren { when (it.tokenType) { MODIFIER_LIST -> modifiers = convertModifierList(it) @@ -885,17 +941,18 @@ class DeclarationsConverter( TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it) TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it) BLOCK -> block = it - else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) + else -> if (it.isExpression()) expression = it } } if (returnType == null) { returnType = - if (block != null || (block == null && firExpression == null)) implicitUnitType + if (block != null || (block == null && expression == null)) implicitUnitType else implicitType } - val isLocal = functionDeclaration.getParent()?.tokenType == BLOCK + val parentNode = functionDeclaration.getParent() + val isLocal = !(parentNode?.tokenType == KT_FILE || parentNode?.tokenType == CLASS_BODY) val firFunction = if (identifier == null) { FirAnonymousFunctionImpl(session, null, returnType!!, receiverType) } else { @@ -930,7 +987,7 @@ class DeclarationsConverter( } firFunction.valueParameters += valueParametersList.map { it.firValueParameter } - firFunction.body = convertFunctionBody(block, firExpression) + firFunction.body = convertFunctionBody(block, expression?.let { expressionConverter.getAsFirExpression(it) }) FunctionUtil.firFunctions.removeLast() return firFunction } 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 e2da98943c0..74361bfdd14 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 @@ -6,28 +6,33 @@ package org.jetbrains.kotlin.fir.lightTree.converter import com.intellij.lang.LighterASTNode -import com.intellij.psi.tree.IElementType +import com.intellij.psi.impl.source.tree.java.PsiForStatementImpl import com.intellij.util.diff.FlyweightCapableTreeStructure import org.jetbrains.kotlin.KtNodeTypes.* +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.builder.* import org.jetbrains.kotlin.fir.declarations.FirClass -import org.jetbrains.kotlin.fir.declarations.impl.* +import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl +import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousObjectImpl +import org.jetbrains.kotlin.fir.declarations.impl.FirErrorLoop +import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.expressions.* 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.isExpression import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringUnescapedValue -import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn -import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast 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.fir.ClassWrapper import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry +import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirExplicitSuperReference import org.jetbrains.kotlin.fir.references.FirExplicitThisReference @@ -39,6 +44,7 @@ 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 @@ -90,12 +96,11 @@ class ExpressionsConverter( PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> convertExpression(expression.getExpressionInParentheses()) THIS_EXPRESSION -> convertThisExpression(expression) SUPER_EXPRESSION -> convertSuperExpression(expression) - OBJECT_LITERAL -> convertObjectLiteral(expression) + OBJECT_LITERAL -> declarationsConverter.convertObjectLiteral(expression) FUN -> declarationsConverter.convertFunctionDeclaration(expression) else -> FirExpressionStub(session, null) } - //TODO("not fully implemented") } return FirExpressionStub(session, null) @@ -467,8 +472,8 @@ class ExpressionsConverter( FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsString()) } ESCAPE_STRING_TEMPLATE_ENTRY -> { - sb.append(it.getAsStringUnescapedValue()) - FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsStringUnescapedValue()) + sb.append(escapedStringToCharacter(it.getAsString())) + FirConstExpressionImpl(session, null, IrConstKind.String, escapedStringToCharacter(it.getAsString())?.toString() ?: "") } SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> { hasExpressions = true @@ -781,7 +786,8 @@ class ExpressionsConverter( } } - return FirBlockImpl(session, null).apply { + //TODO psi must be null + return FirBlockImpl(session, KtForExpression(PsiForStatementImpl())).apply { val rangeVal = generateTemporaryVariable(this@ExpressionsConverter.session, null, Name.special(""), rangeExpression) statements += rangeVal @@ -1088,20 +1094,6 @@ class ExpressionsConverter( } } - /** - * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseObjectLiteral - * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitObjectLiteralExpression - */ - private fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement { - val firObject = declarationsConverter.convertClass(objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first()) as FirClass - return FirAnonymousObjectImpl(session, null).apply { - annotations += firObject.annotations - superTypeRefs += firObject.superTypeRefs - this.typeRef = superTypeRefs.first() - declarations += firObject.declarations - } - } - /** * @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.initializeLValue */ diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt index 6a41c227f2f..85a9a9fd372 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt @@ -26,16 +26,10 @@ class ClassWrapper( private val classKind: ClassKind, val hasPrimaryConstructor: Boolean, val hasSecondaryConstructor: Boolean, - var delegatedSelfTypeRef: FirTypeRef, + val delegatedSelfTypeRef: FirTypeRef, val delegatedSuperTypeRef: FirTypeRef, val superTypeCallEntry: MutableList ) { - init { - if (className == SpecialNames.NO_NAME_PROVIDED) { - delegatedSelfTypeRef = delegatedSuperTypeRef - } - } - private fun isObject(): Boolean { return classKind == ClassKind.OBJECT } 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 eca0cb1e79c..12f38922adf 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 @@ -58,7 +58,7 @@ fun String.parseCharacter(): Char? { } } -internal fun escapedStringToCharacter(text: String): Char? { +fun escapedStringToCharacter(text: String): Char? { assert(text.isNotEmpty() && text[0] == '\\') { "Only escaped sequences must be passed to this routine: $text" }