[PLUGIN API] Extract IrPluginContext into separate interface

- Isolate ir infrastructure implementation details behind special interface
This commit is contained in:
Roman Artemev
2020-05-19 10:27:26 +03:00
committed by romanart
parent a84780fefb
commit 257c4c5604
7 changed files with 160 additions and 114 deletions
@@ -6,116 +6,16 @@
package org.jetbrains.kotlin.backend.common.extensions
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IrDeserializer
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.scopes.MemberScope
// TODO: Make IrPluginContext be interface
open class IrPluginContext(
@Deprecated("FrontEnd API shouldn't be accessed in Ir plugin environment")
val moduleDescriptor: ModuleDescriptor,
@Deprecated("FrontEnd API shouldn't be accessed in Ir plugin environment")
val bindingContext: BindingContext,
val languageVersionSettings: LanguageVersionSettings,
@Deprecated("FrontEnd API shouldn't be accessed in Ir plugin environment")
val symbolTable: ReferenceSymbolTable,
@Deprecated("FrontEnd API shouldn't be accessed in Ir plugin environment")
val typeTranslator: TypeTranslator,
override val irBuiltIns: IrBuiltIns,
private val linker: IrDeserializer,
val symbols: BuiltinSymbolsBase = BuiltinSymbolsBase(irBuiltIns, irBuiltIns.builtIns, symbolTable)
) : IrGeneratorContext() {
private fun resolveMemberScope(fqName: FqName): MemberScope? {
val pkg = moduleDescriptor.getPackage(fqName)
if (fqName.isRoot || pkg.fragments.isNotEmpty()) return pkg.memberScope
val parentMemberScope = resolveMemberScope(fqName.parent()) ?: return null
val classDescriptor =
parentMemberScope.getContributedClassifier(fqName.shortName(), NoLookupLocation.FROM_BACKEND) as? ClassDescriptor ?: return null
return classDescriptor.unsubstitutedMemberScope
}
private fun <S : IrSymbol> resolveSymbol(fqName: FqName, referencer: (MemberScope) -> S?): S? {
val memberScope = resolveMemberScope(fqName) ?: return null
val symbol = referencer(memberScope) ?: return null
if (symbol.isBound) return symbol
linker.getDeclaration(symbol)
linker.postProcess()
return symbol
}
private fun <S : IrSymbol> resolveSymbolCollection(fqName: FqName, referencer: (MemberScope) -> Collection<S>): Collection<S> {
val memberScope = resolveMemberScope(fqName) ?: return emptyList()
val symbols = referencer(memberScope)
symbols.forEach { if (!it.isBound) linker.getDeclaration(it) }
linker.postProcess()
return symbols
}
fun referenceClass(fqName: FqName): IrClassSymbol? {
assert(!fqName.isRoot)
return resolveSymbol(fqName.parent()) { scope ->
val classDescriptor = scope.getContributedClassifier(fqName.shortName(), NoLookupLocation.FROM_BACKEND) as? ClassDescriptor?
classDescriptor?.let {
symbolTable.referenceClass(it)
}
}
}
fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn")
return classSymbol.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol }
}
fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> {
assert(!fqName.isRoot)
return resolveSymbolCollection(fqName.parent()) { scope ->
val descriptors = scope.getContributedFunctions(fqName.shortName(), NoLookupLocation.FROM_BACKEND)
descriptors.map { symbolTable.referenceSimpleFunction(it) }
}
}
fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> {
assert(!fqName.isRoot)
return resolveSymbolCollection(fqName.parent()) { scope ->
val descriptors = scope.getContributedVariables(fqName.shortName(), NoLookupLocation.FROM_BACKEND)
descriptors.map { symbolTable.referenceProperty(it) }
}
}
}
interface IrGenerationExtension {
companion object :
ProjectExtensionDescriptor<IrGenerationExtension>("org.jetbrains.kotlin.irGenerationExtension", IrGenerationExtension::class.java)
ProjectExtensionDescriptor<IrGenerationExtension>(
"org.jetbrains.kotlin.rGenerationExtension", IrGenerationExtension::class.java
)
fun generate(
moduleFragment: IrModuleFragment,
pluginContext: IrPluginContext
)
fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext)
}
// Extension point for plugins which run before any lowerings, but after the Ir has been constructed.
@@ -127,8 +27,5 @@ interface PureIrGenerationExtension {
"org.jetbrains.kotlin.pureIrGenerationExtension", PureIrGenerationExtension::class.java
)
fun generate(
moduleFragment: IrModuleFragment,
context: CommonBackendContext
)
fun generate(moduleFragment: IrModuleFragment, context: CommonBackendContext)
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.extensions
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingContext
interface IrPluginContext : IrGeneratorContext {
val languageVersionSettings: LanguageVersionSettings
@Deprecated("FrontEnd API shouldn't be accessed in Ir plugin environment")
val moduleDescriptor: ModuleDescriptor
@Deprecated("FrontEnd API shouldn't be accessed in Ir plugin environment")
val bindingContext: BindingContext
@Deprecated("FrontEnd API shouldn't be accessed in Ir plugin environment")
val symbolTable: ReferenceSymbolTable
@Deprecated("FrontEnd API shouldn't be accessed in Ir plugin environment")
val typeTranslator: TypeTranslator
val symbols: BuiltinSymbolsBase
// The following API is experimental
fun referenceClass(fqName: FqName): IrClassSymbol?
fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol>
fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol>
fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol>
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.extensions
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IrDeserializer
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.scopes.MemberScope
open class IrPluginContextImpl(
private val module: ModuleDescriptor,
override val bindingContext: BindingContext,
override val languageVersionSettings: LanguageVersionSettings,
private val st: ReferenceSymbolTable,
override val typeTranslator: TypeTranslator,
override val irBuiltIns: IrBuiltIns,
private val linker: IrDeserializer,
override val symbols: BuiltinSymbolsBase = BuiltinSymbolsBase(irBuiltIns, irBuiltIns.builtIns, st)
) : IrPluginContext {
override val moduleDescriptor: ModuleDescriptor = module
override val symbolTable: ReferenceSymbolTable = st
private fun resolveMemberScope(fqName: FqName): MemberScope? {
val pkg = module.getPackage(fqName)
if (fqName.isRoot || pkg.fragments.isNotEmpty()) return pkg.memberScope
val parentMemberScope = resolveMemberScope(fqName.parent()) ?: return null
val classDescriptor =
parentMemberScope.getContributedClassifier(fqName.shortName(), NoLookupLocation.FROM_BACKEND) as? ClassDescriptor ?: return null
return classDescriptor.unsubstitutedMemberScope
}
private fun <S : IrSymbol> resolveSymbol(fqName: FqName, referencer: (MemberScope) -> S?): S? {
val memberScope = resolveMemberScope(fqName) ?: return null
val symbol = referencer(memberScope) ?: return null
if (symbol.isBound) return symbol
linker.getDeclaration(symbol)
linker.postProcess()
return symbol
}
private fun <S : IrSymbol> resolveSymbolCollection(fqName: FqName, referencer: (MemberScope) -> Collection<S>): Collection<S> {
val memberScope = resolveMemberScope(fqName) ?: return emptyList()
val symbols = referencer(memberScope)
symbols.forEach { if (!it.isBound) linker.getDeclaration(it) }
linker.postProcess()
return symbols
}
override fun referenceClass(fqName: FqName): IrClassSymbol? {
assert(!fqName.isRoot)
return resolveSymbol(fqName.parent()) { scope ->
val classDescriptor = scope.getContributedClassifier(fqName.shortName(), NoLookupLocation.FROM_BACKEND) as? ClassDescriptor?
classDescriptor?.let {
st.referenceClass(it)
}
}
}
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn")
return classSymbol.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol }
}
override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> {
assert(!fqName.isRoot)
return resolveSymbolCollection(fqName.parent()) { scope ->
val descriptors = scope.getContributedFunctions(fqName.shortName(), NoLookupLocation.FROM_BACKEND)
descriptors.map { st.referenceSimpleFunction(it) }
}
}
override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> {
assert(!fqName.isRoot)
return resolveSymbolCollection(fqName.parent()) { scope ->
val descriptors = scope.getContributedVariables(fqName.shortName(), NoLookupLocation.FROM_BACKEND)
descriptors.map { st.referenceProperty(it) }
}
}
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen
@@ -57,7 +57,7 @@ object JvmBackendFacade {
val pluginContext by lazy {
psi2irContext.run {
val symbols = BuiltinSymbolsBase(irBuiltIns, moduleDescriptor.builtIns, symbolTable.lazyWrapper)
IrPluginContext(
IrPluginContextImpl(
moduleDescriptor, bindingContext, languageVersionSettings, symbolTable, typeTranslator, irBuiltIns, irLinker, symbols
)
}
@@ -57,7 +57,7 @@ class GeneratorContext(
val typeTranslator: TypeTranslator,
val constantValueGenerator: ConstantValueGenerator,
override val irBuiltIns: IrBuiltIns
) : IrGeneratorContext() {
) : IrGeneratorContext {
val callToSubstitutedDescriptorMap = mutableMapOf<IrDeclarationReference, CallableDescriptor>()
@@ -31,8 +31,8 @@ interface IrGeneratorContextInterface {
val irBuiltIns: IrBuiltIns
}
abstract class IrGeneratorContext : IrGeneratorContextInterface {
interface IrGeneratorContext : IrGeneratorContextInterface {
val builtIns: KotlinBuiltIns get() = irBuiltIns.builtIns
}
open class IrGeneratorContextBase(override val irBuiltIns: IrBuiltIns) : IrGeneratorContext()
open class IrGeneratorContextBase(override val irBuiltIns: IrBuiltIns) : IrGeneratorContext
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion
import org.jetbrains.kotlin.backend.common.serialization.knownBuiltins
@@ -301,7 +302,7 @@ fun GeneratorContext.generateModuleFragmentWithPlugins(
psi2Ir.addPostprocessingStep { module ->
extension.generate(
module,
IrPluginContext(
IrPluginContextImpl(
moduleDescriptor,
bindingContext,
languageVersionSettings,