From 2427406a8f517dc2687b0baec5c3bc37629d8143 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Fri, 1 Jun 2018 05:21:10 +0300 Subject: [PATCH] Add 'Change to val' quickfix for delegates without setValue So #KT-13688 Fixed --- .../quickfix/ChangeVariableMutabilityFix.kt | 18 +++++++++++++++--- .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 1 + .../canBeVal/delegatedProperty.kt | 12 ++++++++++++ .../canBeVal/delegatedProperty.kt.after | 12 ++++++++++++ .../canBeVal/delegatedProperty2.kt | 14 ++++++++++++++ .../canBeVal/delegatedProperty3.kt | 12 ++++++++++++ .../idea/quickfix/QuickFixTestGenerated.java | 15 +++++++++++++++ 7 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt create mode 100644 idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt.after create mode 100644 idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty2.kt create mode 100644 idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty3.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableMutabilityFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableMutabilityFix.kt index 72b417ab00e..aa4778b3da7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableMutabilityFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableMutabilityFix.kt @@ -23,18 +23,20 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1 import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.lexer.KtToken +import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreatePropertyDelegateAccessorsActionFactory import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.util.OperatorNameConventions class ChangeVariableMutabilityFix( element: KtValVarKeywordOwner, - private val makeVar: Boolean + private val makeVar: Boolean, + private val actionText: String? = null ) : KotlinQuickFixAction(element) { - override fun getText() = if (makeVar) "Make variable mutable" else "Make variable immutable" + override fun getText() = actionText ?: if (makeVar) "Make variable mutable" else "Make variable immutable" override fun getFamilyName(): String = text @@ -108,5 +110,15 @@ class ChangeVariableMutabilityFix( return ChangeVariableMutabilityFix(property, makeVar = false) } } + + val DELEGATED_PROPERTY_VAL_FACTORY = object : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val element = Errors.DELEGATE_SPECIAL_FUNCTION_MISSING.cast(diagnostic).psiElement + val property = element.getStrictParentOfType() ?: return null + val info = CreatePropertyDelegateAccessorsActionFactory.extractFixData(property, diagnostic).singleOrNull() ?: return null + if (info.name != OperatorNameConventions.SET_VALUE.asString()) return null + return ChangeVariableMutabilityFix(property, makeVar = false, actionText = "Change to val") + } + } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index b8c3fe87375..0d1a145b3b3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -386,6 +386,7 @@ class QuickFixRegistrar : QuickFixContributor { CreateDataClassPropertyFromDestructuringActionFactory ) + DELEGATE_SPECIAL_FUNCTION_MISSING.registerFactory(ChangeVariableMutabilityFix.DELEGATED_PROPERTY_VAL_FACTORY) DELEGATE_SPECIAL_FUNCTION_MISSING.registerFactory(CreatePropertyDelegateAccessorsActionFactory) DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE.registerFactory(CreatePropertyDelegateAccessorsActionFactory) diff --git a/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt b/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt new file mode 100644 index 00000000000..de55239102a --- /dev/null +++ b/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt @@ -0,0 +1,12 @@ +// "Change to val" "true" +import kotlin.reflect.KProperty + +fun test() { + var foo: String by Delegate() +} + +class Delegate { + operator fun getValue(thisRef: Any?, property: KProperty<*>): String { + return "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt.after b/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt.after new file mode 100644 index 00000000000..890e65269ca --- /dev/null +++ b/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt.after @@ -0,0 +1,12 @@ +// "Change to val" "true" +import kotlin.reflect.KProperty + +fun test() { + val foo: String by Delegate() +} + +class Delegate { + operator fun getValue(thisRef: Any?, property: KProperty<*>): String { + return "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty2.kt b/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty2.kt new file mode 100644 index 00000000000..eb8bbf44fba --- /dev/null +++ b/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty2.kt @@ -0,0 +1,14 @@ +// "Change to val" "false" +// ACTION: Create extension function 'Delegate.getValue' +// ACTION: Create member function 'Delegate.getValue' +// ERROR: Missing 'getValue(Nothing?, KProperty<*>)' method on delegate of type 'Delegate' +import kotlin.reflect.KProperty + +fun test() { + var foo: String by Delegate() +} + +class Delegate { + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty3.kt b/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty3.kt new file mode 100644 index 00000000000..fc7f16db9b5 --- /dev/null +++ b/idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty3.kt @@ -0,0 +1,12 @@ +// "Change to val" "false" +// ACTION: Create extension function 'Delegate.getValue', function 'Delegate.setValue' +// ACTION: Create member function 'Delegate.getValue', function 'Delegate.setValue' +// ERROR: Missing 'getValue(Nothing?, KProperty<*>)' method on delegate of type 'Delegate' +// ERROR: Missing 'setValue(Nothing?, KProperty<*>, String)' method on delegate of type 'Delegate' +import kotlin.reflect.KProperty + +fun test() { + var foo: String by Delegate() +} + +class Delegate \ 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 40d56e325e1..fab58bffd92 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -12085,6 +12085,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/variables/changeMutability/canBeVal/const.kt"); } + @TestMetadata("delegatedProperty.kt") + public void testDelegatedProperty() throws Exception { + runTest("idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty.kt"); + } + + @TestMetadata("delegatedProperty2.kt") + public void testDelegatedProperty2() throws Exception { + runTest("idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty2.kt"); + } + + @TestMetadata("delegatedProperty3.kt") + public void testDelegatedProperty3() throws Exception { + runTest("idea/testData/quickfix/variables/changeMutability/canBeVal/delegatedProperty3.kt"); + } + @TestMetadata("multiVariable.kt") public void testMultiVariable() throws Exception { runTest("idea/testData/quickfix/variables/changeMutability/canBeVal/multiVariable.kt");