[Wasm] External inheritance checker

Check that non-external types can't extend external type
diff --git a/compiler/cli/resources/META-INF/services/org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages$Extension b/compiler/cli/resources/META-INF/services/org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages$Extension
index a7a0ec3..d9c11f9 100644
--- a/compiler/cli/resources/META-INF/services/org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages$Extension
+++ b/compiler/cli/resources/META-INF/services/org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages$Extension
@@ -2,3 +2,4 @@
 org.jetbrains.kotlin.resolve.jvm.diagnostics.DefaultErrorMessagesJvm
 org.jetbrains.kotlin.js.resolve.diagnostics.DefaultErrorMessagesJs
 org.jetbrains.kotlin.resolve.konan.diagnostics.DefaultErrorMessagesNative
+org.jetbrains.kotlin.wasm.resolve.diagnostics.DefaultErrorMessagesWasm
diff --git a/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.kt b/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.kt
index 56d3ed9..a6eaa28 100644
--- a/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.kt
+++ b/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.kt
@@ -1,11 +1,22 @@
-open class A
+open class C1
 
-interface I
+interface I1
 
-external open class B
+external open class EC1
 
-external class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>C<!> : A
+external class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>EC2<!> : C1
 
-external class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>D<!> : B, I
+external class <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>EC3<!> : I1, C1
 
-external interface <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>K<!> : I
\ No newline at end of file
+external interface <!EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE!>EI1<!> : I1
+
+interface <!NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE!>I2<!> : EI1
+
+class <!NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE!>C3<!> : EI1
+
+class <!NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE!>C4<!> : EI1, EC1()
+
+<!NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE!>object O1<!> : EC1()
+
+val x1: Any = <!NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE!>object<!> : EI1 {}
+val x2: Any = <!NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE!>object<!> : EC1() {}
diff --git a/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.txt b/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.txt
index 217300a..f15e07c 100644
--- a/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.txt
+++ b/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.txt
@@ -1,7 +1,10 @@
 package
 
