Infer API version from older runtime in compiler's classpath
For example, if you invoke kotlinc 1.1 with kotlin-stdlib 1.0 in the classpath, we now infer -api-version 1.0 automatically
This commit is contained in:
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.utils.StringsKt;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -280,7 +281,12 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
||||
|
||||
configuration.put(
|
||||
CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS,
|
||||
new LanguageVersionSettingsImpl(languageVersion, ApiVersion.createByLanguageVersion(apiVersion), extraLanguageFeatures)
|
||||
new LanguageVersionSettingsImpl(
|
||||
languageVersion,
|
||||
ApiVersion.createByLanguageVersion(apiVersion),
|
||||
extraLanguageFeatures,
|
||||
arguments.apiVersion != null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+54
-13
@@ -19,12 +19,11 @@ package org.jetbrains.kotlin.cli.jvm
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.MavenComparableVersion
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
import java.util.jar.Attributes
|
||||
@@ -113,29 +112,71 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
|
||||
fun checkCompilerClasspathConsistency(
|
||||
messageCollector: MessageCollector,
|
||||
languageVersionSettings: LanguageVersionSettings?,
|
||||
configuration: CompilerConfiguration,
|
||||
classpathJarRoots: List<VirtualFile>
|
||||
) {
|
||||
val runtimeJarsInfo = collectRuntimeJarsInfo(classpathJarRoots)
|
||||
if (runtimeJarsInfo.jars.isEmpty()) return
|
||||
|
||||
val languageVersionSettings = configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)
|
||||
val apiVersion = languageVersionSettings?.apiVersion?.version ?: CURRENT_COMPILER_VERSION
|
||||
|
||||
val consistency = checkCompilerClasspathConsistency(messageCollector, apiVersion, runtimeJarsInfo)
|
||||
if (consistency != ClasspathConsistency.Consistent) {
|
||||
val message = when (consistency) {
|
||||
is ClasspathConsistency.InconsistentWithApiVersion ->
|
||||
"Runtime JAR files in the classpath have the version ${consistency.actualRuntimeVersion}, " +
|
||||
if (consistency is ClasspathConsistency.InconsistentWithApiVersion) {
|
||||
val actualRuntimeVersion = consistency.actualRuntimeVersion
|
||||
messageCollector.issue(
|
||||
null,
|
||||
"Runtime JAR files in the classpath have the version $actualRuntimeVersion, " +
|
||||
"which is older than the API version $apiVersion. " +
|
||||
"Consider removing them from the classpath or passing '-api-version ${consistency.actualRuntimeVersion}' explicitly. " +
|
||||
"You can also pass '-language-version ${consistency.actualRuntimeVersion}' instead, which will restrict " +
|
||||
"Consider using the runtime of version $apiVersion, or pass '-api-version $actualRuntimeVersion' explicitly to " +
|
||||
"restrict the available APIs to the runtime of version $actualRuntimeVersion. " +
|
||||
"You can also pass '-language-version $actualRuntimeVersion' instead, which will restrict " +
|
||||
"not only the APIs to the specified version, but also the language features. " +
|
||||
"Alternatively, you can use '-Xskip-runtime-version-check' to suppress this warning"
|
||||
else ->
|
||||
)
|
||||
|
||||
val actualApi = ApiVersion.parse(actualRuntimeVersion.toString())
|
||||
if (actualApi != null) {
|
||||
val newSettings = if (languageVersionSettings == null) {
|
||||
LanguageVersionSettingsImpl(
|
||||
LanguageVersionSettingsImpl.DEFAULT.languageVersion,
|
||||
actualApi,
|
||||
listOf(LanguageFeature.WarnOnCoroutines)
|
||||
)
|
||||
}
|
||||
else {
|
||||
val inferredApiVersion =
|
||||
if (@Suppress("DEPRECATION") languageVersionSettings.isApiVersionExplicit)
|
||||
languageVersionSettings.apiVersion
|
||||
else
|
||||
minOf(languageVersionSettings.apiVersion, actualApi)
|
||||
|
||||
// "minOf" is needed in case when API version was inferred from language version and it's older than actualApi.
|
||||
// For example, in "kotlinc-1.2 -language-version 1.0 -cp kotlin-runtime-1.1.jar" we should still infer API = 1.0
|
||||
LanguageVersionSettingsImpl(
|
||||
languageVersionSettings.languageVersion,
|
||||
inferredApiVersion,
|
||||
languageVersionSettings.additionalFeatures,
|
||||
isApiVersionExplicit = false
|
||||
)
|
||||
}
|
||||
|
||||
messageCollector.issue(null, "Old runtime has been found in the classpath. " +
|
||||
"Initial language version settings: $languageVersionSettings. " +
|
||||
"Updated language version settings: $newSettings", CompilerMessageSeverity.LOGGING)
|
||||
|
||||
configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, newSettings)
|
||||
}
|
||||
else {
|
||||
messageCollector.issue(null, "Could not parse runtime JAR version: $actualRuntimeVersion")
|
||||
}
|
||||
}
|
||||
else if (consistency != ClasspathConsistency.Consistent) {
|
||||
messageCollector.issue(
|
||||
null,
|
||||
"Some runtime JAR files in the classpath have an incompatible version. " +
|
||||
"Consider removing them from the classpath or use '-Xskip-runtime-version-check' to suppress this warning"
|
||||
}
|
||||
messageCollector.issue(null, message)
|
||||
)
|
||||
}
|
||||
|
||||
val librariesWithBundled = runtimeJarsInfo.otherLibrariesWithBundledRuntime
|
||||
|
||||
@@ -159,7 +159,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
if (messageCollector != null) {
|
||||
JvmRuntimeVersionsConsistencyChecker.checkCompilerClasspathConsistency(
|
||||
messageCollector,
|
||||
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS),
|
||||
configuration,
|
||||
initialRoots.mapNotNull { (file, type) -> if (type == JavaRoot.RootType.BINARY) file else null }
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user