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)
|
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 {
|
fun configureLanguageVersionSettings(collector: MessageCollector): LanguageVersionSettings {
|
||||||
|
|
||||||
// If only "-api-version" is specified, language version is assumed to be the latest stable
|
// 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)
|
@GradleOption(DefaultValues.BooleanFalseDefault::class)
|
||||||
@Argument(value = "-Werror", description = "Report an error if there are any warnings")
|
@Argument(value = "-Werror", description = "Report an error if there are any warnings")
|
||||||
var allWarningsAsErrors: Boolean by FreezableVar(false)
|
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 org.jetbrains.kotlin.utils.SmartList
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KMutableProperty1
|
import kotlin.reflect.KMutableProperty1
|
||||||
import kotlin.reflect.full.findAnnotation
|
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
|
|
||||||
@Target(AnnotationTarget.PROPERTY)
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
@@ -102,6 +101,7 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
|||||||
}
|
}
|
||||||
|
|
||||||
val freeArgs = ArrayList<String>()
|
val freeArgs = ArrayList<String>()
|
||||||
|
val internalArguments = ArrayList<String>()
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
loop@ while (i < args.size) {
|
loop@ while (i < args.size) {
|
||||||
@@ -116,6 +116,21 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
|||||||
continue
|
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) }
|
val argumentField = properties.firstOrNull { it.matches(arg) }
|
||||||
if (argumentField == null) {
|
if (argumentField == null) {
|
||||||
when {
|
when {
|
||||||
@@ -154,6 +169,7 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.freeArgs += freeArgs
|
result.freeArgs += freeArgs
|
||||||
|
result.internalArguments += internalArguments
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <A : CommonToolArguments> updateField(property: KMutableProperty1<A, Any?>, result: A, value: Any, delimiter: String) {
|
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(
|
protected fun exec(
|
||||||
errStream: PrintStream,
|
errStream: PrintStream,
|
||||||
services: Services,
|
services: Services,
|
||||||
messageRenderer: MessageRenderer,
|
messageRenderer: MessageRenderer,
|
||||||
args: Array<out String>
|
args: Array<out String>
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
val arguments = createArguments()
|
val arguments = createArguments()
|
||||||
parseCommandLineArguments(args.asList(), arguments)
|
parseCommandLineArguments(args.asList(), arguments)
|
||||||
@@ -67,8 +67,7 @@ abstract class CLITool<A : CommonToolArguments> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return exec(collector, services, arguments)
|
return exec(collector, services, arguments)
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
errStream.print(messageRenderer.renderConclusion())
|
errStream.print(messageRenderer.renderConclusion())
|
||||||
|
|
||||||
if (PlainTextMessageRenderer.COLOR_ENABLED) {
|
if (PlainTextMessageRenderer.COLOR_ENABLED) {
|
||||||
@@ -84,12 +83,11 @@ abstract class CLITool<A : CommonToolArguments> {
|
|||||||
|
|
||||||
val fixedMessageCollector = if (arguments.suppressWarnings && !arguments.allWarningsAsErrors) {
|
val fixedMessageCollector = if (arguments.suppressWarnings && !arguments.allWarningsAsErrors) {
|
||||||
FilteringMessageCollector(messageCollector, Predicate.isEqual(CompilerMessageSeverity.WARNING))
|
FilteringMessageCollector(messageCollector, Predicate.isEqual(CompilerMessageSeverity.WARNING))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
messageCollector
|
messageCollector
|
||||||
}
|
}
|
||||||
|
|
||||||
reportArgumentParseProblems(fixedMessageCollector, arguments.errors)
|
reportArgumentParseProblems(fixedMessageCollector, arguments)
|
||||||
return execImpl(fixedMessageCollector, services, 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) {
|
for (flag in errors.unknownExtraFlags) {
|
||||||
collector.report(STRONG_WARNING, "Flag is not supported by this version of the compiler: $flag")
|
collector.report(STRONG_WARNING, "Flag is not supported by this version of the compiler: $flag")
|
||||||
}
|
}
|
||||||
for (argument in errors.extraArgumentsPassedInObsoleteForm) {
|
for (argument in errors.extraArgumentsPassedInObsoleteForm) {
|
||||||
collector.report(STRONG_WARNING, "Advanced option value is passed in an obsolete form. Please use the '=' character " +
|
collector.report(
|
||||||
"to specify the value: $argument=...")
|
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) {
|
for ((key, value) in errors.duplicateArguments) {
|
||||||
collector.report(STRONG_WARNING, "Argument $key is passed multiple times. Only the last value will be used: $value")
|
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) {
|
for ((deprecatedName, newName) in errors.deprecatedArguments) {
|
||||||
collector.report(STRONG_WARNING, "Argument $deprecatedName is deprecated. Please use $newName instead")
|
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) {
|
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 {
|
fun doMainNoExit(compiler: CLITool<*>, args: Array<String>): ExitCode {
|
||||||
try {
|
try {
|
||||||
return compiler.exec(System.err, *args)
|
return compiler.exec(System.err, *args)
|
||||||
}
|
} catch (e: CompileEnvironmentException) {
|
||||||
catch (e: CompileEnvironmentException) {
|
|
||||||
System.err.println(e.message)
|
System.err.println(e.message)
|
||||||
return ExitCode.INTERNAL_ERROR
|
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 =
|
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State =
|
||||||
languageFeatures[feature] ?: delegate.getFeatureSupport(feature)
|
languageFeatures[feature] ?: delegate.getFeatureSupport(feature)
|
||||||
|
|
||||||
|
override fun isPreRelease(): Boolean = languageVersion.isPreRelease()
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun <T> getFlag(flag: AnalysisFlag<T>): T = analysisFlags[flag] as T? ?: flag.defaultValue
|
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");
|
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")
|
@TestMetadata("javaSrcWrongPackage.args")
|
||||||
public void testJavaSrcWrongPackage() throws Exception {
|
public void testJavaSrcWrongPackage() throws Exception {
|
||||||
runTest("compiler/testData/cli/jvm/javaSrcWrongPackage.args");
|
runTest("compiler/testData/cli/jvm/javaSrcWrongPackage.args");
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ enum class LanguageFeature(
|
|||||||
val sinceApiVersion: ApiVersion = ApiVersion.KOTLIN_1_0,
|
val sinceApiVersion: ApiVersion = ApiVersion.KOTLIN_1_0,
|
||||||
val hintUrl: String? = null,
|
val hintUrl: String? = null,
|
||||||
val defaultState: State = State.ENABLED,
|
val defaultState: State = State.ENABLED,
|
||||||
|
val forcesPreReleaseBinaries: Boolean = false,
|
||||||
val enabledInProgressiveMode: 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)
|
// 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),
|
ProperVisibilityForCompanionObjectInstanceField(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||||
ProperForInArrayLoopRangeVariableAssignmentSemantic(KOTLIN_1_3, enabledInProgressiveMode = true),
|
ProperForInArrayLoopRangeVariableAssignmentSemantic(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||||
NestedClassesInAnnotations(KOTLIN_1_3),
|
NestedClassesInAnnotations(KOTLIN_1_3),
|
||||||
JvmStaticInInterface(KOTLIN_1_3),
|
JvmStaticInInterface(KOTLIN_1_3, forcesPreReleaseBinaries = true),
|
||||||
ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion(KOTLIN_1_3, enabledInProgressiveMode = true),
|
ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||||
ProhibitNonConstValuesAsVarargsInAnnotations(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),
|
ReadDeserializedContracts(KOTLIN_1_3),
|
||||||
UseReturnsEffect(KOTLIN_1_3),
|
UseReturnsEffect(KOTLIN_1_3),
|
||||||
UseCallsInPlaceEffect(KOTLIN_1_3),
|
UseCallsInPlaceEffect(KOTLIN_1_3),
|
||||||
AllowContractsForCustomFunctions(KOTLIN_1_3),
|
AllowContractsForCustomFunctions(KOTLIN_1_3, forcesPreReleaseBinaries = true),
|
||||||
ProhibitLocalAnnotations(KOTLIN_1_3, enabledInProgressiveMode = true),
|
ProhibitLocalAnnotations(KOTLIN_1_3, enabledInProgressiveMode = true),
|
||||||
|
|
||||||
StrictJavaNullabilityAssertions(sinceVersion = null, defaultState = State.DISABLED),
|
StrictJavaNullabilityAssertions(sinceVersion = null, defaultState = State.DISABLED),
|
||||||
@@ -90,7 +91,7 @@ enum class LanguageFeature(
|
|||||||
|
|
||||||
NewInference(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED),
|
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 getFeatureSupport(feature: LanguageFeature): LanguageFeature.State
|
||||||
|
|
||||||
fun supportsFeature(feature: LanguageFeature): Boolean =
|
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
|
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 {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
val DEFAULT = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE)
|
val DEFAULT = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LanguageVersionSettings.isPreRelease(): Boolean =
|
|
||||||
languageVersion.isPreRelease()
|
|
||||||
|
|
||||||
fun LanguageVersion.isPreRelease(): 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
return delegate.getFeatureSupport(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPreRelease() {
|
||||||
|
return delegate.isPreRelease();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T getFlag(@NotNull AnalysisFlag<? extends T> flag) {
|
public <T> T getFlag(@NotNull AnalysisFlag<? extends T> flag) {
|
||||||
return delegate.getFlag(flag);
|
return delegate.getFlag(flag);
|
||||||
|
|||||||
Reference in New Issue
Block a user