Debugger: implement findExpression method correctly to make work Alt+Click in debugger
This commit is contained in:
@@ -106,6 +106,7 @@ import org.jetbrains.jet.plugin.debugger.AbstractKotlinSteppingTest
|
||||
import org.jetbrains.jet.completion.AbstractMultiFileJvmBasicCompletionTest
|
||||
import org.jetbrains.jet.plugin.refactoring.introduce.introduceVariable.AbstractJetExtractionTest
|
||||
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractKotlinEvaluateExpressionTest
|
||||
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractSelectExpressionForDebuggerTest
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
System.setProperty("java.awt.headless", "true")
|
||||
@@ -574,6 +575,10 @@ fun main(args: Array<String>) {
|
||||
model("refactoring/introduceVariable", extension = "kt", testMethod = "doIntroduceVariableTest")
|
||||
model("refactoring/extractFunction", extension = "kt", testMethod = "doExtractFunctionTest")
|
||||
}
|
||||
|
||||
testClass(javaClass<AbstractSelectExpressionForDebuggerTest>()) {
|
||||
model("debugger/selectExpression")
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("j2k/tests/test", "j2k/tests/testData") {
|
||||
|
||||
@@ -23,18 +23,29 @@ import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.openapi.util.Pair
|
||||
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl
|
||||
import com.intellij.debugger.engine.evaluation.CodeFragmentKind
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import org.jetbrains.jet.plugin.JetFileType
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression
|
||||
import org.jetbrains.jet.lang.psi.JetThisExpression
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.jet.lang.psi.JetOperationExpression
|
||||
import org.jetbrains.jet.lang.psi.JetExpression
|
||||
import org.jetbrains.jet.lang.psi.JetExpressionCodeFragmentImpl
|
||||
import org.jetbrains.jet.lang.psi.JetSuperExpression
|
||||
|
||||
class KotlinEditorTextProvider : EditorTextProvider {
|
||||
override fun getEditorText(elementAtCaret: PsiElement): TextWithImports? {
|
||||
return TextWithImportsImpl(CodeFragmentKind.EXPRESSION, elementAtCaret.getText(), getImports(elementAtCaret), JetFileType.INSTANCE)
|
||||
val expression = findExpressionInner(elementAtCaret)
|
||||
return TextWithImportsImpl(CodeFragmentKind.EXPRESSION, expression?.getText() ?: "", getImports(elementAtCaret), JetFileType.INSTANCE)
|
||||
}
|
||||
|
||||
override fun findExpression(elementAtCaret: PsiElement, allowMethodCalls: Boolean): Pair<PsiElement, TextRange>? {
|
||||
return Pair(elementAtCaret, elementAtCaret.getTextRange())
|
||||
val expression = findExpressionInner(elementAtCaret)
|
||||
if (expression == null) return null
|
||||
return Pair(expression, expression.getTextRange())
|
||||
}
|
||||
|
||||
class object {
|
||||
@@ -43,8 +54,51 @@ class KotlinEditorTextProvider : EditorTextProvider {
|
||||
if (containingFile !is JetFile) return ""
|
||||
|
||||
return containingFile.getImportList()?.getImports()
|
||||
?.map { it.getText() }
|
||||
?.makeString(JetExpressionCodeFragmentImpl.IMPORT_SEPARATOR) ?: ""
|
||||
?.map { it.getText() }
|
||||
?.makeString(JetExpressionCodeFragmentImpl.IMPORT_SEPARATOR) ?: ""
|
||||
}
|
||||
|
||||
fun findExpressionInner(element: PsiElement): JetExpression? {
|
||||
val jetElement = PsiTreeUtil.getParentOfType(element, javaClass<JetElement>())
|
||||
if (jetElement == null) return null
|
||||
|
||||
val parent = jetElement.getParent()
|
||||
if (parent == null) return null
|
||||
|
||||
val newExpression = when (parent) {
|
||||
is JetThisExpression,
|
||||
is JetSuperExpression,
|
||||
is JetReferenceExpression -> {
|
||||
val pparent = parent.getParent()
|
||||
when (pparent) {
|
||||
is JetQualifiedExpression -> pparent
|
||||
else -> parent
|
||||
}
|
||||
}
|
||||
is JetQualifiedExpression -> {
|
||||
if (parent.getReceiverExpression() != jetElement) {
|
||||
parent
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
is JetOperationExpression -> {
|
||||
if (parent.getOperationReference() == jetElement) {
|
||||
parent
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (newExpression is JetExpression) return newExpression
|
||||
|
||||
if (jetElement is JetSimpleNameExpression) {
|
||||
return jetElement
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lexer.JetToken
|
||||
import org.jetbrains.jet.JetNodeType
|
||||
import org.jetbrains.jet.lexer.JetTokens
|
||||
import org.jetbrains.jet.lang.psi.JetExpressionCodeFragmentImpl
|
||||
import com.intellij.psi.PsiCodeBlock
|
||||
|
||||
class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
||||
override fun createCodeFragment(item: TextWithImports, context: PsiElement?, project: Project): JavaCodeFragment {
|
||||
@@ -45,6 +46,9 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
||||
}
|
||||
|
||||
override fun isContextAccepted(contextElement: PsiElement?): Boolean {
|
||||
if (contextElement is PsiCodeBlock) {
|
||||
return contextElement.getContext()?.getContext()?.getLanguage() == JetFileType.INSTANCE.getLanguage()
|
||||
}
|
||||
return contextElement?.getLanguage() == JetFileType.INSTANCE.getLanguage()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo() {
|
||||
1 <caret>+ 1
|
||||
}
|
||||
|
||||
// EXPECTED: 1 + 1
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
<caret>bar()
|
||||
}
|
||||
|
||||
fun bar() = 1
|
||||
|
||||
// EXPECTED: bar()
|
||||
@@ -0,0 +1,4 @@
|
||||
val a = 1
|
||||
val b = <caret>a
|
||||
|
||||
// EXPECTED: a
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
1.<caret>foo()
|
||||
}
|
||||
|
||||
fun Int.foo() = 1
|
||||
|
||||
// EXPECTED: 1.foo()
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo() {
|
||||
val a = 1
|
||||
bar(<caret>a)
|
||||
}
|
||||
|
||||
fun bar(i: Int) = 1
|
||||
|
||||
// EXPECTED: a
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
<caret>bar { }
|
||||
}
|
||||
|
||||
fun bar(f: () -> Unit) = 1
|
||||
|
||||
// EXPECTED: bar { }
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
val klass = MyClass()
|
||||
klass<caret>[1]
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
fun get(i: Int): Int = 1
|
||||
}
|
||||
|
||||
// EXPECTED: klass[1]
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
1 <caret>foo 1
|
||||
}
|
||||
|
||||
fun Int.foo(i: Int) = 1
|
||||
|
||||
// EXPECTED: 1 foo 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo() {
|
||||
val a = 1
|
||||
<caret>a foo 1
|
||||
}
|
||||
|
||||
fun Int.foo(i: Int) = 1
|
||||
|
||||
// EXPECTED: a
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo() {
|
||||
1 <caret>is Int
|
||||
}
|
||||
|
||||
// EXPECTED: 1 is Int
|
||||
@@ -0,0 +1,3 @@
|
||||
<caret>val a = 1
|
||||
|
||||
// EXPECTED: null
|
||||
@@ -0,0 +1,3 @@
|
||||
<caret>public fun foo() = 1
|
||||
|
||||
// EXPECTED: null
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo(i: Int) {
|
||||
<caret>i
|
||||
}
|
||||
|
||||
// EXPECTED: i
|
||||
@@ -0,0 +1,6 @@
|
||||
val a = 1
|
||||
fun foo() {
|
||||
<caret>a
|
||||
}
|
||||
|
||||
// EXPECTED: a
|
||||
@@ -0,0 +1,3 @@
|
||||
val <caret>a = 1
|
||||
|
||||
// EXPECTED: null
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
val klass = MyClass()
|
||||
klass.<caret>bar
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
val bar = 1
|
||||
}
|
||||
|
||||
// EXPECTED: klass.bar
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
val klass = MyClass()
|
||||
<caret>klass.bar()
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
fun bar() = 1
|
||||
}
|
||||
|
||||
// EXPECTED: klass
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
val klass = MyClass()
|
||||
klass.<caret>bar()
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
fun bar() = 1
|
||||
}
|
||||
|
||||
// EXPECTED: klass.bar()
|
||||
@@ -0,0 +1,11 @@
|
||||
class Derived: Base() {
|
||||
fun test() {
|
||||
<caret>super.test()
|
||||
}
|
||||
}
|
||||
|
||||
open class Base {
|
||||
fun test() {}
|
||||
}
|
||||
|
||||
// EXPECTED: super.test()
|
||||
@@ -0,0 +1,7 @@
|
||||
class MyClass {
|
||||
fun test() {
|
||||
<caret>this.test()
|
||||
}
|
||||
}
|
||||
|
||||
// EXPECTED: this.test()
|
||||
@@ -0,0 +1,7 @@
|
||||
class MyClass {
|
||||
fun Int.test() {
|
||||
<caret>this@MyClass
|
||||
}
|
||||
}
|
||||
|
||||
// EXPECTED: this@MyClass
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo() {
|
||||
<caret>+1
|
||||
}
|
||||
|
||||
// EXPECTED: +1
|
||||
+1
-1
@@ -77,7 +77,7 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC
|
||||
private fun SuspendContextImpl.evaluate(expression: String, expectedResult: String) {
|
||||
try {
|
||||
val sourcePosition = ContextUtil.getSourcePosition(this)
|
||||
val contextElement = sourcePosition?.getElementAt()!!
|
||||
val contextElement = ContextUtil.getContextElement(sourcePosition)!!
|
||||
Assert.assertTrue("KotlinCodeFragmentFactory should be accepted for context element otherwise default evaluator will be called. ContextElement = ${contextElement.getText()}",
|
||||
KotlinCodeFragmentFactory().isContextAccepted(contextElement))
|
||||
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.debugger.evaluate
|
||||
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.jet.plugin.debugger.KotlinEditorTextProvider
|
||||
import org.jetbrains.jet.plugin.PluginTestCaseBase
|
||||
import org.jetbrains.jet.InTextDirectivesUtils
|
||||
import org.junit.Assert
|
||||
|
||||
public abstract class AbstractSelectExpressionForDebuggerTest : LightCodeInsightFixtureTestCase() {
|
||||
|
||||
fun doTest(path: String) {
|
||||
myFixture.configureByFile(path)
|
||||
|
||||
val elementAt = myFixture.getFile()?.findElementAt(myFixture.getCaretOffset())!!
|
||||
val selectedExpression = KotlinEditorTextProvider.findExpressionInner(elementAt)
|
||||
|
||||
val expected = InTextDirectivesUtils.findStringWithPrefixes(myFixture.getFile()?.getText()!!, "// EXPECTED: ")
|
||||
Assert.assertEquals("Another expression should be selected", expected, selectedExpression?.getText() ?: "null")
|
||||
}
|
||||
|
||||
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/debugger/selectExpression";
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.debugger.evaluate;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.test.InnerTestClasses;
|
||||
import org.jetbrains.jet.test.TestMetadata;
|
||||
|
||||
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractSelectExpressionForDebuggerTest;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/debugger/selectExpression")
|
||||
public class SelectExpressionForDebuggerTestGenerated extends AbstractSelectExpressionForDebuggerTest {
|
||||
public void testAllFilesPresentInSelectExpression() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/selectExpression"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("binaryExpression.kt")
|
||||
public void testBinaryExpression() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/binaryExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("call.kt")
|
||||
public void testCall() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/call.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expressionInPropertyInitializer.kt")
|
||||
public void testExpressionInPropertyInitializer() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/expressionInPropertyInitializer.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionFun.kt")
|
||||
public void testExtensionFun() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/extensionFun.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("funArgument.kt")
|
||||
public void testFunArgument() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/funArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionLiteral.kt")
|
||||
public void testFunctionLiteral() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/functionLiteral.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("getConvention.kt")
|
||||
public void testGetConvention() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/getConvention.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("infixCall.kt")
|
||||
public void testInfixCall() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/infixCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("infixCallArgument.kt")
|
||||
public void testInfixCallArgument() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/infixCallArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("isExpression.kt")
|
||||
public void testIsExpression() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/isExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("keyword.kt")
|
||||
public void testKeyword() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/keyword.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("modifier.kt")
|
||||
public void testModifier() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/modifier.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("param.kt")
|
||||
public void testParam() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/param.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyCall.kt")
|
||||
public void testPropertyCall() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/propertyCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyDeclaration.kt")
|
||||
public void testPropertyDeclaration() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/propertyDeclaration.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("qualifiedExpressionProperty.kt")
|
||||
public void testQualifiedExpressionProperty() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/qualifiedExpressionProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("qualifiedExpressionReceiver.kt")
|
||||
public void testQualifiedExpressionReceiver() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/qualifiedExpressionReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("qualifiedExpressionSelector.kt")
|
||||
public void testQualifiedExpressionSelector() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/qualifiedExpressionSelector.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("super.kt")
|
||||
public void testSuper() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/super.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("this.kt")
|
||||
public void testThis() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/this.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("thisWithLabel.kt")
|
||||
public void testThisWithLabel() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/thisWithLabel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unaryExpression.kt")
|
||||
public void testUnaryExpression() throws Exception {
|
||||
doTest("idea/testData/debugger/selectExpression/unaryExpression.kt");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user