psi2ir: Fix return insertion
We should only insert a return statement at the end of a lambda or function if the final statement is used as an expression (slice USED_AS_RESULT_OF_LAMBDA and USED_AS_EXPRESSION).
This commit is contained in:
committed by
Dmitry Petrov
parent
b3e733ea4f
commit
0da4b06074
@@ -31,6 +31,8 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.VariableLValue
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -56,7 +58,13 @@ class BodyGenerator(
|
||||
if (ktBody is KtBlockExpression) {
|
||||
statementGenerator.generateStatements(ktBody.statements, irBlockBody)
|
||||
} else {
|
||||
statementGenerator.generateReturnExpression(ktBody, irBlockBody)
|
||||
val irBody = statementGenerator.generateStatement(ktBody)
|
||||
irBlockBody.statements.add(
|
||||
if (ktBody.isUsedAsExpression(context.bindingContext) && irBody is IrExpression)
|
||||
generateReturnExpression(irBody.startOffset, irBody.endOffset, irBody)
|
||||
else
|
||||
irBody
|
||||
)
|
||||
}
|
||||
|
||||
return irBlockBody
|
||||
@@ -90,7 +98,14 @@ class BodyGenerator(
|
||||
irBlockBody.statements.add(statementGenerator.generateStatement(ktStatement))
|
||||
}
|
||||
val ktReturnedValue = ktBodyStatements.last()
|
||||
statementGenerator.generateReturnExpression(ktReturnedValue, irBlockBody)
|
||||
val irReturnedValue = statementGenerator.generateStatement(ktReturnedValue)
|
||||
irBlockBody.statements.add(
|
||||
if (ktReturnedValue.isUsedAsResultOfLambda(context.bindingContext) && irReturnedValue is IrExpression) {
|
||||
generateReturnExpression(irReturnedValue.startOffset, irReturnedValue.endOffset, irReturnedValue)
|
||||
} else {
|
||||
irReturnedValue
|
||||
}
|
||||
)
|
||||
} else {
|
||||
irBlockBody.statements.add(
|
||||
generateReturnExpression(
|
||||
@@ -106,23 +121,6 @@ class BodyGenerator(
|
||||
return irBlockBody
|
||||
}
|
||||
|
||||
private fun StatementGenerator.generateReturnExpression(ktExpression: KtExpression, irBlockBody: IrBlockBodyImpl) {
|
||||
val irReturnExpression = generateStatement(ktExpression)
|
||||
if (irReturnExpression is IrExpression) {
|
||||
irBlockBody.statements.add(irReturnExpression.wrapWithReturn())
|
||||
} else {
|
||||
irBlockBody.statements.add(irReturnExpression)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrExpression.wrapWithReturn() =
|
||||
if (this is IrReturn || this is IrErrorExpression || this is IrThrow)
|
||||
this
|
||||
else {
|
||||
generateReturnExpression(startOffset, endOffset, this)
|
||||
}
|
||||
|
||||
|
||||
private fun generateReturnExpression(startOffset: Int, endOffset: Int, returnValue: IrExpression): IrReturnImpl {
|
||||
val returnTarget = (scopeOwner as? CallableDescriptor) ?: throw AssertionError("'return' in a non-callable: $scopeOwner")
|
||||
return IrReturnImpl(
|
||||
@@ -132,7 +130,6 @@ class BodyGenerator(
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun generateSecondaryConstructorBody(ktConstructor: KtSecondaryConstructor): IrBody {
|
||||
val irBlockBody = IrBlockBodyImpl(ktConstructor.startOffsetSkippingComments, ktConstructor.endOffset)
|
||||
|
||||
@@ -319,7 +316,7 @@ class BodyGenerator(
|
||||
}
|
||||
|
||||
val enumDefaultConstructorCall = getResolvedCall(ktEnumEntry)
|
||||
?: throw AssertionError("No default constructor call for enum entry $enumClassDescriptor")
|
||||
?: throw AssertionError("No default constructor call for enum entry $enumClassDescriptor")
|
||||
return statementGenerator.generateEnumConstructorCall(enumDefaultConstructorCall, ktEnumEntry)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user