Navigate to lambda declaration from generated 'it' (KT-16992)
#KT-16992 Fixed #KT-13013 In Progress
This commit is contained in:
@@ -24,9 +24,9 @@ import org.jetbrains.kotlin.allopen.AbstractBytecodeListingTestForAllOpen
|
|||||||
import org.jetbrains.kotlin.android.*
|
import org.jetbrains.kotlin.android.*
|
||||||
import org.jetbrains.kotlin.android.configure.AbstractConfigureProjectTest
|
import org.jetbrains.kotlin.android.configure.AbstractConfigureProjectTest
|
||||||
import org.jetbrains.kotlin.android.folding.AbstractAndroidResourceFoldingTest
|
import org.jetbrains.kotlin.android.folding.AbstractAndroidResourceFoldingTest
|
||||||
import org.jetbrains.kotlin.android.quickfix.AbstractAndroidLintQuickfixTest
|
|
||||||
import org.jetbrains.kotlin.android.intention.AbstractAndroidResourceIntentionTest
|
import org.jetbrains.kotlin.android.intention.AbstractAndroidResourceIntentionTest
|
||||||
import org.jetbrains.kotlin.android.lint.AbstractKotlinLintTest
|
import org.jetbrains.kotlin.android.lint.AbstractKotlinLintTest
|
||||||
|
import org.jetbrains.kotlin.android.quickfix.AbstractAndroidLintQuickfixTest
|
||||||
import org.jetbrains.kotlin.android.quickfix.AbstractAndroidQuickFixMultiFileTest
|
import org.jetbrains.kotlin.android.quickfix.AbstractAndroidQuickFixMultiFileTest
|
||||||
import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessorBoxTest
|
import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessorBoxTest
|
||||||
import org.jetbrains.kotlin.annotation.processing.test.sourceRetention.AbstractBytecodeListingTestForSourceRetention
|
import org.jetbrains.kotlin.annotation.processing.test.sourceRetention.AbstractBytecodeListingTestForSourceRetention
|
||||||
@@ -104,10 +104,7 @@ import org.jetbrains.kotlin.idea.kdoc.AbstractKDocHighlightingTest
|
|||||||
import org.jetbrains.kotlin.idea.kdoc.AbstractKDocTypingTest
|
import org.jetbrains.kotlin.idea.kdoc.AbstractKDocTypingTest
|
||||||
import org.jetbrains.kotlin.idea.maven.AbstractKotlinMavenInspectionTest
|
import org.jetbrains.kotlin.idea.maven.AbstractKotlinMavenInspectionTest
|
||||||
import org.jetbrains.kotlin.idea.maven.configuration.AbstractMavenConfigureProjectByChangingFileTest
|
import org.jetbrains.kotlin.idea.maven.configuration.AbstractMavenConfigureProjectByChangingFileTest
|
||||||
import org.jetbrains.kotlin.idea.navigation.AbstractGotoSuperTest
|
import org.jetbrains.kotlin.idea.navigation.*
|
||||||
import org.jetbrains.kotlin.idea.navigation.AbstractGotoTypeDeclarationTest
|
|
||||||
import org.jetbrains.kotlin.idea.navigation.AbstractKotlinGotoImplementationTest
|
|
||||||
import org.jetbrains.kotlin.idea.navigation.AbstractKotlinGotoTest
|
|
||||||
import org.jetbrains.kotlin.idea.parameterInfo.AbstractParameterInfoTest
|
import org.jetbrains.kotlin.idea.parameterInfo.AbstractParameterInfoTest
|
||||||
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiFileTest
|
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiFileTest
|
||||||
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest
|
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest
|
||||||
@@ -506,6 +503,10 @@ fun main(args: Array<String>) {
|
|||||||
model("navigation/gotoTypeDeclaration", extension = "test")
|
model("navigation/gotoTypeDeclaration", extension = "test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass<AbstractGotoDeclarationTest> {
|
||||||
|
model("navigation/gotoDeclaration", extension = "test")
|
||||||
|
}
|
||||||
|
|
||||||
testClass<AbstractParameterInfoTest> {
|
testClass<AbstractParameterInfoTest> {
|
||||||
model("parameterInfo", recursive = true, excludeDirs = listOf("withLib1/sharedLib", "withLib2/sharedLib", "withLib3/sharedLib"))
|
model("parameterInfo", recursive = true, excludeDirs = listOf("withLib1/sharedLib", "withLib2/sharedLib", "withLib3/sharedLib"))
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-2
@@ -22,16 +22,39 @@ import com.intellij.codeInsight.TargetElementUtil
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiReference
|
import com.intellij.psi.PsiReference
|
||||||
|
import com.intellij.util.BitUtil
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage
|
||||||
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
||||||
|
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isAbstract
|
||||||
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
|
|
||||||
class KotlinTargetElementEvaluator : TargetElementEvaluatorEx {
|
class KotlinTargetElementEvaluator : TargetElementEvaluatorEx {
|
||||||
|
companion object {
|
||||||
|
// Place caret after the open curly brace in lambda for generated 'it'
|
||||||
|
fun findLambdaOpenLBraceForGeneratedIt(ref: PsiReference): PsiElement? {
|
||||||
|
val element: PsiElement = ref.element
|
||||||
|
if (element.text != "it") return null
|
||||||
|
|
||||||
|
if (element !is KtNameReferenceExpression || !isAutoCreatedItUsage(element)) return null
|
||||||
|
|
||||||
|
val itDescriptor = element.resolveMainReferenceToDescriptors().singleOrNull() ?: return null
|
||||||
|
val descriptorWithSource = itDescriptor.containingDeclaration as? DeclarationDescriptorWithSource ?: return null
|
||||||
|
val lambdaExpression = descriptorWithSource.source.getPsi()?.parent as? KtLambdaExpression ?: return null
|
||||||
|
return lambdaExpression.leftCurlyBrace.treeNext?.psi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun includeSelfInGotoImplementation(element: PsiElement): Boolean = !(element is KtClass && element.isAbstract())
|
override fun includeSelfInGotoImplementation(element: PsiElement): Boolean = !(element is KtClass && element.isAbstract())
|
||||||
|
|
||||||
override fun getElementByReference(ref: PsiReference, flags: Int): PsiElement? {
|
override fun getElementByReference(ref: PsiReference, flags: Int): PsiElement? {
|
||||||
// prefer destructing declaration entry to its target if element name is accepted
|
// prefer destructing declaration entry to its target if element name is accepted
|
||||||
if (ref is KtDestructuringDeclarationReference && flags.and(TargetElementUtil.ELEMENT_NAME_ACCEPTED) != 0) {
|
if (ref is KtDestructuringDeclarationReference && BitUtil.isSet(flags, TargetElementUtil.ELEMENT_NAME_ACCEPTED)) {
|
||||||
return ref.element
|
return ref.element
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +66,10 @@ class KotlinTargetElementEvaluator : TargetElementEvaluatorEx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BitUtil.isSet(flags, TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED)) {
|
||||||
|
return findLambdaOpenLBraceForGeneratedIt(ref)
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// FILE: before.kt
|
||||||
|
interface Foo
|
||||||
|
interface Bar
|
||||||
|
|
||||||
|
fun foo(a: Foo.(Bar) -> Unit) {}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo {
|
||||||
|
<caret>it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: after.kt
|
||||||
|
interface Foo
|
||||||
|
interface Bar
|
||||||
|
|
||||||
|
fun foo(a: Foo.(Bar) -> Unit) {}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo {<caret>
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// FILE: before.kt
|
||||||
|
interface Foo
|
||||||
|
interface Bar
|
||||||
|
|
||||||
|
fun foo(b: Int, a: Foo.(Bar) -> Unit) {}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(12, {
|
||||||
|
<caret>it
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: after.kt
|
||||||
|
interface Foo
|
||||||
|
interface Bar
|
||||||
|
|
||||||
|
fun foo(b: Int, a: Foo.(Bar) -> Unit) {}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(12, {<caret>
|
||||||
|
it
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// FILE: before.kt
|
||||||
|
fun test(a: (Int) -> Unit = { <caret>it }) {}
|
||||||
|
|
||||||
|
// FILE: after.kt
|
||||||
|
fun test(a: (Int) -> Unit = {<caret> it }) {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// FILE: before.kt
|
||||||
|
val a: (Int) -> Unit = { <caret>it }
|
||||||
|
|
||||||
|
// FILE: after.kt
|
||||||
|
val a: (Int) -> Unit = {<caret> it }
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// FILE: before.kt
|
||||||
|
class Foo
|
||||||
|
|
||||||
|
fun <T> some(a: T, f: (T) -> Unit) {}
|
||||||
|
fun foo(a: Any) {}
|
||||||
|
|
||||||
|
fun baz() {
|
||||||
|
some(Foo()) {
|
||||||
|
foo(it<caret>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: after.kt
|
||||||
|
class Foo
|
||||||
|
|
||||||
|
fun <T> some(a: T, f: (T) -> Unit) {}
|
||||||
|
fun foo(a: Any) {}
|
||||||
|
|
||||||
|
fun baz() {
|
||||||
|
some(Foo()) {<caret>
|
||||||
|
foo(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 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.kotlin.idea.navigation
|
||||||
|
|
||||||
|
abstract class AbstractGotoDeclarationTest : AbstractGotoActionTest() {
|
||||||
|
override val actionName: String get() = "GotoDeclaration"
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 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.kotlin.idea.navigation;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("idea/testData/navigation/gotoDeclaration")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public class GotoDeclarationTestGenerated extends AbstractGotoDeclarationTest {
|
||||||
|
public void testAllFilesPresentInGotoDeclaration() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/navigation/gotoDeclaration"), Pattern.compile("^(.+)\\.test$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("itExtensionLambda.test")
|
||||||
|
public void testItExtensionLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/navigation/gotoDeclaration/itExtensionLambda.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("itExtensionLambdaInBrackets.test")
|
||||||
|
public void testItExtensionLambdaInBrackets() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/navigation/gotoDeclaration/itExtensionLambdaInBrackets.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("itInLambdaAsDefaultArgument.test")
|
||||||
|
public void testItInLambdaAsDefaultArgument() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/navigation/gotoDeclaration/itInLambdaAsDefaultArgument.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("itInLambdaWithoutCall.test")
|
||||||
|
public void testItInLambdaWithoutCall() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/navigation/gotoDeclaration/itInLambdaWithoutCall.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("itParameterInLambda.test")
|
||||||
|
public void testItParameterInLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/navigation/gotoDeclaration/itParameterInLambda.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user