JS: allow to inherit external classes with overloaded functions in case we don't override them (see KT-13910).
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
|||||||
|
external open class A {
|
||||||
|
open fun f(x: Int): Unit
|
||||||
|
|
||||||
|
<!JS_NAME_CLASH!>open fun f(x: String): Unit<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
class InheritClass : A() {
|
||||||
|
<!JS_NAME_CLASH!>override fun f(x: Int): Unit<!> { }
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public external open class A {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun f(/*0*/ x: kotlin.Int): kotlin.Unit
|
||||||
|
public open fun f(/*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 final class InheritClass : A {
|
||||||
|
public constructor InheritClass()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun f(/*0*/ x: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun f(/*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
|
||||||
|
}
|
||||||
@@ -476,6 +476,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideOverloadedNativeFunction.kt")
|
||||||
|
public void testOverrideOverloadedNativeFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/overrideOverloadedNativeFunction.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");
|
||||||
|
|||||||
+7
-2
@@ -73,8 +73,8 @@ class JsNameClashChecker : SimpleDeclarationChecker {
|
|||||||
val overrideFqn = nameSuggestion.suggest(override)!!
|
val overrideFqn = nameSuggestion.suggest(override)!!
|
||||||
val scope = getScope(overrideFqn.scope)
|
val scope = getScope(overrideFqn.scope)
|
||||||
val name = overrideFqn.names.last()
|
val name = overrideFqn.names.last()
|
||||||
val existing = scope[name]
|
val existing = scope[name] as? CallableMemberDescriptor
|
||||||
if (existing != null && existing != overrideFqn.descriptor) {
|
if (existing != null && existing != overrideFqn.descriptor && !isFakeOverridingNative(existing)) {
|
||||||
diagnosticHolder.report(ErrorsJs.JS_FAKE_NAME_CLASH.on(declaration, name, override, existing))
|
diagnosticHolder.report(ErrorsJs.JS_FAKE_NAME_CLASH.on(declaration, name, override, existing))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -89,6 +89,11 @@ class JsNameClashChecker : SimpleDeclarationChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isFakeOverridingNative(descriptor: CallableMemberDescriptor): Boolean {
|
||||||
|
return descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
|
||||||
|
descriptor.overriddenDescriptors.all { !presentsInGeneratedCode(it) }
|
||||||
|
}
|
||||||
|
|
||||||
private fun getScope(descriptor: DeclarationDescriptor) = scopes.getOrPut(descriptor) {
|
private fun getScope(descriptor: DeclarationDescriptor) = scopes.getOrPut(descriptor) {
|
||||||
val scope = mutableMapOf<String, DeclarationDescriptor>()
|
val scope = mutableMapOf<String, DeclarationDescriptor>()
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
|
|||||||
@@ -5681,6 +5681,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideNativeOverloadedFunction.kt")
|
||||||
|
public void testOverrideNativeOverloadedFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/overrideNativeOverloadedFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("passExtLambdaFromNative.kt")
|
@TestMetadata("passExtLambdaFromNative.kt")
|
||||||
public void testPassExtLambdaFromNative() throws Exception {
|
public void testPassExtLambdaFromNative() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/passExtLambdaFromNative.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/passExtLambdaFromNative.kt");
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
function A() {
|
||||||
|
}
|
||||||
|
A.prototype.f = function(x) {
|
||||||
|
return typeof x;
|
||||||
|
};
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
external open class A {
|
||||||
|
open fun f(x: Int) = "number"
|
||||||
|
|
||||||
|
open fun f(x: String) = "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
fun g(x: Int) = "[${f(x)}]"
|
||||||
|
|
||||||
|
fun g(x: String) = "[${f(x)}]"
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
fun f(x: Int): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : A(), I
|
||||||
|
|
||||||
|
external interface J {
|
||||||
|
fun f(x: Int): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class D : A(), J
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var result = B().g(23) + B().g("foo")
|
||||||
|
if (result != "[number][string]") return "fail1: $result"
|
||||||
|
|
||||||
|
result = C().f(42)
|
||||||
|
if (result != "number") return "fail2: $result"
|
||||||
|
|
||||||
|
result = D().f("bar")
|
||||||
|
if (result != "string") return "fail3: $result"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user