From 666c2414797633349c40c8fc63870df88a42a204 Mon Sep 17 00:00:00 2001 From: Andrius Semionovas Date: Mon, 7 Aug 2017 12:53:37 +0300 Subject: [PATCH] KT-19126 Add convert property initializer to getter in interfaces (#1224) --- .../org/jetbrains/kotlin/psi/KtPsiFactory.kt | 9 +++++ ...ertPropertyInitializerToGetterIntention.kt | 15 ++++++++- .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 3 +- .../convertPropertyInitializerToGetter/val.kt | 7 ++++ .../val.kt.after | 8 +++++ .../convertPropertyInitializerToGetter/var.kt | 8 +++++ .../var.kt.after | 10 ++++++ .../varWithSetter.kt | 11 +++++++ .../varWithSetter.kt.after | 12 +++++++ .../baseCaseVar.kt | 3 ++ .../baseCaseVar.kt.after | 5 +++ .../idea/quickfix/QuickFixTestGenerated.java | 33 +++++++++++++++++++ 12 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt create mode 100644 idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt.after create mode 100644 idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt create mode 100644 idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt.after create mode 100644 idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt create mode 100644 idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt.after create mode 100644 idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt create mode 100644 idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt index 3a65aa73916..2d48f5a7a74 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt @@ -261,6 +261,15 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m return getter } + fun createPropertySetter(expression: KtExpression): KtPropertyAccessor { + val property = createProperty("val x get() = 1\nset(value) = TODO()") + val setter = property.setter!! + val bodyExpression = setter.bodyExpression!! + + bodyExpression.replace(expression) + return setter + } + fun createDestructuringDeclaration(text: String): KtDestructuringDeclaration { return (createFunction("fun foo() {$text}").bodyExpression as KtBlockExpression).statements.first() as KtDestructuringDeclaration } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyInitializerToGetterIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyInitializerToGetterIntention.kt index 2d23ea5342c..c1653429ccd 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyInitializerToGetterIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyInitializerToGetterIntention.kt @@ -16,9 +16,12 @@ package org.jetbrains.kotlin.idea.intentions +import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtPsiFactory @@ -43,7 +46,11 @@ class ConvertPropertyInitializerToGetterIntention : SelfTargetingRangeIntention< convertPropertyInitializerToGetter(element, editor) } - companion object { + companion object : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + return ConvertPropertyInitializerToGetterIntention() + } + fun convertPropertyInitializerToGetter(property: KtProperty, editor: Editor?) { val type = SpecifyTypeExplicitlyIntention.getTypeForDeclaration(property) SpecifyTypeExplicitlyIntention.addTypeAnnotation(editor, property, type) @@ -55,6 +62,12 @@ class ConvertPropertyInitializerToGetterIntention : SelfTargetingRangeIntention< if (setter != null) { property.addBefore(getter, setter) } + else if (property.isVar) { + property.add(getter) + val notImplemented = KtPsiFactory(property).createExpression("TODO()") + val notImplementedSetter = KtPsiFactory(property).createPropertySetter(notImplemented) + property.add(notImplementedSetter) + } else { property.add(getter) } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index b046551dda3..3884b9dcea8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementAsConstructorPa import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler import org.jetbrains.kotlin.idea.inspections.* import org.jetbrains.kotlin.idea.intentions.AddValVarToConstructorParameterAction +import org.jetbrains.kotlin.idea.intentions.ConvertPropertyInitializerToGetterIntention import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.* import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.CreateClassFromCallWithConstructorCalleeActionFactory import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.CreateClassFromConstructorCallActionFactory @@ -69,7 +70,7 @@ class QuickFixRegistrar : QuickFixContributor { ABSTRACT_PROPERTY_WITH_GETTER.registerFactory(removeAbstractModifierFactory, removePartsFromPropertyFactory) ABSTRACT_PROPERTY_WITH_SETTER.registerFactory(removeAbstractModifierFactory, removePartsFromPropertyFactory) - PROPERTY_INITIALIZER_IN_INTERFACE.registerFactory(removePartsFromPropertyFactory) + PROPERTY_INITIALIZER_IN_INTERFACE.registerFactory(removePartsFromPropertyFactory, ConvertPropertyInitializerToGetterIntention) MUST_BE_INITIALIZED_OR_BE_ABSTRACT.registerFactory(addAbstractModifierFactory) ABSTRACT_MEMBER_NOT_IMPLEMENTED.registerFactory(addAbstractModifierFactory) diff --git a/idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt b/idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt new file mode 100644 index 00000000000..0cd4e1793f9 --- /dev/null +++ b/idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt @@ -0,0 +1,7 @@ +// "Convert property initializer to getter" "true" + +fun String.foo() = "bar" + +interface A { + val name = "The quick brown fox jumps over the lazy dog".foo() +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt.after b/idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt.after new file mode 100644 index 00000000000..35291850dee --- /dev/null +++ b/idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt.after @@ -0,0 +1,8 @@ +// "Convert property initializer to getter" "true" + +fun String.foo() = "bar" + +interface A { + val name: String + get() = "The quick brown fox jumps over the lazy dog".foo() +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt b/idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt new file mode 100644 index 00000000000..ef75832f170 --- /dev/null +++ b/idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt @@ -0,0 +1,8 @@ +// "Convert property initializer to getter" "true" +// WITH_RUNTIME + +fun String.foo() = "bar" + +interface A { + var name = "The quick brown fox jumps over the lazy dog".foo() +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt.after b/idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt.after new file mode 100644 index 00000000000..1656e023396 --- /dev/null +++ b/idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt.after @@ -0,0 +1,10 @@ +// "Convert property initializer to getter" "true" +// WITH_RUNTIME + +fun String.foo() = "bar" + +interface A { + var name: String + get() = "The quick brown fox jumps over the lazy dog".foo() + set(value) = TODO() +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt b/idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt new file mode 100644 index 00000000000..5b661867dbf --- /dev/null +++ b/idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt @@ -0,0 +1,11 @@ +// "Convert property initializer to getter" "true" + +fun String.foo() = "bar" +fun nop() { + +} + +interface A { + var name = "The quick brown fox jumps over the lazy dog".foo() + set(value) = nop() +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt.after b/idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt.after new file mode 100644 index 00000000000..402ede9b739 --- /dev/null +++ b/idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt.after @@ -0,0 +1,12 @@ +// "Convert property initializer to getter" "true" + +fun String.foo() = "bar" +fun nop() { + +} + +interface A { + var name: String + get() = "The quick brown fox jumps over the lazy dog".foo() + set(value) = nop() +} \ No newline at end of file diff --git a/idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt b/idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt new file mode 100644 index 00000000000..c0682b82b71 --- /dev/null +++ b/idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt @@ -0,0 +1,3 @@ +// "Convert extension property initializer to getter" "true" +// WITH_RUNTIME +var String.foo: Int = 0 \ No newline at end of file diff --git a/idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt.after b/idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt.after new file mode 100644 index 00000000000..d870d3f4bd0 --- /dev/null +++ b/idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt.after @@ -0,0 +1,5 @@ +// "Convert extension property initializer to getter" "true" +// WITH_RUNTIME +var String.foo: Int + get() = 0 + set(value) = TODO() \ 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 0276ae2e96d..bfbb6670bf7 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -1422,6 +1422,33 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/convertPropertyInitializerToGetter") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ConvertPropertyInitializerToGetter extends AbstractQuickFixTest { + public void testAllFilesPresentInConvertPropertyInitializerToGetter() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/convertPropertyInitializerToGetter"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("val.kt") + public void testVal() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/convertPropertyInitializerToGetter/val.kt"); + doTest(fileName); + } + + @TestMetadata("var.kt") + public void testVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/convertPropertyInitializerToGetter/var.kt"); + doTest(fileName); + } + + @TestMetadata("varWithSetter.kt") + public void testVarWithSetter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/convertPropertyInitializerToGetter/varWithSetter.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/createFromUsage") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -8287,6 +8314,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("baseCaseVar.kt") + public void testBaseCaseVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseVar.kt"); + doTest(fileName); + } + @TestMetadata("baseCaseWithoutTypeAnnotation.kt") public void testBaseCaseWithoutTypeAnnotation() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/properties/extensionPropertyInitializerToGetter/baseCaseWithoutTypeAnnotation.kt");