From c5d4f22e4fd9e0f02277b2f63335bd6966d0833c Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 6 Apr 2018 16:26:48 +0200 Subject: [PATCH] Add quick fix for adding @JvmDefault annotation --- .../annotations/jvmDefault/javaOverride.txt | 16 +++++++++ .../idea/quickfix/AddJvmDefaultAnnotation.kt | 36 +++++++++++++++++++ .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 3 ++ .../addJvmDefault/functionOverride.kt | 16 +++++++++ .../addJvmDefault/functionOverride.kt.after | 17 +++++++++ .../javaDefaultOverride.after.kt | 9 +++++ ...javaDefaultOverride.before.Dependency.java | 3 ++ .../javaDefaultOverride.before.Main.kt | 8 +++++ .../addJvmDefault/propertyOverride.kt | 14 ++++++++ .../addJvmDefault/propertyOverride.kt.after | 15 ++++++++ .../QuickFixMultiFileTestGenerated.java | 15 ++++++++ .../idea/quickfix/QuickFixTestGenerated.java | 21 +++++++++++ 12 files changed, 173 insertions(+) create mode 100644 idea/src/org/jetbrains/kotlin/idea/quickfix/AddJvmDefaultAnnotation.kt create mode 100644 idea/testData/quickfix/addJvmDefault/functionOverride.kt create mode 100644 idea/testData/quickfix/addJvmDefault/functionOverride.kt.after create mode 100644 idea/testData/quickfix/addJvmDefault/javaDefaultOverride.after.kt create mode 100644 idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Dependency.java create mode 100644 idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Main.kt create mode 100644 idea/testData/quickfix/addJvmDefault/propertyOverride.kt create mode 100644 idea/testData/quickfix/addJvmDefault/propertyOverride.kt.after diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/javaOverride.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/javaOverride.txt index b24afc80609..39b1f5d883a 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/javaOverride.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/javaOverride.txt @@ -4,6 +4,7 @@ public interface JavaInterface { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open fun test(): kotlin.Unit + public abstract fun testAbstract(): kotlin.Unit public open fun testForNonDefault(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -13,6 +14,7 @@ public open class KotlinClass : JavaInterface { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun test(): kotlin.Unit + public open override /*1*/ fun testAbstract(): kotlin.Unit public open override /*1*/ fun testForNonDefault(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -21,14 +23,25 @@ public interface KotlinInterface : JavaInterface { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @kotlin.jvm.JvmDefault public open override /*1*/ fun test(): kotlin.Unit + public open override /*1*/ fun testAbstract(): kotlin.Unit public open override /*1*/ fun testForNonDefault(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +public interface KotlinInterface2 : JavaInterface, KotlinInterface { + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + @kotlin.jvm.JvmDefault public open override /*2*/ fun test(): kotlin.Unit + public open override /*2*/ fun testAbstract(): kotlin.Unit + public open override /*2*/ fun testForNonDefault(): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + public interface KotlinInterfaceForIndirect : JavaInterface { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun test(): kotlin.Unit + public abstract override /*1*/ /*fake_override*/ fun testAbstract(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun testForNonDefault(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -37,6 +50,7 @@ public interface KotlinInterfaceIndirectInheritance : KotlinInterfaceForIndirect public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @kotlin.jvm.JvmDefault public open override /*1*/ fun test(): kotlin.Unit + public open override /*1*/ fun testAbstract(): kotlin.Unit public open override /*1*/ fun testForNonDefault(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -45,6 +59,7 @@ public interface KotlinInterfaceManySuper : JavaInterface, KotlinInterfaceX { public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int @kotlin.jvm.JvmDefault public open override /*2*/ fun test(): kotlin.Unit + public open override /*2*/ fun testAbstract(): kotlin.Unit public open override /*2*/ fun testForNonDefault(): kotlin.Unit public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String } @@ -53,6 +68,7 @@ public interface KotlinInterfaceX { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open fun test(): kotlin.Unit + public open fun testAbstract(): kotlin.Unit public open fun testForNonDefault(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddJvmDefaultAnnotation.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddJvmDefaultAnnotation.kt new file mode 100644 index 00000000000..910a6ba2bc5 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddJvmDefaultAnnotation.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.quickfix + +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.util.addAnnotation +import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.resolve.annotations.JVM_DEFAULT_FQ_NAME + +class AddJvmDefaultAnnotation(declaration: KtCallableDeclaration) : KotlinQuickFixAction(declaration) { + override fun getText(): String = "Add '@JvmDefault' annotation" + + override fun getFamilyName(): String = text + + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + element?.addAnnotation(JVM_DEFAULT_FQ_NAME) + } + + companion object : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val psiElement = diagnostic.psiElement + if (psiElement is KtNamedFunction || psiElement is KtProperty) + return AddJvmDefaultAnnotation(psiElement as KtCallableDeclaration) + return null + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index a21c6710c34..69c04777db3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -519,5 +519,8 @@ class QuickFixRegistrar : QuickFixContributor { ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION.registerFactory(SurroundWithArrayOfWithSpreadOperatorInFunctionFix) JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE.registerFactory(KotlinAddRequiredModuleFix) + + JVM_DEFAULT_REQUIRED_FOR_OVERRIDE.registerFactory(AddJvmDefaultAnnotation) + NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT.registerFactory(AddJvmDefaultAnnotation) } } diff --git a/idea/testData/quickfix/addJvmDefault/functionOverride.kt b/idea/testData/quickfix/addJvmDefault/functionOverride.kt new file mode 100644 index 00000000000..73f343240ef --- /dev/null +++ b/idea/testData/quickfix/addJvmDefault/functionOverride.kt @@ -0,0 +1,16 @@ +// "Add '@JvmDefault' annotation" "true" +// JVM_TARGET: 1.8 +// COMPILER_ARGUMENTS: -Xenable-jvm-default +// WITH_RUNTIME +interface Foo { + @JvmDefault + fun foo() { + + } +} +interface Bar: Foo { + + override fun foo() { + + } +} diff --git a/idea/testData/quickfix/addJvmDefault/functionOverride.kt.after b/idea/testData/quickfix/addJvmDefault/functionOverride.kt.after new file mode 100644 index 00000000000..8eb245d87ce --- /dev/null +++ b/idea/testData/quickfix/addJvmDefault/functionOverride.kt.after @@ -0,0 +1,17 @@ +// "Add '@JvmDefault' annotation" "true" +// JVM_TARGET: 1.8 +// COMPILER_ARGUMENTS: -Xenable-jvm-default +// WITH_RUNTIME +interface Foo { + @JvmDefault + fun foo() { + + } +} +interface Bar: Foo { + + @JvmDefault + override fun foo() { + + } +} diff --git a/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.after.kt b/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.after.kt new file mode 100644 index 00000000000..582a272a4e1 --- /dev/null +++ b/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.after.kt @@ -0,0 +1,9 @@ +// "Add '@JvmDefault' annotation" "true" +// COMPILER_ARGUMENTS: -Xenable-jvm-default +// WITH_RUNTIME +interface Bar : Foo { + @JvmDefault + override fun foo() { + + } +} diff --git a/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Dependency.java b/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Dependency.java new file mode 100644 index 00000000000..b723022dc74 --- /dev/null +++ b/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Dependency.java @@ -0,0 +1,3 @@ +public interface Foo { + default void foo() {} +} diff --git a/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Main.kt b/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Main.kt new file mode 100644 index 00000000000..e8957dcf1c0 --- /dev/null +++ b/idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Main.kt @@ -0,0 +1,8 @@ +// "Add '@JvmDefault' annotation" "true" +// COMPILER_ARGUMENTS: -Xenable-jvm-default +// WITH_RUNTIME +interface Bar : Foo { + override fun foo() { + + } +} diff --git a/idea/testData/quickfix/addJvmDefault/propertyOverride.kt b/idea/testData/quickfix/addJvmDefault/propertyOverride.kt new file mode 100644 index 00000000000..7984fc858bf --- /dev/null +++ b/idea/testData/quickfix/addJvmDefault/propertyOverride.kt @@ -0,0 +1,14 @@ +// "Add '@JvmDefault' annotation" "true" +// JVM_TARGET: 1.8 +// COMPILER_ARGUMENTS: -Xenable-jvm-default +// WITH_RUNTIME +interface Foo { + @JvmDefault + val foo: String + get() = "" +} +interface Bar: Foo { + + override val foo: String + get() = "" +} diff --git a/idea/testData/quickfix/addJvmDefault/propertyOverride.kt.after b/idea/testData/quickfix/addJvmDefault/propertyOverride.kt.after new file mode 100644 index 00000000000..d9002b4b174 --- /dev/null +++ b/idea/testData/quickfix/addJvmDefault/propertyOverride.kt.after @@ -0,0 +1,15 @@ +// "Add '@JvmDefault' annotation" "true" +// JVM_TARGET: 1.8 +// COMPILER_ARGUMENTS: -Xenable-jvm-default +// WITH_RUNTIME +interface Foo { + @JvmDefault + val foo: String + get() = "" +} +interface Bar: Foo { + + @JvmDefault + override val foo: String + get() = "" +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index 64950337fc5..516c764cefe 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -25,6 +25,21 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true); } + @TestMetadata("idea/testData/quickfix/addJvmDefault") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AddJvmDefault extends AbstractQuickFixMultiFileTest { + public void testAllFilesPresentInAddJvmDefault() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addJvmDefault"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true); + } + + @TestMetadata("javaDefaultOverride.before.Main.kt") + public void testJavaDefaultOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/addJvmDefault/javaDefaultOverride.before.Main.kt"); + doTestWithExtraFile(fileName); + } + } + @TestMetadata("idea/testData/quickfix/addStarProjections") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index b06b3312dc0..4477a797e22 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -754,6 +754,27 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/addJvmDefault") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AddJvmDefault extends AbstractQuickFixTest { + public void testAllFilesPresentInAddJvmDefault() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addJvmDefault"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("functionOverride.kt") + public void testFunctionOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/addJvmDefault/functionOverride.kt"); + doTest(fileName); + } + + @TestMetadata("propertyOverride.kt") + public void testPropertyOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/addJvmDefault/propertyOverride.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/addNewLineAfterAnnotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)