Debugger: do not resolve symbols on breakpoint line in Evaluate Expression
This commit is contained in:
@@ -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
|
||||||
+1
@@ -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)
|
||||||
+12
@@ -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");
|
||||||
|
|||||||
+12
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user