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}"
+4 -4
View File
@@ -6,14 +6,14 @@ IrFile /calls.kt
IrFunction public fun bar(/*0*/ x: kotlin.Int): kotlin.Int
IrExpressionBody
RETURN type=kotlin.Int
CALL foo
CALL .foo
x: VAR x
y: LITERAL Int type=kotlin.Int value='1'
IrFunction public fun qux(/*0*/ x: kotlin.Int): kotlin.Int
IrExpressionBody
RETURN type=kotlin.Int
CALL foo
x: CALL foo
CALL .foo
x: CALL .foo
x: VAR x
y: VAR x
y: VAR x
@@ -24,6 +24,6 @@ IrFile /calls.kt
IrFunction public fun kotlin.Int.ext2(/*0*/ x: kotlin.Int): kotlin.Int
IrExpressionBody
RETURN type=kotlin.Int
CALL foo
CALL .foo
x: $RECEIVER of: <root>
y: VAR x
+4
View File
@@ -0,0 +1,4 @@
fun length(s: String) = s.length
fun lengthN(s: String?) = s?.length
// IR_FILE_TXT dotQualified.txt
+11
View File
@@ -0,0 +1,11 @@
IrFile /dotQualified.kt
IrFunction public fun length(/*0*/ s: kotlin.String): kotlin.Int
IrExpressionBody
RETURN type=kotlin.Int
CALL .length PROPERTY_GET
$this: VAR s
IrFunction public fun lengthN(/*0*/ s: kotlin.String?): kotlin.Int?
IrExpressionBody
RETURN type=kotlin.Int?
CALL ?.length PROPERTY_GET
$this: VAR s
@@ -7,5 +7,5 @@ IrFile /extensionPropertyGetterCall.kt
IrFunction public fun kotlin.String.test5(): kotlin.String
IrExpressionBody
RETURN type=kotlin.String
CALL okext PROPERTY_GET
CALL .okext PROPERTY_GET
$receiver: $RECEIVER of: test5
+4 -4
View File
@@ -6,7 +6,7 @@ IrFile /references.kt
IrProperty public val ok2: kotlin.String = "OK" getter=null setter=null
IrExpressionBody
RETURN type=kotlin.String
CALL ok PROPERTY_GET
CALL .ok PROPERTY_GET
IrProperty public val ok3: kotlin.String getter=<get-ok3> setter=null
IrPropertyGetter public fun <get-ok3>(): kotlin.String property=ok3
IrExpressionBody
@@ -15,7 +15,7 @@ IrFile /references.kt
IrFunction public fun test1(): kotlin.String
IrExpressionBody
RETURN type=kotlin.String
CALL ok PROPERTY_GET
CALL .ok PROPERTY_GET
IrFunction public fun test2(/*0*/ x: kotlin.String): kotlin.String
IrExpressionBody
RETURN type=kotlin.String
@@ -29,7 +29,7 @@ IrFile /references.kt
IrFunction public fun test4(): kotlin.String
IrExpressionBody
RETURN type=kotlin.String
CALL ok3 PROPERTY_GET
CALL .ok3 PROPERTY_GET
IrProperty public val kotlin.String.okext: kotlin.String getter=<get-okext> setter=null
IrPropertyGetter public fun kotlin.String.<get-okext>(): kotlin.String property=okext
IrExpressionBody
@@ -38,5 +38,5 @@ IrFile /references.kt
IrFunction public fun kotlin.String.test5(): kotlin.String
IrExpressionBody
RETURN type=kotlin.String
CALL okext PROPERTY_GET
CALL .okext PROPERTY_GET
$receiver: $RECEIVER of: test5
@@ -47,6 +47,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
@TestMetadata("dotQualified.kt")
public void testDotQualified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/dotQualified.kt");
doTest(fileName);
}
@TestMetadata("extensionPropertyGetterCall.kt")
public void testExtensionPropertyGetterCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/extensionPropertyGetterCall.kt");