diff --git a/compiler/tests-common/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt b/compiler/tests-common/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt index 9b0ea46f362..a4cb15e6921 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt +++ b/compiler/tests-common/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt @@ -222,7 +222,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() { } } - return result ?: BaseDiagnosticsTest.DiagnosticTestLanguageVersionSettings( + return result ?: CompilerTestLanguageVersionSettings( BaseDiagnosticsTest.DEFAULT_DIAGNOSTIC_TESTS_FEATURES, LanguageVersionSettingsImpl.DEFAULT.apiVersion, LanguageVersionSettingsImpl.DEFAULT.languageVersion diff --git a/compiler/tests-common/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.kt b/compiler/tests-common/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.kt index 1a738e9b079..4c191b1cfb6 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.kt +++ b/compiler/tests-common/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.kt @@ -28,7 +28,9 @@ import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestFile import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestModule import org.jetbrains.kotlin.checkers.CheckerTestUtil.ActualDiagnostic import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.diagnostics.* import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer @@ -111,19 +113,6 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava, - override val apiVersion: ApiVersion, - override val languageVersion: LanguageVersion - ) : LanguageVersionSettings { - private val delegate = LanguageVersionSettingsImpl(languageVersion, apiVersion) - - override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State = - languageFeatures[feature] ?: delegate.getFeatureSupport(feature) - - override fun getFlag(flag: AnalysisFlag): T = flag.defaultValue - } - inner class TestFile( val module: TestModule?, fileName: String, @@ -293,15 +282,10 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava): LanguageVersionSettings? { - val apiVersionString = directiveMap[API_VERSION_DIRECTIVE] - val directives = directiveMap[LANGUAGE_DIRECTIVE] - if (apiVersionString == null && directives == null) return null - - val apiVersion = (if (apiVersionString != null) ApiVersion.parse(apiVersionString) else ApiVersion.LATEST_STABLE) - ?: error("Unknown API version: $apiVersionString") - - val languageFeatures = directives?.let(this::collectLanguageFeatureMap).orEmpty() - - return DiagnosticTestLanguageVersionSettings(languageFeatures, apiVersion, LanguageVersion.LATEST_STABLE) - } - - private fun collectLanguageFeatureMap(directives: String): Map { - val matcher = LANGUAGE_PATTERN.matcher(directives) - if (!matcher.find()) { - Assert.fail( - "Wrong syntax in the '// !$LANGUAGE_DIRECTIVE: ...' directive:\n" + - "found: '$directives'\n" + - "Must be '((+|-|warn:)LanguageFeatureName)+'\n" + - "where '+' means 'enable', '-' means 'disable', 'warn:' means 'enable with warning'\n" + - "and language feature names are names of enum entries in LanguageFeature enum class" - ) - } - - val values = HashMap() - do { - val mode = when (matcher.group(1)) { - "+" -> LanguageFeature.State.ENABLED - "-" -> LanguageFeature.State.DISABLED - "warn:" -> LanguageFeature.State.ENABLED_WITH_WARNING - else -> error("Unknown mode for language feature: ${matcher.group(1)}") - } - val name = matcher.group(2) - val feature = LanguageFeature.fromString(name) ?: throw AssertionError( - "Language feature not found, please check spelling: $name\n" + - "Known features:\n ${LanguageFeature.values().joinToString("\n ")}" - ) - if (values.put(feature, mode) != null) { - Assert.fail("Duplicate entry for the language feature: $name") - } - } - while (matcher.find()) - - return values - } - private fun parseDiagnosticFilterDirective(directiveMap: Map, allowUnderscoreUsage: Boolean): Condition { val directives = directiveMap[DIAGNOSTICS_DIRECTIVE] val initialCondition = diff --git a/compiler/tests-common/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt b/compiler/tests-common/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt new file mode 100644 index 00000000000..b73fdf53f33 --- /dev/null +++ b/compiler/tests-common/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.checkers + +import org.jetbrains.kotlin.config.* +import org.junit.Assert +import java.util.* +import java.util.regex.Pattern + +const val LANGUAGE_DIRECTIVE = "LANGUAGE" +const val API_VERSION_DIRECTIVE = "API_VERSION" + +data class CompilerTestLanguageVersionSettings( + private val languageFeatures: Map, + override val apiVersion: ApiVersion, + override val languageVersion: LanguageVersion +) : LanguageVersionSettings { + private val delegate = LanguageVersionSettingsImpl(languageVersion, apiVersion) + + override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State = + languageFeatures[feature] ?: delegate.getFeatureSupport(feature) + + override fun getFlag(flag: AnalysisFlag): T = flag.defaultValue +} + +fun parseLanguageVersionSettings(directiveMap: Map): LanguageVersionSettings? { + val apiVersionString = directiveMap[API_VERSION_DIRECTIVE] + val directives = directiveMap[LANGUAGE_DIRECTIVE] + if (apiVersionString == null && directives == null) return null + + val apiVersion = (if (apiVersionString != null) ApiVersion.parse(apiVersionString) else ApiVersion.LATEST_STABLE) + ?: error("Unknown API version: $apiVersionString") + + val languageFeatures = directives?.let(::collectLanguageFeatureMap).orEmpty() + + return CompilerTestLanguageVersionSettings(languageFeatures, apiVersion, LanguageVersion.LATEST_STABLE) +} + +private val languagePattern = Pattern.compile("(\\+|\\-|warn:)(\\w+)\\s*") + +private fun collectLanguageFeatureMap(directives: String): Map { + val matcher = languagePattern.matcher(directives) + if (!matcher.find()) { + Assert.fail( + "Wrong syntax in the '// !$LANGUAGE_DIRECTIVE: ...' directive:\n" + + "found: '$directives'\n" + + "Must be '((+|-|warn:)LanguageFeatureName)+'\n" + + "where '+' means 'enable', '-' means 'disable', 'warn:' means 'enable with warning'\n" + + "and language feature names are names of enum entries in LanguageFeature enum class" + ) + } + + val values = HashMap() + do { + val mode = when (matcher.group(1)) { + "+" -> LanguageFeature.State.ENABLED + "-" -> LanguageFeature.State.DISABLED + "warn:" -> LanguageFeature.State.ENABLED_WITH_WARNING + else -> error("Unknown mode for language feature: ${matcher.group(1)}") + } + val name = matcher.group(2) + val feature = LanguageFeature.fromString(name) ?: throw AssertionError( + "Language feature not found, please check spelling: $name\n" + + "Known features:\n ${LanguageFeature.values().joinToString("\n ")}" + ) + if (values.put(feature, mode) != null) { + Assert.fail("Duplicate entry for the language feature: $name") + } + } + while (matcher.find()) + + return values +} diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java b/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java index deafe4c28bb..ba389c9d147 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java @@ -76,6 +76,7 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettingsKt.parseLanguageVersionSettings; import static org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt.writeAllTo; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*; import static org.jetbrains.kotlin.codegen.TestUtilsKt.*; @@ -161,8 +162,10 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { @NotNull List testFilesWithConfigurationDirectives, @NotNull CompilerConfiguration configuration ) { - List kotlinConfigurationFlags = new ArrayList<>(0); + LanguageVersionSettings explicitLanguageVersionSettings = null; LanguageVersion explicitLanguageVersion = null; + + List kotlinConfigurationFlags = new ArrayList<>(0); for (TestFile testFile : testFilesWithConfigurationDirectives) { kotlinConfigurationFlags.addAll(InTextDirectivesUtils.findListWithPrefixes(testFile.content, "// KOTLIN_CONFIGURATION_FLAGS:")); @@ -176,12 +179,22 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { String version = InTextDirectivesUtils.findStringWithPrefixes(testFile.content, "// LANGUAGE_VERSION:"); if (version != null) { - assert explicitLanguageVersion == null : "Should not specify LANGUAGE_VERSION twice"; + assertDirectivesToNull(explicitLanguageVersionSettings, explicitLanguageVersion); explicitLanguageVersion = LanguageVersion.fromVersionString(version); } + + Map directives = KotlinTestUtils.parseDirectives(testFile.content); + LanguageVersionSettings fileLanguageVersionSettings = parseLanguageVersionSettings(directives); + if (fileLanguageVersionSettings != null) { + assertDirectivesToNull(explicitLanguageVersionSettings, explicitLanguageVersion); + explicitLanguageVersionSettings = fileLanguageVersionSettings; + } } - if (explicitLanguageVersion != null) { + if (explicitLanguageVersionSettings != null) { + CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, explicitLanguageVersionSettings); + } + else if (explicitLanguageVersion != null) { CommonConfigurationKeysKt.setLanguageVersionSettings( configuration, new LanguageVersionSettingsImpl(explicitLanguageVersion, ApiVersion.createByLanguageVersion(explicitLanguageVersion)) @@ -191,6 +204,10 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { updateConfigurationWithFlags(configuration, kotlinConfigurationFlags); } + private static void assertDirectivesToNull(@Nullable LanguageVersionSettings settings, @Nullable LanguageVersion version) { + assert settings == null && version == null : "Should not specify LANGUAGE_VERSION twice or together with !LANGUAGE directive"; + } + private static final Map> FLAG_NAMESPACE_TO_CLASS = ImmutableMap.of( "CLI", CLIConfigurationKeys.class, "JVM", JVMConfigurationKeys.class