Introduce LT file abstraction in tests parallel to KtFile
allows to create a valid LT-based file with synthetic path important for dumps comparisons in tests
This commit is contained in:
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.builder.PsiHandlingMode
|
|||||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
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.moduleData
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
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.ir.declarations.impl.IrFactoryImpl
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
abstract class AbstractFirAnalyzerFacade {
|
abstract class AbstractFirAnalyzerFacade {
|
||||||
abstract val scopeSession: ScopeSession
|
abstract val scopeSession: ScopeSession
|
||||||
@@ -45,7 +45,7 @@ class FirAnalyzerFacade(
|
|||||||
val session: FirSession,
|
val session: FirSession,
|
||||||
val languageVersionSettings: LanguageVersionSettings,
|
val languageVersionSettings: LanguageVersionSettings,
|
||||||
val ktFiles: Collection<KtFile> = emptyList(), // may be empty if light tree mode enabled
|
val ktFiles: Collection<KtFile> = emptyList(), // may be empty if light tree mode enabled
|
||||||
val originalFiles: Collection<File> = emptyList(), // may be empty if light tree mode disabled
|
val lightTreeFiles: Collection<LightTreeFile> = emptyList(), // may be empty if light tree mode disabled
|
||||||
val irGeneratorExtensions: Collection<IrGenerationExtension>,
|
val irGeneratorExtensions: Collection<IrGenerationExtension>,
|
||||||
val useLightTree: Boolean = false,
|
val useLightTree: Boolean = false,
|
||||||
val enablePluginPhases: Boolean = false,
|
val enablePluginPhases: Boolean = false,
|
||||||
@@ -62,7 +62,7 @@ class FirAnalyzerFacade(
|
|||||||
val firProvider = (session.firProvider as FirProviderImpl)
|
val firProvider = (session.firProvider as FirProviderImpl)
|
||||||
firFiles = if (useLightTree) {
|
firFiles = if (useLightTree) {
|
||||||
val builder = LightTree2Fir(session, firProvider.kotlinScopeProvider)
|
val builder = LightTree2Fir(session, firProvider.kotlinScopeProvider)
|
||||||
originalFiles.map {
|
lightTreeFiles.map {
|
||||||
builder.buildFirFile(it).also { firFile ->
|
builder.buildFirFile(it).also { firFile ->
|
||||||
firProvider.recordFile(firFile)
|
firProvider.recordFile(firFile)
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-4
@@ -39,6 +39,12 @@ class LightTree2Fir(
|
|||||||
KotlinLightParser.parseLambdaExpression(builder)
|
KotlinLightParser.parseLambdaExpression(builder)
|
||||||
return builder.lightTree
|
return builder.lightTree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun buildLightTree(code: String): FlyweightCapableTreeStructure<LighterASTNode> {
|
||||||
|
val builder = PsiBuilderFactoryImpl().createBuilder(parserDefinition, makeLexer(), code)
|
||||||
|
KotlinLightParser.parse(builder)
|
||||||
|
return builder.lightTree
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildFirFile(path: Path): FirFile {
|
fun buildFirFile(path: Path): FirFile {
|
||||||
@@ -50,10 +56,11 @@ class LightTree2Fir(
|
|||||||
return buildFirFile(code, file.name, file.path)
|
return buildFirFile(code, file.name, file.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildLightTree(code: String): FlyweightCapableTreeStructure<LighterASTNode> {
|
fun buildFirFile(lightTreeFile: LightTreeFile): FirFile = with(lightTreeFile) {
|
||||||
val builder = PsiBuilderFactoryImpl().createBuilder(parserDefinition, makeLexer(), code)
|
DeclarationsConverter(
|
||||||
KotlinLightParser.parse(builder)
|
session, scopeProvider, lightTree, diagnosticsReporter = diagnosticsReporter,
|
||||||
return builder.lightTree
|
diagnosticContext = makeDiagnosticContext(path)
|
||||||
|
).convertFile(lightTree.root, fileName, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildFirFile(code: String, fileName: String, path: String?): FirFile {
|
fun buildFirFile(code: String, fileName: String, path: String?): FirFile {
|
||||||
@@ -63,3 +70,10 @@ class LightTree2Fir(
|
|||||||
.convertFile(lightTree.root, fileName, path)
|
.convertFile(lightTree.root, fileName, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class LightTreeFile(
|
||||||
|
val lightTree: FlyweightCapableTreeStructure<LighterASTNode>,
|
||||||
|
val fileName: String,
|
||||||
|
val path: String?
|
||||||
|
)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ class TotalKotlinTest : AbstractRawFirBuilderTestCase() {
|
|||||||
|
|
||||||
private fun generateFirFromLightTree(onlyLightTree: Boolean, converter: LightTree2Fir, text: String, fileName: String, filePath: String) {
|
private fun generateFirFromLightTree(onlyLightTree: Boolean, converter: LightTree2Fir, text: String, fileName: String, filePath: String) {
|
||||||
if (onlyLightTree) {
|
if (onlyLightTree) {
|
||||||
val lightTree = converter.buildLightTree(text)
|
val lightTree = LightTree2Fir.buildLightTree(text)
|
||||||
DebugUtil.lightTreeToString(lightTree, false)
|
DebugUtil.lightTreeToString(lightTree, false)
|
||||||
} else {
|
} else {
|
||||||
val firFile = converter.buildFirFile(text, fileName, filePath)
|
val firFile = converter.buildFirFile(text, fileName, filePath)
|
||||||
|
|||||||
+16
@@ -6,6 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.test.services
|
package org.jetbrains.kotlin.test.services
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
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.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.model.TestFile
|
import org.jetbrains.kotlin.test.model.TestFile
|
||||||
import org.jetbrains.kotlin.test.util.KtTestUtil
|
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||||
@@ -97,6 +99,20 @@ fun SourceFileProvider.getKtFilesForSourceFiles(testFiles: Collection<TestFile>,
|
|||||||
}.toMap()
|
}.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<TestFile>): Map<TestFile, LightTreeFile> {
|
||||||
|
return testFiles.mapNotNull {
|
||||||
|
if (!it.isKtFile) return@mapNotNull null
|
||||||
|
it to getLightTreeKtFileForSourceFile(it)
|
||||||
|
}.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
val TestFile.isKtFile: Boolean
|
val TestFile.isKtFile: Boolean
|
||||||
get() = name.endsWith(".kt") || name.endsWith(".kts")
|
get() = name.endsWith(".kt") || name.endsWith(".kts")
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -66,8 +66,8 @@ class FirFrontendFacade(
|
|||||||
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java)
|
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java)
|
||||||
|
|
||||||
val lightTreeEnabled = FirDiagnosticsDirectives.USE_LIGHT_TREE in module.directives
|
val lightTreeEnabled = FirDiagnosticsDirectives.USE_LIGHT_TREE in module.directives
|
||||||
val (ktFiles, originalFiles) = if (lightTreeEnabled) {
|
val (ktFiles, lightTreeFiles) = if (lightTreeEnabled) {
|
||||||
emptyList<KtFile>() to module.files.filter { it.isKtFile }.map { testServices.sourceFileProvider.getRealFileForSourceFile(it) }
|
emptyList<KtFile>() to testServices.sourceFileProvider.getLightTreeFilesForSourceFiles(module.files).values
|
||||||
} else {
|
} else {
|
||||||
testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList()
|
testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList()
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ class FirFrontendFacade(
|
|||||||
session,
|
session,
|
||||||
languageVersionSettings,
|
languageVersionSettings,
|
||||||
ktFiles,
|
ktFiles,
|
||||||
originalFiles,
|
lightTreeFiles,
|
||||||
IrGenerationExtension.getInstances(project),
|
IrGenerationExtension.getInstances(project),
|
||||||
lightTreeEnabled,
|
lightTreeEnabled,
|
||||||
enablePluginPhases
|
enablePluginPhases
|
||||||
|
|||||||
Reference in New Issue
Block a user