[kotlin] INVISIBLE_MEMBER quickfix: remove redundant primary constructor

^KTIJ-28872 Fixed

GitOrigin-RevId: 3c149e5964e2a04541f8a641cdb48b0e0d71502d
This commit is contained in:
Alexey Belkov
2024-02-22 20:37:48 +00:00
committed by intellij-monorepo-bot
parent 4a7a6d24d5
commit 669b5084c8
6 changed files with 55 additions and 23 deletions
@@ -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<PsiElement> =
sequence {
suspend fun SequenceScope<PsiElement>.visit(element: PsiElement) {
@@ -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<KtPrimaryConstructor>(
@@ -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()
}
@@ -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()
}
}
}
}
@@ -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");
@@ -0,0 +1,9 @@
// "Make '<init>' public" "true"
private class Marker private constructor()
fun foo(): Any {
return <caret>Marker()
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ChangeVisibilityFix$ChangeToPublicFix
@@ -0,0 +1,9 @@
// "Make '<init>' public" "true"
private class Marker
fun foo(): Any {
return Marker()
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ChangeVisibilityFix$ChangeToPublicFix