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() }