diff --git a/plugins/kotlin/base/psi/src/org/jetbrains/kotlin/idea/base/psi/KotlinPsiUtils.kt b/plugins/kotlin/base/psi/src/org/jetbrains/kotlin/idea/base/psi/KotlinPsiUtils.kt index 72a4c62f97e1..815b4bc3c7eb 100644 --- a/plugins/kotlin/base/psi/src/org/jetbrains/kotlin/idea/base/psi/KotlinPsiUtils.kt +++ b/plugins/kotlin/base/psi/src/org/jetbrains/kotlin/idea/base/psi/KotlinPsiUtils.kt @@ -219,6 +219,19 @@ fun KtModifierListOwner.hasInlineModifier(): Boolean = fun KtPrimaryConstructor.mustHaveValOrVar(): Boolean = containingClass()?.mustHaveOnlyPropertiesInPrimaryConstructor() ?: false +fun KtPrimaryConstructor.isRedundant(): Boolean { + val containingClass = containingClass() ?: return false + return when { + valueParameters.isNotEmpty() -> false + annotations.isNotEmpty() -> false + modifierList?.text?.isBlank() == false -> false + isExpectDeclaration() -> false + containingClass.mustHaveNonEmptyPrimaryConstructor() -> false + containingClass.secondaryConstructors.isNotEmpty() -> false + else -> true + } +} + fun PsiElement.childrenDfsSequence(): Sequence = sequence { suspend fun SequenceScope.visit(element: PsiElement) { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveEmptyPrimaryConstructorIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveEmptyPrimaryConstructorIntention.kt index 42a8ad7577e4..aebbc3b4349e 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveEmptyPrimaryConstructorIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveEmptyPrimaryConstructorIntention.kt @@ -4,13 +4,11 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.codeInspection.CleanupLocalInspectionTool import com.intellij.openapi.editor.Editor -import org.jetbrains.kotlin.idea.base.psi.mustHaveNonEmptyPrimaryConstructor +import org.jetbrains.kotlin.idea.base.psi.isRedundant import org.jetbrains.kotlin.idea.base.resources.KotlinBundle -import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingOffsetIndependentIntention import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.IntentionBasedInspection -import org.jetbrains.kotlin.idea.util.isExpectDeclaration +import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingOffsetIndependentIntention import org.jetbrains.kotlin.psi.KtPrimaryConstructor -import org.jetbrains.kotlin.psi.psiUtil.containingClass @Suppress("DEPRECATION") class RemoveEmptyPrimaryConstructorInspection : IntentionBasedInspection( @@ -26,16 +24,6 @@ class RemoveEmptyPrimaryConstructorIntention : SelfTargetingOffsetIndependentInt element.delete() } - override fun isApplicableTo(element: KtPrimaryConstructor): Boolean { - val containingClass = element.containingClass() ?: return false - return when { - element.valueParameters.isNotEmpty() -> false - element.annotations.isNotEmpty() -> false - element.modifierList?.text?.isBlank() == false -> false - element.isExpectDeclaration() -> false - containingClass.mustHaveNonEmptyPrimaryConstructor() -> false - containingClass.secondaryConstructors.isNotEmpty() -> false - else -> true - } - } + override fun isApplicableTo(element: KtPrimaryConstructor): Boolean = + element.isRedundant() } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityFix.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityFix.kt index d1797670b353..ad0feb3fb226 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityFix.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityFix.kt @@ -13,18 +13,17 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0 import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings +import org.jetbrains.kotlin.idea.base.psi.isRedundant import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.KotlinQuickFixAction import org.jetbrains.kotlin.idea.codeinsight.utils.isRedundantSetter import org.jetbrains.kotlin.idea.codeinsight.utils.removeRedundantSetter import org.jetbrains.kotlin.idea.core.* +import org.jetbrains.kotlin.idea.intentions.RemoveEmptyPrimaryConstructorIntention import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor import org.jetbrains.kotlin.idea.util.runOnExpectAndAllActuals import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtModifierListOwner -import org.jetbrains.kotlin.psi.KtPropertyAccessor +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer import org.jetbrains.kotlin.resolve.ExposedVisibilityChecker @@ -49,9 +48,18 @@ open class ChangeVisibilityFix( originalElement?.setVisibility(visibilityModifier, addImplicitVisibilityModifier) } - val propertyAccessor = pointer?.element as? KtPropertyAccessor - if (propertyAccessor?.isRedundantSetter() == true) { - removeRedundantSetter(propertyAccessor) + when (val originalElementAfter = pointer?.element) { + is KtPropertyAccessor -> { + if (originalElementAfter.isRedundantSetter()) { + removeRedundantSetter(originalElementAfter) + } + } + + is KtPrimaryConstructor -> { + if (originalElementAfter.isRedundant()) { + originalElementAfter.delete() + } + } } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/K1QuickFixTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/K1QuickFixTestGenerated.java index 4fc611d7e022..da9b1203b5af 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/K1QuickFixTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/K1QuickFixTestGenerated.java @@ -9115,6 +9115,11 @@ public abstract class K1QuickFixTestGenerated extends AbstractK1QuickFixTest { runTest("testData/quickfix/increaseVisibility/overriddenProtectedMemberToPublicSingleFile.kt"); } + @TestMetadata("privateEmptyPrimaryConstructorToPublic.kt") + public void testPrivateEmptyPrimaryConstructorToPublic() throws Exception { + runTest("testData/quickfix/increaseVisibility/privateEmptyPrimaryConstructorToPublic.kt"); + } + @TestMetadata("privateInFileExposesPrivateInFile.kt") public void testPrivateInFileExposesPrivateInFile() throws Exception { runTest("testData/quickfix/increaseVisibility/privateInFileExposesPrivateInFile.kt"); diff --git a/plugins/kotlin/idea/tests/testData/quickfix/increaseVisibility/privateEmptyPrimaryConstructorToPublic.kt b/plugins/kotlin/idea/tests/testData/quickfix/increaseVisibility/privateEmptyPrimaryConstructorToPublic.kt new file mode 100644 index 000000000000..d0f4b869db0c --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/increaseVisibility/privateEmptyPrimaryConstructorToPublic.kt @@ -0,0 +1,9 @@ +// "Make '' public" "true" + +private class Marker private constructor() + +fun foo(): Any { + return Marker() +} + +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ChangeVisibilityFix$ChangeToPublicFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/increaseVisibility/privateEmptyPrimaryConstructorToPublic.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/increaseVisibility/privateEmptyPrimaryConstructorToPublic.kt.after new file mode 100644 index 000000000000..a3dafd1cc5ba --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/increaseVisibility/privateEmptyPrimaryConstructorToPublic.kt.after @@ -0,0 +1,9 @@ +// "Make '' public" "true" + +private class Marker + +fun foo(): Any { + return Marker() +} + +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ChangeVisibilityFix$ChangeToPublicFix \ No newline at end of file