KT-2752: add diagnostics that reports about conflicting overridden declarations
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
// TARGET_BACKEND: JS
|
||||||
|
package foo
|
||||||
|
|
||||||
|
@native interface A {
|
||||||
|
fun foo(value: Int): String
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
fun foo(value: Int): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : A, B {
|
||||||
|
override fun foo(value: Int) = "C.foo($value)"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a: A = C()
|
||||||
|
assertEquals("C.foo(55)", a.foo(55))
|
||||||
|
|
||||||
|
val b: B = C()
|
||||||
|
assertEquals("C.foo(23)", b.foo(23))
|
||||||
|
|
||||||
|
val d: dynamic = C()
|
||||||
|
assertEquals("C.foo(42)", d.foo(42))
|
||||||
|
assertEquals("C.foo(99)", d.`foo_za3lpa$`(99))
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
interface A {
|
||||||
|
@JsName("foo") fun f()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
@JsName("foo") fun g()
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : A, B {
|
||||||
|
<!JS_NAME_CLASH!>override fun f() {}<!>
|
||||||
|
|
||||||
|
<!JS_NAME_CLASH!>override fun g() {}<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!JS_NAME_CLASH_SYNTHETIC!>abstract class D : A, B<!>
|
||||||
|
|
||||||
|
open class E {
|
||||||
|
open fun f() {}
|
||||||
|
|
||||||
|
open fun g() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!JS_NAME_OVERRIDE_CLASH!>class F : E(), A, B<!>
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public interface A {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
@kotlin.js.JsName(name = "foo") public abstract fun f(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface B {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
@kotlin.js.JsName(name = "foo") public abstract fun g(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class C : A, B {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun f(): kotlin.Unit
|
||||||
|
public open override /*1*/ fun g(): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class D : A, B {
|
||||||
|
public constructor D()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
@kotlin.js.JsName(name = "foo") public abstract override /*1*/ /*fake_override*/ fun f(): kotlin.Unit
|
||||||
|
@kotlin.js.JsName(name = "foo") public abstract override /*1*/ /*fake_override*/ fun g(): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class E {
|
||||||
|
public constructor E()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun f(): kotlin.Unit
|
||||||
|
public open fun g(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class F : E, A, B {
|
||||||
|
public constructor F()
|
||||||
|
public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ /*fake_override*/ fun f(): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun g(): kotlin.Unit
|
||||||
|
public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
interface A {
|
||||||
|
@JsName("f") fun foo(value: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
@JsName("g") fun foo(value: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : A, B {
|
||||||
|
<!JS_NAME_OVERRIDE_CLASH!>override fun foo(value: Int) { }<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
@native interface NA {
|
||||||
|
@JsName("f") fun foo(value: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
@native interface NB {
|
||||||
|
@JsName("g") fun foo(value: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
class NC : NA, NB {
|
||||||
|
<!JS_NAME_OVERRIDE_CLASH!>override fun foo(value: Int) { }<!>
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public interface A {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
@kotlin.js.JsName(name = "f") public abstract fun foo(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface B {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
@kotlin.js.JsName(name = "g") public abstract fun foo(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class C : A, B {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ fun foo(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.js.native() public interface NA {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
@kotlin.js.JsName(name = "f") public abstract fun foo(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.js.native() public interface NB {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
@kotlin.js.JsName(name = "g") public abstract fun foo(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class NC : NA, NB {
|
||||||
|
public constructor NC()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ fun foo(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+12
@@ -301,6 +301,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("conflictingNamesFromSuperclass.kt")
|
||||||
|
public void testConflictingNamesFromSuperclass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extensionPropertyAndMethod.kt")
|
@TestMetadata("extensionPropertyAndMethod.kt")
|
||||||
public void testExtensionPropertyAndMethod() throws Exception {
|
public void testExtensionPropertyAndMethod() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.kt");
|
||||||
@@ -367,6 +373,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overriddenJsNameClash.kt")
|
||||||
|
public void testOverriddenJsNameClash() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/overriddenJsNameClash.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("packageAndMethod.kt")
|
@TestMetadata("packageAndMethod.kt")
|
||||||
public void testPackageAndMethod() throws Exception {
|
public void testPackageAndMethod() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.kt");
|
||||||
|
|||||||
@@ -906,6 +906,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public static class Bridges extends AbstractBlackBoxCodegenTest {
|
public static class Bridges extends AbstractBlackBoxCodegenTest {
|
||||||
|
@TestMetadata("jsNative.kt")
|
||||||
|
public void ignoredJsNative() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/jsNative.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInBridges() throws Exception {
|
public void testAllFilesPresentInBridges() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -39,10 +39,14 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
|||||||
put(ErrorsJs.NATIVE_INNER_CLASS_PROHIBITED, "Native inner classes are prohibited")
|
put(ErrorsJs.NATIVE_INNER_CLASS_PROHIBITED, "Native inner classes are prohibited")
|
||||||
put(ErrorsJs.JS_NAME_CLASH, "JavaScript name ({0}) generated for this declaration clashes with another declaration: {1}",
|
put(ErrorsJs.JS_NAME_CLASH, "JavaScript name ({0}) generated for this declaration clashes with another declaration: {1}",
|
||||||
Renderers.STRING, Renderers.COMPACT)
|
Renderers.STRING, Renderers.COMPACT)
|
||||||
|
put(ErrorsJs.JS_NAME_CLASH_SYNTHETIC, "JavaScript name {0} is generated from two different inherited members: {1} and {2}",
|
||||||
|
Renderers.STRING, Renderers.COMPACT, Renderers.COMPACT)
|
||||||
put(ErrorsJs.JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED, "@JsName annotation is prohibited for primary constructors")
|
put(ErrorsJs.JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED, "@JsName annotation is prohibited for primary constructors")
|
||||||
put(ErrorsJs.JS_NAME_ON_ACCESSOR_AND_PROPERTY, "@JsName can be either on a property or its accessors, not both of them")
|
put(ErrorsJs.JS_NAME_ON_ACCESSOR_AND_PROPERTY, "@JsName can be either on a property or its accessors, not both of them")
|
||||||
put(ErrorsJs.JS_NAME_IS_NOT_ON_ALL_ACCESSORS, "@JsName should be on all of the property accessors")
|
put(ErrorsJs.JS_NAME_IS_NOT_ON_ALL_ACCESSORS, "@JsName should be on all of the property accessors")
|
||||||
put(ErrorsJs.JS_NAME_PROHIBITED_FOR_OVERRIDE, "@JsName is prohibited for overridden members")
|
put(ErrorsJs.JS_NAME_PROHIBITED_FOR_OVERRIDE, "@JsName is prohibited for overridden members")
|
||||||
|
put(ErrorsJs.JS_NAME_OVERRIDE_CLASH, "Conflicting names got from overridden declarations {0} and {1}", Renderers.COMPACT,
|
||||||
|
Renderers.COMPACT)
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.js.resolve.diagnostics;
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
|
import org.jetbrains.kotlin.diagnostics.*;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||||
import org.jetbrains.kotlin.psi.KtElement;
|
import org.jetbrains.kotlin.psi.KtElement;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
@@ -46,10 +43,13 @@ public interface ErrorsJs {
|
|||||||
DiagnosticFactory0<KtExpression> JSCODE_NO_JAVASCRIPT_PRODUCED = DiagnosticFactory0.create(ERROR, DEFAULT);
|
DiagnosticFactory0<KtExpression> JSCODE_NO_JAVASCRIPT_PRODUCED = DiagnosticFactory0.create(ERROR, DEFAULT);
|
||||||
DiagnosticFactory0<KtExpression> NATIVE_INNER_CLASS_PROHIBITED = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtExpression> NATIVE_INNER_CLASS_PROHIBITED = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory2<KtElement, String, DeclarationDescriptor> JS_NAME_CLASH = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<KtElement, String, DeclarationDescriptor> JS_NAME_CLASH = DiagnosticFactory2.create(ERROR);
|
||||||
|
DiagnosticFactory3<KtElement, String, DeclarationDescriptor, DeclarationDescriptor> JS_NAME_CLASH_SYNTHETIC =
|
||||||
|
DiagnosticFactory3.create(ERROR);
|
||||||
DiagnosticFactory0<KtElement> JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtElement> JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtElement> JS_NAME_ON_ACCESSOR_AND_PROPERTY = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtElement> JS_NAME_ON_ACCESSOR_AND_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> JS_NAME_IS_NOT_ON_ALL_ACCESSORS = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> JS_NAME_IS_NOT_ON_ALL_ACCESSORS = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> JS_NAME_PROHIBITED_FOR_OVERRIDE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> JS_NAME_PROHIBITED_FOR_OVERRIDE = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory2<PsiElement, DeclarationDescriptor, DeclarationDescriptor> JS_NAME_OVERRIDE_CLASH = DiagnosticFactory2.create(ERROR);
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
Object _initializer = new Object() {
|
Object _initializer = new Object() {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeatureSettings
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||||
@@ -25,7 +26,7 @@ import org.jetbrains.kotlin.resolve.SimpleDeclarationChecker
|
|||||||
|
|
||||||
object JsNameChecker : SimpleDeclarationChecker {
|
object JsNameChecker : SimpleDeclarationChecker {
|
||||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink,
|
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink,
|
||||||
bindingContext: BindingContext) {
|
bindingContext: BindingContext, languageFeatureSettings: LanguageFeatureSettings) {
|
||||||
if (descriptor is PropertyDescriptor) {
|
if (descriptor is PropertyDescriptor) {
|
||||||
val namedAccessorCount = descriptor.accessors.count { AnnotationsUtils.getJsName(it) != null }
|
val namedAccessorCount = descriptor.accessors.count { AnnotationsUtils.getJsName(it) != null }
|
||||||
if (namedAccessorCount > 0 && namedAccessorCount < descriptor.accessors.size) {
|
if (namedAccessorCount > 0 && namedAccessorCount < descriptor.accessors.size) {
|
||||||
|
|||||||
+18
-14
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import org.jetbrains.kotlin.config.LanguageFeatureSettings
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.js.naming.FQNGenerator
|
import org.jetbrains.kotlin.js.naming.FQNGenerator
|
||||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.resolve.SimpleDeclarationChecker
|
import org.jetbrains.kotlin.resolve.SimpleDeclarationChecker
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
|
||||||
|
|
||||||
class JsNameClashChecker : SimpleDeclarationChecker {
|
class JsNameClashChecker : SimpleDeclarationChecker {
|
||||||
private val fqnGenerator = FQNGenerator()
|
private val fqnGenerator = FQNGenerator()
|
||||||
@@ -40,7 +39,8 @@ class JsNameClashChecker : SimpleDeclarationChecker {
|
|||||||
declaration: KtDeclaration,
|
declaration: KtDeclaration,
|
||||||
descriptor: DeclarationDescriptor,
|
descriptor: DeclarationDescriptor,
|
||||||
diagnosticHolder: DiagnosticSink,
|
diagnosticHolder: DiagnosticSink,
|
||||||
bindingContext: BindingContext
|
bindingContext: BindingContext,
|
||||||
|
languageFeatureSettings: LanguageFeatureSettings
|
||||||
) {
|
) {
|
||||||
if (declaration !is KtProperty || !descriptor.isExtension) {
|
if (declaration !is KtProperty || !descriptor.isExtension) {
|
||||||
checkDescriptor(descriptor, declaration, diagnosticHolder)
|
checkDescriptor(descriptor, declaration, diagnosticHolder)
|
||||||
@@ -55,23 +55,27 @@ class JsNameClashChecker : SimpleDeclarationChecker {
|
|||||||
val existing = scope[name]
|
val existing = scope[name]
|
||||||
if (existing != null && existing != fqn.descriptor) {
|
if (existing != null && existing != fqn.descriptor) {
|
||||||
diagnosticHolder.report(ErrorsJs.JS_NAME_CLASH.on(declaration, name, existing))
|
diagnosticHolder.report(ErrorsJs.JS_NAME_CLASH.on(declaration, name, existing))
|
||||||
val existingDeclaration = findPsi(existing) ?: declaration
|
val existingDeclaration = existing.findPsi() ?: declaration
|
||||||
if (clashedDescriptors.add(existing) && existingDeclaration is KtDeclaration && existingDeclaration != declaration) {
|
if (clashedDescriptors.add(existing) && existingDeclaration is KtDeclaration && existingDeclaration != declaration) {
|
||||||
diagnosticHolder.report(ErrorsJs.JS_NAME_CLASH.on(existingDeclaration, name, descriptor))
|
diagnosticHolder.report(ErrorsJs.JS_NAME_CLASH.on(existingDeclaration, name, descriptor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun findPsi(descriptor: DeclarationDescriptor): PsiElement? {
|
val fqnDescriptor = fqn.descriptor
|
||||||
val psi = (descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi()
|
if (fqnDescriptor is ClassDescriptor) {
|
||||||
return if (psi == null && descriptor is CallableMemberDescriptor &&
|
val fakeOverrides = fqnDescriptor.defaultType.memberScope.getContributedDescriptors().asSequence()
|
||||||
descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
.mapNotNull { it as? CallableMemberDescriptor }
|
||||||
) {
|
.filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
|
||||||
descriptor.overriddenDescriptors.mapNotNull { findPsi(it) }.firstOrNull()
|
for (override in fakeOverrides) {
|
||||||
}
|
val overrideFqn = fqnGenerator.generate(override)
|
||||||
else {
|
val scope = getScope(overrideFqn.scope)
|
||||||
psi
|
val name = overrideFqn.names.last()
|
||||||
|
val existing = scope[name]
|
||||||
|
if (existing != null && existing != overrideFqn.descriptor) {
|
||||||
|
diagnosticHolder.report(ErrorsJs.JS_NAME_CLASH_SYNTHETIC.on(declaration, name, override, existing))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeatureSettings
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
|
import org.jetbrains.kotlin.js.naming.FQNGenerator
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.DeclarationChecker
|
||||||
|
|
||||||
|
class OverriddenJsNameChecker : DeclarationChecker {
|
||||||
|
private val fqnGenerator = FQNGenerator()
|
||||||
|
|
||||||
|
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink,
|
||||||
|
bindingContext: BindingContext, languageFeatureSettings: LanguageFeatureSettings) {
|
||||||
|
doCheck(descriptor) { first, second ->
|
||||||
|
val psi = descriptor.findPsi() ?: declaration
|
||||||
|
diagnosticHolder.report(ErrorsJs.JS_NAME_OVERRIDE_CLASH.on(psi, first, second))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor is ClassDescriptor) {
|
||||||
|
val fakeOverrides = descriptor.defaultType.memberScope.getContributedDescriptors().asSequence()
|
||||||
|
.mapNotNull { it as? CallableMemberDescriptor }
|
||||||
|
.filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
|
||||||
|
for (override in fakeOverrides) {
|
||||||
|
val errorFound = doCheck(override) { first, second ->
|
||||||
|
val psi = descriptor.findPsi() ?: declaration
|
||||||
|
diagnosticHolder.report(ErrorsJs.JS_NAME_OVERRIDE_CLASH.on(psi, first, second))
|
||||||
|
}
|
||||||
|
if (errorFound) break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doCheck(descriptor: DeclarationDescriptor, onClash: (CallableMemberDescriptor, CallableMemberDescriptor) -> Unit):
|
||||||
|
Boolean {
|
||||||
|
if (descriptor !is CallableMemberDescriptor) return false
|
||||||
|
|
||||||
|
var knownName: String? = null
|
||||||
|
var knownDescriptor: CallableMemberDescriptor? = null
|
||||||
|
for (overridden in descriptor.overriddenDescriptors) {
|
||||||
|
val fqn = fqnGenerator.generate(overridden)
|
||||||
|
if (!fqn.shared) continue
|
||||||
|
|
||||||
|
val name = fqnGenerator.generate(overridden).names.last()
|
||||||
|
if (knownName == null) {
|
||||||
|
knownName = name
|
||||||
|
knownDescriptor = overridden
|
||||||
|
}
|
||||||
|
else if (knownName != name &&
|
||||||
|
(AnnotationsUtils.getJsName(knownDescriptor!!) != null || AnnotationsUtils.getJsName(overridden) != null)) {
|
||||||
|
onClash(knownDescriptor, overridden)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||||
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
|
|
||||||
|
fun DeclarationDescriptor.findPsi(): PsiElement? {
|
||||||
|
val psi = (this as? DeclarationDescriptorWithSource)?.source?.getPsi()
|
||||||
|
return if (psi == null && this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||||
|
overriddenDescriptors.mapNotNull { it.findPsi() }.firstOrNull()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
psi
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -131,6 +131,12 @@ public class BridgeTestGenerated extends AbstractBridgeTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jsNative.kt")
|
||||||
|
public void testJsNative() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/jsNative.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt1939.kt")
|
@TestMetadata("kt1939.kt")
|
||||||
public void testKt1939() throws Exception {
|
public void testKt1939() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/kt1939.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/kt1939.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user