IR: Allow references to script constructor in module
aso add test checking (somewhat confusing) semantic of script nested classes.
This commit is contained in:
committed by
TeamCityServer
parent
e7cbc9a0fb
commit
47ea5330ff
+12
@@ -40141,6 +40141,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
public void testLocalCaptureTests() throws Exception {
|
public void testLocalCaptureTests() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/script/localCaptureTests.kt");
|
runTest("compiler/testData/codegen/box/script/localCaptureTests.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("scripInstance.kt")
|
||||||
|
public void testScripInstance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/script/scripInstance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("scriptNestedClassInstance.kt")
|
||||||
|
public void testScriptNestedClassInstance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/script/scriptNestedClassInstance.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ val IrType.erasedUpperBound: IrClass
|
|||||||
get() = when (val classifier = classifierOrNull) {
|
get() = when (val classifier = classifierOrNull) {
|
||||||
is IrClassSymbol -> classifier.owner
|
is IrClassSymbol -> classifier.owner
|
||||||
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
|
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
|
||||||
|
is IrScriptSymbol -> classifier.owner.targetClass!!.owner
|
||||||
else -> error(render())
|
else -> error(render())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-32
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
internal val scriptsToClassesPhase = makeCustomPhase<JvmBackendContext, IrModuleFragment>(
|
internal val scriptsToClassesPhase = makeCustomPhase<JvmBackendContext, IrModuleFragment>(
|
||||||
name = "ScriptsToClasses",
|
name = "ScriptsToClasses",
|
||||||
@@ -98,44 +99,20 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext) {
|
|||||||
|
|
||||||
irScriptClass.thisReceiver = irScript.thisReceiver.transform(scriptTransformer, null)
|
irScriptClass.thisReceiver = irScript.thisReceiver.transform(scriptTransformer, null)
|
||||||
|
|
||||||
irScriptClass.addConstructor {
|
irScript.constructor?.patchForClass()?.safeAs<IrConstructor>()!!.also { constructor ->
|
||||||
isPrimary = true
|
val explicitParamsStartIndex = if (irScript.earlierScriptsParameter == null) 0 else 1
|
||||||
}.also { irConstructor ->
|
val explicitParameters = constructor.valueParameters.subList(
|
||||||
|
explicitParamsStartIndex,
|
||||||
fun addConstructorParameter(valueParameter: IrValueParameter, createCorrespondingProperty: Boolean): IrValueParameter {
|
irScript.explicitCallParameters.size + explicitParamsStartIndex
|
||||||
val newValueParameter = valueParameter.patchForClass() as IrValueParameter
|
)
|
||||||
irConstructor.valueParameters = irConstructor.valueParameters + newValueParameter
|
constructor.body = context.createIrBuilder(constructor.symbol).irBlockBody {
|
||||||
if (createCorrespondingProperty) {
|
|
||||||
irScriptClass.addSimplePropertyFrom(
|
|
||||||
newValueParameter,
|
|
||||||
IrExpressionBodyImpl(
|
|
||||||
IrGetValueImpl(
|
|
||||||
newValueParameter.startOffset, newValueParameter.endOffset,
|
|
||||||
newValueParameter.type,
|
|
||||||
newValueParameter.symbol,
|
|
||||||
IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return newValueParameter
|
|
||||||
}
|
|
||||||
|
|
||||||
irScript.earlierScriptsParameter?.let { earlierScriptdParameter ->
|
|
||||||
addConstructorParameter(earlierScriptdParameter, false)
|
|
||||||
}
|
|
||||||
val copiedExplicitParameters = irScript.explicitCallParameters.map { addConstructorParameter(it, false) }
|
|
||||||
irScript.implicitReceiversParameters.forEach { addConstructorParameter(it, false) }
|
|
||||||
irScript.providedProperties.forEach { addConstructorParameter(it.first, false) }
|
|
||||||
|
|
||||||
irConstructor.body = context.createIrBuilder(irConstructor.symbol).irBlockBody {
|
|
||||||
val baseClassCtor = irScript.baseClass.classOrNull?.owner?.constructors?.firstOrNull()
|
val baseClassCtor = irScript.baseClass.classOrNull?.owner?.constructors?.firstOrNull()
|
||||||
// TODO: process situation with multiple constructors (should probably be an error)
|
// TODO: process situation with multiple constructors (should probably be an error)
|
||||||
if (baseClassCtor == null) {
|
if (baseClassCtor == null) {
|
||||||
+irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single())
|
+irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single())
|
||||||
} else {
|
} else {
|
||||||
+irDelegatingConstructorCall(baseClassCtor).also {
|
+irDelegatingConstructorCall(baseClassCtor).also {
|
||||||
copiedExplicitParameters.forEachIndexed { idx, valueParameter ->
|
explicitParameters.forEachIndexed { idx, valueParameter ->
|
||||||
it.putValueArgument(
|
it.putValueArgument(
|
||||||
idx,
|
idx,
|
||||||
IrGetValueImpl(
|
IrGetValueImpl(
|
||||||
@@ -153,7 +130,10 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext) {
|
|||||||
context.irBuiltIns.unitType
|
context.irBuiltIns.unitType
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
irScriptClass.declarations.add(constructor)
|
||||||
|
constructor.parent = irScriptClass
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasMain = false
|
var hasMain = false
|
||||||
irScript.statements.forEach { scriptStatement ->
|
irScript.statements.forEach { scriptStatement ->
|
||||||
when (scriptStatement) {
|
when (scriptStatement) {
|
||||||
|
|||||||
+29
-7
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.assertCast
|
import org.jetbrains.kotlin.ir.assertCast
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.IrFunctionBuilder
|
||||||
import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource
|
import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
@@ -20,26 +21,25 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.types.toArrayOrPrimitiveArrayType
|
import org.jetbrains.kotlin.ir.types.toArrayOrPrimitiveArrayType
|
||||||
import org.jetbrains.kotlin.ir.util.indexOrMinusOne
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.isCrossinline
|
|
||||||
import org.jetbrains.kotlin.ir.util.isNoinline
|
|
||||||
import org.jetbrains.kotlin.ir.util.varargElementType
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtScript
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
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.psi.psiUtil.startOffsetSkippingComments
|
||||||
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
|
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
|
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
|
class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
fun generateScriptDeclaration(ktScript: KtScript): IrDeclaration? {
|
fun generateScriptDeclaration(ktScript: KtScript): IrDeclaration? {
|
||||||
val descriptor = getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, ktScript) as ScriptDescriptor
|
val descriptor = getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, ktScript) as ScriptDescriptor
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
|||||||
descriptor.isCrossinline, descriptor.isNoinline,
|
descriptor.isCrossinline, descriptor.isNoinline,
|
||||||
isHidden = false, isAssignable = false
|
isHidden = false, isAssignable = false
|
||||||
)
|
)
|
||||||
} .also { it.parent = irScript }
|
}.also { it.parent = irScript }
|
||||||
}
|
}
|
||||||
|
|
||||||
irScript.thisReceiver = makeParameter(descriptor.thisAsReceiverParameter, IrDeclarationOrigin.INSTANCE_RECEIVER)
|
irScript.thisReceiver = makeParameter(descriptor.thisAsReceiverParameter, IrDeclarationOrigin.INSTANCE_RECEIVER)
|
||||||
@@ -140,6 +140,28 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
|||||||
valueParameter to irProperty.symbol
|
valueParameter to irProperty.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
irScript.constructor = with(IrFunctionBuilder().apply {
|
||||||
|
isPrimary = true
|
||||||
|
returnType = irScript.thisReceiver.type as IrSimpleType
|
||||||
|
}) {
|
||||||
|
irScript.factory.createConstructor(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
context.symbolTable.referenceConstructor(descriptor.unsubstitutedPrimaryConstructor),
|
||||||
|
SpecialNames.INIT,
|
||||||
|
visibility, returnType,
|
||||||
|
isInline = isInline, isExternal = isExternal, isPrimary = isPrimary, isExpect = isExpect,
|
||||||
|
containerSource = containerSource
|
||||||
|
)
|
||||||
|
}.also { irConstructor ->
|
||||||
|
irConstructor.valueParameters = buildList {
|
||||||
|
addIfNotNull(irScript.earlierScriptsParameter)
|
||||||
|
addAll(irScript.explicitCallParameters)
|
||||||
|
addAll(irScript.implicitReceiversParameters)
|
||||||
|
irScript.providedProperties.forEach { add(it.first) }
|
||||||
|
}
|
||||||
|
irConstructor.parent = irScript
|
||||||
|
}
|
||||||
|
|
||||||
for (d in ktScript.declarations) {
|
for (d in ktScript.declarations) {
|
||||||
when (d) {
|
when (d) {
|
||||||
is KtScriptInitializer -> {
|
is KtScriptInitializer -> {
|
||||||
|
|||||||
@@ -38,4 +38,6 @@ abstract class IrScript :
|
|||||||
abstract var earlierScripts: List<IrScriptSymbol>?
|
abstract var earlierScripts: List<IrScriptSymbol>?
|
||||||
|
|
||||||
abstract var targetClass: IrClassSymbol?
|
abstract var targetClass: IrClassSymbol?
|
||||||
|
|
||||||
|
abstract var constructor: IrConstructor?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class IrScriptImpl(
|
|||||||
override var earlierScriptsParameter: IrValueParameter? = null
|
override var earlierScriptsParameter: IrValueParameter? = null
|
||||||
override var earlierScripts: List<IrScriptSymbol>? = null
|
override var earlierScripts: List<IrScriptSymbol>? = null
|
||||||
override var targetClass: IrClassSymbol? = null
|
override var targetClass: IrClassSymbol? = null
|
||||||
|
override var constructor: IrConstructor? = null
|
||||||
|
|
||||||
@ObsoleteDescriptorBasedAPI
|
@ObsoleteDescriptorBasedAPI
|
||||||
override val descriptor: ScriptDescriptor
|
override val descriptor: ScriptDescriptor
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.impl.*
|
import org.jetbrains.kotlin.ir.types.impl.*
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
@@ -77,7 +78,12 @@ val IrType.classifierOrNull: IrClassifierSymbol?
|
|||||||
get() = safeAs<IrSimpleType>()?.classifier
|
get() = safeAs<IrSimpleType>()?.classifier
|
||||||
|
|
||||||
val IrType.classOrNull: IrClassSymbol?
|
val IrType.classOrNull: IrClassSymbol?
|
||||||
get() = classifierOrNull as? IrClassSymbol
|
get() =
|
||||||
|
when (val classifier = classifierOrNull) {
|
||||||
|
is IrClassSymbol -> classifier
|
||||||
|
is IrScriptSymbol -> classifier.owner.targetClass
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
val IrType.classFqName: FqName?
|
val IrType.classFqName: FqName?
|
||||||
get() = classOrNull?.owner?.fqNameWhenAvailable
|
get() = classOrNull?.owner?.fqNameWhenAvailable
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// IGNORE_LIGHT_ANALYSIS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun box(): String =
|
||||||
|
Script(emptyArray<String>()).x
|
||||||
|
|
||||||
|
// FILE: script.kts
|
||||||
|
|
||||||
|
val x = "OK"
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// IGNORE_LIGHT_ANALYSIS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun box(): String =
|
||||||
|
Script.Nested().x
|
||||||
|
|
||||||
|
// FILE: script.kts
|
||||||
|
|
||||||
|
class Nested {
|
||||||
|
val x = "OK"
|
||||||
|
}
|
||||||
+12
@@ -39967,6 +39967,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testLocalCaptureTests() throws Exception {
|
public void testLocalCaptureTests() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/script/localCaptureTests.kt");
|
runTest("compiler/testData/codegen/box/script/localCaptureTests.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("scripInstance.kt")
|
||||||
|
public void testScripInstance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/script/scripInstance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("scriptNestedClassInstance.kt")
|
||||||
|
public void testScriptNestedClassInstance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/script/scriptNestedClassInstance.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+12
@@ -40141,6 +40141,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testLocalCaptureTests() throws Exception {
|
public void testLocalCaptureTests() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/script/localCaptureTests.kt");
|
runTest("compiler/testData/codegen/box/script/localCaptureTests.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("scripInstance.kt")
|
||||||
|
public void testScripInstance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/script/scripInstance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("scriptNestedClassInstance.kt")
|
||||||
|
public void testScriptNestedClassInstance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/script/scriptNestedClassInstance.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+10
@@ -32030,6 +32030,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testLocalCaptureTests() throws Exception {
|
public void testLocalCaptureTests() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/script/localCaptureTests.kt");
|
runTest("compiler/testData/codegen/box/script/localCaptureTests.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("scripInstance.kt")
|
||||||
|
public void testScripInstance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/script/scripInstance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("scriptNestedClassInstance.kt")
|
||||||
|
public void testScriptNestedClassInstance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/script/scriptNestedClassInstance.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/sealed")
|
@TestMetadata("compiler/testData/codegen/box/sealed")
|
||||||
|
|||||||
Reference in New Issue
Block a user