From c93666f6f1b53df2cf93ca226f67039d8bd21093 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 10 Aug 2016 19:41:07 +0300 Subject: [PATCH] - IR expressions for calls & references - first calls "parsed" --- .../kotlin/psi2ir/IrExpressionGenerator.kt | 152 ++++++++++++++++-- .../jetbrains/kotlin/psi2ir/IrGenerator.kt | 8 +- .../ir/expressions/IrBlockExpression.kt | 10 +- .../kotlin/ir/expressions/IrCallExpression.kt | 142 ++++++++++++++++ .../ir/expressions/IrCallableOperator.kt | 69 ++++++++ .../ir/expressions/IrDeclarationReference.kt | 77 +++++++++ .../ir/expressions/IrDummyExpression.kt | 5 +- .../kotlin/ir/expressions/IrExpression.kt | 11 ++ .../ir/expressions/IrExpressionOwner.kt | 10 -- .../ir/expressions/IrLiteralExpression.kt | 6 +- .../kotlin/ir/expressions/IrThisExpression.kt | 36 +++++ .../expressions/IrTypeOperatorExpression.kt | 44 +++++ .../jetbrains/kotlin/ir/util/DumpIrTree.kt | 39 ++++- .../kotlin/ir/util/RenderIrElement.kt | 50 ++++-- .../kotlin/ir/visitors/IrElementVisitor.kt | 14 ++ compiler/testData/ir/irText/boxOk.txt | 4 +- compiler/testData/ir/irText/calls.kt | 8 + compiler/testData/ir/irText/calls.txt | 29 ++++ .../ir/irText/extensionPropertyGetterCall.kt | 4 + .../ir/irText/extensionPropertyGetterCall.txt | 11 ++ compiler/testData/ir/irText/references.kt | 19 +++ compiler/testData/ir/irText/references.txt | 42 +++++ compiler/testData/ir/irText/smoke.txt | 24 +-- .../kotlin/ir/IrTextTestCaseGenerated.java | 18 +++ 24 files changed, 768 insertions(+), 64 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableOperator.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt create mode 100644 compiler/testData/ir/irText/calls.kt create mode 100644 compiler/testData/ir/irText/calls.txt create mode 100644 compiler/testData/ir/irText/extensionPropertyGetterCall.kt create mode 100644 compiler/testData/ir/irText/extensionPropertyGetterCall.txt create mode 100644 compiler/testData/ir/irText/references.kt create mode 100644 compiler/testData/ir/irText/references.txt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt index ac7336dc0c6..6883e952a3a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt @@ -16,37 +16,61 @@ package org.jetbrains.kotlin.psi2ir +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument +import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.constants.IntValue import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator +import org.jetbrains.kotlin.resolve.scopes.receivers.* class IrExpressionGenerator( override val context: IrGeneratorContext, val declarationFactory: IrDeclarationFactory -) : KtVisitor(), IrGenerator { +) : KtVisitor(), IrGenerator { fun generateExpression(ktExpression: KtExpression) = ktExpression.generate() - private fun KtElement.generate(): IrExpressionBase = accept(this@IrExpressionGenerator, null) - private fun KtExpression.type() = getType(this) ?: TODO("no type for expression") + private fun KtElement.generate(): IrExpression = + accept(this@IrExpressionGenerator, null).applySmartCast(this) - override fun visitExpression(expression: KtExpression, data: Nothing?): IrExpressionBase = - IrDummyExpression(expression.startOffset, expression.endOffset, expression.type()) + private fun KtExpression.type() = + getType(this) ?: TODO("no type for expression") - override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrExpressionBase { - val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, expression.type()) - expression.statements.forEach { irBlock.childExpressions.add(it.generate()) } + private fun IrExpression.applySmartCast(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 } + } + } + return this + } + + override fun visitExpression(expression: KtExpression, data: Nothing?): IrExpression = + IrDummyExpression(expression.startOffset, expression.endOffset, expression.type(), expression.javaClass.simpleName) + + override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrExpression { + val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), false) + expression.statements.forEach { irBlock.addChildExpression(it.generate()) } return irBlock } - override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrExpressionBase = + override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrExpression = IrReturnExpressionImpl(expression.startOffset, expression.endOffset, expression.type()) .apply { this.childExpression = expression.returnedExpression?.generate() } - override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpressionBase { + override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression { val compileTimeConstant = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) ?: error("KtConstantExpression was not evaluated: ${expression.text}") val constantValue = compileTimeConstant.toConstantValue(expression.type()) @@ -62,7 +86,7 @@ class IrExpressionGenerator( } } - override fun visitStringTemplateExpression(expression: KtStringTemplateExpression, data: Nothing?): IrExpressionBase { + override fun visitStringTemplateExpression(expression: KtStringTemplateExpression, data: Nothing?): IrExpression { if (expression.entries.size == 1 && expression.entries[0] is KtLiteralStringTemplateEntry) { return expression.entries[0].generate() } @@ -72,6 +96,110 @@ class IrExpressionGenerator( return irStringTemplate } - override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrExpressionBase = + override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrExpression = IrLiteralExpressionImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text) + + override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): IrExpression { + val resolvedCall = getResolvedCall(expression) + + if (resolvedCall is VariableAsFunctionResolvedCall) { + TODO("Unexpected VariableAsFunctionResolvedCall") + } + + val descriptor = resolvedCall?.resultingDescriptor ?: get(BindingContext.REFERENCE_TARGET, expression) + + return when (descriptor) { + is ClassDescriptor -> + IrSingletonReferenceImpl(expression.startOffset, expression.endOffset, expression.type(), + descriptor.singletonDescriptor() ?: TODO("Unsupported class as value: ${descriptor.name}")) + is PropertyDescriptor -> { + generateCall( + expression, + resolvedCall ?: TODO("Property, no resolved call: ${descriptor.name}"), + IrCallableOperator.PROPERTY_GET + ) + } + is VariableDescriptor -> + IrVariableReferenceImpl(expression.startOffset, expression.endOffset, expression.type(), descriptor) + else -> + IrDummyExpression(expression.startOffset, expression.endOffset, expression.type(), + expression.getReferencedName() + + ": ${descriptor?.name} ${descriptor?.javaClass?.simpleName}") + } + } + + override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrExpression { + val resolvedCall = getResolvedCall(expression) ?: TODO("No resolved call for call expression") + + if (resolvedCall is VariableAsFunctionResolvedCall) { + TODO("VariableAsFunctionResolvedCall = variable call + invoke call") + } + + return generateCall(expression, resolvedCall, null, null) + } + + private fun generateCall( + ktExpression: KtExpression, + resolvedCall: ResolvedCall, + operator: IrCallableOperator?, + superQualifier: ClassDescriptor? = null + ): IrExpression = + IrCallExpressionImpl( + ktExpression.startOffset, ktExpression.endOffset, ktExpression.type(), + resolvedCall.resultingDescriptor, resolvedCall.call.isSafeCall(), operator, superQualifier + ).apply { + dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver) + extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver) + + val valueParameters = resolvedCall.resultingDescriptor.valueParameters + val valueArguments = resolvedCall.valueArgumentsByIndex ?: TODO("null for value arguments: ${ktExpression.text}") + for (index in valueArguments.indices) { + val valueArgument = valueArguments[index] + val valueParameter = valueParameters[index] + putValueArgument(valueParameter, generateValueArgument(valueParameter, valueArgument)) + } + } + + private fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? = + when (receiver) { + is ImplicitClassReceiver -> + IrThisExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, receiver.classDescriptor) + is ThisClassReceiver -> + (receiver as? ExpressionReceiver)?.expression?.let { receiverExpression -> + IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor) + } ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver") + is ExpressionReceiver -> + receiver.expression.generate() + is ClassValueReceiver -> + IrSingletonReferenceImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type, + receiver.classQualifier.descriptor) + is ExtensionReceiver -> + IrExtensionReceiverReferenceImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, + receiver.declarationDescriptor.extensionReceiverParameter!!) + null -> + null + else -> + IrDummyExpression(ktExpression.startOffset, ktExpression.endOffset, receiver.type, + "Receiver: ${receiver.javaClass.simpleName}") + } + + private fun generateValueArgument(valueParameter: ValueParameterDescriptor, valueArgument: ResolvedValueArgument): IrExpression? { + if (valueParameter.varargElementType == null) { + assert(valueArgument.arguments.size == 1) { "Single value argument expected for a non-vararg parameter" } + return valueArgument.arguments.single().getArgumentExpression()!!.generate() + } + else { + TODO("vararg") + } + } + + companion object { + fun ClassDescriptor.singletonDescriptor(): ClassDescriptor? = + if (DescriptorUtils.isObject(this) || DescriptorUtils.isEnumEntry(this)) + this + else + companionObjectDescriptor + + + } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrGenerator.kt index 8411e8006f0..2373304449d 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrGenerator.kt @@ -16,7 +16,10 @@ package org.jetbrains.kotlin.psi2ir +import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice @@ -34,4 +37,7 @@ inline fun IrGenerator.getOrFail(slice: ReadOnlySlice, key: K context.bindingContext[slice, key] ?: throw RuntimeException(message(key)) inline fun IrGenerator.getOrElse(slice: ReadOnlySlice, key: K, otherwise: (K) -> V): V = - context.bindingContext[slice, key] ?: otherwise(key) \ No newline at end of file + context.bindingContext[slice, key] ?: otherwise(key) + +fun IrGenerator.getResolvedCall(key: KtExpression): ResolvedCall? = + key.getResolvedCall(context.bindingContext) \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt index 53d437254c7..b61f9724f01 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt @@ -20,12 +20,18 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrBlockExpression : IrCompoundExpressionN +interface IrBlockExpression : IrCompoundExpressionN { + val hasResult: Boolean +} + +fun IrBlockExpression.getResultExpression() = + if (hasResult) childExpressions.lastOrNull() else null class IrBlockExpressionImpl( startOffset: Int, endOffset: Int, - type: KotlinType + type: KotlinType, + override val hasResult: Boolean ) : IrCompoundExpressionNBase(startOffset, endOffset, type), IrBlockExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitBlockExpression(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt new file mode 100644 index 00000000000..89822a003c4 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt @@ -0,0 +1,142 @@ +/* + * 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.ir.expressions + +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.types.KotlinType + +interface IrCallExpression : IrCompoundExpression { + val superQualifier: ClassDescriptor? + val operator: IrCallableOperator? + val isSafe: Boolean + val callee: CallableDescriptor + var dispatchReceiver: IrExpression? + var extensionReceiver: IrExpression? + + fun getValueArgument(valueParameterDescriptor: ValueParameterDescriptor): IrExpression? + fun putValueArgument(valueParameterDescriptor: ValueParameterDescriptor, valueArgument: IrExpression?) + fun removeValueArgument(valueParameterDescriptor: ValueParameterDescriptor) + + fun acceptValueArguments(visitor: IrElementVisitor, data: D) +} + +fun IrCallExpression.getMappedValueArguments(): List = + callee.valueParameters.mapNotNull { getValueArgument(it) } + +abstract class IrCallExpressionBase( + startOffset: Int, + endOffset: Int, + type: KotlinType, + override final val callee: CallableDescriptor, + override val isSafe: Boolean, + override val operator: IrCallableOperator?, + override val superQualifier: ClassDescriptor? +) : IrExpressionBase(startOffset, endOffset, type), IrCallExpression { + private val argumentsByParameterIndex = + kotlin.arrayOfNulls(callee.valueParameters.size) + + override var dispatchReceiver: IrExpression? = null + set(newReceiver) { + field?.detach() + field = newReceiver + newReceiver?.setTreeLocation(this, DISPATCH_RECEIVER_INDEX) + } + + override var extensionReceiver: IrExpression? = null + set(newReceiver) { + field?.detach() + field = newReceiver + newReceiver?.setTreeLocation(this, EXTENSION_RECEIVER_INDEX) + } + + override fun getValueArgument(valueParameterDescriptor: ValueParameterDescriptor): IrExpression? = + argumentsByParameterIndex[valueParameterDescriptor.index] + + override fun putValueArgument(valueParameterDescriptor: ValueParameterDescriptor, valueArgument: IrExpression?) { + putValueArgument(valueParameterDescriptor.index, valueArgument) + } + + private fun putValueArgument(index: Int, valueArgument: IrExpression?) { + argumentsByParameterIndex[index]?.detach() + argumentsByParameterIndex[index] = valueArgument + valueArgument?.setTreeLocation(this, index) + } + + override fun removeValueArgument(valueParameterDescriptor: ValueParameterDescriptor) { + argumentsByParameterIndex[valueParameterDescriptor.index]?.detach() + argumentsByParameterIndex[valueParameterDescriptor.index] = null + } + + override fun getChildExpression(index: Int): IrExpression? = + when (index) { + DISPATCH_RECEIVER_INDEX -> + dispatchReceiver + EXTENSION_RECEIVER_INDEX -> + extensionReceiver + else -> + argumentsByParameterIndex.getOrNull(index) + } + + override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { + validateChild(oldChild) + when (oldChild.index) { + DISPATCH_RECEIVER_INDEX -> + dispatchReceiver = newChild + EXTENSION_RECEIVER_INDEX -> + extensionReceiver = newChild + else -> + putValueArgument(oldChild.index, newChild) + } + } + + override fun acceptValueArguments(visitor: IrElementVisitor, data: D) { + for (valueArgument in argumentsByParameterIndex) { + valueArgument?.let { it.accept(visitor, data) } + } + } + + override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { + dispatchReceiver?.accept(visitor, data) + extensionReceiver?.accept(visitor, data) + acceptValueArguments(visitor, data) + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + acceptChildExpressions(visitor, data) + } + + companion object { + const val DISPATCH_RECEIVER_INDEX = -1 + const val EXTENSION_RECEIVER_INDEX = -2 + } +} + +class IrCallExpressionImpl( + startOffset: Int, + endOffset: Int, + type: KotlinType, + callee: CallableDescriptor, + isSafe: Boolean, + operator: IrCallableOperator? = null, + superQualifier: ClassDescriptor? = null +) : IrCallExpressionBase(startOffset, endOffset, type, callee, isSafe, operator, superQualifier), IrCallExpression { + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitCallExpression(this, data) +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableOperator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableOperator.kt new file mode 100644 index 00000000000..db4d3b1767e --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableOperator.kt @@ -0,0 +1,69 @@ +/* + * 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.ir.expressions + +enum class IrCallableOperator { + PROPERTY_GET, + PROPERTY_SET, + INVOKE, + INVOKE_EXTENSION, + PLUSPLUS, + MINUSMINUS, + UMINUS, + EXCL, + LT, + GT, + LTEQ, + GTEQ, + EQEQ, + EQEQEQ, + EXCLEQ, + EXCLEQEQ, + IN, + NOT_IN, + ANDAND, + OROR, + RANGE, + PLUS, + MINUS, + MUL, + DIV, + MOD, + PLUSEQ, + MINUSEQ, + MULEQ, + DIVEQ, + MODEQ; +} + +fun IrCallableOperator.isCompoundAssignment(): Boolean = + this >= IrCallableOperator.PLUSEQ && this <= IrCallableOperator.MODEQ + +fun IrCallableOperator.hasCompoundAssignmentDual(): Boolean = + this >= IrCallableOperator.PLUS && this <= IrCallableOperator.MOD + +fun IrCallableOperator.toDualOperator(): IrCallableOperator = + when { + isCompoundAssignment() -> + IrCallableOperator.values()[this.ordinal - IrCallableOperator.PLUSEQ.ordinal + IrCallableOperator.PLUS.ordinal] + hasCompoundAssignmentDual() -> + IrCallableOperator.values()[this.ordinal - IrCallableOperator.PLUS.ordinal + IrCallableOperator.PLUSEQ.ordinal] + else -> + throw UnsupportedOperationException("Operator $this is not a compound assignment") + } + + diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt new file mode 100644 index 00000000000..aaaac125528 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt @@ -0,0 +1,77 @@ +/* + * 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.ir.expressions + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.types.KotlinType + + +interface IrDeclarationReference : IrExpression { + val descriptor: DeclarationDescriptor +} + +interface IrVariableReference : IrDeclarationReference { + override val descriptor: VariableDescriptor +} + +interface IrSingletonReference : IrDeclarationReference { + override val descriptor: ClassDescriptor +} + +interface IrExtensionReceiverReference : IrDeclarationReference { + override val descriptor: CallableDescriptor +} + +abstract class IrDeclarationReferenceBase( + startOffset: Int, + endOffset: Int, + type: KotlinType, + override val descriptor: D +) : IrTerminalExpressionBase(startOffset, endOffset, type), IrDeclarationReference + +class IrVariableReferenceImpl( + startOffset: Int, + endOffset: Int, + type: KotlinType, + descriptor: VariableDescriptor +) : IrDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrVariableReference { + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitVariableReference(this, data) +} + +class IrSingletonReferenceImpl( + startOffset: Int, + endOffset: Int, + type: KotlinType, + descriptor: ClassDescriptor +) : IrDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrSingletonReference { + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitSingletonReference(this, data) +} + + +class IrExtensionReceiverReferenceImpl( + startOffset: Int, + endOffset: Int, + type: KotlinType, + override val descriptor: CallableDescriptor +) : IrTerminalExpressionBase(startOffset, endOffset, type), IrExtensionReceiverReference { + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitExtensionReceiverReference(this, data) + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDummyExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDummyExpression.kt index 87112340fb5..64611478f2c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDummyExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDummyExpression.kt @@ -22,10 +22,11 @@ import org.jetbrains.kotlin.types.KotlinType class IrDummyExpression( startOffset: Int, endOffset: Int, - type: KotlinType + type: KotlinType, + val description: String ) : IrExpressionBase(startOffset, endOffset, type) { override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitElement(this, data) + visitor.visitDummyExpression(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { // No children diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt index 443f860d605..c94cf68f4b9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElementBase +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType @@ -53,4 +54,14 @@ abstract class IrExpressionBase( this.parent = parent this.index = index } +} + +abstract class IrTerminalExpressionBase( + startOffset: Int, + endOffset: Int, + type: KotlinType +) : IrExpressionBase(startOffset, endOffset, type) { + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + // No children + } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt index 04d1a6b8d63..bcfe3ea64d9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt @@ -33,16 +33,6 @@ interface IrExpressionOwner1 : IrExpressionOwner { } } -interface IrExpressionOwner2 : IrExpressionOwner { - var childExpression1: IrExpression? - var childExpression2: IrExpression? - - companion object { - const val EXPRESSION1_INDEX = 1 - const val EXPRESSION2_INDEX = 2 - } -} - interface IrExpressionOwnerN : IrExpressionOwner { val childExpressions: List fun addChildExpression(child: IrExpression) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLiteralExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLiteralExpression.kt index fdfca5bac5b..d090cd55fb6 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLiteralExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLiteralExpression.kt @@ -48,14 +48,10 @@ class IrLiteralExpressionImpl ( type: KotlinType, override val kind: IrLiteralKind, override val value: T -) : IrExpressionBase(startOffset, endOffset, type), IrLiteralExpression { +) : IrTerminalExpressionBase(startOffset, endOffset, type), IrLiteralExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitLiteral(this, data) - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - // No children - } - companion object { fun string(startOffset: Int, endOffset: Int, type: KotlinType, value: String): IrLiteralExpressionImpl = IrLiteralExpressionImpl(startOffset, endOffset, type, IrLiteralKind.String, value) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt new file mode 100644 index 00000000000..3e533fac676 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt @@ -0,0 +1,36 @@ +/* + * 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.ir.expressions + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.types.KotlinType + +interface IrThisExpression : IrExpression { + val classDescriptor: ClassDescriptor +} + +class IrThisExpressionImpl( + startOffset: Int, + endOffset: Int, + type: KotlinType, + override val classDescriptor: ClassDescriptor +) : IrTerminalExpressionBase(startOffset, endOffset, type), IrThisExpression { + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitThisExpression(this, data) + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt new file mode 100644 index 00000000000..0b399e0b053 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt @@ -0,0 +1,44 @@ +/* + * 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.ir.expressions + +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.types.KotlinType + +enum class IrTypeOperator { + SMART_AS, + AS, + AS_SAFE, + IS; +} + +interface IrTypeOperatorExpression : IrExpression, IrCompoundExpression1 { + val operator: IrTypeOperator + val typeOperand: KotlinType +} + +class IrTypeOperatorExpressionImpl( + startOffset: Int, + endOffset: Int, + type: KotlinType, + override val operator: IrTypeOperator, + override val typeOperand: KotlinType +) : IrCompoundExpression1Base(startOffset, endOffset, type), IrTypeOperatorExpression { + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitTypeOperatorExpression(this, data) + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index 68cfce1de02..5eb5e0e54cf 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -18,23 +18,52 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.expressions.IrCallExpression import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.utils.Printer fun IrDeclaration.dump(): String { val sb = StringBuilder() - accept(DumpIrTreeVisitor(sb), null) + accept(DumpIrTreeVisitor(sb), "") return sb.toString() } -class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { +class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { val printer = Printer(out, " ") val elementRenderer = RenderIrElementVisitor() - override fun visitElement(element: IrElement, data: Nothing?) { - printer.println(element.accept(elementRenderer, null)) + override fun visitElement(element: IrElement, data: String) { + element.dumpLabeledSubTree(data) + } + + override fun visitCallExpression(expression: IrCallExpression, data: String) { + expression.dumpLabeledElementWith(data) { + expression.dispatchReceiver?.accept(this, "\$this") + expression.extensionReceiver?.accept(this, "\$receiver") + for (valueParameter in expression.callee.valueParameters) { + expression.getValueArgument(valueParameter)?.accept(this, valueParameter.name.asString()) + } + } + } + + private inline fun IrElement.dumpLabeledElementWith(label: String, body: () -> Unit) { + printer.println(accept(elementRenderer, null).withLabel(label)) + indented(body) + } + + private fun IrElement.dumpLabeledSubTree(label: String) { + printer.println(accept(elementRenderer, null).withLabel(label)) + indented { + acceptChildren(this@DumpIrTreeVisitor, "") + } + } + + private inline fun indented(body: () -> Unit) { printer.pushIndent() - element.acceptChildren(this, null) + body() printer.popIndent() } + + private fun String.withLabel(label: String) = + if (label.isEmpty()) this else "$label: $this" } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index 5136717c75c..e513df74106 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.ir.util +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* @@ -27,40 +28,58 @@ import org.jetbrains.kotlin.renderer.OverrideRenderingPolicy class RenderIrElementVisitor : IrElementVisitor { override fun visitElement(element: IrElement, data: Nothing?): String = - "??? ${element.javaClass.simpleName}" + "? ${element.javaClass.simpleName}" override fun visitDeclaration(declaration: IrDeclaration, data: Nothing?): String = - "??? ${declaration.javaClass.simpleName} ${declaration.descriptor?.name}" + "? ${declaration.javaClass.simpleName} ${declaration.descriptor?.name}" override fun visitFile(declaration: IrFile, data: Nothing?): String = "IrFile ${declaration.name}" override fun visitFunction(declaration: IrFunction, data: Nothing?): String = - "IrFunction ${declaration.renderDescriptor()}" + "IrFunction ${declaration.descriptor.render()}" override fun visitProperty(declaration: IrProperty, data: Nothing?): String = - "IrProperty ${declaration.renderDescriptor()} getter=${declaration.getter?.name()} setter=${declaration.setter?.name()}" + "IrProperty ${declaration.descriptor.render()} getter=${declaration.getter?.name()} setter=${declaration.setter?.name()}" override fun visitPropertyGetter(declaration: IrPropertyGetter, data: Nothing?): String = - "IrPropertyGetter ${declaration.renderDescriptor()} property=${declaration.property?.name()}" + "IrPropertyGetter ${declaration.descriptor.render()} property=${declaration.property?.name()}" override fun visitPropertySetter(declaration: IrPropertySetter, data: Nothing?): String = - "IrPropertySetter ${declaration.renderDescriptor()} property=${declaration.property?.name()}" + "IrPropertySetter ${declaration.descriptor.render()} property=${declaration.property?.name()}" override fun visitExpressionBody(body: IrExpressionBody, data: Nothing?): String = "IrExpressionBody" override fun visitExpression(expression: IrExpression, data: Nothing?): String = - "??? ${expression.javaClass.simpleName} type=${expression.renderType()}" + "? ${expression.javaClass.simpleName} type=${expression.renderType()}" override fun visitLiteral(expression: IrLiteralExpression, data: Nothing?): String = - "IrLiteral ${expression.kind} type=${expression.renderType()} value='${expression.value}'" + "LITERAL ${expression.kind} type=${expression.renderType()} value='${expression.value}'" override fun visitBlockExpression(expression: IrBlockExpression, data: Nothing?): String = - "IrBlockExpression type=${expression.renderType()}" + "BLOCK type=${expression.renderType()}" override fun visitReturnExpression(expression: IrReturnExpression, data: Nothing?): String = - "IrReturnExpression type=${expression.renderType()}" + "RETURN type=${expression.renderType()}" + + override fun visitVariableReference(expression: IrVariableReference, data: Nothing?): String = + "VAR ${expression.descriptor.name}" + + override fun visitSingletonReference(expression: IrSingletonReference, data: Nothing?): String = + "SINGLETON ${expression.descriptor.name}" + + override fun visitExtensionReceiverReference(expression: IrExtensionReceiverReference, data: Nothing?): String = + "\$RECEIVER of: ${expression.descriptor.containingDeclaration.name}" + + override fun visitThisExpression(expression: IrThisExpression, data: Nothing?): String = + "THIS ${expression.classDescriptor.render()}" + + override fun visitCallExpression(expression: IrCallExpression, data: Nothing?): String = + "CALL ${expression.callee.name} ${expression.operator ?: ""}" + + override fun visitDummyExpression(expression: IrDummyExpression, data: Nothing?): String = + "DUMMY ${expression.description}" companion object { private val DESCRIPTOR_RENDERER = DescriptorRenderer.withOptions { @@ -72,8 +91,13 @@ class RenderIrElementVisitor : IrElementVisitor { modifiers = DescriptorRendererModifier.ALL } - private fun IrDeclaration.name(): String = descriptor?.let { it.name.toString() } ?: "" - private fun IrDeclaration.renderDescriptor(): String = descriptor?.let { DESCRIPTOR_RENDERER.render(it) } ?: "" - private fun IrExpression.renderType(): String = DESCRIPTOR_RENDERER.renderType(type) + internal fun IrDeclaration.name(): String = + descriptor?.let { it.name.toString() } ?: "" + + internal fun DeclarationDescriptor.render(): String = + DESCRIPTOR_RENDERER.render(this) + + internal fun IrExpression.renderType(): String = + DESCRIPTOR_RENDERER.renderType(type) } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt index 28f3472e0dd..54c990975d5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt @@ -43,4 +43,18 @@ interface IrElementVisitor { fun visitReturnExpression(expression: IrReturnExpression, data: D): R = visitExpression(expression, data) fun visitBlockExpression(expression: IrBlockExpression, data: D): R = visitExpression(expression, data) fun visitStringTemplate(expression: IrStringConcatenationExpression, data: D) = visitExpression(expression, data) + fun visitThisExpression(expression: IrThisExpression, data: D) = visitExpression(expression, data) + fun visitDeclarationReference(expression: IrDeclarationReference, data: D) = visitExpression(expression, data) + fun visitVariableReference(expression: IrVariableReference, data: D) = visitDeclarationReference(expression, data) + fun visitSingletonReference(expression: IrSingletonReference, data: D) = visitDeclarationReference(expression, data) + fun visitExtensionReceiverReference(expression: IrExtensionReceiverReference, data: D) = visitDeclarationReference(expression, data) + + + fun visitCallExpression(expression: IrCallExpression, data: D) = visitExpression(expression, data) + fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: D) = visitExpression(expression, data) + + // NB Use it only for testing purposes; will be removed as soon as all Kotlin expression types are covered + fun visitDummyExpression(expression: IrDummyExpression, data: D) = visitExpression(expression, data) + + } diff --git a/compiler/testData/ir/irText/boxOk.txt b/compiler/testData/ir/irText/boxOk.txt index 34da35098fb..5bf9798e49f 100644 --- a/compiler/testData/ir/irText/boxOk.txt +++ b/compiler/testData/ir/irText/boxOk.txt @@ -1,5 +1,5 @@ IrFile /boxOk.kt IrFunction public fun box(): kotlin.String IrExpressionBody - IrReturnExpression type=kotlin.String - IrLiteral String type=kotlin.String value='OK' + RETURN type=kotlin.String + LITERAL String type=kotlin.String value='OK' diff --git a/compiler/testData/ir/irText/calls.kt b/compiler/testData/ir/irText/calls.kt new file mode 100644 index 00000000000..7e1a5dfa12d --- /dev/null +++ b/compiler/testData/ir/irText/calls.kt @@ -0,0 +1,8 @@ +fun foo(x: Int, y: Int) = x +fun bar(x: Int) = foo(x, 1) +fun qux(x: Int) = foo(foo(x, x), x) + +fun Int.ext1() = this +fun Int.ext2(x: Int) = foo(this, x) + +// IR_FILE_TXT calls.txt \ No newline at end of file diff --git a/compiler/testData/ir/irText/calls.txt b/compiler/testData/ir/irText/calls.txt new file mode 100644 index 00000000000..a4c054d6b02 --- /dev/null +++ b/compiler/testData/ir/irText/calls.txt @@ -0,0 +1,29 @@ +IrFile /calls.kt + IrFunction public fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int): kotlin.Int + IrExpressionBody + RETURN type=kotlin.Int + VAR x + IrFunction public fun bar(/*0*/ x: kotlin.Int): kotlin.Int + IrExpressionBody + RETURN type=kotlin.Int + 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 + x: VAR x + y: VAR x + y: VAR x + IrFunction public fun kotlin.Int.ext1(): kotlin.Int + IrExpressionBody + RETURN type=kotlin.Int + DUMMY KtThisExpression + IrFunction public fun kotlin.Int.ext2(/*0*/ x: kotlin.Int): kotlin.Int + IrExpressionBody + RETURN type=kotlin.Int + CALL foo + x: DUMMY KtThisExpression + y: VAR x diff --git a/compiler/testData/ir/irText/extensionPropertyGetterCall.kt b/compiler/testData/ir/irText/extensionPropertyGetterCall.kt new file mode 100644 index 00000000000..211bfa4934d --- /dev/null +++ b/compiler/testData/ir/irText/extensionPropertyGetterCall.kt @@ -0,0 +1,4 @@ +val String.okext: String get() = "OK" +fun String.test5() = okext + +// IR_FILE_TXT extensionPropertyGetterCall.txt \ No newline at end of file diff --git a/compiler/testData/ir/irText/extensionPropertyGetterCall.txt b/compiler/testData/ir/irText/extensionPropertyGetterCall.txt new file mode 100644 index 00000000000..405cafdc503 --- /dev/null +++ b/compiler/testData/ir/irText/extensionPropertyGetterCall.txt @@ -0,0 +1,11 @@ +IrFile /extensionPropertyGetterCall.kt + IrProperty public val kotlin.String.okext: kotlin.String getter= setter=null + IrPropertyGetter public fun kotlin.String.(): kotlin.String property=okext + IrExpressionBody + RETURN type=kotlin.String + LITERAL String type=kotlin.String value='OK' + IrFunction public fun kotlin.String.test5(): kotlin.String + IrExpressionBody + RETURN type=kotlin.String + CALL okext PROPERTY_GET + $receiver: $RECEIVER of: test5 diff --git a/compiler/testData/ir/irText/references.kt b/compiler/testData/ir/irText/references.kt new file mode 100644 index 00000000000..6aa5c1244af --- /dev/null +++ b/compiler/testData/ir/irText/references.kt @@ -0,0 +1,19 @@ +val ok = "OK" +val ok2 = ok +val ok3: String get() = "OK" + +fun test1() = ok + +fun test2(x: String) = x + +fun test3(): String { + val x = "OK" + return x +} + +fun test4() = ok3 + +val String.okext: String get() = "OK" +fun String.test5() = okext + +// IR_FILE_TXT references.txt \ No newline at end of file diff --git a/compiler/testData/ir/irText/references.txt b/compiler/testData/ir/irText/references.txt new file mode 100644 index 00000000000..23e0cebed45 --- /dev/null +++ b/compiler/testData/ir/irText/references.txt @@ -0,0 +1,42 @@ +IrFile /references.kt + IrProperty public val ok: kotlin.String = "OK" getter=null setter=null + IrExpressionBody + RETURN type=kotlin.String + LITERAL String type=kotlin.String value='OK' + IrProperty public val ok2: kotlin.String = "OK" getter=null setter=null + IrExpressionBody + RETURN type=kotlin.String + CALL ok PROPERTY_GET + IrProperty public val ok3: kotlin.String getter= setter=null + IrPropertyGetter public fun (): kotlin.String property=ok3 + IrExpressionBody + RETURN type=kotlin.String + LITERAL String type=kotlin.String value='OK' + IrFunction public fun test1(): kotlin.String + IrExpressionBody + RETURN type=kotlin.String + CALL ok PROPERTY_GET + IrFunction public fun test2(/*0*/ x: kotlin.String): kotlin.String + IrExpressionBody + RETURN type=kotlin.String + VAR x + IrFunction public fun test3(): kotlin.String + IrExpressionBody + BLOCK type=kotlin.Nothing + DUMMY KtProperty + RETURN type=kotlin.Nothing + VAR x + IrFunction public fun test4(): kotlin.String + IrExpressionBody + RETURN type=kotlin.String + CALL ok3 PROPERTY_GET + IrProperty public val kotlin.String.okext: kotlin.String getter= setter=null + IrPropertyGetter public fun kotlin.String.(): kotlin.String property=okext + IrExpressionBody + RETURN type=kotlin.String + LITERAL String type=kotlin.String value='OK' + IrFunction public fun kotlin.String.test5(): kotlin.String + IrExpressionBody + RETURN type=kotlin.String + CALL okext PROPERTY_GET + $receiver: $RECEIVER of: test5 diff --git a/compiler/testData/ir/irText/smoke.txt b/compiler/testData/ir/irText/smoke.txt index 3274804b7e3..fc0f0b021e1 100644 --- a/compiler/testData/ir/irText/smoke.txt +++ b/compiler/testData/ir/irText/smoke.txt @@ -1,27 +1,27 @@ IrFile /smoke.kt IrFunction public fun testFun(): kotlin.String IrExpressionBody - IrBlockExpression type=kotlin.Nothing - IrReturnExpression type=kotlin.Nothing - IrLiteral String type=kotlin.String value='OK' + BLOCK type=kotlin.Nothing + RETURN type=kotlin.Nothing + LITERAL String type=kotlin.String value='OK' IrProperty public val testSimpleVal: kotlin.Int = 1 getter=null setter=null IrExpressionBody - IrReturnExpression type=kotlin.Int - IrLiteral Int type=kotlin.Int value='1' + RETURN type=kotlin.Int + LITERAL Int type=kotlin.Int value='1' IrProperty public val testValWithGetter: kotlin.Int getter= setter=null IrPropertyGetter public fun (): kotlin.Int property=testValWithGetter IrExpressionBody - IrReturnExpression type=kotlin.Int - IrLiteral Int type=kotlin.Int value='42' + RETURN type=kotlin.Int + LITERAL Int type=kotlin.Int value='42' IrProperty public var testSimpleVar: kotlin.Int getter=null setter=null IrExpressionBody - IrReturnExpression type=kotlin.Int - IrLiteral Int type=kotlin.Int value='2' + RETURN type=kotlin.Int + LITERAL Int type=kotlin.Int value='2' IrProperty public var testVarWithAccessors: kotlin.Int getter= setter= IrPropertyGetter public fun (): kotlin.Int property=testVarWithAccessors IrExpressionBody - IrReturnExpression type=kotlin.Int - IrLiteral Int type=kotlin.Int value='42' + RETURN type=kotlin.Int + LITERAL Int type=kotlin.Int value='42' IrPropertySetter public fun (/*0*/ v: kotlin.Int): kotlin.Unit property=testVarWithAccessors IrExpressionBody - IrBlockExpression type=kotlin.Unit + BLOCK type=kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 98246d955ac..50ceed08853 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -41,6 +41,24 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("calls.kt") + public void testCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/calls.kt"); + doTest(fileName); + } + + @TestMetadata("extensionPropertyGetterCall.kt") + public void testExtensionPropertyGetterCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/extensionPropertyGetterCall.kt"); + doTest(fileName); + } + + @TestMetadata("references.kt") + public void testReferences() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/references.kt"); + doTest(fileName); + } + @TestMetadata("smoke.kt") public void testSmoke() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/smoke.kt");