Debugger: get topmost element at offset as contextElement

This commit is contained in:
Natalia Ukhorskaya
2015-08-25 13:24:24 +03:00
parent c6d29cc1d5
commit 06b13f1292
4 changed files with 43 additions and 7 deletions
@@ -70,8 +70,13 @@ public class CodeFragmentAnalyzer(
is JetDeclarationWithBody -> this.getBodyExpression()
is JetBlockExpression -> this.getStatements().lastOrNull()
else -> {
this.siblings(forward = false, withItself = false).firstIsInstanceOrNull<JetExpression>()
?: this.parents.firstIsInstanceOrNull<JetExpression>()
val previousSibling = this.siblings(forward = false, withItself = false).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
}
@@ -284,4 +284,25 @@ public class CodeInsightUtils {
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 org.jetbrains.kotlin.asJava.KotlinLightClass
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.debugger.KotlinEditorTextProvider
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.utils.addToStdlib.check
import java.util.HashMap
import java.util.concurrent.atomic.AtomicReference
import kotlin.reflect.jvm.java
class KotlinCodeFragmentFactory: CodeFragmentFactory() {
private val LOG = Logger.getInstance(this.javaClass)
@@ -143,14 +146,21 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
val containingFile = elementAt.containingFile
if (containingFile !is JetFile) return null
val expressionAtOffset = PsiTreeUtil.findElementOfClassAtOffset(containingFile, elementAt.textOffset, javaClass<JetExpression>(), false)
if (expressionAtOffset != null && KotlinEditorTextProvider.isAcceptedAsCodeFragmentContext(elementAt)) {
return expressionAtOffset
var result = PsiTreeUtil.findElementOfClassAtOffset(containingFile, elementAt.textOffset, javaClass<JetExpression>(), false)
if (result.check()) {
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
fun createCodeFragmentForLabeledObjects(project: Project, markupMap: Map<*, ValueMarkup>): Pair<String, Map<String, Value>> {
val sb = StringBuilder()
+1 -1
View File
@@ -1,6 +1,6 @@
fun foo() {
val a: Int? = 1
if (a != null) {
<caret> a
<caret>a
}
}