Report pre-release errors if release LV is used

#KT-21267 Fixed
This commit is contained in:
Alexander Udalov
2017-11-15 12:50:23 +01:00
parent 64a8008a8a
commit d386712903
15 changed files with 80 additions and 26 deletions
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.shouldWritePreReleaseFlag import org.jetbrains.kotlin.config.isPreRelease
import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
@@ -63,7 +63,7 @@ fun JvmBuildMetaInfo(args: CommonCompilerArguments): JvmBuildMetaInfo {
val languageVersion = args.languageVersion?.let((LanguageVersion)::fromVersionString) ?: LanguageVersion.LATEST_STABLE val languageVersion = args.languageVersion?.let((LanguageVersion)::fromVersionString) ?: LanguageVersion.LATEST_STABLE
return JvmBuildMetaInfo( return JvmBuildMetaInfo(
isEAP = languageVersion.shouldWritePreReleaseFlag(), isEAP = languageVersion.isPreRelease(),
compilerBuildVersion = KotlinCompilerVersion.VERSION, compilerBuildVersion = KotlinCompilerVersion.VERSION,
languageVersionString = languageVersion.versionString, languageVersionString = languageVersion.versionString,
apiVersionString = args.apiVersion ?: ApiVersion.LATEST_STABLE.versionString, apiVersionString = args.apiVersion ?: ApiVersion.LATEST_STABLE.versionString,
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.codegen package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.shouldWritePreReleaseFlag import org.jetbrains.kotlin.config.isPreRelease
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
@@ -36,7 +36,7 @@ fun writeKotlinMetadata(
av.visit(JvmAnnotationNames.BYTECODE_VERSION_FIELD_NAME, JvmBytecodeBinaryVersion.INSTANCE.toArray()) av.visit(JvmAnnotationNames.BYTECODE_VERSION_FIELD_NAME, JvmBytecodeBinaryVersion.INSTANCE.toArray())
av.visit(JvmAnnotationNames.KIND_FIELD_NAME, kind.id) av.visit(JvmAnnotationNames.KIND_FIELD_NAME, kind.id)
var flags = extraFlags var flags = extraFlags
if (state.languageVersionSettings.shouldWritePreReleaseFlag()) { if (state.languageVersionSettings.isPreRelease()) {
flags = flags or JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG flags = flags or JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG
} }
if (flags != 0) { if (flags != 0) {
@@ -19,12 +19,13 @@ package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.config.AnalysisFlag import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isPreRelease
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
class CompilerDeserializationConfiguration(languageVersionSettings: LanguageVersionSettings) : DeserializationConfiguration { class CompilerDeserializationConfiguration(languageVersionSettings: LanguageVersionSettings) : DeserializationConfiguration {
override val skipMetadataVersionCheck = languageVersionSettings.getFlag(AnalysisFlag.skipMetadataVersionCheck) override val skipMetadataVersionCheck = languageVersionSettings.getFlag(AnalysisFlag.skipMetadataVersionCheck)
override val skipPreReleaseCheck = skipMetadataVersionCheck || !languageVersionSettings.languageVersion.isStable override val reportErrorsOnPreReleaseDependencies = !skipMetadataVersionCheck && !languageVersionSettings.isPreRelease()
override val typeAliasesAllowed = languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases) override val typeAliasesAllowed = languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases)
@@ -0,0 +1,5 @@
package a
class A
fun A.foo() = ""
@@ -0,0 +1,7 @@
package usage
import a.*
fun baz(param: A) {
param.foo()
}
@@ -0,0 +1,8 @@
error: incompatible classes were found in dependencies. Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors
compiler/testData/compileKotlinAgainstCustomBinaries/preReleaseCompilerAgainstPreReleaseLibraryStableLanguageVersion/source.kt:5:16: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
fun baz(param: A) {
^
compiler/testData/compileKotlinAgainstCustomBinaries/preReleaseCompilerAgainstPreReleaseLibraryStableLanguageVersion/source.kt:6:5: error: class 'a.AKt' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
foo()
^
COMPILATION_ERROR
@@ -0,0 +1,7 @@
package usage
import a.*
fun baz(param: A) {
foo()
}
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.codegen.inline.remove
import org.jetbrains.kotlin.codegen.optimization.common.asSequence import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.intConstant import org.jetbrains.kotlin.codegen.optimization.common.intConstant
import org.jetbrains.kotlin.config.KotlinCompilerVersion.TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY import org.jetbrains.kotlin.config.KotlinCompilerVersion.TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
@@ -131,27 +132,28 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
) { ) {
// Compiles the library with the "pre-release" flag, then compiles a usage of this library in the release mode // Compiles the library with the "pre-release" flag, then compiles a usage of this library in the release mode
val result = try { val result = withPreRelease(true) {
System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "true")
when (compiler) { when (compiler) {
is K2JSCompiler -> compileJsLibrary(libraryName) is K2JSCompiler -> compileJsLibrary(libraryName)
is K2JVMCompiler -> compileLibrary(libraryName) is K2JVMCompiler -> compileLibrary(libraryName)
else -> throw UnsupportedOperationException(compiler.toString()) else -> throw UnsupportedOperationException(compiler.toString())
} }
} }
finally {
System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY)
}
try { withPreRelease(false) {
System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "false")
compileKotlin("source.kt", usageDestination, listOf(result), compiler, additionalOptions.toList()) compileKotlin("source.kt", usageDestination, listOf(result), compiler, additionalOptions.toList())
} }
finally {
System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY)
}
} }
private fun <T> withPreRelease(value: Boolean, block: () -> T): T =
try {
System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, value.toString())
block()
}
finally {
System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY)
}
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
fun testRawTypes() { fun testRawTypes() {
@@ -258,6 +260,23 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
doTestPreReleaseKotlinLibrary(K2JSCompiler(), "library", File(tmpdir, "usage.js"), "-Xskip-metadata-version-check") doTestPreReleaseKotlinLibrary(K2JSCompiler(), "library", File(tmpdir, "usage.js"), "-Xskip-metadata-version-check")
} }
fun testPreReleaseCompilerAgainstPreReleaseLibraryStableLanguageVersion() {
withPreRelease(true) {
val library = compileLibrary("library")
val someStableReleasedVersion = LanguageVersion.values().first().also { assert(it.isStable) }
compileKotlin("source.kt", tmpdir, listOf(library), K2JVMCompiler(),
listOf("-language-version", someStableReleasedVersion.versionString))
}
}
fun testPreReleaseCompilerAgainstPreReleaseLibraryLatestStable() {
withPreRelease(true) {
val library = compileLibrary("library")
compileKotlin("source.kt", tmpdir, listOf(library), K2JVMCompiler(),
listOf("-language-version", LanguageVersion.LATEST_STABLE.versionString))
}
}
fun testWrongMetadataVersion() { fun testWrongMetadataVersion() {
doTestKotlinLibraryWithWrongMetadataVersion("library", null) doTestKotlinLibraryWithWrongMetadataVersion("library", null)
} }
@@ -189,10 +189,10 @@ class LanguageVersionSettingsImpl @JvmOverloads constructor(
} }
} }
fun LanguageVersionSettings.shouldWritePreReleaseFlag(): Boolean = fun LanguageVersionSettings.isPreRelease(): Boolean =
languageVersion.shouldWritePreReleaseFlag() languageVersion.isPreRelease()
fun LanguageVersion.shouldWritePreReleaseFlag(): Boolean { fun LanguageVersion.isPreRelease(): Boolean {
if (!isStable) return true if (!isStable) return true
return KotlinCompilerVersion.isPreRelease() && this == LanguageVersion.LATEST_STABLE return KotlinCompilerVersion.isPreRelease() && this == LanguageVersion.LATEST_STABLE
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.load.kotlin package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
@@ -75,9 +74,12 @@ class DeserializedDescriptorResolver {
return IncompatibleVersionErrorData(classHeader.metadataVersion, JvmMetadataVersion.INSTANCE, location, classId) return IncompatibleVersionErrorData(classHeader.metadataVersion, JvmMetadataVersion.INSTANCE, location, classId)
} }
/**
* @return true if the class is invisible because it's compiled by a pre-release compiler, and this compiler is either released
* or is run with a released language version.
*/
private val KotlinJvmBinaryClass.isPreReleaseInvisible: Boolean private val KotlinJvmBinaryClass.isPreReleaseInvisible: Boolean
get() = !components.configuration.skipPreReleaseCheck && get() = components.configuration.reportErrorsOnPreReleaseDependencies &&
!KotlinCompilerVersion.isPreRelease() &&
(classHeader.isPreRelease || classHeader.metadataVersion == KOTLIN_1_1_EAP_METADATA_VERSION) (classHeader.isPreRelease || classHeader.metadataVersion == KOTLIN_1_1_EAP_METADATA_VERSION)
internal fun readData(kotlinClass: KotlinJvmBinaryClass, expectedKinds: Set<KotlinClassHeader.Kind>): Array<String>? { internal fun readData(kotlinClass: KotlinJvmBinaryClass, expectedKinds: Set<KotlinClassHeader.Kind>): Array<String>? {
@@ -20,7 +20,7 @@ interface DeserializationConfiguration {
val skipMetadataVersionCheck: Boolean val skipMetadataVersionCheck: Boolean
get() = false get() = false
val skipPreReleaseCheck: Boolean val reportErrorsOnPreReleaseDependencies: Boolean
get() = false get() = false
val typeAliasesAllowed: Boolean val typeAliasesAllowed: Boolean
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.serialization.js package org.jetbrains.kotlin.serialization.js
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
@@ -80,7 +79,7 @@ class KotlinJavascriptPackageFragment(
get() = null get() = null
override val isPreReleaseInvisible: Boolean = override val isPreReleaseInvisible: Boolean =
!configuration.skipPreReleaseCheck && (header.flags and 1) != 0 && !KotlinCompilerVersion.isPreRelease() configuration.reportErrorsOnPreReleaseDependencies && (header.flags and 1) != 0
override val presentableString: String override val presentableString: String
get() = "Package '$fqName'" get() = "Package '$fqName'"
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.serialization.js package org.jetbrains.kotlin.serialization.js
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.shouldWritePreReleaseFlag import org.jetbrains.kotlin.config.isPreRelease
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -243,7 +243,7 @@ object KotlinJavascriptSerializationUtil {
header.packageFqName = packageFqName.asString() header.packageFqName = packageFqName.asString()
} }
if (languageVersionSettings.shouldWritePreReleaseFlag()) { if (languageVersionSettings.isPreRelease()) {
header.flags = 1 header.flags = 1
} }