Restore KotlinCompilerVersion.IS_PRE_RELEASE
This commit is a slightly modified revert of 4f29c113.
IS_PRE_RELEASE allows to make LATEST_STABLE version behave as
experimental when this flag is set to true.
The general goal is to prepare fix of KT-62058; after this commit
one can do it by changing IS_PRE_RELEASE flag to true.
The fix of KT-62058 is planned to be done during bootstrapping.
This preparation and the future fix are parts of umbrella KT-61951.
This commit is contained in:
committed by
Space Team
parent
850201a65c
commit
156097fe17
@@ -6,10 +6,7 @@
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.config.PluginClasspaths
|
||||
import org.jetbrains.kotlin.config.PluginClasspathsComparator
|
||||
import org.jetbrains.kotlin.config.*
|
||||
|
||||
abstract class BuildMetaInfo {
|
||||
enum class CustomKeys {
|
||||
@@ -74,7 +71,7 @@ abstract class BuildMetaInfo {
|
||||
val languageVersionSting = languageVersion.versionString
|
||||
resultMap[CustomKeys.LANGUAGE_VERSION_STRING.name] = languageVersionSting
|
||||
|
||||
val isEAP = !languageVersion.isStable
|
||||
val isEAP = languageVersion.isPreRelease()
|
||||
resultMap[CustomKeys.IS_EAP.name] = isEAP.toString()
|
||||
|
||||
val apiVersionString = args.apiVersion ?: languageVersionSting
|
||||
|
||||
@@ -15,6 +15,23 @@ public class KotlinCompilerVersion {
|
||||
public static final String VERSION_FILE_PATH = "/META-INF/compiler.version";
|
||||
public static final String VERSION;
|
||||
|
||||
// True if the latest stable language version supported by this compiler has not yet been released.
|
||||
// Binaries produced by this compiler with that language version (or any future language version) are going to be marked
|
||||
// as "pre-release" and will not be loaded by release versions of the compiler.
|
||||
// Change this value before and after every major release
|
||||
private static final boolean IS_PRE_RELEASE = false;
|
||||
|
||||
public static final String TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY = "kotlin.test.is.pre.release";
|
||||
|
||||
public static boolean isPreRelease() {
|
||||
String overridden = System.getProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY);
|
||||
if (overridden != null) {
|
||||
return Boolean.parseBoolean(overridden);
|
||||
}
|
||||
|
||||
return IS_PRE_RELEASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return version of this compiler, or `null` if it isn't known (if VERSION is "@snapshot@")
|
||||
*/
|
||||
@@ -41,5 +58,12 @@ public class KotlinCompilerVersion {
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to read compiler version from " + VERSION_FILE_PATH);
|
||||
}
|
||||
|
||||
if (!VERSION.equals("@snapshot@") && !VERSION.contains("-") && IS_PRE_RELEASE) {
|
||||
throw new IllegalStateException(
|
||||
"IS_PRE_RELEASE cannot be true for a compiler without '-' in its version.\n" +
|
||||
"Please change IS_PRE_RELEASE to false, commit and push this change to master"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.java.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
|
||||
@@ -60,8 +61,9 @@ class JvmClassFileBasedSymbolProvider(
|
||||
private val annotationsLoader = AnnotationsLoader(session, kotlinClassFinder)
|
||||
private val ownMetadataVersion: JvmMetadataVersion = session.languageVersionSettings.languageVersion.toMetadataVersion()
|
||||
|
||||
private val reportErrorsOnPreReleaseDependencies =
|
||||
!session.languageVersionSettings.getFlag(AnalysisFlags.skipPrereleaseCheck) && !session.languageVersionSettings.isPreRelease()
|
||||
private val reportErrorsOnPreReleaseDependencies = with(session.languageVersionSettings) {
|
||||
!getFlag(AnalysisFlags.skipPrereleaseCheck) && !isPreRelease() && !KotlinCompilerVersion.isPreRelease()
|
||||
}
|
||||
|
||||
override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> =
|
||||
packagePartProvider.findPackageParts(packageFqName.asString()).mapNotNull { partName ->
|
||||
|
||||
+5
-2
@@ -5,7 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
|
||||
open class CompilerDeserializationConfiguration(
|
||||
@@ -17,7 +20,7 @@ open class CompilerDeserializationConfiguration(
|
||||
final override val skipPrereleaseCheck = languageVersionSettings.getFlag(AnalysisFlags.skipPrereleaseCheck)
|
||||
|
||||
final override val reportErrorsOnPreReleaseDependencies =
|
||||
!skipPrereleaseCheck && !languageVersionSettings.isPreRelease()
|
||||
!skipPrereleaseCheck && !languageVersionSettings.isPreRelease() && !KotlinCompilerVersion.isPreRelease()
|
||||
|
||||
final override val allowUnstableDependencies = languageVersionSettings.getFlag(AnalysisFlags.allowUnstableDependencies)
|
||||
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package a
|
||||
|
||||
class A
|
||||
|
||||
fun A.foo() = ""
|
||||
+1
@@ -0,0 +1 @@
|
||||
OK
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package usage
|
||||
|
||||
import a.*
|
||||
|
||||
fun baz(param: A) {
|
||||
param.foo()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package a
|
||||
|
||||
class A
|
||||
|
||||
fun foo() = ""
|
||||
+1
@@ -0,0 +1 @@
|
||||
OK
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package usage
|
||||
|
||||
import a.*
|
||||
|
||||
fun baz(param: A): A {
|
||||
foo()
|
||||
return param
|
||||
}
|
||||
+1
-1
@@ -37,7 +37,7 @@ data class CompilerTestLanguageVersionSettings(
|
||||
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State =
|
||||
extraLanguageFeatures[feature] ?: delegate.getFeatureSupport(feature)
|
||||
|
||||
override fun isPreRelease(): Boolean = false
|
||||
override fun isPreRelease(): Boolean = KotlinCompilerVersion.isPreRelease()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T> getFlag(flag: AnalysisFlag<T>): T = analysisFlags[flag] as T? ?: flag.defaultValue
|
||||
|
||||
+82
-1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.jvm.compiler
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.js.K2JSCompiler
|
||||
@@ -16,6 +17,8 @@ import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler
|
||||
import org.jetbrains.kotlin.cli.transformMetadataInClassFile
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
@@ -25,6 +28,7 @@ import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.MockLibraryUtil
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import org.jetbrains.kotlin.utils.toMetadataVersion
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.ClassNode
|
||||
@@ -128,6 +132,14 @@ abstract class AbstractCompileKotlinAgainstCustomBinariesTest : AbstractKotlinCo
|
||||
compileKotlin("source.kt", usageDestination, listOf(result), compiler, additionalOptions.toList())
|
||||
}
|
||||
|
||||
private fun <T> withPreRelease(block: () -> T): T =
|
||||
try {
|
||||
System.setProperty(KotlinCompilerVersion.TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "true")
|
||||
block()
|
||||
} finally {
|
||||
System.clearProperty(KotlinCompilerVersion.TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
// KT-62043
|
||||
@@ -265,6 +277,31 @@ abstract class AbstractCompileKotlinAgainstCustomBinariesTest : AbstractKotlinCo
|
||||
doTestPreReleaseKotlinLibrary(K2JVMCompiler(), "library", tmpdir, "-Xskip-metadata-version-check")
|
||||
}
|
||||
|
||||
fun testPreReleaseCompilerAgainstPreReleaseLibraryStableLanguageVersion() {
|
||||
withPreRelease {
|
||||
val library = compileLibrary("library")
|
||||
val someStableReleasedVersion = LanguageVersion.entries.first { it.isStable && it >= LanguageVersion.FIRST_NON_DEPRECATED }
|
||||
compileKotlin(
|
||||
"source.kt", tmpdir, listOf(library), K2JVMCompiler(),
|
||||
listOf("-language-version", someStableReleasedVersion.versionString)
|
||||
)
|
||||
|
||||
checkPreReleaseness(File(tmpdir, "usage/SourceKt.class"), shouldBePreRelease = false)
|
||||
}
|
||||
}
|
||||
|
||||
fun testPreReleaseCompilerAgainstPreReleaseLibraryLatestStable() {
|
||||
withPreRelease {
|
||||
val library = compileLibrary("library")
|
||||
compileKotlin(
|
||||
"source.kt", tmpdir, listOf(library), K2JVMCompiler(),
|
||||
listOf("-language-version", LanguageVersion.LATEST_STABLE.versionString)
|
||||
)
|
||||
|
||||
checkPreReleaseness(File(tmpdir, "usage/SourceKt.class"), shouldBePreRelease = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun testReleaseCompilerAgainstPreReleaseLibrarySkipPrereleaseCheckAllowUnstableDependencies() {
|
||||
doTestPreReleaseKotlinLibrary(K2JVMCompiler(), "library", tmpdir, "-Xallow-unstable-dependencies", "-Xskip-prerelease-check")
|
||||
}
|
||||
@@ -671,6 +708,25 @@ abstract class AbstractCompileKotlinAgainstCustomBinariesTest : AbstractKotlinCo
|
||||
assertEquals("Output:\n$output", ExitCode.COMPILATION_ERROR, exitCode)
|
||||
}
|
||||
|
||||
// If this test fails, then bootstrap compiler most likely should be advanced
|
||||
fun testPreReleaseFlagIsConsistentBetweenBootstrapAndCurrentCompiler() {
|
||||
val bootstrapCompiler = JarFile(PathUtil.kotlinPathsForCompiler.compilerPath)
|
||||
val classFromBootstrapCompiler = bootstrapCompiler.getEntry(LanguageFeature::class.java.name.replace(".", "/") + ".class")
|
||||
checkPreReleaseness(
|
||||
bootstrapCompiler.getInputStream(classFromBootstrapCompiler).readBytes(),
|
||||
KotlinCompilerVersion.isPreRelease()
|
||||
)
|
||||
}
|
||||
|
||||
fun testPreReleaseFlagIsConsistentBetweenStdlibAndCurrentCompiler() {
|
||||
val stdlib = JarFile(PathUtil.kotlinPathsForCompiler.stdlibPath)
|
||||
val classFromStdlib = stdlib.getEntry(KotlinVersion::class.java.name.replace(".", "/") + ".class")
|
||||
checkPreReleaseness(
|
||||
stdlib.getInputStream(classFromStdlib).readBytes(),
|
||||
KotlinCompilerVersion.isPreRelease()
|
||||
)
|
||||
}
|
||||
|
||||
fun testAnonymousObjectTypeMetadata() {
|
||||
val library = compileCommonLibrary(
|
||||
libraryName = "library",
|
||||
@@ -696,7 +752,7 @@ abstract class AbstractCompileKotlinAgainstCustomBinariesTest : AbstractKotlinCo
|
||||
listOf("-Xmetadata-klib")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
protected fun copyJarFileWithoutEntry(jarPath: File, vararg entriesToDelete: String): File =
|
||||
@@ -729,4 +785,29 @@ abstract class AbstractCompileKotlinAgainstCustomBinariesTest : AbstractKotlinCo
|
||||
return outputFile
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPreReleaseness(classFileBytes: ByteArray, shouldBePreRelease: Boolean) {
|
||||
// If there's no "xi" field in the Metadata annotation, it's value is assumed to be 0, i.e. _not_ pre-release
|
||||
var isPreRelease = false
|
||||
|
||||
ClassReader(classFileBytes).accept(object : ClassVisitor(Opcodes.API_VERSION) {
|
||||
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
|
||||
if (desc != JvmAnnotationNames.METADATA_DESC) return null
|
||||
|
||||
return object : AnnotationVisitor(Opcodes.API_VERSION) {
|
||||
override fun visit(name: String, value: Any) {
|
||||
if (name != JvmAnnotationNames.METADATA_EXTRA_INT_FIELD_NAME) return
|
||||
|
||||
isPreRelease = (value as Int and JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG) != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0)
|
||||
|
||||
TestCase.assertEquals("Pre-release flag of the class file has incorrect value", shouldBePreRelease, isPreRelease)
|
||||
}
|
||||
|
||||
private fun checkPreReleaseness(file: File, shouldBePreRelease: Boolean) {
|
||||
checkPreReleaseness(file.readBytes(), shouldBePreRelease)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,7 +596,7 @@ class LanguageVersionSettingsImpl @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun isPreRelease(): Boolean = !languageVersion.isStable ||
|
||||
override fun isPreRelease(): Boolean = languageVersion.isPreRelease() ||
|
||||
specificFeatures.any { (feature, state) ->
|
||||
state == LanguageFeature.State.ENABLED && feature.forcesPreReleaseBinariesIfEnabled()
|
||||
}
|
||||
@@ -607,6 +607,12 @@ class LanguageVersionSettingsImpl @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun LanguageVersion.isPreRelease(): Boolean {
|
||||
if (!isStable) return true
|
||||
|
||||
return KotlinCompilerVersion.isPreRelease() && this == LanguageVersion.LATEST_STABLE
|
||||
}
|
||||
|
||||
fun LanguageFeature.forcesPreReleaseBinariesIfEnabled(): Boolean {
|
||||
val isFeatureNotReleasedYet = sinceVersion?.isStable != true
|
||||
return isFeatureNotReleasedYet && kind.forcesPreReleaseBinaries
|
||||
|
||||
Reference in New Issue
Block a user