Qualified expressions and safe calls

This commit is contained in:
Dmitry Petrov
2016-08-11 12:20:41 +03:00
committed by Dmitry Petrov
parent b80782c295
commit 3e11f35918
9 changed files with 80 additions and 15 deletions
@@ -39,19 +39,21 @@ class IrExpressionGenerator(
fun generateExpression(ktExpression: KtExpression) = ktExpression.generate()
private fun KtElement.generate(): IrExpression =
accept(this@IrExpressionGenerator, null).applySmartCast(this)
deparenthesize()
.accept(this@IrExpressionGenerator, null)
.smartCastIfNeeded(this)
private fun KtExpression.type() =
getType(this) ?: TODO("no type for expression")
private fun IrExpression.applySmartCast(ktElement: KtElement): IrExpression {
private fun IrExpression.smartCastIfNeeded(ktElement: KtElement): IrExpression {
if (ktElement is KtExpression) {
val smartCastType = get(BindingContext.SMARTCAST, ktElement)
if (smartCastType != null) {
return IrTypeOperatorExpressionImpl(
ktElement.startOffset, ktElement.endOffset, smartCastType,
IrTypeOperator.SMART_AS, smartCastType
).apply { childExpression = this@applySmartCast }
).apply { childExpression = this@smartCastIfNeeded }
}
}
return this
@@ -138,6 +140,24 @@ class IrExpressionGenerator(
return generateCall(expression, resolvedCall, null, null)
}
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrExpression =
expression.selectorExpression!!.accept(this, data)
override fun visitSafeQualifiedExpression(expression: KtSafeQualifiedExpression, data: Nothing?): IrExpression =
expression.selectorExpression!!.accept(this, data)
override fun visitThisExpression(expression: KtThisExpression, data: Nothing?): IrExpression {
val referenceTarget = getOrFail(BindingContext.REFERENCE_TARGET, expression.instanceReference) { "No reference target for this" }
return when (referenceTarget) {
is ClassDescriptor ->
IrThisExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), referenceTarget)
is CallableDescriptor ->
IrExtensionReceiverReferenceImpl(expression.startOffset, expression.endOffset, expression.type(), referenceTarget)
else ->
error("Expected this or receiver: $referenceTarget")
}
}
private fun generateCall(
ktExpression: KtExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>,
@@ -179,8 +199,7 @@ class IrExpressionGenerator(
null ->
null
else ->
IrDummyExpression(ktExpression.startOffset, ktExpression.endOffset, receiver.type,
"Receiver: ${receiver.javaClass.simpleName}")
TODO("Receiver: ${receiver.javaClass.simpleName}")
}
private fun generateValueArgument(valueParameter: ValueParameterDescriptor, valueArgument: ResolvedValueArgument): IrExpression? {
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
fun KtElement.deparenthesize(): KtElement =
if (this is KtExpression) KtPsiUtil.safeDeparenthesize(this) else this
@@ -76,7 +76,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
"THIS ${expression.classDescriptor.render()}"
override fun visitCallExpression(expression: IrCallExpression, data: Nothing?): String =
"CALL ${expression.callee.name} ${expression.operator ?: ""}"
"CALL ${if (expression.isSafe) "?." else "."}${expression.callee.name} ${expression.operator ?: ""}"
override fun visitDummyExpression(expression: IrDummyExpression, data: Nothing?): String =
"DUMMY ${expression.description}"