[FIR2IR] Introduce staged transformation (first step)
Now FE IR -> BE IR transformation is performed in multiple stages controller by Fir2IrConverter. Stages are * files & classes registration * supertypes & type parameters handling * functions & properties signature generation * body generation After each step we have guarantee (with exception of local classes & type inference combination, and external symbols) that required symbols (class/function/property/variable/type parameter) are already bound to real declarations and have correct parents. This commit also fixes incorrect parents for local classes
This commit is contained in:
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiCompiledElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
@@ -216,3 +217,6 @@ internal fun FirReference.statementOrigin(): IrStatementOrigin? {
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
|
||||
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
|
||||
@@ -17,8 +17,6 @@ class Fir2IrCallableCache {
|
||||
|
||||
private val variableCache = mutableMapOf<FirVariable<*>, IrVariable>()
|
||||
|
||||
private val localClassCache = mutableMapOf<FirClass<*>, IrClass>()
|
||||
|
||||
private val localFunctionCache = mutableMapOf<FirFunction<*>, IrSimpleFunction>()
|
||||
|
||||
fun getParameter(parameter: FirValueParameter): IrValueParameter? = parameterCache[parameter]
|
||||
@@ -33,13 +31,6 @@ class Fir2IrCallableCache {
|
||||
variableCache[firVariable] = irVariable
|
||||
}
|
||||
|
||||
fun getLocalClass(localClass: FirClass<*>): IrClass? = localClassCache[localClass]
|
||||
|
||||
fun putLocalClass(localClass: FirClass<*>, irClass: IrClass) {
|
||||
require(localClass !is FirRegularClass || localClass.visibility == Visibilities.LOCAL)
|
||||
localClassCache[localClass] = irClass
|
||||
}
|
||||
|
||||
fun getLocalFunction(localFunction: FirFunction<*>): IrSimpleFunction? = localFunctionCache[localFunction]
|
||||
|
||||
fun putLocalFunction(localFunction: FirFunction<*>, irFunction: IrSimpleFunction) {
|
||||
@@ -50,7 +41,6 @@ class Fir2IrCallableCache {
|
||||
fun clear() {
|
||||
parameterCache.clear()
|
||||
variableCache.clear()
|
||||
localClassCache.clear()
|
||||
localFunctionCache.clear()
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,8 @@ class Fir2IrConversionScope {
|
||||
return parent
|
||||
}
|
||||
|
||||
fun parentFromStack(): IrDeclarationParent = parentStack.last()
|
||||
|
||||
fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T {
|
||||
declaration.parent = parentStack.last()
|
||||
return declaration
|
||||
|
||||
@@ -7,58 +7,207 @@ package org.jetbrains.kotlin.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
|
||||
object Fir2IrConverter {
|
||||
class Fir2IrConverter(
|
||||
private val moduleDescriptor: FirModuleDescriptor,
|
||||
private val sourceManager: PsiSourceManager,
|
||||
private val declarationStorage: Fir2IrDeclarationStorage
|
||||
) {
|
||||
|
||||
fun createModuleFragment(
|
||||
session: FirSession,
|
||||
firFiles: List<FirFile>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
fakeOverrideMode: FakeOverrideMode = FakeOverrideMode.NORMAL,
|
||||
signaturer: IdSignatureComposer
|
||||
): Fir2IrResult {
|
||||
val moduleDescriptor = FirModuleDescriptor(session)
|
||||
val symbolTable = SymbolTable(signaturer)
|
||||
val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
|
||||
val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings, moduleDescriptor.builtIns)
|
||||
constantValueGenerator.typeTranslator = typeTranslator
|
||||
typeTranslator.constantValueGenerator = constantValueGenerator
|
||||
val builtIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable)
|
||||
val sourceManager = PsiSourceManager()
|
||||
val fir2irVisitor = Fir2IrVisitor(session, moduleDescriptor, symbolTable, sourceManager, builtIns, fakeOverrideMode)
|
||||
val irFiles = mutableListOf<IrFile>()
|
||||
for (firFile in firFiles) {
|
||||
fir2irVisitor.registerFile(firFile)
|
||||
}
|
||||
for (firFile in firFiles) {
|
||||
val irFile = firFile.accept(fir2irVisitor, null) as IrFile
|
||||
val fileEntry = sourceManager.getOrCreateFileEntry(firFile.psi as KtFile)
|
||||
sourceManager.putFileEntry(irFile, fileEntry)
|
||||
irFiles += irFile
|
||||
}
|
||||
|
||||
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, irFiles)
|
||||
generateUnboundSymbolsAsDependencies(irModuleFragment, symbolTable, builtIns)
|
||||
return Fir2IrResult(irModuleFragment, symbolTable, sourceManager)
|
||||
fun processLocalClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent) {
|
||||
val irClass = registerClassAndNestedClasses(regularClass, parent)
|
||||
processClassAndNestedClassHeaders(regularClass)
|
||||
processClassMembers(regularClass, irClass)
|
||||
}
|
||||
|
||||
private fun generateUnboundSymbolsAsDependencies(
|
||||
irModule: IrModuleFragment,
|
||||
symbolTable: SymbolTable,
|
||||
builtIns: IrBuiltIns
|
||||
) {
|
||||
// TODO: provide StubGeneratorExtensions for correct lazy stub IR generation on JVM
|
||||
ExternalDependenciesGenerator(symbolTable, generateTypicalIrProviderList(irModule.descriptor, builtIns, symbolTable))
|
||||
.generateUnboundSymbolsAsDependencies()
|
||||
fun processRegisteredLocalClassAndNestedClasses(regularClass: FirRegularClass, irClass: IrClass) {
|
||||
regularClass.declarations.forEach {
|
||||
if (it is FirRegularClass) {
|
||||
registerClassAndNestedClasses(it, irClass)
|
||||
}
|
||||
}
|
||||
processClassAndNestedClassHeaders(regularClass)
|
||||
processClassMembers(regularClass, irClass)
|
||||
}
|
||||
|
||||
fun registerFileAndClasses(file: FirFile) {
|
||||
val irFile = IrFileImpl(
|
||||
sourceManager.getOrCreateFileEntry(file.psi as KtFile),
|
||||
moduleDescriptor.getPackage(file.packageFqName).fragments.first()
|
||||
)
|
||||
declarationStorage.registerFile(file, irFile)
|
||||
file.declarations.forEach {
|
||||
if (it is FirRegularClass) {
|
||||
registerClassAndNestedClasses(it, irFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun processClassHeaders(file: FirFile) {
|
||||
file.declarations.forEach {
|
||||
if (it is FirRegularClass) {
|
||||
processClassAndNestedClassHeaders(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun processFileAndClassMembers(file: FirFile) {
|
||||
val irFile = declarationStorage.getIrFile(file)
|
||||
for (declaration in file.declarations) {
|
||||
val irDeclaration = processMemberDeclaration(declaration, irFile) ?: continue
|
||||
irFile.declarations += irDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
fun processAnonymousObjectMembers(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
irClass: IrClass = declarationStorage.getCachedIrClass(anonymousObject)!!
|
||||
): IrClass {
|
||||
anonymousObject.getPrimaryConstructorIfAny()?.let {
|
||||
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
|
||||
}
|
||||
for (declaration in anonymousObject.declarations) {
|
||||
if (declaration is FirRegularClass) {
|
||||
registerClassAndNestedClasses(declaration, irClass)
|
||||
processClassAndNestedClassHeaders(declaration)
|
||||
}
|
||||
val irDeclaration = processMemberDeclaration(declaration, irClass) ?: continue
|
||||
irClass.declarations += irDeclaration
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun processClassMembers(
|
||||
regularClass: FirRegularClass,
|
||||
irClass: IrClass = declarationStorage.getCachedIrClass(regularClass)!!
|
||||
): IrClass {
|
||||
regularClass.getPrimaryConstructorIfAny()?.let {
|
||||
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
|
||||
}
|
||||
for (declaration in regularClass.declarations) {
|
||||
val irDeclaration = processMemberDeclaration(declaration, irClass) ?: continue
|
||||
irClass.declarations += irDeclaration
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun registerClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
||||
val irClass = declarationStorage.registerIrClass(regularClass, parent)
|
||||
regularClass.declarations.forEach {
|
||||
if (it is FirRegularClass) {
|
||||
registerClassAndNestedClasses(it, irClass)
|
||||
}
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun processClassAndNestedClassHeaders(regularClass: FirRegularClass) {
|
||||
declarationStorage.processClassHeader(regularClass)
|
||||
regularClass.declarations.forEach {
|
||||
if (it is FirRegularClass) {
|
||||
processClassAndNestedClassHeaders(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processMemberDeclaration(declaration: FirDeclaration, parent: IrDeclarationParent): IrDeclaration? {
|
||||
return when (declaration) {
|
||||
is FirRegularClass -> {
|
||||
processClassMembers(declaration)
|
||||
}
|
||||
is FirSimpleFunction -> {
|
||||
declarationStorage.createIrFunction(declaration, parent)
|
||||
}
|
||||
is FirProperty -> {
|
||||
declarationStorage.createIrProperty(declaration, parent)
|
||||
}
|
||||
is FirConstructor -> if (!declaration.isPrimary) {
|
||||
declarationStorage.createIrConstructor(declaration, parent as IrClass)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
is FirEnumEntry -> {
|
||||
declarationStorage.createIrEnumEntry(declaration, parent as IrClass)
|
||||
}
|
||||
is FirAnonymousInitializer -> {
|
||||
declarationStorage.createIrAnonymousInitializer(declaration, parent as IrClass)
|
||||
}
|
||||
is FirTypeAlias -> {
|
||||
// DO NOTHING
|
||||
null
|
||||
}
|
||||
else -> {
|
||||
throw AssertionError("Unexpected member: ${declaration::class}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun createModuleFragment(
|
||||
session: FirSession,
|
||||
firFiles: List<FirFile>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
fakeOverrideMode: FakeOverrideMode = FakeOverrideMode.NORMAL,
|
||||
signaturer: IdSignatureComposer
|
||||
): Fir2IrResult {
|
||||
val moduleDescriptor = FirModuleDescriptor(session)
|
||||
val symbolTable = SymbolTable(signaturer)
|
||||
val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
|
||||
val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings, moduleDescriptor.builtIns)
|
||||
constantValueGenerator.typeTranslator = typeTranslator
|
||||
typeTranslator.constantValueGenerator = constantValueGenerator
|
||||
val builtIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable)
|
||||
val sourceManager = PsiSourceManager()
|
||||
val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
|
||||
val typeConverter = Fir2IrTypeConverter(session, declarationStorage, builtIns)
|
||||
declarationStorage.typeConverter = typeConverter
|
||||
typeConverter.initBuiltinTypes()
|
||||
val irFiles = mutableListOf<IrFile>()
|
||||
|
||||
val converter = Fir2IrConverter(moduleDescriptor, sourceManager, declarationStorage)
|
||||
for (firFile in firFiles) {
|
||||
converter.registerFileAndClasses(firFile)
|
||||
}
|
||||
for (firFile in firFiles) {
|
||||
converter.processClassHeaders(firFile)
|
||||
}
|
||||
for (firFile in firFiles) {
|
||||
converter.processFileAndClassMembers(firFile)
|
||||
}
|
||||
|
||||
val fir2irVisitor = Fir2IrVisitor(
|
||||
session, symbolTable, declarationStorage, converter, typeConverter, builtIns, fakeOverrideMode
|
||||
)
|
||||
for (firFile in firFiles) {
|
||||
val irFile = firFile.accept(fir2irVisitor, null) as IrFile
|
||||
val fileEntry = sourceManager.getOrCreateFileEntry(firFile.psi as KtFile)
|
||||
sourceManager.putFileEntry(irFile, fileEntry)
|
||||
irFiles += irFile
|
||||
}
|
||||
|
||||
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, irFiles)
|
||||
generateUnboundSymbolsAsDependencies(irModuleFragment, symbolTable, builtIns)
|
||||
return Fir2IrResult(irModuleFragment, symbolTable, sourceManager)
|
||||
}
|
||||
|
||||
private fun generateUnboundSymbolsAsDependencies(
|
||||
irModule: IrModuleFragment,
|
||||
symbolTable: SymbolTable,
|
||||
builtIns: IrBuiltIns
|
||||
) {
|
||||
// TODO: provide StubGeneratorExtensions for correct lazy stub IR generation on JVM
|
||||
ExternalDependenciesGenerator(symbolTable, generateTypicalIrProviderList(irModule.descriptor, builtIns, symbolTable))
|
||||
.generateUnboundSymbolsAsDependencies()
|
||||
}
|
||||
}
|
||||
}
|
||||
+127
-141
@@ -66,6 +66,8 @@ class Fir2IrDeclarationStorage(
|
||||
|
||||
private val constructorCache = mutableMapOf<FirConstructor, IrConstructor>()
|
||||
|
||||
private val initializerCache = mutableMapOf<FirAnonymousInitializer, IrAnonymousInitializer>()
|
||||
|
||||
private val propertyCache = mutableMapOf<FirProperty, IrProperty>()
|
||||
|
||||
private val fieldCache = mutableMapOf<FirField, IrField>()
|
||||
@@ -98,7 +100,8 @@ class Fir2IrDeclarationStorage(
|
||||
fun leaveScope(descriptor: DeclarationDescriptor) {
|
||||
if (descriptor is WrappedSimpleFunctionDescriptor ||
|
||||
descriptor is WrappedClassConstructorDescriptor ||
|
||||
descriptor is WrappedPropertyDescriptor
|
||||
descriptor is WrappedPropertyDescriptor ||
|
||||
descriptor is WrappedEnumEntryDescriptor
|
||||
) {
|
||||
localStorage.leaveCallable()
|
||||
}
|
||||
@@ -189,14 +192,18 @@ class Fir2IrDeclarationStorage(
|
||||
irClass.declarations += when (declaration) {
|
||||
is FirSimpleFunction -> {
|
||||
processedNames += declaration.name
|
||||
getIrFunction(declaration, irClass)
|
||||
createIrFunction(declaration, irClass)
|
||||
}
|
||||
is FirProperty -> {
|
||||
processedNames += declaration.name
|
||||
getIrProperty(declaration, irClass)
|
||||
createIrProperty(declaration, irClass)
|
||||
}
|
||||
is FirConstructor -> {
|
||||
createIrConstructor(declaration, irClass)
|
||||
}
|
||||
is FirRegularClass -> {
|
||||
createIrClass(declaration, irClass)
|
||||
}
|
||||
is FirConstructor -> getIrConstructor(declaration, irClass)
|
||||
is FirRegularClass -> getIrClass(declaration, exactlySourceClass = false)
|
||||
else -> continue
|
||||
}
|
||||
}
|
||||
@@ -210,14 +217,14 @@ class Fir2IrDeclarationStorage(
|
||||
if (functionSymbol is FirNamedFunctionSymbol) {
|
||||
val fakeOverrideSymbol =
|
||||
FirClassSubstitutionScope.createFakeOverrideFunction(session, functionSymbol.fir, functionSymbol)
|
||||
irClass.declarations += getIrFunction(fakeOverrideSymbol.fir, irClass)
|
||||
irClass.declarations += createIrFunction(fakeOverrideSymbol.fir, irClass)
|
||||
}
|
||||
}
|
||||
scope.processPropertiesByName(name) { propertySymbol ->
|
||||
if (propertySymbol is FirPropertySymbol) {
|
||||
val fakeOverrideSymbol =
|
||||
FirClassSubstitutionScope.createFakeOverrideProperty(session, propertySymbol.fir, propertySymbol)
|
||||
irClass.declarations += getIrProperty(fakeOverrideSymbol.fir, irClass)
|
||||
irClass.declarations += createIrProperty(fakeOverrideSymbol.fir, irClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,7 +235,7 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCachedIrClass(klass: FirClass<*>): IrClass? {
|
||||
fun getCachedIrClass(klass: FirClass<*>): IrClass? {
|
||||
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.LOCAL) {
|
||||
localStorage.getLocalClass(klass)
|
||||
} else {
|
||||
@@ -250,24 +257,39 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIrClass(klass: FirClass<*>, exactlySourceClass: Boolean = false): IrClass {
|
||||
private fun createIrClass(klass: FirClass<*>, parent: IrDeclarationParent? = null): IrClass {
|
||||
// NB: klass can be either FirRegularClass or FirAnonymousObject
|
||||
if (klass is FirAnonymousObject) {
|
||||
return createIrAnonymousObject(klass)
|
||||
return createIrAnonymousObject(klass, irParent = parent)
|
||||
}
|
||||
val regularClass = klass as FirRegularClass
|
||||
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val origin =
|
||||
if (exactlySourceClass || firProvider.getFirClassifierContainerFileIfAny(klass.symbol) != null) IrDeclarationOrigin.DEFINED
|
||||
if (firProvider.getFirClassifierContainerFileIfAny(klass.symbol) != null) IrDeclarationOrigin.DEFINED
|
||||
else IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
|
||||
val irClass = registerIrClass(regularClass, parent, origin)
|
||||
processClassHeader(regularClass, irClass)
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
|
||||
irClass.declareSupertypesAndTypeParameters(regularClass)
|
||||
irClass.setThisReceiver()
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun registerIrClass(
|
||||
regularClass: FirRegularClass,
|
||||
parent: IrDeclarationParent? = null,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val visibility = regularClass.visibility
|
||||
val modality = if (regularClass.classKind == ClassKind.ENUM_CLASS) {
|
||||
regularClass.enumClassModality()
|
||||
} else {
|
||||
regularClass.modality ?: Modality.FINAL
|
||||
}
|
||||
val irClass = klass.convertWithOffsets { startOffset, endOffset ->
|
||||
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
|
||||
IrClassImpl(
|
||||
startOffset,
|
||||
@@ -275,7 +297,7 @@ class Fir2IrDeclarationStorage(
|
||||
origin,
|
||||
symbol,
|
||||
regularClass.name,
|
||||
klass.classKind,
|
||||
regularClass.classKind,
|
||||
visibility,
|
||||
modality,
|
||||
isCompanion = regularClass.isCompanion,
|
||||
@@ -290,25 +312,22 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (regularClass.visibility == Visibilities.LOCAL) {
|
||||
localStorage.putLocalClass(klass, irClass)
|
||||
} else {
|
||||
classCache[klass] = irClass
|
||||
if (parent != null) {
|
||||
irClass.parent = parent
|
||||
}
|
||||
if (regularClass.visibility == Visibilities.LOCAL) {
|
||||
localStorage.putLocalClass(regularClass, irClass)
|
||||
} else {
|
||||
classCache[regularClass] = irClass
|
||||
}
|
||||
irClass.declareSupertypesAndTypeParameters(klass)
|
||||
irClass.setThisReceiver()
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun getIrClass(klass: FirClass<*>, exactlySourceClass: Boolean = true): IrClass {
|
||||
return getCachedIrClass(klass) ?: createIrClass(klass, exactlySourceClass)
|
||||
}
|
||||
|
||||
private fun createIrAnonymousObject(
|
||||
fun createIrAnonymousObject(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
visibility: Visibility = Visibilities.LOCAL,
|
||||
name: Name = Name.special("<no name provided>"),
|
||||
irParent: IrClass? = null
|
||||
irParent: IrDeclarationParent? = null
|
||||
): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
@@ -335,18 +354,9 @@ class Fir2IrDeclarationStorage(
|
||||
return result
|
||||
}
|
||||
|
||||
fun getIrAnonymousObject(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
visibility: Visibility = Visibilities.LOCAL,
|
||||
name: Name = Name.special("<no name provided>"),
|
||||
irParent: IrClass? = null
|
||||
): IrClass {
|
||||
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
|
||||
localStorage.getLocalClass(anonymousObject)?.let { return it }
|
||||
return createIrAnonymousObject(anonymousObject, visibility, name, irParent)
|
||||
}
|
||||
|
||||
private fun getIrEnumEntryClass(enumEntry: FirEnumEntry, anonymousObject: FirAnonymousObject, irParent: IrClass?): IrClass {
|
||||
return getIrAnonymousObject(anonymousObject, Visibilities.PRIVATE, enumEntry.name, irParent)
|
||||
return createIrAnonymousObject(anonymousObject, Visibilities.PRIVATE, name, irParent)
|
||||
}
|
||||
|
||||
private fun getIrTypeParameter(
|
||||
@@ -487,7 +497,7 @@ class Fir2IrDeclarationStorage(
|
||||
declareDefaultSetterParameter(type)
|
||||
} else if (function != null) {
|
||||
valueParameters = function.valueParameters.mapIndexed { index, valueParameter ->
|
||||
createAndSaveIrParameter(
|
||||
createIrParameter(
|
||||
valueParameter, index,
|
||||
useStubForDefaultValueStub = function !is FirConstructor || containingClass?.name != Name.identifier("Enum"),
|
||||
typeContext
|
||||
@@ -535,16 +545,18 @@ class Fir2IrDeclarationStorage(
|
||||
return this
|
||||
}
|
||||
|
||||
fun <T : IrFunction> T.enterLocalScope(function: FirFunction<*>): T {
|
||||
enterScope(descriptor)
|
||||
fun <T : IrFunction> T.putParametersInScope(function: FirFunction<*>): T {
|
||||
for ((firParameter, irParameter) in function.valueParameters.zip(valueParameters)) {
|
||||
irSymbolTable.introduceValueParameter(irParameter)
|
||||
localStorage.putParameter(firParameter, irParameter)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getCachedIrFunction(function: FirFunction<*>): IrSimpleFunction? {
|
||||
fun putEnumEntryClassInScope(enumEntry: FirEnumEntry, correspondingClass: IrClass) {
|
||||
localStorage.putLocalClass(enumEntry.initializer as FirAnonymousObject, correspondingClass)
|
||||
}
|
||||
|
||||
fun getCachedIrFunction(function: FirFunction<*>): IrSimpleFunction? {
|
||||
return if (function !is FirSimpleFunction || function.visibility == Visibilities.LOCAL) {
|
||||
localStorage.getLocalFunction(function)
|
||||
} else {
|
||||
@@ -552,10 +564,9 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIrFunction(
|
||||
fun createIrFunction(
|
||||
function: FirFunction<*>,
|
||||
irParent: IrDeclarationParent?,
|
||||
shouldLeaveScope: Boolean = true,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrSimpleFunction {
|
||||
val simpleFunction = function as? FirSimpleFunction
|
||||
@@ -591,9 +602,7 @@ class Fir2IrDeclarationStorage(
|
||||
result
|
||||
}.bindAndDeclareParameters(function, descriptor, irParent, isStatic = simpleFunction?.isStatic == true)
|
||||
|
||||
if (shouldLeaveScope) {
|
||||
leaveScope(created.descriptor)
|
||||
}
|
||||
leaveScope(created.descriptor)
|
||||
if (visibility == Visibilities.LOCAL) {
|
||||
localStorage.putLocalFunction(function, created)
|
||||
return created
|
||||
@@ -607,33 +616,32 @@ class Fir2IrDeclarationStorage(
|
||||
return created
|
||||
}
|
||||
|
||||
fun getIrFunction(
|
||||
function: FirFunction<*>,
|
||||
irParent: IrDeclarationParent?,
|
||||
shouldLeaveScope: Boolean = true,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrSimpleFunction {
|
||||
return getCachedIrFunction(function)?.apply {
|
||||
if (!shouldLeaveScope) enterLocalScope(function)
|
||||
} ?: createIrFunction(function, irParent, shouldLeaveScope, origin)
|
||||
fun getCachedIrAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer): IrAnonymousInitializer? =
|
||||
initializerCache[anonymousInitializer]
|
||||
|
||||
fun createIrAnonymousInitializer(
|
||||
anonymousInitializer: FirAnonymousInitializer,
|
||||
irParent: IrClass
|
||||
): IrAnonymousInitializer {
|
||||
return anonymousInitializer.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareAnonymousInitializer(startOffset, endOffset, IrDeclarationOrigin.DEFINED, irParent.descriptor).apply {
|
||||
this.parent = irParent
|
||||
initializerCache[anonymousInitializer] = this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCachedIrConstructor(
|
||||
constructor: FirConstructor
|
||||
): IrConstructor? {
|
||||
return constructorCache[constructor]
|
||||
}
|
||||
fun getCachedIrConstructor(constructor: FirConstructor): IrConstructor? = constructorCache[constructor]
|
||||
|
||||
private fun createIrConstructor(
|
||||
fun createIrConstructor(
|
||||
constructor: FirConstructor,
|
||||
irParent: IrDeclarationParent,
|
||||
shouldLeaveScope: Boolean = true,
|
||||
irParent: IrClass,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrConstructor {
|
||||
val descriptor = WrappedClassConstructorDescriptor()
|
||||
val isPrimary = constructor.isPrimary
|
||||
val visibility = when {
|
||||
irParent is IrClass && irParent.modality == Modality.SEALED -> Visibilities.PRIVATE
|
||||
val visibility = when (irParent.modality) {
|
||||
Modality.SEALED -> Visibilities.PRIVATE
|
||||
else -> constructor.visibility
|
||||
}
|
||||
val created = constructor.convertWithOffsets { startOffset, endOffset ->
|
||||
@@ -646,9 +654,7 @@ class Fir2IrDeclarationStorage(
|
||||
).apply {
|
||||
enterScope(descriptor)
|
||||
}.bindAndDeclareParameters(constructor, descriptor, irParent, isStatic = true).apply {
|
||||
if (shouldLeaveScope) {
|
||||
leaveScope(descriptor)
|
||||
}
|
||||
leaveScope(descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -656,18 +662,6 @@ class Fir2IrDeclarationStorage(
|
||||
return created
|
||||
}
|
||||
|
||||
fun getIrConstructor(
|
||||
constructor: FirConstructor,
|
||||
irParent: IrDeclarationParent,
|
||||
shouldLeaveScope: Boolean = true
|
||||
): IrConstructor {
|
||||
val cached = getCachedIrConstructor(constructor)
|
||||
if (cached != null) {
|
||||
return if (shouldLeaveScope) cached else cached.enterLocalScope(constructor)
|
||||
}
|
||||
return createIrConstructor(constructor, irParent, shouldLeaveScope)
|
||||
}
|
||||
|
||||
private fun createIrPropertyAccessor(
|
||||
propertyAccessor: FirPropertyAccessor?,
|
||||
property: FirProperty,
|
||||
@@ -725,49 +719,48 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
fun getCachedIrEnumEntry(enumEntry: FirEnumEntry): IrEnumEntry? = enumEntryCache[enumEntry]
|
||||
|
||||
fun getIrEnumEntry(
|
||||
fun createIrEnumEntry(
|
||||
enumEntry: FirEnumEntry,
|
||||
irParent: IrClass? = null,
|
||||
irParent: IrClass?,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrEnumEntry {
|
||||
return enumEntryCache.getOrPut(enumEntry) {
|
||||
enumEntry.convertWithOffsets { startOffset, endOffset ->
|
||||
val desc = WrappedEnumEntryDescriptor()
|
||||
enterScope(desc)
|
||||
val result = irSymbolTable.declareEnumEntry(startOffset, endOffset, origin, desc) { symbol ->
|
||||
IrEnumEntryImpl(
|
||||
startOffset, endOffset, origin, symbol, enumEntry.name
|
||||
).apply {
|
||||
desc.bind(this)
|
||||
val irType = enumEntry.returnTypeRef.toIrType()
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
val initializer = enumEntry.initializer
|
||||
if (initializer != null) {
|
||||
initializer as FirAnonymousObject
|
||||
val klass = getIrEnumEntryClass(enumEntry, initializer, irParent)
|
||||
return enumEntry.convertWithOffsets { startOffset, endOffset ->
|
||||
val desc = WrappedEnumEntryDescriptor()
|
||||
enterScope(desc)
|
||||
val result = irSymbolTable.declareEnumEntry(startOffset, endOffset, origin, desc) { symbol ->
|
||||
IrEnumEntryImpl(
|
||||
startOffset, endOffset, origin, symbol, enumEntry.name
|
||||
).apply {
|
||||
desc.bind(this)
|
||||
val irType = enumEntry.returnTypeRef.toIrType()
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
val initializer = enumEntry.initializer
|
||||
if (initializer != null) {
|
||||
initializer as FirAnonymousObject
|
||||
val klass = getIrAnonymousObjectForEnumEntry(initializer, enumEntry.name, irParent)
|
||||
|
||||
this.correspondingClass = klass
|
||||
} else if (irParent != null) {
|
||||
this.initializerExpression = IrExpressionBodyImpl(
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, irType, irParent.constructors.first().symbol)
|
||||
)
|
||||
}
|
||||
this.correspondingClass = klass
|
||||
} else if (irParent != null) {
|
||||
this.initializerExpression = IrExpressionBodyImpl(
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, irType, irParent.constructors.first().symbol)
|
||||
)
|
||||
}
|
||||
}
|
||||
leaveScope(desc)
|
||||
result
|
||||
}
|
||||
leaveScope(desc)
|
||||
enumEntryCache[enumEntry] = result
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIrProperty(
|
||||
fun createIrProperty(
|
||||
property: FirProperty,
|
||||
irParent: IrDeclarationParent?,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
|
||||
shouldLeaveScope: Boolean = true
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrProperty {
|
||||
val containerSource = property.containerSource
|
||||
val descriptor = containerSource?.let { WrappedPropertyDescriptorWithContainerSource(it) } ?: WrappedPropertyDescriptor()
|
||||
@@ -818,29 +811,13 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldLeaveScope) {
|
||||
leaveScope(descriptor)
|
||||
}
|
||||
leaveScope(descriptor)
|
||||
propertyCache[property] = result
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fun getIrProperty(
|
||||
property: FirProperty,
|
||||
irParent: IrDeclarationParent?,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
|
||||
shouldLeaveScope: Boolean = true
|
||||
): IrProperty {
|
||||
val cached = propertyCache[property]
|
||||
if (cached != null) {
|
||||
if (!shouldLeaveScope) {
|
||||
enterScope(cached.descriptor)
|
||||
}
|
||||
return cached
|
||||
}
|
||||
return createIrProperty(property, irParent, origin, shouldLeaveScope)
|
||||
}
|
||||
fun getCachedIrProperty(property: FirProperty): IrProperty? = propertyCache[property]
|
||||
|
||||
private fun createIrField(field: FirField): IrField {
|
||||
val descriptor = WrappedFieldDescriptor()
|
||||
@@ -866,7 +843,7 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAndSaveIrParameter(
|
||||
private fun createIrParameter(
|
||||
valueParameter: FirValueParameter,
|
||||
index: Int = -1,
|
||||
useStubForDefaultValueStub: Boolean = true,
|
||||
@@ -929,7 +906,7 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
fun createAndSaveIrVariable(variable: FirVariable<*>, givenOrigin: IrDeclarationOrigin? = null): IrVariable {
|
||||
fun createIrVariable(variable: FirVariable<*>, irParent: IrDeclarationParent, givenOrigin: IrDeclarationOrigin? = null): IrVariable {
|
||||
val type = variable.returnTypeRef.toIrType()
|
||||
// Some temporary variables are produced in RawFirBuilder, but we consistently use special names for them.
|
||||
val origin = when {
|
||||
@@ -944,6 +921,7 @@ class Fir2IrDeclarationStorage(
|
||||
variable.name, type, variable.isVar, isConst = false, isLateinit = false
|
||||
)
|
||||
}
|
||||
irVariable.parent = irParent
|
||||
localStorage.putVariable(variable, irVariable)
|
||||
return irVariable
|
||||
}
|
||||
@@ -961,6 +939,7 @@ class Fir2IrDeclarationStorage(
|
||||
fun getIrClassSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
|
||||
val firClass = firClassSymbol.fir
|
||||
getCachedIrClass(firClass)?.let { return irSymbolTable.referenceClass(it.descriptor) }
|
||||
// TODO: remove all this code and change to unbound symbol creation
|
||||
val irClass = createIrClass(firClass)
|
||||
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.LOCAL) {
|
||||
return irSymbolTable.referenceClass(irClass.descriptor)
|
||||
@@ -982,10 +961,22 @@ class Fir2IrDeclarationStorage(
|
||||
firTypeParameterSymbol: FirTypeParameterSymbol,
|
||||
typeContext: ConversionTypeContext
|
||||
): IrTypeParameterSymbol {
|
||||
// TODO: use cached type parameter here
|
||||
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext)
|
||||
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
|
||||
}
|
||||
|
||||
fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol): IrConstructorSymbol {
|
||||
val firConstructor = firConstructorSymbol.fir
|
||||
getCachedIrConstructor(firConstructor)?.let { return irSymbolTable.referenceConstructor(it.descriptor) }
|
||||
val irParent = findIrParent(firConstructor) as IrClass
|
||||
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
|
||||
val irDeclaration = createIrConstructor(firConstructor, irParent, origin = parentOrigin).apply {
|
||||
setAndModifyParent(irParent)
|
||||
}
|
||||
return irSymbolTable.referenceConstructor(irDeclaration.descriptor)
|
||||
}
|
||||
|
||||
fun getIrFunctionSymbol(firFunctionSymbol: FirFunctionSymbol<*>): IrFunctionSymbol {
|
||||
return when (val firDeclaration = firFunctionSymbol.fir) {
|
||||
is FirSimpleFunction, is FirAnonymousFunction -> {
|
||||
@@ -998,13 +989,7 @@ class Fir2IrDeclarationStorage(
|
||||
irSymbolTable.referenceSimpleFunction(irDeclaration.descriptor)
|
||||
}
|
||||
is FirConstructor -> {
|
||||
getCachedIrConstructor(firDeclaration)?.let { return irSymbolTable.referenceConstructor(it.descriptor) }
|
||||
val irParent = findIrParent(firDeclaration)!!
|
||||
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
|
||||
val irDeclaration = createIrConstructor(firDeclaration, irParent, origin = parentOrigin).apply {
|
||||
setAndModifyParent(irParent)
|
||||
}
|
||||
irSymbolTable.referenceConstructor(irDeclaration.descriptor)
|
||||
getIrConstructorSymbol(firDeclaration.symbol)
|
||||
}
|
||||
else -> throw AssertionError("Should not be here: ${firDeclaration::class.java}: ${firDeclaration.render()}")
|
||||
}
|
||||
@@ -1058,10 +1043,11 @@ class Fir2IrDeclarationStorage(
|
||||
fun getIrValueSymbol(firVariableSymbol: FirVariableSymbol<*>): IrSymbol {
|
||||
return when (val firDeclaration = firVariableSymbol.fir) {
|
||||
is FirEnumEntry -> {
|
||||
getCachedIrEnumEntry(firDeclaration)?.let { return irSymbolTable.referenceEnumEntry(it.descriptor) }
|
||||
val containingFile = firProvider.getFirCallableContainerFile(firVariableSymbol)
|
||||
val parentClassSymbol = firVariableSymbol.callableId.classId?.let { firSymbolProvider.getClassLikeSymbolByFqName(it) }
|
||||
val irParentClass = (parentClassSymbol?.fir as? FirClass<*>)?.let { getIrClass(it) }
|
||||
val irEnumEntry = getIrEnumEntry(
|
||||
val irParentClass = (parentClassSymbol?.fir as? FirClass<*>)?.let { getCachedIrClass(it) }
|
||||
val irEnumEntry = createIrEnumEntry(
|
||||
firDeclaration,
|
||||
irParent = irParentClass,
|
||||
origin = if (containingFile == null) IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB else IrDeclarationOrigin.DEFINED
|
||||
|
||||
+5
-7
@@ -43,9 +43,7 @@ class Fir2IrFakeOverrideGenerator(
|
||||
firOverriddenSymbol: FirPropertySymbol
|
||||
): IrProperty {
|
||||
val firOverriddenProperty = firOverriddenSymbol.fir
|
||||
val overriddenProperty = declarationStorage.getIrProperty(
|
||||
firOverriddenProperty, declarationStorage.findIrParent(firOverriddenProperty)
|
||||
)
|
||||
val overriddenProperty = declarationStorage.getCachedIrProperty(firOverriddenProperty)!!
|
||||
getter?.apply {
|
||||
overriddenProperty.getter?.symbol?.let { overriddenSymbols = listOf(it) }
|
||||
}
|
||||
@@ -71,7 +69,7 @@ class Fir2IrFakeOverrideGenerator(
|
||||
if (functionSymbol.isFakeOverride) {
|
||||
// Substitution case
|
||||
val baseSymbol = functionSymbol.deepestOverriddenSymbol() as FirNamedFunctionSymbol
|
||||
val irFunction = declarationStorage.getIrFunction(
|
||||
val irFunction = declarationStorage.createIrFunction(
|
||||
// TODO: parents for functions and properties should be consistent
|
||||
originalFunction, declarationStorage.findIrParent(baseSymbol.fir), origin = origin
|
||||
)
|
||||
@@ -89,7 +87,7 @@ class Fir2IrFakeOverrideGenerator(
|
||||
)
|
||||
val fakeOverrideFunction = fakeOverrideSymbol.fir
|
||||
|
||||
val irFunction = declarationStorage.getIrFunction(
|
||||
val irFunction = declarationStorage.createIrFunction(
|
||||
fakeOverrideFunction, declarationStorage.findIrParent(originalFunction), origin = origin
|
||||
)
|
||||
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(functionSymbol) as IrSimpleFunctionSymbol
|
||||
@@ -106,7 +104,7 @@ class Fir2IrFakeOverrideGenerator(
|
||||
if (propertySymbol.isFakeOverride) {
|
||||
// Substitution case
|
||||
val baseSymbol = propertySymbol.deepestOverriddenSymbol() as FirPropertySymbol
|
||||
val irProperty = declarationStorage.getIrProperty(
|
||||
val irProperty = declarationStorage.createIrProperty(
|
||||
originalProperty, irParent = this, origin = origin
|
||||
)
|
||||
declarations += irProperty.withProperty {
|
||||
@@ -119,7 +117,7 @@ class Fir2IrFakeOverrideGenerator(
|
||||
)
|
||||
val fakeOverrideProperty = fakeOverrideSymbol.fir
|
||||
|
||||
val irProperty = declarationStorage.getIrProperty(
|
||||
val irProperty = declarationStorage.createIrProperty(
|
||||
fakeOverrideProperty, irParent = this, origin = origin
|
||||
)
|
||||
declarations += irProperty.withProperty {
|
||||
|
||||
@@ -18,6 +18,8 @@ class Fir2IrLocalStorage {
|
||||
|
||||
private val cacheStack = mutableListOf<Fir2IrCallableCache>()
|
||||
|
||||
private val localClassCache = mutableMapOf<FirClass<*>, IrClass>()
|
||||
|
||||
fun enterCallable() {
|
||||
cacheStack += Fir2IrCallableCache()
|
||||
}
|
||||
@@ -44,11 +46,7 @@ class Fir2IrLocalStorage {
|
||||
}
|
||||
|
||||
fun getLocalClass(localClass: FirClass<*>): IrClass? {
|
||||
for (cache in cacheStack.asReversed()) {
|
||||
val local = cache.getLocalClass(localClass)
|
||||
if (local != null) return local
|
||||
}
|
||||
return null
|
||||
return localClassCache[localClass]
|
||||
}
|
||||
|
||||
fun getLocalFunction(localFunction: FirFunction<*>): IrSimpleFunction? {
|
||||
@@ -68,7 +66,7 @@ class Fir2IrLocalStorage {
|
||||
}
|
||||
|
||||
fun putLocalClass(firClass: FirClass<*>, irClass: IrClass) {
|
||||
cacheStack.last().putLocalClass(firClass, irClass)
|
||||
localClassCache[firClass] = irClass
|
||||
}
|
||||
|
||||
fun putLocalFunction(firFunction: FirFunction<*>, irFunction: IrSimpleFunction) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
|
||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
@@ -34,7 +33,6 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
@@ -44,14 +42,14 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
import java.util.*
|
||||
|
||||
class Fir2IrVisitor(
|
||||
private val session: FirSession,
|
||||
private val moduleDescriptor: FirModuleDescriptor,
|
||||
private val symbolTable: SymbolTable,
|
||||
private val sourceManager: PsiSourceManager,
|
||||
private val declarationStorage: Fir2IrDeclarationStorage,
|
||||
private val converter: Fir2IrConverter,
|
||||
private val typeConverter: Fir2IrTypeConverter,
|
||||
override val irBuiltIns: IrBuiltIns,
|
||||
fakeOverrideMode: FakeOverrideMode
|
||||
) : FirDefaultVisitor<IrElement, Any?>(), IrGeneratorContextInterface {
|
||||
@@ -63,40 +61,24 @@ class Fir2IrVisitor(
|
||||
|
||||
private val integerApproximator = IntegerLiteralTypeApproximationTransformer(session.firSymbolProvider, session.inferenceContext)
|
||||
|
||||
private val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
|
||||
private val conversionScope = Fir2IrConversionScope()
|
||||
|
||||
private val typeConverter = Fir2IrTypeConverter(session, declarationStorage, irBuiltIns).also {
|
||||
declarationStorage.typeConverter = it
|
||||
it.initBuiltinTypes()
|
||||
}
|
||||
private val fakeOverrideGenerator = Fir2IrFakeOverrideGenerator(session, declarationStorage, conversionScope, fakeOverrideMode)
|
||||
|
||||
private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
|
||||
|
||||
private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() }
|
||||
|
||||
private val conversionScope = Fir2IrConversionScope()
|
||||
|
||||
private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration)
|
||||
|
||||
private val fakeOverrideGenerator = Fir2IrFakeOverrideGenerator(session, declarationStorage, conversionScope, fakeOverrideMode)
|
||||
|
||||
override fun visitElement(element: FirElement, data: Any?): IrElement {
|
||||
TODO("Should not be here: ${element.render()}")
|
||||
}
|
||||
|
||||
fun registerFile(file: FirFile) {
|
||||
val irFile = IrFileImpl(
|
||||
sourceManager.getOrCreateFileEntry(file.psi as KtFile),
|
||||
moduleDescriptor.getPackage(file.packageFqName).fragments.first()
|
||||
)
|
||||
declarationStorage.registerFile(file, irFile)
|
||||
}
|
||||
|
||||
override fun visitFile(file: FirFile, data: Any?): IrFile {
|
||||
return conversionScope.withParent(declarationStorage.getIrFile(file)) {
|
||||
file.declarations.forEach {
|
||||
val irDeclaration = it.toIrDeclaration() ?: return@forEach
|
||||
declarations += irDeclaration
|
||||
it.toIrDeclaration()
|
||||
}
|
||||
|
||||
annotations = file.annotations.mapNotNull {
|
||||
@@ -110,9 +92,14 @@ class Fir2IrVisitor(
|
||||
return accept(this@Fir2IrVisitor, null) as IrDeclaration
|
||||
}
|
||||
|
||||
// ==================================================================================
|
||||
|
||||
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Any?): IrElement {
|
||||
val irEnumEntry = declarationStorage.getIrEnumEntry(enumEntry, irParent = conversionScope.lastClass())
|
||||
val irEnumEntry = declarationStorage.getCachedIrEnumEntry(enumEntry)!!
|
||||
val correspondingClass = irEnumEntry.correspondingClass ?: return irEnumEntry
|
||||
declarationStorage.enterScope(irEnumEntry.descriptor)
|
||||
declarationStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
|
||||
converter.processAnonymousObjectMembers(enumEntry.initializer as FirAnonymousObject, correspondingClass)
|
||||
conversionScope.withParent(correspondingClass) {
|
||||
setClassContent(enumEntry.initializer as FirAnonymousObject)
|
||||
irEnumEntry.initializerExpression = IrExpressionBodyImpl(
|
||||
@@ -122,25 +109,27 @@ class Fir2IrVisitor(
|
||||
)
|
||||
)
|
||||
}
|
||||
declarationStorage.leaveScope(irEnumEntry.descriptor)
|
||||
return irEnumEntry
|
||||
}
|
||||
|
||||
private fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
|
||||
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
|
||||
|
||||
private fun IrClass.setClassContent(klass: FirClass<*>) {
|
||||
declarationStorage.enterScope(descriptor)
|
||||
conversionScope.withClass(this) {
|
||||
val primaryConstructor = klass.getPrimaryConstructorIfAny()
|
||||
val irPrimaryConstructor = primaryConstructor?.accept(this@Fir2IrVisitor, null) as IrConstructor?
|
||||
val irPrimaryConstructor = primaryConstructor?.let { declarationStorage.getCachedIrConstructor(it)!! }
|
||||
if (irPrimaryConstructor != null) {
|
||||
declarations += irPrimaryConstructor
|
||||
with(declarationStorage) {
|
||||
enterScope(irPrimaryConstructor.descriptor)
|
||||
irPrimaryConstructor.valueParameters.forEach { symbolTable.introduceValueParameter(it) }
|
||||
irPrimaryConstructor.putParametersInScope(primaryConstructor)
|
||||
irPrimaryConstructor.setFunctionContent(irPrimaryConstructor.descriptor, primaryConstructor)
|
||||
}
|
||||
}
|
||||
val processedCallableNames = mutableListOf<Name>()
|
||||
klass.declarations.forEach {
|
||||
if (it !is FirConstructor || !it.isPrimary) {
|
||||
val irDeclaration = it.toIrDeclaration() ?: return@forEach
|
||||
declarations += irDeclaration
|
||||
it.toIrDeclaration() ?: return@forEach
|
||||
when (it) {
|
||||
is FirSimpleFunction -> processedCallableNames += it.name
|
||||
is FirProperty -> processedCallableNames += it.name
|
||||
@@ -159,16 +148,64 @@ class Fir2IrVisitor(
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement {
|
||||
return conversionScope.withParent(
|
||||
applyParentFromStackTo(declarationStorage.getIrClass(regularClass))
|
||||
) {
|
||||
if (regularClass.visibility == Visibilities.LOCAL) {
|
||||
val irParent = conversionScope.parentFromStack()
|
||||
val irClass = declarationStorage.getCachedIrClass(regularClass)?.apply { this.parent = irParent }
|
||||
if (irClass != null) {
|
||||
converter.processRegisteredLocalClassAndNestedClasses(regularClass, irClass)
|
||||
return conversionScope.withParent(irClass) {
|
||||
setClassContent(regularClass)
|
||||
}
|
||||
}
|
||||
converter.processLocalClassAndNestedClasses(regularClass, irParent)
|
||||
}
|
||||
val irClass = declarationStorage.getCachedIrClass(regularClass)!!
|
||||
return conversionScope.withParent(irClass) {
|
||||
setClassContent(regularClass)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): IrElement {
|
||||
val irParent = conversionScope.parentFromStack()
|
||||
// NB: for implicit types it is possible that anonymous object is already cached
|
||||
val irAnonymousObject = declarationStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
|
||||
?: declarationStorage.createIrAnonymousObject(anonymousObject, irParent = irParent)
|
||||
converter.processAnonymousObjectMembers(anonymousObject, irAnonymousObject)
|
||||
conversionScope.withParent(irAnonymousObject) {
|
||||
setClassContent(anonymousObject)
|
||||
}
|
||||
val anonymousClassType = irAnonymousObject.thisReceiver!!.type
|
||||
return anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
IrBlockImpl(
|
||||
startOffset, endOffset, anonymousClassType, IrStatementOrigin.OBJECT_LITERAL,
|
||||
listOf(
|
||||
irAnonymousObject,
|
||||
IrConstructorCallImpl.fromSymbolOwner(
|
||||
startOffset,
|
||||
endOffset,
|
||||
anonymousClassType,
|
||||
irAnonymousObject.constructors.first().symbol,
|
||||
irAnonymousObject.typeParameters.size,
|
||||
origin = IrStatementOrigin.OBJECT_LITERAL
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ==================================================================================
|
||||
|
||||
private fun <T : IrFunction> T.setFunctionContent(descriptor: FunctionDescriptor, firFunction: FirFunction<*>?): T {
|
||||
conversionScope.withParent(this) {
|
||||
if (firFunction != null) {
|
||||
if (this !is IrConstructor || !this.isPrimary) {
|
||||
// Scope for primary constructor should be entered before class declaration processing
|
||||
with(declarationStorage) {
|
||||
enterScope(descriptor)
|
||||
valueParameters.forEach { symbolTable.introduceValueParameter(it) }
|
||||
putParametersInScope(firFunction)
|
||||
}
|
||||
}
|
||||
for ((valueParameter, firValueParameter) in valueParameters.zip(firFunction.valueParameters)) {
|
||||
valueParameter.setDefaultValue(firValueParameter)
|
||||
}
|
||||
@@ -208,27 +245,18 @@ class Fir2IrVisitor(
|
||||
}
|
||||
|
||||
override fun visitConstructor(constructor: FirConstructor, data: Any?): IrElement {
|
||||
val irConstructor = declarationStorage.getIrConstructor(
|
||||
constructor, irParent = conversionScope.lastClass()!!, shouldLeaveScope = false
|
||||
)
|
||||
val irConstructor = declarationStorage.getCachedIrConstructor(constructor)!!
|
||||
return conversionScope.withFunction(irConstructor) {
|
||||
setFunctionContent(irConstructor.descriptor, constructor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Any?): IrElement {
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val parent = conversionScope.lastClass()!!
|
||||
return anonymousInitializer.convertWithOffsets { startOffset, endOffset ->
|
||||
symbolTable.declareAnonymousInitializer(
|
||||
startOffset, endOffset, origin, parent.descriptor
|
||||
).apply {
|
||||
this.parent = parent
|
||||
declarationStorage.enterScope(descriptor)
|
||||
body = anonymousInitializer.body!!.convertToIrBlockBody()
|
||||
declarationStorage.leaveScope(descriptor)
|
||||
}
|
||||
}
|
||||
val irAnonymousInitializer = declarationStorage.getCachedIrAnonymousInitializer(anonymousInitializer)!!
|
||||
declarationStorage.enterScope(irAnonymousInitializer.descriptor)
|
||||
irAnonymousInitializer.body = anonymousInitializer.body!!.convertToIrBlockBody()
|
||||
declarationStorage.leaveScope(irAnonymousInitializer.descriptor)
|
||||
return irAnonymousInitializer
|
||||
}
|
||||
|
||||
private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrCallWithIndexedArgumentsBase? {
|
||||
@@ -265,9 +293,12 @@ class Fir2IrVisitor(
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): IrElement {
|
||||
val irFunction = declarationStorage.getIrFunction(
|
||||
simpleFunction, irParent = conversionScope.parent(), shouldLeaveScope = false
|
||||
)
|
||||
val irFunction = if (simpleFunction.visibility == Visibilities.LOCAL) {
|
||||
val irParent = conversionScope.parent()
|
||||
declarationStorage.createIrFunction(simpleFunction, irParent)
|
||||
} else {
|
||||
declarationStorage.getCachedIrFunction(simpleFunction)!!
|
||||
}
|
||||
return conversionScope.withFunction(irFunction) {
|
||||
setFunctionContent(irFunction.descriptor, simpleFunction)
|
||||
}
|
||||
@@ -275,7 +306,7 @@ class Fir2IrVisitor(
|
||||
|
||||
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Any?): IrElement {
|
||||
return anonymousFunction.convertWithOffsets { startOffset, endOffset ->
|
||||
val irFunction = declarationStorage.getIrFunction(anonymousFunction, conversionScope.parent(), shouldLeaveScope = false)
|
||||
val irFunction = declarationStorage.createIrFunction(anonymousFunction, conversionScope.parent())
|
||||
conversionScope.withFunction(irFunction) {
|
||||
setFunctionContent(irFunction.descriptor, anonymousFunction)
|
||||
}
|
||||
@@ -299,14 +330,13 @@ class Fir2IrVisitor(
|
||||
val isNextVariable = initializer is FirFunctionCall &&
|
||||
initializer.resolvedNamedFunctionSymbol()?.callableId?.isIteratorNext() == true &&
|
||||
variable.source.psi?.parent is KtForExpression
|
||||
val irVariable = declarationStorage.createAndSaveIrVariable(
|
||||
variable, if (isNextVariable) IrDeclarationOrigin.FOR_LOOP_VARIABLE else null
|
||||
val irVariable = declarationStorage.createIrVariable(
|
||||
variable, conversionScope.parentFromStack(), if (isNextVariable) IrDeclarationOrigin.FOR_LOOP_VARIABLE else null
|
||||
)
|
||||
return applyParentFromStackTo(irVariable).apply {
|
||||
if (initializer != null) {
|
||||
this.initializer = initializer.toIrExpression()
|
||||
}
|
||||
if (initializer != null) {
|
||||
irVariable.initializer = initializer.toIrExpression()
|
||||
}
|
||||
return irVariable
|
||||
}
|
||||
|
||||
private fun IrProperty.createBackingField(
|
||||
@@ -373,14 +403,15 @@ class Fir2IrVisitor(
|
||||
annotations = property.annotations.mapNotNull {
|
||||
it.accept(this@Fir2IrVisitor, null) as? IrConstructorCall
|
||||
}
|
||||
declarationStorage.leaveScope(descriptor)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun visitProperty(property: FirProperty, data: Any?): IrElement {
|
||||
if (property.isLocal) return visitLocalVariable(property)
|
||||
val irProperty = declarationStorage.getIrProperty(property, irParent = conversionScope.parent(), shouldLeaveScope = false)
|
||||
return conversionScope.withProperty(irProperty) { setPropertyContent(irProperty.descriptor, property) }
|
||||
val irProperty = declarationStorage.getCachedIrProperty(property)!!
|
||||
return conversionScope.withProperty(irProperty) {
|
||||
setPropertyContent(irProperty.descriptor, property)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrFieldAccessExpression.setReceiver(declaration: IrDeclaration): IrFieldAccessExpression {
|
||||
@@ -400,11 +431,6 @@ class Fir2IrVisitor(
|
||||
isDefault: Boolean
|
||||
) {
|
||||
conversionScope.withFunction(this) {
|
||||
if (propertyAccessor != null) {
|
||||
with(declarationStorage) { this@setPropertyAccessorContent.enterLocalScope(propertyAccessor) }
|
||||
} else {
|
||||
declarationStorage.enterScope(descriptor)
|
||||
}
|
||||
applyParentFromStackTo(this)
|
||||
setFunctionContent(descriptor, propertyAccessor)
|
||||
if (isDefault) {
|
||||
@@ -518,14 +544,12 @@ class Fir2IrVisitor(
|
||||
val irClass = symbol.owner
|
||||
val fir = firSymbol?.fir as? FirClass<*>
|
||||
val irConstructor = fir?.getPrimaryConstructorIfAny()?.let { firConstructor ->
|
||||
declarationStorage.getIrConstructor(firConstructor, irParent = irClass)
|
||||
}?.apply {
|
||||
this.parent = irClass
|
||||
declarationStorage.getIrConstructorSymbol(firConstructor.symbol)
|
||||
}
|
||||
if (irConstructor == null) {
|
||||
IrErrorCallExpressionImpl(startOffset, endOffset, type, "No annotation constructor found: ${irClass.name}")
|
||||
} else {
|
||||
IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, type, irConstructor.symbol)
|
||||
IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, type, irConstructor)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -623,7 +647,7 @@ class Fir2IrVisitor(
|
||||
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
||||
}
|
||||
firClass?.convertWithOffsets { startOffset, endOffset ->
|
||||
val irClass = declarationStorage.getIrClass(firClass)
|
||||
val irClass = declarationStorage.getCachedIrClass(firClass)!!
|
||||
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
|
||||
}
|
||||
}
|
||||
@@ -691,7 +715,7 @@ class Fir2IrVisitor(
|
||||
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
|
||||
}
|
||||
if (firObject != null) {
|
||||
val irObject = declarationStorage.getIrClass(firObject)
|
||||
val irObject = declarationStorage.getCachedIrClass(firObject)!!
|
||||
if (irObject != conversionScope.lastClass()) {
|
||||
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
|
||||
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
|
||||
@@ -827,30 +851,6 @@ class Fir2IrVisitor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): IrElement {
|
||||
val anonymousClass = declarationStorage.getIrAnonymousObject(anonymousObject)
|
||||
conversionScope.withParent(applyParentFromStackTo(anonymousClass)) {
|
||||
setClassContent(anonymousObject)
|
||||
}
|
||||
val anonymousClassType = anonymousClass.thisReceiver!!.type
|
||||
return anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
IrBlockImpl(
|
||||
startOffset, endOffset, anonymousClassType, IrStatementOrigin.OBJECT_LITERAL,
|
||||
listOf(
|
||||
anonymousClass,
|
||||
IrConstructorCallImpl.fromSymbolOwner(
|
||||
startOffset,
|
||||
endOffset,
|
||||
anonymousClassType,
|
||||
anonymousClass.constructors.first().symbol,
|
||||
anonymousClass.typeParameters.size,
|
||||
origin = IrStatementOrigin.OBJECT_LITERAL
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ==================================================================================
|
||||
|
||||
private fun FirStatement.toIrStatement(): IrStatement? {
|
||||
@@ -1082,8 +1082,8 @@ class Fir2IrVisitor(
|
||||
|
||||
override fun visitCatch(catch: FirCatch, data: Any?): IrElement {
|
||||
return catch.convertWithOffsets { startOffset, endOffset ->
|
||||
val catchParameter = declarationStorage.createAndSaveIrVariable(catch.parameter)
|
||||
IrCatchImpl(startOffset, endOffset, applyParentFromStackTo(catchParameter)).apply {
|
||||
val catchParameter = declarationStorage.createIrVariable(catch.parameter, conversionScope.parentFromStack())
|
||||
IrCatchImpl(startOffset, endOffset, catchParameter).apply {
|
||||
result = catch.block.convertToIrExpressionOrBlock()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var result = "Fail"
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class A
|
||||
|
||||
fun box(): String {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
class A
|
||||
fun A.foo() = "OK"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun Int.is42With(that: Int) = this + 2 * that == 42
|
||||
return if ((Int::is42With)(16, 13)) "OK" else "Fail"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class A
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun foo(): String {
|
||||
fun bar() = "OK"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(until: Int): String {
|
||||
fun bar(x: Int): String =
|
||||
if (x == until) "OK" else bar(x + 1)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun foo() = "OK"
|
||||
return (::foo)()
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
val result = "OK"
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun foo(s: String) = s
|
||||
return (::foo)("OK")
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
var state = 23
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
package example2
|
||||
|
||||
fun box() = Context.OsType.OK.toString()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun String.f(x: String): String {
|
||||
fun String.g() = { this@f + this@g }()
|
||||
return x.g()
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
open class Base(val fn: () -> String)
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
open class Z(val s: Int) {
|
||||
open fun a() {}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box() : String {
|
||||
|
||||
fun <T> local(s : T) : T {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun rec(n : Int) {
|
||||
fun x(m : Int) {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun rec(n : Int) {
|
||||
fun x(m : Int, k : Int) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun foo(x: Int) {
|
||||
fun bar(y: Int) {
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun foo(x: Int, s: String): String {
|
||||
fun bar(y: Int) {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
//KT-3276
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box() : String {
|
||||
fun <T> foo(t:() -> T) : T = t()
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
val x = "OK"
|
||||
fun bar(y: String = x): String = y
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
val o = "O"
|
||||
fun ok() = o + "K"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
|
||||
fun local():Int {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
|
||||
fun local():Int {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box() : String {
|
||||
|
||||
fun <T> local(s : T) : T {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(s: String): String {
|
||||
fun bar(count: Int): String =
|
||||
if (count == 0) s else bar(count - 1)
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// DONT_RUN_GENERATED_CODE: JS
|
||||
|
||||
fun test() {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
package test
|
||||
|
||||
fun box() = MyEnum.E1.f() + MyEnum.E2.f()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box() = if(Context.operatingSystemType == Context.Companion.OsType.OTHER) "OK" else "fail"
|
||||
|
||||
public class Context
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
enum class X {
|
||||
B {
|
||||
val value2 = "K"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
fun box(): String {
|
||||
val sb = StringBuilder()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun String.foo() : String {
|
||||
fun Int.bar() : String {
|
||||
fun Long.baz() : String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun rmrf(i: Int) {
|
||||
if (i > 0) rmrf(i - 1)
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun <T, V : T> f(x: V): V {
|
||||
fun g(y: V) = y
|
||||
return g(x)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun outer() {
|
||||
fun inner(i: Int) {
|
||||
if (i > 0){
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun <T> foo(t: T) = t
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box() : String {
|
||||
fun local(i: Int = 1) : Int {
|
||||
return i
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class C() {
|
||||
fun box(): Int {
|
||||
fun local(i: Int = 1): Int {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(f: (Int?) -> Int): Int {
|
||||
return f(0)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
infix fun Int.foo(a: Int): Int = a + 2
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun String.f() = this
|
||||
val vf: String.() -> String = { this }
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class T(val value: Int) {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class It(val id: String)
|
||||
|
||||
fun box(): String {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var s = ""
|
||||
var foo = "O"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
fun test(b: Boolean): String {
|
||||
if (b) {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
fun foo(x: String) = x
|
||||
fun foo() = foo("K")
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var s = ""
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var s = ""
|
||||
var foo = "K"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var s = ""
|
||||
var foo = "K"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var s = ""
|
||||
var foo = "O"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(): String {
|
||||
fun bar(x: String, y: String = x): String {
|
||||
return y
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
class Holder<T: Any>(val v: T)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(x: String): String {
|
||||
fun bar(y: String) = x + y
|
||||
return bar("K")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun <X : Any> foo(x: X): String {
|
||||
fun <Y : Any> bar(y: Y) =
|
||||
x.toString() + y.toString()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(x: String): String {
|
||||
fun bar(y: String): String {
|
||||
fun qux(z: String): String =
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun String.foo(): String {
|
||||
fun bar(y: String) = this + y
|
||||
return bar("K")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var result = ""
|
||||
fun add(s: String) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
data class A(val a: Int, val b: Int)
|
||||
|
||||
fun box() : String
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
open class C(val s: String) {
|
||||
fun test(): String {
|
||||
return s
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var x = ""
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var x = ""
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class A {
|
||||
operator fun component1() = 1
|
||||
operator fun component2() = 2
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FILE: fromAnonymousObjectInNestedClass.kt
|
||||
import outer.*
|
||||
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
class Outer {
|
||||
private companion object {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var boo = "OK"
|
||||
var foo = object {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
package p
|
||||
|
||||
private class C(val y: Int) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
open class A(open val v: String)
|
||||
|
||||
fun A.a(newv: String) = object: A("fail") {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
operator fun Int?.inc() = (this ?: 0) + 1
|
||||
var counter: Int? = null
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// SKIP_JDK6
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
private class One {
|
||||
val a1 = arrayOf(
|
||||
object { val fy = "text"}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class Foo {
|
||||
fun bar(): String {
|
||||
fun <T> foo(t:() -> T) : T = t()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -108,7 +108,7 @@ FILE fqName:<root> fileName:/partialSam.kt
|
||||
BLOCK_BODY
|
||||
CALL 'public final fun runConversion (f1: <root>.Fn<kotlin.String, kotlin.Int>, f2: <root>.Fn<kotlin.Int, kotlin.String>): kotlin.Int declared in <root>.J' type=kotlin.Int origin=null
|
||||
$this: GET_VAR 'j: <root>.J declared in <root>.test' type=<root>.J origin=null
|
||||
f1: CALL 'public final fun <get-fsi> (): <root>.fsi.<no name provided> declared in <root>' type=<uninitialized parent>.<no name provided> origin=GET_PROPERTY
|
||||
f1: CALL 'public final fun <get-fsi> (): <root>.fsi.<no name provided> declared in <root>' type=<root>.fsi.<no name provided> origin=GET_PROPERTY
|
||||
f2: FUN_EXPR type=kotlin.Function3<kotlin.String, kotlin.Int, kotlin.Int, kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (s:kotlin.String, i:kotlin.Int, ti:kotlin.Int) returnType:kotlin.String
|
||||
VALUE_PARAMETER name:s index:0 type:kotlin.String
|
||||
@@ -127,4 +127,4 @@ FILE fqName:<root> fileName:/partialSam.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (s: kotlin.String, i: kotlin.Int, ts: kotlin.String): kotlin.Int declared in <root>.test'
|
||||
CONST Int type=kotlin.Int value=1
|
||||
f2: CALL 'public final fun <get-fis> (): <root>.fis.<no name provided> declared in <root>' type=<uninitialized parent>.<no name provided> origin=GET_PROPERTY
|
||||
f2: CALL 'public final fun <get-fis> (): <root>.fis.<no name provided> declared in <root>' type=<root>.fis.<no name provided> origin=GET_PROPERTY
|
||||
|
||||
@@ -11,4 +11,4 @@ FILE fqName:<root> fileName:/localFunction.kt
|
||||
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
||||
$this: GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.outer.local' type=kotlin.Int origin=null
|
||||
GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.outer.local' type=kotlin.Int origin=null
|
||||
CALL 'local final fun local (): kotlin.Unit declared in <local>' type=kotlin.Unit origin=null
|
||||
CALL 'local final fun local (): kotlin.Unit declared in <root>.outer' type=kotlin.Unit origin=null
|
||||
|
||||
Reference in New Issue
Block a user