[stub builder] introduce a separate testsuite where classfiles generated by the K2 compiler

The result of k1/k2 should be similar here, the differences should be fixed by KT-60764
This commit is contained in:
Ilya Kirillov
2023-07-27 14:13:08 +02:00
committed by Space Team
parent 2ab73f286a
commit 419c0c83e3
7 changed files with 123 additions and 8 deletions
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.decompiler.stub.files
abstract class AbstractAdditionalStubInfoK2CompilerTest : AbstractAdditionalStubInfoTest() {
override val useK2ToCompileCode = true
}
@@ -22,7 +22,8 @@ abstract class AbstractAdditionalStubInfoTest : AbstractDecompiledClassTest() {
val stub = KotlinClsStubBuilder().buildFileStub(FileContentImpl.createByFile(getClassFileToDecompile(testData, false)))!!
val builder = StringBuilder()
extractAdditionInfo(stub, builder, 0)
KotlinTestUtils.assertEqualsToFile(testData.expectedFile, builder.toString())
KotlinTestUtils.assertEqualsToFile(testData.getExpectedFile(useK2ToCompileCode), builder.toString())
testData.checkIfIdentical(useK2ToCompileCode)
}
private fun extractAdditionInfo(stub: StubElement<*>, builder: StringBuilder, level: Int) {
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.decompiler.stub.files
abstract class AbstractClsStubBuilderK2CompilerTest : AbstractClsStubBuilderTest() {
override val useK2ToCompileCode: Boolean = true
}
@@ -9,23 +9,29 @@ import com.intellij.core.CoreApplicationEnvironment
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import org.jetbrains.kotlin.analysis.decompiler.stub.file.CachedAttributeData
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
import org.jetbrains.kotlin.analysis.decompiler.stub.file.DummyFileAttributeService
import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.test.*
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.utils.FirIdenticalCheckerHelper
import org.jetbrains.kotlin.utils.addIfNotNull
import java.io.DataInput
import java.io.DataOutput
import java.nio.file.Files
import java.nio.file.Path
import java.util.stream.Collectors
import kotlin.io.path.absolutePathString
import kotlin.io.path.name
import kotlin.io.path.readText
import org.jetbrains.kotlin.test.services.JUnit5Assertions
import java.io.File
import org.jetbrains.kotlin.test.services.AssertionsService
abstract class AbstractDecompiledClassTest : KotlinTestWithEnvironment() {
protected open val useK2ToCompileCode: Boolean = false
override fun createEnvironment(): KotlinCoreEnvironment {
return KotlinTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(
ApplicationEnvironmentDisposer.ROOT_DISPOSABLE,
@@ -55,6 +61,7 @@ abstract class AbstractDecompiledClassTest : KotlinTestWithEnvironment() {
this.add("-Xuse-type-table")
}
this.addAll(testData.additionalCompilerOptions)
addAll(listOf("-language-version", getLanguageVersionToCompile().versionString))
}
val library = CompilerTestUtil.compileJvmLibrary(
src = testData.directory.toFile(),
@@ -65,6 +72,16 @@ abstract class AbstractDecompiledClassTest : KotlinTestWithEnvironment() {
)
}
private fun getLanguageVersionToCompile(): LanguageVersion {
return if (useK2ToCompileCode) {
val k2Version = maxOf(LanguageVersion.LATEST_STABLE, LanguageVersion.KOTLIN_2_0)
check(k2Version.usesK2)
k2Version
} else {
LanguageVersion.KOTLIN_1_9
}
}
private fun findClassFileByName(library: Path, className: String): VirtualFile {
val jarFileSystem = environment.projectEnvironment.environment.jarFileSystem as CoreJarFileSystem
val root = jarFileSystem.refreshAndFindFileByPath(library.absolutePathString() + "!/")!!
@@ -93,6 +110,37 @@ internal data class TestData(
val jvmFileName: String,
val additionalCompilerOptions: List<String>,
) {
fun containsDirective(directive: String): Boolean {
return InTextDirectivesUtils.isDirectiveDefined(mainKotlinFile.readText(), "// $directive")
}
fun <R : Any> withFirIgnoreDirective(action: () -> R): R? {
val directive = "FIR_IGNORE"
if (containsDirective(directive)) return null
return action()
}
fun getExpectedFile(useK2: Boolean): Path {
if (useK2) {
IdenticalCheckerHelper.getFirFileToCompare(expectedFile.toFile()).takeIf { it.exists() }?.let { return it.toPath() }
}
return expectedFile
}
fun checkIfIdentical(useK2: Boolean) {
if (containsDirective(FirDiagnosticsDirectives.FIR_IDENTICAL.name)) {
return
}
if (useK2) {
if (IdenticalCheckerHelper.firAndClassicContentsAreEquals(expectedFile.toFile())) {
IdenticalCheckerHelper.deleteFirFile(expectedFile.toFile())
IdenticalCheckerHelper.addDirectiveToClassicFileAndAssert(mainKotlinFile.toFile())
}
}
}
companion object {
fun createFromDirectory(directory: Path): TestData {
val allFiles = Files.list(directory).collect(Collectors.toList())
@@ -111,5 +159,23 @@ internal data class TestData(
)
}
}
private object IdenticalCheckerHelper : FirIdenticalCheckerHelper(
TestServices().apply {
register(AssertionsService::class, JUnit5Assertions)
}
) {
override fun getClassicFileToCompare(testDataFile: File): File {
val path = testDataFile.toPath()
val fileNameWithoutExtension = path.fileName.toString().removeSuffix(".k2.txt").removeSuffix(".txt")
return path.parent.resolve("$fileNameWithoutExtension.txt").toFile()
}
override fun getFirFileToCompare(testDataFile: File): File {
val path = testDataFile.toPath()
val fileNameWithoutExtension = path.fileName.toString().removeSuffix(".k2.txt").removeSuffix(".txt")
return path.parent.resolve("$fileNameWithoutExtension.k2.txt").toFile()
}
}
}
@@ -19,9 +19,10 @@ abstract class AbstractStubBuilderTest : AbstractDecompiledClassTest() {
fun runTest(testDirectory: String) {
val testDirectoryPath = Paths.get(testDirectory)
val testData = TestData.createFromDirectory(testDirectoryPath)
doTest(testData, useStringTable = true)
doTest(testData, useStringTable = false)
testData.withFirIgnoreDirective {
doTest(testData, useStringTable = true)
doTest(testData, useStringTable = false)
}
}
@@ -31,7 +32,9 @@ abstract class AbstractStubBuilderTest : AbstractDecompiledClassTest() {
}
private fun testClsStubsForFile(classFile: VirtualFile, testData: TestData) {
KotlinTestUtils.assertEqualsToFile(testData.expectedFile, getStubToTest(classFile).serializeToString())
val stub = getStubToTest(classFile)
KotlinTestUtils.assertEqualsToFile(testData.getExpectedFile(useK2ToCompileCode), stub.serializeToString())
testData.checkIfIdentical(useK2ToCompileCode)
}
protected abstract fun getStubToTest(classFile: VirtualFile): PsiFileStub<*>
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.decompiler.psi
abstract class AbstractByDecompiledPsiStubBuilderK2CompilerTest : AbstractByDecompiledPsiStubBuilderTest() {
override val useK2ToCompileCode: Boolean = true
}
@@ -5,8 +5,11 @@
package org.jetbrains.kotlin.generators.tests.analysis.api
import org.jetbrains.kotlin.analysis.decompiler.psi.AbstractByDecompiledPsiStubBuilderK2CompilerTest
import org.jetbrains.kotlin.analysis.decompiler.psi.AbstractByDecompiledPsiStubBuilderTest
import org.jetbrains.kotlin.analysis.decompiler.stub.files.AbstractAdditionalStubInfoK2CompilerTest
import org.jetbrains.kotlin.analysis.decompiler.stub.files.AbstractAdditionalStubInfoTest
import org.jetbrains.kotlin.analysis.decompiler.stub.files.AbstractClsStubBuilderK2CompilerTest
import org.jetbrains.kotlin.analysis.decompiler.stub.files.AbstractClsStubBuilderTest
import org.jetbrains.kotlin.generators.TestGroupSuite
@@ -18,6 +21,10 @@ internal fun TestGroupSuite.generateDecompiledTests() {
testClass<AbstractClsStubBuilderTest> {
model("clsFileStubBuilder", extension = null, recursive = false)
}
testClass<AbstractClsStubBuilderK2CompilerTest> {
model("clsFileStubBuilder", extension = null, recursive = false)
}
}
testGroup(
@@ -27,6 +34,10 @@ internal fun TestGroupSuite.generateDecompiledTests() {
testClass<AbstractAdditionalStubInfoTest> {
model("additionalClsStubInfo", extension = null, recursive = false)
}
testClass<AbstractAdditionalStubInfoK2CompilerTest> {
model("additionalClsStubInfo", extension = null, recursive = false)
}
}
testGroup(
@@ -36,5 +47,9 @@ internal fun TestGroupSuite.generateDecompiledTests() {
testClass<AbstractByDecompiledPsiStubBuilderTest> {
model("clsFileStubBuilder", extension = null, recursive = false)
}
testClass<AbstractByDecompiledPsiStubBuilderK2CompilerTest> {
model("clsFileStubBuilder", extension = null, recursive = false)
}
}
}