FIR body resolve: support subject type calculation

This commit is contained in:
Mikhail Glukhikh
2019-04-11 17:26:23 +03:00
parent e05dfb6541
commit 8b718c6822
15 changed files with 128 additions and 35 deletions
@@ -10,6 +10,7 @@ import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirReference
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirWhenSubject
import org.jetbrains.kotlin.fir.declarations.impl.FirVariableImpl
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.*
@@ -179,10 +180,12 @@ internal fun FirExpression.generateNotNullOrOther(
): FirWhenExpression {
val subjectName = Name.special("<$caseId>")
val subjectVariable = generateTemporaryVariable(session, psi, subjectName, this)
val subjectExpression = FirWhenSubjectExpression(session, psi)
val subject = FirWhenSubject()
val subjectExpression = FirWhenSubjectExpressionImpl(session, psi, subject)
return FirWhenExpressionImpl(
session, basePsi, this, subjectVariable
).apply {
subject.bind(this)
branches += FirWhenBranchImpl(
session, psi,
FirOperatorCallImpl(session, psi, FirOperation.EQ).apply {
@@ -219,10 +222,11 @@ internal fun FirExpression.generateLazyLogicalOperation(
internal fun KtWhenCondition.toFirWhenCondition(
session: FirSession,
subject: FirWhenSubject,
convert: KtExpression?.(String) -> FirExpression,
toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef
): FirExpression {
val firSubjectExpression = FirWhenSubjectExpression(session, this)
val firSubjectExpression = FirWhenSubjectExpressionImpl(session, this, subject)
return when (this) {
is KtWhenConditionWithExpression -> {
FirOperatorCallImpl(
@@ -255,12 +259,13 @@ internal fun KtWhenCondition.toFirWhenCondition(
internal fun Array<KtWhenCondition>.toFirWhenCondition(
session: FirSession,
basePsi: KtElement,
subject: FirWhenSubject,
convert: KtExpression?.(String) -> FirExpression,
toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef
): FirExpression {
var firCondition: FirExpression? = null
for (condition in this) {
val firConditionElement = condition.toFirWhenCondition(session, convert, toFirOrErrorTypeRef)
val firConditionElement = condition.toFirWhenCondition(session, subject, convert, toFirOrErrorTypeRef)
firCondition = when (firCondition) {
null -> firConditionElement
else -> firCondition.generateLazyLogicalOperation(
@@ -972,26 +972,30 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
}
override fun visitWhenExpression(expression: KtWhenExpression, data: Unit): FirElement {
val subjectExpression = expression.subjectExpression
val subject = when (subjectExpression) {
is KtVariableDeclaration -> subjectExpression.initializer
else -> subjectExpression
}?.toFirExpression("Incorrect when subject expression: ${subjectExpression?.text}")
val subjectVariable = when (subjectExpression) {
val ktSubjectExpression = expression.subjectExpression
val subjectExpression = when (ktSubjectExpression) {
is KtVariableDeclaration -> ktSubjectExpression.initializer
else -> ktSubjectExpression
}?.toFirExpression("Incorrect when subject expression: ${ktSubjectExpression?.text}")
val subjectVariable = when (ktSubjectExpression) {
is KtVariableDeclaration -> FirVariableImpl(
session, subjectExpression, subjectExpression.nameAsSafeName,
subjectExpression.typeReference.toFirOrImplicitType(),
isVar = false, initializer = subject
session, ktSubjectExpression, ktSubjectExpression.nameAsSafeName,
ktSubjectExpression.typeReference.toFirOrImplicitType(),
isVar = false, initializer = subjectExpression
)
else -> null
}
val hasSubject = subject != null
val hasSubject = subjectExpression != null
val subject = FirWhenSubject()
return FirWhenExpressionImpl(
session,
expression,
subject,
subjectExpression,
subjectVariable
).apply {
if (hasSubject) {
subject.bind(this)
}
for (entry in expression.entries) {
val branch = entry.expression.toFirBlock()
branches += if (!entry.isElse) {
@@ -999,6 +1003,7 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
val firCondition = entry.conditions.toFirWhenCondition(
this@RawFirBuilder.session,
entry,
subject,
{ toFirExpression(it) },
{ toFirOrErrorType() }
)