KotlinToJVMBytecodeCompiler: J2K

This commit is contained in:
Dmitry Jemerov
2016-01-13 17:48:30 +01:00
parent 0d88595baf
commit bccd64de19
3 changed files with 250 additions and 329 deletions
@@ -14,418 +14,343 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.cli.jvm.compiler; package org.jetbrains.kotlin.cli.jvm.compiler
import com.google.common.base.Function; import com.google.common.base.Joiner
import com.google.common.base.Joiner; import com.google.common.collect.Collections2
import com.google.common.collect.Collections2; import com.google.common.collect.Lists
import com.google.common.collect.Lists; import com.google.common.collect.Maps
import com.google.common.collect.Maps; import com.intellij.util.ArrayUtil
import com.intellij.util.ArrayUtil; import org.jetbrains.kotlin.analyzer.AnalysisResult
import kotlin.Unit; import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
import kotlin.jvm.functions.Function0; import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import kotlin.jvm.functions.Function1; import org.jetbrains.kotlin.cli.common.CompilerPluginContext
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.analyzer.AnalysisResult; import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics; import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.common.CompilerPlugin; import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.cli.common.CompilerPluginContext; import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport; import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.cli.common.messages.MessageCollector; import org.jetbrains.kotlin.config.addKotlinSourceRoots
import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler; import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.cli.jvm.config.JVMConfigurationKeys; import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.cli.jvm.config.ModuleNameKt; import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.codegen.*; import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.config.ContentRootsKt; import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.context.ModuleContext; import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.idea.MainFunctionDetector; import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager; import org.jetbrains.kotlin.utils.rethrow
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache; import java.io.File
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents; import java.lang.reflect.Constructor
import org.jetbrains.kotlin.modules.JavaRootPath; import java.lang.reflect.InvocationTargetException
import org.jetbrains.kotlin.modules.Module; import java.net.URL
import org.jetbrains.kotlin.modules.TargetId; import java.net.URLClassLoader
import org.jetbrains.kotlin.modules.TargetIdKt; import java.util.concurrent.TimeUnit
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.psi.KtScript;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM;
import org.jetbrains.kotlin.util.PerformanceCounter;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import org.jetbrains.kotlin.utils.KotlinPaths;
import java.io.File; object KotlinToJVMBytecodeCompiler {
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class KotlinToJVMBytecodeCompiler { private fun getAbsolutePaths(directory: File, module: Module): List<String> {
val result = Lists.newArrayList<String>()
private KotlinToJVMBytecodeCompiler() { for (sourceFile in module.getSourceFiles()) {
} var source = File(sourceFile)
if (!source.isAbsolute) {
@NotNull source = File(directory, sourceFile)
private static List<String> getAbsolutePaths(@NotNull File directory, @NotNull Module module) {
List<String> result = Lists.newArrayList();
for (String sourceFile : module.getSourceFiles()) {
File source = new File(sourceFile);
if (!source.isAbsolute()) {
source = new File(directory, sourceFile);
} }
result.add(source.getAbsolutePath()); result.add(source.absolutePath)
} }
return result; return result
} }
private static void writeOutput( private fun writeOutput(
@NotNull CompilerConfiguration configuration, configuration: CompilerConfiguration,
@NotNull ClassFileFactory outputFiles, outputFiles: ClassFileFactory,
@Nullable File outputDir, outputDir: File?,
@Nullable File jarPath, jarPath: File?,
boolean jarRuntime, jarRuntime: Boolean,
@Nullable FqName mainClass mainClass: FqName?) {
) {
if (jarPath != null) { if (jarPath != null) {
CompileEnvironmentUtil.writeToJar(jarPath, jarRuntime, mainClass, outputFiles); CompileEnvironmentUtil.writeToJar(jarPath, jarRuntime, mainClass, outputFiles)
} }
else { else {
MessageCollector messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE); val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
OutputUtilsKt.writeAll(outputFiles, outputDir == null ? new File(".") : outputDir, messageCollector); outputFiles.writeAll(outputDir ?: File("."), messageCollector)
} }
} }
public static boolean compileModules( fun compileModules(
@NotNull KotlinCoreEnvironment environment, environment: KotlinCoreEnvironment,
@NotNull CompilerConfiguration configuration, configuration: CompilerConfiguration,
@NotNull List<Module> chunk, chunk: List<Module>,
@NotNull File directory, directory: File,
@Nullable File jarPath, jarPath: File?,
@NotNull List<String> friendPaths, friendPaths: List<String>,
boolean jarRuntime jarRuntime: Boolean): Boolean {
) { val outputFiles = Maps.newHashMap<Module, ClassFileFactory>()
Map<Module, ClassFileFactory> outputFiles = Maps.newHashMap();
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
ModuleVisibilityManager moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.getProject()); val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
for (Module module: chunk) { for (module in chunk) {
moduleVisibilityManager.addModule(module); moduleVisibilityManager.addModule(module)
} }
for (String path : friendPaths) { for (path in friendPaths) {
moduleVisibilityManager.addFriendPath(path); moduleVisibilityManager.addFriendPath(path)
} }
String targetDescription = "in targets [" + Joiner.on(", ").join(Collections2.transform(chunk, new Function<Module, String>() { val targetDescription = "in targets [" + Joiner.on(", ").join(Collections2.transform(chunk) { input -> if (input != null) input.getModuleName() + "-" + input.getModuleType() else "<null>" }) + "] "
@Override val result = analyze(environment, targetDescription) ?: return false
public String apply(@Nullable Module input) {
return input != null ? input.getModuleName() + "-" + input.getModuleType() : "<null>"; ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
}
})) + "] "; result.throwIfError()
AnalysisResult result = analyze(environment, targetDescription);
if (result == null) { for (module in chunk) {
return false; ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val jetFiles = CompileEnvironmentUtil.getKtFiles(
environment.project, getAbsolutePaths(directory, module)) { s -> throw IllegalStateException("Should have been checked before: " + s) }
val moduleOutputDirectory = File(module.getOutputDirectory())
val generationState = generate(environment, result, jetFiles, module, moduleOutputDirectory,
module.getModuleName())
outputFiles.put(module, generationState.factory)
} }
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); for (module in chunk) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
result.throwIfError(); writeOutput(configuration, outputFiles[module]!!, File(module.getOutputDirectory()), jarPath, jarRuntime, null)
for (Module module : chunk) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
List<KtFile> jetFiles = CompileEnvironmentUtil.getKtFiles(
environment.getProject(), getAbsolutePaths(directory, module), new Function1<String, Unit>() {
@Override
public Unit invoke(String s) {
throw new IllegalStateException("Should have been checked before: " + s);
}
}
);
File moduleOutputDirectory = new File(module.getOutputDirectory());
GenerationState generationState =
generate(environment, result, jetFiles, module, moduleOutputDirectory,
module.getModuleName());
outputFiles.put(module, generationState.getFactory());
} }
return true
for (Module module : chunk) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
writeOutput(configuration, outputFiles.get(module), new File(module.getOutputDirectory()), jarPath, jarRuntime, null);
}
return true;
} }
@NotNull fun createCompilerConfiguration(
public static CompilerConfiguration createCompilerConfiguration( base: CompilerConfiguration,
@NotNull CompilerConfiguration base, chunk: List<Module>,
@NotNull List<Module> chunk, directory: File): CompilerConfiguration {
@NotNull File directory val configuration = base.copy()
) {
CompilerConfiguration configuration = base.copy();
for (Module module : chunk) { for (module in chunk) {
ContentRootsKt.addKotlinSourceRoots(configuration, getAbsolutePaths(directory, module)); configuration.addKotlinSourceRoots(getAbsolutePaths(directory, module))
} }
for (Module module : chunk) { for (module in chunk) {
for (JavaRootPath javaRootPath : module.getJavaSourceRoots()) { for (javaRootPath in module.getJavaSourceRoots()) {
JvmContentRootsKt.addJavaSourceRoot(configuration, new File(javaRootPath.getPath()), javaRootPath.getPackagePrefix()); configuration.addJavaSourceRoot(File(javaRootPath.path), javaRootPath.packagePrefix)
} }
} }
for (Module module : chunk) { for (module in chunk) {
for (String classpathRoot : module.getClasspathRoots()) { for (classpathRoot in module.getClasspathRoots()) {
JvmContentRootsKt.addJvmClasspathRoot(configuration, new File(classpathRoot)); configuration.addJvmClasspathRoot(File(classpathRoot))
} }
} }
for (Module module : chunk) { for (module in chunk) {
configuration.add(JVMConfigurationKeys.MODULES, module); configuration.add(JVMConfigurationKeys.MODULES, module)
} }
return configuration; return configuration
} }
@Nullable private fun findMainClass(generationState: GenerationState, files: List<KtFile>): FqName? {
private static FqName findMainClass(@NotNull GenerationState generationState, @NotNull List<KtFile> files) { val mainFunctionDetector = MainFunctionDetector(generationState.bindingContext)
MainFunctionDetector mainFunctionDetector = new MainFunctionDetector(generationState.getBindingContext()); var mainClass: FqName? = null
FqName mainClass = null; for (file in files) {
for (KtFile file : files) { if (mainFunctionDetector.hasMain(file.declarations)) {
if (mainFunctionDetector.hasMain(file.getDeclarations())) {
if (mainClass != null) { if (mainClass != null) {
// more than one main // more than one main
return null; return null
} }
FqName fqName = file.getPackageFqName(); val fqName = file.packageFqName
mainClass = JvmFileClassUtil.getFileClassInfoNoResolve(file).getFacadeClassFqName(); mainClass = JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName
} }
} }
return mainClass; return mainClass
} }
public static boolean compileBunchOfSources( fun compileBunchOfSources(
@NotNull KotlinCoreEnvironment environment, environment: KotlinCoreEnvironment,
@Nullable File jar, jar: File?,
@Nullable File outputDir, outputDir: File?,
@NotNull List<String> friendPaths, friendPaths: List<String>,
boolean includeRuntime includeRuntime: Boolean): Boolean {
) {
ModuleVisibilityManager moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.getProject()); val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
for (String path : friendPaths) { for (path in friendPaths) {
moduleVisibilityManager.addFriendPath(path); moduleVisibilityManager.addFriendPath(path)
} }
GenerationState generationState = analyzeAndGenerate(environment); val generationState = analyzeAndGenerate(environment) ?: return false
if (generationState == null) {
return false;
}
FqName mainClass = findMainClass(generationState, environment.getSourceFiles()); val mainClass = findMainClass(generationState, environment.getSourceFiles())
try { try {
writeOutput(environment.getConfiguration(), generationState.getFactory(), outputDir, jar, includeRuntime, mainClass); writeOutput(environment.configuration, generationState.factory, outputDir, jar, includeRuntime, mainClass)
return true; return true
} }
finally { finally {
generationState.destroy(); generationState.destroy()
} }
} }
public static void compileAndExecuteScript( fun compileAndExecuteScript(
@NotNull CompilerConfiguration configuration, configuration: CompilerConfiguration,
@NotNull KotlinPaths paths, paths: KotlinPaths,
@NotNull KotlinCoreEnvironment environment, environment: KotlinCoreEnvironment,
@NotNull List<String> scriptArgs scriptArgs: List<String>) {
) { val scriptClass = compileScript(configuration, paths, environment) ?: return
Class<?> scriptClass = compileScript(configuration, paths, environment); val scriptConstructor = getScriptConstructor(scriptClass)
if (scriptClass == null) return;
Constructor<?> scriptConstructor = getScriptConstructor(scriptClass);
try { try {
scriptConstructor.newInstance(new Object[] {ArrayUtil.toStringArray(scriptArgs)}); scriptConstructor.newInstance(*arrayOf<Any>(ArrayUtil.toStringArray(scriptArgs)))
} }
catch (Throwable e) { catch (e: Throwable) {
reportExceptionFromScript(e); reportExceptionFromScript(e)
} }
} }
private static void reportExceptionFromScript(@NotNull Throwable exception) { private fun reportExceptionFromScript(exception: Throwable) {
// expecting InvocationTargetException from constructor invocation with cause that describes the actual cause // expecting InvocationTargetException from constructor invocation with cause that describes the actual cause
PrintStream stream = System.err; val stream = System.err
Throwable cause = exception.getCause(); val cause = exception.cause
if (!(exception instanceof InvocationTargetException) || cause == null) { if (exception !is InvocationTargetException || cause == null) {
exception.printStackTrace(stream); exception.printStackTrace(stream)
return; return
} }
stream.println(cause); stream.println(cause)
StackTraceElement[] fullTrace = cause.getStackTrace(); val fullTrace = cause.getStackTrace()
int relevantEntries = fullTrace.length - exception.getStackTrace().length; val relevantEntries = fullTrace.size - exception.getStackTrace().size
for (int i = 0; i < relevantEntries; i++) { for (i in 0..relevantEntries - 1) {
stream.println("\tat " + fullTrace[i]); stream.println("\tat " + fullTrace[i])
} }
} }
@NotNull private fun getScriptConstructor(scriptClass: Class<*>): Constructor<*> {
private static Constructor<?> getScriptConstructor(Class<?> scriptClass) {
try { try {
return scriptClass.getConstructor(String[].class); return scriptClass.getConstructor(Array<String>::class.java)
} }
catch (NoSuchMethodException e) { catch (e: NoSuchMethodException) {
throw ExceptionUtilsKt.rethrow(e); throw rethrow(e)
} }
} }
@Nullable fun compileScript(
public static Class<?> compileScript( configuration: CompilerConfiguration,
@NotNull CompilerConfiguration configuration, paths: KotlinPaths,
@NotNull KotlinPaths paths, environment: KotlinCoreEnvironment): Class<*>? {
@NotNull KotlinCoreEnvironment environment val state = analyzeAndGenerate(environment) ?: return null
) {
GenerationState state = analyzeAndGenerate(environment);
if (state == null) {
return null;
}
GeneratedClassLoader classLoader; val classLoader: GeneratedClassLoader
try { try {
List<URL> classPaths = Lists.newArrayList(paths.getRuntimePath().toURI().toURL()); val classPaths = Lists.newArrayList(paths.runtimePath.toURI().toURL())
for (File file : JvmContentRootsKt.getJvmClasspathRoots(configuration)) { for (file in configuration.jvmClasspathRoots) {
classPaths.add(file.toURI().toURL()); classPaths.add(file.toURI().toURL())
} }
//noinspection UnnecessaryFullyQualifiedName //noinspection UnnecessaryFullyQualifiedName
classLoader = new GeneratedClassLoader(state.getFactory(), classLoader = GeneratedClassLoader(state.factory,
new URLClassLoader(classPaths.toArray(new URL[classPaths.size()]), null) URLClassLoader(classPaths.toArray<URL>(arrayOfNulls<URL>(classPaths.size)), null))
);
KtScript script = environment.getSourceFiles().get(0).getScript(); val script = environment.getSourceFiles()[0].script
assert script != null : "Script must be parsed"; assert(script != null) { "Script must be parsed" }
FqName nameForScript = script.getFqName(); val nameForScript = script!!.fqName
return classLoader.loadClass(nameForScript.asString()); return classLoader.loadClass(nameForScript.asString())
} }
catch (Exception e) { catch (e: Exception) {
throw new RuntimeException("Failed to evaluate script: " + e, e); throw RuntimeException("Failed to evaluate script: " + e, e)
} }
} }
@Nullable fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? {
public static GenerationState analyzeAndGenerate(@NotNull KotlinCoreEnvironment environment) { val result = analyze(environment, null) ?: return null
AnalysisResult result = analyze(environment, null);
if (result == null) { if (!result.shouldGenerateCode) return null
return null;
}
if (!result.getShouldGenerateCode()) return null; result.throwIfError()
result.throwIfError(); return generate(environment, result, environment.getSourceFiles(), null, null, null)
return generate(environment, result, environment.getSourceFiles(), null, null, null);
} }
@Nullable private fun analyze(environment: KotlinCoreEnvironment, targetDescription: String?): AnalysisResult? {
private static AnalysisResult analyze(@NotNull final KotlinCoreEnvironment environment, @Nullable String targetDescription) { val collector = environment.configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)!!
MessageCollector collector = environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY);
assert collector != null;
long analysisStart = PerformanceCounter.Companion.currentTime(); val analysisStart = PerformanceCounter.currentTime()
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(collector); val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
analyzerWithCompilerReport.analyzeAndReport( analyzerWithCompilerReport.analyzeAndReport(
environment.getSourceFiles(), new Function0<AnalysisResult>() { environment.getSourceFiles(), {
@NotNull val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
@Override val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project,
public AnalysisResult invoke() { environment.getModuleName())
BindingTrace sharedTrace = new CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace();
ModuleContext moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.getProject(),
ModuleNameKt
.getModuleName(environment));
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext( TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
moduleContext, moduleContext,
environment.getSourceFiles(), environment.getSourceFiles(),
sharedTrace, sharedTrace,
environment.getConfiguration().get(JVMConfigurationKeys.MODULES), environment.configuration.get(JVMConfigurationKeys.MODULES),
environment.getConfiguration().get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS), environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS),
new JvmPackagePartProvider(environment) JvmPackagePartProvider(environment))
); })
} val analysisNanos = PerformanceCounter.currentTime() - analysisStart
} val message = "ANALYZE: " + environment.getSourceFiles().size + " files (" +
); environment.sourceLinesOfCode + " lines) " +
long analysisNanos = PerformanceCounter.Companion.currentTime() - analysisStart; (targetDescription ?: "") +
String message = "ANALYZE: " + environment.getSourceFiles().size() + " files (" + "in " + TimeUnit.NANOSECONDS.toMillis(analysisNanos) + " ms"
environment.getSourceLinesOfCode() + " lines) " + K2JVMCompiler.reportPerf(environment.configuration, message)
(targetDescription != null ? targetDescription : "") +
"in " + TimeUnit.NANOSECONDS.toMillis(analysisNanos) + " ms";
K2JVMCompiler.Companion.reportPerf(environment.getConfiguration(), message);
AnalysisResult result = analyzerWithCompilerReport.getAnalysisResult(); val result = analyzerWithCompilerReport.getAnalysisResult()
assert result != null : "AnalysisResult should be non-null, compiling: " + environment.getSourceFiles(); assert(result != null) { "AnalysisResult should be non-null, compiling: " + environment.getSourceFiles() }
CompilerPluginContext context = new CompilerPluginContext(environment.getProject(), result.getBindingContext(), val context = CompilerPluginContext(environment.project, result!!.bindingContext,
environment.getSourceFiles()); environment.getSourceFiles())
for (CompilerPlugin plugin : environment.getConfiguration().getList(CLIConfigurationKeys.COMPILER_PLUGINS)) { for (plugin in environment.configuration.getList(CLIConfigurationKeys.COMPILER_PLUGINS)) {
plugin.processFiles(context); plugin.processFiles(context)
} }
return analyzerWithCompilerReport.hasErrors() ? null : result; return if (analyzerWithCompilerReport.hasErrors()) null else result
} }
@NotNull private fun generate(
private static GenerationState generate( environment: KotlinCoreEnvironment,
@NotNull KotlinCoreEnvironment environment, result: AnalysisResult,
@NotNull AnalysisResult result, sourceFiles: List<KtFile>,
@NotNull List<KtFile> sourceFiles, module: Module?,
@Nullable Module module, outputDirectory: File?,
File outputDirectory, moduleName: String?): GenerationState {
String moduleName val configuration = environment.configuration
) { val incrementalCompilationComponents = configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS)
CompilerConfiguration configuration = environment.getConfiguration();
IncrementalCompilationComponents incrementalCompilationComponents = configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS);
Collection<FqName> packagesWithObsoleteParts; val packagesWithObsoleteParts = hashSetOf<FqName>()
List<FqName> obsoleteMultifileClasses; val obsoleteMultifileClasses = arrayListOf<FqName>()
TargetId targetId = null; var targetId: TargetId? = null
if (module == null || incrementalCompilationComponents == null) { if (module != null && incrementalCompilationComponents != null) {
packagesWithObsoleteParts = Collections.emptySet(); targetId = TargetId(module)
obsoleteMultifileClasses = Collections.emptyList(); val incrementalCache = incrementalCompilationComponents.getIncrementalCache(targetId)
}
else {
targetId = TargetIdKt.TargetId(module);
IncrementalCache incrementalCache = incrementalCompilationComponents.getIncrementalCache(targetId);
packagesWithObsoleteParts = new HashSet<FqName>(); for (internalName in incrementalCache.getObsoletePackageParts()) {
for (String internalName : incrementalCache.getObsoletePackageParts()) { packagesWithObsoleteParts.add(JvmClassName.byInternalName(internalName).packageFqName)
packagesWithObsoleteParts.add(JvmClassName.byInternalName(internalName).getPackageFqName());
} }
obsoleteMultifileClasses = new ArrayList<FqName>(); for (obsoleteFacadeInternalName in incrementalCache.getObsoleteMultifileClasses()) {
for (String obsoleteFacadeInternalName : incrementalCache.getObsoleteMultifileClasses()) { obsoleteMultifileClasses.add(JvmClassName.byInternalName(obsoleteFacadeInternalName).fqNameForClassNameWithoutDollars)
obsoleteMultifileClasses.add(JvmClassName.byInternalName(obsoleteFacadeInternalName).getFqNameForClassNameWithoutDollars());
} }
} }
GenerationState generationState = new GenerationState( val generationState = GenerationState(
environment.getProject(), environment.project,
ClassBuilderFactories.BINARIES, ClassBuilderFactories.BINARIES,
result.getModuleDescriptor(), result.moduleDescriptor,
result.getBindingContext(), result.bindingContext,
sourceFiles, sourceFiles,
configuration.get(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, false), configuration.get(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, false),
configuration.get(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, false), configuration.get(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, false),
@@ -439,29 +364,26 @@ public class KotlinToJVMBytecodeCompiler {
moduleName, moduleName,
outputDirectory, outputDirectory,
incrementalCompilationComponents, incrementalCompilationComponents,
configuration.get(JVMConfigurationKeys.MULTIFILE_FACADES_OPEN, false) configuration.get(JVMConfigurationKeys.MULTIFILE_FACADES_OPEN, false))
); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
long generationStart = PerformanceCounter.Companion.currentTime(); val generationStart = PerformanceCounter.currentTime()
KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION); KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION)
long generationNanos = PerformanceCounter.Companion.currentTime() - generationStart; val generationNanos = PerformanceCounter.currentTime() - generationStart
String desc = module != null ? "target " + module.getModuleName() + "-" + module.getModuleType() + " " : ""; val desc = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else ""
String message = "GENERATE: " + sourceFiles.size() + " files (" + val message = "GENERATE: " + sourceFiles.size + " files (" +
environment.countLinesOfCode(sourceFiles) + " lines) " + desc + "in " + TimeUnit.NANOSECONDS.toMillis(generationNanos) + " ms"; environment.countLinesOfCode(sourceFiles) + " lines) " + desc + "in " + TimeUnit.NANOSECONDS.toMillis(generationNanos) + " ms"
K2JVMCompiler.Companion.reportPerf(environment.getConfiguration(), message); K2JVMCompiler.reportPerf(environment.configuration, message)
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
AnalyzerWithCompilerReport.reportDiagnostics( AnalyzerWithCompilerReport.reportDiagnostics(
new FilteredJvmDiagnostics( FilteredJvmDiagnostics(
generationState.getCollectedExtraJvmDiagnostics(), generationState.collectedExtraJvmDiagnostics,
result.getBindingContext().getDiagnostics() result.bindingContext.diagnostics),
), environment.configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)!!)
environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
); return generationState
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
return generationState;
} }
} }
@@ -61,7 +61,7 @@ public class StdlibTest extends KotlinTestWithEnvironment {
} }
public void testStdlib() throws ClassNotFoundException { public void testStdlib() throws ClassNotFoundException {
GenerationState state = KotlinToJVMBytecodeCompiler.analyzeAndGenerate(getEnvironment()); GenerationState state = KotlinToJVMBytecodeCompiler.INSTANCE.analyzeAndGenerate(getEnvironment());
if (state == null) { if (state == null) {
fail("There were compilation errors"); fail("There were compilation errors");
} }
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.config.ContentRootsKt;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform; import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
import org.jetbrains.kotlin.script.KotlinScriptDefinition; import org.jetbrains.kotlin.script.KotlinScriptDefinition;
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider;
import org.jetbrains.kotlin.script.ScriptParameter; import org.jetbrains.kotlin.script.ScriptParameter;
import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.test.KotlinTestUtils; import org.jetbrains.kotlin.test.KotlinTestUtils;
@@ -87,7 +86,7 @@ public class ScriptTest {
KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
try { try {
return KotlinToJVMBytecodeCompiler.compileScript(configuration, paths, environment); return KotlinToJVMBytecodeCompiler.INSTANCE.compileScript(configuration, paths, environment);
} }
catch (CompilationException e) { catch (CompilationException e) {
messageCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(e), messageCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(e),