JS: allow to omit delegated constructor call for external classes in common FE. Prohibit delegated constructor call for external classes in JS FE.
This commit is contained in:
@@ -169,8 +169,8 @@ public class BodyResolver {
|
||||
@NotNull KtSecondaryConstructor constructor,
|
||||
@NotNull ClassConstructorDescriptor descriptor
|
||||
) {
|
||||
if (descriptor.isHeader()) {
|
||||
// For header classes, we do not resolve constructor delegation calls because they are prohibited
|
||||
if (descriptor.isHeader() || DescriptorUtils.isEffectivelyExternal(descriptor)) {
|
||||
// For header and external classes, we do not resolve constructor delegation calls because they are prohibited
|
||||
return DataFlowInfo.Companion.getEMPTY();
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ public class BodyResolver {
|
||||
descriptor.getUnsubstitutedPrimaryConstructor() != null &&
|
||||
superClass.getKind() != ClassKind.INTERFACE &&
|
||||
!superClass.getConstructors().isEmpty() &&
|
||||
!descriptor.isHeader() &&
|
||||
!descriptor.isHeader() && !DescriptorUtils.isEffectivelyExternal(descriptor) &&
|
||||
!ErrorUtils.isError(superClass)
|
||||
) {
|
||||
trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
|
||||
|
||||
+2
-1
@@ -39,4 +39,5 @@ fun box() {
|
||||
<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>baz<!>()
|
||||
}
|
||||
|
||||
external class DerivedB : <!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>B<!>()
|
||||
// TODO: fix and uncomment
|
||||
// external class DerivedB : <! CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>B< !>
|
||||
@@ -28,14 +28,6 @@ package
|
||||
|
||||
package bar {
|
||||
public fun box(): kotlin.Unit
|
||||
|
||||
public external final class DerivedB : foo.B {
|
||||
public constructor DerivedB()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun foo(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
package foo {
|
||||
|
||||
+2
-1
@@ -33,4 +33,5 @@ fun box() {
|
||||
<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>bar<!>()
|
||||
}
|
||||
|
||||
external class DerivedB : <!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>B<!>()
|
||||
// TODO: fix and uncomment
|
||||
// external class DerivedB : <! CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>B< !>
|
||||
-8
@@ -2,14 +2,6 @@ package
|
||||
|
||||
package bar {
|
||||
public fun box(): kotlin.Unit
|
||||
|
||||
public external final class DerivedB : foo.B {
|
||||
public constructor DerivedB()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun foo(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
package foo {
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// !DIAGNOSTICS: -DEBUG_INFO_MISSING_UNRESOLVED
|
||||
|
||||
external open class Base(x: Int) {
|
||||
constructor(x: String) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>this<!>(23)
|
||||
|
||||
constructor(x: String, y: String) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>this<!>("")
|
||||
}
|
||||
|
||||
external open class Derived1() : Base<!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>(23)<!> {
|
||||
constructor(x: Byte) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>super<!>(23)
|
||||
|
||||
constructor(x: String) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>super<!>("")
|
||||
|
||||
constructor(x: String, y: String) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>super<!>("")
|
||||
}
|
||||
|
||||
external open class Derived2() : Base<!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>("")<!>
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package
|
||||
|
||||
public external open class Base {
|
||||
public constructor Base(/*0*/ x: kotlin.Int)
|
||||
public constructor Base(/*0*/ x: kotlin.String)
|
||||
public constructor Base(/*0*/ x: kotlin.String, /*1*/ y: kotlin.String)
|
||||
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 external open class Derived1 : Base {
|
||||
public constructor Derived1()
|
||||
public constructor Derived1(/*0*/ x: kotlin.Byte)
|
||||
public constructor Derived1(/*0*/ x: kotlin.String)
|
||||
public constructor Derived1(/*0*/ x: kotlin.String, /*1*/ y: kotlin.String)
|
||||
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 external open class Derived2 : Base {
|
||||
public constructor Derived2()
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
external interface I
|
||||
|
||||
external object O : I
|
||||
|
||||
|
||||
class Delegate {
|
||||
operator fun getValue(thisRef: Any?, property: Any): String = ""
|
||||
|
||||
operator fun setValue(thisRef: Any?, property: Any, value: String) {}
|
||||
}
|
||||
|
||||
external class A : <!EXTERNAL_DELEGATION!>I by O<!> {
|
||||
val prop <!EXTERNAL_DELEGATION!>by Delegate()<!>
|
||||
|
||||
var mutableProp <!EXTERNAL_DELEGATION!>by Delegate()<!>
|
||||
}
|
||||
|
||||
external val topLevelProp <!EXTERNAL_DELEGATION!>by Delegate()<!>
|
||||
@@ -0,0 +1,34 @@
|
||||
package
|
||||
|
||||
public external val topLevelProp: kotlin.String
|
||||
|
||||
public external final class A : I {
|
||||
public constructor A()
|
||||
public final var mutableProp: kotlin.String
|
||||
public final val prop: kotlin.String
|
||||
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 Delegate {
|
||||
public constructor Delegate()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.Any): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final operator fun setValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.Any, /*2*/ value: kotlin.String): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public external interface I {
|
||||
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 external object O : I {
|
||||
private constructor O()
|
||||
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
|
||||
}
|
||||
@@ -6,9 +6,9 @@ interface I
|
||||
|
||||
external open class B
|
||||
|
||||
external class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>C<!> : A()
|
||||
external class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>C<!> : A
|
||||
|
||||
external class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>D<!> : B(), I
|
||||
external class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>D<!> : B, I
|
||||
|
||||
@native class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>N<!> : A()
|
||||
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ class B : A() {
|
||||
<!OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS!>override fun f(x: Int)<!> {}
|
||||
}
|
||||
|
||||
external class C : A() {
|
||||
external class C : A {
|
||||
override fun f(x: Int)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class F : D(), I {
|
||||
<!OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS!>override fun f(x: Int)<!> {}
|
||||
}
|
||||
|
||||
external class G : D(), I {
|
||||
external class G : D, I {
|
||||
override fun f(x: Int)
|
||||
}
|
||||
|
||||
@@ -45,6 +45,6 @@ open external class XE {
|
||||
|
||||
class <!OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE!>Y<!> : X(), I
|
||||
|
||||
external class YE: XE(), I
|
||||
external class YE: XE, I
|
||||
|
||||
class Z : X(), J
|
||||
+12
@@ -575,6 +575,18 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedConstructorCall.kt")
|
||||
public void testDelegatedConstructorCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/delegatedConstructorCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegation.kt")
|
||||
public void testDelegation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/delegation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extensionFunctionAndProperty.kt")
|
||||
public void testExtensionFunctionAndProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/extensionFunctionAndProperty.kt");
|
||||
|
||||
+3
@@ -75,10 +75,13 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
put(ErrorsJs.INLINE_EXTERNAL_DECLARATION, "Inline external declaration")
|
||||
put(ErrorsJs.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE,
|
||||
"Only nullable properties of external interfaces are allowed to be non-abstract")
|
||||
|
||||
put(ErrorsJs.WRONG_BODY_OF_EXTERNAL_DECLARATION, "Wrong body of external declaration. Must be either ' = noImpl' or { noImpl }")
|
||||
put(ErrorsJs.WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION, "Wrong initializer of external declaration. Must be ' = noImpl'")
|
||||
put(ErrorsJs.WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER,
|
||||
"Wrong default value for parameter of external function. Must be ' = noImpl'")
|
||||
put(ErrorsJs.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL, "Delegated constructor call in external class")
|
||||
put(ErrorsJs.EXTERNAL_DELEGATION, "Using delegate on external declaration")
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
@@ -80,9 +80,13 @@ public interface ErrorsJs {
|
||||
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory0<KtExpression> NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE = DiagnosticFactory0.create(
|
||||
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
// Diagnostics about exposing implementation detail in external declarations
|
||||
DiagnosticFactory0<KtExpression> WRONG_BODY_OF_EXTERNAL_DECLARATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> EXTERNAL_DELEGATED_CONSTRUCTOR_CALL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> EXTERNAL_DELEGATION = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
|
||||
@@ -91,6 +91,7 @@ object JsExternalChecker : SimpleDeclarationChecker {
|
||||
}
|
||||
|
||||
checkBody(declaration, descriptor, diagnosticHolder, bindingContext)
|
||||
checkDelegation(declaration, descriptor, diagnosticHolder)
|
||||
}
|
||||
|
||||
private fun checkBody(
|
||||
@@ -114,6 +115,34 @@ object JsExternalChecker : SimpleDeclarationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkDelegation(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) {
|
||||
if (descriptor !is MemberDescriptor || !DescriptorUtils.isEffectivelyExternal(descriptor)) return
|
||||
|
||||
if (declaration is KtClassOrObject) {
|
||||
for (superTypeEntry in declaration.superTypeListEntries) {
|
||||
when (superTypeEntry) {
|
||||
is KtSuperTypeCallEntry -> {
|
||||
diagnosticHolder.report(ErrorsJs.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL.on(superTypeEntry.valueArgumentList!!))
|
||||
}
|
||||
is KtDelegatedSuperTypeEntry -> {
|
||||
diagnosticHolder.report(ErrorsJs.EXTERNAL_DELEGATION.on(superTypeEntry))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (declaration is KtSecondaryConstructor) {
|
||||
val delegationCall = declaration.getDelegationCall()
|
||||
if (!delegationCall.isImplicit) {
|
||||
diagnosticHolder.report(ErrorsJs.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL.on(delegationCall))
|
||||
}
|
||||
}
|
||||
else if (declaration is KtProperty && descriptor !is PropertyAccessorDescriptor) {
|
||||
declaration.delegate?.let { delegate ->
|
||||
diagnosticHolder.report(ErrorsJs.EXTERNAL_DELEGATION.on(delegate))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isDirectlyExternal(declaration: KtDeclaration, descriptor: DeclarationDescriptor): Boolean {
|
||||
if (declaration is KtProperty && descriptor is PropertyAccessorDescriptor) return false
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ open public external class MouseEvent() {
|
||||
public fun isDefaultPrevented(): Boolean
|
||||
}
|
||||
|
||||
public external class MouseClickEvent() : MouseEvent() {
|
||||
public external class MouseClickEvent() : MouseEvent {
|
||||
public val which: Int
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ class A(val x: Int) {
|
||||
}
|
||||
|
||||
external class B(x: Int) {
|
||||
constructor(a: Int, b: Int) : this(0) { noImpl }
|
||||
constructor(a: Int, b: Int)
|
||||
|
||||
val x: Int
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ external open class A {
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
external open class B : A() {
|
||||
external open class B : A {
|
||||
fun bar(): String
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user