From ed7ac7cea9dae206b131e19dffff44f484b531d7 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Mon, 26 Dec 2016 19:22:57 +0300 Subject: [PATCH] JS: do not report declaration clash when common redeclaration diagnostic applies. See KT-14577 --- .../name/declarationClash.kt | 37 +++++++++++++ .../name/declarationClash.txt | 55 +++++++++++++++++++ .../DiagnosticsTestWithJsStdLibGenerated.java | 6 ++ .../resolve/diagnostics/JsNameClashChecker.kt | 22 +++++++- 4 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.txt diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.kt new file mode 100644 index 00000000000..acf76ddc384 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.kt @@ -0,0 +1,37 @@ +// FILE: first.kt +package foo + +class A +class C +class C + +fun f(): Int = 23 +fun f(): Int = 99 + +fun g(): String = "23" +fun g(): Int = 23 + +val x: Int = 42 +val x: Int = 99 + +val y: String = "42" +val y: Int = 42 + +class B { + fun f(): Int = 23 + fun f(): Int = 99 + + fun g(): String = "23" + fun g(): Int = 23 + + val x: Int = 42 + val x: Int = 99 + + val y: String = "42" + val y: Int = 42 +} + +// FILE: second.kt +package foo + +class A diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.txt b/compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.txt new file mode 100644 index 00000000000..bbc341d4cd3 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.txt @@ -0,0 +1,55 @@ +package + +package foo { + public val x: kotlin.Int = 42 + public val x: kotlin.Int = 99 + public val y: kotlin.Int = 42 + public val y: kotlin.String = "42" + public fun f(): kotlin.Int + public fun f(): kotlin.Int + public fun g(): kotlin.Int + public fun g(): kotlin.String + + public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class B { + public constructor B() + public final val x: kotlin.Int = 42 + public final val x: kotlin.Int = 99 + public final val y: kotlin.Int = 42 + public final val y: kotlin.String = "42" + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun f(): kotlin.Int + public final fun f(): kotlin.Int + public final fun g(): kotlin.Int + public final fun g(): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index dd367789280..737cd8f58b2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -428,6 +428,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes doTest(fileName); } + @TestMetadata("declarationClash.kt") + public void testDeclarationClash() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/declarationClash.kt"); + doTest(fileName); + } + @TestMetadata("extensionPropertyAndMethod.kt") public void testExtensionPropertyAndMethod() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.kt"); diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsNameClashChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsNameClashChecker.kt index 7b541aba3ba..f34d8ff3984 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsNameClashChecker.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsNameClashChecker.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.resolve.diagnostics import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.js.naming.NameSuggestion import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.psi.KtDeclaration @@ -29,6 +30,13 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty import org.jetbrains.kotlin.resolve.scopes.MemberScope class JsNameClashChecker : SimpleDeclarationChecker { + companion object { + private val COMMON_DIAGNOSTICS = setOf( + Errors.REDECLARATION, + Errors.CONFLICTING_OVERLOADS, + Errors.PACKAGE_OR_CLASSIFIER_REDECLARATION) + } + private val nameSuggestion = NameSuggestion() private val scopes = mutableMapOf>() private val clashedFakeOverrides = mutableMapOf>() @@ -43,11 +51,14 @@ class JsNameClashChecker : SimpleDeclarationChecker { // We don't generate JS properties for extension properties, we generate methods instead, so in this case // check name clash only for accessors, not properties if (!descriptor.isExtensionProperty) { - checkDescriptor(descriptor, declaration, diagnosticHolder) + checkDescriptor(descriptor, declaration, diagnosticHolder, bindingContext) } } - private fun checkDescriptor(descriptor: DeclarationDescriptor, declaration: KtDeclaration, diagnosticHolder: DiagnosticSink) { + private fun checkDescriptor( + descriptor: DeclarationDescriptor, declaration: KtDeclaration, + diagnosticHolder: DiagnosticSink, bindingContext: BindingContext + ) { if (descriptor is ConstructorDescriptor && descriptor.isPrimary) return val suggested = nameSuggestion.suggest(descriptor)!! @@ -58,7 +69,8 @@ class JsNameClashChecker : SimpleDeclarationChecker { if (existing != null && existing != descriptor && existing.isImpl == descriptor.isImpl && - existing.isHeader == descriptor.isHeader + existing.isHeader == descriptor.isHeader && + !bindingContext.isCommonDiagnosticReported(declaration) ) { diagnosticHolder.report(ErrorsJs.JS_NAME_CLASH.on(declaration, name, existing)) val existingDeclaration = existing.findPsi() @@ -93,6 +105,10 @@ class JsNameClashChecker : SimpleDeclarationChecker { } } + private fun BindingContext.isCommonDiagnosticReported(declaration: KtDeclaration): Boolean { + return diagnostics.forElement(declaration).any { it.factory in COMMON_DIAGNOSTICS } + } + private val DeclarationDescriptor.isImpl: Boolean get() = this is MemberDescriptor && this.isImpl