From 76c2c2a5e9d478936109c6686d05ebea19660670 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Tue, 21 May 2019 18:11:08 +0700 Subject: [PATCH] Allow "Add val/var to primary constructor parameter" for inline & annotation classes Relates to #KT-29731 --- .../AddValVarToConstructorParameterAction.kt | 3 ++- .../expectactual/CreateExpectedFix.kt | 19 ++++++------------- .../kotlin/idea/util/expressionExt.kt | 8 +++++++- .../addValOrVar/expectAnnotation.kt | 2 ++ .../addValOrVar/expectAnnotation.kt.after | 2 ++ .../addValOrVar/expectInlineClass.kt | 2 ++ .../addValOrVar/expectInlineClass.kt.after | 2 ++ .../intentions/IntentionTestGenerated.java | 10 ++++++++++ 8 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 idea/testData/intentions/addValOrVar/expectAnnotation.kt create mode 100644 idea/testData/intentions/addValOrVar/expectAnnotation.kt.after create mode 100644 idea/testData/intentions/addValOrVar/expectInlineClass.kt create mode 100644 idea/testData/intentions/addValOrVar/expectInlineClass.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/AddValVarToConstructorParameterAction.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/AddValVarToConstructorParameterAction.kt index 18f74214e88..ddb3596c510 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/AddValVarToConstructorParameterAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/AddValVarToConstructorParameterAction.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory import org.jetbrains.kotlin.idea.refactoring.ValVarExpression +import org.jetbrains.kotlin.idea.util.allowedValOrVar import org.jetbrains.kotlin.idea.util.isExpectDeclaration import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer @@ -42,7 +43,7 @@ interface AddValVarToConstructorParameterAction { fun canInvoke(element: KtParameter): Boolean { return element.valOrVarKeyword == null && ((element.parent as? KtParameterList)?.parent as? KtPrimaryConstructor) - ?.takeUnless(KtDeclaration::isExpectDeclaration) != null + ?.takeIf { it.allowedValOrVar() || !it.isExpectDeclaration() } != null } fun invoke(element: KtParameter, editor: Editor?) { diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/CreateExpectedFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/CreateExpectedFix.kt index 363bd794f00..4de202ca5aa 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/CreateExpectedFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/expectactual/CreateExpectedFix.kt @@ -25,13 +25,12 @@ import org.jetbrains.kotlin.idea.core.overrideImplement.makeNotActual import org.jetbrains.kotlin.idea.core.toDescriptor import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory +import org.jetbrains.kotlin.idea.util.allowedValOrVar import org.jetbrains.kotlin.idea.util.application.executeWriteCommand -import org.jetbrains.kotlin.idea.util.hasInlineModifier import org.jetbrains.kotlin.idea.util.isEffectivelyActual import org.jetbrains.kotlin.idea.util.liftToExpected import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClass import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier @@ -197,17 +196,11 @@ private tailrec fun KtDeclaration.recursivelyMakeActual() { containingClassOrObject?.takeUnless(KtDeclaration::hasActualModifier)?.recursivelyMakeActual() } -private fun KtDeclaration.isAlwaysActual(): Boolean { - val primaryConstructor = when (this) { - is KtPrimaryConstructor -> this - is KtParameter -> (parent as? KtParameterList)?.parent as? KtPrimaryConstructor - else -> null - } ?: return false - - return primaryConstructor.containingClass()?.let { - it.isAnnotation() || it.hasInlineModifier() - } ?: false -} +private fun KtDeclaration.isAlwaysActual(): Boolean = when (this) { + is KtPrimaryConstructor -> this + is KtParameter -> (parent as? KtParameterList)?.parent as? KtPrimaryConstructor + else -> null +}?.allowedValOrVar() ?: false class CreateExpectedPropertyFix( property: KtNamedDeclaration, diff --git a/idea/src/org/jetbrains/kotlin/idea/util/expressionExt.kt b/idea/src/org/jetbrains/kotlin/idea/util/expressionExt.kt index ffd5fcdf8ea..2aee6ecee4e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/util/expressionExt.kt +++ b/idea/src/org/jetbrains/kotlin/idea/util/expressionExt.kt @@ -8,7 +8,9 @@ package org.jetbrains.kotlin.idea.util import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.psi.KtPrimaryConstructor import org.jetbrains.kotlin.psi.KtTypeArgumentList +import org.jetbrains.kotlin.psi.psiUtil.containingClass fun KtCallExpression.replaceOrCreateTypeArgumentList(newTypeArgumentList: KtTypeArgumentList) { @@ -19,4 +21,8 @@ fun KtCallExpression.replaceOrCreateTypeArgumentList(newTypeArgumentList: KtType ) } -fun KtModifierListOwner.hasInlineModifier() = hasModifier(KtTokens.INLINE_KEYWORD) \ No newline at end of file +fun KtModifierListOwner.hasInlineModifier() = hasModifier(KtTokens.INLINE_KEYWORD) + +fun KtPrimaryConstructor.allowedValOrVar(): Boolean = containingClass()?.let { + it.isAnnotation() || it.hasInlineModifier() +} ?: false \ No newline at end of file diff --git a/idea/testData/intentions/addValOrVar/expectAnnotation.kt b/idea/testData/intentions/addValOrVar/expectAnnotation.kt new file mode 100644 index 00000000000..6c12c31171b --- /dev/null +++ b/idea/testData/intentions/addValOrVar/expectAnnotation.kt @@ -0,0 +1,2 @@ +// DISABLE-ERRORS +expect annotation class A(a: Int) \ No newline at end of file diff --git a/idea/testData/intentions/addValOrVar/expectAnnotation.kt.after b/idea/testData/intentions/addValOrVar/expectAnnotation.kt.after new file mode 100644 index 00000000000..9c42beb355b --- /dev/null +++ b/idea/testData/intentions/addValOrVar/expectAnnotation.kt.after @@ -0,0 +1,2 @@ +// DISABLE-ERRORS +expect annotation class A(val a: Int) \ No newline at end of file diff --git a/idea/testData/intentions/addValOrVar/expectInlineClass.kt b/idea/testData/intentions/addValOrVar/expectInlineClass.kt new file mode 100644 index 00000000000..600964acb0e --- /dev/null +++ b/idea/testData/intentions/addValOrVar/expectInlineClass.kt @@ -0,0 +1,2 @@ +// 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 new file mode 100644 index 00000000000..0d291286c2f --- /dev/null +++ b/idea/testData/intentions/addValOrVar/expectInlineClass.kt.after @@ -0,0 +1,2 @@ +// DISABLE-ERRORS +expect inline class A(val a: Int) \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index fc86aa9388f..1f7ae7cfefd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -1931,6 +1931,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/addValOrVar/dataClass.kt"); } + @TestMetadata("expectAnnotation.kt") + public void testExpectAnnotation() throws Exception { + runTest("idea/testData/intentions/addValOrVar/expectAnnotation.kt"); + } + @TestMetadata("expectClass.kt") public void testExpectClass() throws Exception { runTest("idea/testData/intentions/addValOrVar/expectClass.kt"); @@ -1941,6 +1946,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/addValOrVar/expectClass2.kt"); } + @TestMetadata("expectInlineClass.kt") + public void testExpectInlineClass() throws Exception { + runTest("idea/testData/intentions/addValOrVar/expectInlineClass.kt"); + } + @TestMetadata("funParameter.kt") public void testFunParameter() throws Exception { runTest("idea/testData/intentions/addValOrVar/funParameter.kt");