Do not report warning if -XXLanguage turns on bugfix

KT-25554 Fixed
This commit is contained in:
Dmitry Savvinov
2018-07-18 12:07:58 +03:00
committed by Dmitry Savvinov
parent e42017a468
commit 6dacd1011f
15 changed files with 69 additions and 56 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.compilerRunner; package org.jetbrains.kotlin.compilerRunner;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.JvmClassMappingKt; import kotlin.jvm.JvmClassMappingKt;
import kotlin.reflect.KClass; import kotlin.reflect.KClass;
import kotlin.reflect.KProperty1; import kotlin.reflect.KProperty1;
@@ -26,6 +27,7 @@ import kotlin.reflect.jvm.ReflectJvmMapping;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.cli.common.arguments.Argument; import org.jetbrains.kotlin.cli.common.arguments.Argument;
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments; import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments;
import org.jetbrains.kotlin.cli.common.arguments.InternalArgument;
import org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt; import org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt;
import org.jetbrains.kotlin.utils.StringsKt; import org.jetbrains.kotlin.utils.StringsKt;
@@ -46,7 +48,7 @@ public class ArgumentUtils {
Class<? extends CommonToolArguments> argumentsClass = arguments.getClass(); Class<? extends CommonToolArguments> argumentsClass = arguments.getClass();
convertArgumentsToStringList(arguments, argumentsClass.newInstance(), JvmClassMappingKt.getKotlinClass(argumentsClass), result); convertArgumentsToStringList(arguments, argumentsClass.newInstance(), JvmClassMappingKt.getKotlinClass(argumentsClass), result);
result.addAll(arguments.getFreeArgs()); result.addAll(arguments.getFreeArgs());
result.addAll(arguments.getInternalArguments()); result.addAll(CollectionsKt.map(arguments.getInternalArguments(), InternalArgument::getStringRepresentation));
return result; return result;
} }
@@ -245,11 +245,9 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
} }
private fun HashMap<LanguageFeature, LanguageFeature.State>.configureLanguageFeaturesFromInternalArgs(collector: MessageCollector) { private fun HashMap<LanguageFeature, LanguageFeature.State>.configureLanguageFeaturesFromInternalArgs(collector: MessageCollector) {
val languageSettingsParser = LanguageSettingsParser()
val featuresThatForcePreReleaseBinaries = mutableListOf<LanguageFeature>() val featuresThatForcePreReleaseBinaries = mutableListOf<LanguageFeature>()
for (argument in internalArguments) { for ((feature, state) in internalArguments.filterIsInstance<ManualLanguageFeatureSetting>()) {
val (feature, state) = languageSettingsParser.parseInternalArgument(argument, collector) ?: continue
put(feature, state) put(feature, state)
if (state == LanguageFeature.State.ENABLED && feature.forcesPreReleaseBinariesIfEnabled()) { if (state == LanguageFeature.State.ENABLED && feature.forcesPreReleaseBinariesIfEnabled()) {
featuresThatForcePreReleaseBinaries += feature featuresThatForcePreReleaseBinaries += feature
@@ -50,5 +50,5 @@ abstract class CommonToolArguments : Freezable(), Serializable {
@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()) var internalArguments: List<InternalArgument> by FreezableVar(emptyList())
} }
@@ -6,8 +6,6 @@
package org.jetbrains.kotlin.cli.common.arguments 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.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 import org.jetbrains.kotlin.config.LanguageFeature
/** /**
@@ -25,7 +23,7 @@ interface InternalArgumentParser<A : InternalArgument> {
// Should be fast // Should be fast
fun canParse(arg: String): Boolean fun canParse(arg: String): Boolean
fun parseInternalArgument(arg: String, messageCollector: MessageCollector): A? fun parseInternalArgument(arg: String, errors: ArgumentParseErrors): A?
companion object { companion object {
internal const val INTERNAL_ARGUMENT_PREFIX = "-XX" internal const val INTERNAL_ARGUMENT_PREFIX = "-XX"
@@ -41,13 +39,13 @@ abstract class AbstractInternalArgumentParser<A : InternalArgument>(familyName:
override fun canParse(arg: String): Boolean = arg.startsWith(wholePrefix) override fun canParse(arg: String): Boolean = arg.startsWith(wholePrefix)
override fun parseInternalArgument(arg: String, messageCollector: MessageCollector): A? { override fun parseInternalArgument(arg: String, errors: ArgumentParseErrors): A? {
if (!arg.startsWith(wholePrefix)) return null if (!arg.startsWith(wholePrefix)) return null
return parseTail(arg.removePrefix(wholePrefix), arg, messageCollector) return parseTail(arg.removePrefix(wholePrefix), arg, errors)
} }
abstract fun parseTail(tail: String, wholeArgument: String, messageCollector: MessageCollector): A? abstract fun parseTail(tail: String, wholeArgument: String, errors: ArgumentParseErrors): A?
} }
@@ -55,9 +53,9 @@ abstract class AbstractInternalArgumentParser<A : InternalArgument>(familyName:
class LanguageSettingsParser : AbstractInternalArgumentParser<ManualLanguageFeatureSetting>("Language") { class LanguageSettingsParser : AbstractInternalArgumentParser<ManualLanguageFeatureSetting>("Language") {
// Expected tail form: ':(+|-)<language feature name>' // Expected tail form: ':(+|-)<language feature name>'
override fun parseTail(tail: String, wholeArgument: String, messageCollector: MessageCollector): ManualLanguageFeatureSetting? { override fun parseTail(tail: String, wholeArgument: String, errors: ArgumentParseErrors): ManualLanguageFeatureSetting? {
fun reportAndReturnNull(message: String): Nothing? { fun reportAndReturnNull(message: String): Nothing? {
messageCollector.report(CompilerMessageSeverity.STRONG_WARNING, message) errors.internalArgumentsParsingProblems += message
return null return null
} }
@@ -76,12 +74,18 @@ class LanguageSettingsParser : AbstractInternalArgumentParser<ManualLanguageFeat
if (languageFeatureName.isEmpty()) return reportAndReturnNull("Empty language feature name for internal argument '$wholeArgument'") if (languageFeatureName.isEmpty()) return reportAndReturnNull("Empty language feature name for internal argument '$wholeArgument'")
val languageFeature = LanguageFeature.fromString(languageFeatureName) val languageFeature = LanguageFeature.fromString(languageFeatureName)
?: return reportAndReturnNull("Unknown language feature '$languageFeatureName' in passed internal argument '$wholeArgument'") ?: return reportAndReturnNull("Unknown language feature '$languageFeatureName' in passed internal argument '$wholeArgument'")
return ManualLanguageFeatureSetting(languageFeature, languageFeatureState) return ManualLanguageFeatureSetting(languageFeature, languageFeatureState, wholeArgument)
} }
} }
interface InternalArgument interface InternalArgument {
val stringRepresentation: String
}
data class ManualLanguageFeatureSetting(val languageFeature: LanguageFeature, val state: LanguageFeature.State) : InternalArgument data class ManualLanguageFeatureSetting(
val languageFeature: LanguageFeature,
val state: LanguageFeature.State,
override val stringRepresentation: String
) : InternalArgument
@@ -54,7 +54,10 @@ data class ArgumentParseErrors(
var argumentWithoutValue: String? = null, var argumentWithoutValue: String? = null,
val argfileErrors: MutableList<String> = SmartList() val argfileErrors: MutableList<String> = SmartList(),
// Reports from internal arguments parsers
val internalArgumentsParsingProblems: MutableList<String> = SmartList()
) )
// Parses arguments into the passed [result] object. Errors related to the parsing will be collected into [CommonToolArguments.errors]. // Parses arguments into the passed [result] object. Errors related to the parsing will be collected into [CommonToolArguments.errors].
@@ -108,7 +111,7 @@ private fun <A : CommonToolArguments> parsePreprocessedCommandLineArguments(args
} }
val freeArgs = ArrayList<String>() val freeArgs = ArrayList<String>()
val internalArguments = ArrayList<String>() val internalArguments = ArrayList<InternalArgument>()
var i = 0 var i = 0
loop@ while (i < args.size) { loop@ while (i < args.size) {
@@ -132,7 +135,7 @@ private fun <A : CommonToolArguments> parsePreprocessedCommandLineArguments(args
if (parser == null) { if (parser == null) {
errors.unknownExtraFlags += arg errors.unknownExtraFlags += arg
} else { } else {
internalArguments.add(arg) internalArguments.add(parser.parseInternalArgument(arg, errors) ?: continue)
} }
continue continue
@@ -23,6 +23,9 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentException import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentException
import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageFeature.Kind.*
import org.jetbrains.kotlin.config.LanguageFeature.State.*
import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.config.Services
import java.io.PrintStream import java.io.PrintStream
import java.net.URL import java.net.URL
@@ -129,20 +132,38 @@ 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()) {
for (argfileError in errors.argfileErrors) {
collector.report(STRONG_WARNING, argfileError)
}
reportUnsafeInternalArgumentsIfAny(arguments, collector)
for (internalArgumentsError in errors.internalArgumentsParsingProblems) {
collector.report(STRONG_WARNING, internalArgumentsError)
}
}
private fun reportUnsafeInternalArgumentsIfAny(arguments: A, collector: MessageCollector) {
val unsafeArguments = arguments.internalArguments.filterNot {
// -XXLanguage which turns on BUG_FIX considered safe
it is ManualLanguageFeatureSetting && it.languageFeature.kind == BUG_FIX && it.state == ENABLED
}
if (unsafeArguments.isNotEmpty()) {
val unsafeArgumentsString = unsafeArguments.joinToString(prefix = "\n", postfix = "\n\n", separator = "\n") {
it.stringRepresentation
}
collector.report( collector.report(
STRONG_WARNING, STRONG_WARNING,
"ATTENTION!\n" + "ATTENTION!\n" +
"This build uses internal compiler arguments:\n" + "This build uses unsafe internal compiler arguments:\n" +
arguments.internalArguments.joinToString(prefix = "\n", postfix = "\n\n", separator = "\n") + unsafeArgumentsString +
"This mode is not recommended for production use,\n" + "This mode is not recommended for production use,\n" +
"as no stability/compatibility guarantees are given on\n" + "as no stability/compatibility guarantees are given on\n" +
"compiler or generated code. Use it at your own risk!\n" "compiler or generated code. Use it at your own risk!\n"
) )
} }
for (argfileError in errors.argfileErrors) {
collector.report(STRONG_WARNING, argfileError)
}
} }
private fun <A : CommonToolArguments> printVersionIfNeeded(messageCollector: MessageCollector, arguments: A) { private fun <A : CommonToolArguments> printVersionIfNeeded(messageCollector: MessageCollector, arguments: A) {
@@ -1,5 +1,5 @@
warning: ATTENTION! warning: ATTENTION!
This build uses internal compiler arguments: This build uses unsafe internal compiler arguments:
-XXLanguage:-SoundSmartCastsAfterTry -XXLanguage:-SoundSmartCastsAfterTry
@@ -1,12 +1,3 @@
warning: ATTENTION!
This build uses internal compiler arguments:
-XXLanguage:+
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: empty language feature name for internal argument '-XXLanguage:+' warning: empty language feature name for internal argument '-XXLanguage:+'
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? 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 some.length
@@ -1,5 +1,5 @@
warning: ATTENTION! warning: ATTENTION!
This build uses internal compiler arguments: This build uses unsafe internal compiler arguments:
-XXLanguage:+SoundSmartCastsAfterTry -XXLanguage:+SoundSmartCastsAfterTry
@@ -1,12 +1,3 @@
warning: ATTENTION!
This build uses internal compiler arguments:
-XXLanguage:SoundSmartCastAfterTry
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: incorrect internal argument syntax, missing modificator: -XXLanguage:SoundSmartCastAfterTry warning: incorrect internal argument syntax, missing modificator: -XXLanguage:SoundSmartCastAfterTry
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? 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 some.length
@@ -0,0 +1,6 @@
$TESTDATA_DIR$/simple.kt
-d
$TEMP_DIR$
-language-version
1.2
-XXLanguage:+ProhibitDataClassesOverridingCopy
@@ -0,0 +1 @@
OK
@@ -1,12 +1,3 @@
warning: ATTENTION!
This build uses internal compiler arguments:
-XXLanguage:+UnknownFeature
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: unknown language feature 'UnknownFeature' in passed internal argument '-XXLanguage:+UnknownFeature' warning: unknown language feature 'UnknownFeature' in passed internal argument '-XXLanguage:+UnknownFeature'
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? 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 some.length
@@ -1,5 +1,5 @@
warning: ATTENTION! warning: ATTENTION!
This build uses internal compiler arguments: This build uses unsafe internal compiler arguments:
-XXLanguage:+SoundSmartCastsAfterTry -XXLanguage:+SoundSmartCastsAfterTry
@@ -261,6 +261,11 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/jvm/internalArgMissingModificator.args"); runTest("compiler/testData/cli/jvm/internalArgMissingModificator.args");
} }
@TestMetadata("internalArgNoWarningForEnablingBugfix.args")
public void testInternalArgNoWarningForEnablingBugfix() throws Exception {
runTest("compiler/testData/cli/jvm/internalArgNoWarningForEnablingBugfix.args");
}
@TestMetadata("internalArgUnrecognizedFeature.args") @TestMetadata("internalArgUnrecognizedFeature.args")
public void testInternalArgUnrecognizedFeature() throws Exception { public void testInternalArgUnrecognizedFeature() throws Exception {
runTest("compiler/testData/cli/jvm/internalArgUnrecognizedFeature.args"); runTest("compiler/testData/cli/jvm/internalArgUnrecognizedFeature.args");