Debugger: Fix evaluation on value parameter name position (KT-30976)

This commit is contained in:
Yan Zhulanow
2019-04-23 23:53:49 +03:00
parent 577b3e096f
commit a385b4d9d0
5 changed files with 54 additions and 12 deletions
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypes2
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypes3
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoAfter
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
@@ -94,7 +94,7 @@ class CodeFragmentAnalyzer(
return info.copy(scope = enrichScopeWithImports(info.scope, codeFragment))
}
private fun getContextInfo(context: PsiElement?, resolutionFactory: (KtElement) -> BindingContext): ContextInfo {
private tailrec fun getContextInfo(context: PsiElement?, resolutionFactory: (KtElement) -> BindingContext): ContextInfo {
var bindingContext: BindingContext = BindingContext.EMPTY
var dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY
var scope: LexicalScope? = null
@@ -127,7 +127,10 @@ class CodeFragmentAnalyzer(
val functionDescriptor = bindingContextForFunction[BindingContext.FUNCTION, context]
if (functionDescriptor != null) {
bindingContext = bindingContextForFunction
@Suppress("NON_TAIL_RECURSIVE_CALL")
val outerScope = getContextInfo(context.getParentOfType<KtDeclaration>(true), resolutionFactory).scope
val localRedeclarationChecker = LocalRedeclarationChecker.DO_NOTHING
scope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, localRedeclarationChecker)
}
@@ -144,7 +147,7 @@ class CodeFragmentAnalyzer(
}
if (scope == null) {
val parentDeclaration = context?.getParentOfTypes2<KtDeclaration, KtFile>()
val parentDeclaration = context?.getParentOfTypes3<KtDeclaration, KtFile, KtExpression>()
if (parentDeclaration != null) {
return getContextInfo(parentDeclaration, resolutionFactory)
}
@@ -8,10 +8,10 @@ package org.jetbrains.kotlin.idea.debugger
import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider.Companion.isAcceptedAsCodeFragmentContext
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.parents
fun getContextElement(elementAt: PsiElement?): PsiElement? {
if (elementAt == null) return null
@@ -36,15 +36,21 @@ fun getContextElement(elementAt: PsiElement?): PsiElement? {
elementAt.textOffset
}
fun KtElement.takeIfAcceptedAsCodeFragmentContext() = takeIf { KotlinEditorTextProvider.isAcceptedAsCodeFragmentContext(it) }
val targetExpression = PsiTreeUtil.findElementOfClassAtOffset(containingFile, lineStartOffset, KtExpression::class.java, false)
PsiTreeUtil.findElementOfClassAtOffset(containingFile, lineStartOffset, KtExpression::class.java, false)
?.takeIfAcceptedAsCodeFragmentContext()
?.let { return CodeInsightUtils.getTopmostElementAtOffset(it, lineStartOffset, KtExpression::class.java) }
if (targetExpression != null) {
if (isAcceptedAsCodeFragmentContext(targetExpression)) {
return targetExpression
}
KotlinEditorTextProvider.findExpressionInner(elementAt, true)
?.takeIfAcceptedAsCodeFragmentContext()
?.let { return it }
KotlinEditorTextProvider.findExpressionInner(elementAt, true)
?.takeIf { isAcceptedAsCodeFragmentContext(it) }
?.let { return it }
targetExpression.parents
.firstOrNull { isAcceptedAsCodeFragmentContext(it) }
?.let { return it }
}
return containingFile
}
@@ -0,0 +1,20 @@
package valueParameterName
fun main() {
"foo".foo()
}
fun String.foo() {
val a = Foo(
a = this
)
val b = Foo(
//Breakpoint!
a = this
)
}
private class Foo(val a: String)
// EXPRESSION: this
// RESULT: "foo": Ljava/lang/String;
@@ -0,0 +1,8 @@
LineBreakpoint created at valueParameterName.kt:13
Run Java
Connected to the target VM
valueParameterName.kt:13
Compile bytecode for this
Disconnected from the target VM
Process finished with exit code 0
@@ -406,6 +406,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/unsafeCall.kt");
}
@TestMetadata("valueParameterName.kt")
public void testValueParameterName() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/valueParameterName.kt");
}
@TestMetadata("vars.kt")
public void testVars() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/vars.kt");