-public open class A {
-    public constructor A()
+public val x1: kotlin.Any
+public val x2: kotlin.Any
+
+public open class C1 {
+    public constructor C1()
     invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
     invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
     public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -9,8 +12,8 @@
     public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
 }
 
-public open external class B {
-    public constructor B()
+public final class C3 : EI1 {
+    public constructor C3()
     invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
     invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
     public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -18,17 +21,8 @@
     public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
 }
 
-public final external class C : A {
-    public constructor C()
-    invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
-    invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
-    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 external class D : B, I {
-    public constructor D()
+public final class C4 : EI1, EC1 {
+    public constructor C4()
     invisible_fake final override /*2*/ /*fake_override*/ var _hashCode: kotlin.Int
     invisible_fake final override /*2*/ /*fake_override*/ var typeInfo: kotlin.Int
     public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -36,45 +30,34 @@
     public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
 }
 
-public final external enum class E : kotlin.Enum<E> {
-    enum entry X
-
-    private constructor E()
+public open external class EC1 {
+    public constructor EC1()
     invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
-    public final override /*1*/ /*fake_override*/ val name: kotlin.String
-    public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
     invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
-    public open override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int
     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
-
-    // Static members
-    public final /*synthesized*/ val entries: kotlin.enums.EnumEntries<E>
-    public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E
-    public final /*synthesized*/ fun values(): kotlin.Array<E>
 }
 
-public final external enum class F : kotlin.Enum<F>, I {
-    enum entry X
+public final external class EC2 : C1 {
+    public constructor EC2()
+    invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
+    invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
+    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
+}
 
-    private constructor F()
+public final external class EC3 : I1, C1 {
+    public constructor EC3()
     invisible_fake final override /*2*/ /*fake_override*/ var _hashCode: kotlin.Int
-    public final override /*1*/ /*fake_override*/ val name: kotlin.String
-    public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
     invisible_fake final override /*2*/ /*fake_override*/ var typeInfo: kotlin.Int
-    public open override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: F): kotlin.Int
     public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
     public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
     public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
-
-    // Static members
-    public final /*synthesized*/ val entries: kotlin.enums.EnumEntries<F>
-    public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): F
-    public final /*synthesized*/ fun values(): kotlin.Array<F>
 }
 
-public interface I {
+public external interface EI1 : I1 {
     invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
     invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
     public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -82,7 +65,24 @@
     public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
 }
 
-public external interface K : I {
+public interface I1 {
+    invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
+    invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
+    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 interface I2 : EI1 {
+    invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
+    invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
+    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 object O1 : EC1 {
+    private constructor O1()
     invisible_fake final override /*1*/ /*fake_override*/ var _hashCode: kotlin.Int
     invisible_fake final override /*1*/ /*fake_override*/ var typeInfo: kotlin.Int
     public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
diff --git a/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/WasmPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/WasmPlatformConfigurator.kt
index 534c7eb..b79d425 100644
--- a/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/WasmPlatformConfigurator.kt
+++ b/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/WasmPlatformConfigurator.kt
@@ -15,11 +15,12 @@
 import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase
 import org.jetbrains.kotlin.resolve.calls.checkers.LateinitIntrinsicApplicabilityChecker
 import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
+import org.jetbrains.kotlin.wasm.resolve.diagnostics.WasmExternalInheritanceChecker
 
 object WasmPlatformConfigurator : PlatformConfiguratorBase(
     additionalDeclarationCheckers = listOf(
         JsNameChecker, JsModuleChecker, JsExternalFileChecker,
-        JsExternalChecker,
+        JsExternalChecker, WasmExternalInheritanceChecker,
         JsRuntimeAnnotationChecker,
         JsExportAnnotationChecker,
         JsExportDeclarationChecker,
diff --git a/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/DefaultErrorMessagesWasm.kt b/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/DefaultErrorMessagesWasm.kt
new file mode 100644
index 0000000..e3d9daf
--- /dev/null
+++ b/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/DefaultErrorMessagesWasm.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.wasm.resolve.diagnostics
+
+import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
+import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap
+import org.jetbrains.kotlin.diagnostics.rendering.Renderers
+
+private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
+    with(DiagnosticFactoryToRendererMap("Wasm")) {
+        put(
+            ErrorsWasm.NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE,
+            "Non-external type extends external type {0}",
+            Renderers.RENDER_TYPE
+        )
+        this
+    }
+}
+
+class DefaultErrorMessagesWasm : DefaultErrorMessages.Extension {
+    override fun getMap(): DiagnosticFactoryToRendererMap = DIAGNOSTIC_FACTORY_TO_RENDERER
+}
\ No newline at end of file
diff --git a/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/ErrorsWasm.java b/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/ErrorsWasm.java
new file mode 100644
index 0000000..245a25b
--- /dev/null
+++ b/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/ErrorsWasm.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.wasm.resolve.diagnostics;
+
+import com.intellij.psi.PsiElement;
+import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
+import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
+import org.jetbrains.kotlin.diagnostics.Errors;
+import org.jetbrains.kotlin.diagnostics.PositioningStrategies;
+import org.jetbrains.kotlin.psi.KtElement;
+import org.jetbrains.kotlin.types.KotlinType;
+
+import static org.jetbrains.kotlin.diagnostics.Severity.ERROR;
+
+public interface ErrorsWasm {
+    DiagnosticFactory1<KtElement, KotlinType> NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE =
+            DiagnosticFactory1.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
+
+    @SuppressWarnings("UnusedDeclaration")
+    Object _initializer = new Object() {
+        {
+            Errors.Initializer.initializeFactoryNames(ErrorsWasm.class);
+        }
+    };
+}
diff --git a/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmExternalInheritanceChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmExternalInheritanceChecker.kt
new file mode 100644
index 0000000..a8b914f
--- /dev/null
+++ b/js/js.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmExternalInheritanceChecker.kt
@@ -0,0 +1,46 @@
+/*
+ * 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.wasm.resolve.diagnostics
+
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.psi.KtClassOrObject
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
+import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
+import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
+import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
+import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
+
+object WasmExternalInheritanceChecker : DeclarationChecker {
+    override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
+        if (descriptor is ClassDescriptor && !descriptor.isEffectivelyExternal()) {
+            val superClasses = listOfNotNull(descriptor.getSuperClassNotAny()) + descriptor.getSuperInterfaces()
+            for (superClass in superClasses) {
+                if (superClass.isEffectivelyExternal()) {
+                    context.trace.report(
+                        ErrorsWasm.NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE.on(
+                            declaration as KtClassOrObject,
+                            superClass.defaultType
+                        )
+                    )
+                    break
+                }
+            }
+        }
+    }
+}