mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[debugger, kotlin] IDEA-346083 Fix smart-step-into methods with context receivers
GitOrigin-RevId: c7c1ee9ad93b21be2508669aeb4ca33791d40b44
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cf003cbd8d
commit
55c932f04f
+13
-1
@@ -1,9 +1,11 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.codeinsight.utils
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.kotlin.analysis.api.KaSession
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.KaFunctionCall
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.successfulFunctionCallOrNull
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.symbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
@@ -61,13 +63,23 @@ context(KaSession)
|
||||
fun getCallExpressionSymbol(argument: KtExpression): Pair<KaFunctionSymbol, KaValueParameterSymbol>? {
|
||||
if (argument !is KtFunction && argument !is KtCallableReferenceExpression) return null
|
||||
val parentCallExpression = KtPsiUtil.getParentCallIfPresent(argument) as? KtCallExpression ?: return null
|
||||
val parentCall = parentCallExpression.resolveToCall()?.successfulFunctionCallOrNull() ?: return null
|
||||
val parentCall = resolveFunctionCall(parentCallExpression) ?: return null
|
||||
val symbol = parentCall.partiallyAppliedSymbol.symbol
|
||||
val valueArgument = parentCallExpression.getContainingValueArgument(argument) ?: return null
|
||||
val argumentSymbol = parentCall.argumentMapping[valueArgument.getArgumentExpression()]?.symbol ?: return null
|
||||
return symbol to argumentSymbol
|
||||
}
|
||||
|
||||
context(KaSession)
|
||||
@ApiStatus.Internal
|
||||
fun resolveFunctionCall(expression: KtExpression): KaFunctionCall<*>? {
|
||||
val successfulCall = expression.resolveToCall()?.successfulFunctionCallOrNull()
|
||||
if (successfulCall != null) return successfulCall
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) return null
|
||||
// Functions with context receivers are not resolved in K2 tests for some reason
|
||||
return expression.resolveToCallCandidates().firstOrNull()?.candidate as? KaFunctionCall<*>
|
||||
}
|
||||
|
||||
context(KaSession)
|
||||
private fun isArrayGeneratorConstructorCall(symbol: KaFunctionSymbol): Boolean {
|
||||
fun checkParameters(symbol: KaFunctionSymbol): Boolean {
|
||||
|
||||
+4
-1
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KaExperimentalApi
|
||||
import org.jetbrains.kotlin.analysis.api.KaSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KaConstructorSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KaFunctionSymbol
|
||||
@@ -53,9 +54,11 @@ internal fun CallableMemberInfo(
|
||||
internal fun KaFunctionSymbol.isSuspend(): Boolean = this is KaNamedFunctionSymbol && this.isSuspend
|
||||
|
||||
context(KaSession)
|
||||
@OptIn(KaExperimentalApi::class)
|
||||
internal fun KaFunctionSymbol.containsInlineClassInParameters(): Boolean =
|
||||
valueParameters.any { it.returnType.expandedSymbol?.isInlineClass() == true }
|
||||
|| receiverParameter?.type?.expandedSymbol?.isInlineClass() == true
|
||||
|| receiverParameter?.returnType?.expandedSymbol?.isInlineClass() == true
|
||||
|| contextReceivers.any { it.type.expandedSymbol?.isInlineClass() == true }
|
||||
|
||||
context(KaSession)
|
||||
private fun KaFunctionSymbol.methodName() = when (this) {
|
||||
|
||||
+3
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.kotlin.idea.debugger.stepping.smartStepInto
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KaExperimentalApi
|
||||
import org.jetbrains.kotlin.analysis.api.KaSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KaFunctionSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KaValueParameterSymbol
|
||||
@@ -45,6 +46,7 @@ internal fun KotlinLambdaInfo(
|
||||
)
|
||||
|
||||
context(KaSession)
|
||||
@OptIn(KaExperimentalApi::class)
|
||||
private fun countParameterIndex(methodSymbol: KaFunctionSymbol, argumentSymbol: KaValueParameterSymbol): Int {
|
||||
var resultIndex = methodSymbol.valueParameters.indexOf(argumentSymbol)
|
||||
|
||||
@@ -52,6 +54,7 @@ private fun countParameterIndex(methodSymbol: KaFunctionSymbol, argumentSymbol:
|
||||
resultIndex++
|
||||
if (methodSymbol.isInsideInlineClass())
|
||||
resultIndex++
|
||||
resultIndex += methodSymbol.contextReceivers.size
|
||||
|
||||
return resultIndex
|
||||
}
|
||||
|
||||
+3
-1
@@ -238,8 +238,10 @@ private fun String.isSubClassOf(baseInternalName: String?): Boolean {
|
||||
}
|
||||
|
||||
context(KaSession)
|
||||
@OptIn(KaExperimentalApi::class)
|
||||
private fun KaCallableSymbol.getJvmSignature(): String? {
|
||||
val element = psi ?: return null
|
||||
val contextReceivers = contextReceivers.mapNotNull { it.type.jvmName(element) }.joinToString("")
|
||||
val receiver = receiverType?.jvmName(element) ?: ""
|
||||
val isSuspend = this is KaFunctionSymbol && isSuspend()
|
||||
val parameterTypes = if (this is KaFunctionSymbol) {
|
||||
@@ -253,7 +255,7 @@ private fun KaCallableSymbol.getJvmSignature(): String? {
|
||||
else -> returnType.jvmName(element) ?: return null
|
||||
}
|
||||
val continuationParameter = if (isSuspend) "Lkotlin/coroutines/Continuation;" else ""
|
||||
return "($receiver$parameterTypes$continuationParameter)$returnType"
|
||||
return "($contextReceivers$receiver$parameterTypes$continuationParameter)$returnType"
|
||||
}
|
||||
|
||||
context(KaSession)
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.analysis.api.resolution.symbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.types.KaFunctionType
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.getCallExpressionSymbol
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.resolveFunctionCall
|
||||
import org.jetbrains.kotlin.idea.debugger.core.breakpoints.isInlineOnly
|
||||
import org.jetbrains.kotlin.idea.debugger.core.isInlineClass
|
||||
import org.jetbrains.kotlin.idea.debugger.core.stepping.getLineRange
|
||||
@@ -330,7 +331,7 @@ class SmartStepTargetVisitor(
|
||||
|
||||
private fun recordFunctionCall(expression: KtExpression, highlightExpression: KtExpression) {
|
||||
analyze(expression) {
|
||||
val resolvedCall = expression.resolveToCall()?.successfulFunctionCallOrNull() ?: return
|
||||
val resolvedCall = resolveFunctionCall(expression) ?: return
|
||||
val symbol = resolvedCall.partiallyAppliedSymbol.symbol
|
||||
if (symbol.annotations.any { it.classId?.internalName == "kotlin/internal/IntrinsicConstEvaluation" }) {
|
||||
return
|
||||
|
||||
+5
@@ -1698,6 +1698,11 @@ public abstract class K2IdeK1CodeKotlinSteppingTestGenerated extends AbstractK2I
|
||||
runTest("../testData/stepping/custom/smartStepIntoDeferredSamLambdas.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithContext.kt")
|
||||
public void testSmartStepIntoFunWithContext() throws Exception {
|
||||
runTest("../testData/stepping/custom/smartStepIntoFunWithContext.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithDefaultArgs.kt")
|
||||
public void testSmartStepIntoFunWithDefaultArgs() throws Exception {
|
||||
runTest("../testData/stepping/custom/smartStepIntoFunWithDefaultArgs.kt");
|
||||
|
||||
+5
@@ -1698,6 +1698,11 @@ public abstract class K2IdeK2CodeKotlinSteppingTestGenerated extends AbstractK2I
|
||||
runTest("../testData/stepping/custom/smartStepIntoDeferredSamLambdas.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithContext.kt")
|
||||
public void testSmartStepIntoFunWithContext() throws Exception {
|
||||
runTest("../testData/stepping/custom/smartStepIntoFunWithContext.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithDefaultArgs.kt")
|
||||
public void testSmartStepIntoFunWithDefaultArgs() throws Exception {
|
||||
runTest("../testData/stepping/custom/smartStepIntoFunWithDefaultArgs.kt");
|
||||
|
||||
+5
@@ -1698,6 +1698,11 @@ public abstract class K2IndyLambdaKotlinSteppingTestGenerated extends AbstractK2
|
||||
runTest("../testData/stepping/custom/smartStepIntoDeferredSamLambdas.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithContext.kt")
|
||||
public void testSmartStepIntoFunWithContext() throws Exception {
|
||||
runTest("../testData/stepping/custom/smartStepIntoFunWithContext.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithDefaultArgs.kt")
|
||||
public void testSmartStepIntoFunWithDefaultArgs() throws Exception {
|
||||
runTest("../testData/stepping/custom/smartStepIntoFunWithDefaultArgs.kt");
|
||||
|
||||
+1
@@ -200,6 +200,7 @@ open class DebuggerTestCompilerFacility(
|
||||
private fun getCompilerOptionsCommonForLibAndSource(): List<String> {
|
||||
val options = mutableListOf(
|
||||
"-Xlambdas=${compileConfig.lambdasGenerationScheme.description}",
|
||||
"-Xcontext-receivers",
|
||||
)
|
||||
if (compileConfig.languageVersion != null) {
|
||||
options.add("-language-version=${compileConfig.languageVersion}")
|
||||
|
||||
+5
@@ -1698,6 +1698,11 @@ public abstract class IndyLambdaIrKotlinSteppingTestGenerated extends AbstractIn
|
||||
runTest("testData/stepping/custom/smartStepIntoDeferredSamLambdas.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithContext.kt")
|
||||
public void testSmartStepIntoFunWithContext() throws Exception {
|
||||
runTest("testData/stepping/custom/smartStepIntoFunWithContext.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithDefaultArgs.kt")
|
||||
public void testSmartStepIntoFunWithDefaultArgs() throws Exception {
|
||||
runTest("testData/stepping/custom/smartStepIntoFunWithDefaultArgs.kt");
|
||||
|
||||
+5
@@ -1698,6 +1698,11 @@ public abstract class IrKotlinSteppingTestGenerated extends AbstractIrKotlinStep
|
||||
runTest("testData/stepping/custom/smartStepIntoDeferredSamLambdas.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithContext.kt")
|
||||
public void testSmartStepIntoFunWithContext() throws Exception {
|
||||
runTest("testData/stepping/custom/smartStepIntoFunWithContext.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithDefaultArgs.kt")
|
||||
public void testSmartStepIntoFunWithDefaultArgs() throws Exception {
|
||||
runTest("testData/stepping/custom/smartStepIntoFunWithDefaultArgs.kt");
|
||||
|
||||
+5
@@ -1698,6 +1698,11 @@ public abstract class K1IdeK2CodeKotlinSteppingTestGenerated extends AbstractK1I
|
||||
runTest("testData/stepping/custom/smartStepIntoDeferredSamLambdas.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithContext.kt")
|
||||
public void testSmartStepIntoFunWithContext() throws Exception {
|
||||
runTest("testData/stepping/custom/smartStepIntoFunWithContext.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartStepIntoFunWithDefaultArgs.kt")
|
||||
public void testSmartStepIntoFunWithDefaultArgs() throws Exception {
|
||||
runTest("testData/stepping/custom/smartStepIntoFunWithDefaultArgs.kt");
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package smartStepIntoFunWithContext
|
||||
|
||||
context(Double)
|
||||
fun funWithContext(lambda: (Int) -> Unit) = lambda(42)
|
||||
|
||||
fun testContext() {
|
||||
with(42.0) {
|
||||
// SMART_STEP_INTO_BY_INDEX: 1
|
||||
// RESUME: 1
|
||||
//Breakpoint!, lambdaOrdinal = -1
|
||||
funWithContext { println() }
|
||||
|
||||
// SMART_STEP_INTO_BY_INDEX: 2
|
||||
// RESUME: 1
|
||||
//Breakpoint!, lambdaOrdinal = -1
|
||||
funWithContext { println() }
|
||||
}
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class X(val x: Int)
|
||||
|
||||
context(X)
|
||||
private fun funWithContext2(x: Int) = Unit
|
||||
private fun getInt(): Int = 5
|
||||
|
||||
fun testContextInline() {
|
||||
with(X(1)) {
|
||||
// SMART_STEP_INTO_BY_INDEX: 1
|
||||
// RESUME: 1
|
||||
//Breakpoint!
|
||||
funWithContext2(getInt())
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
testContext()
|
||||
testContextInline()
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
LineBreakpoint created at smartStepIntoFunWithContext.kt:11 lambdaOrdinal = -1
|
||||
LineBreakpoint created at smartStepIntoFunWithContext.kt:16 lambdaOrdinal = -1
|
||||
LineBreakpoint created at smartStepIntoFunWithContext.kt:32
|
||||
Run Java
|
||||
Connected to the target VM
|
||||
smartStepIntoFunWithContext.kt:11
|
||||
smartStepIntoFunWithContext.kt:4
|
||||
smartStepIntoFunWithContext.kt:16
|
||||
smartStepIntoFunWithContext.kt:16
|
||||
smartStepIntoFunWithContext.kt:32
|
||||
smartStepIntoFunWithContext.kt:24
|
||||
Disconnected from the target VM
|
||||
|
||||
Process finished with exit code 0
|
||||
Reference in New Issue
Block a user