diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt index 27924c5332d..237ec687ed5 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt @@ -17,8 +17,9 @@ package org.jetbrains.kotlin.cli.common.arguments import com.intellij.util.xmlb.annotations.Transient +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.config.AnalysisFlag +import org.jetbrains.kotlin.config.* import java.util.* @SuppressWarnings("WeakerAccess") @@ -164,9 +165,89 @@ abstract class CommonCompilerArguments : CommonToolArguments() { put(AnalysisFlag.allowKotlinPackage, allowKotlinPackage) put(AnalysisFlag.experimental, experimental?.toList().orEmpty()) put(AnalysisFlag.useExperimental, useExperimental?.toList().orEmpty()) + put(AnalysisFlag.explicitApiVersion, apiVersion != null) } } + open fun configureLanguageFeatures(collector: MessageCollector): MutableMap = + HashMap().apply { + if (multiPlatform) { + put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED) + } + + when (coroutinesState) { + CommonCompilerArguments.ERROR -> put(LanguageFeature.Coroutines, LanguageFeature.State.ENABLED_WITH_ERROR) + CommonCompilerArguments.ENABLE -> put(LanguageFeature.Coroutines, LanguageFeature.State.ENABLED) + CommonCompilerArguments.WARN -> {} + else -> { + val message = "Invalid value of -Xcoroutines (should be: enable, warn or error): " + coroutinesState + collector.report(CompilerMessageSeverity.ERROR, message, null) + } + } + + if (newInference) { + put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED) + } + + if (legacySmartCastAfterTry) { + put(LanguageFeature.SoundSmartCastsAfterTry, LanguageFeature.State.DISABLED) + } + + if (effectSystem) { + put(LanguageFeature.UseCallsInPlaceEffect, LanguageFeature.State.ENABLED) + put(LanguageFeature.UseReturnsEffect, LanguageFeature.State.ENABLED) + } + + if (readDeserializedContracts) { + put(LanguageFeature.ReadDeserializedContracts, LanguageFeature.State.ENABLED) + } + + if (properIeee754Comparisons) { + put(LanguageFeature.ProperIeee754Comparisons, LanguageFeature.State.ENABLED) + } + } + + fun configureLanguageVersionSettings(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 + + // If only "-language-version" is specified, API version is assumed to be equal to the language version + // (API version cannot be greater than the language version) + val apiVersion = parseVersion(collector, apiVersion, "API") ?: languageVersion + + if (apiVersion > languageVersion) { + collector.report( + CompilerMessageSeverity.ERROR, + "-api-version (${apiVersion.versionString}) cannot be greater than -language-version (${languageVersion.versionString})" + ) + } + + if (!languageVersion.isStable) { + collector.report( + CompilerMessageSeverity.STRONG_WARNING, + "Language version ${languageVersion.versionString} is experimental, there are no backwards compatibility guarantees for new language and library features" + ) + } + + return LanguageVersionSettingsImpl( + languageVersion, + ApiVersion.createByLanguageVersion(apiVersion), + configureAnalysisFlags(collector), + configureLanguageFeatures(collector) + ) + } + + private fun parseVersion(collector: MessageCollector, value: String?, versionOf: String): LanguageVersion? = + if (value == null) null + else LanguageVersion.fromVersionString(value) + ?: run { + val versionStrings = LanguageVersion.values().map(LanguageVersion::description) + val message = "Unknown $versionOf version: $value\nSupported $versionOf versions: ${versionStrings.joinToString(", ")}" + collector.report(CompilerMessageSeverity.ERROR, message, null) + null + } + // Used only for serialize and deserialize settings. Don't use in other places! class DummyImpl : CommonCompilerArguments() } diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt index c6275a1953d..23bef30a62b 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.config.AnalysisFlag import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.config.LanguageFeature class K2JVMCompilerArguments : CommonCompilerArguments() { companion object { @@ -235,4 +236,12 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { ) return result } + + override fun configureLanguageFeatures(collector: MessageCollector): MutableMap { + val result = super.configureLanguageFeatures(collector) + if (strictJavaNullabilityAssertions) { + result[LanguageFeature.StrictJavaNullabilityAssertions] = LanguageFeature.State.ENABLED + } + return result + } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java index c2ac5f690db..cf93fae92ab 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java @@ -41,7 +41,6 @@ import org.jetbrains.kotlin.utils.StringsKt; import java.io.File; import java.io.PrintStream; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -162,89 +161,10 @@ public abstract class CLICompiler extends CLI } private void setupLanguageVersionSettings(@NotNull CompilerConfiguration configuration, @NotNull A arguments) { - LanguageVersion languageVersion = parseVersion(configuration, arguments.getLanguageVersion(), "language"); - LanguageVersion apiVersion = parseVersion(configuration, arguments.getApiVersion(), "API"); - - if (languageVersion != null || apiVersion != null) { - configuration.put(CLIConfigurationKeys.IS_API_VERSION_EXPLICIT, true); - } - - if (languageVersion == null) { - // If no "-language-version" is specified, language version is assumed to be the latest stable - languageVersion = LanguageVersion.LATEST_STABLE; - } - - if (apiVersion == null) { - // If no "-api-version" is specified, API version is assumed to be equal to the language version - // (API version cannot be greater than the language version) - apiVersion = languageVersion; - } MessageCollector collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY); - if (apiVersion.compareTo(languageVersion) > 0) { - collector.report( - ERROR, - "-api-version (" + apiVersion.getVersionString() + ") cannot be greater than " + - "-language-version (" + languageVersion.getVersionString() + ")", - null - ); - } - if (!languageVersion.isStable()) { - collector.report( - STRONG_WARNING, - "Language version " + languageVersion.getVersionString() + " is experimental, there are " + - "no backwards compatibility guarantees for new language and library features", - null - ); - } - - Map extraLanguageFeatures = new HashMap<>(0); - if (arguments.getMultiPlatform()) { - extraLanguageFeatures.put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED); - } - - LanguageFeature.State coroutinesState = chooseCoroutinesApplicabilityLevel(configuration, arguments); - if (coroutinesState != null) { - extraLanguageFeatures.put(LanguageFeature.Coroutines, coroutinesState); - } - - if (arguments.getNewInference()) { - extraLanguageFeatures.put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED); - } - - if (arguments.getLegacySmartCastAfterTry()) { - extraLanguageFeatures.put(LanguageFeature.SoundSmartCastsAfterTry, LanguageFeature.State.DISABLED); - } - - if (arguments.getEffectSystem()) { - extraLanguageFeatures.put(LanguageFeature.UseCallsInPlaceEffect, LanguageFeature.State.ENABLED); - extraLanguageFeatures.put(LanguageFeature.UseReturnsEffect, LanguageFeature.State.ENABLED); - } - - if (arguments.getReadDeserializedContracts()) { - extraLanguageFeatures.put(LanguageFeature.ReadDeserializedContracts, LanguageFeature.State.ENABLED); - } - - if (arguments.getProperIeee754Comparisons()) { - extraLanguageFeatures.put(LanguageFeature.ProperIeee754Comparisons, LanguageFeature.State.ENABLED); - } - - setupPlatformSpecificLanguageFeatureSettings(extraLanguageFeatures, arguments); - - CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, new LanguageVersionSettingsImpl( - languageVersion, - ApiVersion.createByLanguageVersion(apiVersion), - arguments.configureAnalysisFlags(collector), - extraLanguageFeatures - )); - } - - protected void setupPlatformSpecificLanguageFeatureSettings( - @NotNull Map extraLanguageFeatures, - @NotNull A commandLineArguments - ) { - // do nothing + CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, arguments.configureLanguageVersionSettings(collector)); } private static final String kotlinHomeEnvVar = System.getenv(KOTLIN_HOME_ENV_VAR); @@ -299,43 +219,6 @@ public abstract class CLICompiler extends CLI return null; } - @Nullable - private static LanguageFeature.State chooseCoroutinesApplicabilityLevel( - @NotNull CompilerConfiguration configuration, - @NotNull CommonCompilerArguments arguments - ) { - switch (arguments.getCoroutinesState()) { - case CommonCompilerArguments.ERROR: - return LanguageFeature.State.ENABLED_WITH_ERROR; - case CommonCompilerArguments.ENABLE: - return LanguageFeature.State.ENABLED; - case CommonCompilerArguments.WARN: - return null; - default: - String message = "Invalid value of -Xcoroutines (should be: enable, warn or error): " + arguments.getCoroutinesState(); - configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(ERROR, message, null); - return null; - } - } - - @Nullable - private static LanguageVersion parseVersion( - @NotNull CompilerConfiguration configuration, @Nullable String value, @NotNull String versionOf - ) { - if (value == null) return null; - - LanguageVersion version = LanguageVersion.fromVersionString(value); - if (version != null) { - return version; - } - - List versionStrings = ArraysKt.map(LanguageVersion.values(), LanguageVersion::getDescription); - String message = "Unknown " + versionOf + " version: " + value + "\n" + - "Supported " + versionOf + " versions: " + StringsKt.join(versionStrings, ", "); - configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(ERROR, message, null); - return null; - } - protected abstract void setupPlatformSpecificArgumentsAndServices( @NotNull CompilerConfiguration configuration, @NotNull A arguments, @NotNull Services services ); diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLIConfigurationKeys.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLIConfigurationKeys.java index 06a07bb5c70..ab682493981 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLIConfigurationKeys.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLIConfigurationKeys.java @@ -29,8 +29,6 @@ public class CLIConfigurationKeys { CompilerConfigurationKey.create("allow kotlin package"); public static final CompilerConfigurationKey REPORT_PERF = CompilerConfigurationKey.create("report performance information"); - public static final CompilerConfigurationKey IS_API_VERSION_EXPLICIT = - CompilerConfigurationKey.create("is API version explicit"); // Used in Eclipse plugin (see KotlinCLICompiler) public static final CompilerConfigurationKey INTELLIJ_PLUGIN_ROOT = diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/JvmRuntimeVersionsConsistencyChecker.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/JvmRuntimeVersionsConsistencyChecker.kt index 4090f355d34..53a8d4518de 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/JvmRuntimeVersionsConsistencyChecker.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/JvmRuntimeVersionsConsistencyChecker.kt @@ -129,7 +129,7 @@ object JvmRuntimeVersionsConsistencyChecker { val actualApi = ApiVersion.parse(actualRuntimeVersion.toString()) if (actualApi == null) { messageCollector.issue(null, "Could not parse runtime JAR version: $actualRuntimeVersion") - } else if (!configuration.getBoolean(CLIConfigurationKeys.IS_API_VERSION_EXPLICIT) && actualApi < currentApi) { + } else if (!languageVersionSettings.getFlag(AnalysisFlag.explicitApiVersion) && actualApi < currentApi) { // If there's no explicit "-api-version" AND there's an old stdlib in the classpath (older than the default value of API), // we infer API = the version of that stdlib. // Note that "no explicit -api-version" requirement is necessary because for example, in diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index 32c33540b0d..3203ddf5573 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -227,17 +227,6 @@ class K2JVMCompiler : CLICompiler() { } } - override fun setupPlatformSpecificLanguageFeatureSettings( - extraLanguageFeatures: MutableMap, - commandLineArguments: K2JVMCompilerArguments - ) { - if (commandLineArguments.strictJavaNullabilityAssertions) { - extraLanguageFeatures[LanguageFeature.StrictJavaNullabilityAssertions] = LanguageFeature.State.ENABLED - } - - super.setupPlatformSpecificLanguageFeatureSettings(extraLanguageFeatures, commandLineArguments) - } - private fun registerJavacIfNeeded( environment: KotlinCoreEnvironment, arguments: K2JVMCompilerArguments diff --git a/compiler/util/src/org/jetbrains/kotlin/config/AnalysisFlag.kt b/compiler/util/src/org/jetbrains/kotlin/config/AnalysisFlag.kt index 91ba3f7b22f..c9719968b26 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/AnalysisFlag.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/AnalysisFlag.kt @@ -66,5 +66,8 @@ class AnalysisFlag internal constructor( @JvmStatic val useExperimental by Flag.ListOfStrings + + @JvmStatic + val explicitApiVersion by Flag.Boolean } }