Use multimap for directives

This commit is contained in:
Mikhail Bogdanov
2020-03-17 09:12:01 +01:00
parent 420dd0d440
commit d793fea8d2
6 changed files with 31 additions and 38 deletions
@@ -70,7 +70,6 @@ import static org.jetbrains.kotlin.cli.common.output.OutputUtilsKt.writeAllTo;
import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*;
import static org.jetbrains.kotlin.codegen.TestUtilsKt.extractUrls; import static org.jetbrains.kotlin.codegen.TestUtilsKt.extractUrls;
import static org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar; 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.getBoxMethodOrNull;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getGeneratedClass; import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getGeneratedClass;
@@ -161,11 +160,10 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
List<String> kotlinConfigurationFlags = new ArrayList<>(0); List<String> kotlinConfigurationFlags = new ArrayList<>(0);
for (TestFile testFile : testFilesWithConfigurationDirectives) { for (TestFile testFile : testFilesWithConfigurationDirectives) {
String content = testFile.content; String content = testFile.content;
Directives directives = usePreparsedDirectives ? testFile.directives : parseDirectivesAndFlags(content); Directives directives = usePreparsedDirectives ? testFile.directives : KotlinTestUtils.parseDirectives(content);
List<String> flags = directives.listValues("KOTLIN_CONFIGURATION_FLAGS");
String configurationFlags = directives.get("KOTLIN_CONFIGURATION_FLAGS"); if (flags != null) {
if (configurationFlags != null) { kotlinConfigurationFlags.addAll(flags);
kotlinConfigurationFlags.addAll(InTextDirectivesUtils.splitValues(new ArrayList<>(), configurationFlags));
} }
String targetString = directives.get("JVM_TARGET"); String targetString = directives.get("JVM_TARGET");
@@ -25,8 +25,6 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader 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.kotlin.test.KotlinBaseTest
import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
@@ -172,7 +170,7 @@ object InlineTestUtil {
): ArrayList<NotInlinedParameter> { ): ArrayList<NotInlinedParameter> {
val skipMethods = val skipMethods =
files.flatMap { files.flatMap {
it.getListDirectiveIfPresent("SKIP_INLINE_CHECK_IN") ?: emptyList() it.directives.listValues("SKIP_INLINE_CHECK_IN") ?: emptyList()
}.toSet() }.toSet()
val inlinedMethods = inlineInfo.inlineMethods val inlinedMethods = inlineInfo.inlineMethods
@@ -7,18 +7,33 @@ package org.jetbrains.kotlin.test
class Directives { class Directives {
private val directives = mutableMapOf<String, String?>() private val directives = mutableMapOf<String, MutableList<String>?>()
operator fun contains(key: String): Boolean { operator fun contains(key: String): Boolean {
return key in directives return key in directives
} }
operator fun get(key: String): String? { operator fun get(key: String): String? {
return directives[key] return directives[key]?.single()
} }
fun put(key: String, value: String?): String? { fun put(key: String, value: String?) {
return directives.put(key, value) if (value == null) {
directives[key] = null
} else {
directives.getOrPut(key, { arrayListOf() })!!.add(value)
}
}
// Such values could be defined several times, e.g
// MY_DIRECTIVE: XXX
// MY_DIRECTIVE: YYY
// or
// MY_DIRECTIVE: XXX, YYY
fun listValues(name: String): List<String>? {
return directives[name]?.let { values ->
values.flatMap { InTextDirectivesUtils.splitValues(arrayListOf(), it) }
}
} }
public fun asMapOfSingleValues(): Map<String, String?> { public fun asMapOfSingleValues(): Map<String, String?> {
@@ -91,11 +91,6 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
return name return name
} }
fun getListDirectiveIfPresent(name: String): List<String>? {
return directives[name]?.let {
InTextDirectivesUtils.splitValues(arrayListOf(), it)
} ?: emptyList()
}
} }
open class TestModule( open class TestModule(
@@ -97,8 +97,7 @@ public class KotlinTestUtils {
private static final List<File> filesToDelete = new ArrayList<>(); private static final List<File> filesToDelete = new ArrayList<>();
static final Pattern DIRECTIVE_PATTERN = Pattern.compile("^//\\s*!([\\w_]+)(:\\s*(.*)$)?", Pattern.MULTILINE); private static final Pattern DIRECTIVE_PATTERN = Pattern.compile("^//\\s*[!]?([A-Z_]+)(:[ \\t]*(.*))?$", 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() { private KotlinTestUtils() {
} }
@@ -531,27 +530,15 @@ public class KotlinTestUtils {
@NotNull @NotNull
public static Directives parseDirectives(String expectedText, @NotNull Directives directives) { public static Directives parseDirectives(String expectedText, @NotNull Directives directives) {
return parseByRegexp(DIRECTIVE_PATTERN, expectedText, directives); Matcher directiveMatcher = DIRECTIVE_PATTERN.matcher(expectedText);
}
private static Directives parseByRegexp(Pattern pattern, String expectedText, Directives directives) {
Matcher directiveMatcher = pattern.matcher(expectedText);
while (directiveMatcher.find()) { while (directiveMatcher.find()) {
String name = directiveMatcher.group(1); String name = directiveMatcher.group(1);
String value = directiveMatcher.group(3); String value = directiveMatcher.group(3);
String oldValue = directives.put(name, value); directives.put(name, value);
Assert.assertNull("Directive or flag overwritten: " + name + " old value: " + oldValue + " new value: " + value, oldValue);
} }
return directives; return directives;
} }
@NotNull
public static Directives parseDirectivesAndFlags(String expectedText) {
Directives directiveAndFlags = parseDirectives(expectedText);
parseByRegexp(BACKEND_DIRECTIVE_PATTERN, expectedText, directiveAndFlags);
return directiveAndFlags;
}
public static List<String> loadBeforeAfterText(String filePath) { public static List<String> loadBeforeAfterText(String filePath) {
String content; String content;
@@ -20,7 +20,6 @@ import java.util.stream.Collectors;
import static org.jetbrains.kotlin.test.InTextDirectivesUtils.isDirectiveDefined; import static org.jetbrains.kotlin.test.InTextDirectivesUtils.isDirectiveDefined;
import static org.jetbrains.kotlin.test.KotlinTestUtils.parseDirectives; import static org.jetbrains.kotlin.test.KotlinTestUtils.parseDirectives;
import static org.jetbrains.kotlin.test.KotlinTestUtils.parseDirectivesAndFlags;
public class TestFiles { public class TestFiles {
/** /**
@@ -67,11 +66,11 @@ public class TestFiles {
if (!matcher.find()) { if (!matcher.find()) {
assert testFileName != null : "testFileName should not be null if no FILE directive defined"; assert testFileName != null : "testFileName should not be null if no FILE directive defined";
// One file // One file
testFiles.add(factory.createFile(null, testFileName, expectedText, parseDirectivesAndFlags(expectedText))); testFiles.add(factory.createFile(null, testFileName, expectedText, parseDirectives(expectedText)));
commonPrefixOrWholeFile = expectedText; commonPrefixOrWholeFile = expectedText;
} }
else { else {
Directives allFilesOrCommonPrefixDirectives = parseDirectivesPerFile ? null : parseDirectivesAndFlags(expectedText); Directives allFilesOrCommonPrefixDirectives = parseDirectivesPerFile ? null : parseDirectives(expectedText);
int processedChars = 0; int processedChars = 0;
M module = null; M module = null;
boolean firstFileProcessed = false; boolean firstFileProcessed = false;
@@ -106,9 +105,10 @@ public class TestFiles {
expectedText.substring(start,end); expectedText.substring(start,end);
String expectedText1 = firstFileProcessed ? commonPrefixOrWholeFile + fileText : fileText;
testFiles.add(factory.createFile(module, fileName, fileText, testFiles.add(factory.createFile(module, fileName, fileText,
parseDirectivesPerFile ? parseDirectivesPerFile ?
parseDirectivesAndFlags(firstFileProcessed ? commonPrefixOrWholeFile + fileText : fileText) parseDirectives(expectedText1)
: allFilesOrCommonPrefixDirectives)); : allFilesOrCommonPrefixDirectives));
processedChars = end; processedChars = end;
firstFileProcessed = true; firstFileProcessed = true;