psi2ir: Don't generate constructor bodies for 'external' classes
#KT-27934
This commit is contained in:
+18
-11
@@ -28,7 +28,9 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset
|
import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset
|
import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
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.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -213,23 +215,28 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
declareConstructor(ktClassOrObject, ktClassOrObject.primaryConstructor ?: ktClassOrObject, primaryConstructorDescriptor) {
|
declareConstructor(ktClassOrObject, ktClassOrObject.primaryConstructor ?: ktClassOrObject, primaryConstructorDescriptor) {
|
||||||
if (
|
if (
|
||||||
primaryConstructorDescriptor.isExpect ||
|
primaryConstructorDescriptor.isExpect ||
|
||||||
DescriptorUtils.isAnnotationClass(primaryConstructorDescriptor.constructedClass)
|
DescriptorUtils.isAnnotationClass(primaryConstructorDescriptor.constructedClass) ||
|
||||||
|
primaryConstructorDescriptor.constructedClass.isExternal
|
||||||
)
|
)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
generatePrimaryConstructorBody(ktClassOrObject)
|
generatePrimaryConstructorBody(ktClassOrObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateSecondaryConstructor(ktConstructor: KtSecondaryConstructor): IrConstructor =
|
fun generateSecondaryConstructor(ktConstructor: KtSecondaryConstructor): IrConstructor {
|
||||||
declareConstructor(
|
val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor
|
||||||
ktConstructor, ktConstructor,
|
return declareConstructor(ktConstructor, ktConstructor, constructorDescriptor) {
|
||||||
getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor
|
when {
|
||||||
) {
|
constructorDescriptor.constructedClass.isExternal ->
|
||||||
if (ktConstructor.isConstructorDelegatingToSuper(context.bindingContext))
|
null
|
||||||
generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor)
|
|
||||||
else
|
ktConstructor.isConstructorDelegatingToSuper(context.bindingContext) ->
|
||||||
generateSecondaryConstructorBody(ktConstructor)
|
generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor)
|
||||||
|
|
||||||
|
else -> generateSecondaryConstructorBody(ktConstructor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private inline fun declareConstructor(
|
private inline fun declareConstructor(
|
||||||
|
|||||||
@@ -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"
|
||||||
|
};
|
||||||
@@ -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:<this> 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:<this> 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:<this> 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:<this> 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:<this> type:kotlin.Any flags:
|
||||||
|
CLASS CLASS name:B modality:OPEN visibility:public flags:external superTypes:[foo.A]
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> 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:<this> 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:<this> 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:<this> 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:<this> 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:<this> type:kotlin.Any flags:
|
||||||
|
CLASS CLASS name:C modality:FINAL visibility:public flags: superTypes:[foo.B]
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> 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:<this> 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:<this> 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:<this> 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:<this> 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:<this> 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"
|
||||||
@@ -46,4 +46,22 @@ public class IrJsTextTestCaseGenerated extends AbstractIrJsTextTestCase {
|
|||||||
runTest("compiler/testData/ir/irJsText/dynamic/invokeOperator.kt");
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user