[IR] Improve stepping/LVT behavior around destructuring

This commit is contained in:
Kristoffer Andersen
2022-03-07 19:39:32 +01:00
committed by Alexander Udalov
parent c3dbb44e5f
commit 7f531d8426
21 changed files with 197 additions and 38 deletions
@@ -313,6 +313,12 @@ public class FirSteppingTestGenerated extends AbstractFirSteppingTest {
runTest("compiler/testData/debug/stepping/localFunctionWIthOnelineExpressionBody.kt"); runTest("compiler/testData/debug/stepping/localFunctionWIthOnelineExpressionBody.kt");
} }
@Test
@TestMetadata("localProperty.kt")
public void testLocalProperty() throws Exception {
runTest("compiler/testData/debug/stepping/localProperty.kt");
}
@Test @Test
@TestMetadata("multilineExpression.kt") @TestMetadata("multilineExpression.kt")
public void testMultilineExpression() throws Exception { public void testMultilineExpression() throws Exception {
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
@@ -24,7 +25,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
@@ -252,4 +252,7 @@ open class JvmGeneratorExtensionsImpl(
override val parametersAreAssignable: Boolean override val parametersAreAssignable: Boolean
get() = true get() = true
override val debugInfoOnlyOnVariablesInDestructuringDeclarations: Boolean
get() = true
} }
@@ -722,10 +722,10 @@ private class TypeOperatorLowering(private val backendContext: JvmBackendContext
val source = if (owner is IrFunction && owner.isDelegated()) { val source = if (owner is IrFunction && owner.isDelegated()) {
"${owner.name.asString()}(...)" "${owner.name.asString()}(...)"
} else { } else {
val (startOffset, endOffset) = expression.extents()
val declarationParent = parent as? IrDeclaration val declarationParent = parent as? IrDeclaration
val sourceView = declarationParent?.let(::sourceViewFor) val sourceView = declarationParent?.let(::sourceViewFor)
if (sourceView != null && startOffset >= 0 && endOffset < sourceView.length) { val (startOffset, endOffset) = expression.extents()
if (sourceView?.validSourcePosition(startOffset, endOffset) == true) {
sourceView.subSequence(startOffset, endOffset).toString() sourceView.subSequence(startOffset, endOffset).toString()
} else { } else {
// Fallback for inconsistent line numbers // Fallback for inconsistent line numbers
@@ -757,6 +757,9 @@ private class TypeOperatorLowering(private val backendContext: JvmBackendContext
origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR || origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR ||
origin == IrDeclarationOrigin.DELEGATED_MEMBER origin == IrDeclarationOrigin.DELEGATED_MEMBER
private fun CharSequence.validSourcePosition(startOffset: Int, endOffset: Int): Boolean =
startOffset in 0 until endOffset && endOffset < length
private fun IrElement.extents(): Pair<Int, Int> { private fun IrElement.extents(): Pair<Int, Int> {
var startOffset = Int.MAX_VALUE var startOffset = Int.MAX_VALUE
var endOffset = 0 var endOffset = 0
@@ -103,7 +103,7 @@ class BodyGenerator(
valueParameter.type.toIrType(), valueParameter.type.toIrType(),
IrStatementOrigin.DESTRUCTURING_DECLARATION IrStatementOrigin.DESTRUCTURING_DECLARATION
) )
statementGenerator.declareComponentVariablesInBlock(ktDestructuringDeclaration, irBlockBody, parameterValue) statementGenerator.declareComponentVariablesInBlock(ktDestructuringDeclaration, irBlockBody, parameterValue, parameterValue)
} }
val ktBodyStatements = ktBody.statements val ktBodyStatements = ktBody.statements
@@ -463,8 +463,14 @@ fun IrExpression.isUnchanging() =
fun IrExpression.hasNoSideEffects() = isUnchanging() || this is IrGetValue fun IrExpression.hasNoSideEffects() = isUnchanging() || this is IrGetValue
fun CallGenerator.generateCall(ktElement: KtElement, call: CallBuilder, origin: IrStatementOrigin? = null) = fun CallGenerator.generateCall(
generateCall(ktElement.startOffsetSkippingComments, ktElement.endOffset, call, origin) ktElement: KtElement,
call: CallBuilder,
origin: IrStatementOrigin? = null,
startOffset: Int = ktElement.startOffsetSkippingComments,
endOffset: Int = ktElement.endOffset,
) =
generateCall(startOffset, endOffset, call, origin)
fun CallGenerator.generateCall(irExpression: IrExpression, call: CallBuilder, origin: IrStatementOrigin? = null) = fun CallGenerator.generateCall(irExpression: IrExpression, call: CallBuilder, origin: IrStatementOrigin? = null) =
generateCall(irExpression.startOffset, irExpression.endOffset, call, origin) generateCall(irExpression.startOffset, irExpression.endOffset, call, origin)
@@ -48,4 +48,35 @@ open class GeneratorExtensions : StubGeneratorExtensions() {
open val parametersAreAssignable: Boolean open val parametersAreAssignable: Boolean
get() = false get() = false
/**
* Enables improved source offsets for the desugared IR generated for
* destructuring declarations.
*
* Local variables defined by destructuring, e.g.
*
* val (x, y) = destructee()
*
* is represented in IR by
*
* block {
* val containerTmp = destructee()
* val x = containerTmp.component1()
* val y = containerTmp.component2()
* }
*
* When [debugInfoOnlyOnVariablesInDestructuringDeclarations] is `false`, the
* access to `containerTmp` in the calls to `component` calls are given source
* positions corresponding to `destructee()` which causes multi-line
* destructuring declarations to step back and forth between the variables being
* declared and the right-hand side, implying the repeated evaluation of the
* right-hand side.
*
* When `true`, only the stores to `x` and `y` in the generated code are are
* given source offsets, the source offsets of `x` and `y` in the original
* declaration, giving fewer, more accurate steps, that are closer to the JVM
* backend in behavior.
*/
open val debugInfoOnlyOnVariablesInDestructuringDeclarations: Boolean
get() = false
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
@@ -202,10 +203,16 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
irInnerBody.statements.add(irLoopParameter) irInnerBody.statements.add(irLoopParameter)
if (ktLoopDestructuringDeclaration != null) { if (ktLoopDestructuringDeclaration != null) {
val firstContainerValue = VariableLValue(context, irLoopParameter)
statementGenerator.declareComponentVariablesInBlock( statementGenerator.declareComponentVariablesInBlock(
ktLoopDestructuringDeclaration, ktLoopDestructuringDeclaration,
irInnerBody, irInnerBody,
VariableLValue(context, irLoopParameter) firstContainerValue,
if (context.extensions.debugInfoOnlyOnVariablesInDestructuringDeclarations) {
VariableLValue(context, irLoopParameter, startOffset = SYNTHETIC_OFFSET, endOffset = SYNTHETIC_OFFSET)
} else {
firstContainerValue
}
) )
} }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.psi2ir.generators package org.jetbrains.kotlin.psi2ir.generators
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.BackendException import org.jetbrains.kotlin.backend.common.BackendException
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.ir.util.referenceFunction import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -32,7 +34,8 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.psi2ir.deparenthesize import org.jetbrains.kotlin.psi2ir.deparenthesize
import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock import org.jetbrains.kotlin.psi2ir.intermediate.VariableLValue
import org.jetbrains.kotlin.psi2ir.intermediate.declareTemporaryVariableInBlock
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
@@ -110,8 +113,14 @@ class StatementGenerator(
) )
} }
val sourceElement =
if (context.extensions.debugInfoOnlyOnVariablesInDestructuringDeclarations) {
property.nameIdentifier ?: property
} else {
property
}
return context.symbolTable.declareVariable( return context.symbolTable.declareVariable(
property.startOffsetSkippingComments, property.endOffset, IrDeclarationOrigin.DEFINED, sourceElement.startOffsetSkippingComments, sourceElement.endOffset, IrDeclarationOrigin.DEFINED,
variableDescriptor, variableDescriptor,
variableDescriptor.type.toIrType(), variableDescriptor.type.toIrType(),
property.initializer?.let { generateExpression(it) } property.initializer?.let { generateExpression(it) }
@@ -128,14 +137,31 @@ class StatementGenerator(
.generateLocalDelegatedProperty(ktProperty, ktDelegate, variableDescriptor, scopeOwnerSymbol) .generateLocalDelegatedProperty(ktProperty, ktDelegate, variableDescriptor, scopeOwnerSymbol)
override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Nothing?): IrStatement { override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Nothing?): IrStatement {
val (blockStartOffset, blockEndOffset) = if (context.extensions.debugInfoOnlyOnVariablesInDestructuringDeclarations) {
SYNTHETIC_OFFSET to SYNTHETIC_OFFSET
} else {
multiDeclaration.startOffsetSkippingComments to multiDeclaration.endOffset
}
val irBlock = IrCompositeImpl( val irBlock = IrCompositeImpl(
multiDeclaration.startOffsetSkippingComments, multiDeclaration.endOffset, blockStartOffset, blockEndOffset,
context.irBuiltIns.unitType, IrStatementOrigin.DESTRUCTURING_DECLARATION context.irBuiltIns.unitType, IrStatementOrigin.DESTRUCTURING_DECLARATION
) )
val ktInitializer = multiDeclaration.initializer!! val ktInitializer = multiDeclaration.initializer!!
val containerValue = scope.createTemporaryVariableInBlock(context, generateExpression(ktInitializer), irBlock, "container") val irInitializer = generateExpression(ktInitializer)
declareComponentVariablesInBlock(multiDeclaration, irBlock, containerValue) val containerVariable = scope.declareTemporaryVariableInBlock(irInitializer, irBlock, nameHint = "container")
val firstContainerValue = VariableLValue(context, containerVariable)
declareComponentVariablesInBlock(
multiDeclaration,
irBlock,
firstContainerValue,
if (context.extensions.debugInfoOnlyOnVariablesInDestructuringDeclarations) {
VariableLValue(context, containerVariable, startOffset = SYNTHETIC_OFFSET, endOffset = SYNTHETIC_OFFSET)
} else {
firstContainerValue
}
)
return irBlock return irBlock
} }
@@ -143,26 +169,47 @@ class StatementGenerator(
fun declareComponentVariablesInBlock( fun declareComponentVariablesInBlock(
multiDeclaration: KtDestructuringDeclaration, multiDeclaration: KtDestructuringDeclaration,
irBlock: IrStatementContainer, irBlock: IrStatementContainer,
containerValue: IntermediateValue firstContainerValue: IntermediateValue,
restContainerValue: IntermediateValue
) { ) {
val callGenerator = CallGenerator(this) val callGenerator = CallGenerator(this)
// TODO: Every access to the container value causes a null check even though subsequent checks after the first can be assumed to pass.
var containerValue = firstContainerValue
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) { for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
val componentSubstitutedCall = pregenerateCall(componentResolvedCall)
componentSubstitutedCall.setExplicitReceiverValue(containerValue)
val componentVariable = getOrFail(BindingContext.VARIABLE, ktEntry) val componentVariable = getOrFail(BindingContext.VARIABLE, ktEntry)
// componentN for '_' SHOULD NOT be evaluated // componentN for '_' SHOULD NOT be evaluated
if (componentVariable.name.isSpecial) continue if (componentVariable.name.isSpecial) continue
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
val componentSubstitutedCall = pregenerateCall(componentResolvedCall)
componentSubstitutedCall.setExplicitReceiverValue(containerValue)
containerValue = restContainerValue
val (componentCallStartOffset, componentCallEndOffset) =
if (context.extensions.debugInfoOnlyOnVariablesInDestructuringDeclarations) {
SYNTHETIC_OFFSET to SYNTHETIC_OFFSET
} else {
ktEntry.startOffsetSkippingComments to ktEntry.endOffset
}
val irComponentCall = callGenerator.generateCall( val irComponentCall = callGenerator.generateCall(
ktEntry.startOffsetSkippingComments, ktEntry.endOffset, componentSubstitutedCall, componentCallStartOffset, componentCallEndOffset,
componentSubstitutedCall,
IrStatementOrigin.COMPONENT_N.withIndex(index + 1) IrStatementOrigin.COMPONENT_N.withIndex(index + 1)
) )
val componentVarOffsetSource: PsiElement =
if (context.extensions.debugInfoOnlyOnVariablesInDestructuringDeclarations) {
ktEntry.nameIdentifier ?: ktEntry
} else {
ktEntry
}
val irComponentVar = context.symbolTable.declareVariable( val irComponentVar = context.symbolTable.declareVariable(
ktEntry.startOffsetSkippingComments, ktEntry.endOffset, IrDeclarationOrigin.DEFINED, componentVarOffsetSource.startOffsetSkippingComments, componentVarOffsetSource.endOffset,
IrDeclarationOrigin.DEFINED,
componentVariable, componentVariable.type.toIrType(), irComponentCall componentVariable, componentVariable.type.toIrType(), irComponentCall
) )
irBlock.statements.add(irComponentVar) irBlock.statements.add(irComponentVar)
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementContainer import org.jetbrains.kotlin.ir.expressions.IrStatementContainer
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
@@ -31,9 +32,26 @@ fun Scope.createTemporaryVariableInBlock(
context: IrGeneratorContext, context: IrGeneratorContext,
irExpression: IrExpression, irExpression: IrExpression,
block: IrStatementContainer, block: IrStatementContainer,
nameHint: String? = null nameHint: String? = null,
startOffset: Int = irExpression.startOffset,
endOffset: Int = irExpression.endOffset
): IntermediateValue { ): IntermediateValue {
val temporaryVariable = createTemporaryVariable(irExpression, nameHint) return VariableLValue(
block.statements.add(temporaryVariable) context,
return VariableLValue(context, temporaryVariable) declareTemporaryVariableInBlock(irExpression, block, nameHint, startOffset, endOffset)
)
} }
fun Scope.declareTemporaryVariableInBlock(
irExpression: IrExpression,
block: IrStatementContainer,
nameHint: String? = null,
startOffset: Int = irExpression.startOffset,
endOffset: Int = irExpression.endOffset
): IrVariable {
val temporaryVariable = createTemporaryVariable(irExpression, nameHint, startOffset = startOffset, endOffset = endOffset)
block.statements.add(temporaryVariable)
return temporaryVariable
}
@@ -38,8 +38,14 @@ class VariableLValue(
LValue, LValue,
AssignmentReceiver { AssignmentReceiver {
constructor(context: IrGeneratorContext, irVariable: IrVariable, origin: IrStatementOrigin? = null) : constructor(
this(context, irVariable.startOffset, irVariable.endOffset, irVariable.symbol, irVariable.type, origin) context: IrGeneratorContext,
irVariable: IrVariable,
origin: IrStatementOrigin? = null,
startOffset: Int = irVariable.startOffset,
endOffset: Int = irVariable.endOffset
) :
this(context, startOffset, endOffset, irVariable.symbol, irVariable.type, origin)
override fun load(): IrExpression = override fun load(): IrExpression =
IrGetValueImpl(startOffset, endOffset, type, symbol, origin) IrGetValueImpl(startOffset, endOffset, type, symbol, origin)
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.ir.builders package org.jetbrains.kotlin.ir.builders
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
@@ -71,12 +70,14 @@ class Scope(val scopeOwnerSymbol: IrSymbol) {
nameHint: String? = null, nameHint: String? = null,
isMutable: Boolean = false, isMutable: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
irType: IrType? = null irType: IrType? = null,
startOffset: Int = irExpression.startOffset,
endOffset: Int = irExpression.endOffset
): IrVariable { ): IrVariable {
return createTemporaryVariableDeclaration( return createTemporaryVariableDeclaration(
irType ?: irExpression.type, irType ?: irExpression.type,
nameHint, isMutable, nameHint, isMutable,
origin, irExpression.startOffset, irExpression.endOffset origin, startOffset, endOffset
).apply { ).apply {
initializer = irExpression initializer = irExpression
} }
+1 -1
View File
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// FILE: test.kt // FILE: test.kt
fun box(): String { fun box(): String {
val val
@@ -1,5 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// FILE: test.kt // FILE: test.kt
class MyPair(val x: String, val y: String) { class MyPair(val x: String, val y: String) {
operator fun component1(): String { operator fun component1(): String {
@@ -1,6 +1,6 @@
// WITH_STDLIB // WITH_STDLIB
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// FILE: test.kt // FILE: test.kt
fun box(): String { fun box(): String {
val p = "O" to "K" val p = "O" to "K"
@@ -1,6 +1,6 @@
// WITH_STDLIB // WITH_STDLIB
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// FILE: test.kt // FILE: test.kt
fun box(): String { fun box(): String {
val p = Triple("X","O","K") val p = Triple("X","O","K")
@@ -49,11 +49,9 @@ fun box() {
// test.kt:17 box: // test.kt:17 box:
// test.kt:14 foo: a:MyPair=MyPair, block:kotlin.jvm.functions.Function1=TestKt$box$1 // test.kt:14 foo: a:MyPair=MyPair, block:kotlin.jvm.functions.Function1=TestKt$box$1
// test.kt:19 invoke: // test.kt:19 invoke:
// test.kt:20 invoke:
// test.kt:6 component1: // test.kt:6 component1:
// test.kt:20 invoke: // test.kt:20 invoke:
// test.kt:19 invoke: x:java.lang.String="O":java.lang.String // test.kt:19 invoke: x:java.lang.String="O":java.lang.String
// test.kt:22 invoke: x:java.lang.String="O":java.lang.String
// test.kt:10 component2: // test.kt:10 component2:
// test.kt:22 invoke: x:java.lang.String="O":java.lang.String // test.kt:22 invoke: x:java.lang.String="O":java.lang.String
// test.kt:25 invoke: x:java.lang.String="O":java.lang.String, y:java.lang.String="K":java.lang.String // test.kt:25 invoke: x:java.lang.String="O":java.lang.String, y:java.lang.String="K":java.lang.String
+21
View File
@@ -0,0 +1,21 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: test.kt
fun box(): String {
val
o
=
"O"
val k = "K"
return o + k
}
// EXPECTATIONS
// test.kt:8 box
// test.kt:6 box
// test.kt:11 box
// test.kt:13 box
+1 -1
View File
@@ -18,5 +18,5 @@
@3:27..53 PROPERTY_REFERENCE 'public final lazyNullString: kotlin.String [delegated,val]' field=null getter='public final fun <get-lazyNullString> (): kotlin.String declared in <root>' setter=null type=kotlin.reflect.KProperty0<kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE @3:27..53 PROPERTY_REFERENCE 'public final lazyNullString: kotlin.String [delegated,val]' field=null getter='public final fun <get-lazyNullString> (): kotlin.String declared in <root>' setter=null type=kotlin.reflect.KProperty0<kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE
@5:0..7:1 FUN name:testLazyNullString visibility:public modality:FINAL <> () returnType:kotlin.Unit @5:0..7:1 FUN name:testLazyNullString visibility:public modality:FINAL <> () returnType:kotlin.Unit
@5:25..7:1 BLOCK_BODY @5:25..7:1 BLOCK_BODY
@6:4..34 VAR name:s type:kotlin.String [val] @6:8..9 VAR name:s type:kotlin.String [val]
@6:20..34 CALL 'public final fun <get-lazyNullString> (): kotlin.String declared in <root>' type=kotlin.String origin=GET_PROPERTY @6:20..34 CALL 'public final fun <get-lazyNullString> (): kotlin.String declared in <root>' type=kotlin.String origin=GET_PROPERTY
@@ -1,9 +1,9 @@
@0:0..6:0 FILE fqName:<root> fileName:/postfixIncrementDecrement.kt @0:0..6:0 FILE fqName:<root> fileName:/postfixIncrementDecrement.kt
@0:0..5:1 FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit @0:0..5:1 FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
@0:11..5:1 BLOCK_BODY @0:11..5:1 BLOCK_BODY
@1:4..13 VAR name:x type:kotlin.Int [var] @1:8..9 VAR name:x type:kotlin.Int [var]
@1:12..13 CONST Int type=kotlin.Int value=0 @1:12..13 CONST Int type=kotlin.Int value=0
@2:4..13 VAR name:y type:kotlin.Int [var] @2:8..9 VAR name:y type:kotlin.Int [var]
@2:12..13 CONST Int type=kotlin.Int value=0 @2:12..13 CONST Int type=kotlin.Int value=0
@3:4..5 SET_VAR 'var y: kotlin.Int [var] declared in <root>.test' type=kotlin.Unit origin=EQ @3:4..5 SET_VAR 'var y: kotlin.Int [var] declared in <root>.test' type=kotlin.Unit origin=EQ
@3:8..11 BLOCK type=kotlin.Int origin=POSTFIX_INCR @3:8..11 BLOCK type=kotlin.Int origin=POSTFIX_INCR
@@ -313,6 +313,12 @@ public class IrSteppingTestGenerated extends AbstractIrSteppingTest {
runTest("compiler/testData/debug/stepping/localFunctionWIthOnelineExpressionBody.kt"); runTest("compiler/testData/debug/stepping/localFunctionWIthOnelineExpressionBody.kt");
} }
@Test
@TestMetadata("localProperty.kt")
public void testLocalProperty() throws Exception {
runTest("compiler/testData/debug/stepping/localProperty.kt");
}
@Test @Test
@TestMetadata("multilineExpression.kt") @TestMetadata("multilineExpression.kt")
public void testMultilineExpression() throws Exception { public void testMultilineExpression() throws Exception {
@@ -313,6 +313,12 @@ public class SteppingTestGenerated extends AbstractSteppingTest {
runTest("compiler/testData/debug/stepping/localFunctionWIthOnelineExpressionBody.kt"); runTest("compiler/testData/debug/stepping/localFunctionWIthOnelineExpressionBody.kt");
} }
@Test
@TestMetadata("localProperty.kt")
public void testLocalProperty() throws Exception {
runTest("compiler/testData/debug/stepping/localProperty.kt");
}
@Test @Test
@TestMetadata("multilineExpression.kt") @TestMetadata("multilineExpression.kt")
public void testMultilineExpression() throws Exception { public void testMultilineExpression() throws Exception {