MakeOverriddenMemberOpenFix: should update actual members
#KT-32586 Fixed
This commit is contained in:
@@ -97,7 +97,7 @@ private fun MemberDescriptor.isConstructorInActual(checkConstructor: Boolean) =
|
||||
private fun MemberDescriptor.isEnumEntryInActual() =
|
||||
(DescriptorUtils.isEnumEntry(this) && (containingDeclaration as? MemberDescriptor)?.isActual == true)
|
||||
|
||||
private fun DeclarationDescriptor.actualsForExpected(): Collection<DeclarationDescriptor> {
|
||||
fun DeclarationDescriptor.actualsForExpected(): Collection<DeclarationDescriptor> {
|
||||
if (this is MemberDescriptor) {
|
||||
if (!this.isExpect) return emptyList()
|
||||
|
||||
|
||||
@@ -13,12 +13,16 @@ import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.isOverridable
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.util.CachedValue
|
||||
import org.jetbrains.kotlin.idea.core.util.getValue
|
||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||
import org.jetbrains.kotlin.idea.util.actualsForExpected
|
||||
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.OPEN_KEYWORD
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
@@ -56,6 +60,17 @@ class MakeOverriddenMemberOpenFix(declaration: KtDeclaration) : KotlinQuickFixAc
|
||||
) {
|
||||
return QUICKFIX_UNAVAILABLE
|
||||
}
|
||||
|
||||
overriddenDescriptor.takeIf { overriddenMember.isExpectDeclaration() }?.actualsForExpected()?.forEach {
|
||||
if (it is MemberDescriptor && it.modality < Modality.OPEN) {
|
||||
val member = DescriptorToSourceUtils.descriptorToDeclaration(it)
|
||||
if (member == null || !member.canRefactor() || member !is KtCallableDeclaration) {
|
||||
return QUICKFIX_UNAVAILABLE
|
||||
}
|
||||
overriddenNonOverridableMembers.add(member.createSmartPointer())
|
||||
}
|
||||
}
|
||||
|
||||
val containingDeclarationName = overriddenDescriptor.containingDeclaration.name.asString()
|
||||
overriddenNonOverridableMembers.add(overriddenMember.createSmartPointer())
|
||||
containingDeclarationsNames.add(containingDeclarationName)
|
||||
@@ -69,7 +84,7 @@ class MakeOverriddenMemberOpenFix(declaration: KtDeclaration) : KotlinQuickFixAc
|
||||
|
||||
override fun getText(): String {
|
||||
val element = element ?: return ""
|
||||
if (overriddenNonOverridableMembers.size == 1) {
|
||||
if (containingDeclarationsNames.size == 1) {
|
||||
val name = containingDeclarationsNames[0] + "." + element.name
|
||||
return "Make $name $OPEN_KEYWORD"
|
||||
}
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
expect open class OClass() {
|
||||
val overrideMe: String
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
expect open class OClass() {
|
||||
val overrideMe: String
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Make OClass.overrideMe open" "true"
|
||||
|
||||
actual open class OClass actual constructor() {
|
||||
actual val overrideMe: String = ""
|
||||
}
|
||||
|
||||
class Another: OClass() {
|
||||
override<caret> val overrideMe = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make OClass.overrideMe open" "true"
|
||||
|
||||
actual open class OClass actual constructor() {
|
||||
actual open val overrideMe: String = ""
|
||||
}
|
||||
|
||||
class Another: OClass() {
|
||||
override val overrideMe = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make OClass.overrideMe open" "true"
|
||||
|
||||
expect open class OClass() {
|
||||
val overrideMe: String
|
||||
}
|
||||
|
||||
class Another: OClass() {
|
||||
override<caret> val overrideMe = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make OClass.overrideMe open" "true"
|
||||
|
||||
expect open class OClass() {
|
||||
open val overrideMe: String
|
||||
}
|
||||
|
||||
class Another: OClass() {
|
||||
override val overrideMe = ""
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
actual open class OClass actual constructor() {
|
||||
actual val overrideMe: String = ""
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
actual open class OClass actual constructor() {
|
||||
actual open val overrideMe: String = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make OClass.overrideMe open" "true"
|
||||
|
||||
expect open class OClass() {
|
||||
val overrideMe: String
|
||||
}
|
||||
|
||||
class Another: OClass() {
|
||||
override<caret> val overrideMe = ""
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
// "Make OClass.overrideMe open" "true"
|
||||
|
||||
expect open class OClass() {
|
||||
open val overrideMe: String
|
||||
}
|
||||
|
||||
class Another: OClass() {
|
||||
override val overrideMe = ""
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
actual abstract class OClass actual constructor() {
|
||||
actual abstract val overrideMe: String
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
actual abstract class OClass actual constructor() {
|
||||
actual abstract val overrideMe: String
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make OClass.overrideMe open" "true"
|
||||
|
||||
expect open class OClass() {
|
||||
val overrideMe: String
|
||||
}
|
||||
|
||||
class Another: OClass() {
|
||||
override<caret> val overrideMe = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make OClass.overrideMe open" "true"
|
||||
|
||||
expect open class OClass() {
|
||||
open val overrideMe: String
|
||||
}
|
||||
|
||||
class Another: OClass() {
|
||||
override val overrideMe = ""
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
actual open class OClass actual constructor() {
|
||||
actual open val overrideMe: String = ""
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
actual open class OClass actual constructor() {
|
||||
actual open val overrideMe: String = ""
|
||||
}
|
||||
+33
@@ -558,6 +558,39 @@ public class QuickFixMultiModuleTestGenerated extends AbstractQuickFixMultiModul
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/multiModuleQuickFix/makeOverridenMemberOpen")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class MakeOverridenMemberOpen extends AbstractQuickFixMultiModuleTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("actual")
|
||||
public void testActual() throws Exception {
|
||||
runTest("idea/testData/multiModuleQuickFix/makeOverridenMemberOpen/actual/");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInMakeOverridenMemberOpen() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/multiModuleQuickFix/makeOverridenMemberOpen"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("expect")
|
||||
public void testExpect() throws Exception {
|
||||
runTest("idea/testData/multiModuleQuickFix/makeOverridenMemberOpen/expect/");
|
||||
}
|
||||
|
||||
@TestMetadata("hasAbstract")
|
||||
public void testHasAbstract() throws Exception {
|
||||
runTest("idea/testData/multiModuleQuickFix/makeOverridenMemberOpen/hasAbstract/");
|
||||
}
|
||||
|
||||
@TestMetadata("hasOpen")
|
||||
public void testHasOpen() throws Exception {
|
||||
runTest("idea/testData/multiModuleQuickFix/makeOverridenMemberOpen/hasOpen/");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/multiModuleQuickFix/other")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user