Debugger: Fix evaluation on value parameter name position (KT-30976)
This commit is contained in:
+6
-3
@@ -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)
|
||||
}
|
||||
|
||||
+15
-9
@@ -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
|
||||
}
|
||||
+20
@@ -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;
|
||||
+8
@@ -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
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user