Add basic FIR -> IR converter with a set of text tests
Tests duplicate IrTextTestCaseGenerated #KT-24065 Fixed
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":core:descriptors"))
|
||||
compileOnly(project(":compiler:fir:cones"))
|
||||
compileOnly(project(":compiler:fir:resolve"))
|
||||
compileOnly(project(":compiler:fir:tree"))
|
||||
compileOnly(project(":compiler:ir.tree"))
|
||||
compileOnly(project(":compiler:ir.psi2ir"))
|
||||
compileOnly(project(":compiler:ir.backend.common"))
|
||||
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
|
||||
testCompileOnly(intellijDep()) { includeJars("openapi", "idea", "idea_rt", "util", "asm-all", rootProject = rootProject) }
|
||||
|
||||
testRuntime(intellijDep())
|
||||
|
||||
testCompile(commonDep("junit:junit"))
|
||||
testCompileOnly(project(":kotlin-test:kotlin-test-jvm"))
|
||||
testCompileOnly(project(":kotlin-test:kotlin-test-junit"))
|
||||
testCompile(projectTests(":compiler:tests-common"))
|
||||
testCompile(projectTests(":compiler:fir:resolve"))
|
||||
|
||||
testCompileOnly(project(":kotlin-reflect-api"))
|
||||
testRuntime(project(":kotlin-reflect"))
|
||||
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
projectTest {
|
||||
workingDir = rootDir
|
||||
}
|
||||
|
||||
testsJar()
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.LibraryTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeArgument
|
||||
import org.jetbrains.kotlin.ir.types.impl.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
internal fun <T : IrElement> FirElement.convertWithOffsets(
|
||||
f: (startOffset: Int, endOffset: Int) -> T
|
||||
): T {
|
||||
val startOffset = psi?.startOffsetSkippingComments ?: -1
|
||||
val endOffset = psi?.endOffset ?: -1
|
||||
return f(startOffset, endOffset)
|
||||
}
|
||||
|
||||
internal fun createErrorType(): IrErrorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
|
||||
|
||||
fun FirTypeRef.toIrType(session: FirSession, declarationStorage: Fir2IrDeclarationStorage): IrType {
|
||||
if (this !is FirResolvedTypeRef) {
|
||||
return createErrorType()
|
||||
}
|
||||
return type.toIrType(session, declarationStorage)
|
||||
}
|
||||
|
||||
fun ConeKotlinType.toIrType(session: FirSession, declarationStorage: Fir2IrDeclarationStorage): IrType {
|
||||
return when (this) {
|
||||
is ConeKotlinErrorType -> createErrorType()
|
||||
is ConeLookupTagBasedType -> {
|
||||
val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType()
|
||||
val irSymbol = firSymbol.toIrSymbol(session, declarationStorage)
|
||||
// TODO: annotations
|
||||
IrSimpleTypeImpl(
|
||||
irSymbol, this.isMarkedNullable,
|
||||
typeArguments.map { it.toIrTypeArgument(session, declarationStorage) },
|
||||
emptyList()
|
||||
)
|
||||
}
|
||||
is ConeFlexibleType -> {
|
||||
// TODO: yet we take more general type. Not quite sure it's Ok
|
||||
upperBound.toIrType(session, declarationStorage)
|
||||
}
|
||||
is ConeCapturedType -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeKotlinTypeProjection.toIrTypeArgument(session: FirSession, declarationStorage: Fir2IrDeclarationStorage): IrTypeArgument {
|
||||
return when (this) {
|
||||
ConeStarProjection -> IrStarProjectionImpl
|
||||
is ConeKotlinTypeProjectionIn -> {
|
||||
val irType = this.type.toIrType(session, declarationStorage)
|
||||
makeTypeProjection(irType, Variance.IN_VARIANCE)
|
||||
}
|
||||
is ConeKotlinTypeProjectionOut -> {
|
||||
val irType = this.type.toIrType(session, declarationStorage)
|
||||
makeTypeProjection(irType, Variance.OUT_VARIANCE)
|
||||
}
|
||||
is ConeKotlinType -> {
|
||||
val irType = toIrType(session, declarationStorage)
|
||||
makeTypeProjection(irType, Variance.INVARIANT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeClassifierSymbol.toIrSymbol(session: FirSession, declarationStorage: Fir2IrDeclarationStorage): IrClassifierSymbol {
|
||||
return when (this) {
|
||||
is FirTypeParameterSymbol -> {
|
||||
toTypeParameterSymbol(declarationStorage)
|
||||
}
|
||||
is LibraryTypeParameterSymbol -> {
|
||||
toTypeParameterSymbol(declarationStorage)
|
||||
}
|
||||
is FirTypeAliasSymbol -> {
|
||||
val typeAlias = fir
|
||||
val coneClassLikeType = (typeAlias.expandedTypeRef as FirResolvedTypeRef).type as ConeClassLikeType
|
||||
coneClassLikeType.lookupTag.toSymbol(session)!!.toIrSymbol(session, declarationStorage)
|
||||
}
|
||||
is FirClassSymbol -> {
|
||||
toClassSymbol(declarationStorage)
|
||||
}
|
||||
else -> throw AssertionError("Should not be here: $this")
|
||||
}
|
||||
}
|
||||
|
||||
fun FirReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol? {
|
||||
if (this is FirNamedReference) {
|
||||
return toSymbol(declarationStorage)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun FirNamedReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol? {
|
||||
if (this is FirResolvedCallableReference) {
|
||||
when (val callableSymbol = this.callableSymbol) {
|
||||
is FirFunctionSymbol -> return callableSymbol.toFunctionSymbol(declarationStorage)
|
||||
is FirPropertySymbol -> return callableSymbol.toPropertySymbol(declarationStorage)
|
||||
is FirVariableSymbol -> return callableSymbol.toValueSymbol(declarationStorage)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun FirClassSymbol.toClassSymbol(declarationStorage: Fir2IrDeclarationStorage): IrClassSymbol {
|
||||
return declarationStorage.getIrClassSymbol(this)
|
||||
}
|
||||
|
||||
fun FirTypeParameterSymbol.toTypeParameterSymbol(declarationStorage: Fir2IrDeclarationStorage): IrTypeParameterSymbol {
|
||||
return declarationStorage.getIrTypeParameterSymbol(this)
|
||||
}
|
||||
|
||||
fun LibraryTypeParameterSymbol.toTypeParameterSymbol(declarationStorage: Fir2IrDeclarationStorage): IrTypeParameterSymbol {
|
||||
return declarationStorage.getIrTypeParameterSymbol(this)
|
||||
}
|
||||
|
||||
fun FirFunctionSymbol.toFunctionSymbol(declarationStorage: Fir2IrDeclarationStorage): IrFunctionSymbol {
|
||||
return declarationStorage.getIrFunctionSymbol(this)
|
||||
}
|
||||
|
||||
fun FirPropertySymbol.toPropertySymbol(declarationStorage: Fir2IrDeclarationStorage): IrPropertySymbol {
|
||||
return declarationStorage.getIrPropertySymbol(this)
|
||||
}
|
||||
|
||||
fun FirVariableSymbol.toValueSymbol(declarationStorage: Fir2IrDeclarationStorage): IrValueSymbol {
|
||||
return declarationStorage.getIrValueSymbol(this)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir.backend
|
||||
|
||||
enum class FakeOverrideMode {
|
||||
// No fake overrides are generated
|
||||
NONE,
|
||||
// Only fake overrides with substituted signatures are generated
|
||||
SUBSTITUTION,
|
||||
// All fake overrides are generated, including trivial ones, explicitly declared function is specified as overridden one
|
||||
NORMAL,
|
||||
// All fake overrides are generated, function of direct base class (possibly also fake override) is specified as overridden one
|
||||
// TODO: not supported yet (to be discussed)
|
||||
FULLY_COMPATIBLE
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariable
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
|
||||
class Fir2IrCallableCache {
|
||||
private val parameterCache = mutableMapOf<FirValueParameter, IrValueParameter>()
|
||||
|
||||
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]
|
||||
|
||||
fun putParameter(firParameter: FirValueParameter, irParameter: IrValueParameter) {
|
||||
parameterCache[firParameter] = irParameter
|
||||
}
|
||||
|
||||
fun getVariable(variable: FirVariable): IrVariable? = variableCache[variable]
|
||||
|
||||
fun putVariable(firVariable: FirVariable, irVariable: IrVariable) {
|
||||
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) {
|
||||
require(localFunction !is FirNamedFunction || localFunction.visibility == Visibilities.LOCAL)
|
||||
localFunctionCache[localFunction] = irFunction
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
parameterCache.clear()
|
||||
variableCache.clear()
|
||||
localClassCache.clear()
|
||||
localFunctionCache.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.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.descriptors.FirModuleDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.util.ConstantValueGenerator
|
||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
||||
|
||||
object Fir2IrConverter {
|
||||
|
||||
fun createModuleFragment(
|
||||
session: FirSession,
|
||||
firFiles: List<FirFile>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
fakeOverrideMode: FakeOverrideMode = FakeOverrideMode.NORMAL
|
||||
): IrModuleFragment {
|
||||
val moduleDescriptor = FirModuleDescriptor(session)
|
||||
val symbolTable = SymbolTable()
|
||||
val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
|
||||
val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings, moduleDescriptor.builtIns)
|
||||
constantValueGenerator.typeTranslator = typeTranslator
|
||||
typeTranslator.constantValueGenerator = constantValueGenerator
|
||||
val builtIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, symbolTable)
|
||||
val fir2irTransformer = Fir2IrVisitor(session, moduleDescriptor, symbolTable, builtIns, fakeOverrideMode)
|
||||
val irFiles = mutableListOf<IrFile>()
|
||||
for (firFile in firFiles) {
|
||||
irFiles += firFile.accept(fir2irTransformer, null) as IrFile
|
||||
}
|
||||
|
||||
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, irFiles)
|
||||
generateUnboundSymbolsAsDependencies(irModuleFragment, symbolTable, builtIns)
|
||||
return irModuleFragment
|
||||
}
|
||||
|
||||
private fun generateUnboundSymbolsAsDependencies(
|
||||
irModule: IrModuleFragment,
|
||||
symbolTable: SymbolTable,
|
||||
builtIns: IrBuiltIns
|
||||
) {
|
||||
ExternalDependenciesGenerator(irModule.descriptor, symbolTable, builtIns).generateUnboundSymbolsAsDependencies()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||
import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariable
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.LibraryTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteral
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class Fir2IrDeclarationStorage(
|
||||
private val session: FirSession,
|
||||
private val irSymbolTable: SymbolTable,
|
||||
private val moduleDescriptor: FirModuleDescriptor
|
||||
) {
|
||||
private val firSymbolProvider = session.service<FirSymbolProvider>()
|
||||
|
||||
private val fragmentCache = mutableMapOf<FqName, IrExternalPackageFragment>()
|
||||
|
||||
private val classCache = mutableMapOf<FirRegularClass, IrClass>()
|
||||
|
||||
private val typeParameterCache = mutableMapOf<FirTypeParameter, IrTypeParameter>()
|
||||
|
||||
private val libraryTypeParameterCache = mutableMapOf<LibraryTypeParameterSymbol, IrTypeParameter>()
|
||||
|
||||
private val functionCache = mutableMapOf<FirNamedFunction, IrSimpleFunction>()
|
||||
|
||||
private val constructorCache = mutableMapOf<FirConstructor, IrConstructor>()
|
||||
|
||||
private val propertyCache = mutableMapOf<FirProperty, IrProperty>()
|
||||
|
||||
private val localStorage = Fir2IrLocalStorage()
|
||||
|
||||
fun enterScope(descriptor: DeclarationDescriptor) {
|
||||
irSymbolTable.enterScope(descriptor)
|
||||
if (descriptor is WrappedSimpleFunctionDescriptor ||
|
||||
descriptor is WrappedClassConstructorDescriptor ||
|
||||
descriptor is WrappedPropertyDescriptor
|
||||
) {
|
||||
localStorage.enterCallable()
|
||||
}
|
||||
}
|
||||
|
||||
fun leaveScope(descriptor: DeclarationDescriptor) {
|
||||
if (descriptor is WrappedSimpleFunctionDescriptor ||
|
||||
descriptor is WrappedClassConstructorDescriptor ||
|
||||
descriptor is WrappedPropertyDescriptor
|
||||
) {
|
||||
localStorage.leaveCallable()
|
||||
}
|
||||
irSymbolTable.leaveScope(descriptor)
|
||||
}
|
||||
|
||||
private fun getIrExternalPackageFragment(fqName: FqName): IrExternalPackageFragment {
|
||||
return fragmentCache.getOrPut(fqName) {
|
||||
// TODO: module descriptor is wrong here
|
||||
return irSymbolTable.declareExternalPackageFragment(FirPackageFragmentDescriptor(fqName, moduleDescriptor))
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.declareThisReceiver() {
|
||||
enterScope(descriptor)
|
||||
val thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
|
||||
val thisType = IrSimpleTypeImpl(symbol, false, emptyList(), emptyList())
|
||||
val parent = this
|
||||
thisReceiver = irSymbolTable.declareValueParameter(
|
||||
startOffset, endOffset, thisOrigin, WrappedValueParameterDescriptor(), thisType
|
||||
) { symbol ->
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, thisOrigin, symbol,
|
||||
Name.special("<this>"), -1, thisType,
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false
|
||||
).apply { this.parent = parent }
|
||||
}
|
||||
leaveScope(descriptor)
|
||||
}
|
||||
|
||||
fun getIrClass(regularClass: FirRegularClass, setParent: Boolean = true): IrClass {
|
||||
fun create(): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val modality = regularClass.modality!!
|
||||
return regularClass.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality) { symbol ->
|
||||
IrClassImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
regularClass.name, regularClass.classKind,
|
||||
regularClass.visibility, modality,
|
||||
regularClass.isCompanion, regularClass.isInner,
|
||||
regularClass.isData, false, regularClass.isInline
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
if (setParent) {
|
||||
val classId = regularClass.classId
|
||||
val parentId = classId.outerClassId
|
||||
if (parentId != null) {
|
||||
val parentFirSymbol = firSymbolProvider.getClassLikeSymbolByFqName(parentId)
|
||||
if (parentFirSymbol is FirClassSymbol) {
|
||||
val parentIrSymbol = getIrClassSymbol(parentFirSymbol)
|
||||
parent = parentIrSymbol.owner
|
||||
}
|
||||
} else {
|
||||
val packageFqName = classId.packageFqName
|
||||
parent = getIrExternalPackageFragment(packageFqName)
|
||||
}
|
||||
}
|
||||
declareThisReceiver()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (regularClass.visibility == Visibilities.LOCAL) {
|
||||
val cached = localStorage.getLocalClass(regularClass)
|
||||
if (cached != null) return cached
|
||||
val created = create()
|
||||
localStorage.putLocalClass(regularClass, created)
|
||||
return created
|
||||
}
|
||||
return classCache.getOrPut(regularClass, ::create)
|
||||
}
|
||||
|
||||
fun getIrAnonymousObject(anonymousObject: FirAnonymousObject): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val modality = Modality.FINAL
|
||||
return anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality) { symbol ->
|
||||
IrClassImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
Name.special("<no name provided>"), anonymousObject.classKind,
|
||||
Visibilities.LOCAL, modality,
|
||||
isCompanion = false, isInner = false, isData = false, isExternal = false, isInline = false
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
declareThisReceiver()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getIrTypeParameter(typeParameter: FirTypeParameter, index: Int = 0): IrTypeParameter {
|
||||
return typeParameterCache.getOrPut(typeParameter) {
|
||||
val descriptor = WrappedTypeParameterDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
typeParameter.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareGlobalTypeParameter(startOffset, endOffset, origin, descriptor) { symbol ->
|
||||
IrTypeParameterImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
typeParameter.name, index,
|
||||
typeParameter.isReified,
|
||||
typeParameter.variance
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrDeclaration.setParentByOwnFir(firMember: FirCallableMemberDeclaration) {
|
||||
val firBasedSymbol = firMember.symbol
|
||||
val callableId = firBasedSymbol.callableId
|
||||
val parentClassId = callableId.classId
|
||||
if (parentClassId != null) {
|
||||
val parentFirSymbol = firSymbolProvider.getClassLikeSymbolByFqName(parentClassId)
|
||||
if (parentFirSymbol is FirClassSymbol) {
|
||||
val parentIrSymbol = getIrClassSymbol(parentFirSymbol)
|
||||
val parentIrClass = parentIrSymbol.owner
|
||||
parent = parentIrClass
|
||||
// TODO: parentIrClass.declarations += this (probably needed for external stuff)
|
||||
}
|
||||
} else {
|
||||
val packageFqName = callableId.packageName
|
||||
val parentIrPackageFragment = getIrExternalPackageFragment(packageFqName)
|
||||
parent = parentIrPackageFragment
|
||||
parentIrPackageFragment.declarations += this
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : IrFunction> T.declareParameters(function: FirFunction) {
|
||||
val parent = this
|
||||
for ((index, valueParameter) in function.valueParameters.withIndex()) {
|
||||
valueParameters += createAndSaveIrParameter(valueParameter, index).apply { this.parent = parent }
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : IrFunction> T.bindAndDeclareParameters(
|
||||
function: FirFunction,
|
||||
descriptor: WrappedCallableDescriptor<T>,
|
||||
setParent: Boolean,
|
||||
shouldLeaveScope: Boolean
|
||||
): T {
|
||||
descriptor.bind(this)
|
||||
if (setParent) {
|
||||
setParentByOwnFir(function as FirCallableMemberDeclaration)
|
||||
}
|
||||
enterScope(descriptor)
|
||||
declareParameters(function)
|
||||
if (shouldLeaveScope) {
|
||||
leaveScope(descriptor)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private fun <T : IrFunction> T.enterLocalScope(function: FirFunction): T {
|
||||
enterScope(descriptor)
|
||||
for ((firParameter, irParameter) in function.valueParameters.zip(valueParameters)) {
|
||||
irSymbolTable.introduceValueParameter(irParameter)
|
||||
localStorage.putParameter(firParameter, irParameter)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun getIrFunction(
|
||||
function: FirNamedFunction,
|
||||
setParent: Boolean = true,
|
||||
shouldLeaveScope: Boolean = false,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrSimpleFunction {
|
||||
fun create(): IrSimpleFunction {
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
return function.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareSimpleFunction(startOffset, endOffset, origin, descriptor) { symbol ->
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
function.name, function.visibility, function.modality!!,
|
||||
function.returnTypeRef.toIrType(session, this),
|
||||
function.isInline, function.isExternal,
|
||||
function.isTailRec, function.isSuspend
|
||||
)
|
||||
}
|
||||
}.bindAndDeclareParameters(function, descriptor, setParent, shouldLeaveScope)
|
||||
}
|
||||
|
||||
if (function.visibility == Visibilities.LOCAL) {
|
||||
val cached = localStorage.getLocalFunction(function)
|
||||
if (cached != null) {
|
||||
return if (shouldLeaveScope) cached else cached.enterLocalScope(function)
|
||||
}
|
||||
val created = create()
|
||||
localStorage.putLocalFunction(function, created)
|
||||
return created
|
||||
}
|
||||
val cached = functionCache[function]
|
||||
if (cached != null) {
|
||||
return if (shouldLeaveScope) cached else cached.enterLocalScope(function)
|
||||
}
|
||||
val created = create()
|
||||
functionCache[function] = created
|
||||
return created
|
||||
}
|
||||
|
||||
fun getIrLocalFunction(function: FirAnonymousFunction): IrSimpleFunction {
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
val isLambda = function.psi is KtFunctionLiteral
|
||||
val origin = if (isLambda) IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA else IrDeclarationOrigin.DEFINED
|
||||
return function.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareSimpleFunction(startOffset, endOffset, origin, descriptor) { symbol ->
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
if (isLambda) Name.special("<anonymous>") else Name.special("<no name provided>"),
|
||||
Visibilities.LOCAL, Modality.FINAL,
|
||||
function.returnTypeRef.toIrType(session, this),
|
||||
isInline = false, isExternal = false, isTailrec = false,
|
||||
// TODO: suspend lambda
|
||||
isSuspend = false
|
||||
)
|
||||
}.bindAndDeclareParameters(function, descriptor, setParent = false, shouldLeaveScope = false)
|
||||
}
|
||||
}
|
||||
|
||||
fun getIrConstructor(constructor: FirConstructor, setParent: Boolean = true, shouldLeaveScope: Boolean = false): IrConstructor {
|
||||
return constructorCache.getOrPut(constructor) {
|
||||
val descriptor = WrappedClassConstructorDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val isPrimary = constructor.isPrimary
|
||||
return constructor.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareConstructor(startOffset, endOffset, origin, descriptor) { symbol ->
|
||||
IrConstructorImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
constructor.name, constructor.visibility,
|
||||
constructor.returnTypeRef.toIrType(session, this),
|
||||
false, false, isPrimary
|
||||
).bindAndDeclareParameters(constructor, descriptor, setParent, shouldLeaveScope)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun getIrProperty(property: FirProperty, setParent: Boolean = true): IrProperty {
|
||||
return propertyCache.getOrPut(property) {
|
||||
val descriptor = WrappedPropertyDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
property.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareProperty(
|
||||
startOffset, endOffset,
|
||||
origin, descriptor, property.delegate != null
|
||||
) { symbol ->
|
||||
IrPropertyImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
property.name, property.visibility, property.modality!!,
|
||||
property.isVar, property.isConst, property.isLateInit,
|
||||
property.delegate != null,
|
||||
// TODO
|
||||
isExternal = false
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
if (setParent) {
|
||||
setParentByOwnFir(property)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAndSaveIrParameter(valueParameter: FirValueParameter, index: Int = -1): IrValueParameter {
|
||||
val descriptor = WrappedValueParameterDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val type = valueParameter.returnTypeRef.toIrType(session, this)
|
||||
val irParameter = valueParameter.convertWithOffsets { startOffset, endOffset ->
|
||||
irSymbolTable.declareValueParameter(
|
||||
startOffset, endOffset, origin, descriptor, type
|
||||
) { symbol ->
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
valueParameter.name, index, type,
|
||||
null, valueParameter.isCrossinline, valueParameter.isNoinline
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
localStorage.putParameter(valueParameter, irParameter)
|
||||
return irParameter
|
||||
}
|
||||
|
||||
private var lastTemporaryIndex: Int = 0
|
||||
private fun nextTemporaryIndex(): Int = lastTemporaryIndex++
|
||||
|
||||
private fun getNameForTemporary(nameHint: String?): String {
|
||||
val index = nextTemporaryIndex()
|
||||
return if (nameHint != null) "tmp${index}_$nameHint" else "tmp$index"
|
||||
}
|
||||
|
||||
private fun declareIrVariable(
|
||||
startOffset: Int, endOffset: Int,
|
||||
origin: IrDeclarationOrigin, name: Name, type: IrType,
|
||||
isVar: Boolean, isConst: Boolean, isLateinit: Boolean
|
||||
): IrVariable {
|
||||
val descriptor = WrappedVariableDescriptor()
|
||||
return irSymbolTable.declareVariable(startOffset, endOffset, origin, descriptor, type) { symbol ->
|
||||
IrVariableImpl(
|
||||
startOffset, endOffset, origin, symbol, name, type,
|
||||
isVar, isConst, isLateinit
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createAndSaveIrVariable(variable: FirVariable): IrVariable {
|
||||
val type = variable.returnTypeRef.toIrType(session, this)
|
||||
val irVariable = variable.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrVariable(
|
||||
startOffset, endOffset, IrDeclarationOrigin.DEFINED,
|
||||
variable.name, type, variable.isVar, isConst = false, isLateinit = false
|
||||
)
|
||||
}
|
||||
localStorage.putVariable(variable, irVariable)
|
||||
return irVariable
|
||||
}
|
||||
|
||||
fun declareTemporaryVariable(base: IrExpression, nameHint: String? = null): IrVariable {
|
||||
return declareIrVariable(
|
||||
base.startOffset, base.endOffset, IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||
Name.identifier(getNameForTemporary(nameHint)), base.type,
|
||||
isVar = false, isConst = false, isLateinit = false
|
||||
)
|
||||
}
|
||||
|
||||
fun getIrClassSymbol(firClassSymbol: FirClassSymbol): IrClassSymbol {
|
||||
val irClass = getIrClass(firClassSymbol.fir)
|
||||
return irSymbolTable.referenceClass(irClass.descriptor)
|
||||
}
|
||||
|
||||
fun getIrTypeParameterSymbol(firTypeParameterSymbol: FirTypeParameterSymbol): IrTypeParameterSymbol {
|
||||
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir)
|
||||
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
|
||||
}
|
||||
|
||||
fun getIrTypeParameterSymbol(typeParameterSymbol: LibraryTypeParameterSymbol): IrTypeParameterSymbol {
|
||||
val irTypeParameter = libraryTypeParameterCache.getOrPut(typeParameterSymbol) {
|
||||
val descriptor = WrappedTypeParameterDescriptor()
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
irSymbolTable.declareGlobalTypeParameter(-1, -1, origin, descriptor) { symbol ->
|
||||
IrTypeParameterImpl(
|
||||
-1, -1, origin, symbol,
|
||||
typeParameterSymbol.name, -1,
|
||||
false,
|
||||
Variance.INVARIANT
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
|
||||
}
|
||||
|
||||
fun getIrFunctionSymbol(firFunctionSymbol: FirFunctionSymbol): IrFunctionSymbol {
|
||||
return when (val firDeclaration = firFunctionSymbol.fir) {
|
||||
is FirNamedFunction -> {
|
||||
val irDeclaration = getIrFunction(firDeclaration, shouldLeaveScope = true)
|
||||
irSymbolTable.referenceSimpleFunction(irDeclaration.descriptor)
|
||||
}
|
||||
is FirConstructor -> {
|
||||
val irDeclaration = getIrConstructor(firDeclaration, shouldLeaveScope = true)
|
||||
irSymbolTable.referenceConstructor(irDeclaration.descriptor)
|
||||
}
|
||||
else -> throw AssertionError("Should not be here")
|
||||
}
|
||||
}
|
||||
|
||||
fun getIrPropertySymbol(firPropertySymbol: FirPropertySymbol): IrPropertySymbol {
|
||||
val irProperty = getIrProperty(firPropertySymbol.fir as FirProperty)
|
||||
return irSymbolTable.referenceProperty(irProperty.descriptor)
|
||||
}
|
||||
|
||||
private fun getIrVariableSymbol(firVariable: FirVariable): IrVariableSymbol {
|
||||
val irDeclaration = localStorage.getVariable(firVariable)
|
||||
?: throw IllegalArgumentException("Cannot find variable ${firVariable.render()} in local storage")
|
||||
return irSymbolTable.referenceVariable(irDeclaration.descriptor)
|
||||
}
|
||||
|
||||
fun getIrValueSymbol(firVariableSymbol: FirVariableSymbol): IrValueSymbol {
|
||||
return when (val firDeclaration = firVariableSymbol.fir) {
|
||||
is FirValueParameter -> {
|
||||
val irDeclaration = localStorage.getParameter(firDeclaration)
|
||||
// catch parameter is FirValueParameter in FIR but IrVariable in IR
|
||||
?: return getIrVariableSymbol(firDeclaration)
|
||||
irSymbolTable.referenceValueParameter(irDeclaration.descriptor)
|
||||
}
|
||||
is FirVariable -> {
|
||||
getIrVariableSymbol(firDeclaration)
|
||||
}
|
||||
else -> throw AssertionError("Should not be here")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariable
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
|
||||
class Fir2IrLocalStorage {
|
||||
|
||||
private val cacheStack = mutableListOf<Fir2IrCallableCache>()
|
||||
|
||||
fun enterCallable() {
|
||||
cacheStack += Fir2IrCallableCache()
|
||||
}
|
||||
|
||||
fun leaveCallable() {
|
||||
cacheStack.last().clear()
|
||||
cacheStack.removeAt(cacheStack.size - 1)
|
||||
}
|
||||
|
||||
fun getParameter(parameter: FirValueParameter): IrValueParameter? {
|
||||
for (cache in cacheStack.asReversed()) {
|
||||
val local = cache.getParameter(parameter)
|
||||
if (local != null) return local
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getVariable(variable: FirVariable): IrVariable? {
|
||||
for (cache in cacheStack.asReversed()) {
|
||||
val local = cache.getVariable(variable)
|
||||
if (local != null) return local
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getLocalClass(localClass: FirClass): IrClass? {
|
||||
for (cache in cacheStack.asReversed()) {
|
||||
val local = cache.getLocalClass(localClass)
|
||||
if (local != null) return local
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getLocalFunction(localFunction: FirFunction): IrSimpleFunction? {
|
||||
for (cache in cacheStack.asReversed()) {
|
||||
val local = cache.getLocalFunction(localFunction)
|
||||
if (local != null) return local
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun putParameter(firParameter: FirValueParameter, irParameter: IrValueParameter) {
|
||||
cacheStack.last().putParameter(firParameter, irParameter)
|
||||
}
|
||||
|
||||
fun putVariable(firVariable: FirVariable, irVariable: IrVariable) {
|
||||
cacheStack.last().putVariable(firVariable, irVariable)
|
||||
}
|
||||
|
||||
fun putLocalClass(firClass: FirClass, irClass: IrClass) {
|
||||
cacheStack.last().putLocalClass(firClass, irClass)
|
||||
}
|
||||
|
||||
fun putLocalFunction(firFunction: FirFunction, irFunction: IrSimpleFunction) {
|
||||
cacheStack.last().putLocalFunction(firFunction, irFunction)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorVisitor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FirModuleDescriptor(val session: FirSession) : ModuleDescriptor {
|
||||
override val builtIns: KotlinBuiltIns
|
||||
get() = DefaultBuiltIns.Instance
|
||||
|
||||
override fun shouldSeeInternalsOf(targetModule: ModuleDescriptor): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getPackage(fqName: FqName): PackageViewDescriptor {
|
||||
val symbolProvider = FirSymbolProvider.getInstance(session)
|
||||
if (symbolProvider.getPackage(fqName) != null) {
|
||||
return FirPackageViewDescriptor(fqName, this)
|
||||
}
|
||||
TODO("Missing package reporting")
|
||||
}
|
||||
|
||||
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override val allDependencyModules: List<ModuleDescriptor>
|
||||
get() = TODO("not implemented")
|
||||
override val expectedByModules: List<ModuleDescriptor>
|
||||
get() = TODO("not implemented")
|
||||
|
||||
override fun <T> getCapability(capability: ModuleDescriptor.Capability<T>): T? {
|
||||
return null
|
||||
}
|
||||
|
||||
override val isValid: Boolean
|
||||
get() = true
|
||||
|
||||
override fun assertValid() {
|
||||
|
||||
}
|
||||
|
||||
override fun getOriginal(): DeclarationDescriptor {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun getName(): Name {
|
||||
return Name.identifier("module for FIR session")
|
||||
}
|
||||
|
||||
override val stableName: Name?
|
||||
get() = name
|
||||
|
||||
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override val annotations: Annotations
|
||||
get() = TODO("not implemented")
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
|
||||
class FirPackageFragmentDescriptor(override val fqName: FqName, val moduleDescriptor: ModuleDescriptor) : PackageFragmentDescriptor {
|
||||
override fun getContainingDeclaration(): ModuleDescriptor {
|
||||
return moduleDescriptor
|
||||
}
|
||||
|
||||
|
||||
override fun getMemberScope(): MemberScope {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun getOriginal(): DeclarationDescriptorWithSource {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun getName(): Name {
|
||||
return fqName.shortName()
|
||||
}
|
||||
|
||||
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>?, data: D): R {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun getSource(): SourceElement {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override val annotations: Annotations
|
||||
get() = TODO("not implemented")
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
|
||||
class FirPackageViewDescriptor(override val fqName: FqName, val moduleDescriptor: ModuleDescriptor) : PackageViewDescriptor {
|
||||
override fun getContainingDeclaration(): PackageViewDescriptor? {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override val memberScope: MemberScope
|
||||
get() = TODO("not implemented")
|
||||
override val module: ModuleDescriptor
|
||||
get() = moduleDescriptor
|
||||
override val fragments: List<PackageFragmentDescriptor>
|
||||
get() = listOf(FirPackageFragmentDescriptor(fqName, moduleDescriptor))
|
||||
|
||||
override fun getOriginal(): DeclarationDescriptor {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun getName(): Name {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>?, data: D): R {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override val annotations: Annotations
|
||||
get() = TODO("not implemented")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.fir
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElementFinder
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
|
||||
import org.jetbrains.kotlin.ir.AbstractIrTextTestCase
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFir2IrTextTest : AbstractIrTextTestCase() {
|
||||
|
||||
private fun prepareProjectExtensions(project: Project) {
|
||||
Extensions.getArea(project)
|
||||
.getExtensionPoint(PsiElementFinder.EP_NAME)
|
||||
.unregisterExtension(JavaElementFinder::class.java)
|
||||
}
|
||||
|
||||
override fun doTest(filePath: String?) {
|
||||
if (filePath != null) {
|
||||
val originalTextPath = filePath.replace(".kt", ".txt")
|
||||
val firTextPath = filePath.replace(".kt", ".fir.txt")
|
||||
val originalText = File(originalTextPath)
|
||||
val firText = File(firTextPath)
|
||||
if (originalText.exists() && firText.exists()) {
|
||||
val originalLines = originalText.readLines()
|
||||
val firLines = firText.readLines()
|
||||
TestCase.assertFalse(
|
||||
"Dumps via FIR & via old FE are the same. Please delete .fir.txt dump and add // FIR_IDENTICAL to test source",
|
||||
firLines.withIndex().all { (index, line) ->
|
||||
val trimmed = line.trim()
|
||||
val originalTrimmed = originalLines.getOrNull(index)?.trim()
|
||||
trimmed.isEmpty() && originalTrimmed?.isEmpty() != false || trimmed == originalTrimmed
|
||||
} && originalLines.withIndex().all { (index, line) ->
|
||||
index < firLines.size || line.trim().isEmpty()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
super.doTest(filePath)
|
||||
}
|
||||
|
||||
override fun getExpectedTextFileName(testFile: TestFile, name: String): String {
|
||||
// NB: replace with if (true) to make test against old FE results
|
||||
if ("// FIR_IDENTICAL" in testFile.content.split("\n")) {
|
||||
return super.getExpectedTextFileName(testFile, name)
|
||||
}
|
||||
return name.replace(".txt", ".fir.txt").replace(".kt", ".fir.txt")
|
||||
}
|
||||
|
||||
override fun generateIrModule(ignoreErrors: Boolean): IrModuleFragment {
|
||||
val psiFiles = myFiles.psiFiles
|
||||
|
||||
val project = psiFiles.first().project
|
||||
prepareProjectExtensions(project)
|
||||
|
||||
val scope = GlobalSearchScope.filesScope(project, psiFiles.map { it.virtualFile })
|
||||
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
|
||||
val session = createSession(myEnvironment, scope)
|
||||
|
||||
val builder = RawFirBuilder(session, stubMode = false)
|
||||
|
||||
val resolveTransformer = FirTotalResolveTransformer()
|
||||
val firFiles = psiFiles.map {
|
||||
val firFile = builder.buildFirFile(it)
|
||||
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)
|
||||
firFile
|
||||
}.also {
|
||||
try {
|
||||
resolveTransformer.processFiles(it)
|
||||
} catch (e: Exception) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
return Fir2IrConverter.createModuleFragment(session, firFiles, myEnvironment.configuration.languageVersionSettings)
|
||||
}
|
||||
}
|
||||
+1614
File diff suppressed because it is too large
Load Diff
+37
-27
@@ -90,7 +90,7 @@ class FirClassSubstitutionScope(
|
||||
override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction {
|
||||
useSiteScope.processFunctionsByName(name) process@{ original ->
|
||||
|
||||
val function = fakeOverrides.getOrPut(original) { createFakeOverride(original, name) }
|
||||
val function = fakeOverrides.getOrPut(original) { createFakeOverride(original) }
|
||||
processor(function as ConeFunctionSymbol)
|
||||
}
|
||||
|
||||
@@ -104,10 +104,7 @@ class FirClassSubstitutionScope(
|
||||
|
||||
private val typeCalculator by lazy { ReturnTypeCalculatorWithJump(session) }
|
||||
|
||||
private fun createFakeOverride(
|
||||
original: ConeFunctionSymbol,
|
||||
name: Name
|
||||
): FirFunctionSymbol {
|
||||
private fun createFakeOverride(original: ConeFunctionSymbol): FirFunctionSymbol {
|
||||
|
||||
val member = original.firUnsafe<FirFunction>()
|
||||
if (member is FirConstructor) return original as FirFunctionSymbol // TODO: substitution for constructors
|
||||
@@ -123,32 +120,45 @@ class FirClassSubstitutionScope(
|
||||
it.returnTypeRef.coneTypeUnsafe().substitute()
|
||||
}
|
||||
|
||||
val symbol = FirFunctionSymbol(original.callableId, true)
|
||||
with(member) {
|
||||
// TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl
|
||||
// As second alternative, we can invent some light-weight kind of FirRegularClass
|
||||
FirMemberFunctionImpl(
|
||||
this@FirClassSubstitutionScope.session,
|
||||
psi,
|
||||
symbol,
|
||||
name,
|
||||
member.receiverTypeRef?.withReplacedConeType(this@FirClassSubstitutionScope.session, newReceiverType),
|
||||
member.returnTypeRef.withReplacedConeType(this@FirClassSubstitutionScope.session, newReturnType)
|
||||
).apply {
|
||||
status = member.status as FirDeclarationStatusImpl
|
||||
valueParameters += member.valueParameters.zip(newParameterTypes) { valueParameter, newType ->
|
||||
with(valueParameter) {
|
||||
FirValueParameterImpl(
|
||||
this@FirClassSubstitutionScope.session, psi,
|
||||
name, this.returnTypeRef.withReplacedConeType(this@FirClassSubstitutionScope.session, newType),
|
||||
defaultValue, isCrossinline, isNoinline, isVararg,
|
||||
FirVariableSymbol(valueParameter.symbol.callableId)
|
||||
)
|
||||
return createFakeOverride(session, member, original as FirFunctionSymbol, newReceiverType, newReturnType, newParameterTypes)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun createFakeOverride(
|
||||
session: FirSession,
|
||||
baseFunction: FirNamedFunction,
|
||||
baseSymbol: FirFunctionSymbol,
|
||||
newReceiverType: ConeKotlinType? = null,
|
||||
newReturnType: ConeKotlinType? = null,
|
||||
newParameterTypes: List<ConeKotlinType?>? = null
|
||||
): FirFunctionSymbol {
|
||||
val symbol = FirFunctionSymbol(baseSymbol.callableId, true, baseSymbol)
|
||||
with(baseFunction) {
|
||||
// TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl
|
||||
// As second alternative, we can invent some light-weight kind of FirRegularClass
|
||||
FirMemberFunctionImpl(
|
||||
session,
|
||||
psi, symbol, name,
|
||||
baseFunction.receiverTypeRef?.withReplacedConeType(session, newReceiverType),
|
||||
baseFunction.returnTypeRef.withReplacedConeType(session, newReturnType)
|
||||
).apply {
|
||||
status = baseFunction.status as FirDeclarationStatusImpl
|
||||
valueParameters += baseFunction.valueParameters.zip(
|
||||
newParameterTypes ?: List(baseFunction.valueParameters.size) { null }
|
||||
) { valueParameter, newType ->
|
||||
with(valueParameter) {
|
||||
FirValueParameterImpl(
|
||||
session, psi,
|
||||
name, this.returnTypeRef.withReplacedConeType(session, newType),
|
||||
defaultValue, isCrossinline, isNoinline, isVararg,
|
||||
FirVariableSymbol(valueParameter.symbol.callableId)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return symbol
|
||||
}
|
||||
return symbol
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,5 +41,7 @@ enum class FirOperation(val operator: String = "???") {
|
||||
val BOOLEANS: Set<FirOperation> = EnumSet.of(
|
||||
EQ, NOT_EQ, IDENTITY, NOT_IDENTITY, LT, GT, LT_EQ, GT_EQ, IS, NOT_IS
|
||||
)
|
||||
|
||||
val COMPARISONS: Set<FirOperation> = EnumSet.of(LT, GT, LT_EQ, GT_EQ)
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,9 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
|
||||
class FirFunctionSymbol(
|
||||
override val callableId: CallableId,
|
||||
val isFakeOverride: Boolean = false
|
||||
val isFakeOverride: Boolean = false,
|
||||
// Actual for fake override only
|
||||
val overriddenSymbol: FirFunctionSymbol? = null
|
||||
) : ConeFunctionSymbol, FirCallableSymbol() {
|
||||
override val parameters: List<ConeKotlinType>
|
||||
get() = emptyList()
|
||||
|
||||
@@ -57,3 +57,9 @@ class FirImplicitBooleanTypeRef(
|
||||
session: FirSession,
|
||||
psi: PsiElement?
|
||||
) : FirImplicitBuiltinTypeRef(session, psi, StandardClassIds.Boolean)
|
||||
|
||||
class FirImplicitNothingTypeRef(
|
||||
session: FirSession,
|
||||
psi: PsiElement?
|
||||
) : FirImplicitBuiltinTypeRef(session, psi, StandardClassIds.Nothing)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user