FIR IDE: introduce multi module lazy resolve tests
This commit is contained in:
@@ -88,6 +88,7 @@ import org.jetbrains.kotlin.idea.filters.AbstractKotlinExceptionFilterTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLazyResolveTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirMultiModuleResolveTest
|
||||
import org.jetbrains.kotlin.idea.fir.AbstractKtDeclarationAndFirDeclarationEqualityChecker
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirMultiModuleLazyResolveTest
|
||||
import org.jetbrains.kotlin.idea.folding.AbstractKotlinFoldingTest
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AbstractResolveCallTest
|
||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.AbstractMemberScopeByFqNameTest
|
||||
@@ -1015,6 +1016,12 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("idea/idea-frontend-fir/idea-fir-low-level-api/tests", "idea/idea-frontend-fir/idea-fir-low-level-api/testdata") {
|
||||
testClass<AbstractFirMultiModuleLazyResolveTest> {
|
||||
model("multiModuleLazyResolve", recursive = false, extension = null)
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("idea/idea-fir/tests", "idea") {
|
||||
testClass<AbstractFirHighlightingTest> {
|
||||
model("testData/highlighter")
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
interface A
|
||||
|
||||
interface X : A
|
||||
interface Y : A
|
||||
|
||||
interface F : Y, X
|
||||
interface G : Y, X
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
FILE: main.kt
|
||||
public abstract interface A : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface X : R|A| {
|
||||
}
|
||||
public abstract interface Y : R|A| {
|
||||
}
|
||||
public abstract interface F : R|Y|, R|X| {
|
||||
}
|
||||
public abstract interface G : R|Y|, R|X| {
|
||||
}
|
||||
public final fun R|Y|.test(): R|kotlin/String?| {
|
||||
lval a: R|kotlin/Int| = when (this@R|/test|) {
|
||||
($subj$ is R|F|) -> {
|
||||
Int(1)
|
||||
}
|
||||
($subj$ is R|G|) -> {
|
||||
Int(2)
|
||||
}
|
||||
else -> {
|
||||
^test Null(null)
|
||||
}
|
||||
}
|
||||
|
||||
^test Null(null)
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fun Y.test(): String? {
|
||||
val a = when (this) {
|
||||
is F -> 1
|
||||
is G -> 2
|
||||
else -> return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"modules" : [
|
||||
{ "name": "main", "dependsOn": ["dependency"] },
|
||||
{ "name": "dependency" }
|
||||
],
|
||||
"fileToResolve": { "module": "main", "file": "main.kt" },
|
||||
"fails": true
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.fir.low.level.api
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest
|
||||
import org.jetbrains.kotlin.idea.util.sourceRoots
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
|
||||
abstract class AbstractFirMultiModuleLazyResolveTest : AbstractMultiModuleTest() {
|
||||
override fun getTestDataPath(): String =
|
||||
"${KotlinTestUtils.getHomeDirectory()}/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/multiModuleLazyResolve/"
|
||||
|
||||
fun doTest(path: String) {
|
||||
val testStructure = TestProjectStructureReader.read(Paths.get(path))
|
||||
val modulesByNames = testStructure.modules.associate { moduleData ->
|
||||
moduleData.name to module(moduleData.name)
|
||||
}
|
||||
testStructure.modules.forEach { moduleData ->
|
||||
val module = modulesByNames.getValue(moduleData.name)
|
||||
moduleData.dependsOnModules.forEach { dependencyName ->
|
||||
module.addDependency(modulesByNames.getValue(dependencyName))
|
||||
}
|
||||
}
|
||||
val moduleToResolve = modulesByNames.getValue(testStructure.fileToResolve.moduleName)
|
||||
val fileToAnalysePath = moduleToResolve.sourceRoots.first().url + "/" + testStructure.fileToResolve.relativeFilePath
|
||||
|
||||
val virtualFileToAnalyse = VirtualFileManager.getInstance().findFileByUrl(fileToAnalysePath)
|
||||
?: error("File ${testStructure.fileToResolve.filePath} not found")
|
||||
val ktFileToAnalyse = PsiManager.getInstance(project).findFile(virtualFileToAnalyse) as KtFile
|
||||
val resolveState = LowLevelFirApiFacade.getResolveStateFor(ktFileToAnalyse)
|
||||
|
||||
val fails = testStructure.fails
|
||||
|
||||
try {
|
||||
val fir = LowLevelFirApiFacade.getOrBuildFirFor(ktFileToAnalyse, resolveState, FirResolvePhase.BODY_RESOLVE)
|
||||
KotlinTestUtils.assertEqualsToFile(File("$path/expected.txt"), fir.render())
|
||||
} catch (e: Exception) {
|
||||
if (!fails) throw e
|
||||
return
|
||||
}
|
||||
if (fails) {
|
||||
throw AssertionError("Looks like test is passing, please remove // FAILS form the file")
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.fir.low.level.api;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
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("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/multiModuleLazyResolve")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class FirMultiModuleLazyResolveTestGenerated extends AbstractFirMultiModuleLazyResolveTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInMultiModuleLazyResolve() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/multiModuleLazyResolve"), Pattern.compile("^([^\\.]+)$"), null, false);
|
||||
}
|
||||
|
||||
@TestMetadata("whenWithHeiarchy")
|
||||
public void testWhenWithHeiarchy() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/multiModuleLazyResolve/whenWithHeiarchy/");
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.fir.low.level.api
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.idea.jsonUtils.getString
|
||||
import java.nio.file.Path
|
||||
|
||||
sealed class TestProjectStructure {
|
||||
abstract val modules: List<TestProjectModule>
|
||||
abstract val fileToResolve: FileToResolve
|
||||
abstract val fails: Boolean
|
||||
|
||||
companion object {
|
||||
fun parse(json: JsonElement): TestProjectStructure {
|
||||
require(json is JsonObject)
|
||||
val fails = if (json.has(FAILS_FIELD)) json.get(FAILS_FIELD).asBoolean else false
|
||||
|
||||
return MultiModuleTestProjectStructure(
|
||||
json.getAsJsonArray("modules").map { TestProjectModule.parse(it) },
|
||||
FileToResolve.parse(json.getAsJsonObject("fileToResolve")),
|
||||
fails
|
||||
)
|
||||
}
|
||||
|
||||
private const val FAILS_FIELD = "fails"
|
||||
}
|
||||
}
|
||||
|
||||
data class FileToResolve(val moduleName: String, val relativeFilePath: String) {
|
||||
val filePath get() = "$moduleName/$relativeFilePath"
|
||||
|
||||
companion object {
|
||||
fun parse(json: JsonElement): FileToResolve {
|
||||
require(json is JsonObject)
|
||||
return FileToResolve(
|
||||
moduleName = json.getString("module"),
|
||||
relativeFilePath = json.getString("file")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class MultiModuleTestProjectStructure(
|
||||
override val modules: List<TestProjectModule>,
|
||||
override val fileToResolve: FileToResolve,
|
||||
override val fails: Boolean
|
||||
) : TestProjectStructure()
|
||||
|
||||
data class TestProjectModule(val name: String, val dependsOnModules: List<String>) {
|
||||
companion object {
|
||||
fun parse(json: JsonElement): TestProjectModule {
|
||||
require(json is JsonObject)
|
||||
val dependencies = if (json.has(DEPENDS_ON_FIELD)) {
|
||||
json.getAsJsonArray(DEPENDS_ON_FIELD).map { (it as JsonPrimitive).asString }
|
||||
} else emptyList()
|
||||
return TestProjectModule(
|
||||
json.getString("name"),
|
||||
dependencies
|
||||
)
|
||||
}
|
||||
|
||||
private const val DEPENDS_ON_FIELD = "dependsOn"
|
||||
}
|
||||
}
|
||||
|
||||
object TestProjectStructureReader {
|
||||
fun read(testDirectory: Path, jsonFileName: String = "structure.json"): TestProjectStructure {
|
||||
val jsonFile = testDirectory.resolve(jsonFileName)
|
||||
|
||||
@Suppress("DEPRECATION") // AS 4.0
|
||||
val json = JsonParser().parse(FileUtil.loadFile(jsonFile.toFile(), /*convertLineSeparators=*/true))
|
||||
return TestProjectStructure.parse(json)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user