diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/analysis/FirAnalyzerFacade.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/analysis/FirAnalyzerFacade.kt index 0d43c83b09f..b0642f5c40c 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/analysis/FirAnalyzerFacade.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/analysis/FirAnalyzerFacade.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.builder.PsiHandlingMode import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir +import org.jetbrains.kotlin.fir.lightTree.LightTreeFile import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.providers.firProvider @@ -30,7 +31,6 @@ import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions -import java.io.File abstract class AbstractFirAnalyzerFacade { abstract val scopeSession: ScopeSession @@ -45,7 +45,7 @@ class FirAnalyzerFacade( val session: FirSession, val languageVersionSettings: LanguageVersionSettings, val ktFiles: Collection = emptyList(), // may be empty if light tree mode enabled - val originalFiles: Collection = emptyList(), // may be empty if light tree mode disabled + val lightTreeFiles: Collection = emptyList(), // may be empty if light tree mode disabled val irGeneratorExtensions: Collection, val useLightTree: Boolean = false, val enablePluginPhases: Boolean = false, @@ -62,7 +62,7 @@ class FirAnalyzerFacade( val firProvider = (session.firProvider as FirProviderImpl) firFiles = if (useLightTree) { val builder = LightTree2Fir(session, firProvider.kotlinScopeProvider) - originalFiles.map { + lightTreeFiles.map { builder.buildFirFile(it).also { firFile -> firProvider.recordFile(firFile) } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/LightTree2Fir.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/LightTree2Fir.kt index e41a784a90b..e16eb41e6e4 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/LightTree2Fir.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/LightTree2Fir.kt @@ -39,6 +39,12 @@ class LightTree2Fir( KotlinLightParser.parseLambdaExpression(builder) return builder.lightTree } + + fun buildLightTree(code: String): FlyweightCapableTreeStructure { + val builder = PsiBuilderFactoryImpl().createBuilder(parserDefinition, makeLexer(), code) + KotlinLightParser.parse(builder) + return builder.lightTree + } } fun buildFirFile(path: Path): FirFile { @@ -50,10 +56,11 @@ class LightTree2Fir( return buildFirFile(code, file.name, file.path) } - fun buildLightTree(code: String): FlyweightCapableTreeStructure { - val builder = PsiBuilderFactoryImpl().createBuilder(parserDefinition, makeLexer(), code) - KotlinLightParser.parse(builder) - return builder.lightTree + fun buildFirFile(lightTreeFile: LightTreeFile): FirFile = with(lightTreeFile) { + DeclarationsConverter( + session, scopeProvider, lightTree, diagnosticsReporter = diagnosticsReporter, + diagnosticContext = makeDiagnosticContext(path) + ).convertFile(lightTree.root, fileName, path) } fun buildFirFile(code: String, fileName: String, path: String?): FirFile { @@ -63,3 +70,10 @@ class LightTree2Fir( .convertFile(lightTree.root, fileName, path) } } + +data class LightTreeFile( + val lightTree: FlyweightCapableTreeStructure, + val fileName: String, + val path: String? +) + diff --git a/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt b/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt index bb016ea8fe5..6a6a4404106 100644 --- a/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt +++ b/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt @@ -35,7 +35,7 @@ class TotalKotlinTest : AbstractRawFirBuilderTestCase() { private fun generateFirFromLightTree(onlyLightTree: Boolean, converter: LightTree2Fir, text: String, fileName: String, filePath: String) { if (onlyLightTree) { - val lightTree = converter.buildLightTree(text) + val lightTree = LightTree2Fir.buildLightTree(text) DebugUtil.lightTreeToString(lightTree, false) } else { val firFile = converter.buildFirFile(text, fileName, filePath) diff --git a/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt b/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt index 0945a1d1283..edfeadab85b 100644 --- a/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt +++ b/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.test.services import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir +import org.jetbrains.kotlin.fir.lightTree.LightTreeFile import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.model.TestFile import org.jetbrains.kotlin.test.util.KtTestUtil @@ -97,6 +99,20 @@ fun SourceFileProvider.getKtFilesForSourceFiles(testFiles: Collection, }.toMap() } +fun SourceFileProvider.getLightTreeKtFileForSourceFile(testFile: TestFile): LightTreeFile { + val shortName = testFile.name.substringAfterLast('/').substringAfterLast('\\') + val file = getRealFileForSourceFile(testFile) + val lightTree = LightTree2Fir.buildLightTree(file.readText()) + return LightTreeFile(lightTree, shortName, "/$shortName") // emulating behavior of KtTestUtil.createFile so path looks the same in testdata +} + +fun SourceFileProvider.getLightTreeFilesForSourceFiles(testFiles: Collection): Map { + return testFiles.mapNotNull { + if (!it.isKtFile) return@mapNotNull null + it to getLightTreeKtFileForSourceFile(it) + }.toMap() +} + val TestFile.isKtFile: Boolean get() = name.endsWith(".kt") || name.endsWith(".kts") diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt index 253d55be2d9..deb03bd1962 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt @@ -66,8 +66,8 @@ class FirFrontendFacade( PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java) val lightTreeEnabled = FirDiagnosticsDirectives.USE_LIGHT_TREE in module.directives - val (ktFiles, originalFiles) = if (lightTreeEnabled) { - emptyList() to module.files.filter { it.isKtFile }.map { testServices.sourceFileProvider.getRealFileForSourceFile(it) } + val (ktFiles, lightTreeFiles) = if (lightTreeEnabled) { + emptyList() to testServices.sourceFileProvider.getLightTreeFilesForSourceFiles(module.files).values } else { testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList() } @@ -120,7 +120,7 @@ class FirFrontendFacade( session, languageVersionSettings, ktFiles, - originalFiles, + lightTreeFiles, IrGenerationExtension.getInstances(project), lightTreeEnabled, enablePluginPhases