Extract bangbang and bindLabel methods (raw FIR)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
c5547a2229
commit
01daa90f5c
+2
-23
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumen
|
||||
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.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
|
||||
@@ -313,7 +312,7 @@ class ExpressionsConverter(
|
||||
|
||||
val operationToken = operationTokenName.getOperationSymbol()
|
||||
if (operationToken == EXCLEXCL) {
|
||||
return bangBangToWhen(session, getAsFirExpression(argument, "No operand"))
|
||||
return argument.bangBangToWhen(null) { toFirExpression(it) }
|
||||
}
|
||||
|
||||
val conventionCallName = operationToken.toUnaryName()
|
||||
@@ -875,34 +874,14 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertLoopJump(jump: LighterASTNode): FirExpression {
|
||||
var isBreak = true
|
||||
var labelName: String? = null
|
||||
jump.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
CONTINUE_KEYWORD -> isBreak = false
|
||||
//BREAK -> isBreak = true
|
||||
LABEL_QUALIFIER -> labelName = it.asText.replace("@", "")
|
||||
}
|
||||
}
|
||||
|
||||
return (if (isBreak) FirBreakExpressionImpl(session, null) else FirContinueExpressionImpl(session, null)).apply {
|
||||
target = FirLoopTarget(labelName)
|
||||
val lastLoop = context.firLoops.lastOrNull()
|
||||
if (labelName == null) {
|
||||
if (lastLoop != null) {
|
||||
target.bind(lastLoop)
|
||||
} else {
|
||||
target.bind(FirErrorLoop(this@ExpressionsConverter.session, null, "Cannot bind unlabeled jump to a loop"))
|
||||
}
|
||||
} else {
|
||||
for (firLoop in context.firLoops.asReversed()) {
|
||||
if (firLoop.label?.name == labelName) {
|
||||
target.bind(firLoop)
|
||||
return this
|
||||
}
|
||||
}
|
||||
target.bind(FirErrorLoop(this@ExpressionsConverter.session, null, "Cannot bind label $labelName to a loop"))
|
||||
}
|
||||
}
|
||||
return (if (isBreak) FirBreakExpressionImpl(session, null) else FirContinueExpressionImpl(session, null)).bindLabel(jump)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
-11
@@ -63,14 +63,3 @@ fun generateDestructuringBlock(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun bangBangToWhen(session: FirSession, baseExpression: FirExpression): FirWhenExpression {
|
||||
return baseExpression.generateNotNullOrOther(
|
||||
session,
|
||||
FirThrowExpressionImpl(
|
||||
session, null, FirFunctionCallImpl(session, null).apply {
|
||||
calleeReference = FirSimpleNamedReference(session, null, RawFirBuilder.KNPE)
|
||||
}
|
||||
), "bangbang", null
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,11 +9,15 @@ 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.FirLoopTarget
|
||||
import org.jetbrains.kotlin.fir.FirReference
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirErrorLoop
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||
@@ -30,10 +34,11 @@ 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.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
||||
import org.jetbrains.kotlin.psi.KtUnaryExpression
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.*
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
@@ -89,6 +94,10 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
|
||||
}
|
||||
|
||||
/**** Common utils ****/
|
||||
companion object {
|
||||
val KNPE = Name.identifier("KotlinNullPointerException")
|
||||
}
|
||||
|
||||
fun FirExpression.toReturn(basePsi: PsiElement? = psi, labelName: String? = null): FirReturnExpression {
|
||||
return FirReturnExpressionImpl(
|
||||
this@BaseFirBuilder.session,
|
||||
@@ -149,6 +158,17 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
fun T?.bangBangToWhen(parent: KtUnaryExpression?, convert: T?.(String) -> FirExpression): FirWhenExpression {
|
||||
return this.convert("No operand").generateNotNullOrOther(
|
||||
session,
|
||||
FirThrowExpressionImpl(
|
||||
session, parent.getPsiOrNull(), FirFunctionCallImpl(session, parent.getPsiOrNull()).apply {
|
||||
calleeReference = FirSimpleNamedReference(this@BaseFirBuilder.session, parent, KNPE)
|
||||
}
|
||||
), "bangbang", parent
|
||||
)
|
||||
}
|
||||
|
||||
fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop {
|
||||
label = context.firLabels.pop()
|
||||
context.firLoops += this
|
||||
@@ -157,6 +177,28 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
|
||||
return this
|
||||
}
|
||||
|
||||
fun FirLoopJump.bindLabel(expression: T): FirLoopJump {
|
||||
val labelName = expression.getLabelName()
|
||||
target = FirLoopTarget(labelName)
|
||||
val lastLoop = context.firLoops.lastOrNull()
|
||||
if (labelName == null) {
|
||||
if (lastLoop != null) {
|
||||
target.bind(lastLoop)
|
||||
} else {
|
||||
target.bind(FirErrorLoop(this@BaseFirBuilder.session, expression.getPsiOrNull(), "Cannot bind unlabeled jump to a loop"))
|
||||
}
|
||||
} else {
|
||||
for (firLoop in context.firLoops.asReversed()) {
|
||||
if (firLoop.label?.name == labelName) {
|
||||
target.bind(firLoop)
|
||||
return this
|
||||
}
|
||||
}
|
||||
target.bind(FirErrorLoop(this@BaseFirBuilder.session, expression.getPsiOrNull(), "Cannot bind label $labelName to a loop"))
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**** Conversion utils ****/
|
||||
private fun <T> T.getPsiOrNull(): PsiElement? {
|
||||
return if (this is PsiElement) this else null
|
||||
@@ -181,7 +223,9 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
|
||||
)
|
||||
} else if (convertedText is Number) {
|
||||
// TODO: support byte / short
|
||||
FirConstExpressionImpl(session, expression.getPsiOrNull(), IrConstKind.Int, convertedText.toInt(), "Incorrect int: $text")
|
||||
FirConstExpressionImpl(
|
||||
session, expression.getPsiOrNull(), IrConstKind.Int, convertedText.toInt(), "Incorrect int: $text"
|
||||
)
|
||||
} else {
|
||||
FirErrorExpressionImpl(session, expression.getPsiOrNull(), reason = "Incorrect constant expression: $text")
|
||||
}
|
||||
|
||||
@@ -1035,28 +1035,6 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirLoopJump.bindLabel(expression: KtExpressionWithLabel): FirLoopJump {
|
||||
val labelName = expression.getLabelName()
|
||||
target = FirLoopTarget(labelName)
|
||||
val lastLoop = context.firLoops.lastOrNull()
|
||||
if (labelName == null) {
|
||||
if (lastLoop != null) {
|
||||
target.bind(lastLoop)
|
||||
} else {
|
||||
target.bind(FirErrorLoop(psi, "Cannot bind unlabeled jump to a loop"))
|
||||
}
|
||||
} else {
|
||||
for (firLoop in context.firLoops.asReversed()) {
|
||||
if (firLoop.label?.name == labelName) {
|
||||
target.bind(firLoop)
|
||||
return this
|
||||
}
|
||||
}
|
||||
target.bind(FirErrorLoop(psi, "Cannot bind label $labelName to a loop"))
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
override fun visitBreakExpression(expression: KtBreakExpression, data: Unit): FirElement {
|
||||
return FirBreakExpressionImpl(expression).bindLabel(expression)
|
||||
}
|
||||
@@ -1065,17 +1043,6 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
|
||||
return FirContinueExpressionImpl(expression).bindLabel(expression)
|
||||
}
|
||||
|
||||
private fun KtUnaryExpression.bangBangToWhen(): FirWhenExpression {
|
||||
return baseExpression.toFirExpression("No operand").generateNotNullOrOther(
|
||||
session,
|
||||
FirThrowExpressionImpl(
|
||||
this, FirFunctionCallImpl(this).apply {
|
||||
calleeReference = FirSimpleNamedReference(this@bangBangToWhen, KNPE)
|
||||
}
|
||||
), "bangbang", this
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression, data: Unit): FirElement {
|
||||
val operationToken = expression.operationToken
|
||||
val leftArgument = expression.left.toFirExpression("No left operand")
|
||||
@@ -1137,7 +1104,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
|
||||
val operationToken = expression.operationToken
|
||||
val argument = expression.baseExpression
|
||||
if (operationToken == EXCLEXCL) {
|
||||
return expression.bangBangToWhen()
|
||||
return expression.baseExpression.bangBangToWhen(expression) { (this as KtExpression).toFirExpression(it) }
|
||||
}
|
||||
val conventionCallName = operationToken.toUnaryName()
|
||||
return if (conventionCallName != null) {
|
||||
@@ -1298,8 +1265,4 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
|
||||
return FirExpressionStub(expression)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val KNPE = Name.identifier("KotlinNullPointerException")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user