Fix accidental overrides computation

Consider the whole overridden tree instead of only direct overridden

 #KT-14146 Fixed
This commit is contained in:
Denis Zharkov
2016-10-04 14:14:58 +03:00
parent aca05003a9
commit a4978c794f
5 changed files with 57 additions and 7 deletions
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.load.java.descriptors.getParentJavaStaticClassScope
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
import org.jetbrains.kotlin.resolve.jvm.diagnostics.*
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -220,7 +221,10 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
else if (member is FunctionDescriptor) {
val signatures =
if (member.kind == FAKE_OVERRIDE)
member.overriddenDescriptors.mapTo(HashSet()) { it.original.asRawSignature() }
member.overriddenTreeUniqueAsSequence(useOriginal = true)
// drop the root (itself)
.drop(1)
.mapTo(HashSet()) { it.asRawSignature() }
else
setOf(member.asRawSignature())
@@ -0,0 +1,14 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
interface Foo<X> {
fun foo(x: X)
}
open class FooImpl : Foo<String> {
override fun foo(x: String) {
}
}
open class FooImpl2 : FooImpl() {
<!ACCIDENTAL_OVERRIDE!>fun foo(x: Any)<!> {
}
}
@@ -0,0 +1,25 @@
package
public interface Foo</*0*/ X> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ x: X): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class FooImpl : Foo<kotlin.String> {
public constructor FooImpl()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ fun foo(/*0*/ x: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class FooImpl2 : FooImpl {
public constructor FooImpl2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ x: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun foo(/*0*/ x: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -6037,6 +6037,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AccidentalOverrides extends AbstractDiagnosticsTest {
@TestMetadata("accidentalOverrideFromGrandparent.kt")
public void testAccidentalOverrideFromGrandparent() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/accidentalOverrideFromGrandparent.kt");
doTest(fileName);
}
public void testAllFilesPresentInAccidentalOverrides() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides"), Pattern.compile("^(.+)\\.kt$"), true);
}
@@ -237,16 +237,17 @@ fun CallableMemberDescriptor.overriddenTreeAsSequence(useOriginal: Boolean): Seq
sequenceOf(this) + overriddenDescriptors.asSequence().flatMap { it.overriddenTreeAsSequence(useOriginal) }
}
fun CallableDescriptor.overriddenTreeUniqueAsSequence(useOriginal: Boolean): Sequence<CallableDescriptor> {
val set = hashSetOf<CallableDescriptor>()
fun <D : CallableDescriptor> D.overriddenTreeUniqueAsSequence(useOriginal: Boolean): Sequence<D> {
val set = hashSetOf<D>()
fun CallableDescriptor.doBuildOverriddenTreeAsSequence(): Sequence<CallableDescriptor> {
return with(if (useOriginal) original else this) {
@Suppress("UNCHECKED_CAST")
fun D.doBuildOverriddenTreeAsSequence(): Sequence<D> {
return with(if (useOriginal) original as D else this) {
if (original in set)
emptySequence()
else {
set += original
sequenceOf(this) + overriddenDescriptors.asSequence().flatMap { it.doBuildOverriddenTreeAsSequence() }
set += original as D
sequenceOf(this) + (overriddenDescriptors as Collection<D>).asSequence().flatMap { it.doBuildOverriddenTreeAsSequence() }
}
}
}