IC: Implement expect/actual tracking
fixes NewMultiplatformIT.testIncrementalCompilation also #KT-61590 fixed
This commit is contained in:
committed by
Space Team
parent
9ed23a7f07
commit
e5ee364419
+3
-2
@@ -141,8 +141,9 @@ internal class KtFirCompilerFacility(
|
|||||||
effectiveConfiguration.languageVersionSettings,
|
effectiveConfiguration.languageVersionSettings,
|
||||||
diagnosticsReporter,
|
diagnosticsReporter,
|
||||||
linkViaSignatures = false,
|
linkViaSignatures = false,
|
||||||
effectiveConfiguration[CommonConfigurationKeys.EVALUATED_CONST_TRACKER] ?: EvaluatedConstTracker.create(),
|
evaluatedConstTracker = effectiveConfiguration[CommonConfigurationKeys.EVALUATED_CONST_TRACKER] ?: EvaluatedConstTracker.create(),
|
||||||
effectiveConfiguration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
inlineConstTracker = effectiveConfiguration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
||||||
|
expectActualTracker = effectiveConfiguration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = true,
|
allowNonCachedDeclarations = true,
|
||||||
useIrFakeOverrideBuilder = effectiveConfiguration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
useIrFakeOverrideBuilder = effectiveConfiguration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ fun transformFirToIr(
|
|||||||
evaluatedConstTracker = moduleStructure.compilerConfiguration
|
evaluatedConstTracker = moduleStructure.compilerConfiguration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = null,
|
inlineConstTracker = null,
|
||||||
|
expectActualTracker = moduleStructure.compilerConfiguration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder =
|
useIrFakeOverrideBuilder =
|
||||||
moduleStructure.compilerConfiguration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
moduleStructure.compilerConfiguration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||||
|
|||||||
+1
@@ -243,6 +243,7 @@ object FirKotlinToJvmBytecodeCompiler {
|
|||||||
evaluatedConstTracker = configuration
|
evaluatedConstTracker = configuration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
inlineConstTracker = configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
||||||
|
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ fun convertAnalyzedFirToIr(
|
|||||||
evaluatedConstTracker = input.configuration
|
evaluatedConstTracker = input.configuration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = input.configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
inlineConstTracker = input.configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
||||||
|
expectActualTracker = input.configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder = input.configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
useIrFakeOverrideBuilder = input.configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.fir.backend.jvm.Fir2IrJvmSpecialAnnotationSymbolProv
|
|||||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
|
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
|
||||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter
|
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.moduleData
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
|
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
|
||||||
@@ -171,7 +170,8 @@ fun FirResult.convertToIrAndActualize(
|
|||||||
commonMemberStorage.symbolTable,
|
commonMemberStorage.symbolTable,
|
||||||
irMangler,
|
irMangler,
|
||||||
Fir2IrConverter.friendModulesMap(outputs.last().session),
|
Fir2IrConverter.friendModulesMap(outputs.last().session),
|
||||||
fir2IrConfiguration.useIrFakeOverrideBuilder
|
fir2IrConfiguration.useIrFakeOverrideBuilder,
|
||||||
|
fir2IrConfiguration.expectActualTracker
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.fir.backend
|
|||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
|
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||||
import org.jetbrains.kotlin.incremental.components.InlineConstTracker
|
import org.jetbrains.kotlin.incremental.components.InlineConstTracker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,6 +37,7 @@ data class Fir2IrConfiguration(
|
|||||||
val linkViaSignatures: Boolean,
|
val linkViaSignatures: Boolean,
|
||||||
val evaluatedConstTracker: EvaluatedConstTracker,
|
val evaluatedConstTracker: EvaluatedConstTracker,
|
||||||
val inlineConstTracker: InlineConstTracker?,
|
val inlineConstTracker: InlineConstTracker?,
|
||||||
|
val expectActualTracker: ExpectActualTracker?,
|
||||||
val allowNonCachedDeclarations: Boolean,
|
val allowNonCachedDeclarations: Boolean,
|
||||||
val useIrFakeOverrideBuilder: Boolean,
|
val useIrFakeOverrideBuilder: Boolean,
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -278,6 +278,7 @@ open class IncrementalFirJvmCompilerRunner(
|
|||||||
evaluatedConstTracker = configuration
|
evaluatedConstTracker = configuration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
inlineConstTracker = configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
||||||
|
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||||
)
|
)
|
||||||
|
|||||||
+95
-40
@@ -6,21 +6,23 @@
|
|||||||
package org.jetbrains.kotlin.backend.common.actualizer
|
package org.jetbrains.kotlin.backend.common.actualizer
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
|
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
|
||||||
|
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.PsiIrFileEntry
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||||
import org.jetbrains.kotlin.ir.util.callableId
|
import org.jetbrains.kotlin.ir.util.callableId
|
||||||
import org.jetbrains.kotlin.ir.util.classIdOrFail
|
import org.jetbrains.kotlin.ir.util.classIdOrFail
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker
|
import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker
|
||||||
import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker
|
import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualCompatibilityChecker
|
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualCompatibilityChecker
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used to collect mapping between all expect and actuals declarations, which are declared in passed module fragments
|
* This class is used to collect mapping between all expect and actuals declarations, which are declared in passed module fragments
|
||||||
@@ -41,6 +43,7 @@ internal class ExpectActualCollector(
|
|||||||
private val dependentFragments: List<IrModuleFragment>,
|
private val dependentFragments: List<IrModuleFragment>,
|
||||||
private val typeSystemContext: IrTypeSystemContext,
|
private val typeSystemContext: IrTypeSystemContext,
|
||||||
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
|
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
|
||||||
|
private val expectActualTracker: ExpectActualTracker?,
|
||||||
) {
|
) {
|
||||||
data class Result(val expectToActualMap: MutableMap<IrSymbol, IrSymbol>, val classActualizationInfo: ClassActualizationInfo)
|
data class Result(val expectToActualMap: MutableMap<IrSymbol, IrSymbol>, val classActualizationInfo: ClassActualizationInfo)
|
||||||
|
|
||||||
@@ -61,12 +64,16 @@ internal class ExpectActualCollector(
|
|||||||
destination: MutableMap<IrSymbol, IrSymbol>,
|
destination: MutableMap<IrSymbol, IrSymbol>,
|
||||||
classActualizationInfo: ClassActualizationInfo,
|
classActualizationInfo: ClassActualizationInfo,
|
||||||
) {
|
) {
|
||||||
val linkCollector = ExpectActualLinkCollector(destination, classActualizationInfo, typeSystemContext, diagnosticsReporter)
|
val linkCollector = ExpectActualLinkCollector()
|
||||||
dependentFragments.forEach { linkCollector.visitModuleFragment(it) }
|
val linkCollectorContext =
|
||||||
|
ExpectActualLinkCollector.MatchingContext(
|
||||||
|
typeSystemContext, destination, diagnosticsReporter, expectActualTracker, classActualizationInfo, null
|
||||||
|
)
|
||||||
|
dependentFragments.forEach { linkCollector.visitModuleFragment(it, linkCollectorContext) }
|
||||||
// It doesn't make sense to link expects from the last module because actuals always should be located in another module
|
// It doesn't make sense to link expects from the last module because actuals always should be located in another module
|
||||||
// Thus relevant actuals are always missing for the last module
|
// Thus relevant actuals are always missing for the last module
|
||||||
// But the collector should be run anyway to detect and report "hanging" expect declarations
|
// But the collector should be run anyway to detect and report "hanging" expect declarations
|
||||||
linkCollector.visitModuleFragment(mainFragment)
|
linkCollector.visitModuleFragment(mainFragment, linkCollectorContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +82,8 @@ internal data class ClassActualizationInfo(
|
|||||||
val actualClasses: Map<ClassId, IrClassSymbol>,
|
val actualClasses: Map<ClassId, IrClassSymbol>,
|
||||||
// mapping from classId to actual typealias
|
// mapping from classId to actual typealias
|
||||||
val actualTypeAliases: Map<ClassId, IrTypeAliasSymbol>,
|
val actualTypeAliases: Map<ClassId, IrTypeAliasSymbol>,
|
||||||
val actualTopLevels: Map<CallableId, List<IrDeclarationWithName>>,
|
val actualTopLevels: Map<CallableId, List<IrSymbol>>,
|
||||||
|
val actualSymbolsToFile: Map<IrSymbol, IrFile?>,
|
||||||
) {
|
) {
|
||||||
fun getActualWithoutExpansion(classId: ClassId): IrSymbol? {
|
fun getActualWithoutExpansion(classId: ClassId): IrSymbol? {
|
||||||
return actualTypeAliases[classId] ?: actualClasses[classId]
|
return actualTypeAliases[classId] ?: actualClasses[classId]
|
||||||
@@ -94,16 +102,19 @@ private class ActualDeclarationsCollector {
|
|||||||
return ClassActualizationInfo(
|
return ClassActualizationInfo(
|
||||||
collector.actualClasses,
|
collector.actualClasses,
|
||||||
collector.actualTypeAliasesWithoutExpansion,
|
collector.actualTypeAliasesWithoutExpansion,
|
||||||
collector.actualTopLevels
|
collector.actualTopLevels,
|
||||||
|
collector.actualSymbolsToFile
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val actualClasses: MutableMap<ClassId, IrClassSymbol> = mutableMapOf()
|
private val actualClasses: MutableMap<ClassId, IrClassSymbol> = mutableMapOf()
|
||||||
private val actualTypeAliasesWithoutExpansion: MutableMap<ClassId, IrTypeAliasSymbol> = mutableMapOf()
|
private val actualTypeAliasesWithoutExpansion: MutableMap<ClassId, IrTypeAliasSymbol> = mutableMapOf()
|
||||||
private val actualTopLevels: MutableMap<CallableId, MutableList<IrDeclarationWithName>> = mutableMapOf()
|
private val actualTopLevels: MutableMap<CallableId, MutableList<IrSymbol>> = mutableMapOf()
|
||||||
|
private val actualSymbolsToFile: MutableMap<IrSymbol, IrFile?> = mutableMapOf()
|
||||||
|
|
||||||
private val visitedActualClasses = mutableSetOf<IrClass>()
|
private val visitedActualClasses = mutableSetOf<IrClass>()
|
||||||
|
private var currentFile: IrFile? = null
|
||||||
|
|
||||||
private fun collect(element: IrElement) {
|
private fun collect(element: IrElement) {
|
||||||
when (element) {
|
when (element) {
|
||||||
@@ -112,6 +123,12 @@ private class ActualDeclarationsCollector {
|
|||||||
collect(file)
|
collect(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is IrFile -> {
|
||||||
|
currentFile = element
|
||||||
|
for (declaration in element.declarations) {
|
||||||
|
collect(declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
is IrTypeAlias -> {
|
is IrTypeAlias -> {
|
||||||
if (!element.isActual) return
|
if (!element.isActual) return
|
||||||
|
|
||||||
@@ -120,6 +137,8 @@ private class ActualDeclarationsCollector {
|
|||||||
|
|
||||||
actualClasses[classId] = expandedTypeSymbol
|
actualClasses[classId] = expandedTypeSymbol
|
||||||
actualTypeAliasesWithoutExpansion[classId] = element.symbol
|
actualTypeAliasesWithoutExpansion[classId] = element.symbol
|
||||||
|
actualSymbolsToFile[expandedTypeSymbol] = currentFile
|
||||||
|
actualSymbolsToFile[element.symbol] = currentFile
|
||||||
|
|
||||||
collect(expandedTypeSymbol.owner)
|
collect(expandedTypeSymbol.owner)
|
||||||
}
|
}
|
||||||
@@ -127,6 +146,7 @@ private class ActualDeclarationsCollector {
|
|||||||
if (element.isExpect || !visitedActualClasses.add(element)) return
|
if (element.isExpect || !visitedActualClasses.add(element)) return
|
||||||
|
|
||||||
actualClasses[element.classIdOrFail] = element.symbol
|
actualClasses[element.classIdOrFail] = element.symbol
|
||||||
|
actualSymbolsToFile[element.symbol] = currentFile
|
||||||
for (declaration in element.declarations) {
|
for (declaration in element.declarations) {
|
||||||
collect(declaration)
|
collect(declaration)
|
||||||
}
|
}
|
||||||
@@ -154,65 +174,86 @@ private class ActualDeclarationsCollector {
|
|||||||
if (callableId.classId == null) {
|
if (callableId.classId == null) {
|
||||||
actualTopLevels
|
actualTopLevels
|
||||||
.getOrPut(callableId) { mutableListOf() }
|
.getOrPut(callableId) { mutableListOf() }
|
||||||
.add(callableDeclaration)
|
.add(callableDeclaration.symbol)
|
||||||
|
actualSymbolsToFile[callableDeclaration.symbol] = currentFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExpectActualLinkCollector(
|
private class ExpectActualLinkCollector : IrElementVisitor<Unit, ExpectActualLinkCollector.MatchingContext> {
|
||||||
private val destination: MutableMap<IrSymbol, IrSymbol>,
|
|
||||||
private val classActualizationInfo: ClassActualizationInfo,
|
|
||||||
typeSystemContext: IrTypeSystemContext,
|
|
||||||
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
|
|
||||||
) : IrElementVisitorVoid {
|
|
||||||
private val context = MatchingContext(typeSystemContext)
|
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction) {
|
override fun visitFile(declaration: IrFile, data: MatchingContext) {
|
||||||
|
super.visitFile(declaration, data.withNewCurrentFile(declaration))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunction(declaration: IrFunction, data: MatchingContext) {
|
||||||
if (declaration.isExpect) {
|
if (declaration.isExpect) {
|
||||||
matchExpectCallable(declaration, declaration.callableId)
|
matchExpectCallable(declaration, declaration.callableId, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitProperty(declaration: IrProperty) {
|
override fun visitProperty(declaration: IrProperty, data: MatchingContext) {
|
||||||
if (declaration.isExpect) {
|
if (declaration.isExpect) {
|
||||||
matchExpectCallable(declaration, declaration.callableId)
|
matchExpectCallable(declaration, declaration.callableId, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun matchExpectCallable(declaration: IrDeclarationWithName, callableId: CallableId) {
|
private fun matchExpectCallable(declaration: IrDeclarationWithName, callableId: CallableId, context: MatchingContext) {
|
||||||
val actualSymbols = classActualizationInfo.actualTopLevels[callableId]?.map { it.symbol }.orEmpty()
|
matchExpectDeclaration(
|
||||||
matchExpectDeclaration(declaration.symbol, actualSymbols)
|
declaration.symbol,
|
||||||
}
|
context.classActualizationInfo.actualTopLevels[callableId].orEmpty(),
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass) {
|
|
||||||
if (!declaration.isExpect) return
|
|
||||||
val classId = declaration.classIdOrFail
|
|
||||||
val expectClassSymbol = declaration.symbol
|
|
||||||
val actualClassLikeSymbol = classActualizationInfo.getActualWithoutExpansion(classId)
|
|
||||||
matchExpectDeclaration(expectClassSymbol, listOfNotNull(actualClassLikeSymbol))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun matchExpectDeclaration(expectSymbol: IrSymbol, actualSymbols: List<IrSymbol>) {
|
|
||||||
AbstractExpectActualCompatibilityChecker.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals(
|
|
||||||
expectSymbol,
|
|
||||||
actualSymbols,
|
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitClass(declaration: IrClass, data: MatchingContext) {
|
||||||
element.acceptChildrenVoid(this)
|
if (!declaration.isExpect) return
|
||||||
|
val classId = declaration.classIdOrFail
|
||||||
|
val expectClassSymbol = declaration.symbol
|
||||||
|
val actualClassLikeSymbol = data.classActualizationInfo.getActualWithoutExpansion(classId)
|
||||||
|
matchExpectDeclaration(expectClassSymbol, listOfNotNull(actualClassLikeSymbol), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class MatchingContext(
|
private fun matchExpectDeclaration(
|
||||||
|
expectSymbol: IrSymbol,
|
||||||
|
actualSymbols: List<IrSymbol>,
|
||||||
|
context: MatchingContext
|
||||||
|
) {
|
||||||
|
AbstractExpectActualCompatibilityChecker.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals(
|
||||||
|
expectSymbol,
|
||||||
|
actualSymbols,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitElement(element: IrElement, data: MatchingContext) {
|
||||||
|
element.acceptChildren(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MatchingContext(
|
||||||
typeSystemContext: IrTypeSystemContext,
|
typeSystemContext: IrTypeSystemContext,
|
||||||
|
private val destination: MutableMap<IrSymbol, IrSymbol>,
|
||||||
|
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
|
||||||
|
private val expectActualTracker: ExpectActualTracker?,
|
||||||
|
internal val classActualizationInfo: ClassActualizationInfo,
|
||||||
|
private val currentExpectFile: IrFile?,
|
||||||
) : IrExpectActualMatchingContext(typeSystemContext, classActualizationInfo.actualClasses) {
|
) : IrExpectActualMatchingContext(typeSystemContext, classActualizationInfo.actualClasses) {
|
||||||
|
|
||||||
|
private val currentExpectIoFile by lazy(LazyThreadSafetyMode.PUBLICATION) { currentExpectFile?.toIoFile() }
|
||||||
|
|
||||||
|
fun withNewCurrentFile(newCurrentFile: IrFile) =
|
||||||
|
MatchingContext(
|
||||||
|
typeContext, destination, diagnosticsReporter, expectActualTracker, classActualizationInfo, newCurrentFile
|
||||||
|
)
|
||||||
|
|
||||||
override fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol) {
|
override fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol) {
|
||||||
destination[expectClassSymbol] = actualClassSymbol
|
destination[expectClassSymbol] = actualClassSymbol
|
||||||
|
expectActualTracker?.reportWithCurrentFile(actualClassSymbol)
|
||||||
recordActualForExpectDeclaration(expectClassSymbol, actualClassSymbol, destination)
|
recordActualForExpectDeclaration(expectClassSymbol, actualClassSymbol, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol) {
|
override fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol) {
|
||||||
|
expectActualTracker?.reportWithCurrentFile(actualSymbol)
|
||||||
recordActualForExpectDeclaration(expectSymbol, actualSymbol, destination)
|
recordActualForExpectDeclaration(expectSymbol, actualSymbol, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,5 +274,19 @@ private class ExpectActualLinkCollector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ExpectActualTracker.reportWithCurrentFile(actualSymbol: IrSymbol) {
|
||||||
|
if (currentExpectFile != null) {
|
||||||
|
val actualIoFile = classActualizationInfo.actualSymbolsToFile[actualSymbol]?.toIoFile()
|
||||||
|
if (actualIoFile != null) {
|
||||||
|
report(currentExpectIoFile!!, actualIoFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrFile.toIoFile(): File? = when (val fe = fileEntry) {
|
||||||
|
is PsiIrFileEntry -> fe.psiFile.virtualFile.let { it.fileSystem.getNioPath(it)?.toFile() }
|
||||||
|
else -> File(fileEntry.name).takeIf { it.exists() }
|
||||||
|
}
|
||||||
+5
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
|
|||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
||||||
@@ -27,7 +28,8 @@ object IrActualizer {
|
|||||||
mangler: KotlinMangler.IrMangler,
|
mangler: KotlinMangler.IrMangler,
|
||||||
// TODO: drop this argument in favor of using [IrModuleDescriptor::shouldSeeInternalsOf] in FakeOverrideBuilder KT-61384
|
// TODO: drop this argument in favor of using [IrModuleDescriptor::shouldSeeInternalsOf] in FakeOverrideBuilder KT-61384
|
||||||
friendModules: Map<String, List<String>>,
|
friendModules: Map<String, List<String>>,
|
||||||
useIrFakeOverrideBuilder: Boolean
|
useIrFakeOverrideBuilder: Boolean,
|
||||||
|
expectActualTracker: ExpectActualTracker?
|
||||||
): IrActualizedResult {
|
): IrActualizedResult {
|
||||||
val ktDiagnosticReporter = KtDiagnosticReporterWithImplicitIrBasedContext(diagnosticReporter, languageVersionSettings)
|
val ktDiagnosticReporter = KtDiagnosticReporterWithImplicitIrBasedContext(diagnosticReporter, languageVersionSettings)
|
||||||
|
|
||||||
@@ -37,7 +39,8 @@ object IrActualizer {
|
|||||||
mainFragment,
|
mainFragment,
|
||||||
dependentFragments,
|
dependentFragments,
|
||||||
typeSystemContext,
|
typeSystemContext,
|
||||||
ktDiagnosticReporter
|
ktDiagnosticReporter,
|
||||||
|
expectActualTracker
|
||||||
).collect()
|
).collect()
|
||||||
if (languageVersionSettings.supportsFeature(LanguageFeature.MultiplatformRestrictions)) {
|
if (languageVersionSettings.supportsFeature(LanguageFeature.MultiplatformRestrictions)) {
|
||||||
IrExpectActualAnnotationMatchingChecker(expectActualMap, actualDeclarations, typeSystemContext, ktDiagnosticReporter).check()
|
IrExpectActualAnnotationMatchingChecker(expectActualMap, actualDeclarations, typeSystemContext, ktDiagnosticReporter).check()
|
||||||
|
|||||||
+1
@@ -40,6 +40,7 @@ class IrActualizerAndPluginsFacade(
|
|||||||
inputArtifact.irMangler,
|
inputArtifact.irMangler,
|
||||||
mapOf(module.name to module.friendDependencies.map { it.moduleName }),
|
mapOf(module.name to module.friendDependencies.map { it.moduleName }),
|
||||||
useIrFakeOverrideBuilder = CodegenTestDirectives.ENABLE_IR_FAKE_OVERRIDE_GENERATION in module.directives,
|
useIrFakeOverrideBuilder = CodegenTestDirectives.ENABLE_IR_FAKE_OVERRIDE_GENERATION in module.directives,
|
||||||
|
expectActualTracker = null,
|
||||||
)
|
)
|
||||||
inputArtifact.irActualizerResult = result
|
inputArtifact.irActualizerResult = result
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -168,6 +168,7 @@ fun ModuleCompilerAnalyzedOutput.convertToJsIr(
|
|||||||
evaluatedConstTracker = configuration
|
evaluatedConstTracker = configuration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = null,
|
inlineConstTracker = null,
|
||||||
|
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder = module.shouldUseIrFakeOverrideBuilderInConvertToIr()
|
useIrFakeOverrideBuilder = module.shouldUseIrFakeOverrideBuilderInConvertToIr()
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -105,6 +105,7 @@ class Fir2IrJvmResultsConverter(
|
|||||||
evaluatedConstTracker = compilerConfiguration
|
evaluatedConstTracker = compilerConfiguration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = compilerConfiguration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
inlineConstTracker = compilerConfiguration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
||||||
|
expectActualTracker = compilerConfiguration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder = module.shouldUseIrFakeOverrideBuilderInConvertToIr(),
|
useIrFakeOverrideBuilder = module.shouldUseIrFakeOverrideBuilderInConvertToIr(),
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -167,6 +167,7 @@ fun ModuleCompilerAnalyzedOutput.convertToWasmIr(
|
|||||||
evaluatedConstTracker = configuration
|
evaluatedConstTracker = configuration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = null,
|
inlineConstTracker = null,
|
||||||
|
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder = module.shouldUseIrFakeOverrideBuilderInConvertToIr(),
|
useIrFakeOverrideBuilder = module.shouldUseIrFakeOverrideBuilderInConvertToIr(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ object GenerationUtils {
|
|||||||
evaluatedConstTracker = configuration
|
evaluatedConstTracker = configuration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
inlineConstTracker = configuration[CommonConfigurationKeys.INLINE_CONST_TRACKER],
|
||||||
|
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -80,6 +80,7 @@ internal fun PhaseContext.fir2Ir(
|
|||||||
evaluatedConstTracker = configuration
|
evaluatedConstTracker = configuration
|
||||||
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
|
||||||
inlineConstTracker = null,
|
inlineConstTracker = null,
|
||||||
|
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
|
||||||
allowNonCachedDeclarations = false,
|
allowNonCachedDeclarations = false,
|
||||||
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user