Pull Up: Skip super members without explicit declarations
#KT-13124 Fixed
This commit is contained in:
@@ -269,6 +269,7 @@ Using 'this' as function argument in constructor of non-final class
|
|||||||
- [`KT-13240`](https://youtrack.jetbrains.com/issue/KT-13240) Rename: Do not report shadowing conflict if redeclaration is detected
|
- [`KT-13240`](https://youtrack.jetbrains.com/issue/KT-13240) Rename: Do not report shadowing conflict if redeclaration is detected
|
||||||
- [`KT-13253`](https://youtrack.jetbrains.com/issue/KT-13253) Rename: Report conflicts for constructor parameters
|
- [`KT-13253`](https://youtrack.jetbrains.com/issue/KT-13253) Rename: Report conflicts for constructor parameters
|
||||||
- [`KT-12971`](https://youtrack.jetbrains.com/issue/KT-12971) Push Down: Do not specifiy visibility on generated overriding members
|
- [`KT-12971`](https://youtrack.jetbrains.com/issue/KT-12971) Push Down: Do not specifiy visibility on generated overriding members
|
||||||
|
- [`KT-13124`](https://youtrack.jetbrains.com/issue/KT-13124) Pull Up: Skip super members without explicit declarations
|
||||||
|
|
||||||
##### New features
|
##### New features
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.refactoring.pullUp
|
|||||||
|
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
@@ -27,9 +28,11 @@ import org.jetbrains.kotlin.idea.core.ShortenReferences
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.allChildren
|
import org.jetbrains.kotlin.psi.psiUtil.allChildren
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForReceiver
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForReceiverOrThis
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForReceiverOrThis
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getExplicitReceiverValue
|
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getExplicitReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
@@ -53,8 +56,10 @@ fun markElements(
|
|||||||
private fun visitSuperOrThis(expression: KtInstanceExpressionWithLabel) {
|
private fun visitSuperOrThis(expression: KtInstanceExpressionWithLabel) {
|
||||||
if (targetClassDescriptor == null) return
|
if (targetClassDescriptor == null) return
|
||||||
|
|
||||||
val referenceTarget = context[BindingContext.REFERENCE_TARGET, expression.instanceReference]
|
val callee = expression.getQualifiedExpressionForReceiver()?.selectorExpression?.getCalleeExpressionIfAny() ?: return
|
||||||
if (referenceTarget == targetClassDescriptor) {
|
val calleeTarget = callee.getResolvedCall(context)?.resultingDescriptor ?: return
|
||||||
|
if ((calleeTarget as? CallableMemberDescriptor)?.kind != CallableMemberDescriptor.Kind.DECLARATION) return
|
||||||
|
if (calleeTarget.containingDeclaration == targetClassDescriptor) {
|
||||||
expression.replaceWithTargetThis = true
|
expression.replaceWithTargetThis = true
|
||||||
affectedElements.add(expression)
|
affectedElements.add(expression)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,13 +91,13 @@ private fun KotlinPullUpData.checkClashWithSuperDeclaration(
|
|||||||
member: KtNamedDeclaration,
|
member: KtNamedDeclaration,
|
||||||
memberDescriptor: DeclarationDescriptor,
|
memberDescriptor: DeclarationDescriptor,
|
||||||
conflicts: MultiMap<PsiElement, String>) {
|
conflicts: MultiMap<PsiElement, String>) {
|
||||||
if (memberDescriptor is CallableMemberDescriptor) {
|
if (memberDescriptor !is CallableMemberDescriptor) return
|
||||||
val clashingSuper = getClashingMemberInTargetClass(memberDescriptor)
|
|
||||||
if (clashingSuper != null && clashingSuper.modality != Modality.ABSTRACT) {
|
val clashingSuper = getClashingMemberInTargetClass(memberDescriptor) ?: return
|
||||||
val message = "${targetClassDescriptor.renderForConflicts()} already contains ${memberDescriptor.renderForConflicts()}"
|
if (clashingSuper.modality == Modality.ABSTRACT) return
|
||||||
conflicts.putValue(member, message.capitalize())
|
if (clashingSuper.kind != CallableMemberDescriptor.Kind.DECLARATION) return
|
||||||
}
|
val message = "${targetClassDescriptor.renderForConflicts()} already contains ${memberDescriptor.renderForConflicts()}"
|
||||||
}
|
conflicts.putValue(member, message.capitalize())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinPullUpData.checkAccidentalOverrides(
|
private fun KotlinPullUpData.checkAccidentalOverrides(
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// TARGET_CLASS: B
|
||||||
|
open class A {
|
||||||
|
open fun callSuper() {
|
||||||
|
// Something important
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B : A() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class <caret>C : B() {
|
||||||
|
// INFO: {"checked": "true"}
|
||||||
|
override fun callSuper() {
|
||||||
|
super.callSuper() // We simply call up to the base class
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// TARGET_CLASS: B
|
||||||
|
open class A {
|
||||||
|
open fun callSuper() {
|
||||||
|
// Something important
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B : A() {
|
||||||
|
// INFO: {"checked": "true"}
|
||||||
|
override fun callSuper() {
|
||||||
|
super.callSuper() // We simply call up to the base class
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : B() {
|
||||||
|
}
|
||||||
@@ -223,6 +223,12 @@ public class PullUpTestGenerated extends AbstractPullUpTest {
|
|||||||
doKotlinTest(fileName);
|
doKotlinTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("skipFakeOverrides.kt")
|
||||||
|
public void testSkipFakeOverrides() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/pullUp/k2k/skipFakeOverrides.kt");
|
||||||
|
doKotlinTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("spaceAfterModifier.kt")
|
@TestMetadata("spaceAfterModifier.kt")
|
||||||
public void testSpaceAfterModifier() throws Exception {
|
public void testSpaceAfterModifier() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/pullUp/k2k/spaceAfterModifier.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/pullUp/k2k/spaceAfterModifier.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user