diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt index 28b1ce16c4f..87433b15bfc 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt @@ -28,7 +28,9 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments -import org.jetbrains.kotlin.psi2ir.* +import org.jetbrains.kotlin.psi2ir.isConstructorDelegatingToSuper +import org.jetbrains.kotlin.psi2ir.pureEndOffsetOrUndefined +import org.jetbrains.kotlin.psi2ir.pureStartOffsetOrUndefined import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -213,23 +215,28 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio declareConstructor(ktClassOrObject, ktClassOrObject.primaryConstructor ?: ktClassOrObject, primaryConstructorDescriptor) { if ( primaryConstructorDescriptor.isExpect || - DescriptorUtils.isAnnotationClass(primaryConstructorDescriptor.constructedClass) + DescriptorUtils.isAnnotationClass(primaryConstructorDescriptor.constructedClass) || + primaryConstructorDescriptor.constructedClass.isExternal ) null else generatePrimaryConstructorBody(ktClassOrObject) } - fun generateSecondaryConstructor(ktConstructor: KtSecondaryConstructor): IrConstructor = - declareConstructor( - ktConstructor, ktConstructor, - getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor - ) { - if (ktConstructor.isConstructorDelegatingToSuper(context.bindingContext)) - generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor) - else - generateSecondaryConstructorBody(ktConstructor) + fun generateSecondaryConstructor(ktConstructor: KtSecondaryConstructor): IrConstructor { + val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor + return declareConstructor(ktConstructor, ktConstructor, constructorDescriptor) { + when { + constructorDescriptor.constructedClass.isExternal -> + null + + ktConstructor.isConstructorDelegatingToSuper(context.bindingContext) -> + generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor) + + else -> generateSecondaryConstructorBody(ktConstructor) + } } + } private inline fun declareConstructor( diff --git a/compiler/testData/ir/irJsText/native/nativeNativeKotlin.kt b/compiler/testData/ir/irJsText/native/nativeNativeKotlin.kt new file mode 100644 index 00000000000..ea2571670b5 --- /dev/null +++ b/compiler/testData/ir/irJsText/native/nativeNativeKotlin.kt @@ -0,0 +1,39 @@ +// FILE: nativeNativeKotlin.kt + +package foo + +external open class A { + fun foo(): String +} + +external open class B : A { + fun bar(): String +} + +class C : B() + +fun box(): String { + val c = C() + return "OK" +} + +// FILE: nativeNativeKotlin.js + +function A() { + +} + +A.prototype.foo = function () { + return "A.foo" +}; + +function B() { + +} + +B.prototype = Object.create(A.prototype); +B.prototype.constructor = B; + +B.prototype.bar = function () { + return "B.bar" +}; \ No newline at end of file diff --git a/compiler/testData/ir/irJsText/native/nativeNativeKotlin.txt b/compiler/testData/ir/irJsText/native/nativeNativeKotlin.txt new file mode 100644 index 00000000000..f5f2418840a --- /dev/null +++ b/compiler/testData/ir/irJsText/native/nativeNativeKotlin.txt @@ -0,0 +1,74 @@ +FILE fqName:foo fileName:/nativeNativeKotlin.kt + CLASS CLASS name:A modality:OPEN visibility:public flags:external superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.A flags: + CONSTRUCTOR visibility:public <> () returnType:foo.A flags:external,primary + FUN name:foo visibility:public modality:FINAL <> ($this:foo.A) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:foo.A flags: + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + CLASS CLASS name:B modality:OPEN visibility:public flags:external superTypes:[foo.A] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.B flags: + CONSTRUCTOR visibility:public <> () returnType:foo.B flags:external,primary + FUN name:bar visibility:public modality:FINAL <> ($this:foo.B) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:foo.B flags: + FUN FAKE_OVERRIDE name:foo visibility:public modality:FINAL <> ($this:foo.A) returnType:kotlin.String flags: + overridden: + FUN name:foo visibility:public modality:FINAL <> ($this:foo.A) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:foo.A flags: + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + overridden: + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + overridden: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + overridden: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + CLASS CLASS name:C modality:FINAL visibility:public flags: superTypes:[foo.B] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.C flags: + CONSTRUCTOR visibility:public <> () returnType:foo.C flags:primary + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor B()' + INSTANCE_INITIALIZER_CALL classDescriptor='C' + FUN FAKE_OVERRIDE name:bar visibility:public modality:FINAL <> ($this:foo.B) returnType:kotlin.String flags: + overridden: + FUN name:bar visibility:public modality:FINAL <> ($this:foo.B) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:foo.B flags: + FUN FAKE_OVERRIDE name:foo visibility:public modality:FINAL <> ($this:foo.A) returnType:kotlin.String flags: + overridden: + FUN FAKE_OVERRIDE name:foo visibility:public modality:FINAL <> ($this:foo.A) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:foo.A flags: + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + overridden: + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + overridden: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + overridden: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String flags: + BLOCK_BODY + VAR name:c type:foo.C flags:val + CALL 'constructor C()' type=foo.C origin=null + RETURN type=kotlin.Nothing from='box(): String' + CONST String type=kotlin.String value="OK" diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java index 27c90f25273..81ed7cdfbd6 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java @@ -46,4 +46,22 @@ public class IrJsTextTestCaseGenerated extends AbstractIrJsTextTestCase { runTest("compiler/testData/ir/irJsText/dynamic/invokeOperator.kt"); } } + + @TestMetadata("compiler/testData/ir/irJsText/native") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Native extends AbstractIrJsTextTestCase { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInNative() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irJsText/native"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("nativeNativeKotlin.kt") + public void testNativeNativeKotlin() throws Exception { + runTest("compiler/testData/ir/irJsText/native/nativeNativeKotlin.kt"); + } + } }