Refactor compiler arguments to configuration conversion:
extract into independent functions, rearrange logic
This commit is contained in:
+1
-1
@@ -331,7 +331,7 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
}
|
||||
}
|
||||
|
||||
fun configureLanguageVersionSettings(collector: MessageCollector): LanguageVersionSettings {
|
||||
fun toLanguageVersionSettings(collector: MessageCollector): LanguageVersionSettings {
|
||||
|
||||
// If only "-api-version" is specified, language version is assumed to be the latest stable
|
||||
val languageVersion = parseVersion(collector, languageVersion, "language") ?: LanguageVersion.LATEST_STABLE
|
||||
|
||||
+20
-19
@@ -40,25 +40,25 @@ fun <From : Any, To : From> mergeBeans(from: From, to: To): To {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <From : Any, To : Any> copyInheritedFields(from: From, to: To) =
|
||||
copyProperties(from, to, true, collectProperties(from::class as KClass<From>, true))
|
||||
copyProperties(from, to, true, collectProperties(from::class as KClass<From>, true))
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <From : Any, To : Any> copyFieldsSatisfying(from: From, to: To, predicate: (KProperty1<From, Any?>) -> Boolean) =
|
||||
copyProperties(from, to, true, collectProperties(from::class as KClass<From>, false).filter(predicate))
|
||||
copyProperties(from, to, true, collectProperties(from::class as KClass<From>, false).filter(predicate))
|
||||
|
||||
private fun <From : Any, To : Any> copyProperties(
|
||||
from: From,
|
||||
to: To,
|
||||
deepCopyWhenNeeded: Boolean,
|
||||
propertiesToCopy: List<KProperty1<From, Any?>>,
|
||||
filter: ((KProperty1<From, Any?>, Any?) -> Boolean)? = null
|
||||
from: From,
|
||||
to: To,
|
||||
deepCopyWhenNeeded: Boolean,
|
||||
propertiesToCopy: List<KProperty1<From, Any?>>,
|
||||
filter: ((KProperty1<From, Any?>, Any?) -> Boolean)? = null
|
||||
): To {
|
||||
if (from == to) return to
|
||||
|
||||
for (fromProperty in propertiesToCopy) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val toProperty = to::class.memberProperties.firstOrNull { it.name == fromProperty.name } as? KMutableProperty1<To, Any?>
|
||||
?: continue
|
||||
?: continue
|
||||
val fromValue = fromProperty.get(from)
|
||||
if (filter != null && !filter(fromProperty, fromValue)) continue
|
||||
toProperty.set(to, if (deepCopyWhenNeeded) fromValue?.copyValueIfNeeded() else fromValue)
|
||||
@@ -69,14 +69,14 @@ private fun <From : Any, To : Any> copyProperties(
|
||||
private fun Any.copyValueIfNeeded(): Any {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return when (this) {
|
||||
is ByteArray -> Arrays.copyOf(this, size)
|
||||
is CharArray -> Arrays.copyOf(this, size)
|
||||
is ShortArray -> Arrays.copyOf(this, size)
|
||||
is IntArray -> Arrays.copyOf(this, size)
|
||||
is LongArray -> Arrays.copyOf(this, size)
|
||||
is FloatArray -> Arrays.copyOf(this, size)
|
||||
is DoubleArray -> Arrays.copyOf(this, size)
|
||||
is BooleanArray -> Arrays.copyOf(this, size)
|
||||
is ByteArray -> this.copyOf(size)
|
||||
is CharArray -> this.copyOf(size)
|
||||
is ShortArray -> this.copyOf(size)
|
||||
is IntArray -> this.copyOf(size)
|
||||
is LongArray -> this.copyOf(size)
|
||||
is FloatArray -> this.copyOf(size)
|
||||
is DoubleArray -> this.copyOf(size)
|
||||
is BooleanArray -> this.copyOf(size)
|
||||
|
||||
is Array<*> -> java.lang.reflect.Array.newInstance(this::class.java.componentType, size).apply {
|
||||
this as Array<Any?>
|
||||
@@ -100,8 +100,8 @@ fun <T : Any> collectProperties(kClass: KClass<T>, inheritedOnly: Boolean): List
|
||||
if (inheritedOnly) {
|
||||
properties.removeAll(kClass.declaredMemberProperties)
|
||||
}
|
||||
return properties.filter {
|
||||
it.visibility == KVisibility.PUBLIC && (it.annotations.firstOrNull { it is Transient } as Transient?) == null
|
||||
return properties.filter { property ->
|
||||
property.visibility == KVisibility.PUBLIC && (property.annotations.firstOrNull { it is Transient } as Transient?) == null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,4 +109,5 @@ fun CommonCompilerArguments.setApiVersionToLanguageVersionIfNeeded() {
|
||||
if (languageVersion != null && VersionComparatorUtil.compare(languageVersion, apiVersion) < 0) {
|
||||
apiVersion = languageVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,17 @@ package org.jetbrains.kotlin.cli.common
|
||||
|
||||
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.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.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
|
||||
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
|
||||
@@ -34,18 +36,9 @@ 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 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.*
|
||||
|
||||
abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
|
||||
|
||||
protected abstract val performanceManager: CommonCompilerPerformanceManager
|
||||
@@ -60,22 +53,24 @@ abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
|
||||
return exec(errStream, Services.EMPTY, MessageRenderer.PLAIN_FULL_PATHS, args)
|
||||
}
|
||||
|
||||
public override fun execImpl(messageCollector: MessageCollector, services: Services, arguments: A): ExitCode {
|
||||
public override fun execImpl(baseMessageCollector: MessageCollector, services: Services, arguments: A): ExitCode {
|
||||
val performanceManager = performanceManager
|
||||
if (arguments.reportPerf || arguments.dumpPerf != null) {
|
||||
performanceManager.enableCollectingPerformanceStatistics()
|
||||
}
|
||||
|
||||
val groupingCollector = GroupingMessageCollector(messageCollector, arguments.allWarningsAsErrors)
|
||||
|
||||
val configuration = CompilerConfiguration()
|
||||
configuration.put(MESSAGE_COLLECTOR_KEY, groupingCollector)
|
||||
|
||||
val messageCollector = GroupingMessageCollector(baseMessageCollector, arguments.allWarningsAsErrors).also {
|
||||
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, it)
|
||||
}
|
||||
|
||||
configuration.put(CLIConfigurationKeys.PERF_MANAGER, performanceManager)
|
||||
try {
|
||||
setupCommonArguments(configuration, arguments)
|
||||
setupPlatformSpecificArgumentsAndServices(configuration, arguments, services)
|
||||
val paths = computeKotlinPaths(groupingCollector, arguments)
|
||||
if (groupingCollector.hasErrors()) {
|
||||
val paths = computeKotlinPaths(messageCollector, arguments)
|
||||
if (messageCollector.hasErrors()) {
|
||||
return ExitCode.COMPILATION_ERROR
|
||||
}
|
||||
|
||||
@@ -85,6 +80,7 @@ abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
|
||||
val rootDisposable = Disposer.newDisposable()
|
||||
try {
|
||||
setIdeaIoUseFallback()
|
||||
|
||||
val code = doExecute(arguments, configuration, rootDisposable, paths)
|
||||
|
||||
performanceManager.notifyCompilationFinished()
|
||||
@@ -97,7 +93,7 @@ abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
|
||||
performanceManager.dumpPerformanceReport(File(arguments.dumpPerf!!))
|
||||
}
|
||||
|
||||
return if (groupingCollector.hasErrors()) COMPILATION_ERROR else code
|
||||
return if (messageCollector.hasErrors()) COMPILATION_ERROR else code
|
||||
} catch (e: CompilationCanceledException) {
|
||||
messageCollector.report(INFO, "Compilation was canceled", null)
|
||||
return ExitCode.OK
|
||||
@@ -115,61 +111,19 @@ abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
|
||||
} catch (e: AnalysisResult.CompilationErrorException) {
|
||||
return COMPILATION_ERROR
|
||||
} catch (t: Throwable) {
|
||||
MessageCollectorUtil.reportException(groupingCollector, t)
|
||||
MessageCollectorUtil.reportException(messageCollector, t)
|
||||
return INTERNAL_ERROR
|
||||
} finally {
|
||||
groupingCollector.flush()
|
||||
messageCollector.flush()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCommonArguments(configuration: CompilerConfiguration, arguments: A) {
|
||||
if (arguments.noInline) {
|
||||
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, true)
|
||||
}
|
||||
if (arguments.intellijPluginRoot != null) {
|
||||
configuration.put(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, arguments.intellijPluginRoot!!)
|
||||
}
|
||||
if (arguments.reportOutputFiles) {
|
||||
configuration.put(CommonConfigurationKeys.REPORT_OUTPUT_FILES, true)
|
||||
}
|
||||
|
||||
val metadataVersionString = arguments.metadataVersion
|
||||
if (metadataVersionString != null) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
setupLanguageVersionSettings(configuration, arguments)
|
||||
|
||||
configuration.put(CommonConfigurationKeys.LIST_PHASES, arguments.listPhases)
|
||||
if (arguments.disablePhases != null) {
|
||||
configuration.put(CommonConfigurationKeys.DISABLED_PHASES, setOf(*arguments.disablePhases!!))
|
||||
}
|
||||
if (arguments.verbosePhases != null) {
|
||||
configuration.put(CommonConfigurationKeys.VERBOSE_PHASES, setOf(*arguments.verbosePhases!!))
|
||||
}
|
||||
if (arguments.phasesToDumpBefore != null) {
|
||||
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_BEFORE, setOf(*arguments.phasesToDumpBefore!!))
|
||||
}
|
||||
if (arguments.phasesToDumpAfter != null) {
|
||||
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_AFTER, setOf(*arguments.phasesToDumpAfter!!))
|
||||
}
|
||||
if (arguments.phasesToDump != null) {
|
||||
configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE, setOf(*arguments.phasesToDump!!))
|
||||
}
|
||||
configuration.put(CommonConfigurationKeys.PROFILE_PHASES, arguments.profilePhases)
|
||||
configuration.setupCommonArguments(arguments, this::createMetadataVersion)
|
||||
}
|
||||
|
||||
protected abstract fun createMetadataVersion(versionArray: IntArray): BinaryVersion
|
||||
|
||||
private fun setupLanguageVersionSettings(configuration: CompilerConfiguration, arguments: A) {
|
||||
configuration.languageVersionSettings = arguments.configureLanguageVersionSettings(configuration.getNotNull(MESSAGE_COLLECTOR_KEY))
|
||||
}
|
||||
|
||||
protected abstract fun setupPlatformSpecificArgumentsAndServices(
|
||||
configuration: CompilerConfiguration, arguments: A, services: Services
|
||||
)
|
||||
@@ -180,58 +134,5 @@ abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
|
||||
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
|
||||
}
|
||||
|
||||
if (paths != null) {
|
||||
messageCollector.report(LOGGING, "Using Kotlin home directory " + paths.homePath, null)
|
||||
}
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
messageCollector
|
||||
}
|
||||
|
||||
reportArgumentParseProblems(fixedMessageCollector, arguments)
|
||||
fixedMessageCollector.reportArgumentParseProblems(arguments)
|
||||
return execImpl(fixedMessageCollector, services, arguments)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.common
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.ManualLanguageFeatureSetting
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
|
||||
fun <A : CommonCompilerArguments> CompilerConfiguration.setupCommonArguments(
|
||||
arguments: A,
|
||||
createMetadataVersion: ((IntArray) -> BinaryVersion)? = null
|
||||
) {
|
||||
put(CommonConfigurationKeys.DISABLE_INLINE, arguments.noInline)
|
||||
putIfNotNull(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, arguments.intellijPluginRoot)
|
||||
put(CommonConfigurationKeys.REPORT_OUTPUT_FILES, arguments.reportOutputFiles)
|
||||
|
||||
val metadataVersionString = arguments.metadataVersion
|
||||
if (metadataVersionString != null) {
|
||||
val versionArray = BinaryVersion.parseVersionArray(metadataVersionString)
|
||||
val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
when {
|
||||
versionArray == null -> messageCollector.report(
|
||||
CompilerMessageSeverity.ERROR, "Invalid metadata version: $metadataVersionString", null
|
||||
)
|
||||
createMetadataVersion == null -> throw IllegalStateException("Unable to create metadata version: missing argument")
|
||||
else -> put(CommonConfigurationKeys.METADATA_VERSION, createMetadataVersion(versionArray))
|
||||
}
|
||||
}
|
||||
|
||||
setupLanguageVersionSettings(arguments)
|
||||
|
||||
put(CommonConfigurationKeys.LIST_PHASES, arguments.listPhases)
|
||||
|
||||
listOf(
|
||||
CommonConfigurationKeys.DISABLED_PHASES to arguments.disablePhases,
|
||||
CommonConfigurationKeys.VERBOSE_PHASES to arguments.verbosePhases,
|
||||
CommonConfigurationKeys.PHASES_TO_DUMP_STATE_BEFORE to arguments.phasesToDumpBefore,
|
||||
CommonConfigurationKeys.PHASES_TO_DUMP_STATE_AFTER to arguments.phasesToDumpAfter,
|
||||
CommonConfigurationKeys.PHASES_TO_DUMP_STATE to arguments.phasesToDump
|
||||
).forEach { (k, v) ->
|
||||
if (v != null) put(k, setOf(*v))
|
||||
}
|
||||
|
||||
put(CommonConfigurationKeys.PROFILE_PHASES, arguments.profilePhases)
|
||||
}
|
||||
|
||||
fun <A : CommonCompilerArguments> CompilerConfiguration.setupLanguageVersionSettings(arguments: A) {
|
||||
languageVersionSettings = arguments.toLanguageVersionSettings(getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY))
|
||||
}
|
||||
|
||||
const val KOTLIN_HOME_PROPERTY = "kotlin.home"
|
||||
|
||||
fun computeKotlinPaths(messageCollector: MessageCollector, arguments: CommonCompilerArguments): KotlinPaths? {
|
||||
val kotlinHomeProperty = System.getProperty(KOTLIN_HOME_PROPERTY)
|
||||
val kotlinHome = when {
|
||||
arguments.kotlinHome != null -> File(arguments.kotlinHome!!)
|
||||
kotlinHomeProperty != null -> File(kotlinHomeProperty)
|
||||
else -> null
|
||||
}
|
||||
|
||||
return when {
|
||||
kotlinHome == null -> PathUtil.kotlinPathsForCompiler
|
||||
kotlinHome.isDirectory -> KotlinPathsFromHomeDir(kotlinHome)
|
||||
else -> {
|
||||
messageCollector.report(CompilerMessageSeverity.ERROR, "Kotlin home does not exist or is not a directory: $kotlinHome", null)
|
||||
null
|
||||
}
|
||||
}?.also {
|
||||
messageCollector.report(CompilerMessageSeverity.LOGGING, "Using Kotlin home directory " + it.homePath, null)
|
||||
}
|
||||
}
|
||||
|
||||
fun <A : CommonToolArguments> MessageCollector.reportArgumentParseProblems(arguments: A) {
|
||||
val errors = arguments.errors ?: return
|
||||
for (flag in errors.unknownExtraFlags) {
|
||||
report(CompilerMessageSeverity.STRONG_WARNING, "Flag is not supported by this version of the compiler: $flag")
|
||||
}
|
||||
for (argument in errors.extraArgumentsPassedInObsoleteForm) {
|
||||
report(
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"Advanced option value is passed in an obsolete form. Please use the '=' character to specify the value: $argument=..."
|
||||
)
|
||||
}
|
||||
for ((key, value) in errors.duplicateArguments) {
|
||||
report(CompilerMessageSeverity.STRONG_WARNING, "Argument $key is passed multiple times. Only the last value will be used: $value")
|
||||
}
|
||||
for ((deprecatedName, newName) in errors.deprecatedArguments) {
|
||||
report(CompilerMessageSeverity.STRONG_WARNING, "Argument $deprecatedName is deprecated. Please use $newName instead")
|
||||
}
|
||||
for (argfileError in errors.argfileErrors) {
|
||||
report(CompilerMessageSeverity.STRONG_WARNING, argfileError)
|
||||
}
|
||||
|
||||
reportUnsafeInternalArgumentsIfAny(arguments)
|
||||
|
||||
for (internalArgumentsError in errors.internalArgumentsParsingProblems) {
|
||||
report(CompilerMessageSeverity.STRONG_WARNING, internalArgumentsError)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <A : CommonToolArguments> MessageCollector.reportUnsafeInternalArgumentsIfAny(arguments: A) {
|
||||
val unsafeArguments = arguments.internalArguments.filterNot {
|
||||
// -XXLanguage which turns on BUG_FIX considered safe
|
||||
it is ManualLanguageFeatureSetting && it.languageFeature.kind == LanguageFeature.Kind.BUG_FIX && it.state == LanguageFeature.State.ENABLED
|
||||
}
|
||||
|
||||
if (unsafeArguments.isNotEmpty()) {
|
||||
val unsafeArgumentsString = unsafeArguments.joinToString(prefix = "\n", postfix = "\n\n", separator = "\n") {
|
||||
it.stringRepresentation
|
||||
}
|
||||
|
||||
report(
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"ATTENTION!\n" +
|
||||
"This build uses unsafe internal compiler arguments:\n" +
|
||||
unsafeArgumentsString +
|
||||
"This mode is not recommended for production use,\n" +
|
||||
"as no stability/compatibility guarantees are given on\n" +
|
||||
"compiler or generated code. Use it at your own risk!\n"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.isSubpackageOf
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||
import java.io.File
|
||||
|
||||
fun checkKotlinPackageUsage(environment: KotlinCoreEnvironment, files: Collection<KtFile>): Boolean {
|
||||
if (environment.configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE)) {
|
||||
@@ -42,3 +44,25 @@ fun checkKotlinPackageUsage(environment: KotlinCoreEnvironment, files: Collectio
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun getLibraryFromHome(
|
||||
paths: KotlinPaths?,
|
||||
getLibrary: (KotlinPaths) -> File,
|
||||
libraryName: String,
|
||||
messageCollector: MessageCollector,
|
||||
noLibraryArgument: String
|
||||
): File? {
|
||||
if (paths != null) {
|
||||
val stdlibJar = getLibrary(paths)
|
||||
if (stdlibJar.exists()) {
|
||||
return stdlibJar
|
||||
}
|
||||
}
|
||||
|
||||
messageCollector.report(
|
||||
CompilerMessageSeverity.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
|
||||
}
|
||||
@@ -77,6 +77,7 @@ import java.util.*;
|
||||
import static org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR;
|
||||
import static org.jetbrains.kotlin.cli.common.ExitCode.OK;
|
||||
import static org.jetbrains.kotlin.cli.common.UtilsKt.checkKotlinPackageUsage;
|
||||
import static org.jetbrains.kotlin.cli.common.UtilsKt.getLibraryFromHome;
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*;
|
||||
|
||||
public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
@@ -460,7 +461,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
) {
|
||||
List<String> libraries = new SmartList<>();
|
||||
if (!arguments.getNoStdlib()) {
|
||||
File stdlibJar = Companion.getLibraryFromHome(
|
||||
File stdlibJar = getLibraryFromHome(
|
||||
paths, KotlinPaths::getJsStdLibJarPath, PathUtil.JS_LIB_JAR_NAME, messageCollector, "'-no-stdlib'");
|
||||
if (stdlibJar != null) {
|
||||
libraries.add(stdlibJar.getAbsolutePath());
|
||||
|
||||
@@ -31,10 +31,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentUtil
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
|
||||
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal
|
||||
import org.jetbrains.kotlin.codegen.CompilationException
|
||||
@@ -66,13 +63,9 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
): ExitCode {
|
||||
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
|
||||
configureJdkHome(arguments, configuration, messageCollector).let {
|
||||
if (it != OK) return it
|
||||
}
|
||||
if (!configuration.configureJdkHome(arguments)) return COMPILATION_ERROR
|
||||
|
||||
if (arguments.disableStandardScript) {
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION, true)
|
||||
}
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION, arguments.disableStandardScript)
|
||||
|
||||
val pluginLoadResult = loadPlugins(arguments, configuration)
|
||||
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
|
||||
@@ -94,7 +87,8 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
|
||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME)
|
||||
|
||||
configureContentRoots(paths, arguments, configuration)
|
||||
configuration.configureExplicitContentRoots(arguments)
|
||||
configuration.configureStandardLibs(paths, arguments)
|
||||
|
||||
if (arguments.buildFile == null && arguments.freeArgs.isEmpty() && !arguments.version) {
|
||||
if (arguments.script) {
|
||||
@@ -105,29 +99,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
return ExitCode.OK
|
||||
}
|
||||
|
||||
if (arguments.includeRuntime) {
|
||||
configuration.put(JVMConfigurationKeys.INCLUDE_RUNTIME, true)
|
||||
}
|
||||
val friendPaths = arguments.friendPaths?.toList()
|
||||
if (friendPaths != null) {
|
||||
configuration.put(JVMConfigurationKeys.FRIEND_PATHS, friendPaths)
|
||||
}
|
||||
|
||||
if (arguments.jvmTarget != null) {
|
||||
val jvmTarget = JvmTarget.fromString(arguments.jvmTarget!!)
|
||||
if (jvmTarget != null) {
|
||||
configuration.put(JVMConfigurationKeys.JVM_TARGET, jvmTarget)
|
||||
} else {
|
||||
messageCollector.report(
|
||||
ERROR, "Unknown JVM target version: ${arguments.jvmTarget}\n" +
|
||||
"Supported versions: ${JvmTarget.values().joinToString { it.description }}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
configuration.put(JVMConfigurationKeys.PARAMETERS_METADATA, arguments.javaParameters)
|
||||
|
||||
putAdvancedOptions(configuration, arguments)
|
||||
configuration.configureAdvancedJvmOptions(arguments)
|
||||
|
||||
messageCollector.report(LOGGING, "Configuring the compilation environment")
|
||||
try {
|
||||
@@ -152,7 +124,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
|
||||
?: return COMPILATION_ERROR
|
||||
|
||||
registerJavacIfNeeded(environment, arguments).let {
|
||||
environment.registerJavacIfNeeded(arguments).let {
|
||||
if (!it) return COMPILATION_ERROR
|
||||
}
|
||||
|
||||
@@ -190,7 +162,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
|
||||
?: return COMPILATION_ERROR
|
||||
|
||||
registerJavacIfNeeded(environment, arguments).let {
|
||||
environment.registerJavacIfNeeded(arguments).let {
|
||||
if (!it) return COMPILATION_ERROR
|
||||
}
|
||||
|
||||
@@ -263,21 +235,6 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
return PluginCliParser.loadPluginsSafe(pluginClasspaths, pluginOptions, configuration)
|
||||
}
|
||||
|
||||
private fun registerJavacIfNeeded(
|
||||
environment: KotlinCoreEnvironment,
|
||||
arguments: K2JVMCompilerArguments
|
||||
): Boolean {
|
||||
if (arguments.useJavac) {
|
||||
environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
|
||||
if (arguments.compileJava) {
|
||||
environment.configuration.put(JVMConfigurationKeys.COMPILE_JAVA, true)
|
||||
}
|
||||
return environment.registerJavac(arguments = arguments.javacArguments)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun compileJavaFilesIfNeeded(
|
||||
environment: KotlinCoreEnvironment,
|
||||
arguments: K2JVMCompilerArguments
|
||||
@@ -305,26 +262,20 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
override fun setupPlatformSpecificArgumentsAndServices(
|
||||
configuration: CompilerConfiguration, arguments: K2JVMCompilerArguments, services: Services
|
||||
) {
|
||||
if (IncrementalCompilation.isEnabledForJvm()) {
|
||||
services[LookupTracker::class.java]?.let {
|
||||
configuration.put(CommonConfigurationKeys.LOOKUP_TRACKER, it)
|
||||
}
|
||||
with(configuration) {
|
||||
if (IncrementalCompilation.isEnabledForJvm()) {
|
||||
putIfNotNull(CommonConfigurationKeys.LOOKUP_TRACKER, services[LookupTracker::class.java])
|
||||
|
||||
services[ExpectActualTracker::class.java]?.let {
|
||||
configuration.put(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER, it)
|
||||
}
|
||||
putIfNotNull(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER, services[ExpectActualTracker::class.java])
|
||||
|
||||
services[IncrementalCompilationComponents::class.java]?.let {
|
||||
configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, it)
|
||||
}
|
||||
putIfNotNull(
|
||||
JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS,
|
||||
services[IncrementalCompilationComponents::class.java]
|
||||
)
|
||||
|
||||
services[JavaClassesTracker::class.java]?.let {
|
||||
configuration.put(JVMConfigurationKeys.JAVA_CLASSES_TRACKER, it)
|
||||
putIfNotNull(JVMConfigurationKeys.JAVA_CLASSES_TRACKER, services[JavaClassesTracker::class.java])
|
||||
}
|
||||
}
|
||||
|
||||
arguments.additionalJavaModules?.let { additionalJavaModules ->
|
||||
configuration.addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, additionalJavaModules.toList())
|
||||
setupJvmSpecificArguments(arguments)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,131 +297,8 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
CLITool.doMain(K2JVMCompiler(), args)
|
||||
}
|
||||
|
||||
private fun putAdvancedOptions(configuration: CompilerConfiguration, arguments: K2JVMCompilerArguments) {
|
||||
configuration.put(JVMConfigurationKeys.IR, arguments.useIR)
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions)
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions)
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, arguments.noParamAssertions)
|
||||
configuration.put(
|
||||
JVMConfigurationKeys.NO_EXCEPTION_ON_EXPLICIT_EQUALS_FOR_BOXED_NULL,
|
||||
arguments.noExceptionOnExplicitEqualsForBoxedNull
|
||||
)
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_OPTIMIZATION, arguments.noOptimize)
|
||||
|
||||
if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) {
|
||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
|
||||
ERROR,
|
||||
"Unknown constructor call normalization mode: ${arguments.constructorCallNormalizationMode}, " +
|
||||
"supported modes: ${JVMConstructorCallNormalizationMode.values().map { it.description }}"
|
||||
)
|
||||
}
|
||||
|
||||
val constructorCallNormalizationMode =
|
||||
JVMConstructorCallNormalizationMode.fromStringOrNull(arguments.constructorCallNormalizationMode)
|
||||
if (constructorCallNormalizationMode != null) {
|
||||
configuration.put(
|
||||
JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE,
|
||||
constructorCallNormalizationMode
|
||||
)
|
||||
}
|
||||
|
||||
val assertionsMode =
|
||||
JVMAssertionsMode.fromStringOrNull(arguments.assertionsMode)
|
||||
if (assertionsMode == null) {
|
||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
|
||||
ERROR,
|
||||
"Unknown assertions mode: ${arguments.assertionsMode}, " +
|
||||
"supported modes: ${JVMAssertionsMode.values().map { it.description }}"
|
||||
)
|
||||
}
|
||||
configuration.put(
|
||||
JVMConfigurationKeys.ASSERTIONS_MODE,
|
||||
assertionsMode ?: JVMAssertionsMode.DEFAULT
|
||||
)
|
||||
|
||||
configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, arguments.useTypeTable)
|
||||
configuration.put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck)
|
||||
configuration.put(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING, !arguments.useOldClassFilesReading)
|
||||
|
||||
if (arguments.useOldClassFilesReading) {
|
||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
.report(INFO, "Using the old java class files reading implementation")
|
||||
}
|
||||
|
||||
configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
|
||||
configuration.put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule)
|
||||
configuration.put(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES, arguments.addCompilerBuiltIns)
|
||||
configuration.put(JVMConfigurationKeys.CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES, arguments.loadBuiltInsFromDependencies)
|
||||
|
||||
arguments.declarationsOutputPath?.let { configuration.put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
|
||||
}
|
||||
|
||||
private fun configureContentRoots(paths: KotlinPaths?, arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration) {
|
||||
for (modularRoot in arguments.javaModulePath?.split(File.pathSeparatorChar).orEmpty()) {
|
||||
configuration.add(CLIConfigurationKeys.CONTENT_ROOTS, JvmModulePathRoot(File(modularRoot)))
|
||||
}
|
||||
|
||||
if (arguments.buildFile != null) {
|
||||
// In the .xml compilation mode, all content roots except module path will be loaded from the .xml build file.
|
||||
return
|
||||
}
|
||||
|
||||
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
for (path in arguments.classpath?.split(File.pathSeparatorChar).orEmpty()) {
|
||||
configuration.add(CLIConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(File(path)))
|
||||
}
|
||||
|
||||
val isModularJava = configuration.get(JVMConfigurationKeys.JDK_HOME).let { it != null && CoreJrtFileSystem.isModularJdk(it) }
|
||||
fun addRoot(moduleName: String, libraryName: String, getLibrary: (KotlinPaths) -> File, noLibraryArgument: String) {
|
||||
val file = getLibraryFromHome(paths, getLibrary, libraryName, messageCollector, noLibraryArgument) ?: return
|
||||
if (isModularJava) {
|
||||
configuration.add(CLIConfigurationKeys.CONTENT_ROOTS, JvmModulePathRoot(file))
|
||||
configuration.add(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, moduleName)
|
||||
} else {
|
||||
configuration.add(CLIConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(file))
|
||||
}
|
||||
}
|
||||
|
||||
if (!arguments.noStdlib) {
|
||||
addRoot("kotlin.stdlib", PathUtil.KOTLIN_JAVA_STDLIB_JAR, KotlinPaths::getStdlibPath, "'-no-stdlib'")
|
||||
addRoot("kotlin.script.runtime", PathUtil.KOTLIN_JAVA_SCRIPT_RUNTIME_JAR, KotlinPaths::getScriptRuntimePath, "'-no-stdlib'")
|
||||
}
|
||||
// "-no-stdlib" implies "-no-reflect": otherwise we would be able to transitively read stdlib classes through kotlin-reflect,
|
||||
// which is likely not what user wants since s/he manually provided "-no-stdlib"
|
||||
if (!arguments.noReflect && !arguments.noStdlib) {
|
||||
addRoot("kotlin.reflect", PathUtil.KOTLIN_JAVA_REFLECT_JAR, KotlinPaths::getReflectPath, "'-no-reflect' or '-no-stdlib'")
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureJdkHome(
|
||||
arguments: K2JVMCompilerArguments,
|
||||
configuration: CompilerConfiguration,
|
||||
messageCollector: MessageCollector
|
||||
): ExitCode {
|
||||
if (arguments.noJdk) {
|
||||
configuration.put(JVMConfigurationKeys.NO_JDK, true)
|
||||
|
||||
if (arguments.jdkHome != null) {
|
||||
messageCollector.report(STRONG_WARNING, "The '-jdk-home' option is ignored because '-no-jdk' is specified")
|
||||
}
|
||||
return OK
|
||||
}
|
||||
|
||||
if (arguments.jdkHome != null) {
|
||||
val jdkHome = File(arguments.jdkHome)
|
||||
if (!jdkHome.exists()) {
|
||||
messageCollector.report(ERROR, "JDK home directory does not exist: $jdkHome")
|
||||
return COMPILATION_ERROR
|
||||
}
|
||||
|
||||
messageCollector.report(LOGGING, "Using JDK home directory $jdkHome")
|
||||
|
||||
configuration.put(JVMConfigurationKeys.JDK_HOME, jdkHome)
|
||||
}
|
||||
|
||||
return OK
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun main(args: Array<String>) = K2JVMCompiler.main(args)
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.getLibraryFromHome
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
|
||||
fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArguments) {
|
||||
|
||||
val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
|
||||
put(JVMConfigurationKeys.INCLUDE_RUNTIME, arguments.includeRuntime)
|
||||
|
||||
putIfNotNull(JVMConfigurationKeys.FRIEND_PATHS, arguments.friendPaths?.asList())
|
||||
|
||||
if (arguments.jvmTarget != null) {
|
||||
val jvmTarget = JvmTarget.fromString(arguments.jvmTarget!!)
|
||||
if (jvmTarget != null) {
|
||||
put(JVMConfigurationKeys.JVM_TARGET, jvmTarget)
|
||||
} else {
|
||||
messageCollector.report(
|
||||
ERROR, "Unknown JVM target version: ${arguments.jvmTarget}\n" +
|
||||
"Supported versions: ${JvmTarget.values().joinToString { it.description }}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, arguments.additionalJavaModules?.asList())
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.configureJdkHome(arguments: K2JVMCompilerArguments): Boolean {
|
||||
|
||||
val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
|
||||
if (arguments.noJdk) {
|
||||
put(JVMConfigurationKeys.NO_JDK, true)
|
||||
|
||||
if (arguments.jdkHome != null) {
|
||||
messageCollector.report(STRONG_WARNING, "The '-jdk-home' option is ignored because '-no-jdk' is specified")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if (arguments.jdkHome != null) {
|
||||
val jdkHome = File(arguments.jdkHome)
|
||||
if (!jdkHome.exists()) {
|
||||
messageCollector.report(ERROR, "JDK home directory does not exist: $jdkHome")
|
||||
return false
|
||||
}
|
||||
|
||||
messageCollector.report(LOGGING, "Using JDK home directory $jdkHome")
|
||||
|
||||
put(JVMConfigurationKeys.JDK_HOME, jdkHome)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.configureExplicitContentRoots(arguments: K2JVMCompilerArguments) {
|
||||
for (modularRoot in arguments.javaModulePath?.split(File.pathSeparatorChar).orEmpty()) {
|
||||
add(CLIConfigurationKeys.CONTENT_ROOTS, JvmModulePathRoot(File(modularRoot)))
|
||||
}
|
||||
|
||||
if (arguments.buildFile != null) {
|
||||
// In the .xml compilation mode, all content roots except module path will be loaded from the .xml build file.
|
||||
return
|
||||
}
|
||||
|
||||
for (path in arguments.classpath?.split(File.pathSeparatorChar).orEmpty()) {
|
||||
add(CLIConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(File(path)))
|
||||
}
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.configureStandardLibs(paths: KotlinPaths?, arguments: K2JVMCompilerArguments) {
|
||||
val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
val isModularJava = isModularJava()
|
||||
|
||||
fun addRoot(moduleName: String, libraryName: String, getLibrary: (KotlinPaths) -> File, noLibraryArgument: String) {
|
||||
addModularRootIfNotNull(
|
||||
isModularJava, moduleName,
|
||||
getLibraryFromHome(paths, getLibrary, libraryName, messageCollector, noLibraryArgument)
|
||||
)
|
||||
}
|
||||
|
||||
if (!arguments.noStdlib) {
|
||||
addRoot("kotlin.stdlib", PathUtil.KOTLIN_JAVA_STDLIB_JAR, KotlinPaths::getStdlibPath, "'-no-stdlib'")
|
||||
addRoot("kotlin.script.runtime", PathUtil.KOTLIN_JAVA_SCRIPT_RUNTIME_JAR, KotlinPaths::getScriptRuntimePath, "'-no-stdlib'")
|
||||
}
|
||||
// "-no-stdlib" implies "-no-reflect": otherwise we would be able to transitively read stdlib classes through kotlin-reflect,
|
||||
// which is likely not what user wants since s/he manually provided "-no-stdlib"
|
||||
if (!arguments.noReflect && !arguments.noStdlib) {
|
||||
addRoot("kotlin.reflect", PathUtil.KOTLIN_JAVA_REFLECT_JAR, KotlinPaths::getReflectPath, "'-no-reflect' or '-no-stdlib'")
|
||||
}
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.isModularJava(): Boolean {
|
||||
return get(JVMConfigurationKeys.JDK_HOME)?.let {
|
||||
CoreJrtFileSystem.isModularJdk(it)
|
||||
} ?: false
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.addModularRootIfNotNull(isModularJava: Boolean, moduleName: String, file: File?) {
|
||||
when {
|
||||
file == null -> {
|
||||
}
|
||||
isModularJava -> {
|
||||
add(CLIConfigurationKeys.CONTENT_ROOTS, JvmModulePathRoot(file))
|
||||
add(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, moduleName)
|
||||
}
|
||||
else -> add(CLIConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(file))
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinCoreEnvironment.registerJavacIfNeeded(
|
||||
arguments: K2JVMCompilerArguments
|
||||
): Boolean {
|
||||
if (arguments.useJavac) {
|
||||
configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
|
||||
if (arguments.compileJava) {
|
||||
configuration.put(JVMConfigurationKeys.COMPILE_JAVA, true)
|
||||
}
|
||||
return registerJavac(arguments = arguments.javacArguments)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerArguments) {
|
||||
|
||||
put(JVMConfigurationKeys.PARAMETERS_METADATA, arguments.javaParameters)
|
||||
|
||||
put(JVMConfigurationKeys.IR, arguments.useIR)
|
||||
put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions)
|
||||
put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions)
|
||||
put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, arguments.noParamAssertions)
|
||||
put(
|
||||
JVMConfigurationKeys.NO_EXCEPTION_ON_EXPLICIT_EQUALS_FOR_BOXED_NULL,
|
||||
arguments.noExceptionOnExplicitEqualsForBoxedNull
|
||||
)
|
||||
put(JVMConfigurationKeys.DISABLE_OPTIMIZATION, arguments.noOptimize)
|
||||
|
||||
if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) {
|
||||
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
|
||||
ERROR,
|
||||
"Unknown constructor call normalization mode: ${arguments.constructorCallNormalizationMode}, " +
|
||||
"supported modes: ${JVMConstructorCallNormalizationMode.values().map { it.description }}"
|
||||
)
|
||||
}
|
||||
|
||||
val constructorCallNormalizationMode =
|
||||
JVMConstructorCallNormalizationMode.fromStringOrNull(arguments.constructorCallNormalizationMode)
|
||||
if (constructorCallNormalizationMode != null) {
|
||||
put(
|
||||
JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE,
|
||||
constructorCallNormalizationMode
|
||||
)
|
||||
}
|
||||
|
||||
val assertionsMode =
|
||||
JVMAssertionsMode.fromStringOrNull(arguments.assertionsMode)
|
||||
if (assertionsMode == null) {
|
||||
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
|
||||
ERROR,
|
||||
"Unknown assertions mode: ${arguments.assertionsMode}, " +
|
||||
"supported modes: ${JVMAssertionsMode.values().map { it.description }}"
|
||||
)
|
||||
}
|
||||
put(
|
||||
JVMConfigurationKeys.ASSERTIONS_MODE,
|
||||
assertionsMode ?: JVMAssertionsMode.DEFAULT
|
||||
)
|
||||
|
||||
put(JVMConfigurationKeys.USE_TYPE_TABLE, arguments.useTypeTable)
|
||||
put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck)
|
||||
put(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING, !arguments.useOldClassFilesReading)
|
||||
|
||||
if (arguments.useOldClassFilesReading) {
|
||||
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
.report(INFO, "Using the old java class files reading implementation")
|
||||
}
|
||||
|
||||
put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
|
||||
put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule)
|
||||
put(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES, arguments.addCompilerBuiltIns)
|
||||
put(JVMConfigurationKeys.CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES, arguments.loadBuiltInsFromDependencies)
|
||||
|
||||
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
|
||||
}
|
||||
@@ -73,6 +73,12 @@ public class CompilerConfiguration {
|
||||
map.put(key.ideaKey, value);
|
||||
}
|
||||
|
||||
public <T> void putIfNotNull(@NotNull CompilerConfigurationKey<T> key, @Nullable T value) {
|
||||
if (value != null) {
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void add(@NotNull CompilerConfigurationKey<List<T>> key, @NotNull T value) {
|
||||
checkReadOnly();
|
||||
Key<List<T>> ideaKey = key.ideaKey;
|
||||
@@ -89,8 +95,10 @@ public class CompilerConfiguration {
|
||||
data.put(key, value);
|
||||
}
|
||||
|
||||
public <T> void addAll(@NotNull CompilerConfigurationKey<List<T>> key, @NotNull Collection<T> values) {
|
||||
addAll(key, getList(key).size(), values);
|
||||
public <T> void addAll(@NotNull CompilerConfigurationKey<List<T>> key, @Nullable Collection<T> values) {
|
||||
if (values != null) {
|
||||
addAll(key, getList(key).size(), values);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void addAll(@NotNull CompilerConfigurationKey<List<T>> key, int index, @NotNull Collection<T> values) {
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ private fun getLanguageSettingsForScripts(project: Project, scriptDefinition: Ko
|
||||
val compilerArguments = K2JVMCompilerArguments()
|
||||
parseCommandLineArguments(args.toList(), compilerArguments)
|
||||
// TODO: reporting
|
||||
val verSettings = compilerArguments.configureLanguageVersionSettings(MessageCollector.NONE)
|
||||
val verSettings = compilerArguments.toLanguageVersionSettings(MessageCollector.NONE)
|
||||
val jvmTarget = compilerArguments.jvmTarget?.let { JvmTarget.fromString(it) } ?: TargetPlatformVersion.NoVersion
|
||||
ScriptLanguageSettings(verSettings, jvmTarget)
|
||||
}.also { scriptDefinition.putUserData(SCRIPT_LANGUAGE_SETTINGS, it) }
|
||||
|
||||
Reference in New Issue
Block a user