From a08ab45e224bc885b11541cc0ce12e97e615b2cf Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Mon, 4 Oct 2021 13:33:19 -0700 Subject: [PATCH] FIR IDE: make all HL tests covering depended mode Also changed tests to do the analysis on the KtElement of interest instead of the KtFile where possible because currently depended mode does not support analysing the entire file. Maybe we should support analysing the whole file at some point. --- .../api/fir/AbstractReferenceResolveTest.kt | 18 +++--- ...bstractCompileTimeConstantEvaluatorTest.kt | 8 +-- .../AbstractExpectedExpressionTypeTest.kt | 4 +- .../AbstractHLExpressionTypeTest.kt | 6 +- .../AbstractHLImportOptimizerTest.kt | 3 +- .../AbstractHasCommonSubtypeTest.kt | 3 +- ...stractOverriddenDeclarationProviderTest.kt | 4 +- .../fir/components/AbstractRendererTest.kt | 6 +- .../fir/components/AbstractResolveCallTest.kt | 4 +- .../api/fir/scopes/AbstractFileScopeTest.kt | 4 +- .../api/fir/symbols/AbstractSymbolTest.kt | 1 - .../kotlin/analysis/api/fir/testUtils.kt | 20 ------- .../based/TestProjectModuleProvider.kt | 2 +- .../fir/test/base/AbstractLowLevelApiTest.kt | 60 +++++++++++++++++-- 14 files changed, 76 insertions(+), 67 deletions(-) diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/AbstractReferenceResolveTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/AbstractReferenceResolveTest.kt index 84eabe538d6..58eb32dc5fb 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/AbstractReferenceResolveTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/AbstractReferenceResolveTest.kt @@ -7,17 +7,18 @@ package org.jetbrains.kotlin.analysis.api.fir import com.intellij.psi.PsiReference import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference -import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleModuleTest -import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider +import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions import org.jetbrains.kotlin.analysis.api.components.RendererModifier +import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleModuleTest import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind +import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives @@ -45,11 +46,12 @@ abstract class AbstractReferenceResolveTest : AbstractHLApiSingleModuleTest() { testServices.assertions.fail { "No references at caret found" } } - val resolvedTo = analyse(mainKtFile) { - val symbols = ktReferences.flatMap { it.resolveToSymbols() } - checkReferenceResultForValidity(module, testServices, symbols) - renderResolvedTo(symbols) - } + val resolvedTo = + analyseForTest(PsiTreeUtil.findElementOfClassAtOffset(mainKtFile, caretPosition, KtDeclaration::class.java, false) ?: mainKtFile) { + val symbols = ktReferences.flatMap { it.resolveToSymbols() } + checkReferenceResultForValidity(module, testServices, symbols) + renderResolvedTo(symbols) + } if (Directives.UNRESOLVED_REFERENCE in module.directives) { return diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractCompileTimeConstantEvaluatorTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractCompileTimeConstantEvaluatorTest.kt index 25c4138cb51..7cc63ebbe58 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractCompileTimeConstantEvaluatorTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractCompileTimeConstantEvaluatorTest.kt @@ -5,11 +5,9 @@ package org.jetbrains.kotlin.analysis.api.fir.components -import org.jetbrains.kotlin.analysis.api.fir.executeOnPooledThreadInReadAction import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest -import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.analysis.api.symbols.markers.* +import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtValueArgument @@ -26,11 +24,11 @@ abstract class AbstractCompileTimeConstantEvaluatorTest : AbstractHLApiSingleFil else -> null } ?: testServices.assertions.fail { "Unsupported expression: $element" } val constantValue = executeOnPooledThreadInReadAction { - analyse(expression) { expression.evaluate() } + analyseForTest(expression) { expression.evaluate() } } val actual = buildString { appendLine("expression: ${expression.text}") - appendLine("constant_value: ${analyse(ktFile) { constantValue?.stringRepresentation() }}") + appendLine("constant_value: ${analyseForTest(expression) { constantValue?.stringRepresentation() }}") appendLine("constant: ${(constantValue as? KtLiteralConstantValue<*>)?.toConst()}") } testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual) diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractExpectedExpressionTypeTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractExpectedExpressionTypeTest.kt index b9ed0091608..173047bde48 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractExpectedExpressionTypeTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractExpectedExpressionTypeTest.kt @@ -5,10 +5,8 @@ package org.jetbrains.kotlin.analysis.api.fir.components -import org.jetbrains.kotlin.analysis.api.fir.executeOnPooledThreadInReadAction import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.model.TestModule @@ -20,7 +18,7 @@ abstract class AbstractExpectedExpressionTypeTest : AbstractHLApiSingleFileTest( val expressionAtCaret = testServices.expressionMarkerProvider.getElementOfTypAtCaret(ktFile) as KtExpression val actualExpectedTypeText: String? = executeOnPooledThreadInReadAction { - analyse(ktFile) { + analyseForTest(expressionAtCaret) { expressionAtCaret.getExpectedType()?.asStringForDebugging() } } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHLExpressionTypeTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHLExpressionTypeTest.kt index af1f5094760..361e1cc7da1 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHLExpressionTypeTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHLExpressionTypeTest.kt @@ -5,15 +5,11 @@ package org.jetbrains.kotlin.analysis.api.fir.components -import org.jetbrains.kotlin.analysis.api.fir.executeOnPooledThreadInReadAction import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest -import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.model.TestModule -import org.jetbrains.kotlin.test.services.TestModuleStructure import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.assertions @@ -21,7 +17,7 @@ abstract class AbstractHLExpressionTypeTest : AbstractHLApiSingleFileTest() { override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) { val expression = testServices.expressionMarkerProvider.getSelectedElement(ktFile) as KtExpression val type = executeOnPooledThreadInReadAction { - analyse(expression) { expression.getKtType()?.render() } + analyseForTest(expression) { expression.getKtType()?.render() } } val actual = buildString { appendLine("expression: ${expression.text}") diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHLImportOptimizerTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHLImportOptimizerTest.kt index 7acb8f2cd12..99553af6c1a 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHLImportOptimizerTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHLImportOptimizerTest.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.analysis.api.fir.components import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleModuleTest -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.TestServices @@ -15,7 +14,7 @@ import org.jetbrains.kotlin.test.services.assertions abstract class AbstractHLImportOptimizerTest : AbstractHLApiSingleModuleTest() { override fun doTestByFileStructure(ktFiles: List, module: TestModule, testServices: TestServices) { val mainKtFile = ktFiles.singleOrNull() ?: ktFiles.first { it.name == "main.kt" } - val unusedImports = analyse(mainKtFile) { analyseImports(mainKtFile).unusedImports } + val unusedImports = analyseForTest(mainKtFile) { analyseImports(mainKtFile).unusedImports } val unusedImportPaths = unusedImports .map { it.importPath ?: error("Import $it should have an import path, instead was ${it.text}") } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHasCommonSubtypeTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHasCommonSubtypeTest.kt index 02274f96041..605184171b7 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHasCommonSubtypeTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractHasCommonSubtypeTest.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.analysis.api.fir.components import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtFile @@ -27,7 +26,7 @@ abstract class AbstractHasCommonSubtypeTest : AbstractHLApiSingleFileTest() { val errors = mutableListOf() val originalText = ktFile.text val actualTextBuilder = StringBuilder() - analyse(ktFile) { + analyseForTest(ktFile) { val visitor = object : KtTreeVisitorVoid() { override fun visitElement(element: PsiElement) { if (element.firstChild == null) { diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractOverriddenDeclarationProviderTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractOverriddenDeclarationProviderTest.kt index 6ebd5a190f6..75dd7ced4d7 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractOverriddenDeclarationProviderTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractOverriddenDeclarationProviderTest.kt @@ -5,12 +5,10 @@ package org.jetbrains.kotlin.analysis.api.fir.components -import org.jetbrains.kotlin.analysis.api.fir.executeOnPooledThreadInReadAction import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleModuleTest import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentsOfType import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol @@ -26,7 +24,7 @@ abstract class AbstractOverriddenDeclarationProviderTest : AbstractHLApiSingleMo val declaration = testServices.expressionMarkerProvider.getElementOfTypAtCaret(ktFiles.first()) val actual = executeOnPooledThreadInReadAction { - analyse(ktFiles.first()) { + analyseForTest(declaration) { val symbol = declaration.getSymbol() as KtCallableSymbol val allOverriddenSymbols = symbol.getAllOverriddenSymbols().map { renderSignature(it) } val directlyOverriddenSymbols = symbol.getDirectlyOverriddenSymbols().map { renderSignature(it) } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractRendererTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractRendererTest.kt index 351e4cc0c4e..598f5dc291c 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractRendererTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractRendererTest.kt @@ -5,15 +5,11 @@ package org.jetbrains.kotlin.analysis.api.fir.components -import org.jetbrains.kotlin.analysis.api.fir.executeOnPooledThreadInReadAction import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest -import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.model.TestModule -import org.jetbrains.kotlin.test.services.TestModuleStructure import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.assertions @@ -28,7 +24,7 @@ abstract class AbstractRendererTest : AbstractHLApiSingleFileTest() { val actual = executeOnPooledThreadInReadAction { buildString { ktFile.declarations.forEach { - analyse(it) { + analyseForTest(it) { append(it.getSymbol().render(options)) appendLine() } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractResolveCallTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractResolveCallTest.kt index da42d78f50b..c175b1bdf59 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractResolveCallTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractResolveCallTest.kt @@ -7,12 +7,10 @@ package org.jetbrains.kotlin.analysis.api.fir.components import com.intellij.psi.PsiElement import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.analysis.api.calls.KtCall import org.jetbrains.kotlin.analysis.api.calls.KtDelegatedConstructorCallKind import org.jetbrains.kotlin.analysis.api.calls.KtErrorCallTarget import org.jetbrains.kotlin.analysis.api.calls.KtSuccessCallTarget -import org.jetbrains.kotlin.analysis.api.fir.executeOnPooledThreadInReadAction import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleModuleTest import org.jetbrains.kotlin.analysis.api.fir.types.KtFirSubstitutor import org.jetbrains.kotlin.analysis.api.symbols.* @@ -36,7 +34,7 @@ abstract class AbstractResolveCallTest : AbstractHLApiSingleModuleTest() { val expression = testServices.expressionMarkerProvider.getSelectedElement(ktFile) val actual = executeOnPooledThreadInReadAction { - analyse(ktFile) { + analyseForTest(expression) { resolveCall(expression)?.stringRepresentation() } } ?: "null" diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/AbstractFileScopeTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/AbstractFileScopeTest.kt index 0d59de8e57e..299cf82c997 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/AbstractFileScopeTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/AbstractFileScopeTest.kt @@ -5,9 +5,7 @@ package org.jetbrains.kotlin.analysis.api.fir.scopes -import org.jetbrains.kotlin.analysis.api.fir.executeOnPooledThreadInReadAction import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest -import org.jetbrains.kotlin.analysis.api.analyse import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.model.TestModule @@ -17,7 +15,7 @@ import org.jetbrains.kotlin.test.services.assertions abstract class AbstractFileScopeTest : AbstractHLApiSingleFileTest() { override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) { val actual = executeOnPooledThreadInReadAction { - analyse(ktFile) { + analyseForTest(ktFile) { val symbol = ktFile.getFileSymbol() val scope = symbol.getFileScope() with(DebugSymbolRenderer) { diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/symbols/AbstractSymbolTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/symbols/AbstractSymbolTest.kt index 53167f37c37..35d7d32ec45 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/symbols/AbstractSymbolTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/symbols/AbstractSymbolTest.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.analysis.api.fir.symbols import com.intellij.openapi.components.ServiceManager import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory -import org.jetbrains.kotlin.analysis.api.fir.analyseOnPooledThreadInReadAction import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/testUtils.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/testUtils.kt index 24c44437505..e17a1589bab 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/testUtils.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/testUtils.kt @@ -5,28 +5,8 @@ package org.jetbrains.kotlin.analysis.api.fir -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.util.Computable import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.DuplicatedFirSourceElementsException -import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.analyse -import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.test.InTextDirectivesUtils -import java.io.File - - -inline fun runReadAction(crossinline runnable: () -> T): T { - return ApplicationManager.getApplication().runReadAction(Computable { runnable() }) -} - -fun executeOnPooledThreadInReadAction(action: () -> R): R = - ApplicationManager.getApplication().executeOnPooledThread { runReadAction(action) }.get() - -inline fun analyseOnPooledThreadInReadAction(context: KtElement, crossinline action: KtAnalysisSession.() -> R): R = - executeOnPooledThreadInReadAction { - analyse(context) { action() } - } - /** * Temporary diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/TestProjectModuleProvider.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/TestProjectModuleProvider.kt index 019ef71e729..852b81623ee 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/TestProjectModuleProvider.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/TestProjectModuleProvider.kt @@ -23,7 +23,7 @@ class TestKtModuleProvider( internal fun getModuleInfoByKtFile(ktFile: KtFile): TestKtSourceModule = cache.values.first { moduleSourceInfo -> - ktFile in moduleSourceInfo.ktFiles + (if (ktFile.isPhysical) ktFile else ktFile.originalFile) in moduleSourceInfo.ktFiles } internal fun getModule(moduleName: String): TestKtSourceModule = diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/base/AbstractLowLevelApiTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/base/AbstractLowLevelApiTest.kt index 34652312e2e..f28a1066197 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/base/AbstractLowLevelApiTest.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/base/AbstractLowLevelApiTest.kt @@ -8,13 +8,19 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.test.base import com.intellij.mock.MockApplication import com.intellij.mock.MockProject import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.util.Computable import com.intellij.openapi.util.Disposer import com.intellij.testFramework.TestDataFile -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.analyse +import org.jetbrains.kotlin.analysis.api.analyseInDependedAnalysisSession import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.ModuleRegistrarPreAnalysisHandler import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.TestKtModuleProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.projectModuleProvider +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.platform.jvm.JvmPlatforms +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.TestInfrastructureInternals import org.jetbrains.kotlin.test.bind @@ -33,10 +39,12 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.TestInfo import java.nio.file.Path import java.nio.file.Paths +import java.util.concurrent.ExecutionException import kotlin.io.path.nameWithoutExtension abstract class AbstractLowLevelApiTest : TestWithDisposable() { private lateinit var testInfo: KotlinTestInfo + private var useDependedAnalysisSession: Boolean = false @OptIn(TestInfrastructureInternals::class) private val configure: TestConfigurationBuilder.() -> Unit = { @@ -102,11 +110,24 @@ abstract class AbstractLowLevelApiTest : TestWithDisposable() { registerApplicationServices() - doTestByFileStructure( - moduleInfo.testFilesToKtFiles.filter { (testFile, _) -> !testFile.isAdditional }.values.toList(), - moduleStructure, - testServices - ) + val ktFiles = moduleInfo.testFilesToKtFiles.filterKeys { testFile -> !testFile.isAdditional }.values.toList() + + doTestByFileStructure(ktFiles, moduleStructure, testServices) + useDependedAnalysisSession = true + try { + doTestByFileStructure(ktFiles.map { + val fakeFile = it.copy() as KtFile + fakeFile.originalKtFile = it + fakeFile + }, moduleStructure, testServices) + } catch (e: SkipDependedModeException) { + // Skip the test if needed + } catch (e: ExecutionException) { + if (e.cause !is SkipDependedModeException) + throw Exception("Test succeeded in normal analysis mode but failed in depended analysis mode.", e) + } catch (e: Exception) { + throw Exception("Test succeeded in normal analysis mode but failed in depended analysis mode.", e) + } } private fun registerApplicationServices() { @@ -130,5 +151,32 @@ abstract class AbstractLowLevelApiTest : TestWithDisposable() { tags = testInfo.tags ) } + + protected inline fun analyseOnPooledThreadInReadAction(context: KtElement, crossinline action: KtAnalysisSession.() -> R): R = + executeOnPooledThreadInReadAction { + analyseForTest(context) { action() } + } + + protected inline fun runReadAction(crossinline runnable: () -> T): T { + return ApplicationManager.getApplication().runReadAction(Computable { runnable() }) + } + + protected inline fun executeOnPooledThreadInReadAction(crossinline action: () -> R): R = + ApplicationManager.getApplication().executeOnPooledThread { runReadAction(action) }.get() + + + protected fun analyseForTest(contextElement: KtElement, action: KtAnalysisSession.() -> R): R { + return if (useDependedAnalysisSession) { + // Depended mode does not support analysing a KtFile. See org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir#getResolveStateForDependentCopy + if (contextElement is KtFile) throw SkipDependedModeException() + + require(!contextElement.isPhysical) + analyseInDependedAnalysisSession(contextElement.containingKtFile.originalKtFile!!, contextElement, action) + } else { + analyse(contextElement, action) + } + } + + private class SkipDependedModeException : Exception() }