[LL API] Run fir2ir separately for files in different modules
Each module may have its own compiler configuration. ^KTIJ-27061 Fixed
This commit is contained in:
+169
-50
@@ -17,10 +17,14 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsForFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getModule
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CodeFragmentCapturedId
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CodeFragmentCapturedValueAnalyzer
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CompilationPeerCollector
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.codeFragment
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||
@@ -31,17 +35,17 @@ import org.jetbrains.kotlin.codegen.CodegenFactory
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticMarker
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
|
||||
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.backend.jvm.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.pipeline.applyIrGenerationExtensions
|
||||
import org.jetbrains.kotlin.fir.pipeline.signatureComposerForJvmFir2Ir
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
@@ -65,8 +69,11 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbolInternals
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
|
||||
import org.jetbrains.kotlin.ir.util.DelicateSymbolTableApi
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.classId
|
||||
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
@@ -95,12 +102,6 @@ internal class KtFirCompilerFacility(
|
||||
is KtCompilerTarget.Jvm -> target.classBuilderFactory
|
||||
}
|
||||
|
||||
val effectiveConfiguration = configuration
|
||||
.copy()
|
||||
.apply {
|
||||
put(CommonConfigurationKeys.USE_FIR, true)
|
||||
}
|
||||
|
||||
val mainFirFile = getFullyResolvedFirFile(file)
|
||||
|
||||
val frontendDiagnostics = file.collectDiagnosticsForFile(firResolveSession, DiagnosticCheckerFilter.ONLY_COMMON_CHECKERS)
|
||||
@@ -129,61 +130,67 @@ internal class KtFirCompilerFacility(
|
||||
add(file)
|
||||
}
|
||||
|
||||
val firFilesToCompile = filesToCompile.map(::getFullyResolvedFirFile)
|
||||
// Files in the code fragment context module are compiled together with the code fragment itself.
|
||||
val targetModule = mainFirFile.llFirModuleData.ktModule
|
||||
val (targetFiles, dependencyFiles) = filesToCompile.partition { firResolveSession.getModule(it) == targetModule }
|
||||
require(targetFiles.isNotEmpty())
|
||||
|
||||
val generateClassFilter = SingleFileGenerateClassFilter(file, compilationPeerData.inlinedClasses)
|
||||
val jvmIrDeserializer = JvmIrDeserializerImpl()
|
||||
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
|
||||
|
||||
val jvmGeneratorExtensions = JvmFir2IrExtensions(effectiveConfiguration, JvmIrDeserializerImpl(), JvmIrMangler)
|
||||
val fir2IrExtensions = CompilerFacilityFir2IrExtensions(jvmGeneratorExtensions, codeFragmentMappings?.injectedValueProvider)
|
||||
val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
|
||||
val dependencyFir2IrResults = dependencyFiles
|
||||
.map(::getFullyResolvedFirFile)
|
||||
.groupBy { it.llFirSession }
|
||||
.map { (dependencySession, dependencyFiles) ->
|
||||
val dependencyConfiguration = configuration
|
||||
.copy()
|
||||
.apply {
|
||||
put(CommonConfigurationKeys.USE_FIR, true)
|
||||
put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, dependencySession.languageVersionSettings)
|
||||
}
|
||||
|
||||
val fir2IrConfiguration = Fir2IrConfiguration(
|
||||
effectiveConfiguration.languageVersionSettings,
|
||||
diagnosticsReporter,
|
||||
linkViaSignatures = false,
|
||||
evaluatedConstTracker = effectiveConfiguration[CommonConfigurationKeys.EVALUATED_CONST_TRACKER] ?: EvaluatedConstTracker.create(),
|
||||
inlineConstTracker = effectiveConfiguration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
||||
expectActualTracker = effectiveConfiguration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||
allowNonCachedDeclarations = true,
|
||||
useIrFakeOverrideBuilder = effectiveConfiguration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||
val dependencyFir2IrExtensions = JvmFir2IrExtensions(dependencyConfiguration, jvmIrDeserializer, JvmIrMangler)
|
||||
runFir2Ir(dependencySession, dependencyFiles, dependencyFir2IrExtensions, diagnosticReporter, dependencyConfiguration)
|
||||
}
|
||||
|
||||
val targetConfiguration = configuration
|
||||
.copy()
|
||||
.apply {
|
||||
put(CommonConfigurationKeys.USE_FIR, true)
|
||||
}
|
||||
|
||||
val jvmGeneratorExtensions = JvmFir2IrExtensions(targetConfiguration, jvmIrDeserializer, JvmIrMangler)
|
||||
val targetFir2IrExtensions = CompilerFacilityFir2IrExtensions(
|
||||
jvmGeneratorExtensions,
|
||||
dependencyFir2IrResults,
|
||||
codeFragmentMappings?.injectedValueProvider
|
||||
)
|
||||
|
||||
val fir2IrResult = Fir2IrConverter.createIrModuleFragment(
|
||||
rootModuleSession,
|
||||
firResolveSession.getScopeSessionFor(rootModuleSession),
|
||||
firFilesToCompile,
|
||||
fir2IrExtensions,
|
||||
fir2IrConfiguration,
|
||||
JvmIrMangler,
|
||||
IrFactoryImpl,
|
||||
FirJvmVisibilityConverter,
|
||||
Fir2IrJvmSpecialAnnotationSymbolProvider(),
|
||||
DefaultBuiltIns.Instance,
|
||||
Fir2IrCommonMemberStorage(signatureComposerForJvmFir2Ir(false), FirJvmKotlinMangler()),
|
||||
initializedIrBuiltIns = null,
|
||||
::JvmIrTypeSystemContext,
|
||||
)
|
||||
val targetSession = mainFirFile.llFirSession
|
||||
val targetFirFiles = targetFiles.map(::getFullyResolvedFirFile)
|
||||
val targetFir2IrResult = runFir2Ir(targetSession, targetFirFiles, targetFir2IrExtensions, diagnosticReporter, targetConfiguration)
|
||||
|
||||
patchCodeFragmentIr(fir2IrResult)
|
||||
patchCodeFragmentIr(targetFir2IrResult)
|
||||
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
val irGeneratorExtensions = IrGenerationExtension.getInstances(project)
|
||||
fir2IrResult.components.applyIrGenerationExtensions(fir2IrResult.irModuleFragment, irGeneratorExtensions)
|
||||
targetFir2IrResult.components.applyIrGenerationExtensions(targetFir2IrResult.irModuleFragment, irGeneratorExtensions)
|
||||
|
||||
val bindingContext = NoScopeRecordCliBindingTrace().bindingContext
|
||||
val codegenFactory = createJvmIrCodegenFactory(effectiveConfiguration, file is KtCodeFragment, fir2IrResult.irModuleFragment)
|
||||
val codegenFactory = createJvmIrCodegenFactory(targetConfiguration, file is KtCodeFragment, targetFir2IrResult.irModuleFragment)
|
||||
val generateClassFilter = SingleFileGenerateClassFilter(file, compilationPeerData.inlinedClasses)
|
||||
|
||||
val generationState = GenerationState.Builder(
|
||||
project,
|
||||
classBuilderFactory,
|
||||
fir2IrResult.irModuleFragment.descriptor,
|
||||
targetFir2IrResult.irModuleFragment.descriptor,
|
||||
bindingContext,
|
||||
filesToCompile,
|
||||
effectiveConfiguration,
|
||||
targetFiles,
|
||||
targetConfiguration,
|
||||
).generateDeclaredClassFilter(generateClassFilter)
|
||||
.codegenFactory(codegenFactory)
|
||||
.diagnosticReporter(diagnosticsReporter)
|
||||
.diagnosticReporter(diagnosticReporter)
|
||||
.build()
|
||||
|
||||
try {
|
||||
@@ -193,12 +200,12 @@ internal class KtFirCompilerFacility(
|
||||
|
||||
codegenFactory.generateModuleInFrontendIRMode(
|
||||
generationState,
|
||||
fir2IrResult.irModuleFragment,
|
||||
fir2IrResult.components.symbolTable,
|
||||
fir2IrResult.components.irProviders,
|
||||
targetFir2IrResult.irModuleFragment,
|
||||
targetFir2IrResult.components.symbolTable,
|
||||
targetFir2IrResult.components.irProviders,
|
||||
CompilerFacilityJvmGeneratorExtensions(jvmGeneratorExtensions),
|
||||
FirJvmBackendExtension(fir2IrResult.components, null),
|
||||
fir2IrResult.pluginContext
|
||||
FirJvmBackendExtension(targetFir2IrResult.components, null),
|
||||
targetFir2IrResult.pluginContext
|
||||
)
|
||||
|
||||
CodegenFactory.doCheckCancelled(generationState)
|
||||
@@ -222,12 +229,48 @@ internal class KtFirCompilerFacility(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return KtCompilationResult.Success(outputFiles, capturedValues)
|
||||
} finally {
|
||||
generationState.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
private fun runFir2Ir(
|
||||
session: LLFirSession,
|
||||
firFiles: List<FirFile>,
|
||||
fir2IrExtensions: Fir2IrExtensions,
|
||||
diagnosticReporter: DiagnosticReporter,
|
||||
effectiveConfiguration: CompilerConfiguration,
|
||||
): Fir2IrResult {
|
||||
val fir2IrConfiguration = Fir2IrConfiguration(
|
||||
session.languageVersionSettings,
|
||||
diagnosticReporter,
|
||||
linkViaSignatures = false,
|
||||
evaluatedConstTracker = effectiveConfiguration[CommonConfigurationKeys.EVALUATED_CONST_TRACKER] ?: EvaluatedConstTracker.create(),
|
||||
inlineConstTracker = effectiveConfiguration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
||||
expectActualTracker = effectiveConfiguration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||
allowNonCachedDeclarations = true,
|
||||
useIrFakeOverrideBuilder = effectiveConfiguration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||
)
|
||||
|
||||
return Fir2IrConverter.createIrModuleFragment(
|
||||
session,
|
||||
session.getScopeSession(),
|
||||
firFiles,
|
||||
fir2IrExtensions,
|
||||
fir2IrConfiguration,
|
||||
JvmIrMangler,
|
||||
IrFactoryImpl,
|
||||
FirJvmVisibilityConverter,
|
||||
Fir2IrJvmSpecialAnnotationSymbolProvider(),
|
||||
DefaultBuiltIns.Instance,
|
||||
Fir2IrCommonMemberStorage(signatureComposerForJvmFir2Ir(false), FirJvmKotlinMangler()),
|
||||
initializedIrBuiltIns = null,
|
||||
::JvmIrTypeSystemContext,
|
||||
)
|
||||
}
|
||||
|
||||
private fun patchCodeFragmentIr(fir2IrResult: Fir2IrResult) {
|
||||
fun isCodeFragmentFile(irFile: IrFile): Boolean {
|
||||
val firFiles = (irFile.metadata as? FirMetadataSource.File)?.files ?: return false
|
||||
@@ -391,11 +434,23 @@ internal class KtFirCompilerFacility(
|
||||
|
||||
private class CompilerFacilityFir2IrExtensions(
|
||||
delegate: Fir2IrExtensions,
|
||||
private val dependencyFir2IrResults: List<Fir2IrResult>,
|
||||
private val injectedValueProvider: InjectedSymbolProvider?
|
||||
) : Fir2IrExtensions by delegate {
|
||||
override fun findInjectedValue(calleeReference: FirReference, conversionScope: Fir2IrConversionScope): InjectedValue? {
|
||||
return injectedValueProvider?.invoke(calleeReference, conversionScope)
|
||||
}
|
||||
|
||||
@OptIn(DelicateSymbolTableApi::class)
|
||||
override fun registerDeclarations(symbolTable: SymbolTable) {
|
||||
val visitor = DeclarationRegistrarVisitor(symbolTable)
|
||||
|
||||
for (dependencyFir2IrResult in dependencyFir2IrResults) {
|
||||
for (dependencyFile in dependencyFir2IrResult.irModuleFragment.files) {
|
||||
dependencyFile.acceptVoid(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SingleFileGenerateClassFilter(
|
||||
@@ -567,3 +622,67 @@ private class IrDeclarationPatchingVisitor(private val mapping: Map<FirDeclarati
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DeclarationRegistrarVisitor(private val consumer: SymbolTable) : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
register(declaration, consumer::declareClassIfNotExists)
|
||||
super.visitClass(declaration)
|
||||
}
|
||||
|
||||
override fun visitTypeAlias(declaration: IrTypeAlias) {
|
||||
register(declaration, consumer::declareTypeAliasIfNotExists)
|
||||
super.visitTypeAlias(declaration)
|
||||
}
|
||||
|
||||
override fun visitScript(declaration: IrScript) {
|
||||
register(declaration, consumer::declareScript)
|
||||
super.visitScript(declaration)
|
||||
}
|
||||
|
||||
override fun visitTypeParameter(declaration: IrTypeParameter) {
|
||||
if (declaration.parent is IrClass) {
|
||||
register(declaration, consumer::declareGlobalTypeParameter)
|
||||
}
|
||||
|
||||
super.visitTypeParameter(declaration)
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
register(declaration, consumer::declareConstructorIfNotExists)
|
||||
super.visitConstructor(declaration)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||
register(declaration, consumer::declareSimpleFunctionIfNotExists)
|
||||
super.visitSimpleFunction(declaration)
|
||||
}
|
||||
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
register(declaration, consumer::declarePropertyIfNotExists)
|
||||
super.visitProperty(declaration)
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
register(declaration, consumer::declareField)
|
||||
super.visitField(declaration)
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(declaration: IrEnumEntry) {
|
||||
register(declaration, consumer::declareEnumEntry)
|
||||
super.visitEnumEntry(declaration)
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
private inline fun <reified S : IrSymbol, D : IrDeclaration> register(
|
||||
declaration: D,
|
||||
registrar: (IdSignature, () -> S, (S) -> D) -> Unit,
|
||||
) {
|
||||
val symbol = declaration.symbol as S
|
||||
val signature = symbol.signature ?: return
|
||||
registrar(signature, { symbol }, { declaration })
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.analysis.api.fir.test.cases.generated.cases.components.compilerFacility;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory;
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData;
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator;
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind;
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind;
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode;
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode;
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.compilerFacility.AbstractMultiModuleCompilerFacilityTest;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class FirIdeNormalAnalysisSourceModuleMultiModuleCompilerFacilityTestGenerated extends AbstractMultiModuleCompilerFacilityTest {
|
||||
@NotNull
|
||||
@Override
|
||||
public AnalysisApiTestConfigurator getConfigurator() {
|
||||
return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator(
|
||||
new AnalysisApiTestConfiguratorFactoryData(
|
||||
FrontendKind.Fir,
|
||||
TestModuleKind.Source,
|
||||
AnalysisSessionMode.Normal,
|
||||
AnalysisApiMode.Ide
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllFilesPresentInCompilationMultiModule() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonUsage.kt")
|
||||
public void testCommonUsage() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/commonUsage.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultParameterValue.kt")
|
||||
public void testDefaultParameterValue() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/defaultParameterValue.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("internalUsage.kt")
|
||||
public void testInternalUsage() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/internalUsage.kt");
|
||||
}
|
||||
}
|
||||
+15
-9
@@ -13,7 +13,8 @@ import org.jetbrains.kotlin.analysis.api.components.KtCompilerFacility
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtCompilerTarget
|
||||
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic
|
||||
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnosticWithPsi
|
||||
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedSingleModuleTest
|
||||
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedTest
|
||||
import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider
|
||||
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
@@ -36,6 +37,7 @@ import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirective
|
||||
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
@@ -45,7 +47,9 @@ import org.jetbrains.org.objectweb.asm.tree.ClassNode
|
||||
import java.io.File
|
||||
import kotlin.test.assertFalse
|
||||
|
||||
abstract class AbstractCompilerFacilityTest : AbstractAnalysisApiBasedSingleModuleTest() {
|
||||
abstract class AbstractMultiModuleCompilerFacilityTest : AbstractCompilerFacilityTest()
|
||||
|
||||
abstract class AbstractCompilerFacilityTest : AbstractAnalysisApiBasedTest() {
|
||||
private companion object {
|
||||
private val ALLOWED_ERRORS = listOf(
|
||||
FirErrors.INVISIBLE_REFERENCE,
|
||||
@@ -64,7 +68,9 @@ abstract class AbstractCompilerFacilityTest : AbstractAnalysisApiBasedSingleModu
|
||||
).map { it.name }
|
||||
}
|
||||
|
||||
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
||||
override fun doTestByModuleStructure(moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||
val mainModule = moduleStructure.modules.first { it.name == "main" }
|
||||
val ktFiles = testServices.ktModuleProvider.getModuleFiles(mainModule).filterIsInstance<KtFile>()
|
||||
val ktFile = ktFiles.singleOrNull() ?: ktFiles.first { it.name == "main.kt" }
|
||||
|
||||
val irCollector = CollectingIrGenerationExtension()
|
||||
@@ -73,22 +79,22 @@ abstract class AbstractCompilerFacilityTest : AbstractAnalysisApiBasedSingleModu
|
||||
project.extensionArea.getExtensionPoint(IrGenerationExtension.extensionPointName)
|
||||
.registerExtension(irCollector, LoadingOrder.LAST, project)
|
||||
|
||||
val ktCodeFragment = createCodeFragment(ktFile, module, testServices)
|
||||
val ktCodeFragment = createCodeFragment(ktFile, mainModule, testServices)
|
||||
if (ktCodeFragment != null) {
|
||||
for (importNameString in module.directives[Directives.CODE_FRAGMENT_IMPORT]) {
|
||||
for (importNameString in mainModule.directives[Directives.CODE_FRAGMENT_IMPORT]) {
|
||||
ktCodeFragment.addImport("import $importNameString")
|
||||
}
|
||||
}
|
||||
|
||||
val compilerConfiguration = CompilerConfiguration().apply {
|
||||
put(CommonConfigurationKeys.MODULE_NAME, module.name)
|
||||
put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, module.languageVersionSettings)
|
||||
put(CommonConfigurationKeys.MODULE_NAME, mainModule.name)
|
||||
put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, mainModule.languageVersionSettings)
|
||||
put(JVMConfigurationKeys.IR, true)
|
||||
|
||||
module.directives[Directives.CODE_FRAGMENT_CLASS_NAME].singleOrNull()
|
||||
mainModule.directives[Directives.CODE_FRAGMENT_CLASS_NAME].singleOrNull()
|
||||
?.let { put(KtCompilerFacility.CODE_FRAGMENT_CLASS_NAME, it) }
|
||||
|
||||
module.directives[Directives.CODE_FRAGMENT_METHOD_NAME].singleOrNull()
|
||||
mainModule.directives[Directives.CODE_FRAGMENT_METHOD_NAME].singleOrNull()
|
||||
?.let { put(KtCompilerFacility.CODE_FRAGMENT_METHOD_NAME, it) }
|
||||
}
|
||||
|
||||
|
||||
analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/commonUsage.ir.txt
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
MODULE_FRAGMENT
|
||||
FILE fqName:<root> fileName:main.kt
|
||||
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
||||
CALL 'public final fun lib (): kotlin.String declared in lib.LibKt' type=kotlin.String origin=null
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// MODULE: lib
|
||||
// TARGET_PLATFORM: Common
|
||||
// FILE: lib.kt
|
||||
|
||||
package lib
|
||||
|
||||
fun lib(): String = "foo"
|
||||
|
||||
// MODULE: main()()(lib)
|
||||
// TARGET_PLATFORM: JVM
|
||||
// FILE: main.kt
|
||||
|
||||
import lib.lib
|
||||
|
||||
fun test() {
|
||||
lib()
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
public final class MainKt {
|
||||
// source: 'main.kt'
|
||||
public final static method test(): void
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
MODULE_FRAGMENT
|
||||
FILE fqName:<root> fileName:main.kt
|
||||
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
||||
CALL 'public final fun lib (a: kotlin.Int): kotlin.String declared in lib.LibKt' type=kotlin.String origin=null
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
|
||||
package lib
|
||||
|
||||
fun lib(a: Int = 5): String {
|
||||
return "$a"
|
||||
}
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: main.kt
|
||||
|
||||
import lib.lib
|
||||
|
||||
fun test() {
|
||||
lib()
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
public final class MainKt {
|
||||
// source: 'main.kt'
|
||||
public final static method test(): void
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
MODULE_FRAGMENT
|
||||
FILE fqName:<root> fileName:main.kt
|
||||
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
||||
CALL 'internal final fun lib (): kotlin.String declared in lib.LibKt' type=kotlin.String origin=null
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
|
||||
package lib
|
||||
|
||||
internal fun lib(): String = "foo"
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: main.kt
|
||||
|
||||
import lib.lib
|
||||
|
||||
fun test() {
|
||||
lib()
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
public final class MainKt {
|
||||
// source: 'main.kt'
|
||||
public final static method test(): void
|
||||
}
|
||||
+5
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.callRes
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.callResolver.AbstractResolveCandidatesTest
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.compileTimeConstantProvider.AbstractCompileTimeConstantEvaluatorTest
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.compilerFacility.AbstractCompilerFacilityTest
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.compilerFacility.AbstractMultiModuleCompilerFacilityTest
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.containingDeclarationProvider.AbstractContainingDeclarationProviderByDelegatedMemberScopeTest
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.containingDeclarationProvider.AbstractContainingDeclarationProviderByMemberScopeTest
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.containingDeclarationProvider.AbstractContainingDeclarationProviderByPsiTest
|
||||
@@ -92,6 +93,10 @@ internal fun AnalysisApiTestGroup.generateAnalysisApiTests() {
|
||||
test(AbstractCompilerFacilityTest::class) {
|
||||
model("compilation", pattern = TestGeneratorUtil.KT_WITHOUT_DOTS_IN_NAME)
|
||||
}
|
||||
|
||||
test(AbstractMultiModuleCompilerFacilityTest::class, filter = testModuleKindIs(TestModuleKind.Source)) {
|
||||
model("compilationMultiModule", pattern = TestGeneratorUtil.KT_WITHOUT_DOTS_IN_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
group(filter = testModuleKindIs(TestModuleKind.Source, TestModuleKind.ScriptSource)) {
|
||||
|
||||
Reference in New Issue
Block a user