Add 'generateModule' method to CodegenFactory

This commit is contained in:
Mikhael Bogdanov
2017-06-22 11:32:48 +02:00
parent 06fd996266
commit 3432014971
4 changed files with 92 additions and 63 deletions
@@ -16,19 +16,85 @@
package org.jetbrains.kotlin.codegen
import com.google.common.collect.Sets
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
interface CodegenFactory {
fun generateModule(state: GenerationState, files: Collection<KtFile?>, errorHandler: CompilationErrorHandler)
fun createPackageCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry): PackageCodegen
fun createMultifileClassCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry): MultifileClassCodegen
companion object {
fun doCheckCancelled(state: GenerationState) {
if (state.classBuilderMode.generateBodies) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
}
}
}
}
object DefaultCodegenFactory : CodegenFactory {
override fun generateModule(state: GenerationState, files: Collection<KtFile?>, errorHandler: CompilationErrorHandler) {
val filesInPackages = MultiMap<FqName, KtFile>()
val filesInMultifileClasses = MultiMap<FqName, KtFile>()
for (file in files) {
if (file == null) throw IllegalArgumentException("A null file given for compilation")
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file)
if (fileClassInfo.withJvmMultifileClass) {
filesInMultifileClasses.putValue(fileClassInfo.facadeClassFqName, file)
}
else {
filesInPackages.putValue(file.packageFqName, file)
}
}
val obsoleteMultifileClasses = HashSet(state.obsoleteMultifileClasses)
for (multifileClassFqName in filesInMultifileClasses.keySet() + obsoleteMultifileClasses) {
CodegenFactory.doCheckCancelled(state)
generateMultifileClass(state, multifileClassFqName, filesInMultifileClasses.get(multifileClassFqName), errorHandler)
}
val packagesWithObsoleteParts = HashSet(state.packagesWithObsoleteParts)
for (packageFqName in packagesWithObsoleteParts + filesInPackages.keySet()) {
CodegenFactory.doCheckCancelled(state)
generatePackage(state, packageFqName, filesInPackages.get(packageFqName), errorHandler)
}
}
override fun createPackageCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry) =
PackageCodegenImpl(state, files, fqName, registry)
override fun createMultifileClassCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry) =
MultifileClassCodegenImpl(state, files, fqName, registry)
private fun generateMultifileClass(
state: GenerationState,
multifileClassFqName: FqName,
files: Collection<KtFile>,
handler: CompilationErrorHandler
) {
val codegen = state.factory.forMultifileClass(multifileClassFqName, files)
codegen.generate(handler)
}
fun generatePackage(
state: GenerationState,
packageFqName: FqName,
jetFiles: Collection<KtFile>,
errorHandler: CompilationErrorHandler
) {
// We do not really generate package class, but use old package fqName to identify package in module-info.
//FqName packageClassFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
val codegen = state.factory.forPackage(packageFqName, jetFiles)
codegen.generate(errorHandler)
}
}
@@ -16,19 +16,13 @@
package org.jetbrains.kotlin.codegen;
import com.intellij.util.containers.MultiMap;
import kotlin.collections.SetsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.KtFile;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class KotlinCodegenFacade {
@@ -50,64 +44,19 @@ public class KotlinCodegenFacade {
@NotNull GenerationState state,
@NotNull CompilationErrorHandler errorHandler
) {
MultiMap<FqName, KtFile> filesInPackages = new MultiMap<>();
MultiMap<FqName, KtFile> filesInMultifileClasses = new MultiMap<>();
state.getCodegenFactory().generateModule(state, files, errorHandler);
for (KtFile file : files) {
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
JvmFileClassInfo fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file);
if (fileClassInfo.getWithJvmMultifileClass()) {
filesInMultifileClasses.putValue(fileClassInfo.getFacadeClassFqName(), file);
}
else {
filesInPackages.putValue(file.getPackageFqName(), file);
}
}
Set<FqName> obsoleteMultifileClasses = new HashSet<>(state.getObsoleteMultifileClasses());
for (FqName multifileClassFqName : SetsKt.plus(filesInMultifileClasses.keySet(), obsoleteMultifileClasses)) {
doCheckCancelled(state);
generateMultifileClass(state, multifileClassFqName, filesInMultifileClasses.get(multifileClassFqName), errorHandler);
}
Set<FqName> packagesWithObsoleteParts = new HashSet<>(state.getPackagesWithObsoleteParts());
for (FqName packageFqName : SetsKt.plus(packagesWithObsoleteParts, filesInPackages.keySet())) {
doCheckCancelled(state);
generatePackage(state, packageFqName, filesInPackages.get(packageFqName), errorHandler);
}
doCheckCancelled(state);
CodegenFactory.Companion.doCheckCancelled(state);
state.getFactory().done();
}
private static void doCheckCancelled(GenerationState state) {
if (state.getClassBuilderMode().generateBodies) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
}
}
public static void generatePackage(
@NotNull GenerationState state,
@NotNull FqName packageFqName,
@NotNull Collection<KtFile> jetFiles,
@NotNull CompilationErrorHandler errorHandler
) {
// We do not really generate package class, but use old package fqName to identify package in module-info.
//FqName packageClassFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
PackageCodegen codegen = state.getFactory().forPackage(packageFqName, jetFiles);
codegen.generate(errorHandler);
}
private static void generateMultifileClass(
@NotNull GenerationState state,
@NotNull FqName multifileClassFqName,
@NotNull Collection<KtFile> files,
@NotNull CompilationErrorHandler handler
) {
MultifileClassCodegen codegen = state.getFactory().forMultifileClass(multifileClassFqName, files);
codegen.generate(handler);
DefaultCodegenFactory.INSTANCE.generatePackage(state, packageFqName, jetFiles, errorHandler);
}
private KotlinCodegenFacade() {}
@@ -18,25 +18,28 @@ package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
object JvmBackendFacade {
fun compileCorrectFiles(state: GenerationState, errorHandler: CompilationErrorHandler) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
state.beforeCompile()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
doGenerateFiles(state.files, state, errorHandler)
}
fun doGenerateFiles(files: Collection<KtFile>, state: GenerationState, errorHandler: CompilationErrorHandler) {
// TODO multifile classes support
val psi2ir = Psi2IrTranslator()
val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext)
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files)
doGenerateFilesInternal(state, errorHandler, irModuleFragment, psi2irContext)
}
internal fun doGenerateFilesInternal(
state: GenerationState,
errorHandler: CompilationErrorHandler,
irModuleFragment: IrModuleFragment,
psi2irContext: GeneratorContext
) {
val jvmBackendContext = JvmBackendContext(
state, psi2irContext.sourceManager, psi2irContext.irBuiltIns, irModuleFragment, psi2irContext.symbolTable
)
@@ -23,8 +23,19 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
object JvmIrCodegenFactory : CodegenFactory {
override fun generateModule(state: GenerationState, files: Collection<KtFile?>, errorHandler: CompilationErrorHandler) {
assert(!files.any { it == null })
val psi2ir = Psi2IrTranslator()
val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext)
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files as Collection<KtFile>)
JvmBackendFacade.doGenerateFilesInternal(state, errorHandler, irModuleFragment, psi2irContext)
}
override fun createPackageCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry): PackageCodegen {
val impl = PackageCodegenImpl(state, files, fqName, registry)