Qualified expressions and safe calls
This commit is contained in:
committed by
Dmitry Petrov
parent
b80782c295
commit
3e11f35918
@@ -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
@@ -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
@@ -0,0 +1,4 @@
|
||||
fun length(s: String) = s.length
|
||||
fun lengthN(s: String?) = s?.length
|
||||
|
||||
// IR_FILE_TXT dotQualified.txt
|
||||
+11
@@ -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
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user