Converting KotlinCompilerRunner.java to kotlin - phase 2 - converter + manual fixes

Original commit: 0047fb1272
This commit is contained in:
Ilya Chernikov
2015-09-23 14:56:41 +02:00
parent 1d3856b70e
commit 448551f3f3
2 changed files with 165 additions and 180 deletions
@@ -14,261 +14,247 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.compilerRunner; package org.jetbrains.kotlin.compilerRunner
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil
import com.intellij.util.Function; import com.intellij.util.Function
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil
import com.intellij.util.xmlb.XmlSerializerUtil; import com.intellij.util.xmlb.XmlSerializerUtil
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.ExitCode; import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments; import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.cli.common.messages.MessageCollector; import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil; import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.config.CompilerSettings; import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache; import org.jetbrains.kotlin.rmi.*
import org.jetbrains.kotlin.modules.TargetId; import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportCategory
import org.jetbrains.kotlin.rmi.*; import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportMessage
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportCategory; import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportingTargets
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportMessage; import org.jetbrains.kotlin.rmi.kotlinr.KotlinCompilerClient
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportingTargets; import org.jetbrains.kotlin.utils.*
import org.jetbrains.kotlin.rmi.kotlinr.KotlinCompilerClient;
import org.jetbrains.kotlin.utils.UtilsPackage;
import java.io.*; import java.io.*
import java.lang.reflect.Field; import java.lang.reflect.Field
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier
import java.util.ArrayList; import java.util.ArrayList
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.NO_LOCATION; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO;
public class KotlinCompilerRunner { public object KotlinCompilerRunner {
private static final String K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"; private val K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
private static final String K2JS_COMPILER = "org.jetbrains.kotlin.cli.js.K2JSCompiler"; private val K2JS_COMPILER = "org.jetbrains.kotlin.cli.js.K2JSCompiler"
private static final String INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString(); private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString()
public static void runK2JvmCompiler( public fun runK2JvmCompiler(
CommonCompilerArguments commonArguments, commonArguments: CommonCompilerArguments,
K2JVMCompilerArguments k2jvmArguments, k2jvmArguments: K2JVMCompilerArguments,
CompilerSettings compilerSettings, compilerSettings: CompilerSettings,
MessageCollector messageCollector, messageCollector: MessageCollector,
CompilerEnvironment environment, environment: CompilerEnvironment,
Map<TargetId, IncrementalCache> incrementalCaches, incrementalCaches: Map<TargetId, IncrementalCache>?,
File moduleFile, moduleFile: File,
OutputItemsCollector collector collector: OutputItemsCollector) {
) { val arguments = mergeBeans(commonArguments, k2jvmArguments)
K2JVMCompilerArguments arguments = mergeBeans(commonArguments, k2jvmArguments); setupK2JvmArguments(moduleFile, arguments)
setupK2JvmArguments(moduleFile, arguments);
runCompiler(K2JVM_COMPILER, arguments, compilerSettings.getAdditionalArguments(), messageCollector, collector, environment, runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment,
incrementalCaches); incrementalCaches)
} }
public static void runK2JsCompiler( public fun runK2JsCompiler(
@NotNull CommonCompilerArguments commonArguments, commonArguments: CommonCompilerArguments,
@NotNull K2JSCompilerArguments k2jsArguments, k2jsArguments: K2JSCompilerArguments,
@NotNull CompilerSettings compilerSettings, compilerSettings: CompilerSettings,
@NotNull MessageCollector messageCollector, messageCollector: MessageCollector,
@NotNull CompilerEnvironment environment, environment: CompilerEnvironment,
Map<TargetId, IncrementalCache> incrementalCaches, incrementalCaches: Map<TargetId, IncrementalCache>?,
@NotNull OutputItemsCollector collector, collector: OutputItemsCollector,
@NotNull Collection<File> sourceFiles, sourceFiles: Collection<File>,
@NotNull List<String> libraryFiles, libraryFiles: List<String>,
@NotNull File outputFile outputFile: File) {
) { val arguments = mergeBeans(commonArguments, k2jsArguments)
K2JSCompilerArguments arguments = mergeBeans(commonArguments, k2jsArguments); setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments)
setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments);
runCompiler(K2JS_COMPILER, arguments, compilerSettings.getAdditionalArguments(), messageCollector, collector, environment, runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment,
incrementalCaches); incrementalCaches)
} }
private static void ProcessCompilerOutput( private fun ProcessCompilerOutput(
MessageCollector messageCollector, messageCollector: MessageCollector,
OutputItemsCollector collector, collector: OutputItemsCollector,
ByteArrayOutputStream stream, stream: ByteArrayOutputStream,
String exitCode exitCode: String) {
) { val reader = BufferedReader(StringReader(stream.toString()))
BufferedReader reader = new BufferedReader(new StringReader(stream.toString())); CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector)
CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector);
if (INTERNAL_ERROR.equals(exitCode)) { if (INTERNAL_ERROR == exitCode) {
reportInternalCompilerError(messageCollector); reportInternalCompilerError(messageCollector)
} }
} }
private static void reportInternalCompilerError(MessageCollector messageCollector) { private fun reportInternalCompilerError(messageCollector: MessageCollector) {
messageCollector.report(ERROR, "Compiler terminated with internal error", NO_LOCATION); messageCollector.report(ERROR, "Compiler terminated with internal error", CompilerMessageLocation.NO_LOCATION)
} }
private static void runCompiler( private fun runCompiler(
String compilerClassName, compilerClassName: String,
CommonCompilerArguments arguments, arguments: CommonCompilerArguments,
String additionalArguments, additionalArguments: String,
MessageCollector messageCollector, messageCollector: MessageCollector,
OutputItemsCollector collector, collector: OutputItemsCollector,
CompilerEnvironment environment, environment: CompilerEnvironment,
Map<TargetId, IncrementalCache> incrementalCaches incrementalCaches: Map<TargetId, IncrementalCache>?) {
) {
try { try {
messageCollector.report(INFO, "Using kotlin-home = " + environment.getKotlinPaths().getHomePath(), NO_LOCATION); messageCollector.report(INFO, "Using kotlin-home = " + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION)
List<String> argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments); val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments)
argumentsList.addAll(StringUtil.split(additionalArguments, " ")); argumentsList.addAll(StringUtil.split(additionalArguments, " "))
String[] argsArray = ArrayUtil.toStringArray(argumentsList); val argsArray = ArrayUtil.toStringArray(argumentsList)
if (!tryCompileWithDaemon(messageCollector, collector, environment, incrementalCaches, argsArray)) { if (!tryCompileWithDaemon(messageCollector, collector, environment, incrementalCaches, argsArray)) {
// otherwise fallback to in-process // otherwise fallback to in-process
ByteArrayOutputStream stream = new ByteArrayOutputStream(); val stream = ByteArrayOutputStream()
PrintStream out = new PrintStream(stream); val out = PrintStream(stream)
Object rc = CompilerRunnerUtil.invokeExecMethod( compilerClassName, argsArray, environment, messageCollector, out); val rc = CompilerRunnerUtil.invokeExecMethod(compilerClassName, argsArray, environment, messageCollector, out)
// exec() returns an ExitCode object, class of which is loaded with a different class loader, // exec() returns an ExitCode object, class of which is loaded with a different class loader,
// so we take it's contents through reflection // so we take it's contents through reflection
ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc)); ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc))
} }
} }
catch (Throwable e) { catch (e: Throwable) {
MessageCollectorUtil.reportException(messageCollector, e); MessageCollectorUtil.reportException(messageCollector, e)
reportInternalCompilerError(messageCollector); reportInternalCompilerError(messageCollector)
} }
} }
private static boolean tryCompileWithDaemon( private fun tryCompileWithDaemon(
MessageCollector messageCollector, messageCollector: MessageCollector,
OutputItemsCollector collector, collector: OutputItemsCollector,
CompilerEnvironment environment, environment: CompilerEnvironment,
Map<TargetId, IncrementalCache> incrementalCaches, incrementalCaches: Map<TargetId, IncrementalCache>?,
String[] argsArray argsArray: Array<String>): Boolean {
) throws IOException { if (incrementalCaches != null && isDaemonEnabled()) {
if (incrementalCaches != null && RmiPackage.isDaemonEnabled()) { val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, messageCollector)
File libPath = CompilerRunnerUtil.getLibPath(environment.getKotlinPaths(), messageCollector);
// TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\
// the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler
CompilerId compilerId = CompilerId.makeCompilerId(new File(libPath, "kotlin-compiler.jar")); val compilerId = CompilerId.makeCompilerId(File(libPath, "kotlin-compiler.jar"))
DaemonOptions daemonOptions = RmiPackage.configureDaemonOptions(); val daemonOptions = configureDaemonOptions()
DaemonJVMOptions daemonJVMOptions = RmiPackage.configureDaemonJVMOptions(true); val daemonJVMOptions = configureDaemonJVMOptions(true)
ArrayList<DaemonReportMessage> daemonReportMessages = new ArrayList<DaemonReportMessage>(); val daemonReportMessages = ArrayList<DaemonReportMessage>()
CompileService daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, new DaemonReportingTargets(null, daemonReportMessages), true, true); val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true)
for (DaemonReportMessage msg: daemonReportMessages) { for (msg in daemonReportMessages) {
if (msg.getCategory() == DaemonReportCategory.EXCEPTION && daemon == null) { if (msg.category === DaemonReportCategory.EXCEPTION && daemon == null) {
messageCollector.report(CompilerMessageSeverity.INFO, messageCollector.report(CompilerMessageSeverity.INFO,
"Falling back to compilation without daemon due to error: " + msg.getMessage(), "Falling back to compilation without daemon due to error: " + msg.message,
CompilerMessageLocation.NO_LOCATION); CompilerMessageLocation.NO_LOCATION)
} }
else { else {
messageCollector.report(CompilerMessageSeverity.INFO, msg.getMessage(), CompilerMessageLocation.NO_LOCATION); messageCollector.report(CompilerMessageSeverity.INFO, msg.message, CompilerMessageLocation.NO_LOCATION)
} }
} }
if (daemon != null) { if (daemon != null) {
ByteArrayOutputStream compilerOut = new ByteArrayOutputStream(); val compilerOut = ByteArrayOutputStream()
ByteArrayOutputStream daemonOut = new ByteArrayOutputStream(); val daemonOut = ByteArrayOutputStream()
Integer res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, incrementalCaches, compilerOut, daemonOut); val res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, incrementalCaches, compilerOut, daemonOut)
ProcessCompilerOutput(messageCollector, collector, compilerOut, res.toString()); ProcessCompilerOutput(messageCollector, collector, compilerOut, res.toString())
BufferedReader reader = new BufferedReader(new StringReader(daemonOut.toString())); BufferedReader(StringReader(daemonOut.toString())).forEachLine {
String line = null; messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION)
while ((line = reader.readLine()) != null) {
messageCollector.report(CompilerMessageSeverity.INFO, line, CompilerMessageLocation.NO_LOCATION);
} }
return true; return true
} }
} }
return false; return false
} }
@NotNull private fun getReturnCodeFromObject(rc: Any?): String {
private static String getReturnCodeFromObject(@Nullable Object rc) throws Exception {
if (rc == null) { if (rc == null) {
return INTERNAL_ERROR; return INTERNAL_ERROR
} }
else if (ExitCode.class.getName().equals(rc.getClass().getName())) { else if (ExitCode::class.java.name == rc.javaClass.name) {
return rc.toString(); return rc.toString()
} }
else { else {
throw new IllegalStateException("Unexpected return: " + rc); throw IllegalStateException("Unexpected return: " + rc)
} }
} }
private static <T extends CommonCompilerArguments> T mergeBeans(CommonCompilerArguments from, T to) { private fun <T : CommonCompilerArguments> mergeBeans(from: CommonCompilerArguments, to: T): T {
// TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity // TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity
try { try {
T copy = XmlSerializerUtil.createCopy(to); val copy = XmlSerializerUtil.createCopy(to)
List<Field> fromFields = collectFieldsToCopy(from.getClass()); val fromFields = collectFieldsToCopy(from.javaClass)
for (Field fromField : fromFields) { for (fromField in fromFields) {
Field toField = copy.getClass().getField(fromField.getName()); val toField = copy.javaClass.getField(fromField.name)
toField.set(copy, fromField.get(from)); toField.set(copy, fromField.get(from))
} }
return copy; return copy
} }
catch (NoSuchFieldException e) { catch (e: NoSuchFieldException) {
throw UtilsPackage.rethrow(e); throw rethrow(e)
} }
catch (IllegalAccessException e) { catch (e: IllegalAccessException) {
throw UtilsPackage.rethrow(e); throw rethrow(e)
} }
} }
private static List<Field> collectFieldsToCopy(Class<?> clazz) { private fun collectFieldsToCopy(clazz: Class<*>): List<Field> {
List<Field> fromFields = new ArrayList<Field>(); val fromFields = ArrayList<Field>()
Class currentClass = clazz; var currentClass: Class<*>? = clazz
do { while (currentClass != null) {
for (Field field : currentClass.getDeclaredFields()) { for (field in currentClass.declaredFields) {
int modifiers = field.getModifiers(); val modifiers = field.modifiers
if (!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) { if (!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) {
fromFields.add(field); fromFields.add(field)
} }
} }
currentClass = currentClass.superclass
} }
while ((currentClass = currentClass.getSuperclass()) != null);
return fromFields; return fromFields
} }
private static void setupK2JvmArguments(File moduleFile, K2JVMCompilerArguments settings) { private fun setupK2JvmArguments(moduleFile: File, settings: K2JVMCompilerArguments) {
settings.module = moduleFile.getAbsolutePath(); settings.module = moduleFile.absolutePath
settings.noStdlib = true; settings.noStdlib = true
settings.noJdkAnnotations = true; settings.noJdkAnnotations = true
settings.noJdk = true; settings.noJdk = true
} }
private static void setupK2JsArguments( private fun setupK2JsArguments(
@NotNull File outputFile, outputFile: File,
@NotNull Collection<File> sourceFiles, sourceFiles: Collection<File>,
@NotNull List<String> libraryFiles, libraryFiles: List<String>,
@NotNull K2JSCompilerArguments settings settings: K2JSCompilerArguments) {
) { settings.noStdlib = true
settings.noStdlib = true; settings.freeArgs = ContainerUtil.map(sourceFiles, object : Function<File, String> {
settings.freeArgs = ContainerUtil.map(sourceFiles, new Function<File, String>() { override fun `fun`(file: File): String {
@Override return file.path
public String fun(File file) {
return file.getPath();
} }
}); })
settings.outputFile = outputFile.getPath(); settings.outputFile = outputFile.path
settings.metaInfo = true; settings.metaInfo = true
settings.libraryFiles = ArrayUtil.toStringArray(libraryFiles); settings.libraryFiles = ArrayUtil.toStringArray(libraryFiles)
} }
} }
@@ -47,8 +47,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.compilerRunner.CompilerEnvironment import org.jetbrains.kotlin.compilerRunner.CompilerEnvironment
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner.runK2JsCompiler import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner.runK2JvmCompiler
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.config.CompilerRunnerConstants import org.jetbrains.kotlin.config.CompilerRunnerConstants
import org.jetbrains.kotlin.config.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX import org.jetbrains.kotlin.config.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX
@@ -520,7 +519,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(project) val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(project)
val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(project) val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(project)
runK2JsCompiler(commonArguments, k2JsArguments, compilerSettings, messageCollector, environment, incrementalCaches, outputItemCollector, sourceFiles, libraryFiles, outputFile) KotlinCompilerRunner.runK2JsCompiler(commonArguments, k2JsArguments, compilerSettings, messageCollector, environment, incrementalCaches, outputItemCollector, sourceFiles, libraryFiles, outputFile)
return outputItemCollector return outputItemCollector
} }
@@ -587,7 +586,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
+ (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)") + (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)")
+ " in " + filesToCompile.keySet().map { it.getPresentableName() }.join()) + " in " + filesToCompile.keySet().map { it.getPresentableName() }.join())
runK2JvmCompiler(commonArguments, k2JvmArguments, compilerSettings, messageCollector, environment, incrementalCaches, moduleFile, outputItemCollector) KotlinCompilerRunner.runK2JvmCompiler(commonArguments, k2JvmArguments, compilerSettings, messageCollector, environment, incrementalCaches, moduleFile, outputItemCollector)
moduleFile.delete() moduleFile.delete()
return outputItemCollector return outputItemCollector