Add support of internal arguments for language feature settings
Arguments are passed in form '-XXLanguage:+LanguageFeatureName' for enabling
LanguageFeature.LanguageFeatureName, and '-XXLanguage:-LanguageFeatureName'
for disabling.
Note that they do override other settings, including 'language-version'
or extra ('-X') args.
This commit is contained in:
+26
@@ -230,8 +230,34 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
if (!contains(it)) put(it, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
}
|
||||
|
||||
// Internal arguments should go last, because it may be useful to override
|
||||
// some feature state via -XX (even if some -X flags were passed)
|
||||
if (internalArguments.isNotEmpty()) {
|
||||
configureLanguageFeaturesFromInternalArgs(collector)
|
||||
}
|
||||
}
|
||||
|
||||
private fun HashMap<LanguageFeature, LanguageFeature.State>.configureLanguageFeaturesFromInternalArgs(collector: MessageCollector) {
|
||||
val languageSettingsParser = LanguageSettingsParser()
|
||||
val featuresThatForcePreReleaseBinaries = mutableListOf<LanguageFeature>()
|
||||
|
||||
for (argument in internalArguments) {
|
||||
val (feature, state) = languageSettingsParser.parseInternalArgument(argument, collector) ?: continue
|
||||
put(feature, state)
|
||||
if (state == LanguageFeature.State.ENABLED && feature.forcesPreReleaseBinariesIfEnabled()) {
|
||||
featuresThatForcePreReleaseBinaries += feature
|
||||
}
|
||||
}
|
||||
|
||||
if (featuresThatForcePreReleaseBinaries.isNotEmpty()) {
|
||||
collector.report(
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"Following manually enabled features will force generation of pre-release binaries: ${featuresThatForcePreReleaseBinaries.joinToString()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun configureLanguageVersionSettings(collector: MessageCollector): LanguageVersionSettings {
|
||||
|
||||
// If only "-api-version" is specified, language version is assumed to be the latest stable
|
||||
|
||||
+2
@@ -49,4 +49,6 @@ abstract class CommonToolArguments : Freezable(), Serializable {
|
||||
@GradleOption(DefaultValues.BooleanFalseDefault::class)
|
||||
@Argument(value = "-Werror", description = "Report an error if there are any warnings")
|
||||
var allWarningsAsErrors: Boolean by FreezableVar(false)
|
||||
|
||||
var internalArguments: List<String> by FreezableVar(emptyList())
|
||||
}
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.arguments
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.InternalArgumentParser.Companion.INTERNAL_ARGUMENT_PREFIX
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
|
||||
/**
|
||||
* Arguments that can drastically change compiler behavior,
|
||||
* breaking stability/compatibility.
|
||||
*
|
||||
* Internal arguments are split into 'families', each family
|
||||
* with its own set of arguments, settings and parsing rules
|
||||
*
|
||||
* Internal arguments start with '-XX' prefix, followed by
|
||||
* family name. Everything after that is handled by the corresponding
|
||||
* parser of that particular family.
|
||||
*/
|
||||
interface InternalArgumentParser<A : InternalArgument> {
|
||||
// Should be fast
|
||||
fun canParse(arg: String): Boolean
|
||||
|
||||
fun parseInternalArgument(arg: String, messageCollector: MessageCollector): A?
|
||||
|
||||
companion object {
|
||||
internal const val INTERNAL_ARGUMENT_PREFIX = "-XX"
|
||||
|
||||
internal val PARSERS: List<InternalArgumentParser<*>> = listOf(
|
||||
LanguageSettingsParser()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractInternalArgumentParser<A : InternalArgument>(familyName: String) : InternalArgumentParser<A> {
|
||||
private val wholePrefix: String = INTERNAL_ARGUMENT_PREFIX + familyName
|
||||
|
||||
override fun canParse(arg: String): Boolean = arg.startsWith(wholePrefix)
|
||||
|
||||
override fun parseInternalArgument(arg: String, messageCollector: MessageCollector): A? {
|
||||
if (!arg.startsWith(wholePrefix)) return null
|
||||
|
||||
return parseTail(arg.removePrefix(wholePrefix), arg, messageCollector)
|
||||
}
|
||||
|
||||
abstract fun parseTail(tail: String, wholeArgument: String, messageCollector: MessageCollector): A?
|
||||
}
|
||||
|
||||
|
||||
// Arguments of form '-XXLanguage:+LanguageFeature' or '-XXLanguage:-LanguageFeature', which enable or disable corresponding LanguageFeature.
|
||||
class LanguageSettingsParser : AbstractInternalArgumentParser<ManualLanguageFeatureSetting>("Language") {
|
||||
|
||||
// Expected tail form: ':(+|-)<language feature name>'
|
||||
override fun parseTail(tail: String, wholeArgument: String, messageCollector: MessageCollector): ManualLanguageFeatureSetting? {
|
||||
fun reportAndReturnNull(message: String): Nothing? {
|
||||
messageCollector.report(CompilerMessageSeverity.STRONG_WARNING, message)
|
||||
return null
|
||||
}
|
||||
|
||||
val colon = tail.getOrNull(0) ?: return reportAndReturnNull("Incorrect internal argument syntax, missing colon: $wholeArgument")
|
||||
|
||||
val modificator = tail.getOrNull(1)
|
||||
val languageFeatureState = when (modificator) {
|
||||
'+' -> LanguageFeature.State.ENABLED
|
||||
|
||||
'-' -> LanguageFeature.State.DISABLED
|
||||
|
||||
else -> return reportAndReturnNull("Incorrect internal argument syntax, missing modificator: $wholeArgument")
|
||||
}
|
||||
|
||||
val languageFeatureName = tail.substring(2)
|
||||
if (languageFeatureName.isEmpty()) return reportAndReturnNull("Empty language feature name for internal argument '$wholeArgument'")
|
||||
|
||||
val languageFeature = LanguageFeature.fromString(languageFeatureName)
|
||||
?: return reportAndReturnNull("Unknown language feature '$languageFeatureName' in passed internal argument '$wholeArgument'")
|
||||
|
||||
return ManualLanguageFeatureSetting(languageFeature, languageFeatureState)
|
||||
}
|
||||
}
|
||||
|
||||
interface InternalArgument
|
||||
|
||||
data class ManualLanguageFeatureSetting(val languageFeature: LanguageFeature, val state: LanguageFeature.State) : InternalArgument
|
||||
+17
-1
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.cli.common.arguments
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.memberProperties
|
||||
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@@ -102,6 +101,7 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
||||
}
|
||||
|
||||
val freeArgs = ArrayList<String>()
|
||||
val internalArguments = ArrayList<String>()
|
||||
|
||||
var i = 0
|
||||
loop@ while (i < args.size) {
|
||||
@@ -116,6 +116,21 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
||||
continue
|
||||
}
|
||||
|
||||
if (arg.startsWith(InternalArgumentParser.INTERNAL_ARGUMENT_PREFIX)) {
|
||||
val matchingParsers = InternalArgumentParser.PARSERS.filter { it.canParse(arg) }
|
||||
assert(matchingParsers.size <= 1) { "Internal error: internal argument $arg can be ambiguously parsed by parsers ${matchingParsers.joinToString()}" }
|
||||
|
||||
val parser = matchingParsers.firstOrNull()
|
||||
|
||||
if (parser == null) {
|
||||
errors.unknownExtraFlags += arg
|
||||
} else {
|
||||
internalArguments.add(arg)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
val argumentField = properties.firstOrNull { it.matches(arg) }
|
||||
if (argumentField == null) {
|
||||
when {
|
||||
@@ -154,6 +169,7 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
||||
}
|
||||
|
||||
result.freeArgs += freeArgs
|
||||
result.internalArguments += internalArguments
|
||||
}
|
||||
|
||||
private fun <A : CommonToolArguments> updateField(property: KMutableProperty1<A, Any?>, result: A, value: Any, delimiter: String) {
|
||||
|
||||
@@ -38,10 +38,10 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
}
|
||||
|
||||
protected fun exec(
|
||||
errStream: PrintStream,
|
||||
services: Services,
|
||||
messageRenderer: MessageRenderer,
|
||||
args: Array<out String>
|
||||
errStream: PrintStream,
|
||||
services: Services,
|
||||
messageRenderer: MessageRenderer,
|
||||
args: Array<out String>
|
||||
): ExitCode {
|
||||
val arguments = createArguments()
|
||||
parseCommandLineArguments(args.asList(), arguments)
|
||||
@@ -67,8 +67,7 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
}
|
||||
|
||||
return exec(collector, services, arguments)
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
errStream.print(messageRenderer.renderConclusion())
|
||||
|
||||
if (PlainTextMessageRenderer.COLOR_ENABLED) {
|
||||
@@ -84,12 +83,11 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
|
||||
val fixedMessageCollector = if (arguments.suppressWarnings && !arguments.allWarningsAsErrors) {
|
||||
FilteringMessageCollector(messageCollector, Predicate.isEqual(CompilerMessageSeverity.WARNING))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
messageCollector
|
||||
}
|
||||
|
||||
reportArgumentParseProblems(fixedMessageCollector, arguments.errors)
|
||||
reportArgumentParseProblems(fixedMessageCollector, arguments)
|
||||
return execImpl(fixedMessageCollector, services, arguments)
|
||||
}
|
||||
|
||||
@@ -117,13 +115,16 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportArgumentParseProblems(collector: MessageCollector, errors: ArgumentParseErrors) {
|
||||
private fun reportArgumentParseProblems(collector: MessageCollector, arguments: A) {
|
||||
val errors = arguments.errors
|
||||
for (flag in errors.unknownExtraFlags) {
|
||||
collector.report(STRONG_WARNING, "Flag is not supported by this version of the compiler: $flag")
|
||||
}
|
||||
for (argument in errors.extraArgumentsPassedInObsoleteForm) {
|
||||
collector.report(STRONG_WARNING, "Advanced option value is passed in an obsolete form. Please use the '=' character " +
|
||||
"to specify the value: $argument=...")
|
||||
collector.report(
|
||||
STRONG_WARNING, "Advanced option value is passed in an obsolete form. Please use the '=' character " +
|
||||
"to specify the value: $argument=..."
|
||||
)
|
||||
}
|
||||
for ((key, value) in errors.duplicateArguments) {
|
||||
collector.report(STRONG_WARNING, "Argument $key is passed multiple times. Only the last value will be used: $value")
|
||||
@@ -131,6 +132,17 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
for ((deprecatedName, newName) in errors.deprecatedArguments) {
|
||||
collector.report(STRONG_WARNING, "Argument $deprecatedName is deprecated. Please use $newName instead")
|
||||
}
|
||||
if (arguments.internalArguments.isNotEmpty()) {
|
||||
collector.report(
|
||||
STRONG_WARNING,
|
||||
"ATTENTION!\n" +
|
||||
"This build uses internal compiler arguments:\n" +
|
||||
arguments.internalArguments.joinToString(prefix = "\n", postfix = "\n\n", separator = "\n") +
|
||||
"This mode is strictly prohibited for production use,\n" +
|
||||
"as no stability/compatibility guarantees are given on\n" +
|
||||
"compiler or generated code. Use it at your own risk!\n"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <A : CommonToolArguments> printVersionIfNeeded(messageCollector: MessageCollector, arguments: A) {
|
||||
@@ -166,8 +178,7 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
fun doMainNoExit(compiler: CLITool<*>, args: Array<String>): ExitCode {
|
||||
try {
|
||||
return compiler.exec(System.err, *args)
|
||||
}
|
||||
catch (e: CompileEnvironmentException) {
|
||||
} catch (e: CompileEnvironmentException) {
|
||||
System.err.println(e.message)
|
||||
return ExitCode.INTERNAL_ERROR
|
||||
}
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
inline class Foo(val x: Int)
|
||||
@@ -0,0 +1,6 @@
|
||||
-language-version
|
||||
1.3
|
||||
-XXLanguage\:-InlineClasses
|
||||
$TESTDATA_DIR$/inlineClass.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
@@ -0,0 +1,14 @@
|
||||
warning: ATTENTION!
|
||||
This build uses internal compiler arguments:
|
||||
|
||||
-XXLanguage:-InlineClasses
|
||||
|
||||
This mode is strictly prohibited 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.3 is experimental, there are no backwards compatibility guarantees for new language and library features
|
||||
compiler/testData/cli/jvm/inlineClass.kt:1:1: error: the feature "inline classes" is experimental and should be enabled explicitly
|
||||
inline class Foo(val x: Int)
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,4 @@
|
||||
$TESTDATA_DIR$/inlineClass.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-XXLanguage\:+
|
||||
@@ -0,0 +1,14 @@
|
||||
warning: ATTENTION!
|
||||
This build uses internal compiler arguments:
|
||||
|
||||
-XXLanguage:+
|
||||
|
||||
This mode is strictly prohibited for production use,
|
||||
as no stability/compatibility guarantees are given on
|
||||
compiler or generated code. Use it at your own risk!
|
||||
|
||||
warning: empty language feature name for internal argument '-XXLanguage:+'
|
||||
compiler/testData/cli/jvm/inlineClass.kt:1:1: error: the feature "inline classes" is experimental and should be enabled explicitly
|
||||
inline class Foo(val x: Int)
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,6 @@
|
||||
$TESTDATA_DIR$/inlineClass.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-language-version
|
||||
1.2
|
||||
-XXLanguage\:+InlineClasses
|
||||
@@ -0,0 +1,11 @@
|
||||
warning: ATTENTION!
|
||||
This build uses internal compiler arguments:
|
||||
|
||||
-XXLanguage:+InlineClasses
|
||||
|
||||
This mode is strictly prohibited for production use,
|
||||
as no stability/compatibility guarantees are given on
|
||||
compiler or generated code. Use it at your own risk!
|
||||
|
||||
warning: following manually enabled features will force generation of pre-release binaries: InlineClasses
|
||||
OK
|
||||
@@ -0,0 +1,4 @@
|
||||
$TESTDATA_DIR$/inlineClass.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-XXLanguage\:InlineClasses
|
||||
@@ -0,0 +1,14 @@
|
||||
warning: ATTENTION!
|
||||
This build uses internal compiler arguments:
|
||||
|
||||
-XXLanguage:InlineClasses
|
||||
|
||||
This mode is strictly prohibited for production use,
|
||||
as no stability/compatibility guarantees are given on
|
||||
compiler or generated code. Use it at your own risk!
|
||||
|
||||
warning: incorrect internal argument syntax, missing modificator: -XXLanguage:InlineClasses
|
||||
compiler/testData/cli/jvm/inlineClass.kt:1:1: error: the feature "inline classes" is experimental and should be enabled explicitly
|
||||
inline class Foo(val x: Int)
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,4 @@
|
||||
$TESTDATA_DIR$/inlineClass.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-XXLanguage\:+UnknownFeature
|
||||
@@ -0,0 +1,14 @@
|
||||
warning: ATTENTION!
|
||||
This build uses internal compiler arguments:
|
||||
|
||||
-XXLanguage:+UnknownFeature
|
||||
|
||||
This mode is strictly prohibited for production use,
|
||||
as no stability/compatibility guarantees are given on
|
||||
compiler or generated code. Use it at your own risk!
|
||||
|
||||
warning: unknown language feature 'UnknownFeature' in passed internal argument '-XXLanguage:+UnknownFeature'
|
||||
compiler/testData/cli/jvm/inlineClass.kt:1:1: error: the feature "inline classes" is experimental and should be enabled explicitly
|
||||
inline class Foo(val x: Int)
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,4 @@
|
||||
$TESTDATA_DIR$/inlineClass.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-XX:+InlineClasses
|
||||
@@ -0,0 +1,5 @@
|
||||
warning: flag is not supported by this version of the compiler: -XX:+InlineClasses
|
||||
compiler/testData/cli/jvm/inlineClass.kt:1:1: error: the feature "inline classes" is experimental and should be enabled explicitly
|
||||
inline class Foo(val x: Int)
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,5 @@
|
||||
$TESTDATA_DIR$/legacySmartCastsAfterTry.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-XXLanguage\:+SoundSmartCastsAfterTry
|
||||
-Xlegacy-smart-cast-after-try
|
||||
@@ -0,0 +1,13 @@
|
||||
warning: ATTENTION!
|
||||
This build uses internal compiler arguments:
|
||||
|
||||
-XXLanguage:+SoundSmartCastsAfterTry
|
||||
|
||||
This mode is strictly prohibited for production use,
|
||||
as no stability/compatibility guarantees are given on
|
||||
compiler or generated code. Use it at your own risk!
|
||||
|
||||
compiler/testData/cli/jvm/legacySmartCastsAfterTry.kt:8:9: error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
|
||||
some.length
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
+2
@@ -42,6 +42,8 @@ data class CompilerTestLanguageVersionSettings(
|
||||
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State =
|
||||
languageFeatures[feature] ?: delegate.getFeatureSupport(feature)
|
||||
|
||||
override fun isPreRelease(): Boolean = languageVersion.isPreRelease()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T> getFlag(flag: AnalysisFlag<T>): T = analysisFlags[flag] as T? ?: flag.defaultValue
|
||||
}
|
||||
|
||||
@@ -232,6 +232,48 @@ public class CliTestGenerated extends AbstractCliTest {
|
||||
runTest("compiler/testData/cli/jvm/inlineCycle.args");
|
||||
}
|
||||
|
||||
@TestMetadata("internalArgDisableLanguageFeature.args")
|
||||
public void testInternalArgDisableLanguageFeature() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/internalArgDisableLanguageFeature.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("internalArgEmptyFeatureName.args")
|
||||
public void testInternalArgEmptyFeatureName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/internalArgEmptyFeatureName.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("internalArgEnableLanguageFeature.args")
|
||||
public void testInternalArgEnableLanguageFeature() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/internalArgEnableLanguageFeature.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("internalArgMissingModificator.args")
|
||||
public void testInternalArgMissingModificator() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/internalArgMissingModificator.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("internalArgUnrecognizedFeature.args")
|
||||
public void testInternalArgUnrecognizedFeature() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/internalArgUnrecognizedFeature.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("internalArgWrongPrefix.args")
|
||||
public void testInternalArgWrongPrefix() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/internalArgWrongPrefix.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("internalArgumentOverrideExtraArgument.args")
|
||||
public void testInternalArgumentOverrideExtraArgument() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/internalArgumentOverrideExtraArgument.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("javaSrcWrongPackage.args")
|
||||
public void testJavaSrcWrongPackage() throws Exception {
|
||||
runTest("compiler/testData/cli/jvm/javaSrcWrongPackage.args");
|
||||
|
||||
@@ -14,6 +14,7 @@ enum class LanguageFeature(
|
||||
val sinceApiVersion: ApiVersion = ApiVersion.KOTLIN_1_0,
|
||||
val hintUrl: String? = null,
|
||||
val defaultState: State = State.ENABLED,
|
||||
val forcesPreReleaseBinaries: Boolean = false,
|
||||
val enabledInProgressiveMode: Boolean = false
|
||||
) {
|
||||
// Note: names of these entries are also used in diagnostic tests and in user-visible messages (see presentableText below)
|
||||
@@ -65,14 +66,14 @@ enum class LanguageFeature(
|
||||
ProperVisibilityForCompanionObjectInstanceField(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||
ProperForInArrayLoopRangeVariableAssignmentSemantic(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||
NestedClassesInAnnotations(KOTLIN_1_3),
|
||||
JvmStaticInInterface(KOTLIN_1_3),
|
||||
JvmStaticInInterface(KOTLIN_1_3, forcesPreReleaseBinaries = true),
|
||||
ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||
ProhibitNonConstValuesAsVarargsInAnnotations(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||
ReleaseCoroutines(KOTLIN_1_3),
|
||||
ReleaseCoroutines(KOTLIN_1_3, forcesPreReleaseBinaries = true),
|
||||
ReadDeserializedContracts(KOTLIN_1_3),
|
||||
UseReturnsEffect(KOTLIN_1_3),
|
||||
UseCallsInPlaceEffect(KOTLIN_1_3),
|
||||
AllowContractsForCustomFunctions(KOTLIN_1_3),
|
||||
AllowContractsForCustomFunctions(KOTLIN_1_3, forcesPreReleaseBinaries = true),
|
||||
ProhibitLocalAnnotations(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||
|
||||
StrictJavaNullabilityAssertions(sinceVersion = null, defaultState = State.DISABLED),
|
||||
@@ -90,7 +91,7 @@ enum class LanguageFeature(
|
||||
|
||||
NewInference(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED),
|
||||
|
||||
InlineClasses(sinceVersion = null, defaultState = State.DISABLED),
|
||||
InlineClasses(sinceVersion = null, defaultState = State.DISABLED, forcesPreReleaseBinaries = true),
|
||||
|
||||
;
|
||||
|
||||
@@ -147,7 +148,12 @@ interface LanguageVersionSettings {
|
||||
fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State
|
||||
|
||||
fun supportsFeature(feature: LanguageFeature): Boolean =
|
||||
getFeatureSupport(feature).let { it == LanguageFeature.State.ENABLED || it == LanguageFeature.State.ENABLED_WITH_WARNING }
|
||||
getFeatureSupport(feature).let {
|
||||
it == LanguageFeature.State.ENABLED ||
|
||||
it == LanguageFeature.State.ENABLED_WITH_WARNING
|
||||
}
|
||||
|
||||
fun isPreRelease(): Boolean
|
||||
|
||||
fun <T> getFlag(flag: AnalysisFlag<T>): T
|
||||
|
||||
@@ -192,17 +198,24 @@ class LanguageVersionSettingsImpl @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun isPreRelease(): Boolean = languageVersion.isPreRelease() ||
|
||||
specificFeatures.any { (feature, state) ->
|
||||
state == LanguageFeature.State.ENABLED && feature.forcesPreReleaseBinariesIfEnabled()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val DEFAULT = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE)
|
||||
}
|
||||
}
|
||||
|
||||
fun LanguageVersionSettings.isPreRelease(): Boolean =
|
||||
languageVersion.isPreRelease()
|
||||
|
||||
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 && forcesPreReleaseBinaries
|
||||
}
|
||||
|
||||
+5
@@ -25,6 +25,11 @@ public class ReleaseCoroutinesDisabledLanguageVersionSettings implements Languag
|
||||
return delegate.getFeatureSupport(feature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreRelease() {
|
||||
return delegate.isPreRelease();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getFlag(@NotNull AnalysisFlag<? extends T> flag) {
|
||||
return delegate.getFlag(flag);
|
||||
|
||||
Reference in New Issue
Block a user