Support per files test directives

This commit is contained in:
Mikhael Bogdanov
2020-03-05 14:18:41 +01:00
committed by Mikhail Bogdanov
parent 34547b4e27
commit ab7e71fd68
29 changed files with 128 additions and 81 deletions
@@ -243,7 +243,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
expectedText,
object : TestFiles.TestFileFactoryNoModules<TestFile>() {
override fun create(fileName: String, text: String, directives: Map<String, String>): TestFile {
return TestFile(fileName, text)
return TestFile(fileName, text, directives)
}
}, false,
"kotlin.coroutines"
@@ -1,5 +1,5 @@
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// FILE: inline.kt
// WITH_RUNTIME
// FULL_JDK
// TARGET_BACKEND: JVM
@@ -11,7 +11,6 @@ inline fun inlineMe() {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
@@ -11,7 +11,6 @@ inline fun inlineMe() {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
@@ -1,6 +1,6 @@
// TARGET_BACKEND: JVM
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// FILE: inline.kt
// WITH_RUNTIME
// NO_CHECK_LAMBDA_INLINING
@@ -11,7 +11,6 @@ inline fun call(c: () -> Unit) {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
@@ -12,7 +12,6 @@ class A {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
class B {
@@ -17,7 +17,6 @@ class State {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
class CheckerJvmAssertInlineFunctionAssertionsEnabled {
@@ -1,6 +1,6 @@
// TARGET_BACKEND: JVM
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// FILE: inline.kt
// WITH_RUNTIME
// NO_CHECK_LAMBDA_INLINING
@@ -14,7 +14,6 @@ object CrossinlineLambdaContainer {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.CrossinlineLambdaContainer.call
@@ -1,6 +1,6 @@
// TARGET_BACKEND: JVM
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// FILE: inline.kt
// WITH_RUNTIME
// NO_CHECK_LAMBDA_INLINING
@@ -17,7 +17,6 @@ object CrossinlineLambdaContainer {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.CrossinlineLambdaContainer.call
@@ -1,6 +1,6 @@
// TARGET_BACKEND: JVM
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// FILE: inline.kt
// WITH_RUNTIME
// NO_CHECK_LAMBDA_INLINING
@@ -17,7 +17,6 @@ object CrossinlineLambdaContainer {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.CrossinlineLambdaContainer.call
@@ -14,7 +14,6 @@ object CrossinlineLambdaContainer {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.CrossinlineLambdaContainer.call
@@ -13,7 +13,6 @@ object CrossinlineLambdaContainer {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.CrossinlineLambdaContainer.call
@@ -19,7 +19,6 @@ class B {
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
class Checker {
@@ -1,12 +1,12 @@
// TODO: split SKIP_INLINE_CHECK_IN by files
// SKIP_INLINE_CHECK_IN: bar$default, foo$default
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: bar$default
package test
inline fun bar(f: () -> String = { "OK" }) = f()
// FILE: 2.kt
import test.*
// SKIP_INLINE_CHECK_IN: foo$default
inline fun foo(f: () -> String = { bar() }) = f()
fun box(): String {
@@ -57,8 +57,8 @@ abstract class AbstractCompilerLightClassTest : KotlinMultiFileTestWithJava<Kotl
module: TestModule?,
fileName: String,
text: String,
directives: Map<String, String>
): TestFile = TestFile(fileName, text)
directives: Map<String, String?>
): TestFile = TestFile(fileName, text, directives)
companion object {
fun findLightClass(allowFrontendExceptions: Boolean, environment: KotlinCoreEnvironment, fqname: String): PsiClass? {
@@ -83,7 +83,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
): TestModule =
TestModule(name, dependencies, friends)
override fun createTestFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String>): TestFile =
override fun createTestFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String?>): TestFile =
TestFile(module, fileName, text, directives)
@@ -138,8 +138,8 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
val module: TestModule?,
val fileName: String,
textWithMarkers: String,
val directives: Map<String, String>
) : KotlinBaseTest.TestFile(fileName, textWithMarkers) {
directives: Map<String, String?>
) : KotlinBaseTest.TestFile(fileName, textWithMarkers, directives) {
val diagnosedRanges: MutableList<DiagnosedRange> = mutableListOf()
private val diagnosedRangesToDiagnosticNames: MutableMap<IntRange, MutableSet<String>> = mutableMapOf()
val actualDiagnostics: MutableList<ActualDiagnostic> = mutableListOf()
@@ -411,7 +411,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
val DIAGNOSTIC_IN_TESTDATA_PATTERN = Regex("<!>|<!(.*?(\\(\".*?\"\\)|\\(\\))??)+(?<!<)!>")
fun parseDiagnosticFilterDirective(
directiveMap: Map<String, String>,
directiveMap: Map<String, String?>,
allowUnderscoreUsage: Boolean
): Condition<Diagnostic> {
val directives = directiveMap[DIAGNOSTICS_DIRECTIVE]
@@ -499,7 +499,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
}
}
private fun parseJvmTarget(directiveMap: Map<String, String>) = directiveMap[JVM_TARGET]?.let { JvmTarget.fromString(it) }
private fun parseJvmTarget(directiveMap: Map<String, String?>) = directiveMap[JVM_TARGET]?.let { JvmTarget.fromString(it) }
protected fun parseModulePlatformByName(moduleName: String): TargetPlatform? {
val nameSuffix = moduleName.substringAfterLast("-", "").toUpperCase()
@@ -53,7 +53,7 @@ private fun specificFeaturesForTests(): Map<LanguageFeature, LanguageFeature.Sta
fun parseLanguageVersionSettingsOrDefault(directiveMap: Map<String, String>): CompilerTestLanguageVersionSettings =
parseLanguageVersionSettings(directiveMap) ?: defaultLanguageVersionSettings()
fun parseLanguageVersionSettings(directives: Map<String, String>): CompilerTestLanguageVersionSettings? {
fun parseLanguageVersionSettings(directives: Map<String, String?>): CompilerTestLanguageVersionSettings? {
val apiVersionString = directives[API_VERSION_DIRECTIVE]
val languageFeaturesString = directives[LANGUAGE_DIRECTIVE]
@@ -119,7 +119,7 @@ abstract class KotlinMultiFileTestWithJava<M : KotlinBaseTest.TestModule, F : Ko
protected abstract fun createTestModule(name: String, dependencies: List<String>, friends: List<String>): M?
protected abstract fun createTestFile(module: M?, fileName: String, text: String, directives: Map<String, String>): F
protected abstract fun createTestFile(module: M?, fileName: String, text: String, directives: Map<String, String?>): F
protected open fun createTestFiles(
file: File,
@@ -22,7 +22,7 @@ abstract class AbstractBlackBoxInlineCodegenTest : AbstractBlackBoxCodegenTest()
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
super.doMultiFileTest(wholeFile, files)
try {
InlineTestUtil.checkNoCallsToInline(initializedClassLoader.allGeneratedFiles.filterClassFiles(), myFiles.psiFiles)
InlineTestUtil.checkNoCallsToInline(initializedClassLoader.allGeneratedFiles.filterClassFiles(), files)
SMAPTestUtil.checkSMAP(files, generateClassesInFile().getClassFiles(), false)
} catch (e: Throwable) {
println(generateToText())
@@ -29,7 +29,7 @@ abstract class AbstractCompileKotlinAgainstInlineKotlinTest : AbstractCompileKot
try {
val allGeneratedFiles = factory1.asList() + factory2.asList()
val sourceFiles = factory1.inputFiles + factory2.inputFiles
InlineTestUtil.checkNoCallsToInline(allGeneratedFiles.filterClassFiles(), sourceFiles)
InlineTestUtil.checkNoCallsToInline(allGeneratedFiles.filterClassFiles(), files)
SMAPTestUtil.checkSMAP(files, allGeneratedFiles.filterClassFiles(), true)
} catch (e: Throwable) {
if (!isIgnored) {
@@ -83,6 +83,11 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
callBoxMethodAndCheckResult(createGeneratedClassLoader(), className);
}
@Override
protected boolean parseDirectivesPerFiles() {
return true;
}
@NotNull
private URLClassLoader createGeneratedClassLoader() throws Exception {
return new URLClassLoader(
@@ -70,6 +70,7 @@ import static org.jetbrains.kotlin.cli.common.output.OutputUtilsKt.writeAllTo;
import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*;
import static org.jetbrains.kotlin.codegen.TestUtilsKt.extractUrls;
import static org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar;
import static org.jetbrains.kotlin.test.KotlinTestUtils.parseDirectivesAndFlags;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getBoxMethodOrNull;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getGeneratedClass;
@@ -131,7 +132,7 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
CompilerConfiguration configuration = KotlinTestUtils.newConfiguration(kind, jdkKind, classpath, javaSource);
configuration.put(JVMConfigurationKeys.IR, getBackend().isIR());
updateConfigurationByDirectivesInTestFiles(testFilesWithConfigurationDirectives, configuration, coroutinesPackage);
updateConfigurationByDirectivesInTestFiles(testFilesWithConfigurationDirectives, configuration, coroutinesPackage, parseDirectivesPerFiles());
updateConfiguration(configuration);
setCustomDefaultJvmTarget(configuration);
@@ -144,13 +145,14 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
@NotNull List<TestFile> testFilesWithConfigurationDirectives,
@NotNull CompilerConfiguration configuration
) {
updateConfigurationByDirectivesInTestFiles(testFilesWithConfigurationDirectives, configuration, "");
updateConfigurationByDirectivesInTestFiles(testFilesWithConfigurationDirectives, configuration, "", false);
}
private static void updateConfigurationByDirectivesInTestFiles(
@NotNull List<TestFile> testFilesWithConfigurationDirectives,
@NotNull CompilerConfiguration configuration,
@NotNull String coroutinesPackage
@NotNull String coroutinesPackage,
boolean usePreparsedDirectives
) {
LanguageVersionSettings explicitLanguageVersionSettings = null;
boolean disableReleaseCoroutines = false;
@@ -158,17 +160,22 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
List<String> kotlinConfigurationFlags = new ArrayList<>(0);
for (TestFile testFile : testFilesWithConfigurationDirectives) {
kotlinConfigurationFlags.addAll(InTextDirectivesUtils.findListWithPrefixes(testFile.content, "// KOTLIN_CONFIGURATION_FLAGS:"));
String content = testFile.content;
Map<String, String> directives = usePreparsedDirectives ? testFile.directives : parseDirectivesAndFlags(content);
List<String> lines = InTextDirectivesUtils.findLinesWithPrefixesRemoved(testFile.content, "// JVM_TARGET:");
if (!lines.isEmpty()) {
String targetString = CollectionsKt.single(lines);
String configurationFlags = directives.get("KOTLIN_CONFIGURATION_FLAGS");
if (configurationFlags != null) {
kotlinConfigurationFlags.addAll(InTextDirectivesUtils.splitValues(new ArrayList<>(), configurationFlags));
}
String targetString = directives.get("JVM_TARGET");
if (targetString != null) {
JvmTarget jvmTarget = JvmTarget.Companion.fromString(targetString);
assert jvmTarget != null : "Unknown target: " + targetString;
configuration.put(JVMConfigurationKeys.JVM_TARGET, jvmTarget);
}
String version = InTextDirectivesUtils.findStringWithPrefixes(testFile.content, "// LANGUAGE_VERSION:");
String version = directives.get("LANGUAGE_VERSION");
if (version != null) {
throw new AssertionError(
"Do not use LANGUAGE_VERSION directive in compiler tests because it's prone to limiting the test\n" +
@@ -178,20 +185,18 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
);
}
if (!InTextDirectivesUtils.findLinesWithPrefixesRemoved(testFile.content, "// COMMON_COROUTINES_TEST").isEmpty()) {
assert !testFile.content.contains("COROUTINES_PACKAGE") : "Must replace COROUTINES_PACKAGE prior to tests compilation";
if (directives.containsKey("COMMON_COROUTINES_TEST")) {
assert !directives.containsKey("COROUTINES_PACKAGE") : "Must replace COROUTINES_PACKAGE prior to tests compilation";
if (DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString().equals(coroutinesPackage)) {
disableReleaseCoroutines = true;
includeCompatExperimentalCoroutines = true;
}
}
if (testFile.content.contains(DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString())) {
if (content.contains(DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString())) {
includeCompatExperimentalCoroutines = true;
}
Map<String, String> directives = KotlinTestUtils.parseDirectives(testFile.content);
LanguageVersionSettings fileLanguageVersionSettings = parseLanguageVersionSettings(directives);
if (fileLanguageVersionSettings != null) {
assert explicitLanguageVersionSettings == null : "Should not specify !LANGUAGE directive twice";
@@ -770,20 +775,24 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
@Override
@NotNull
protected List<TestFile> createTestFilesFromFile(File file, String expectedText) {
protected List<TestFile> createTestFilesFromFile(File file, @NotNull String expectedText) {
List testFiles = TestFiles.createTestFiles(file.getName(), expectedText, new TestFiles.TestFileFactoryNoModules<TestFile>() {
@NotNull
@Override
public TestFile create(@NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives) {
return new TestFile(fileName, text);
return new TestFile(fileName, text, directives);
}
}, coroutinesPackage);
}, false, coroutinesPackage, parseDirectivesPerFiles());
if (InTextDirectivesUtils.isDirectiveDefined(expectedText, "WITH_HELPERS")) {
testFiles.add(new TestFile("CodegenTestHelpers.kt", TestHelperGeneratorKt.createTextForCodegenTestHelpers(getBackend())));
}
return testFiles;
}
protected boolean parseDirectivesPerFiles() {
return false;
}
@NotNull
protected File getJavaSourcesOutputDirectory() {
return createTempDirectory("java-files");
@@ -27,12 +27,13 @@ import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinBaseTest
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.*
object InlineTestUtil {
fun checkNoCallsToInline(outputFiles: Iterable<OutputFile>, sourceFiles: List<KtFile>) {
fun checkNoCallsToInline(outputFiles: Iterable<OutputFile>, files: List<KotlinBaseTest.TestFile>) {
val inlineInfo = obtainInlineInfo(outputFiles)
val inlineMethods = inlineInfo.inlineMethods
assert(inlineMethods.isNotEmpty()) { "There are no inline methods" }
@@ -40,12 +41,12 @@ object InlineTestUtil {
val notInlinedCalls = checkInlineMethodNotInvoked(outputFiles, inlineMethods)
assert(notInlinedCalls.isEmpty()) { "All inline methods should be inlined but:\n" + notInlinedCalls.joinToString("\n") }
val skipParameterChecking = sourceFiles.any {
InTextDirectivesUtils.isDirectiveDefined(it.text, "NO_CHECK_LAMBDA_INLINING")
val skipParameterChecking = files.any {
it.directives.containsKey("NO_CHECK_LAMBDA_INLINING")
} || !doLambdaInliningCheck(outputFiles, inlineInfo)
if (!skipParameterChecking) {
val notInlinedParameters = checkParametersInlined(outputFiles, inlineInfo, sourceFiles)
val notInlinedParameters = checkParametersInlined(outputFiles, inlineInfo, files)
assert(notInlinedParameters.isEmpty()) {
"All inline parameters should be inlined but:\n${notInlinedParameters.joinToString("\n")}\n" +
"but if you have not inlined lambdas or anonymous objects enable NO_CHECK_LAMBDA_INLINING directive"
@@ -167,11 +168,11 @@ object InlineTestUtil {
}
private fun checkParametersInlined(
outputFiles: Iterable<OutputFile>, inlineInfo: InlineInfo, sourceFiles: List<KtFile>
outputFiles: Iterable<OutputFile>, inlineInfo: InlineInfo, files: List<KotlinBaseTest.TestFile>
): ArrayList<NotInlinedParameter> {
val skipMethods =
sourceFiles.flatMap {
InTextDirectivesUtils.findLinesWithPrefixesRemoved(it.text, "// SKIP_INLINE_CHECK_IN: ")
files.flatMap {
it.getListDirectiveIfPresent("SKIP_INLINE_CHECK_IN") ?: emptyList()
}.toSet()
val inlinedMethods = inlineInfo.inlineMethods
@@ -62,21 +62,26 @@ public final class InTextDirectivesUtils {
List<String> result = new ArrayList<>();
for (String line : findLinesWithPrefixesRemoved(fileText, prefixes)) {
String unquoted = StringUtil.unquoteString(line);
if (!unquoted.equals(line)) {
result.add(unquoted);
}
else{
String[] variants = line.split(",");
for (String variant : variants) {
result.add(variant.trim());
}
}
splitValues(result, line);
}
return result;
}
public static List<String> splitValues(List<String> result, String line) {
String unquoted = StringUtil.unquoteString(line);
if (!unquoted.equals(line)) {
result.add(unquoted);
}
else{
String[] variants = line.split(",");
for (String variant : variants) {
result.add(variant.trim());
}
}
return result;
}
public static boolean isDirectiveDefined(String fileText, String directive) {
return !findListWithPrefixes(fileText, directive).isEmpty();
}
@@ -70,7 +70,11 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
}
open class TestFile(@JvmField val name: String, @JvmField val content: String) : Comparable<TestFile> {
open class TestFile @JvmOverloads constructor(
@JvmField val name: String,
@JvmField val content: String,
@JvmField val directives: Map<String, String?> = emptyMap()
) : Comparable<TestFile> {
override operator fun compareTo(other: TestFile): Int {
return name.compareTo(other.name)
}
@@ -86,6 +90,12 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
override fun toString(): String {
return name
}
fun getListDirectiveIfPresent(name: String): List<String>? {
return directives[name]?.let {
InTextDirectivesUtils.splitValues(arrayListOf(), it)
} ?: emptyList()
}
}
open class TestModule(
@@ -98,6 +98,7 @@ public class KotlinTestUtils {
private static final List<File> filesToDelete = new ArrayList<>();
static final Pattern DIRECTIVE_PATTERN = Pattern.compile("^//\\s*!([\\w_]+)(:\\s*(.*)$)?", Pattern.MULTILINE);
static final Pattern BACKEND_DIRECTIVE_PATTERN = Pattern.compile("^//\\s*(FULL_JDK|JVM_TARGET|KOTLIN_CONFIGURATION_FLAGS|LANGUAGE_VERSION|COMMON_COROUTINES_TEST|COROUTINES_PACKAGE|WITH_RUNTIME|WITH_REFLECT|NO_CHECK_LAMBDA_INLINING|SKIP_INLINE_CHECK_IN)(:[ \\t]*(.*)$)?", Pattern.MULTILINE);
private KotlinTestUtils() {
}
@@ -526,16 +527,27 @@ public class KotlinTestUtils {
@NotNull
public static Map<String, String> parseDirectives(String expectedText) {
Map<String, String> directives = new HashMap<>();
Matcher directiveMatcher = DIRECTIVE_PATTERN.matcher(expectedText);
return parseByRegexp(DIRECTIVE_PATTERN, expectedText, directives);
}
private static Map<String, String> parseByRegexp(Pattern pattern, String expectedText, Map<String, String> directives) {
Matcher directiveMatcher = pattern.matcher(expectedText);
while (directiveMatcher.find()) {
String name = directiveMatcher.group(1);
String value = directiveMatcher.group(3);
String oldValue = directives.put(name, value);
Assert.assertNull("Directive overwritten: " + name + " old value: " + oldValue + " new value: " + value, oldValue);
Assert.assertNull("Directive or flag overwritten: " + name + " old value: " + oldValue + " new value: " + value, oldValue);
}
return directives;
}
@NotNull
public static Map<String, String> parseDirectivesAndFlags(String expectedText) {
Map<String, String> directiveAndFlags = parseDirectives(expectedText);
parseByRegexp(BACKEND_DIRECTIVE_PATTERN, expectedText, directiveAndFlags);
return directiveAndFlags;
}
public static List<String> loadBeforeAfterText(String filePath) {
String content;
@@ -19,6 +19,8 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.jetbrains.kotlin.test.InTextDirectivesUtils.isDirectiveDefined;
import static org.jetbrains.kotlin.test.KotlinTestUtils.parseDirectives;
import static org.jetbrains.kotlin.test.KotlinTestUtils.parseDirectivesAndFlags;
public class TestFiles {
/**
@@ -51,19 +53,30 @@ public class TestFiles {
@NotNull
public static <M extends KotlinBaseTest.TestModule, F> List<F> createTestFiles(String testFileName, String expectedText, TestFileFactory<M , F> factory,
boolean preserveLocations, String coroutinesPackage) {
Map<String, String> directives = KotlinTestUtils.parseDirectives(expectedText);
return createTestFiles(testFileName, expectedText, factory, preserveLocations, coroutinesPackage, false);
}
@NotNull
public static <M extends KotlinBaseTest.TestModule, F> List<F> createTestFiles(String testFileName, String expectedText, TestFileFactory<M , F> factory,
boolean preserveLocations, String coroutinesPackage, boolean parseDirectivesPerFile) {
Map<String, M> modules = new HashMap<>();
List<F> testFiles = Lists.newArrayList();
Matcher matcher = FILE_OR_MODULE_PATTERN.matcher(expectedText);
boolean hasModules = false;
String commonPrefixOrWholeFile;
if (!matcher.find()) {
assert testFileName != null : "testFileName should not be null if no FILE directive defined";
// One file
testFiles.add(factory.createFile(null, testFileName, expectedText, directives));
testFiles.add(factory.createFile(null, testFileName, expectedText, parseDirectivesAndFlags(expectedText)));
commonPrefixOrWholeFile = expectedText;
}
else {
Map<String, String> allFilesOrCommonPrefixDirectives = parseDirectivesPerFile ? null : parseDirectivesAndFlags(expectedText);
int processedChars = 0;
M module = null;
boolean firstFileProcessed = false;
commonPrefixOrWholeFile = expectedText.substring(0, matcher.start());
// Many files
while (true) {
String moduleName = matcher.group(1);
@@ -91,10 +104,14 @@ public class TestFiles {
String fileText = preserveLocations ?
substringKeepingLocations(expectedText, start, end) :
expectedText.substring(start,end);
testFiles.add(factory.createFile(module, fileName, fileText,
parseDirectivesPerFile ?
parseDirectivesAndFlags(firstFileProcessed ? commonPrefixOrWholeFile + fileText : fileText)
: allFilesOrCommonPrefixDirectives));
processedChars = end;
testFiles.add(factory.createFile(module, fileName, fileText, directives));
firstFileProcessed = true;
if (!nextFileExists) break;
}
assert processedChars == expectedText.length() : "Characters skipped from " +
@@ -123,7 +140,7 @@ public class TestFiles {
"CoroutineUtil.kt",
TestHelperGeneratorKt.createTextForCoroutineHelpers(
isReleaseCoroutines, checkStateMachine, checkTailCallOptimization),
directives
parseDirectives(commonPrefixOrWholeFile)
));
}
@@ -5,11 +5,9 @@
package org.jetbrains.kotlin.visualizer
import org.jetbrains.kotlin.test.KotlinBaseTest
import org.jetbrains.kotlin.checkers.KotlinMultiFileTestWithJava
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.KotlinBaseTest
import java.io.File
abstract class AbstractVisualizer : KotlinMultiFileTestWithJava<KotlinBaseTest.TestModule, KotlinBaseTest.TestFile>() {
@@ -22,8 +20,8 @@ abstract class AbstractVisualizer : KotlinMultiFileTestWithJava<KotlinBaseTest.T
): TestModule? = null
override fun createTestFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String>): TestFile =
TestFile(fileName, text)
override fun createTestFile(module: TestModule?, fileName: String, text: String, directives: Map<String, String?>): TestFile =
TestFile(fileName, text, directives)
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
@@ -129,8 +129,8 @@ abstract class KotlinDescriptorTestCase : DescriptorTestCase() {
wholeFile.name,
wholeFileContents,
object : org.jetbrains.kotlin.test.TestFiles.TestFileFactoryNoModules<TestFile>() {
override fun create(fileName: String, text: String, directives: Map<String, String>): TestFile {
return TestFile(fileName, text)
override fun create(fileName: String, text: String, directives: Map<String, String?>): TestFile {
return TestFile(fileName, text, directives)
}
}
)
@@ -147,7 +147,7 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
KotlinTestUtils.mkdirs(temporaryFile.parentFile)
temporaryFile.writeText(text, Charsets.UTF_8)
return TestFile(temporaryFile.absolutePath, text, currentModule)
return TestFile(temporaryFile.absolutePath, text, currentModule, directives)
}
override fun createModule(name: String, dependencies: List<String>, friends: List<String>) = TestModule(name, dependencies, friends)
@@ -165,7 +165,8 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() {
val files = mutableListOf<TestFile>()
}
private class TestFile(val fileName: String, content: String, val module: TestModule) : KotlinBaseTest.TestFile(fileName, content) {
private class TestFile(val fileName: String, content: String, val module: TestModule, directives: Map<String, String?>) :
KotlinBaseTest.TestFile(fileName, content, directives) {
init {
module.files += this
}