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