From d886cd7d066f4eacdcde7240b88ab4d58f87a863 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 3 Mar 2017 17:23:24 +0300 Subject: [PATCH] Fix breakpoints when inline call is in qualified expression (KT-16062) Scope is stored for DOT_QUALIFIED_EXPRESSION not directly for CALL_EXPRESSION. #KT-16062 Fixed --- .../idea/debugger/DebuggerClassNameProvider.kt | 13 +++++++++++-- .../tinyApp/outs/stopInExtensionInlineCall.out | 8 ++++++++ .../stepOver/stopInExtensionInlineCall.kt | 15 +++++++++++++++ .../debugger/KotlinSteppingTestGenerated.java | 6 ++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 idea/testData/debugger/tinyApp/outs/stopInExtensionInlineCall.out create mode 100644 idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInExtensionInlineCall.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt index 9d101e6e621..ea369de95f9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt @@ -25,6 +25,7 @@ import com.intellij.openapi.project.DumbService import com.intellij.openapi.roots.libraries.LibraryUtil import com.intellij.openapi.ui.MessageType import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.util.PsiTreeUtil @@ -49,12 +50,13 @@ import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.parents +import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.inline.InlineUtil +import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull @@ -219,7 +221,7 @@ class DebuggerClassNameProvider(val myDebugProcess: DebugProcess, val scopes: Li }?.first } ?: return emptyList() - val lexicalScope = context[BindingContext.LEXICAL_SCOPE, inlineCall] ?: return emptyList() + val lexicalScope = runReadAction { inlineCall.getExpressionResolutionScope(context) } ?: return emptyList() val baseClassName = classNamesForPosition(inlineCall, false).firstOrNull() ?: return emptyList() val resolvedCall = runReadAction { inlineCall.getResolvedCall(context) } ?: return emptyList() @@ -424,4 +426,11 @@ private fun String.substringIndex(): String { return substringBeforeLast("$") + "$" } return this +} + +private fun KtCallExpression.getExpressionResolutionScope(bindingContext: BindingContext): LexicalScope? { + return parentsWithSelf + .takeWhile { it !is KtClassBody && it !is KtBlockExpression && it !is PsiFile } + .map { if (it is KtElement) bindingContext[BindingContext.LEXICAL_SCOPE, it] else null } + .firstOrNull { it != null } } \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/outs/stopInExtensionInlineCall.out b/idea/testData/debugger/tinyApp/outs/stopInExtensionInlineCall.out new file mode 100644 index 00000000000..6e0d96384e8 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInExtensionInlineCall.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInExtensionInlineCall.kt:8 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stopInExtensionInlineCall.StopInExtensionInlineCallKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInExtensionInlineCall.kt:8 +stopInExtensionInlineCall.kt:9 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInExtensionInlineCall.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInExtensionInlineCall.kt new file mode 100644 index 00000000000..3c37c036b25 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInExtensionInlineCall.kt @@ -0,0 +1,15 @@ +package stopInExtensionInlineCall + +fun main(args: Array) { + val a = 1 + 12.apply { + { + //Breakpoint! + foo(a) + }() + } +} + +inline fun T.inlineApply(block: T.() -> kotlin.Unit) { this.block() } + +fun foo(a: Any) {} diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java index defbc278132..44afe8f767a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java @@ -722,6 +722,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { doStepOverTest(fileName); } + @TestMetadata("stopInExtensionInlineCall.kt") + public void testStopInExtensionInlineCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInExtensionInlineCall.kt"); + doStepOverTest(fileName); + } + @TestMetadata("stopInInlineCallLocalFunLambda.kt") public void testStopInInlineCallLocalFunLambda() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlineCallLocalFunLambda.kt");