Debugger: get topmost element at offset as contextElement
This commit is contained in:
+7
-2
@@ -70,8 +70,13 @@ public class CodeFragmentAnalyzer(
|
|||||||
is JetDeclarationWithBody -> this.getBodyExpression()
|
is JetDeclarationWithBody -> this.getBodyExpression()
|
||||||
is JetBlockExpression -> this.getStatements().lastOrNull()
|
is JetBlockExpression -> this.getStatements().lastOrNull()
|
||||||
else -> {
|
else -> {
|
||||||
this.siblings(forward = false, withItself = false).firstIsInstanceOrNull<JetExpression>()
|
val previousSibling = this.siblings(forward = false, withItself = false).firstIsInstanceOrNull<JetExpression>()
|
||||||
?: this.parents.firstIsInstanceOrNull<JetExpression>()
|
if (previousSibling != null) return previousSibling
|
||||||
|
for (parent in this.parents) {
|
||||||
|
if (parent is JetWhenEntry || parent is JetIfExpression || parent is JetBlockExpression) return this
|
||||||
|
if (parent is JetExpression) return parent
|
||||||
|
}
|
||||||
|
null
|
||||||
}
|
}
|
||||||
} ?: this
|
} ?: this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,4 +284,25 @@ public class CodeInsightUtils {
|
|||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static <T> T getTopmostElementAtOffset(@NotNull PsiElement element, int offset, @NotNull Class<T> klass) {
|
||||||
|
T lastElementOfType = null;
|
||||||
|
if (klass.isInstance(element)) {
|
||||||
|
lastElementOfType = (T) element;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
PsiElement parent = element.getParent();
|
||||||
|
if (parent == null || (parent.getTextOffset() < offset) || parent instanceof JetBlockExpression) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (klass.isInstance(parent)) {
|
||||||
|
lastElementOfType = (T) parent;
|
||||||
|
}
|
||||||
|
element = parent;
|
||||||
|
}
|
||||||
|
while(true);
|
||||||
|
|
||||||
|
return lastElementOfType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,14 +37,17 @@ import com.sun.jdi.PrimitiveValue
|
|||||||
import com.sun.jdi.Value
|
import com.sun.jdi.Value
|
||||||
import org.jetbrains.kotlin.asJava.KotlinLightClass
|
import org.jetbrains.kotlin.asJava.KotlinLightClass
|
||||||
import org.jetbrains.kotlin.idea.JetFileType
|
import org.jetbrains.kotlin.idea.JetFileType
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||||
import org.jetbrains.kotlin.idea.core.refactoring.j2kText
|
import org.jetbrains.kotlin.idea.core.refactoring.j2kText
|
||||||
import org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider
|
import org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
import kotlin.reflect.jvm.java
|
||||||
|
|
||||||
class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
||||||
private val LOG = Logger.getInstance(this.javaClass)
|
private val LOG = Logger.getInstance(this.javaClass)
|
||||||
@@ -143,14 +146,21 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
|||||||
val containingFile = elementAt.containingFile
|
val containingFile = elementAt.containingFile
|
||||||
if (containingFile !is JetFile) return null
|
if (containingFile !is JetFile) return null
|
||||||
|
|
||||||
val expressionAtOffset = PsiTreeUtil.findElementOfClassAtOffset(containingFile, elementAt.textOffset, javaClass<JetExpression>(), false)
|
var result = PsiTreeUtil.findElementOfClassAtOffset(containingFile, elementAt.textOffset, javaClass<JetExpression>(), false)
|
||||||
if (expressionAtOffset != null && KotlinEditorTextProvider.isAcceptedAsCodeFragmentContext(elementAt)) {
|
if (result.check()) {
|
||||||
return expressionAtOffset
|
return CodeInsightUtils.getTopmostElementAtOffset(result!!, result.textOffset, JetExpression::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
return KotlinEditorTextProvider.findExpressionInner(elementAt, true) ?: containingFile
|
result = KotlinEditorTextProvider.findExpressionInner(elementAt, true)
|
||||||
|
if (result.check()) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return containingFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun JetElement?.check(): Boolean = this != null && this.check { KotlinEditorTextProvider.isAcceptedAsCodeFragmentContext(it) } != null
|
||||||
|
|
||||||
//internal for tests
|
//internal for tests
|
||||||
fun createCodeFragmentForLabeledObjects(project: Project, markupMap: Map<*, ValueMarkup>): Pair<String, Map<String, Value>> {
|
fun createCodeFragmentForLabeledObjects(project: Project, markupMap: Map<*, ValueMarkup>): Pair<String, Map<String, Value>> {
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
fun foo() {
|
fun foo() {
|
||||||
val a: Int? = 1
|
val a: Int? = 1
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
<caret> a
|
<caret>a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user