[FIR] Setup tests for IC with compiler plugins

Most of those tests are ignored, because IC is not supported properly
  for compiler plugins. This commit is needed to prepare infrastructure,
  fix current behaviour and collect main problems of IC with plugins

Check fail.txt files in new testdata for explanation of problems
This commit is contained in:
Dmitriy Novozhilov
2021-12-01 17:16:21 +03:00
committed by TeamCityServer
parent 8fcb525d75
commit 77101edfa4
32 changed files with 303 additions and 5 deletions
+3 -1
View File
@@ -733,6 +733,7 @@ tasks {
dependsOn(":compiler:fir:analysis-tests:legacy-fir-tests:test")
dependsOn(":compiler:fir:fir2ir:test")
dependsOn(":plugins:fir-plugin-prototype:test")
dependsOn(":plugins:fir-plugin-prototype:fir-plugin-ic-test:test")
}
register("firAllTest") {
@@ -743,7 +744,8 @@ tasks {
":compiler:fir:analysis-tests:test",
":compiler:fir:analysis-tests:legacy-fir-tests:test",
":compiler:fir:fir2ir:test",
":plugins:fir-plugin-prototype:test"
":plugins:fir-plugin-prototype:test",
":plugins:fir-plugin-prototype:fir-plugin-ic-test:test"
)
}
+1
View File
@@ -67,6 +67,7 @@ dependencies {
testApi(projectTests(":kotlinx-serialization-compiler-plugin"))
testApi(projectTests(":kotlinx-atomicfu-compiler-plugin"))
testApi(projectTests(":plugins:fir-plugin-prototype"))
testApi(projectTests(":plugins:fir-plugin-prototype:fir-plugin-ic-test"))
testApi(projectTests(":generators:test-generator"))
testCompileOnly(project(":kotlin-reflect-api"))
testImplementation(intellijDep()) { includeJars("idea_rt") }
@@ -347,6 +347,12 @@ fun main(args: Array<String>) {
}
}
*/
testGroup("plugins/fir-plugin-prototype/fir-plugin-ic-test/tests-gen", "plugins/fir-plugin-prototype/fir-plugin-ic-test/testData") {
testClass<AbstractIncrementalFirJvmWithPluginCompilerRunnerTest> {
model("pureKotlin", extension = null, recursive = false, targetBackend = TargetBackend.JVM_IR)
}
}
}
generateTestGroupSuiteWithJUnit5 {
@@ -14,6 +14,7 @@ dependencies {
compileOnly(project(":compiler:ir.backend.common"))
compileOnly(project(":compiler:ir.tree.impl"))
compileOnly(project(":compiler:fir:entrypoint"))
compileOnly(project(":compiler:plugin-api"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
compileOnly(project(":kotlin-reflect-api"))
@@ -0,0 +1,61 @@
import org.jetbrains.kotlin.ideaExt.idea
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
testApi(project(":plugins:fir-plugin-prototype"))
testApi(project(":compiler:incremental-compilation-impl"))
testApi(projectTests(":compiler:incremental-compilation-impl"))
testCompileOnly(intellijCoreDep()) { includeJars("intellij-core") }
testCompileOnly(project(":kotlin-reflect-api"))
testRuntimeOnly(project(":kotlin-reflect"))
testRuntimeOnly(project(":core:descriptors.runtime"))
testRuntimeOnly(project(":compiler:fir:fir-serialization"))
testRuntimeOnly(intellijDep()) {
includeJars(
"lz4-java",
"jna",
"jdom",
"trove4j",
"intellij-deps-fastutil-8.4.1-4",
rootProject = rootProject)
}
testRuntimeOnly(toolsJar())
}
val generationRoot = projectDir.resolve("tests-gen")
sourceSets {
"main" {
projectDefault()
}
"test" {
projectDefault()
this.java.srcDir(generationRoot.name)
}
}
if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
apply(plugin = "idea")
idea {
this.module.generatedSourceDirs.add(generationRoot)
}
}
projectTest(parallel = true, jUnitMode = JUnitMode.JUnit4) {
workingDir = rootDir
useJUnitPlatform()
jvmArgs!!.removeIf { it.contains("-Xmx") }
maxHeapSize = "3g"
dependsOn(":plugins:fir-plugin-prototype:jar")
dependsOn(":plugins:fir-plugin-prototype:plugin-annotations:jar")
}
testsJar()
@@ -0,0 +1,9 @@
package bar
import foo.AllOpenGenerated
import org.jetbrains.kotlin.fir.plugin.ExternalClassWithNested
@ExternalClassWithNested
class A
FAIL // comment me to actually run test
@@ -0,0 +1,6 @@
package bar
import org.jetbrains.kotlin.fir.plugin.ExternalClassWithNested
@ExternalClassWithNested
class B
@@ -0,0 +1,8 @@
================ Step #1 =================
Compiling files:
src/B.kt
End of files
Exit code: OK
------------------------------------------
@@ -0,0 +1,2 @@
For some reason IC goes to eternal loop of compilation in this test. To observe this comment `FAIL` line in A.kt
to make test actually compilable
@@ -0,0 +1,7 @@
package bar
import foo.AllOpenGenerated
fun test() {
AllOpenGenerated.NestedA().materialize()
}
@@ -0,0 +1,5 @@
package foo
interface MyInterface {
fun foo()
}
@@ -0,0 +1,7 @@
package foo
interface MyInterface {
fun foo()
fun bar() {}
}
@@ -0,0 +1,8 @@
package foo
import org.jetbrains.kotlin.fir.plugin.MyInterfaceSupertype
@MyInterfaceSupertype
class SomeClass {
override fun foo() {}
}
@@ -0,0 +1,7 @@
================ Step #1 =================
Compiling files:
src/MyInterface.kt
src/SomeClass.kt
End of files
Exit code: OK
------------------------------------------
@@ -0,0 +1,5 @@
package foo
fun test() {
SomeClass().foo()
}
@@ -0,0 +1,4 @@
import org.jetbrains.kotlin.fir.plugin.MySerializable
@MySerializable
class A
@@ -0,0 +1,4 @@
import org.jetbrains.kotlin.fir.plugin.MySerializable
@MySerializable
class B
@@ -0,0 +1,4 @@
import org.jetbrains.kotlin.fir.plugin.CoreSerializer
@CoreSerializer
object Serializer
@@ -0,0 +1,8 @@
================ Step #1 =================
Compiling files:
src/B.kt
End of files
Exit code: OK
------------------------------------------
@@ -0,0 +1 @@
Serializer.kt should be also marked as dirty, because it's content depends on declarations which are annotated with @Serializable
@@ -0,0 +1,6 @@
package foo
import org.jetbrains.kotlin.fir.plugin.DummyFunction
@DummyFunction
class A
@@ -0,0 +1,6 @@
package foo
import org.jetbrains.kotlin.fir.plugin.DummyFunction
@DummyFunction
class B
@@ -0,0 +1,9 @@
================ Step #1 =================
Compiling files:
src/B.kt
src/usage.kt
End of files
Exit code: OK
------------------------------------------
@@ -0,0 +1,2 @@
Test fails because FirPredicateBasedProvider doesn't search for annotated declarations in binary dependencies
which came from previous compilation round, so plugin can not generate all what it wants
@@ -0,0 +1,3 @@
package bar
fun dummyB(any: Any) {}
@@ -0,0 +1,7 @@
package foo
import bar.*
fun test() {
dummyB("hello")
}
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2021 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.incremental;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("plugins/fir-plugin-prototype/fir-plugin-ic-test/testData/pureKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IncrementalFirJvmWithPluginCompilerRunnerTestGenerated extends AbstractIncrementalFirJvmWithPluginCompilerRunnerTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
@TestMetadata("addMethodToGeneratedClass")
public void testAddMethodToGeneratedClass() throws Exception {
runTest("plugins/fir-plugin-prototype/fir-plugin-ic-test/testData/pureKotlin/addMethodToGeneratedClass/");
}
@TestMetadata("addMethodToGeneratedSupertype")
public void testAddMethodToGeneratedSupertype() throws Exception {
runTest("plugins/fir-plugin-prototype/fir-plugin-ic-test/testData/pureKotlin/addMethodToGeneratedSupertype/");
}
@TestMetadata("addNewSerializableClass")
public void testAddNewSerializableClass() throws Exception {
runTest("plugins/fir-plugin-prototype/fir-plugin-ic-test/testData/pureKotlin/addNewSerializableClass/");
}
public void testAllFilesPresentInPureKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/fir-plugin-prototype/fir-plugin-ic-test/testData/pureKotlin"), Pattern.compile("^([^\\.]+)$"), null, TargetBackend.JVM_IR, false);
}
@TestMetadata("generateNewTopLevelFunction")
public void testGenerateNewTopLevelFunction() throws Exception {
runTest("plugins/fir-plugin-prototype/fir-plugin-ic-test/testData/pureKotlin/generateNewTopLevelFunction/");
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2021 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.incremental
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.incremental.testingUtils.BuildLogFinder
import org.junit.jupiter.api.fail
import java.io.File
import java.io.FilenameFilter
abstract class AbstractIncrementalFirJvmWithPluginCompilerRunnerTest : AbstractIncrementalFirJvmCompilerRunnerTest() {
companion object {
private const val ANNOTATIONS_JAR_DIR = "plugins/fir-plugin-prototype/plugin-annotations/build/libs/"
private const val ANNOTATIONS_JAR_NAME = "plugin-annotations"
private const val PLUGIN_JAR_DIR = "plugins/fir-plugin-prototype/build/libs/"
private const val PLUGIN_JAR_NAME = "fir-plugin-prototype"
private fun findJar(dir: String, name: String, taskName: String): String {
val failMessage = { "Jar $name does not exist. Please run $taskName" }
val libDir = File(dir)
kotlin.test.assertTrue(libDir.exists() && libDir.isDirectory)
val jar = libDir.listFiles()?.firstOrNull {
it.name.startsWith(name) && it.extension == "jar"
} ?: fail(failMessage)
return jar.canonicalPath
}
}
override fun createCompilerArguments(destinationDir: File, testDir: File): K2JVMCompilerArguments =
super.createCompilerArguments(destinationDir, testDir).apply {
val annotationsJar = findJar(ANNOTATIONS_JAR_DIR, ANNOTATIONS_JAR_NAME, ":plugins:fir-plugin-prototype:plugin-annotations:jar")
val pluginJar = findJar(PLUGIN_JAR_DIR, PLUGIN_JAR_NAME, ":plugins:fir-plugin-prototype:jar")
classpath += "${File.pathSeparator}$annotationsJar"
pluginClasspaths = arrayOf(pluginJar)
}
override val buildLogFinder: BuildLogFinder
get() = BuildLogFinder(isGradleEnabled = true, isFirEnabled = true) // TODO: investigate cases that need isGradleEnabled - the combination looks fragile
}
@@ -3,4 +3,4 @@
# Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
#
org.jetbrains.kotlin.fir.plugin.FirAllOpenComponentRegistrar
org.jetbrains.kotlin.fir.plugin.FirPluginPrototypeComponentRegistrar
@@ -5,11 +5,16 @@
package org.jetbrains.kotlin.fir.plugin
import com.intellij.mock.MockProject
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.plugin.generators.*
import org.jetbrains.kotlin.fir.plugin.types.FirNumberSignAttributeExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.plugin.GeneratedDeclarationsIrBodyFiller
class FirAllOpenComponentRegistrar : FirExtensionRegistrar() {
class FirPluginPrototypeExtensionRegistrar : FirExtensionRegistrar() {
override fun ExtensionRegistrarContext.configurePlugin() {
+::AllOpenStatusTransformer
+::AllPublicVisibilityTransformer
@@ -25,3 +30,10 @@ class FirAllOpenComponentRegistrar : FirExtensionRegistrar() {
+::MembersOfSerializerGenerator
}
}
class FirPluginPrototypeComponentRegistrar : ComponentRegistrar {
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
FirExtensionRegistrar.registerExtension(project, FirPluginPrototypeExtensionRegistrar())
IrGenerationExtension.registerExtension(project, GeneratedDeclarationsIrBodyFiller())
}
}
@@ -8,14 +8,14 @@ package org.jetbrains.kotlin.fir.plugin.services
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.plugin.FirAllOpenComponentRegistrar
import org.jetbrains.kotlin.fir.plugin.FirPluginPrototypeExtensionRegistrar
import org.jetbrains.kotlin.ir.plugin.GeneratedDeclarationsIrBodyFiller
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
import org.jetbrains.kotlin.test.services.TestServices
class ExtensionRegistrarConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
override fun registerCompilerExtensions(project: Project) {
FirExtensionRegistrar.registerExtension(project, FirAllOpenComponentRegistrar())
FirExtensionRegistrar.registerExtension(project, FirPluginPrototypeExtensionRegistrar())
IrGenerationExtension.registerExtension(project, GeneratedDeclarationsIrBodyFiller())
}
}
+1
View File
@@ -197,6 +197,7 @@ include ":benchmarks",
":kotlin-script-runtime",
":plugins:fir-plugin-prototype",
":plugins:fir-plugin-prototype:plugin-annotations",
":plugins:fir-plugin-prototype:fir-plugin-ic-test",
":kotlin-test:kotlin-test-common",
":kotlin-test:kotlin-test-annotations-common",
":kotlin-test:kotlin-test-jvm",