Add new options for '-Xjvm-default'

This commit is contained in:
Mikhail Bogdanov
2020-04-01 08:30:27 +02:00
parent 7876d821a9
commit 0ddef7e4e4
4 changed files with 72 additions and 23 deletions
@@ -270,13 +270,31 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
@Argument(
value = "-Xjvm-default",
valueDescription = "{disable|enable|compatibility}",
description = "Allow to use '@JvmDefault' annotation for JVM default method support.\n" +
"-Xjvm-default=disable Prohibit usages of @JvmDefault\n" +
"-Xjvm-default=enable Allow usages of @JvmDefault; only generate the default method\n" +
" in the interface (annotating an existing method can break binary compatibility)\n" +
"-Xjvm-default=compatibility Allow usages of @JvmDefault; generate a compatibility accessor\n" +
" in the 'DefaultImpls' class in addition to the interface method"
valueDescription = "{all|all-compatibility|disable|enable|compatibility}",
description = """Emit JVM default methods for interface declarations with bodies.
-Xjvm-default=all-compatibility Generate both a default method in the interface, and a compatibility accessor
in the DefaultImpls class.
In case of inheritance from a Kotlin interface compiled in the old scheme
(DefaultImpls, no default methods), the compatibility accessor in DefaultImpls
will delegate to the DefaultImpls method of the superinterface. Otherwise the
compatibility accessor will invoke the default method on the interface, with
standard JVM runtime resolution semantics.
Note that if interface delegation is used, all interface methods are delegated.
The only exception are methods annotated with the deprecated @JvmDefault annotation.
-Xjvm-default=all Generate default methods for all interface declarations with bodies.
Do not generate DefaultImpls classes at all.
BREAKS BINARY COMPATIBILITY if some client code relies on the presence of
DefaultImpls classes. Also prohibits the produced binaries to be read by Kotlin
compilers earlier than 1.4.
Note that if interface delegation is used, all interface methods are delegated.
The only exception are methods annotated with the deprecated @JvmDefault annotation.
-Xjvm-default=disable Do not generate JVM default methods and prohibit @JvmDefault annotation usage.
The following modes are DEPRECATED:
-Xjvm-default=enable Allow usages of @JvmDefault; only generate the default method
for annotated method in the interface
(annotating an existing method can break binary compatibility)
-Xjvm-default=compatibility Allow usages of @JvmDefault; generate a compatibility accessor
in the 'DefaultImpls' class in addition to the default interface method"""
)
var jvmDefault: String by FreezableVar(JvmDefaultMode.DEFAULT.description)
@@ -337,12 +355,19 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
supportCompatqualCheckerFrameworkAnnotations
)
result[AnalysisFlags.ignoreDataFlowInAssert] = JVMAssertionsMode.fromString(assertionsMode) != JVMAssertionsMode.LEGACY
JvmDefaultMode.fromStringOrNull(jvmDefault)?.let { result[JvmAnalysisFlags.jvmDefaultMode] = it }
?: collector.report(
CompilerMessageSeverity.ERROR,
"Unknown @JvmDefault mode: $jvmDefault, " +
"supported modes: ${JvmDefaultMode.values().map { it.description }}"
)
JvmDefaultMode.fromStringOrNull(jvmDefault)?.let {
result[JvmAnalysisFlags.jvmDefaultMode] = it
if (it == JvmDefaultMode.ENABLE || it == JvmDefaultMode.ENABLE_WITH_DEFAULT_IMPLS) {
collector.report(
CompilerMessageSeverity.WARNING,
"'-Xjvm-default=$jvmDefault' mode is deprecated. Please considering to switch to new modes: 'all' and 'all-compatibility'"
)
}
} ?: collector.report(
CompilerMessageSeverity.ERROR,
"Unknown @JvmDefault mode: $jvmDefault, " +
"supported modes: ${JvmDefaultMode.values().map { it.description }}"
)
result[JvmAnalysisFlags.inheritMultifileParts] = inheritMultifileParts
result[JvmAnalysisFlags.sanitizeParentheses] = sanitizeParentheses
result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError
@@ -108,9 +108,6 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<List<String>> ADDITIONAL_JAVA_MODULES =
CompilerConfigurationKey.create("additional Java modules");
public static final CompilerConfigurationKey<Boolean> ENABLE_JVM_DEFAULT =
CompilerConfigurationKey.create("Allow to use '@JvmDefault'");
public static final CompilerConfigurationKey<Boolean> EMIT_JVM_TYPE_ANNOTATIONS =
CompilerConfigurationKey.create("Emit JVM type annotations in bytecode");
+26 -7
View File
@@ -38,13 +38,32 @@ where advanced options include:
* ignore
* strict (experimental; treat as other supported nullability annotations)
* warn (report a warning)
-Xjvm-default={disable|enable|compatibility}
Allow to use '@JvmDefault' annotation for JVM default method support.
-Xjvm-default=disable Prohibit usages of @JvmDefault
-Xjvm-default=enable Allow usages of @JvmDefault; only generate the default method
in the interface (annotating an existing method can break binary compatibility)
-Xjvm-default=compatibility Allow usages of @JvmDefault; generate a compatibility accessor
in the 'DefaultImpls' class in addition to the interface method
-Xjvm-default={all|all-compatibility|disable|enable|compatibility}
Emit JVM default methods for interface declarations with bodies.
-Xjvm-default=all-compatibility Generate both a default method in the interface, and a compatibility accessor
in the DefaultImpls class.
In case of inheritance from a Kotlin interface compiled in the old scheme
(DefaultImpls, no default methods), the compatibility accessor in DefaultImpls
will delegate to the DefaultImpls method of the superinterface. Otherwise the
compatibility accessor will invoke the default method on the interface, with
standard JVM runtime resolution semantics.
Note that if interface delegation is used, all interface methods are delegated.
The only exception are methods annotated with the deprecated @JvmDefault annotation.
-Xjvm-default=all Generate default methods for all interface declarations with bodies.
Do not generate DefaultImpls classes at all.
BREAKS BINARY COMPATIBILITY if some client code relies on the presence of
DefaultImpls classes. Also prohibits the produced binaries to be read by Kotlin
compilers earlier than 1.4.
Note that if interface delegation is used, all interface methods are delegated.
The only exception are methods annotated with the deprecated @JvmDefault annotation.
-Xjvm-default=disable Do not generate JVM default methods and prohibit @JvmDefault annotation usage.
The following modes are DEPRECATED:
-Xjvm-default=enable Allow usages of @JvmDefault; only generate the default method
for annotated method in the interface
(annotating an existing method can break binary compatibility)
-Xjvm-default=compatibility Allow usages of @JvmDefault; generate a compatibility accessor
in the 'DefaultImpls' class in addition to the default interface method
-Xklib=<path> Paths to cross-platform libraries in .klib format
-Xno-call-assertions Don't generate not-null assertions for arguments of platform types
-Xno-exception-on-explicit-equals-for-boxed-null
@@ -9,6 +9,7 @@ import kotlin.internal.RequireKotlin
import kotlin.internal.RequireKotlinVersionKind
/**
*
* Specifies that a JVM default method should be generated for non-abstract Kotlin interface member.
*
* Usages of this annotation require an explicit compilation argument to be specified:
@@ -26,6 +27,13 @@ import kotlin.internal.RequireKotlinVersionKind
* Generation of default methods is only possible with JVM target bytecode version 1.8 (`-jvm-target 1.8`) or higher.
*
* @[JvmDefault] methods are excluded from interface delegation.
*
* #
* This annotation is **deprecated** in favor of new compiler arguments `-Xjvm-default=all-compatibility` and `-Xjvm-default=all`.
* The new arguments allow all interface methods with bodies to be generated as JVM default methods on JVM target 1.8+.
* Please refer to the [official documentation](https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#default-methods-in-interfaces)
* for more information.
*
*/
@SinceKotlin("1.2")
@RequireKotlin("1.2.40", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)