Separate JVM target option from javac's --enable-preview analogue

This commit is contained in:
Denis.Zharkov
2020-12-04 19:04:14 +03:00
parent 3abd8b1ab2
commit 46c3979acd
18 changed files with 73 additions and 39 deletions
@@ -272,7 +272,10 @@ class GenerationState private constructor(
val rootContext: CodegenContext<*> = RootContext(this)
val classFileVersion: Int = target.bytecodeVersion
val classFileVersion: Int = run {
val minorVersion = if (configuration.getBoolean(JVMConfigurationKeys.ENABLE_JVM_PREVIEW)) 0xffff else 0
(minorVersion shl 16) + target.majorVersion
}
val generateParametersMetadata: Boolean = configuration.getBoolean(JVMConfigurationKeys.PARAMETERS_METADATA)
@@ -418,6 +418,13 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
var useOldInlineClassesManglingScheme: Boolean by FreezableVar(false)
@Argument(
value = "-Xjvm-enable-preview",
description = "Allow using features from Java language that are in preview phase.\n" +
"Works as `--enable-preview` in Java. All class files are marked as preview-generated thus it won't be possible to use them in release environment"
)
var enableJvmPreview: Boolean by FreezableVar(false)
override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
val result = super.configureAnalysisFlags(collector)
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
@@ -67,19 +67,19 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
}
}
if (languageVersionSettings.supportsFeature(LanguageFeature.JvmRecordSupport) && !jvmTarget.isRecordsAllowed()) {
if (languageVersionSettings.supportsFeature(LanguageFeature.JvmRecordSupport) && !jvmTarget.areRecordsAllowed(arguments.enableJvmPreview)) {
messageCollector.report(
ERROR,
"-XXLanguage:+${LanguageFeature.JvmRecordSupport} feature is only supported with JVM target ${JvmTarget.JVM_15_PREVIEW.description} or later"
"-XXLanguage:+${LanguageFeature.JvmRecordSupport} feature is only supported with JVM target ${JvmTarget.JVM_15.description} or later"
)
}
addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, arguments.additionalJavaModules?.asList())
}
private fun JvmTarget.isRecordsAllowed(): Boolean {
if (majorVersion < JvmTarget.JVM_15_PREVIEW.majorVersion) return false
return isPreview || majorVersion > JvmTarget.JVM_15_PREVIEW.majorVersion
private fun JvmTarget.areRecordsAllowed(enableJvmPreview: Boolean): Boolean {
if (majorVersion < JvmTarget.JVM_15.majorVersion) return false
return enableJvmPreview || majorVersion > JvmTarget.JVM_15.majorVersion
}
fun CompilerConfiguration.configureJdkHome(arguments: K2JVMCompilerArguments): Boolean {
@@ -244,6 +244,12 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule)
put(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS, arguments.useOldSpilledVarTypeAnalysis)
put(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME, arguments.useOldInlineClassesManglingScheme)
put(JVMConfigurationKeys.ENABLE_JVM_PREVIEW, arguments.enableJvmPreview)
if (arguments.enableJvmPreview) {
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
.report(INFO, "Using preview Java language features")
}
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
}
@@ -140,4 +140,7 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> USE_OLD_INLINE_CLASSES_MANGLING_SCHEME =
CompilerConfigurationKey.create("Use old, 1.4 version of inline classes mangling scheme");
public static final CompilerConfigurationKey<Boolean> ENABLE_JVM_PREVIEW =
CompilerConfigurationKey.create("Enable Java language preview features");
}
@@ -22,8 +22,6 @@ import org.jetbrains.org.objectweb.asm.Opcodes
enum class JvmTarget(
override val description: String,
val majorVersion: Int,
val descriptionForJavacArgument: String = description,
val isPreview: Boolean = false,
) : TargetPlatformVersion {
JVM_1_6("1.6", Opcodes.V1_6),
JVM_1_8("1.8", Opcodes.V1_8),
@@ -34,22 +32,8 @@ enum class JvmTarget(
JVM_13("13", Opcodes.V13),
JVM_14("14", Opcodes.V14),
JVM_15("15", Opcodes.V15),
JVM_15_PREVIEW(
"15_PREVIEW", Opcodes.V15,
descriptionForJavacArgument = "15", isPreview = true
),
;
val minorVersion: Int =
if (isPreview)
0xffff
else
0
val bytecodeVersion: Int by lazy {
(minorVersion shl 16) + majorVersion
}
companion object {
@JvmField
val DEFAULT = JVM_1_6
@@ -57,14 +41,14 @@ enum class JvmTarget(
@JvmStatic
fun fromString(string: String) = values().find { it.description == string }
fun getDescription(bytecodeVersion: Int): String {
val platformDescription = values().find { it.bytecodeVersion == bytecodeVersion }?.description ?: when (bytecodeVersion) {
fun getDescription(majorVersion: Int): String {
val platformDescription = values().find { it.majorVersion == majorVersion }?.description ?: when (majorVersion) {
Opcodes.V1_7 -> "1.7"
else -> null
}
return if (platformDescription != null) "JVM target $platformDescription"
else "JVM bytecode version $bytecodeVersion"
else "JVM bytecode version $majorVersion"
}
}
}
+2
View File
@@ -22,6 +22,8 @@ where advanced options include:
-Xir-do-not-clear-binding-context
When using the IR backend, do not clear BindingContext between psi2ir and lowerings
-Xemit-jvm-type-annotations Emit JVM type annotations in bytecode
-Xjvm-enable-preview Allow using features from Java language that are in preview phase.
Works as `--enable-preview` in Java. All class files are marked as preview-generated thus it won't be possible to use them in release environment
-Xfriend-paths=<path> Paths to output directories for friend modules (whose internals should be visible)
-Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade
-Xir-check-local-names Check that names of local classes and anonymous objects are the same in the IR backend as in the old backend
+2 -1
View File
@@ -8,5 +8,6 @@ $TEMP_DIR$
-jdk-home
$JDK_15$
-XXLanguage:+JvmRecordSupport
-Xjvm-enable-preview
-jvm-target
15_PREVIEW
15
+2
View File
@@ -7,4 +7,6 @@ This mode is not recommended for production use,
as no stability/compatibility guarantees are given on
compiler or generated code. Use it at your own risk!
warning: language version 1.5 is experimental, there are no backwards compatibility guarantees for new language and library features
info: using preview Java language features
OK
+1 -1
View File
@@ -1,3 +1,3 @@
error: unknown JVM target version: 1.5
Supported versions: 1.6, 1.8, 9, 10, 11, 12, 13, 14, 15, 15_PREVIEW
Supported versions: 1.6, 1.8, 9, 10, 11, 12, 13, 14, 15
COMPILATION_ERROR
@@ -1,6 +1,7 @@
// !API_VERSION: 1.5
// !LANGUAGE: +JvmRecordSupport
// JVM_TARGET: 15_PREVIEW
// JVM_TARGET: 15
// ENABLE_JVM_PREVIEW
// FILE: JavaClass.java
public class JavaClass {
public static String box() {
@@ -1,6 +1,7 @@
// !API_VERSION: 1.5
// !LANGUAGE: +JvmRecordSupport
// JVM_TARGET: 15_PREVIEW
// JVM_TARGET: 15
// ENABLE_JVM_PREVIEW
@JvmRecord
data class MyRec<R>(val x: String, val y: R)
@@ -1,4 +1,5 @@
// JVM_TARGET: 15_PREVIEW
// JVM_TARGET: 15
// ENABLE_JVM_PREVIEW
// FILE: MyRec.java
public record MyRec(String name) implements KI {
public String getName() {
@@ -1,4 +1,5 @@
// JVM_TARGET: 15_PREVIEW
// JVM_TARGET: 15
// ENABLE_JVM_PREVIEW
// FILE: MyRec.java
public record MyRec(String name) {
public String getName() {
@@ -1,5 +1,6 @@
// !LANGUAGE: +JvmRecordSupport
// JVM_TARGET: 15_PREVIEW
// JVM_TARGET: 15
// ENABLE_JVM_PREVIEW
// FILE: MyRec.java
public record MyRec(String name) {}
@@ -1,6 +1,7 @@
// !API_VERSION: 1.5
// !LANGUAGE: +JvmRecordSupport
// JVM_TARGET: 15_PREVIEW
// JVM_TARGET: 15
// ENABLE_JVM_PREVIEW
// FILE: A.kt
@JvmRecord
data class MyRecord(val foo: String, val bar: String)
@@ -25,9 +25,16 @@ abstract class AbstractBlackBoxAgainstJavaCodegenTest : AbstractBlackBoxCodegenT
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
javaClassesOutputDirectory = writeJavaFiles(files)!!.let { directory ->
val jvmTargets = files.mapNotNullTo(mutableSetOf()) { it.directives["JVM_TARGET"]?.let((JvmTarget)::fromString) }
val enablePreview = files.any { it.directives.contains("ENABLE_JVM_PREVIEW") }
check(jvmTargets.size <= 1) { "Having different JVM_TARGETs for different files is not supported in this test." }
CodegenTestUtil.compileJava(
CodegenTestUtil.findJavaSourcesInDirectory(directory), emptyList(), extractJavacOptions(files, jvmTargets.firstOrNull())
CodegenTestUtil.findJavaSourcesInDirectory(directory),
emptyList(),
extractJavacOptions(
files,
jvmTargets.firstOrNull(),
enablePreview,
),
)
}
@@ -529,7 +529,11 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
updateJavaClasspath(javaClasspath);
javaClassesOutputDirectory = getJavaClassesOutputDirectory();
List<String> javacOptions = extractJavacOptions(files, configuration.get(JVMConfigurationKeys.JVM_TARGET));
List<String> javacOptions = extractJavacOptions(
files,
configuration.get(JVMConfigurationKeys.JVM_TARGET),
configuration.getBoolean(JVMConfigurationKeys.ENABLE_JVM_PREVIEW)
);
List<String> finalJavacOptions = prepareJavacOptions(javaClasspath, javacOptions, javaClassesOutputDirectory);
try {
@@ -551,15 +555,19 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
protected void updateJavaClasspath(@NotNull List<String> javaClasspath) {}
@NotNull
protected static List<String> extractJavacOptions(@NotNull List<TestFile> files, @Nullable JvmTarget kotlinTarget) {
protected static List<String> extractJavacOptions(
@NotNull List<TestFile> files,
@Nullable JvmTarget kotlinTarget,
boolean isJvmPreviewEnabled
) {
List<String> javacOptions = new ArrayList<>(0);
for (TestFile file : files) {
javacOptions.addAll(InTextDirectivesUtils.findListWithPrefixes(file.content, "// JAVAC_OPTIONS:"));
}
if (kotlinTarget != null && kotlinTarget.isPreview()) {
if (kotlinTarget != null && isJvmPreviewEnabled) {
javacOptions.add("--release");
javacOptions.add(kotlinTarget.getDescriptionForJavacArgument());
javacOptions.add(kotlinTarget.getDescription());
javacOptions.add("--enable-preview");
return javacOptions;
}
@@ -582,7 +590,7 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
if (JAVA_COMPILATION_TARGET != null && !javacOptions.contains("-target"))
return JAVA_COMPILATION_TARGET;
if (kotlinTarget != null && kotlinTarget.compareTo(JvmTarget.JVM_1_6) > 0)
return kotlinTarget.getDescriptionForJavacArgument();
return kotlinTarget.getDescription();
if (IS_SOURCE_6_STILL_SUPPORTED)
return "1.6";
return null;
@@ -227,6 +227,11 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
?: error("Unknown target: $targetString")
configuration.put(JVMConfigurationKeys.JVM_TARGET, jvmTarget)
}
if (directives.contains("ENABLE_JVM_PREVIEW")) {
configuration.put(JVMConfigurationKeys.ENABLE_JVM_PREVIEW, true)
}
val version = directives["LANGUAGE_VERSION"]
if (version != null) {
throw AssertionError(