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
This commit is contained in:
Nikolay Krasko
2017-03-03 17:23:24 +03:00
parent 2719016539
commit d886cd7d06
4 changed files with 40 additions and 2 deletions
@@ -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 }
}
@@ -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
@@ -0,0 +1,15 @@
package stopInExtensionInlineCall
fun main(args: Array<String>) {
val a = 1
12.apply {
{
//Breakpoint!
foo(a)
}()
}
}
inline fun <T> T.inlineApply(block: T.() -> kotlin.Unit) { this.block() }
fun foo(a: Any) {}
@@ -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");