Convert CliCompiler class to Kotlin

This commit is contained in:
Ilya Chernikov
2019-01-08 16:25:35 +01:00
parent 025d2d1b66
commit d5d60cbc6b
4 changed files with 169 additions and 192 deletions
@@ -14,244 +14,224 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.common;
package org.jetbrains.kotlin.cli.common
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import kotlin.collections.SetsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector;
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil;
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer;
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
import org.jetbrains.kotlin.config.CommonConfigurationKeysKt;
import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.Services;
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion;
import org.jetbrains.kotlin.progress.CompilationCanceledException;
import org.jetbrains.kotlin.progress.CompilationCanceledStatus;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.utils.KotlinPaths;
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir;
import org.jetbrains.kotlin.utils.PathUtil;
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import kotlin.collections.*
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.progress.CompilationCanceledException
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File;
import java.io.PrintStream;
import java.io.File
import java.io.PrintStream
import static org.jetbrains.kotlin.cli.common.CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY;
import static org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR;
import static org.jetbrains.kotlin.cli.common.ExitCode.INTERNAL_ERROR;
import static org.jetbrains.kotlin.cli.common.environment.UtilKt.setIdeaIoUseFallback;
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*;
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY
import org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR
import org.jetbrains.kotlin.cli.common.ExitCode.INTERNAL_ERROR
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLITool<A> {
abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
public static String KOTLIN_HOME_PROPERTY = "kotlin.home";
protected abstract val performanceManager: CommonCompilerPerformanceManager
// Used in CompilerRunnerUtil#invokeExecMethod, in Eclipse plugin (KotlinCLICompiler) and in kotlin-gradle-plugin (GradleCompilerRunner)
@NotNull
public ExitCode execAndOutputXml(@NotNull PrintStream errStream, @NotNull Services services, @NotNull String... args) {
return exec(errStream, services, MessageRenderer.XML, args);
fun execAndOutputXml(errStream: PrintStream, services: Services, vararg args: String): ExitCode {
return exec(errStream, services, MessageRenderer.XML, args)
}
// Used via reflection in KotlinCompilerBaseTask
@SuppressWarnings("UnusedDeclaration")
@NotNull
public ExitCode execFullPathsInMessages(@NotNull PrintStream errStream, @NotNull String[] args) {
return exec(errStream, Services.EMPTY, MessageRenderer.PLAIN_FULL_PATHS, args);
fun execFullPathsInMessages(errStream: PrintStream, args: Array<String>): ExitCode {
return exec(errStream, Services.EMPTY, MessageRenderer.PLAIN_FULL_PATHS, args)
}
@NotNull
@Override
public ExitCode execImpl(@NotNull MessageCollector messageCollector, @NotNull Services services, @NotNull A arguments) {
CommonCompilerPerformanceManager performanceManager = getPerformanceManager();
if (arguments.getReportPerf() || arguments.getDumpPerf() != null) {
performanceManager.enableCollectingPerformanceStatistics();
public override fun execImpl(messageCollector: MessageCollector, services: Services, arguments: A): ExitCode {
val performanceManager = performanceManager
if (arguments.reportPerf || arguments.dumpPerf != null) {
performanceManager.enableCollectingPerformanceStatistics()
}
GroupingMessageCollector groupingCollector = new GroupingMessageCollector(messageCollector, arguments.getAllWarningsAsErrors());
val groupingCollector = GroupingMessageCollector(messageCollector, arguments.allWarningsAsErrors)
CompilerConfiguration configuration = new CompilerConfiguration();
configuration.put(MESSAGE_COLLECTOR_KEY, groupingCollector);
configuration.put(CLIConfigurationKeys.PERF_MANAGER, performanceManager);
val configuration = CompilerConfiguration()
configuration.put(MESSAGE_COLLECTOR_KEY, groupingCollector)
configuration.put(CLIConfigurationKeys.PERF_MANAGER, performanceManager)
try {
setupCommonArguments(configuration, arguments);
setupPlatformSpecificArgumentsAndServices(configuration, arguments, services);
KotlinPaths paths = computeKotlinPaths(groupingCollector, arguments);
setupCommonArguments(configuration, arguments)
setupPlatformSpecificArgumentsAndServices(configuration, arguments, services)
val paths = computeKotlinPaths(groupingCollector, arguments)
if (groupingCollector.hasErrors()) {
return ExitCode.COMPILATION_ERROR;
return ExitCode.COMPILATION_ERROR
}
CompilationCanceledStatus canceledStatus = services.get(CompilationCanceledStatus.class);
ProgressIndicatorAndCompilationCanceledStatus.setCompilationCanceledStatus(canceledStatus);
val canceledStatus = services[CompilationCanceledStatus::class.java]
ProgressIndicatorAndCompilationCanceledStatus.setCompilationCanceledStatus(canceledStatus)
Disposable rootDisposable = Disposer.newDisposable();
val rootDisposable = Disposer.newDisposable()
try {
setIdeaIoUseFallback();
ExitCode code = doExecute(arguments, configuration, rootDisposable, paths);
setIdeaIoUseFallback()
val code = doExecute(arguments, configuration, rootDisposable, paths)
performanceManager.notifyCompilationFinished();
if (arguments.getReportPerf()) {
performanceManager.getMeasurementResults().forEach(
it -> configuration.get(MESSAGE_COLLECTOR_KEY).report(INFO, "PERF: " + it.render(), null)
);
performanceManager.notifyCompilationFinished()
if (arguments.reportPerf) {
performanceManager.getMeasurementResults()
.forEach { it -> configuration.get(MESSAGE_COLLECTOR_KEY)!!.report(INFO, "PERF: " + it.render(), null) }
}
if (arguments.getDumpPerf() != null) {
performanceManager.dumpPerformanceReport(new File(arguments.getDumpPerf()));
if (arguments.dumpPerf != null) {
performanceManager.dumpPerformanceReport(File(arguments.dumpPerf!!))
}
return groupingCollector.hasErrors() ? COMPILATION_ERROR : code;
}
catch (CompilationCanceledException e) {
messageCollector.report(INFO, "Compilation was canceled", null);
return ExitCode.OK;
}
catch (RuntimeException e) {
Throwable cause = e.getCause();
if (cause instanceof CompilationCanceledException) {
messageCollector.report(INFO, "Compilation was canceled", null);
return ExitCode.OK;
}
else {
throw e;
return if (groupingCollector.hasErrors()) COMPILATION_ERROR else code
} catch (e: CompilationCanceledException) {
messageCollector.report(INFO, "Compilation was canceled", null)
return ExitCode.OK
} catch (e: RuntimeException) {
val cause = e.cause
if (cause is CompilationCanceledException) {
messageCollector.report(INFO, "Compilation was canceled", null)
return ExitCode.OK
} else {
throw e
}
} finally {
Disposer.dispose(rootDisposable)
}
finally {
Disposer.dispose(rootDisposable);
}
}
catch (AnalysisResult.CompilationErrorException e) {
return COMPILATION_ERROR;
}
catch (Throwable t) {
MessageCollectorUtil.reportException(groupingCollector, t);
return INTERNAL_ERROR;
}
finally {
groupingCollector.flush();
} catch (e: AnalysisResult.CompilationErrorException) {
return COMPILATION_ERROR
} catch (t: Throwable) {
MessageCollectorUtil.reportException(groupingCollector, t)
return INTERNAL_ERROR
} finally {
groupingCollector.flush()
}
}
private void setupCommonArguments(@NotNull CompilerConfiguration configuration, @NotNull A arguments) {
if (arguments.getNoInline()) {
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, true);
private fun setupCommonArguments(configuration: CompilerConfiguration, arguments: A) {
if (arguments.noInline) {
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, true)
}
if (arguments.getIntellijPluginRoot()!= null) {
configuration.put(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, arguments.getIntellijPluginRoot());
if (arguments.intellijPluginRoot != null) {
configuration.put(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, arguments.intellijPluginRoot!!)
}
if (arguments.getReportOutputFiles()) {
configuration.put(CommonConfigurationKeys.REPORT_OUTPUT_FILES, true);
if (arguments.reportOutputFiles) {
configuration.put(CommonConfigurationKeys.REPORT_OUTPUT_FILES, true)
}
String metadataVersionString = arguments.getMetadataVersion();
val metadataVersionString = arguments.metadataVersion
if (metadataVersionString != null) {
int[] versionArray = BinaryVersion.parseVersionArray(metadataVersionString);
val versionArray = BinaryVersion.parseVersionArray(metadataVersionString)
if (versionArray == null) {
configuration.getNotNull(MESSAGE_COLLECTOR_KEY).report(ERROR, "Invalid metadata version: " + metadataVersionString, null);
}
else {
configuration.put(CommonConfigurationKeys.METADATA_VERSION, createMetadataVersion(versionArray));
configuration.getNotNull(MESSAGE_COLLECTOR_KEY).report(ERROR, "Invalid metadata version: $metadataVersionString", null)
} else {
configuration.put(CommonConfigurationKeys.METADATA_VERSION, createMetadataVersion(versionArray))
}
}
setupLanguageVersionSettings(configuration, arguments);
setupLanguageVersionSettings(configuration, arguments)
configuration.put(CommonConfigurationKeys.LIST_PHASES, arguments.getListPhases());
if (arguments.getDisablePhases() != null) {
configuration.put(CommonConfigurationKeys.DISABLED_PHASES, SetsKt.setOf(arguments.getDisablePhases()));
configuration.put(CommonConfigurationKeys.LIST_PHASES, arguments.listPhases)
if (arguments.disablePhases != null) {
configuration.put(CommonConfigurationKeys.DISABLED_PHASES, setOf(*arguments.disablePhases!!))
}
if (arguments.getVerbosePhases() != null) {
configuration.put(CommonConfigurationKeys.VERBOSE_PHASES, SetsKt.setOf(arguments.getVerbosePhases()));
if (arguments.verbosePhases != null) {
configuration.put(CommonConfigurationKeys.VERBOSE_PHASES, setOf(*arguments.verbosePhases!!))
}
if (arguments.getPhasesToDumpBefore() != null) {
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_BEFORE, SetsKt.setOf(arguments.getPhasesToDumpBefore()));
if (arguments.phasesToDumpBefore != null) {
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_BEFORE, setOf(*arguments.phasesToDumpBefore!!))
}
if (arguments.getPhasesToDumpAfter() != null) {
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_AFTER, SetsKt.setOf(arguments.getPhasesToDumpAfter()));
if (arguments.phasesToDumpAfter != null) {
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_AFTER, setOf(*arguments.phasesToDumpAfter!!))
}
if (arguments.getPhasesToDump() != null) {
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE, SetsKt.setOf(arguments.getPhasesToDump()));
if (arguments.phasesToDump != null) {
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE, setOf(*arguments.phasesToDump!!))
}
configuration.put(CommonConfigurationKeys.PROFILE_PHASES, arguments.getProfilePhases());
configuration.put(CommonConfigurationKeys.PROFILE_PHASES, arguments.profilePhases)
}
@NotNull
protected abstract BinaryVersion createMetadataVersion(@NotNull int[] versionArray);
protected abstract fun createMetadataVersion(versionArray: IntArray): BinaryVersion
private void setupLanguageVersionSettings(@NotNull CompilerConfiguration configuration, @NotNull A arguments) {
CommonConfigurationKeysKt.setLanguageVersionSettings(
configuration,
arguments.configureLanguageVersionSettings(configuration.getNotNull(MESSAGE_COLLECTOR_KEY))
);
private fun setupLanguageVersionSettings(configuration: CompilerConfiguration, arguments: A) {
configuration.languageVersionSettings = arguments.configureLanguageVersionSettings(configuration.getNotNull(MESSAGE_COLLECTOR_KEY))
}
@Nullable
private static KotlinPaths computeKotlinPaths(@NotNull MessageCollector messageCollector, @NotNull CommonCompilerArguments arguments) {
KotlinPaths paths;
String kotlinHomeProperty = System.getProperty(KOTLIN_HOME_PROPERTY);
File kotlinHome =
arguments.getKotlinHome() != null ? new File(arguments.getKotlinHome()) :
kotlinHomeProperty != null ? new File(kotlinHomeProperty)
: null;
if (kotlinHome != null) {
if (kotlinHome.isDirectory()) {
paths = new KotlinPathsFromHomeDir(kotlinHome);
protected abstract fun setupPlatformSpecificArgumentsAndServices(
configuration: CompilerConfiguration, arguments: A, services: Services
)
protected abstract fun doExecute(
arguments: A,
configuration: CompilerConfiguration,
rootDisposable: Disposable,
paths: KotlinPaths?
): ExitCode
companion object {
var KOTLIN_HOME_PROPERTY = "kotlin.home"
private fun computeKotlinPaths(messageCollector: MessageCollector, arguments: CommonCompilerArguments): KotlinPaths? {
val paths: KotlinPaths?
val kotlinHomeProperty = System.getProperty(KOTLIN_HOME_PROPERTY)
val kotlinHome = if (arguments.kotlinHome != null)
File(arguments.kotlinHome!!)
else if (kotlinHomeProperty != null)
File(kotlinHomeProperty)
else
null
if (kotlinHome != null) {
if (kotlinHome.isDirectory) {
paths = KotlinPathsFromHomeDir(kotlinHome)
} else {
messageCollector.report(ERROR, "Kotlin home does not exist or is not a directory: $kotlinHome", null)
paths = null
}
} else {
paths = PathUtil.kotlinPathsForCompiler
}
else {
messageCollector.report(ERROR, "Kotlin home does not exist or is not a directory: " + kotlinHome, null);
paths = null;
if (paths != null) {
messageCollector.report(LOGGING, "Using Kotlin home directory " + paths.homePath, null)
}
}
else {
paths = PathUtil.getKotlinPathsForCompiler();
return paths
}
if (paths != null) {
messageCollector.report(LOGGING, "Using Kotlin home directory " + paths.getHomePath(), null);
}
fun getLibraryFromHome(
paths: KotlinPaths?,
getLibrary: Function1<KotlinPaths, File>,
libraryName: String,
messageCollector: MessageCollector,
noLibraryArgument: String
): File? {
if (paths != null) {
val stdlibJar = getLibrary.invoke(paths)
if (stdlibJar.exists()) {
return stdlibJar
}
}
return paths;
messageCollector.report(
STRONG_WARNING, "Unable to find " + libraryName + " in the Kotlin home directory. " +
"Pass either " + noLibraryArgument + " to prevent adding it to the classpath, " +
"or the correct '-kotlin-home'", null
)
return null
}
}
@Nullable
public static File getLibraryFromHome(
@Nullable KotlinPaths paths,
@NotNull Function1<KotlinPaths, File> getLibrary,
@NotNull String libraryName,
@NotNull MessageCollector messageCollector,
@NotNull String noLibraryArgument
) {
if (paths != null) {
File stdlibJar = getLibrary.invoke(paths);
if (stdlibJar.exists()) {
return stdlibJar;
}
}
messageCollector.report(STRONG_WARNING, "Unable to find " + libraryName + " in the Kotlin home directory. " +
"Pass either " + noLibraryArgument + " to prevent adding it to the classpath, " +
"or the correct '-kotlin-home'", null);
return null;
}
protected abstract void setupPlatformSpecificArgumentsAndServices(
@NotNull CompilerConfiguration configuration, @NotNull A arguments, @NotNull Services services
);
@NotNull
protected abstract ExitCode doExecute(
@NotNull A arguments,
@NotNull CompilerConfiguration configuration,
@NotNull Disposable rootDisposable,
@Nullable KotlinPaths paths
);
@NotNull
protected abstract CommonCompilerPerformanceManager getPerformanceManager();
}
@@ -460,7 +460,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
) {
List<String> libraries = new SmartList<>();
if (!arguments.getNoStdlib()) {
File stdlibJar = getLibraryFromHome(
File stdlibJar = Companion.getLibraryFromHome(
paths, KotlinPaths::getJsStdLibJarPath, PathUtil.JS_LIB_JAR_NAME, messageCollector, "'-no-stdlib'");
if (stdlibJar != null) {
libraries.add(stdlibJar.getAbsolutePath());
@@ -56,7 +56,7 @@ import java.util.*
class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
private val performanceManager: K2JVMCompilerPerformanceManager = K2JVMCompilerPerformanceManager()
override val performanceManager = K2JVMCompilerPerformanceManager()
override fun doExecute(
arguments: K2JVMCompilerArguments,
@@ -220,8 +220,6 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
}
}
override fun getPerformanceManager(): CommonCompilerPerformanceManager = performanceManager
private fun loadPlugins(arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration): ExitCode {
var pluginClasspaths: Iterable<String> = arguments.pluginClasspaths?.asIterable() ?: emptyList()
val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList()
@@ -340,7 +338,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
override fun createMetadataVersion(versionArray: IntArray): BinaryVersion = JvmMetadataVersion(*versionArray)
private class K2JVMCompilerPerformanceManager : CommonCompilerPerformanceManager("Kotlin to JVM Compiler")
protected class K2JVMCompilerPerformanceManager : CommonCompilerPerformanceManager("Kotlin to JVM Compiler")
companion object {
@JvmStatic
@@ -38,7 +38,8 @@ import org.jetbrains.kotlin.utils.KotlinPaths
import java.io.File
class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
private val performanceManager: K2MetadataCompilerPerformanceManager = K2MetadataCompilerPerformanceManager()
override val performanceManager = K2MetadataCompilerPerformanceManager()
override fun createArguments() = K2MetadataCompilerArguments()
@@ -112,8 +113,6 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
override fun createMetadataVersion(versionArray: IntArray): BinaryVersion = BuiltInsBinaryVersion(*versionArray)
override fun getPerformanceManager(): CommonCompilerPerformanceManager = performanceManager
companion object {
@JvmStatic
fun main(args: Array<String>) {
@@ -121,5 +120,5 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
}
}
private class K2MetadataCompilerPerformanceManager : CommonCompilerPerformanceManager("Kotlin to Metadata compiler")
protected class K2MetadataCompilerPerformanceManager : CommonCompilerPerformanceManager("Kotlin to Metadata compiler")
}