ChangeVisibilityModifierIntention: should affect all actual/expect declarations
#KT-29737 Fixed
This commit is contained in:
@@ -145,4 +145,10 @@ fun KtDeclaration.runOnExpectAndAllActuals(checkExpect: Boolean = true, f: (KtDe
|
|||||||
} else if (!checkExpect || isExpectDeclaration()) {
|
} else if (!checkExpect || isExpectDeclaration()) {
|
||||||
actualsForExpected().forEach { f(it) }
|
actualsForExpected().forEach { f(it) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KtDeclaration.collectAllExpectAndActualDeclaration(): Set<KtDeclaration> = when {
|
||||||
|
isExpectDeclaration() -> actualsForExpected() + this
|
||||||
|
hasActualModifier() -> liftToExpected()?.let { it.actualsForExpected() + it }.orEmpty()
|
||||||
|
else -> emptySet()
|
||||||
}
|
}
|
||||||
@@ -23,17 +23,17 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.idea.core.*
|
import org.jetbrains.kotlin.idea.core.*
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
|
import org.jetbrains.kotlin.idea.util.collectAllExpectAndActualDeclaration
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.toVisibility
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
|
||||||
|
|
||||||
open class ChangeVisibilityModifierIntention protected constructor(
|
open class ChangeVisibilityModifierIntention protected constructor(
|
||||||
val modifier: KtModifierKeywordToken
|
val modifier: KtModifierKeywordToken
|
||||||
) : SelfTargetingRangeIntention<KtDeclaration>(KtDeclaration::class.java, "Make ${modifier.value}") {
|
) : SelfTargetingRangeIntention<KtDeclaration>(KtDeclaration::class.java, "Make ${modifier.value}") {
|
||||||
|
override fun startInWriteAction(): Boolean = false
|
||||||
|
|
||||||
override fun applicabilityRange(element: KtDeclaration): TextRange? {
|
override fun applicabilityRange(element: KtDeclaration): TextRange? {
|
||||||
val modifierList = element.modifierList
|
val modifierList = element.modifierList
|
||||||
@@ -46,11 +46,12 @@ open class ChangeVisibilityModifierIntention protected constructor(
|
|||||||
if (descriptor.visibility == targetVisibility) return null
|
if (descriptor.visibility == targetVisibility) return null
|
||||||
|
|
||||||
if (modifierList?.hasModifier(KtTokens.OVERRIDE_KEYWORD) == true) {
|
if (modifierList?.hasModifier(KtTokens.OVERRIDE_KEYWORD) == true) {
|
||||||
val callableDescriptor = descriptor as? CallableDescriptor ?: return null
|
val callableDescriptor = descriptor as? CallableDescriptor ?: return null
|
||||||
// cannot make visibility less than (or non-comparable with) any of the supers
|
// cannot make visibility less than (or non-comparable with) any of the supers
|
||||||
if (callableDescriptor.overriddenDescriptors
|
if (callableDescriptor.overriddenDescriptors
|
||||||
.map { Visibilities.compare(it.visibility, targetVisibility) }
|
.map { Visibilities.compare(it.visibility, targetVisibility) }
|
||||||
.any { it == null || it > 0 }) return null
|
.any { it == null || it > 0 }
|
||||||
|
) return null
|
||||||
}
|
}
|
||||||
|
|
||||||
text = defaultText
|
text = defaultText
|
||||||
@@ -80,8 +81,21 @@ open class ChangeVisibilityModifierIntention protected constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: KtDeclaration, editor: Editor?) {
|
override fun applyTo(element: KtDeclaration, editor: Editor?) {
|
||||||
element.setVisibility(modifier)
|
val pointers = element.collectAllExpectAndActualDeclaration().map { it.createSmartPointer() }
|
||||||
if (element is KtPropertyAccessor) element.modifierList?.nextSibling?.replace(KtPsiFactory(element).createWhiteSpace())
|
|
||||||
|
val project = element.project
|
||||||
|
val factory = KtPsiFactory(project)
|
||||||
|
project.executeWriteCommand("Change visibility modifier") {
|
||||||
|
for (pointer in pointers) {
|
||||||
|
val declaration = pointer.element ?: continue
|
||||||
|
|
||||||
|
declaration.setVisibility(modifier)
|
||||||
|
if (declaration is KtPropertyAccessor) {
|
||||||
|
declaration.modifierList?.nextSibling?.replace(factory.createWhiteSpace())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun noModifierYetApplicabilityRange(declaration: KtDeclaration): TextRange? {
|
private fun noModifierYetApplicabilityRange(declaration: KtDeclaration): TextRange? {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// "Make internal" "true"
|
||||||
|
|
||||||
|
expect <caret>class Sample
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// "Make internal" "true"
|
||||||
|
|
||||||
|
internal expect <caret>class Sample
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
actual class Sample
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
internal actual class Sample
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
actual class Sample
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
internal actual class Sample
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
internal expect class Sample
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
expect class Sample
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// "Make public" "true"
|
||||||
|
|
||||||
|
internal actual c<caret>lass Sample
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// "Make public" "true"
|
||||||
|
|
||||||
|
actual c<caret>lass Sample
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
internal actual class Sample
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
actual class Sample
|
||||||
+23
@@ -209,6 +209,29 @@ public class QuickFixMultiModuleTestGenerated extends AbstractQuickFixMultiModul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/multiModuleQuickFix/changeModifier")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ChangeModifier extends AbstractQuickFixMultiModuleTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInChangeModifier() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/multiModuleQuickFix/changeModifier"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("internal")
|
||||||
|
public void testInternal() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/changeModifier/internal/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("public")
|
||||||
|
public void testPublic() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/changeModifier/public/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/multiModuleQuickFix/changeSignature")
|
@TestMetadata("idea/testData/multiModuleQuickFix/changeSignature")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user