diff --git a/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/CodeFragmentContextUtils.kt b/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/CodeFragmentContextUtils.kt index e9fa08a99dd..973b0c61a74 100644 --- a/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/CodeFragmentContextUtils.kt +++ b/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/CodeFragmentContextUtils.kt @@ -6,11 +6,12 @@ package org.jetbrains.kotlin.idea.debugger import com.intellij.psi.* +import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.classes.KtLightClass 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.lexer.KtTokens +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.parents fun getContextElement(elementAt: PsiElement?): PsiElement? { @@ -25,17 +26,41 @@ fun getContextElement(elementAt: PsiElement?): PsiElement? { } val containingFile = elementAt.containingFile - if (containingFile is PsiJavaFile) return elementAt - if (containingFile !is KtFile) return null - - // elementAt can be PsiWhiteSpace when codeFragment is created from line start offset (in case of first opening EE window) - val lineStartOffset = if (elementAt is PsiWhiteSpace || elementAt is PsiComment) { - PsiTreeUtil.skipSiblingsForward(elementAt, PsiWhiteSpace::class.java, PsiComment::class.java)?.textOffset - ?: elementAt.textOffset - } else { - elementAt.textOffset + if (containingFile is PsiJavaFile) { + return elementAt } + if (containingFile !is KtFile) { + return null + } + + val accurateElement = getAccurateContextElement(elementAt, containingFile) + if (accurateElement != null) { + return accurateElement + } + + return containingFile +} + +private fun getAccurateContextElement(elementAt: PsiElement, containingFile: KtFile): PsiElement? { + // elementAt can be PsiWhiteSpace when codeFragment is created from line start offset (in case of first opening EE window) + val elementAtSkippingWhitespaces = getElementSkippingWhitespaces(elementAt) + + if (elementAtSkippingWhitespaces is LeafPsiElement && elementAtSkippingWhitespaces.elementType == KtTokens.RBRACE) { + val classBody = elementAtSkippingWhitespaces.parent as? KtClassBody + val classOrObject = classBody?.parent as? KtClassOrObject + var declarationParent = classOrObject?.parent + if (declarationParent is KtObjectLiteralExpression) { + declarationParent = declarationParent.parent + } + + if (declarationParent != null) { + return getAccurateContextElement(declarationParent, containingFile) + } + } + + val lineStartOffset = elementAtSkippingWhitespaces.textOffset + val targetExpression = PsiTreeUtil.findElementOfClassAtOffset(containingFile, lineStartOffset, KtExpression::class.java, false) if (targetExpression != null) { @@ -52,5 +77,16 @@ fun getContextElement(elementAt: PsiElement?): PsiElement? { ?.let { return it } } - return containingFile + return null +} + +private fun getElementSkippingWhitespaces(elementAt: PsiElement): PsiElement { + if (elementAt is PsiWhiteSpace || elementAt is PsiComment) { + val newElement = PsiTreeUtil.skipSiblingsForward(elementAt, PsiWhiteSpace::class.java, PsiComment::class.java) + if (newElement != null) { + return newElement + } + } + + return elementAt } \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/anonymousObject.kt b/idea/testData/checker/codeFragments/anonymousObject.kt index 359571355df..cb5d9422162 100644 --- a/idea/testData/checker/codeFragments/anonymousObject.kt +++ b/idea/testData/checker/codeFragments/anonymousObject.kt @@ -1,5 +1,5 @@ val global = 2 fun makeFace() = object : ObjectFace { - val inObject = 1 -} \ No newline at end of file + val inObject = 1 +} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt15259.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt15259.kt new file mode 100644 index 00000000000..5319a43b206 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt15259.kt @@ -0,0 +1,14 @@ +package kt15259 + +interface ObjectFace + +private fun makeFace() = object : ObjectFace { +//Breakpoint! +} + +fun main() { + makeFace() +} + +// EXPRESSION: this +// RESULT: 'this' is not defined in this context \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt15259.out b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt15259.out new file mode 100644 index 00000000000..a5126d6f8da --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt15259.out @@ -0,0 +1,7 @@ +LineBreakpoint created at kt15259.kt:7 +Run Java +Connected to the target VM +kt15259.kt:7 +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index 24672eb8db9..d7848696b6a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -256,6 +256,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt12206BasePropertyWithoutBackingField.kt"); } + @TestMetadata("kt15259.kt") + public void testKt15259() throws Exception { + runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt15259.kt"); + } + @TestMetadata("kt17514.kt") public void testKt17514() throws Exception { runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt17514.kt");