Fix 'Redundant override' when delegated member hides super type override
So #KT-20231 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
3daee25ce8
commit
bbb571260b
+29
-1
@@ -19,11 +19,17 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
import com.intellij.codeInspection.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
|
||||
class KotlinRedundantOverrideInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool {
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) =
|
||||
@@ -59,6 +65,7 @@ class KotlinRedundantOverrideInspection : AbstractKotlinInspection(), CleanupLoc
|
||||
val superCallElement = qualifiedExpression.selectorExpression as? KtCallElement ?: return
|
||||
if (!isSameFunctionName(superCallElement, function)) return
|
||||
if (!isSameArguments(superCallElement, function)) return
|
||||
if (function.isDefinedInDelegatedSuperType(qualifiedExpression)) return
|
||||
|
||||
val descriptor = holder.manager.createProblemDescriptor(
|
||||
function,
|
||||
@@ -98,4 +105,25 @@ class KotlinRedundantOverrideInspection : AbstractKotlinInspection(), CleanupLoc
|
||||
companion object {
|
||||
private val MODIFIER_EXCLUDE_OVERRIDE = KtTokens.MODIFIER_KEYWORDS_ARRAY.asList() - KtTokens.OVERRIDE_KEYWORD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtNamedFunction.isDefinedInDelegatedSuperType(superQualifiedExpression: KtDotQualifiedExpression): Boolean {
|
||||
val delegatedSuperTypeEntries =
|
||||
containingClassOrObject?.superTypeListEntries?.filterIsInstance<KtDelegatedSuperTypeEntry>() ?: return false
|
||||
if (delegatedSuperTypeEntries.isEmpty()) return false
|
||||
|
||||
val context = superQualifiedExpression.analyze()
|
||||
val delegatedSuperTypes = delegatedSuperTypeEntries.mapNotNull { entry ->
|
||||
context[BindingContext.TYPE, entry.typeReference]
|
||||
}
|
||||
|
||||
val superResolvedCall = superQualifiedExpression.getResolvedCall(context) ?: return false
|
||||
val superCallResolvedDescriptor = superResolvedCall.resultingDescriptor
|
||||
val superCallResolvedReceiverTypes = superCallResolvedDescriptor.overriddenDescriptors.mapNotNull { it.dispatchReceiverParameter?.type }
|
||||
|
||||
return delegatedSuperTypes.any { delegatedSuperType ->
|
||||
superCallResolvedReceiverTypes.any { superCallReceiverType ->
|
||||
delegatedSuperType.isSubtypeOf(superCallReceiverType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// PROBLEM: none
|
||||
interface Foo {
|
||||
fun test(arg: String)
|
||||
}
|
||||
|
||||
open class Bar : Foo {
|
||||
override fun test(arg: String) {}
|
||||
open fun test(a: Int) {}
|
||||
open fun test2() {}
|
||||
}
|
||||
|
||||
class Baz(val foo: Foo) : Bar(), Foo by foo {
|
||||
override <caret>fun test(arg: String) = super.test(arg)
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// PROBLEM: none
|
||||
interface A
|
||||
|
||||
interface B {
|
||||
fun test(arg: String)
|
||||
}
|
||||
|
||||
interface Foo : A, B
|
||||
|
||||
open class Bar : Foo {
|
||||
override fun test(arg: String) {}
|
||||
open fun test(a: Int) {}
|
||||
open fun test2() {}
|
||||
}
|
||||
|
||||
class Baz(val foo: Foo) : Bar(), Foo by foo {
|
||||
override <caret>fun test(arg: String) = super.test(arg)
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
interface Foo {
|
||||
fun test(arg: Int)
|
||||
}
|
||||
|
||||
open class Bar : Foo {
|
||||
override fun test(arg: Int) {}
|
||||
open fun test(a: String) {}
|
||||
open fun test2() {}
|
||||
}
|
||||
|
||||
class Baz(val foo: Foo) : Bar(), Foo by foo {
|
||||
override <caret>fun test(a: String) = super.test(a)
|
||||
}
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
interface Foo {
|
||||
fun test(arg: Int)
|
||||
}
|
||||
|
||||
open class Bar : Foo {
|
||||
override fun test(arg: Int) {}
|
||||
open fun test(a: String) {}
|
||||
open fun test2() {}
|
||||
}
|
||||
|
||||
class Baz(val foo: Foo) : Bar(), Foo by foo {
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
interface Foo {
|
||||
fun test(arg: Int)
|
||||
}
|
||||
|
||||
open class Bar : Foo {
|
||||
override fun test(arg: Int) {}
|
||||
open fun test(a: String) {}
|
||||
open fun test2() {}
|
||||
}
|
||||
|
||||
class Baz(val foo: Foo) : Bar(), Foo by foo {
|
||||
override <caret>fun test2(arg: Int) = super.test2(arg)
|
||||
}
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
interface Foo {
|
||||
fun test(arg: Int)
|
||||
}
|
||||
|
||||
open class Bar : Foo {
|
||||
override fun test(arg: Int) {}
|
||||
open fun test(a: String) {}
|
||||
open fun test2() {}
|
||||
}
|
||||
|
||||
class Baz(val foo: Foo) : Bar(), Foo by foo {
|
||||
}
|
||||
@@ -1466,6 +1466,30 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedMemberHidesSuperTypeOverride.kt")
|
||||
public void testDelegatedMemberHidesSuperTypeOverride() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantOverride/delegatedMemberHidesSuperTypeOverride.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedMemberHidesSuperTypeOverride2.kt")
|
||||
public void testDelegatedMemberHidesSuperTypeOverride2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantOverride/delegatedMemberHidesSuperTypeOverride2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedMemberHidesSuperTypeOverride3.kt")
|
||||
public void testDelegatedMemberHidesSuperTypeOverride3() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantOverride/delegatedMemberHidesSuperTypeOverride3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedMemberHidesSuperTypeOverride4.kt")
|
||||
public void testDelegatedMemberHidesSuperTypeOverride4() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantOverride/delegatedMemberHidesSuperTypeOverride4.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notCallSuper.kt")
|
||||
public void testNotCallSuper() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantOverride/notCallSuper.kt");
|
||||
|
||||
Reference in New Issue
Block a user