Debugger: Do not assume we are inside the class body when in '}' (KT-15259)

This commit is contained in:
Yan Zhulanow
2019-06-28 18:41:51 +09:00
parent a8efb349ed
commit 0f4085066f
5 changed files with 76 additions and 14 deletions
@@ -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
}
+2 -2
View File
@@ -1,5 +1,5 @@
val global = 2
fun makeFace() = object : ObjectFace {
val inObject = 1
<caret>}
<caret>val inObject = 1
}
@@ -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
@@ -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
@@ -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");