Debugger: do not resolve symbols on breakpoint line in Evaluate Expression

This commit is contained in:
Natalia Ukhorskaya
2015-07-16 13:08:31 +03:00
parent 9a53142b26
commit 75edfa6527
11 changed files with 93 additions and 9 deletions
@@ -16,29 +16,48 @@
package org.jetbrains.kotlin.resolve.util package org.jetbrains.kotlin.resolve.util
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
import org.jetbrains.kotlin.resolve.scopes.ChainedScope import org.jetbrains.kotlin.resolve.scopes.ChainedScope
import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
//TODO: this code should be moved into debugger which should set correct context for its code fragment //TODO: this code should be moved into debugger which should set correct context for its code fragment
private fun correctContext(oldContext: PsiElement?): PsiElement? { private fun JetExpression.correctContextForExpression(): JetExpression {
if (oldContext is JetBlockExpression) { when (this) {
return oldContext.getStatements().lastOrNull() ?: oldContext is JetBlockExpression -> {
return this.getStatements().lastOrNull() ?: this
}
is JetFunctionLiteral -> {
return this.getBodyExpression()?.getStatements()?.lastOrNull() ?: this
}
else -> {
val previousExpression = this.siblings(forward = false, withItself = false).firstIsInstanceOrNull<JetExpression>()
if (previousExpression is JetExpression) {
return previousExpression
}
else {
val parentExpression = this.parents.firstIsInstanceOrNull<JetExpression>()
if (parentExpression is JetExpression) {
return parentExpression
}
}
}
} }
return oldContext return this
} }
public fun JetCodeFragment.getScopeAndDataFlowForAnalyzeFragment( public fun JetCodeFragment.getScopeAndDataFlowForAnalyzeFragment(
resolveSession: KotlinCodeAnalyzer, resolveSession: KotlinCodeAnalyzer,
resolveToElement: (JetElement) -> BindingContext resolveToElement: (JetElement) -> BindingContext
): Pair<JetScope, DataFlowInfo>? { ): Pair<JetScope, DataFlowInfo>? {
val context = correctContext(getContext()) val context = getContext()
if (context !is JetExpression) return null if (context !is JetExpression) return null
val scopeForContextElement: JetScope? val scopeForContextElement: JetScope?
@@ -52,10 +71,12 @@ public fun JetCodeFragment.getScopeAndDataFlowForAnalyzeFragment(
dataFlowInfo = DataFlowInfo.EMPTY dataFlowInfo = DataFlowInfo.EMPTY
} }
is JetExpression -> { is JetExpression -> {
val contextForElement = resolveToElement(context) val correctedContext = context.correctContextForExpression()
scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, context] val contextForElement = resolveToElement(correctedContext)
dataFlowInfo = contextForElement.getDataFlowInfo(context)
scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, correctedContext]
dataFlowInfo = contextForElement.getDataFlowInfo(correctedContext)
} }
else -> return null else -> return null
} }
@@ -0,0 +1,9 @@
fun foo() {
val aaaB = 1
<caret>val aaaC = 1
val aaaD = 1
}
// INVOCATION_COUNT: 1
// EXIST: aaaB
// ABSENT: aaaC, aaaD
@@ -0,0 +1 @@
aaa<caret>
@@ -0,0 +1,6 @@
fun foo() {
<caret>val aaaB = 1
}
// INVOCATION_COUNT: 1
// ABSENT: aaaB
@@ -0,0 +1 @@
aaa<caret>
@@ -0,0 +1,10 @@
fun main(args: Array<String>) {
val str: String? = ""
if (str != null)
<caret>test(str)
else
test("")
}
fun test(s: String) = 1
@@ -0,0 +1 @@
test(str)
@@ -0,0 +1,10 @@
fun main(args: Array<String>) {
val str: String? = ""
when(str) {
null -> test("")
else -> <caret>test(str)
}
}
fun test(s: String) = 1
@@ -0,0 +1 @@
test(str)
@@ -47,6 +47,18 @@ public class CodeFragmentCompletionTestGenerated extends AbstractCodeFragmentCom
doTest(fileName); doTest(fileName);
} }
@TestMetadata("elementAt.kt")
public void testElementAt() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/elementAt.kt");
doTest(fileName);
}
@TestMetadata("elementAtFirstInBlock.kt")
public void testElementAtFirstInBlock() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt");
doTest(fileName);
}
@TestMetadata("localVal.kt") @TestMetadata("localVal.kt")
public void testLocalVal() throws Exception { public void testLocalVal() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/localVal.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/localVal.kt");
@@ -73,6 +73,18 @@ public class CodeFragmentHighlightingTestGenerated extends AbstractCodeFragmentH
doTest(fileName); doTest(fileName);
} }
@TestMetadata("elementAtIfWithoutBraces.kt")
public void testElementAtIfWithoutBraces() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt");
doTest(fileName);
}
@TestMetadata("elementAtWhenBranch.kt")
public void testElementAtWhenBranch() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/codeFragments/elementAtWhenBranch.kt");
doTest(fileName);
}
@TestMetadata("localVariables.kt") @TestMetadata("localVariables.kt")
public void testLocalVariables() throws Exception { public void testLocalVariables() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/codeFragments/localVariables.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/codeFragments/localVariables.kt");