From a76bb80e4d9f007099f034a1d90a6ed9407d3393 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 23 May 2018 18:21:18 +0300 Subject: [PATCH] Experimental fixes: additional tests, handle local declarations --- .../idea/quickfix/ExperimentalFixesFactory.kt | 14 +++++--- .../experimental/functionInLocalClass.kt | 20 +++++++++++ .../functionInLocalClass.kt.after | 21 ++++++++++++ .../quickfix/experimental/localFunction.kt | 15 +++++++++ .../experimental/localFunction.kt.after | 16 +++++++++ .../quickfix/experimental/nestedClasses.kt | 23 +++++++++++++ .../idea/quickfix/QuickFixTestGenerated.java | 33 ++++++++++++------- 7 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 idea/testData/quickfix/experimental/functionInLocalClass.kt create mode 100644 idea/testData/quickfix/experimental/functionInLocalClass.kt.after create mode 100644 idea/testData/quickfix/experimental/localFunction.kt create mode 100644 idea/testData/quickfix/experimental/localFunction.kt.after create mode 100644 idea/testData/quickfix/experimental/nestedClasses.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ExperimentalFixesFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ExperimentalFixesFactory.kt index 830378210d7..468025fb57d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ExperimentalFixesFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ExperimentalFixesFactory.kt @@ -15,11 +15,9 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.core.toDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate import org.jetbrains.kotlin.resolve.AnnotationChecker import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker import org.jetbrains.kotlin.resolve.descriptorUtil.module @@ -27,7 +25,13 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module object ExperimentalFixesFactory : KotlinIntentionActionsFactory() { override fun doCreateActions(diagnostic: Diagnostic): List { val element = diagnostic.psiElement - val containingDeclaration: KtDeclaration = element.getStrictParentOfType() ?: return emptyList() + val containingDeclaration: KtDeclaration = element.getParentOfTypesAndPredicate( + true, + KtDeclarationWithBody::class.java, + KtClassOrObject::class.java + ) { + !KtPsiUtil.isLocal(it) + } ?: return emptyList() val factory = diagnostic.factory val annotationFqName = when (factory) { diff --git a/idea/testData/quickfix/experimental/functionInLocalClass.kt b/idea/testData/quickfix/experimental/functionInLocalClass.kt new file mode 100644 index 00000000000..4e0db40c4ea --- /dev/null +++ b/idea/testData/quickfix/experimental/functionInLocalClass.kt @@ -0,0 +1,20 @@ +// "Add '@MyExperimentalAPI' annotation to 'outer'" "true" +// COMPILER_ARGUMENTS: -Xuse-experimental=kotlin.Experimental +// WITH_RUNTIME + +@Experimental +@Target(AnnotationTarget.FUNCTION) +annotation class MyExperimentalAPI + +open class Base { + @MyExperimentalAPI + open fun foo() {} +} + +class Outer { + fun outer() { + class Derived : Base() { + override fun foo() {} + } + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/experimental/functionInLocalClass.kt.after b/idea/testData/quickfix/experimental/functionInLocalClass.kt.after new file mode 100644 index 00000000000..d0e29501df4 --- /dev/null +++ b/idea/testData/quickfix/experimental/functionInLocalClass.kt.after @@ -0,0 +1,21 @@ +// "Add '@MyExperimentalAPI' annotation to 'outer'" "true" +// COMPILER_ARGUMENTS: -Xuse-experimental=kotlin.Experimental +// WITH_RUNTIME + +@Experimental +@Target(AnnotationTarget.FUNCTION) +annotation class MyExperimentalAPI + +open class Base { + @MyExperimentalAPI + open fun foo() {} +} + +class Outer { + @MyExperimentalAPI + fun outer() { + class Derived : Base() { + override fun foo() {} + } + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/experimental/localFunction.kt b/idea/testData/quickfix/experimental/localFunction.kt new file mode 100644 index 00000000000..1806062508d --- /dev/null +++ b/idea/testData/quickfix/experimental/localFunction.kt @@ -0,0 +1,15 @@ +// "Add '@MyExperimentalAPI' annotation to 'outer'" "true" +// COMPILER_ARGUMENTS: -Xuse-experimental=kotlin.Experimental +// WITH_RUNTIME + +@Experimental +annotation class MyExperimentalAPI + +@MyExperimentalAPI +fun foo() {} + +fun outer() { + fun bar() { + foo() + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/experimental/localFunction.kt.after b/idea/testData/quickfix/experimental/localFunction.kt.after new file mode 100644 index 00000000000..56052daf95d --- /dev/null +++ b/idea/testData/quickfix/experimental/localFunction.kt.after @@ -0,0 +1,16 @@ +// "Add '@MyExperimentalAPI' annotation to 'outer'" "true" +// COMPILER_ARGUMENTS: -Xuse-experimental=kotlin.Experimental +// WITH_RUNTIME + +@Experimental +annotation class MyExperimentalAPI + +@MyExperimentalAPI +fun foo() {} + +@MyExperimentalAPI +fun outer() { + fun bar() { + foo() + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/experimental/nestedClasses.kt b/idea/testData/quickfix/experimental/nestedClasses.kt new file mode 100644 index 00000000000..a4e6c037cf0 --- /dev/null +++ b/idea/testData/quickfix/experimental/nestedClasses.kt @@ -0,0 +1,23 @@ +// "Add '@MyExperimentalAPI' annotation to containing class 'Outer'" "false" +// COMPILER_ARGUMENTS: -Xuse-experimental=kotlin.Experimental +// WITH_RUNTIME +// ACTION: Add '@MyExperimentalAPI' annotation to 'bar' +// ACTION: Add '@MyExperimentalAPI' annotation to containing class 'Inner' +// ACTION: Add '@UseExperimental(MyExperimentalAPI::class)' annotation to 'bar' +// ERROR: This declaration is experimental and its usage must be marked with '@MyExperimentalAPI' or '@UseExperimental(MyExperimentalAPI::class)' + +@Experimental +annotation class MyExperimentalAPI + +@MyExperimentalAPI +fun foo() {} + +class Outer { + class Bar { + class Inner { + fun bar() { + foo() + } + } + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index aaa61967f2e..d6b1c45bb6a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -1645,38 +1645,32 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { @TestMetadata("removeUnusedParameterWithTypeParameter.kt") public void testRemoveUnusedParameterWithTypeParameter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter.kt"); - doTest(fileName); + runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter.kt"); } @TestMetadata("removeUnusedParameterWithTypeParameter2.kt") public void testRemoveUnusedParameterWithTypeParameter2() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter2.kt"); - doTest(fileName); + runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter2.kt"); } @TestMetadata("removeUnusedParameterWithTypeParameter3.kt") public void testRemoveUnusedParameterWithTypeParameter3() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter3.kt"); - doTest(fileName); + runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter3.kt"); } @TestMetadata("removeUnusedParameterWithTypeParameter4.kt") public void testRemoveUnusedParameterWithTypeParameter4() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter4.kt"); - doTest(fileName); + runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter4.kt"); } @TestMetadata("removeUnusedParameterWithTypeParameter5.kt") public void testRemoveUnusedParameterWithTypeParameter5() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter5.kt"); - doTest(fileName); + runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter5.kt"); } @TestMetadata("removeUnusedParameterWithTypeParameter6.kt") public void testRemoveUnusedParameterWithTypeParameter6() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter6.kt"); - doTest(fileName); + runTest("idea/testData/quickfix/changeSignature/removeUnusedParameterWithTypeParameter6.kt"); } @TestMetadata("removeUnusedPrimaryConstructorParameter.kt") @@ -6063,6 +6057,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/experimental/classUseExperimental.kt"); } + @TestMetadata("functionInLocalClass.kt") + public void testFunctionInLocalClass() throws Exception { + runTest("idea/testData/quickfix/experimental/functionInLocalClass.kt"); + } + + @TestMetadata("localFunction.kt") + public void testLocalFunction() throws Exception { + runTest("idea/testData/quickfix/experimental/localFunction.kt"); + } + + @TestMetadata("nestedClasses.kt") + public void testNestedClasses() throws Exception { + runTest("idea/testData/quickfix/experimental/nestedClasses.kt"); + } + @TestMetadata("override.kt") public void testOverride() throws Exception { runTest("idea/testData/quickfix/experimental/override.kt");