From 75edfa652793e47b0ff6128be332ea1e8a0736c3 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Thu, 16 Jul 2015 13:08:31 +0300 Subject: [PATCH] Debugger: do not resolve symbols on breakpoint line in Evaluate Expression --- .../resolve/util/codeFragmentResolveUtils.kt | 39 ++++++++++++++----- .../testData/basic/codeFragments/elementAt.kt | 9 +++++ .../basic/codeFragments/elementAt.kt.fragment | 1 + .../codeFragments/elementAtFirstInBlock.kt | 6 +++ .../elementAtFirstInBlock.kt.fragment | 1 + .../codeFragments/elementAtIfWithoutBraces.kt | 10 +++++ .../elementAtIfWithoutBraces.kt.fragment | 1 + .../codeFragments/elementAtWhenBranch.kt | 10 +++++ .../elementAtWhenBranch.kt.fragment | 1 + .../CodeFragmentCompletionTestGenerated.java | 12 ++++++ ...CodeFragmentHighlightingTestGenerated.java | 12 ++++++ 11 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 idea/idea-completion/testData/basic/codeFragments/elementAt.kt create mode 100644 idea/idea-completion/testData/basic/codeFragments/elementAt.kt.fragment create mode 100644 idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt create mode 100644 idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt.fragment create mode 100644 idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt create mode 100644 idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt.fragment create mode 100644 idea/testData/checker/codeFragments/elementAtWhenBranch.kt create mode 100644 idea/testData/checker/codeFragments/elementAtWhenBranch.kt.fragment diff --git a/idea/ide-common/src/org/jetbrains/kotlin/resolve/util/codeFragmentResolveUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/resolve/util/codeFragmentResolveUtils.kt index 77afac95010..11b88ec2736 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/resolve/util/codeFragmentResolveUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/resolve/util/codeFragmentResolveUtils.kt @@ -16,29 +16,48 @@ package org.jetbrains.kotlin.resolve.util -import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes 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.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer import org.jetbrains.kotlin.resolve.scopes.ChainedScope 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 -private fun correctContext(oldContext: PsiElement?): PsiElement? { - if (oldContext is JetBlockExpression) { - return oldContext.getStatements().lastOrNull() ?: oldContext +private fun JetExpression.correctContextForExpression(): JetExpression { + when (this) { + 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() + if (previousExpression is JetExpression) { + return previousExpression + } + else { + val parentExpression = this.parents.firstIsInstanceOrNull() + if (parentExpression is JetExpression) { + return parentExpression + } + } + } } - return oldContext + return this } public fun JetCodeFragment.getScopeAndDataFlowForAnalyzeFragment( resolveSession: KotlinCodeAnalyzer, resolveToElement: (JetElement) -> BindingContext ): Pair? { - val context = correctContext(getContext()) + val context = getContext() if (context !is JetExpression) return null val scopeForContextElement: JetScope? @@ -52,10 +71,12 @@ public fun JetCodeFragment.getScopeAndDataFlowForAnalyzeFragment( dataFlowInfo = DataFlowInfo.EMPTY } is JetExpression -> { - val contextForElement = resolveToElement(context) + val correctedContext = context.correctContextForExpression() - scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, context] - dataFlowInfo = contextForElement.getDataFlowInfo(context) + val contextForElement = resolveToElement(correctedContext) + + scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, correctedContext] + dataFlowInfo = contextForElement.getDataFlowInfo(correctedContext) } else -> return null } diff --git a/idea/idea-completion/testData/basic/codeFragments/elementAt.kt b/idea/idea-completion/testData/basic/codeFragments/elementAt.kt new file mode 100644 index 00000000000..45cae3892e1 --- /dev/null +++ b/idea/idea-completion/testData/basic/codeFragments/elementAt.kt @@ -0,0 +1,9 @@ +fun foo() { + val aaaB = 1 + val aaaC = 1 + val aaaD = 1 +} + +// INVOCATION_COUNT: 1 +// EXIST: aaaB +// ABSENT: aaaC, aaaD \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/codeFragments/elementAt.kt.fragment b/idea/idea-completion/testData/basic/codeFragments/elementAt.kt.fragment new file mode 100644 index 00000000000..1a83755fab1 --- /dev/null +++ b/idea/idea-completion/testData/basic/codeFragments/elementAt.kt.fragment @@ -0,0 +1 @@ +aaa \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt b/idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt new file mode 100644 index 00000000000..3083066d049 --- /dev/null +++ b/idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt @@ -0,0 +1,6 @@ +fun foo() { + val aaaB = 1 +} + +// INVOCATION_COUNT: 1 +// ABSENT: aaaB \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt.fragment b/idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt.fragment new file mode 100644 index 00000000000..1a83755fab1 --- /dev/null +++ b/idea/idea-completion/testData/basic/codeFragments/elementAtFirstInBlock.kt.fragment @@ -0,0 +1 @@ +aaa \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt b/idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt new file mode 100644 index 00000000000..d178d6df57e --- /dev/null +++ b/idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt @@ -0,0 +1,10 @@ +fun main(args: Array) { + val str: String? = "" + + if (str != null) + test(str) + else + test("") +} + +fun test(s: String) = 1 \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt.fragment b/idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt.fragment new file mode 100644 index 00000000000..fc12a393b72 --- /dev/null +++ b/idea/testData/checker/codeFragments/elementAtIfWithoutBraces.kt.fragment @@ -0,0 +1 @@ +test(str) \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/elementAtWhenBranch.kt b/idea/testData/checker/codeFragments/elementAtWhenBranch.kt new file mode 100644 index 00000000000..47389c6aac1 --- /dev/null +++ b/idea/testData/checker/codeFragments/elementAtWhenBranch.kt @@ -0,0 +1,10 @@ +fun main(args: Array) { + val str: String? = "" + + when(str) { + null -> test("") + else -> test(str) + } +} + +fun test(s: String) = 1 \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/elementAtWhenBranch.kt.fragment b/idea/testData/checker/codeFragments/elementAtWhenBranch.kt.fragment new file mode 100644 index 00000000000..fc12a393b72 --- /dev/null +++ b/idea/testData/checker/codeFragments/elementAtWhenBranch.kt.fragment @@ -0,0 +1 @@ +test(str) \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionTestGenerated.java index 5541f7c1e54..116c022dc08 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionTestGenerated.java @@ -47,6 +47,18 @@ public class CodeFragmentCompletionTestGenerated extends AbstractCodeFragmentCom 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") public void testLocalVal() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/localVal.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java index 234d00c3012..346da628466 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java @@ -73,6 +73,18 @@ public class CodeFragmentHighlightingTestGenerated extends AbstractCodeFragmentH 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") public void testLocalVariables() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/codeFragments/localVariables.kt");