Working infrastructure for external dependencies testing

(not really, but at least something)
This commit is contained in:
Dmitry Petrov
2018-09-19 14:14:28 +03:00
parent 6022fb4ec3
commit ec8bdff5c7
5 changed files with 312 additions and 20 deletions
@@ -18,15 +18,19 @@ package org.jetbrains.kotlin.ir
import com.intellij.openapi.util.text.StringUtil
import junit.framework.TestCase
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.utils.rethrow
import java.io.File
@@ -42,9 +46,36 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() {
for ((testFile, irFile) in ktFiles.zip(irModule.files)) {
doTestIrFileAgainstExpectations(dir, testFile, irFile)
}
doTestIrModuleDependencies(wholeFile, irModule)
}
protected fun doTestIrFileAgainstExpectations(dir: File, testFile: TestFile, irFile: IrFile) {
private fun doTestIrModuleDependencies(wholeFile: File, irModule: IrModuleFragment) {
val wholeText = wholeFile.readText()
val stubGenerator = DeclarationStubGenerator(
irModule.descriptor,
SymbolTable(), // TODO
IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
myEnvironment.configuration.languageVersionSettings
)
for (externalClassFqn in parseDumpExternalClasses(wholeText)) {
val classDump = stubGenerator.generateExternalClass(irModule.descriptor, externalClassFqn).dump()
val expectedFile = File(wholeFile.path.replace(".kt", "__$externalClassFqn.txt"))
KotlinTestUtils.assertEqualsToFile(expectedFile, classDump)
}
}
private fun DeclarationStubGenerator.generateExternalClass(descriptor: ModuleDescriptor, externalClassFqn: String): IrClass {
val classDescriptor =
descriptor.findClassAcrossModuleDependencies(ClassId.topLevel(FqName(externalClassFqn)))
?: throw AssertionError("Can't find a class in external dependencies: $externalClassFqn")
return generateMemberStub(classDescriptor) as IrClass
}
private fun doTestIrFileAgainstExpectations(dir: File, testFile: TestFile, irFile: IrFile) {
if (testFile.isExternalFile()) return
val expectations = parseExpectations(dir, testFile)
@@ -244,36 +275,35 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() {
private val EXPECTED_OCCURRENCES_PATTERN = Regex("""^\s*//\s*(\d+)\s*(.*)$""")
private val IR_FILE_TXT_PATTERN = Regex("""// IR_FILE: (.*)$""")
private val DUMP_DEPENDENCIES_PATTERN = Regex("""// !DUMP_DEPENDENCIES""")
private val DUMP_EXTERNAL_CLASS = Regex("""// DUMP_EXTERNAL_CLASS (.*)""")
private val EXTERNAL_FILE_PATTERN = Regex("""// EXTERNAL_FILE""")
internal fun shouldDumpDependencies(wholeFile: File): Boolean =
DUMP_DEPENDENCIES_PATTERN.containsMatchIn(wholeFile.readText())
private inline fun <T> String.matchLinesWith(regex: Regex, ifMatched: (MatchResult) -> T): List<T> =
split("\n").mapNotNull { regex.matchEntire(it)?.let(ifMatched) }
internal fun parseDumpExternalClasses(text: String) =
text.matchLinesWith(DUMP_EXTERNAL_CLASS) { it.groupValues[1] }
internal fun TestFile.isExternalFile() =
EXTERNAL_FILE_PATTERN.containsMatchIn(content)
internal fun KtFile.isExternalFile() =
EXTERNAL_FILE_PATTERN.containsMatchIn(text)
internal fun parseExpectations(dir: File, testFile: TestFile): Expectations {
val regexps = ArrayList<RegexpInText>()
val treeFiles = ArrayList<IrTreeFileLabel>()
for (line in testFile.content.split("\n")) {
EXPECTED_OCCURRENCES_PATTERN.matchEntire(line)?.let { matchResult ->
regexps.add(RegexpInText(matchResult.groupValues[1], matchResult.groupValues[2].trim()))
} ?: IR_FILE_TXT_PATTERN.find(line)?.let { matchResult ->
val fileName = matchResult.groupValues[1].trim()
val file = createExpectedTextFile(testFile, dir, fileName)
treeFiles.add(IrTreeFileLabel(file, 0))
val regexps =
testFile.content.matchLinesWith(EXPECTED_OCCURRENCES_PATTERN) {
RegexpInText(it.groupValues[1], it.groupValues[2].trim())
}
var treeFiles =
testFile.content.matchLinesWith(IR_FILE_TXT_PATTERN) {
val fileName = it.groupValues[1].trim()
val file = createExpectedTextFile(testFile, dir, fileName)
IrTreeFileLabel(file, 0)
}
}
if (treeFiles.isEmpty()) {
val file = createExpectedTextFile(testFile, dir, testFile.name.replace(".kt", ".txt"))
treeFiles.add(IrTreeFileLabel(file, 0))
treeFiles = listOf(IrTreeFileLabel(file, 0))
}
return Expectations(regexps, treeFiles)