[LL FIR] rework lazy annotation resolve for file to remove hacks

The previous solution blocked implementation of parallel resolve
This commit is contained in:
Ilya Kirillov
2022-12-07 18:38:36 +01:00
committed by teamcity
parent 3ad2b8a209
commit c2c615be99
20 changed files with 137 additions and 240 deletions
@@ -18,8 +18,8 @@ internal class LLFirLazyDeclarationResolver : FirLazyDeclarationResolver() {
val session = fir.moduleData.session val session = fir.moduleData.session
if (session !is LLFirResolvableModuleSession) return if (session !is LLFirResolvableModuleSession) return
val moduleComponents = session.moduleComponents val moduleComponents = session.moduleComponents
moduleComponents.firModuleLazyDeclarationResolver.lazyResolveDeclaration( moduleComponents.firModuleLazyDeclarationResolver.lazyResolve(
firDeclarationToResolve = fir, target = fir,
scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(), scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
toPhase = toPhase, toPhase = toPhase,
checkPCE = true, checkPCE = true,
@@ -62,19 +62,19 @@ private fun FirRegularClass.collectForNonLocal(): List<FirDeclaration> {
return designation return designation
} }
private fun collectDesignationPath(resolvable: FirElementWithResolvePhase): List<FirDeclaration>? { private fun collectDesignationPath(target: FirElementWithResolvePhase): List<FirDeclaration>? {
val containingClass = when (resolvable) { val containingClass = when (target) {
is FirCallableDeclaration -> { is FirCallableDeclaration -> {
if (resolvable !is FirConstructor && resolvable.symbol.callableId.isLocal) return null if (target !is FirConstructor && target.symbol.callableId.isLocal) return null
if ((resolvable as? FirCallableDeclaration)?.status?.visibility == Visibilities.Local) return null if ((target as? FirCallableDeclaration)?.status?.visibility == Visibilities.Local) return null
when (resolvable) { when (target) {
is FirSimpleFunction, is FirProperty, is FirField, is FirConstructor, is FirEnumEntry, is FirPropertyAccessor -> { is FirSimpleFunction, is FirProperty, is FirField, is FirConstructor, is FirEnumEntry, is FirPropertyAccessor -> {
val klass = resolvable.containingClassLookupTag() ?: return emptyList() val klass = target.containingClassLookupTag() ?: return emptyList()
if (klass.classId.isLocal) return null if (klass.classId.isLocal) return null
klass.toFirRegularClassFromSameSession(resolvable.moduleData.session) klass.toFirRegularClassFromSameSession(target.moduleData.session)
} }
is FirErrorProperty -> { is FirErrorProperty -> {
return if (resolvable.diagnostic == ConeDestructuringDeclarationsOnTopLevel) { return if (target.diagnostic == ConeDestructuringDeclarationsOnTopLevel) {
emptyList() emptyList()
} else { } else {
null null
@@ -84,10 +84,10 @@ private fun collectDesignationPath(resolvable: FirElementWithResolvePhase): List
} }
} }
is FirClassLikeDeclaration -> { is FirClassLikeDeclaration -> {
if (resolvable.isLocal) return null if (target.isLocal) return null
val outerClassId = resolvable.symbol.classId.outerClassId val outerClassId = target.symbol.classId.outerClassId
outerClassId?.let(resolvable.moduleData.session.firProvider::getFirClassifierByFqName) outerClassId?.let(target.moduleData.session.firProvider::getFirClassifierByFqName)
?: outerClassId?.let(resolvable.moduleData.session.javaSymbolProvider::getClassLikeSymbolByClassId)?.fir ?: outerClassId?.let(target.moduleData.session.javaSymbolProvider::getClassLikeSymbolByClassId)?.fir
} }
else -> return null else -> return null
} ?: return emptyList() } ?: return emptyList()
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.builder.buildFileAnnotationsContainer
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.realPsi import org.jetbrains.kotlin.fir.realPsi
@@ -188,18 +189,22 @@ object LowLevelFirApiFacadeForResolveOnAir {
fileAnnotation = annotationEntry, fileAnnotation = annotationEntry,
replacement = replacement replacement = replacement
) )
val fileAnnotationsContainer = buildFileAnnotationsContainer {
moduleData = firFile.moduleData
containingFileSymbol = firFile.symbol
annotations += annotationCall
}
val llFirResolvableSession = firFile.llFirResolvableSession val llFirResolvableSession = firFile.llFirResolvableSession
?: buildErrorWithAttachment("FirFile session expected to be a resolvable session but was ${firFile.llFirSession::class.java}") { ?: buildErrorWithAttachment("FirFile session expected to be a resolvable session but was ${firFile.llFirSession::class.java}") {
withEntry("firSession", firFile.llFirSession) { it.toString() } withEntry("firSession", firFile.llFirSession) { it.toString() }
} }
val declarationResolver = llFirResolvableSession.moduleComponents.firModuleLazyDeclarationResolver val declarationResolver = llFirResolvableSession.moduleComponents.firModuleLazyDeclarationResolver
declarationResolver.resolveFileAnnotations( declarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock(
firFile = firFile, FirDesignationWithFile(path = emptyList(), target = fileAnnotationsContainer, firFile),
annotations = listOf(annotationCall),
scopeSession = ScopeSession(),
checkPCE = true, checkPCE = true,
collector = collector onAirCreatedDeclaration = true,
collector
) )
return annotationCall return annotationCall
@@ -49,7 +49,7 @@ internal class FileStructure private constructor(
when { when {
structureElement == null -> createStructureElement(declaration) structureElement == null -> createStructureElement(declaration)
structureElement is ReanalyzableStructureElement<KtDeclaration, *> && !structureElement.isUpToDate() -> { structureElement is ReanalyzableStructureElement<KtDeclaration, *> && !structureElement.isUpToDate() -> {
structureElement.reanalyze(newKtDeclaration = declaration as KtDeclaration,) structureElement.reanalyze(newKtDeclaration = declaration as KtDeclaration)
} }
else -> structureElement else -> structureElement
} }
@@ -115,12 +115,13 @@ internal class FileStructure private constructor(
private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) { private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) {
is KtFile -> { is KtFile -> {
val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile) val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
moduleComponents.firModuleLazyDeclarationResolver.resolveFileAnnotations( moduleComponents.firModuleLazyDeclarationResolver.lazyResolve(
firFile = firFile, target = firFile.annotationsContainer,
annotations = firFile.annotations,
scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(), scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
FirResolvePhase.BODY_RESOLVE,
checkPCE = true checkPCE = true
) )
RootStructureElement(firFile, container, moduleComponents) RootStructureElement(firFile, container, moduleComponents)
} }
is KtDeclaration -> createDeclarationStructure(container) is KtDeclaration -> createDeclarationStructure(container)
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.runCustomRes
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionInvalidator import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionInvalidator
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.transformers.LLFirFileAnnotationsResolveTransformer
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirFirProviderInterceptor import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirFirProviderInterceptor
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformerExecutor import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformerExecutor
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
@@ -22,10 +21,10 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFi
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
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
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
@@ -38,57 +37,6 @@ import org.jetbrains.kotlin.util.SourceCodeAnalysisException
import org.jetbrains.kotlin.util.shouldIjPlatformExceptionBeRethrown import org.jetbrains.kotlin.util.shouldIjPlatformExceptionBeRethrown
internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirModuleResolveComponents) { internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirModuleResolveComponents) {
/**
* Fully resolve file annotations (synchronized)
* @see resolveFileAnnotationsWithoutLock not synchronized
*/
fun resolveFileAnnotations(
firFile: FirFile,
annotations: List<FirAnnotation>,
scopeSession: ScopeSession,
checkPCE: Boolean,
collector: FirTowerDataContextCollector? = null,
) {
val fromPhase = firFile.resolvePhase
try {
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS && annotations.all { it.resolved }) return
moduleComponents.globalResolveComponents.lockProvider.runCustomResolveUnderLock(firFile, checkPCE) {
resolveFileAnnotationsWithoutLock(
firFile = firFile,
annotations = annotations,
scopeSession = scopeSession,
collector = collector
)
}
} catch (e: Throwable) {
handleExceptionFromResolve(e, moduleComponents.sessionInvalidator, firFile, fromPhase, toPhase = null)
}
}
/**
* Fully resolve file annotations (not synchronized)
* @see resolveFileAnnotations synchronized version
*/
private fun resolveFileAnnotationsWithoutLock(
firFile: FirFile,
annotations: List<FirAnnotation>,
scopeSession: ScopeSession,
collector: FirTowerDataContextCollector? = null,
) {
if (firFile.resolvePhase < FirResolvePhase.IMPORTS) {
resolveFileToImportsWithoutLock(firFile, false)
}
if (!annotations.all { it.resolved }) {
LLFirFileAnnotationsResolveTransformer(
firFile = firFile,
annotations = annotations,
session = firFile.moduleData.session,
scopeSession = scopeSession,
firTowerDataContextCollector = collector,
).transformDeclaration(moduleComponents.globalResolveComponents.phaseRunner)
}
}
private fun FirDeclaration.isValidForResolve(): Boolean = when (origin) { private fun FirDeclaration.isValidForResolve(): Boolean = when (origin) {
is FirDeclarationOrigin.Source, is FirDeclarationOrigin.Source,
@@ -173,10 +121,11 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
if (toPhase == FirResolvePhase.IMPORTS) return if (toPhase == FirResolvePhase.IMPORTS) return
if (checkPCE) checkCanceled() if (checkPCE) checkCanceled()
resolveFileAnnotationsWithoutLock(firFile, firFile.annotations, scopeSession, collector) val validForResolveDeclarations = buildList {
add(firFile.annotationsContainer)
firFile.declarations.filterTo(this) { it.isValidForResolve() }
}.filter { it.resolvePhase < toPhase }
val validForResolveDeclarations = firFile.declarations
.filter { it.isValidForResolve() && it.resolvePhase < toPhase }
if (validForResolveDeclarations.isEmpty()) return if (validForResolveDeclarations.isEmpty()) return
val designations = validForResolveDeclarations.map { val designations = validForResolveDeclarations.map {
@@ -213,14 +162,14 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
} }
private fun fastTrackForImportsPhase( private fun fastTrackForImportsPhase(
firDeclarationToResolve: FirDeclaration, target: FirElementWithResolvePhase,
checkPCE: Boolean, checkPCE: Boolean,
): Boolean { ): Boolean {
val provider = firDeclarationToResolve.moduleData.session.firProvider val provider = target.moduleData.session.firProvider
val firFile = when (firDeclarationToResolve) { val firFile = when (target) {
is FirFile -> firDeclarationToResolve is FirFile -> target
is FirCallableDeclaration -> provider.getFirCallableContainerFile(firDeclarationToResolve.symbol) is FirCallableDeclaration -> provider.getFirCallableContainerFile(target.symbol)
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(firDeclarationToResolve.symbol) is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(target.symbol)
else -> null else -> null
} ?: return false } ?: return false
resolveFileToImports(firFile, checkPCE) resolveFileToImports(firFile, checkPCE)
@@ -230,58 +179,57 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
/** /**
* Run designated resolve only designation with fully resolved path (synchronized). * Run designated resolve only designation with fully resolved path (synchronized).
* Suitable for body resolve or/and on-air resolve. * Suitable for body resolve or/and on-air resolve.
* @see lazyResolveDeclaration for ordinary resolve * @see lazyResolve for ordinary resolve
* @param firDeclarationToResolve target non-local declaration * @param target target non-local declaration
*/ */
fun lazyResolveDeclaration( fun lazyResolve(
firDeclarationToResolve: FirDeclaration, target: FirElementWithResolvePhase,
scopeSession: ScopeSession, scopeSession: ScopeSession,
toPhase: FirResolvePhase, toPhase: FirResolvePhase,
checkPCE: Boolean, checkPCE: Boolean,
) { ) {
val fromPhase = firDeclarationToResolve.resolvePhase val fromPhase = target.resolvePhase
try { try {
doLazyResolveDeclaration(firDeclarationToResolve, scopeSession, toPhase, checkPCE) doLazyResolve(target, scopeSession, toPhase, checkPCE)
} catch (e: Throwable) { } catch (e: Throwable) {
handleExceptionFromResolve(e, moduleComponents.sessionInvalidator, firDeclarationToResolve, fromPhase, toPhase) handleExceptionFromResolve(e, moduleComponents.sessionInvalidator, target, fromPhase, toPhase)
} }
} }
private fun doLazyResolveDeclaration( private fun doLazyResolve(
firDeclarationToResolve: FirDeclaration, target: FirElementWithResolvePhase,
scopeSession: ScopeSession, scopeSession: ScopeSession,
toPhase: FirResolvePhase, toPhase: FirResolvePhase,
checkPCE: Boolean, checkPCE: Boolean,
) { ) {
if (toPhase == FirResolvePhase.RAW_FIR) return if (toPhase == FirResolvePhase.RAW_FIR) return
if (toPhase == FirResolvePhase.IMPORTS) { if (toPhase == FirResolvePhase.IMPORTS) {
if (fastTrackForImportsPhase(firDeclarationToResolve, checkPCE)) { if (fastTrackForImportsPhase(target, checkPCE)) {
return return
} }
} }
when (firDeclarationToResolve) { when (target) {
is FirSyntheticPropertyAccessor -> { is FirSyntheticPropertyAccessor -> {
lazyResolveDeclaration(firDeclarationToResolve.delegate, scopeSession, toPhase, checkPCE,) lazyResolve(target.delegate, scopeSession, toPhase, checkPCE,)
return return
} }
is FirBackingField -> { is FirBackingField -> {
lazyResolveDeclaration(firDeclarationToResolve.propertySymbol.fir, scopeSession, toPhase, checkPCE,) lazyResolve(target.propertySymbol.fir, scopeSession, toPhase, checkPCE,)
return return
} }
is FirFile -> { is FirFile -> {
lazyResolveFileDeclaration(firDeclarationToResolve, toPhase, scopeSession, checkPCE = checkPCE) lazyResolveFileDeclaration(target, toPhase, scopeSession, checkPCE = checkPCE)
return return
} }
else -> {} else -> {}
} }
if (!firDeclarationToResolve.isValidForResolve()) return if (target is FirDeclaration && !target.isValidForResolve()) return
if (firDeclarationToResolve.resolvePhase >= toPhase) return if (target.resolvePhase >= toPhase) return
val requestedDeclarationDesignation = target.tryCollectDesignationWithFile()
val requestedDeclarationDesignation = firDeclarationToResolve.tryCollectDesignationWithFile()
val designation: FirDesignationWithFile val designation: FirDesignationWithFile
val neededPhase: FirResolvePhase val neededPhase: FirResolvePhase
@@ -290,12 +238,12 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
designation = requestedDeclarationDesignation designation = requestedDeclarationDesignation
neededPhase = toPhase neededPhase = toPhase
} else { } else {
val possiblyLocalDeclaration = firDeclarationToResolve.getKtDeclarationForFirElement() val possiblyLocalDeclaration = (target as FirDeclaration).getKtDeclarationForFirElement()
val nonLocalDeclaration = possiblyLocalDeclaration.getNonLocalContainingOrThisDeclaration() val nonLocalDeclaration = possiblyLocalDeclaration.getNonLocalContainingOrThisDeclaration()
?: error("Container for local declaration cannot be null") ?: error("Container for local declaration cannot be null")
val isLocalDeclarationResolveRequested = val isLocalDeclarationResolveRequested =
possiblyLocalDeclaration != nonLocalDeclaration possiblyLocalDeclaration != nonLocalDeclaration
val isValueParameterInsidePrimaryConstructor = firDeclarationToResolve is FirValueParameter val isValueParameterInsidePrimaryConstructor = target is FirValueParameter
&& possiblyLocalDeclaration is KtPrimaryConstructor && possiblyLocalDeclaration is KtPrimaryConstructor
val declarationToResolve: FirDeclaration val declarationToResolve: FirDeclaration
@@ -305,13 +253,13 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
declarationToResolve = enumEntry.findSourceNonLocalFirDeclaration( declarationToResolve = enumEntry.findSourceNonLocalFirDeclaration(
moduleComponents.firFileBuilder, moduleComponents.firFileBuilder,
firDeclarationToResolve.moduleData.session.firProvider, target.moduleData.session.firProvider,
) )
neededPhase = FirResolvePhase.BODY_RESOLVE neededPhase = FirResolvePhase.BODY_RESOLVE
} else { } else {
declarationToResolve = nonLocalDeclaration.findSourceNonLocalFirDeclaration( declarationToResolve = nonLocalDeclaration.findSourceNonLocalFirDeclaration(
moduleComponents.firFileBuilder, moduleComponents.firFileBuilder,
firDeclarationToResolve.moduleData.session.firProvider, target.moduleData.session.firProvider,
) )
neededPhase = toPhase neededPhase = toPhase
} }
@@ -413,7 +361,7 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
private fun handleExceptionFromResolve( private fun handleExceptionFromResolve(
e: Throwable, e: Throwable,
sessionInvalidator: LLFirSessionInvalidator, sessionInvalidator: LLFirSessionInvalidator,
firDeclarationToResolve: FirDeclaration, firDeclarationToResolve: FirElementWithResolvePhase,
fromPhase: FirResolvePhase, fromPhase: FirResolvePhase,
toPhase: FirResolvePhase? toPhase: FirResolvePhase?
): Nothing { ): Nothing {
@@ -425,11 +373,11 @@ private fun handleExceptionFromResolve(
appendLine("Error while resolving ${firDeclarationToResolve::class.java.name} ") appendLine("Error while resolving ${firDeclarationToResolve::class.java.name} ")
appendLine("from $fromPhase to $toPhase") appendLine("from $fromPhase to $toPhase")
appendLine("current declaration phase ${firDeclarationToResolve.resolvePhase}") appendLine("current declaration phase ${firDeclarationToResolve.resolvePhase}")
appendLine("declaration origin: ${firDeclarationToResolve.origin}") appendLine("origin: ${(firDeclarationToResolve as? FirDeclaration)?.origin}")
appendLine("declaration session: ${firDeclarationToResolve.llFirSession::class}") appendLine("session: ${firDeclarationToResolve.llFirSession::class}")
appendLine("declaration module data: ${moduleData::class}") appendLine("module data: ${moduleData::class}")
appendLine("declaration KtModule: ${moduleData.ktModule::class}") appendLine("KtModule: ${moduleData.ktModule::class}")
appendLine("declaration platform: ${moduleData.ktModule.platform}") appendLine("platform: ${moduleData.ktModule.platform}")
}, },
cause = if (e is SourceCodeAnalysisException) e.cause else e, cause = if (e is SourceCodeAnalysisException) e.cause else e,
) { ) {
@@ -48,14 +48,14 @@ internal class LLFirDesignatedAnnotationArgumentsMappingTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING) target.checkPhase(FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING)
if (resolvable !is FirAnnotationContainer) return if (target !is FirAnnotationContainer) return
for (annotation in resolvable.annotations) { for (annotation in target.annotations) {
if (annotation is FirAnnotationCall) { if (annotation is FirAnnotationCall) {
checkAnnotationArgumentsMappingIsResolved(annotation, resolvable) checkAnnotationArgumentsMappingIsResolved(annotation, target)
} }
} }
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
} }
} }
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFil
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
@@ -66,23 +67,23 @@ internal class LLFirDesignatedAnnotationArgumentsResolveTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
if (resolvable !is FirDeclaration) return if (target !is FirAnnotationContainer) return
val unresolvedAnnotation = resolvable.annotations.firstOrNull { it.annotationTypeRef !is FirResolvedTypeRef } val unresolvedAnnotation = target.annotations.firstOrNull { it.annotationTypeRef !is FirResolvedTypeRef }
check(unresolvedAnnotation == null) { check(unresolvedAnnotation == null) {
"Unexpected annotationTypeRef annotation, expected resolvedType but actual ${unresolvedAnnotation?.annotationTypeRef}" "Unexpected annotationTypeRef annotation, expected resolvedType but actual ${unresolvedAnnotation?.annotationTypeRef}"
} }
resolvable.checkPhase(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS) target.checkPhase(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS)
for (annotation in resolvable.annotations) { for (annotation in target.annotations) {
for (argument in annotation.argumentMapping.mapping.values) { for (argument in annotation.argumentMapping.mapping.values) {
checkTypeRefIsResolved(argument.typeRef, "annotation argument", resolvable) { checkTypeRefIsResolved(argument.typeRef, "annotation argument", target) {
withFirEntry("firAnnotation", annotation) withFirEntry("firAnnotation", annotation)
withFirEntry("firArgument", argument) withFirEntry("firArgument", argument)
} }
} }
} }
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
} }
} }
@@ -57,8 +57,8 @@ internal class LLFirDesignatedAnnotationsResolveTransformed(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) target.checkPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
// todo add proper check that COMPILER_REQUIRED_ANNOTATIONS are resolved // todo add proper check that COMPILER_REQUIRED_ANNOTATIONS are resolved
// checkNestedDeclarationsAreResolved(declaration) // checkNestedDeclarationsAreResolved(declaration)
} }
@@ -64,9 +64,9 @@ internal class LLFirDesignatedBodyResolveTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.BODY_RESOLVE) target.checkPhase(FirResolvePhase.BODY_RESOLVE)
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
} }
} }
@@ -57,11 +57,11 @@ internal class LLFirDesignatedContractsResolveTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.CONTRACTS) target.checkPhase(FirResolvePhase.CONTRACTS)
if (resolvable is FirContractDescriptionOwner) { if (target is FirContractDescriptionOwner) {
// TODO checkContractDescriptionIsResolved(declaration) // TODO checkContractDescriptionIsResolved(declaration)
} }
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
} }
} }
@@ -52,10 +52,10 @@ internal class LLFirDesignatedExpectActualMatcherTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING) target.checkPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING)
// TODO check if expect-actual matching is present // TODO check if expect-actual matching is present
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
} }
} }
@@ -30,7 +30,7 @@ internal class LLFirDesignatedGeneratedCompanionObjectResolveTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
check(resolvable.resolvePhase >= FirResolvePhase.COMPANION_GENERATION) check(target.resolvePhase >= FirResolvePhase.COMPANION_GENERATION)
} }
} }
@@ -64,11 +64,11 @@ internal class LLFirDesignatedImplicitTypesTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) target.checkPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
if (resolvable is FirCallableDeclaration) { if (target is FirCallableDeclaration) {
checkReturnTypeRefIsResolved(resolvable) checkReturnTypeRefIsResolved(target)
} }
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
} }
} }
@@ -51,13 +51,13 @@ internal class LLFirDesignatedStatusResolveTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
if (resolvable !is FirAnonymousInitializer) { if (target !is FirAnonymousInitializer) {
resolvable.checkPhase(FirResolvePhase.STATUS) target.checkPhase(FirResolvePhase.STATUS)
} }
if (resolvable is FirMemberDeclaration) { if (target is FirMemberDeclaration) {
checkDeclarationStatusIsResolved(resolvable) checkDeclarationStatusIsResolved(target)
} }
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
} }
} }
@@ -153,21 +153,21 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
checkIsResolved(designation.target) checkIsResolved(designation.target)
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.SUPER_TYPES) target.checkPhase(FirResolvePhase.SUPER_TYPES)
when (resolvable) { when (target) {
is FirClass -> { is FirClass -> {
for (superTypeRef in resolvable.superTypeRefs) { for (superTypeRef in target.superTypeRefs) {
checkTypeRefIsResolved(superTypeRef, "class super type", resolvable) checkTypeRefIsResolved(superTypeRef, "class super type", target)
} }
} }
is FirTypeAlias -> { is FirTypeAlias -> {
checkTypeRefIsResolved(resolvable.expandedTypeRef, typeRefName = "type alias expanded type", resolvable) checkTypeRefIsResolved(target.expandedTypeRef, typeRefName = "type alias expanded type", target)
} }
else -> {} else -> {}
} }
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
} }
} }
@@ -53,23 +53,23 @@ internal class LLFirDesignatedTypeResolverTransformer(
(designation.target as? FirDeclaration)?.let { checkClassMembersAreResolved(it) } (designation.target as? FirDeclaration)?.let { checkClassMembersAreResolved(it) }
} }
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) { override fun checkIsResolved(target: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.TYPES) target.checkPhase(FirResolvePhase.TYPES)
when (resolvable) { when (target) {
is FirCallableDeclaration -> { is FirCallableDeclaration -> {
checkReturnTypeRefIsResolved(resolvable, acceptImplicitTypeRef = true) checkReturnTypeRefIsResolved(target, acceptImplicitTypeRef = true)
checkReceiverTypeRefIsResolved(resolvable) checkReceiverTypeRefIsResolved(target)
} }
is FirTypeParameter -> { is FirTypeParameter -> {
for (bound in resolvable.bounds) { for (bound in target.bounds) {
checkTypeRefIsResolved(bound, "type parameter bound", resolvable) checkTypeRefIsResolved(bound, "type parameter bound", target)
} }
} }
else -> {} else -> {}
} }
checkNestedDeclarationsAreResolved(resolvable) checkNestedDeclarationsAreResolved(target)
(resolvable as? FirDeclaration)?.let { checkTypeParametersAreResolved(it) } (target as? FirDeclaration)?.let { checkTypeParametersAreResolved(it) }
} }
} }
@@ -1,60 +0,0 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.resolved
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
internal class LLFirFileAnnotationsResolveTransformer(
private val firFile: FirFile,
private val annotations: List<FirAnnotation>,
session: FirSession,
scopeSession: ScopeSession,
implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession = ImplicitBodyResolveComputationSession(),
firTowerDataContextCollector: FirTowerDataContextCollector? = null,
) : FirBodyResolveTransformer(
session = session,
phase = FirResolvePhase.BODY_RESOLVE,
implicitTypeOnly = false,
scopeSession = scopeSession,
returnTypeCalculator = createReturnTypeCalculatorForIDE(
scopeSession,
implicitBodyResolveComputationSession,
::LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
),
firTowerDataContextCollector = firTowerDataContextCollector
), LLFirLazyTransformer {
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration {
require(declaration is FirFile) { "Unexpected declaration ${declaration::class.simpleName}" }
annotations.forEach {
if (!it.resolved) {
it.visitNoTransform(this, data)
}
}
return declaration
}
override fun transformDeclaration(phaseRunner: LLFirPhaseRunner) {
if (annotations.all { it.resolved }) return
check(firFile.resolvePhase >= FirResolvePhase.IMPORTS) { "Invalid file resolve phase ${firFile.resolvePhase}" }
firFile.accept(this, ResolutionMode.ContextDependent)
check(annotations.all { it.resolved }) {
"Annotation was not resolved"
}
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) = error("Not implemented")
}
@@ -16,13 +16,13 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitor
internal interface LLFirLazyTransformer { internal interface LLFirLazyTransformer {
fun transformDeclaration(phaseRunner: LLFirPhaseRunner) fun transformDeclaration(phaseRunner: LLFirPhaseRunner)
fun checkIsResolved(resolvable: FirElementWithResolvePhase) fun checkIsResolved(target: FirElementWithResolvePhase)
fun checkNestedDeclarationsAreResolved(resolvable: FirElementWithResolvePhase) { fun checkNestedDeclarationsAreResolved(target: FirElementWithResolvePhase) {
if (resolvable !is FirDeclaration) return if (target !is FirDeclaration) return
checkFunctionParametersAreResolved(resolvable) checkFunctionParametersAreResolved(target)
checkPropertyAccessorsAreResolved(resolvable) checkPropertyAccessorsAreResolved(target)
checkClassMembersAreResolved(resolvable) checkClassMembersAreResolved(target)
} }
fun checkClassMembersAreResolved(declaration: FirDeclaration) { fun checkClassMembersAreResolved(declaration: FirDeclaration) {
@@ -63,7 +63,7 @@ internal interface LLFirLazyTransformer {
companion object { companion object {
private object WholeTreePhaseUpdater : FirVisitor<Unit, FirResolvePhase>() { private object WholeTreePhaseUpdater : FirVisitor<Unit, FirResolvePhase>() {
override fun visitElement(element: FirElement, data: FirResolvePhase) { override fun visitElement(element: FirElement, data: FirResolvePhase) {
if (element is FirDeclaration) { if (element is FirElementWithResolvePhase) {
if (element.resolvePhase >= data && element !is FirDefaultPropertyAccessor) return if (element.resolvePhase >= data && element !is FirDefaultPropertyAccessor) return
element.replaceResolvePhase(data) element.replaceResolvePhase(data)
} }
@@ -114,7 +114,7 @@ internal interface LLFirLazyTransformer {
val DUMMY = object : LLFirLazyTransformer { val DUMMY = object : LLFirLazyTransformer {
override fun transformDeclaration(phaseRunner: LLFirPhaseRunner) = Unit override fun transformDeclaration(phaseRunner: LLFirPhaseRunner) = Unit
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) = error("Not implemented") override fun checkIsResolved(target: FirElementWithResolvePhase) = error("Not implemented")
} }
} }
} }
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider
fun FirElementWithResolvePhase.getContainingFile(): FirFile? { fun FirElementWithResolvePhase.getContainingFile(): FirFile? {
@@ -17,6 +15,9 @@ fun FirElementWithResolvePhase.getContainingFile(): FirFile? {
return when (this) { return when (this) {
is FirFile -> this is FirFile -> this
is FirFileAnnotationsContainer -> containingFileSymbol.fir is FirFileAnnotationsContainer -> containingFileSymbol.fir
is FirTypeParameter -> containingDeclarationSymbol.fir.getContainingFile()
is FirPropertyAccessor -> propertySymbol.fir.getContainingFile()
is FirValueParameter -> containingFunctionSymbol.fir.getContainingFile()
is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol) is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol)
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(symbol) is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(symbol)
else -> errorWithFirSpecificEntries("Unsupported declaration ${this::class.java}", fir = this) else -> errorWithFirSpecificEntries("Unsupported declaration ${this::class.java}", fir = this)
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.analysis.utils.errors.ExceptionAttachmentBuilder import org.jetbrains.kotlin.analysis.utils.errors.ExceptionAttachmentBuilder
import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder
import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
@@ -20,7 +21,7 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
internal inline fun checkTypeRefIsResolved( internal inline fun checkTypeRefIsResolved(
typeRef: FirTypeRef, typeRef: FirTypeRef,
typeRefName: String, typeRefName: String,
owner: FirDeclaration, owner: FirElementWithResolvePhase,
acceptImplicitTypeRef: Boolean = false, acceptImplicitTypeRef: Boolean = false,
extraAttachment: ExceptionAttachmentBuilder.() -> Unit = {} extraAttachment: ExceptionAttachmentBuilder.() -> Unit = {}
) { ) {
@@ -32,7 +33,7 @@ internal inline fun checkTypeRefIsResolved(
if (acceptImplicitTypeRef) { if (acceptImplicitTypeRef) {
append(" or ${FirImplicitTypeRef::class.simpleName}") append(" or ${FirImplicitTypeRef::class.simpleName}")
} }
append(" for $typeRefName of ${owner::class.simpleName}(${owner.origin}) but ${typeRef::class.simpleName} found") append(" for $typeRefName of ${owner::class.simpleName}(${(owner as? FirDeclaration)?.origin}) but ${typeRef::class.simpleName} found")
} }
} }
) { ) {