[IR] More user-friendly compilation exceptions from lowerings and JS codegen

Merge-request: KT-MR-5004
This commit is contained in:
Ilya Goncharov
2021-11-25 13:21:34 +00:00
committed by Space
parent 844876a974
commit 98bedf7eed
31 changed files with 439 additions and 150 deletions
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.cli.js
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.backend.common.CompilationException
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.backend.wasm.compileWasm
import org.jetbrains.kotlin.backend.wasm.wasmPhases
import org.jetbrains.kotlin.cli.common.*
import org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR
import org.jetbrains.kotlin.cli.common.ExitCode.OK
import org.jetbrains.kotlin.cli.common.ExitCode.*
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants
import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.RUNTIME_DIAGNOSTIC_EXCEPTION
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.RUNTIME_D
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.extensions.ScriptEvaluationExtension
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageUtil
@@ -35,15 +36,11 @@ import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
import org.jetbrains.kotlin.incremental.js.IncrementalNextRoundChecker
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.backend.js.ic.actualizeCacheForModule
import org.jetbrains.kotlin.ir.backend.js.ic.buildCache
import org.jetbrains.kotlin.ir.backend.js.ic.checkCaches
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
import org.jetbrains.kotlin.ir.backend.js.ic.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
import org.jetbrains.kotlin.ir.backend.js.ic.*
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformerTmp
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
import org.jetbrains.kotlin.js.config.*
@@ -59,7 +56,6 @@ import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
import org.jetbrains.kotlin.utils.join
import java.io.File
import java.io.IOException
import java.lang.IllegalArgumentException
enum class ProduceKind {
DEFAULT, // Determine what to produce based on js-v1 options
@@ -236,7 +232,10 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
if (updated) {
messageCollector.report(INFO, "IC $invalidationType cache building duration: ${System.currentTimeMillis() - start}ms")
} else {
messageCollector.report(INFO, "IC $invalidationType cache up-to-date check duration: ${System.currentTimeMillis() - start}ms")
messageCollector.report(
INFO,
"IC $invalidationType cache up-to-date check duration: ${System.currentTimeMillis() - start}ms"
)
}
return OK
}
@@ -281,7 +280,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
}
if (arguments.irProduceJs) {
messageCollector.report(INFO,"Produce executable: $outputFilePath")
messageCollector.report(INFO, "Produce executable: $outputFilePath")
messageCollector.report(INFO, arguments.cacheDirectories ?: "")
if (icCaches.isNotEmpty()) {
@@ -384,68 +383,80 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
arguments.irPerFile -> JsGenerationGranularity.PER_FILE
else -> JsGenerationGranularity.WHOLE_PROGRAM
}
val ir = compile(
module,
phaseConfig,
if (arguments.irDceDriven) PersistentIrFactory() else IrFactoryImpl,
dceRuntimeDiagnostic = RuntimeDiagnostic.resolve(
arguments.irDceRuntimeDiagnostic,
messageCollector
),
dceDriven = arguments.irDceDriven,
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
safeExternalBoolean = arguments.irSafeExternalBoolean,
safeExternalBooleanDiagnostic = RuntimeDiagnostic.resolve(
arguments.irSafeExternalBooleanDiagnostic,
messageCollector
),
lowerPerModule = false,//icCaches.isNotEmpty(),
granularity = granularity,
icCompatibleIr2Js = arguments.irNewIr2Js,
)
val compiledModule: CompilerResult = if (arguments.irNewIr2Js) {
val transformer = IrModuleToJsTransformerTmp(
ir.context,
mainCallArguments,
fullJs = true,
dceJs = arguments.irDce,
multiModule = arguments.irPerModule,
relativeRequirePath = false,
try {
val ir = compile(
module,
phaseConfig,
if (arguments.irDceDriven) PersistentIrFactory() else IrFactoryImpl,
dceRuntimeDiagnostic = RuntimeDiagnostic.resolve(
arguments.irDceRuntimeDiagnostic,
messageCollector
),
dceDriven = arguments.irDceDriven,
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
safeExternalBoolean = arguments.irSafeExternalBoolean,
safeExternalBooleanDiagnostic = RuntimeDiagnostic.resolve(
arguments.irSafeExternalBooleanDiagnostic,
messageCollector
),
lowerPerModule = false,//icCaches.isNotEmpty(),
granularity = granularity,
icCompatibleIr2Js = arguments.irNewIr2Js,
)
transformer.generateModule(ir.allModules)
} else {
val transformer = IrModuleToJsTransformer(
ir.context,
mainCallArguments,
fullJs = true,
dceJs = arguments.irDce,
multiModule = arguments.irPerModule,
relativeRequirePath = false
val compiledModule: CompilerResult = if (arguments.irNewIr2Js) {
val transformer = IrModuleToJsTransformerTmp(
ir.context,
mainCallArguments,
fullJs = true,
dceJs = arguments.irDce,
multiModule = arguments.irPerModule,
relativeRequirePath = false,
)
transformer.generateModule(ir.allModules)
} else {
val transformer = IrModuleToJsTransformer(
ir.context,
mainCallArguments,
fullJs = true,
dceJs = arguments.irDce,
multiModule = arguments.irPerModule,
relativeRequirePath = false,
)
transformer.generateModule(ir.allModules)
}
messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms")
val outputs = if (arguments.irDce && !arguments.irDceDriven)
compiledModule.outputsAfterDce!!
else
compiledModule.outputs!!
outputFile.write(outputs)
outputs.dependencies.forEach { (name, content) ->
outputFile.resolveSibling("$name.js").write(content)
}
if (arguments.generateDts) {
val dtsFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "d.ts")!!
dtsFile.writeText(compiledModule.tsDefinitions ?: error("No ts definitions"))
}
} catch (e: CompilationException) {
messageCollector.report(
ERROR,
e.stackTraceToString(),
CompilerMessageLocation.create(
path = e.path,
line = e.line,
column = e.column,
lineContent = e.content
)
)
transformer.generateModule(ir.allModules)
}
messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms")
val outputs = if (arguments.irDce && !arguments.irDceDriven)
compiledModule.outputsAfterDce!!
else
compiledModule.outputs!!
outputFile.write(outputs)
outputs.dependencies.forEach { (name, content) ->
outputFile.resolveSibling("$name.js").write(content)
}
if (arguments.generateDts) {
val dtsFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "d.ts")!!
dtsFile.writeText(compiledModule.tsDefinitions ?: error("No ts definitions"))
return INTERNAL_ERROR
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2010-2021 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.backend.common
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.path
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.dumpKotlinLike
import org.jetbrains.kotlin.ir.util.fileOrNull
class CompilationException(
message: String,
// file is not known in any moment, need to set it later in catch to save stacktrace
var file: IrFile?,
val ir: Any?, /* IrElement | IrType */
cause: Throwable? = null
) : RuntimeException(message, cause) {
override val message: String
get() = buildString {
appendLine("Back-end: Please report this problem https://kotl.in/issue")
path?.let { appendLine("$it:$line:$column") }
content?.let { appendLine("Problem with `$it`") }
append("Details: " + super.message)
}
val line: Int
get() {
val irStartOffset = irStartOffset
?: return UNDEFINED_OFFSET
val lineNumber = file?.fileEntry?.getLineNumber(irStartOffset)
?: return UNDEFINED_OFFSET
return lineNumber + 1
}
val column: Int
get() {
val irStartOffset = irStartOffset
?: return UNDEFINED_OFFSET
val columnNumber = file?.fileEntry?.getColumnNumber(irStartOffset)
?: return UNDEFINED_OFFSET
return columnNumber + 1
}
private val irStartOffset: Int?
get() = (ir as? IrElement)?.startOffset
val path: String?
get() = file?.path
val content: String?
get() = when (ir) {
is IrElement -> ir.dumpKotlinLike()
is IrType -> ir.dumpKotlinLike()
else -> null
}
}
fun compilationException(message: String, element: IrElement): Nothing {
throw CompilationException(message, null, element)
}
fun compilationException(message: String, type: IrType?): Nothing {
throw CompilationException(message, null, type)
}
fun compilationException(message: String, declaration: IrDeclaration): Nothing {
val file = try {
declaration.fileOrNull
} catch (e: Throwable) {
null
}
throw CompilationException(message, file, declaration)
}
fun Throwable.wrapWithCompilationException(
message: String,
file: IrFile,
element: IrElement?
): CompilationException {
return CompilationException(
"$message: ${this::class.qualifiedName}: ${this.message}",
file,
element,
cause = this
).apply {
stackTrace = this@wrapWithCompilationException.stackTrace
}
}
@@ -67,7 +67,22 @@ interface BodyAndScriptBodyLoweringPass : BodyLoweringPass {
override fun lower(irFile: IrFile) = runOnFilePostfix(irFile)
}
fun FileLoweringPass.lower(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { lower(it) }
fun FileLoweringPass.lower(
moduleFragment: IrModuleFragment
) = moduleFragment.files.forEach {
try {
lower(it)
} catch (e: CompilationException) {
e.file = it
throw e
} catch (e: Throwable) {
throw e.wrapWithCompilationException(
"Internal error in file lowering",
it,
null
)
}
}
fun ClassLoweringPass.runOnFilePostfix(irFile: IrFile) {
irFile.acceptVoid(ClassLoweringVisitor(this))
@@ -128,7 +143,18 @@ fun BodyLoweringPass.runOnFilePostfix(
) {
val visitor = BodyLoweringVisitor(this, withLocalDeclarations, allowDeclarationModification)
for (declaration in ArrayList(irFile.declarations)) {
declaration.accept(visitor, null)
try {
declaration.accept(visitor, null)
} catch (e: CompilationException) {
e.file = irFile
throw e
} catch (e: Throwable) {
throw e.wrapWithCompilationException(
"Internal error in body lowering",
irFile,
declaration
)
}
}
}
@@ -214,8 +240,19 @@ interface DeclarationTransformer : FileLoweringPass {
override fun lower(irFile: IrFile) {
val visitor = Visitor(this)
irFile.declarations.transformFlat { declaration ->
declaration.acceptVoid(visitor)
transformFlatRestricted(declaration)
try {
declaration.acceptVoid(visitor)
transformFlatRestricted(declaration)
} catch (e: CompilationException) {
e.file = irFile
throw e
} catch (e: Throwable) {
throw e.wrapWithCompilationException(
"Internal error in declaration transformer",
irFile,
declaration
)
}
}
}
@@ -62,6 +62,7 @@ class JsIrBackendContext(
val granularity: JsGenerationGranularity = JsGenerationGranularity.WHOLE_PROGRAM,
val icCompatibleIr2Js: Boolean = false,
) : JsCommonBackendContext {
val fileToInitializationFuns: MutableMap<IrFile, IrSimpleFunction?> = mutableMapOf()
val fileToInitializerPureness: MutableMap<IrFile, Boolean> = mutableMapOf()
val fieldToInitializer: MutableMap<IrField, IrExpression> = mutableMapOf()
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.lower.AbstractValueUsageTransformer
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
@@ -33,7 +34,7 @@ abstract class AbstractValueUsageLowering(val context: JsCommonBackendContext) :
val replacement = container.transform(this, null) as IrDeclaration
if (container !== replacement) error("Declaration has changed: ${container}")
if (container !== replacement) compilationException("Declaration has changed", container)
// TODO: Track & insert parents for temporary variables
irBody.patchDeclarationParents(container as? IrDeclarationParent ?: container.parent)
@@ -7,21 +7,21 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
import org.jetbrains.kotlin.backend.common.ir.isPure
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.backend.common.ir.isPure
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.transformStatement
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
@@ -620,11 +620,17 @@ class BlockDecomposerTransformer(
)
expression.receiver = newArguments[0]
?: error("No new receiver in destructured composite for:\n${expression.dump()}")
?: compilationException(
"No new receiver in destructured composite",
expression
)
for (i in expression.arguments.indices) {
expression.arguments[i] = newArguments[i + 1]
?: error("No argument #$i in destructured composite for:\n${expression.dump()}")
?: compilationException(
"No argument #$i in destructured composite",
expression
)
}
newStatements.add(expression)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.ir.moveBodyTo
@@ -120,7 +121,11 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
private val referenceType = reference.type as IrSimpleType
private val superFunctionInterface: IrClass = referenceType.classOrNull?.owner ?: error("Expected functional type")
private val superFunctionInterface: IrClass = referenceType.classOrNull?.owner
?: compilationException(
"Expected functional type",
reference
)
private val isKReference = superFunctionInterface.name.identifier[0] == 'K'
// If we implement KFunctionN we also need FunctionN
@@ -324,7 +329,7 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
JsStatementOrigins.CALLABLE_REFERENCE_INVOKE
)
else ->
error("unknown function kind: ${callee.render()}")
compilationException("unknown function kind", callee)
}
}
@@ -411,7 +416,11 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
.filterIsInstance<IrProperty>()
.single { it.name == Name.identifier("name") } // In K/Wasm interfaces can have fake overridden properties from Any
val supperGetter = superProperty.getter ?: error("Expected getter for KFunction.name property")
val supperGetter = superProperty.getter
?: compilationException(
"Expected getter for KFunction.name property",
superProperty
)
val nameProperty = clazz.addProperty() {
visibility = superProperty.visibility
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
@@ -158,7 +159,7 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
return createSimpleKType(type, visitedTypeParams)
if (type is IrDynamicType)
return createDynamicType()
error("Unexpected type $type")
compilationException("Unexpected type", type)
}
private fun createDynamicType(): IrExpression {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
@@ -55,7 +56,7 @@ class ConstTransformer(private val context: JsIrBackendContext) : IrElementTrans
uLongClassSymbol -> lowerConst(uLongClassSymbol, { _, _, _, v -> createLong(v) }, IrConstKind.Long.valueOf(expression))
else -> error("Unknown unsigned type")
else -> compilationException("Unknown unsigned type", expression)
}
}
return when {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyToWithoutSuperTypes
import org.jetbrains.kotlin.backend.common.lower.LoweredStatementOrigins
@@ -61,7 +62,7 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
}
override fun lower(irBody: IrBody, container: IrDeclaration) {
error("Unreachable")
compilationException("Unreachable", irBody)
}
private inner class CallableReferenceClassTransformer(private val ctorToFactoryMap: MutableMap<IrConstructorSymbol, IrSimpleFunctionSymbol>) : IrElementTransformerVoid() {
@@ -109,7 +110,11 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
invokeMapping: Map<IrValueParameterSymbol, IrValueParameterSymbol>,
factoryMapping: Map<IrFieldSymbol, IrValueParameterSymbol>
): IrBlockBody {
val body = invokeFun.body ?: error("invoke() method has to have a body")
val body = invokeFun.body
?: compilationException(
"invoke() method has to have a body",
invokeFun
)
fun IrExpression.getValue(d: IrValueSymbol): IrExpression = IrGetValueImpl(startOffset, endOffset, d)
fun IrExpression.getCastedValue(d: IrValueSymbol, toType: IrType): IrExpression =
@@ -180,7 +185,11 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
}
private fun capturedFieldsToParametersMap(constructor: IrConstructor, factoryFunction: IrSimpleFunction): Map<IrFieldSymbol, IrValueParameterSymbol> {
val statements = constructor.body?.let { it.cast<IrBlockBody>().statements } ?: error("Expecting Body for function ref constructor")
val statements = constructor.body?.let { it.cast<IrBlockBody>().statements }
?: compilationException(
"Expecting Body for function ref constructor",
constructor
)
val fieldSetters = statements.filterIsInstance<IrSetField>()
.filter { it.origin == LoweredStatementOrigins.STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE }
@@ -193,7 +202,11 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
}
private fun extractReferenceReflectionName(getter: IrSimpleFunction): IrExpression {
val body = getter.body?.cast<IrBlockBody>() ?: error("Expected body for ${getter.render()}")
val body = getter.body?.cast<IrBlockBody>()
?: compilationException(
"Expected body",
getter
)
val statements = body.statements
val returnStmt = statements[0] as IrReturn
@@ -6,23 +6,20 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
import org.jetbrains.kotlin.ir.util.render
// JS PIR (and IC) requires DeclarationTransformer instead of FileLoweringPass
@@ -55,13 +52,16 @@ class JsAnnotationImplementationTransformer(val jsContext: JsIrBackendContext) :
when {
type.isPrimitiveArray() -> arraysContentEquals[type]
else -> arraysContentEquals.entries.singleOrNull { (k, _) -> k.isArray() }?.value
} ?: error("Can't find an Arrays.contentEquals method for array type ${type.render()}")
} ?: compilationException("Can't find an Arrays.contentEquals method for array type", type)
override fun implementAnnotationPropertiesAndConstructor(
implClass: IrClass,
annotationClass: IrClass,
generatedConstructor: IrConstructor
) {
throw IllegalStateException("Should not be called")
compilationException(
"Should not be called",
implClass
)
}
}
@@ -5,11 +5,8 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
@@ -30,14 +27,12 @@ import org.jetbrains.kotlin.ir.expressions.IrContainerExpression
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.dumpKotlinLike
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addIfNotNull
import java.lang.IllegalStateException
// Outlines `kotlin.js.js(code: String)` calls where JS code references Kotlin locals.
// Makes locals usages explicit.
@@ -96,7 +91,11 @@ private class JsCodeOutlineTransformer(
val name = irValueDeclaration.name
if (!name.isSpecial) {
val identifier = name.identifier
val currentScope = localScopes.lastOrNull() ?: error("Expecting a scope")
val currentScope = localScopes.lastOrNull()
?: compilationException(
"Expecting a scope",
irValueDeclaration
)
currentScope[identifier] = irValueDeclaration
}
}
@@ -133,7 +132,11 @@ private class JsCodeOutlineTransformer(
if (expression.symbol != backendContext.intrinsics.jsCode)
return null
val jsCodeArg = expression.getValueArgument(0) ?: error("Expected js code string")
val jsCodeArg = expression.getValueArgument(0)
?: compilationException(
"Expected js code string",
expression
)
val jsStatements = translateJsCodeIntoStatementList(jsCodeArg, backendContext) ?: return null
// Collect used Kotlin local variables and parameters.
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.getOrPut
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
@@ -18,7 +19,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.name.Name
class JsInnerClassesSupport(mapping: JsMapping, private val irFactory: IrFactory) : InnerClassesSupport {
@@ -27,11 +27,17 @@ class JsInnerClassesSupport(mapping: JsMapping, private val irFactory: IrFactory
private val originalInnerClassPrimaryConstructorByClass = mapping.originalInnerClassPrimaryConstructorByClass
override fun getOuterThisField(innerClass: IrClass): IrField =
if (!innerClass.isInner) throw AssertionError("Class is not inner: ${innerClass.dump()}")
if (!innerClass.isInner) compilationException(
"Class is not inner",
innerClass
)
else {
outerThisFieldSymbols.getOrPut(innerClass) {
val outerClass = innerClass.parent as? IrClass
?: throw AssertionError("No containing class for inner class ${innerClass.dump()}")
?: compilationException(
"No containing class for inner class",
innerClass
)
irFactory.buildField {
origin = IrDeclarationOrigin.FIELD_FOR_OUTER_THIS
@@ -8,10 +8,10 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.ir.util.render
class JsSingleAbstractMethodLowering(context: CommonBackendContext) : SingleAbstractMethodLowering(context), BodyLoweringPass {
@@ -60,6 +59,7 @@ class JsSingleAbstractMethodLowering(context: CommonBackendContext) : SingleAbst
// FE doesn't allow type parameters for now.
// And since there is a to-do in common SingleAbstractMethodLowering (at function visitTypeOperator),
// we don't have to be more saint than a pope here.
return typeOperand.classOrNull?.defaultType ?: error("Unsupported SAM conversion: ${typeOperand.render()}")
return typeOperand.classOrNull?.defaultType
?: compilationException("Unsupported SAM conversion", typeOperand)
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
@@ -14,10 +15,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl
import org.jetbrains.kotlin.ir.util.constructedClass
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.name.FqName
@@ -134,7 +132,10 @@ fun validateIsExternal(packageFragment: IrPackageFragment) {
fun validateNestedExternalDeclarations(declaration: IrDeclaration, isExternalTopLevel: Boolean) {
fun IrPossiblyExternalDeclaration.checkExternal() {
if (isExternal != isExternalTopLevel) {
error("isExternal validation failed for declaration ${declaration.render()}")
compilationException(
"isExternal validation failed for declaration",
declaration,
)
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
@@ -118,7 +119,10 @@ class PrivateMembersLowering(val context: JsIrBackendContext) : DeclarationTrans
expression = (it.copyWithParameters() as IrExpressionBody).expression
}
is IrSyntheticBody -> it
else -> error("Unexpected body kind: ${it.javaClass}")
else -> compilationException(
"Unexpected body kind",
it,
)
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.isPure
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities.INTERNAL
@@ -266,7 +267,10 @@ private val IrDeclaration.correspondingProperty: IrProperty?
is IrField -> propertyWithPersistentSafe {
correspondingPropertySymbol?.owner
}
else -> error("Can be only IrProperty, IrSimpleFunction or IrField")
else -> compilationException(
"Can be only IrProperty, IrSimpleFunction or IrField",
this
)
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
@@ -20,7 +21,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
@@ -101,7 +101,11 @@ class PropertyReferenceLowering(private val context: JsIrBackendContext) : BodyL
}
private fun buildGetterLambda(factory: IrSimpleFunction, reference: IrPropertyReference, boundValueParameters: List<IrValueParameter>): IrExpression {
val getter = reference.getter?.owner ?: error("Getter expected")
val getter = reference.getter?.owner
?: compilationException(
"Getter expected",
reference
)
return buildAccessorLambda(factory, getter, reference, boundValueParameters)
}
@@ -117,10 +121,17 @@ class PropertyReferenceLowering(private val context: JsIrBackendContext) : BodyL
val superName = when (accessor.symbol) {
reference.getter -> "get"
reference.setter -> "set"
else -> error("Unexpected accessor ${accessor.render()}")
else -> compilationException(
"Unexpected accessor",
accessor
)
}
val classifier = (reference.type as IrSimpleType).classOrNull ?: error("Simple type expected")
val classifier = (reference.type as IrSimpleType).classOrNull
?: compilationException(
"Simple type expected",
reference
)
val supperAccessor =
classifier.owner.declarations.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == superName }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.getOrPut
import org.jetbrains.kotlin.backend.common.ir.ValueRemapper
import org.jetbrains.kotlin.backend.common.ir.copyTo
@@ -264,7 +265,11 @@ private class CallsiteRedirectionTransformer(private val context: JsIrBackendCon
val target = expression.symbol.owner
return if (target.isSecondaryConstructorCall) {
val factory = with(context) {
if (es6mode) mapping.secondaryConstructorToDelegate[target] ?: error("Not found IrFunction for secondary ctor")
if (es6mode) mapping.secondaryConstructorToDelegate[target]
?: compilationException(
"Not found IrFunction for secondary ctor",
expression
)
else buildConstructorFactory(target, target.parentAsClass)
}
replaceSecondaryConstructorWithFactoryFunction(expression, factory.symbol)
@@ -279,7 +284,11 @@ private class CallsiteRedirectionTransformer(private val context: JsIrBackendCon
return if (target.isSecondaryConstructorCall) {
val klass = target.parentAsClass
val delegate = with(context) {
if (es6mode) mapping.secondaryConstructorToDelegate[target] ?: error("Not found IrFunction for secondary ctor")
if (es6mode) mapping.secondaryConstructorToDelegate[target]
?: compilationException(
"Not found IrFunction for secondary ctor",
expression
)
else buildConstructorDelegate(target, klass)
}
val newCall = replaceSecondaryConstructorWithFactoryFunction(expression, delegate.symbol)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.isPure
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
@@ -262,7 +263,11 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass {
private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: IrType): IrExpression {
val typeParameterSymbol =
(toType.classifierOrNull as? IrTypeParameterSymbol) ?: error("expected type parameter, but $toType")
(toType.classifierOrNull as? IrTypeParameterSymbol)
?: compilationException(
"expected type parameter, but $toType",
argument
)
val typeParameter = typeParameterSymbol.owner
@@ -371,7 +376,10 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass {
toType.isLong() -> JsIrBuilder.buildCall(context.intrinsics.jsToLong).apply {
putValueArgument(0, argument())
}
else -> error("Unreachable execution (coercion to non-Integer type")
else -> compilationException(
"Unreachable execution (coercion to non-Integer type)",
expression
)
}
newStatements += if (isNullable) JsIrBuilder.buildIfElse(toType, nullCheck(argument()), litNull, casted) else casted
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower.calls
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
@@ -27,7 +28,10 @@ class EnumIntrinsicsTransformer(private val context: JsIrBackendContext) : Calls
if (!enum.isEnumClass) return call
val staticMethod = enum.findDeclaration(staticMethodPredicate)
if (staticMethod == null || !staticMethod.isStaticMethodOfClass)
throw IllegalStateException("Enum class should have static method for ${call.symbol.owner.name}")
compilationException(
"Enum class should have static method for ${call.symbol.owner.name}",
call
)
return irCall(call, staticMethod.symbol)
}
@@ -364,7 +364,11 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
val thisReceiver = this.dispatchReceiverParameter!!
val boundFields =
context.mapping.capturedFields[coroutineClass] ?: error("No captured values for class ${coroutineClass.render()}")
context.mapping.capturedFields[coroutineClass]
?: compilationException(
"No captured values",
coroutineClass
)
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
@@ -393,7 +397,11 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
private fun transformInvokeMethod(createFunction: IrSimpleFunction, stateMachineFunction: IrSimpleFunction) {
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
val thisReceiver = function.dispatchReceiverParameter ?: error("Expected dispatch receiver for invoke")
val thisReceiver = function.dispatchReceiverParameter
?: compilationException(
"Expected dispatch receiver for invoke",
function
)
val functionBody = function.body as IrBlockBody
functionBody.statements.clear()
functionBody.statements.addAll(irBuilder.irBlockBody(startOffset, endOffset) {
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
@@ -58,8 +59,14 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
is IrConstKind.Byte -> JsIntLiteral(kind.valueOf(expression).toInt())
is IrConstKind.Short -> JsIntLiteral(kind.valueOf(expression).toInt())
is IrConstKind.Int -> JsIntLiteral(kind.valueOf(expression))
is IrConstKind.Long -> throw IllegalStateException("Long const should have been lowered at this point")
is IrConstKind.Char -> throw IllegalStateException("Char const should have been lowered at this point")
is IrConstKind.Long -> compilationException(
"Long const should have been lowered at this point",
expression
)
is IrConstKind.Char -> compilationException(
"Char const should have been lowered at this point",
expression
)
is IrConstKind.Float -> JsDoubleLiteral(toDoubleConst(kind.valueOf(expression)))
is IrConstKind.Double -> JsDoubleLiteral(kind.valueOf(expression))
}.withSource(expression, context)
@@ -98,7 +105,11 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
"${field.render()} in non-external class ${fieldParent.render()}"
}
val receiver = expression.receiver?.accept(this, context) ?: error("Expect expression.receiver to not be null")
val receiver = expression.receiver?.accept(this, context)
?: compilationException(
"Expect expression.receiver to not be null",
expression
)
return JsNameRef(field.getJsNameOrKotlinName().identifier, receiver).withSource(expression, context)
}
@@ -204,9 +215,16 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
override fun visitCall(expression: IrCall, context: JsGenerationContext): JsExpression {
if (context.checkIfJsCode(expression.symbol)) {
val statements = translateJsCodeIntoStatementList(
expression.getValueArgument(0) ?: error("JsCode is expected"),
expression.getValueArgument(0)
?: compilationException(
"JsCode is expected",
expression
),
context.staticContext.backendContext
) ?: error("Cannot compute js code for ${expression.render()}")
) ?: compilationException(
"Cannot compute js code",
expression
)
if (statements.isEmpty()) return JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(3)) // TODO: report warning or even error
@@ -250,7 +268,10 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: JsGenerationContext): JsExpression {
return when (expression.operator) {
IrTypeOperator.REINTERPRET_CAST -> expression.argument.accept(this, data)
else -> error("All type operator calls except REINTERPRET_CAST should be lowered at this point: ${expression.operator}")
else -> compilationException(
"All type operator calls except REINTERPRET_CAST should be lowered at this point",
expression
)
}.withSource(expression, data)
}
@@ -305,14 +326,20 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
expression.arguments.map { it.accept(this, data) }
)
else -> error("Unexpected operator ${expression.operator}: ${expression.render()}")
else -> compilationException(
"Unexpected operator ${expression.operator}",
expression
)
}.withSource(expression, data)
override fun visitRawFunctionReference(expression: IrRawFunctionReference, data: JsGenerationContext): JsExpression {
val name = when (val function = expression.symbol.owner) {
is IrConstructor -> data.getNameForConstructor(function)
is IrSimpleFunction -> data.getNameForStaticFunction(function)
else -> error("Unexpected function kind")
else -> compilationException(
"Unexpected function kind",
expression
)
}
return JsNameRef(name).withSource(expression, data)
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
@@ -134,9 +135,16 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
override fun visitCall(expression: IrCall, data: JsGenerationContext): JsStatement {
if (data.checkIfJsCode(expression.symbol)) {
val statements = translateJsCodeIntoStatementList(
expression.getValueArgument(0) ?: error("JsCode is expected"),
expression.getValueArgument(0)
?: compilationException(
"JsCode is expected",
expression
),
data.staticContext.backendContext
) ?: error("Cannot compute js code for ${expression.render()}")
) ?: compilationException(
"Cannot compute js code",
expression
)
return when (statements.size) {
0 -> JsEmpty
1 -> statements.single().withSource(expression, data)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.backend.js.export.isAllowedFakeOverriddenDeclaration
@@ -94,7 +95,10 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
is IrField -> {
}
else -> {
error("Unexpected declaration in class: ${declaration.render()}")
compilationException(
"Unexpected declaration in class",
declaration
)
}
}
}
@@ -5,17 +5,21 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.*
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.backend.js.utils.getClassRef
import org.jetbrains.kotlin.ir.backend.js.utils.invokeFunForLambda
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.getInlineClassBackingField
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.js.backend.ast.*
typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression
@@ -91,7 +95,10 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
add(intrinsics.jsClass) { call, context ->
val typeArgument = call.getTypeArgument(0)
typeArgument?.getClassRef(context)
?: error("Type argument of jsClass must be statically known class, but " + typeArgument?.render())
?: compilationException(
"Type argument of jsClass must be statically known class",
typeArgument
)
}
add(intrinsics.jsNewTarget) { _, _ ->
@@ -116,7 +123,12 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
typeArgument.getClassRef(context)
}
addIfNotNull(intrinsics.jsCode) { _, _ -> error("Should not be called") }
addIfNotNull(intrinsics.jsCode) { call, _ ->
compilationException(
"Should not be called",
call
)
}
add(intrinsics.jsArrayLength) { call, context ->
val args = translateCallArguments(call, context)
@@ -96,7 +96,7 @@ private class JsIrModuleCrossModuleReferecenceBuilder(val module: JsIrModule, va
}.internalName
}
val tagToName = module.fragments.flatMap { it.nameBindings.entries}.associate { it.key to it.value }
val tagToName = module.fragments.flatMap { it.nameBindings.entries }.associate { it.key to it.value }
val resultImports = imports.associate {
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
import org.jetbrains.kotlin.backend.common.ir.isSuspend
import org.jetbrains.kotlin.ir.IrElement
@@ -159,7 +160,10 @@ fun translateCall(
return when (function) {
property.getter -> nameRef
property.setter -> jsAssignment(nameRef, arguments.single())
else -> error("Function must be an accessor of corresponding property")
else -> compilationException(
"Function must be an accessor of corresponding property",
function
)
}
}
}
@@ -5,23 +5,23 @@
package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.collectRealOverrides
import org.jetbrains.kotlin.ir.util.render
val IrFunction.realOverrideTarget: IrFunction
get() = when (this) {
is IrSimpleFunction -> this.realOverrideTarget
is IrConstructor -> this
else -> error(this)
else -> compilationException("Unexpected declaration", this)
}
val IrSimpleFunction.realOverrideTarget: IrSimpleFunction
get(): IrSimpleFunction {
val realOverrides = collectRealOverrides()
return realOverrides.find { it.modality != Modality.ABSTRACT } ?: realOverrides.firstOrNull() ?:
error("No real override target found for ${this.render()}")
return realOverrides.find { it.modality != Modality.ABSTRACT } ?: realOverrides.firstOrNull()
?: compilationException("No real override target found", this)
}