From 75e8849c94cfbd196c2a9d63848886717f153098 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Tue, 22 Oct 2019 23:31:21 +0900 Subject: [PATCH] Add quick fix for INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER #KT-34533 Fixed --- .../src/org/jetbrains/kotlin/psi/KtClass.kt | 1 + .../messages/KotlinBundle.properties | 1 + .../AddValVarToConstructorParameterAction.kt | 12 +++++++--- ...eClassConstructorNotValParameterFactory.kt | 21 +++++++++++++++++ .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 2 ++ .../addValOrVar/expectInlineClass.kt | 1 + .../addValOrVar/expectInlineClass.kt.after | 2 -- .../basic.kt | 2 ++ .../basic.kt.after | 2 ++ .../var.kt | 2 ++ .../var.kt.after | 2 ++ .../QuickFixMultiFileTestGenerated.java | 13 +++++++++++ .../idea/quickfix/QuickFixTestGenerated.java | 23 +++++++++++++++++++ 13 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/quickfix/InlineClassConstructorNotValParameterFactory.kt delete mode 100644 idea/testData/intentions/addValOrVar/expectInlineClass.kt.after create mode 100644 idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt create mode 100644 idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt.after create mode 100644 idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt create mode 100644 idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt.after diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtClass.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtClass.kt index 7ca970386d0..958f66636c1 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtClass.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtClass.kt @@ -34,6 +34,7 @@ open class KtClass : KtClassOrObject { fun isData(): Boolean = hasModifier(KtTokens.DATA_KEYWORD) fun isSealed(): Boolean = hasModifier(KtTokens.SEALED_KEYWORD) fun isInner(): Boolean = hasModifier(KtTokens.INNER_KEYWORD) + fun isInline(): Boolean = hasModifier(KtTokens.INLINE_KEYWORD) override fun getCompanionObjects(): List = body?.allCompanionObjects.orEmpty() diff --git a/idea/resources-en/messages/KotlinBundle.properties b/idea/resources-en/messages/KotlinBundle.properties index 5862400902d..9fc65d6f82d 100644 --- a/idea/resources-en/messages/KotlinBundle.properties +++ b/idea/resources-en/messages/KotlinBundle.properties @@ -1583,6 +1583,7 @@ looking.for.usages.in.java.files=Looking for usages in Java files... add.return.at.0=Add return@{0} add.0.to.argument=Add ''{0} ='' to argument add.val.var.to.parameter.0=Add val/var to parameter ''{0}'' +add.val.to.parameter.0=Add val to parameter ''{0}'' add.val.var.to.primary.constructor.parameter=Add val/var to primary constructor parameter make.primary.constructor.0=Make primary constructor {0} change.visibility.modifier=Change visibility modifier diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/AddValVarToConstructorParameterAction.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/AddValVarToConstructorParameterAction.kt index ea1d6e5ee81..21b47ffcd30 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/AddValVarToConstructorParameterAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/AddValVarToConstructorParameterAction.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.idea.refactoring.ValVarExpression import org.jetbrains.kotlin.idea.util.isExpectDeclaration import org.jetbrains.kotlin.idea.util.mustHaveValOrVar import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.containingClass import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.startOffset @@ -33,7 +34,7 @@ interface AddValVarToConstructorParameterAction { element.addBefore(KtPsiFactory(project).createValKeyword(), element.nameIdentifier) - if (editor == null) return + if (element.containingClass()?.isInline() == true || editor == null) return val parameter = element.createSmartPointer().let { PsiDocumentManager.getInstance(project).commitAllDocuments() @@ -55,7 +56,8 @@ interface AddValVarToConstructorParameterAction { ), AddValVarToConstructorParameterAction { override fun applicabilityRange(element: KtParameter): TextRange? { if (!canInvoke(element)) return null - if (element.getStrictParentOfType()?.isData() == true) return null + val containingClass = element.getStrictParentOfType() + if (containingClass?.isData() == true || containingClass?.isInline() == true) return null setTextGetter(KotlinBundle.lazyMessage("add.val.var.to.parameter.0", element.name ?: "")) return element.nameIdentifier?.textRange } @@ -66,7 +68,11 @@ interface AddValVarToConstructorParameterAction { class QuickFix(parameter: KtParameter) : KotlinQuickFixAction(parameter), AddValVarToConstructorParameterAction { - override fun getText() = element?.let { KotlinBundle.message("add.val.var.to.parameter.0", it.name ?: "") } ?: "" + override fun getText() = element?.let { + val key = + if (it.getStrictParentOfType()?.isInline() == true) "add.val.to.parameter.0" else "add.val.var.to.parameter.0" + KotlinBundle.message(key, it.name ?: "") + } ?: "" override fun getFamilyName() = KotlinBundle.message("add.val.var.to.primary.constructor.parameter") diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/InlineClassConstructorNotValParameterFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/InlineClassConstructorNotValParameterFactory.kt new file mode 100644 index 00000000000..1363dce1353 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/InlineClassConstructorNotValParameterFactory.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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 org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.idea.intentions.AddValVarToConstructorParameterAction + +object InlineClassConstructorNotValParameterFactory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val parameter = Errors.INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER.cast(diagnostic).psiElement + return if (parameter.isMutable) + ChangeVariableMutabilityFix(parameter, false) + else + AddValVarToConstructorParameterAction.QuickFix(parameter) + } +} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 56d1f0a05c5..0eae3e1e9d5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -658,5 +658,7 @@ class QuickFixRegistrar : QuickFixContributor { MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND.registerFactory(AddExceptionToThrowsFix) THROWS_LIST_EMPTY.registerFactory(RemoveAnnotationFix) INCOMPATIBLE_THROWS_OVERRIDE.registerFactory(RemoveAnnotationFix) + + INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER.registerFactory(InlineClassConstructorNotValParameterFactory) } } diff --git a/idea/testData/intentions/addValOrVar/expectInlineClass.kt b/idea/testData/intentions/addValOrVar/expectInlineClass.kt index 600964acb0e..484a6e36e9a 100644 --- a/idea/testData/intentions/addValOrVar/expectInlineClass.kt +++ b/idea/testData/intentions/addValOrVar/expectInlineClass.kt @@ -1,2 +1,3 @@ +// IS_APPLICABLE: false // DISABLE-ERRORS expect inline class A(a: Int) \ No newline at end of file diff --git a/idea/testData/intentions/addValOrVar/expectInlineClass.kt.after b/idea/testData/intentions/addValOrVar/expectInlineClass.kt.after deleted file mode 100644 index 0d291286c2f..00000000000 --- a/idea/testData/intentions/addValOrVar/expectInlineClass.kt.after +++ /dev/null @@ -1,2 +0,0 @@ -// DISABLE-ERRORS -expect inline class A(val a: Int) \ No newline at end of file diff --git a/idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt b/idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt new file mode 100644 index 00000000000..279bb6db5fe --- /dev/null +++ b/idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt @@ -0,0 +1,2 @@ +// "Add val to parameter 'x'" "true" +inline class Foo(x: Int) \ No newline at end of file diff --git a/idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt.after b/idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt.after new file mode 100644 index 00000000000..c9c873e62a5 --- /dev/null +++ b/idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt.after @@ -0,0 +1,2 @@ +// "Add val to parameter 'x'" "true" +inline class Foo(val x: Int) \ No newline at end of file diff --git a/idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt b/idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt new file mode 100644 index 00000000000..a6b3bea3e15 --- /dev/null +++ b/idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt @@ -0,0 +1,2 @@ +// "Change to val" "true" +inline class Foo(var x: Int) \ No newline at end of file diff --git a/idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt.after b/idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt.after new file mode 100644 index 00000000000..ec12364da82 --- /dev/null +++ b/idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt.after @@ -0,0 +1,2 @@ +// "Change to val" "true" +inline class Foo(val x: Int) \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index 2cffbc371d0..fe776afc307 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -3048,6 +3048,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes } } + @TestMetadata("idea/testData/quickfix/inlineClassConstructorNotValParameter") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InlineClassConstructorNotValParameter extends AbstractQuickFixMultiFileTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath); + } + + public void testAllFilesPresentInInlineClassConstructorNotValParameter() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/inlineClassConstructorNotValParameter"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), null, true); + } + } + @TestMetadata("idea/testData/quickfix/inlineTypeParameterFix") @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 5d3cb03e07b..2f0f35d6a3e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -8503,6 +8503,29 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/inlineClassConstructorNotValParameter") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InlineClassConstructorNotValParameter extends AbstractQuickFixTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInlineClassConstructorNotValParameter() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/inlineClassConstructorNotValParameter"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true); + } + + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + runTest("idea/testData/quickfix/inlineClassConstructorNotValParameter/basic.kt"); + } + + @TestMetadata("var.kt") + public void testVar() throws Exception { + runTest("idea/testData/quickfix/inlineClassConstructorNotValParameter/var.kt"); + } + } + @TestMetadata("idea/testData/quickfix/inlineTypeParameterFix") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)