[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
if (session !is LLFirResolvableModuleSession) return
val moduleComponents = session.moduleComponents
moduleComponents.firModuleLazyDeclarationResolver.lazyResolveDeclaration(
firDeclarationToResolve = fir,
moduleComponents.firModuleLazyDeclarationResolver.lazyResolve(
target = fir,
scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
toPhase = toPhase,
checkPCE = true,
@@ -62,19 +62,19 @@ private fun FirRegularClass.collectForNonLocal(): List<FirDeclaration> {
return designation
}
private fun collectDesignationPath(resolvable: FirElementWithResolvePhase): List<FirDeclaration>? {
val containingClass = when (resolvable) {
private fun collectDesignationPath(target: FirElementWithResolvePhase): List<FirDeclaration>? {
val containingClass = when (target) {
is FirCallableDeclaration -> {
if (resolvable !is FirConstructor && resolvable.symbol.callableId.isLocal) return null
if ((resolvable as? FirCallableDeclaration)?.status?.visibility == Visibilities.Local) return null
when (resolvable) {
if (target !is FirConstructor && target.symbol.callableId.isLocal) return null
if ((target as? FirCallableDeclaration)?.status?.visibility == Visibilities.Local) return null
when (target) {
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
klass.toFirRegularClassFromSameSession(resolvable.moduleData.session)
klass.toFirRegularClassFromSameSession(target.moduleData.session)
}
is FirErrorProperty -> {
return if (resolvable.diagnostic == ConeDestructuringDeclarationsOnTopLevel) {
return if (target.diagnostic == ConeDestructuringDeclarationsOnTopLevel) {
emptyList()
} else {
null
@@ -84,10 +84,10 @@ private fun collectDesignationPath(resolvable: FirElementWithResolvePhase): List
}
}
is FirClassLikeDeclaration -> {
if (resolvable.isLocal) return null
val outerClassId = resolvable.symbol.classId.outerClassId
outerClassId?.let(resolvable.moduleData.session.firProvider::getFirClassifierByFqName)
?: outerClassId?.let(resolvable.moduleData.session.javaSymbolProvider::getClassLikeSymbolByClassId)?.fir
if (target.isLocal) return null
val outerClassId = target.symbol.classId.outerClassId
outerClassId?.let(target.moduleData.session.firProvider::getFirClassifierByFqName)
?: outerClassId?.let(target.moduleData.session.javaSymbolProvider::getClassLikeSymbolByClassId)?.fir
}
else -> return null
} ?: 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.parentsOfType
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.builder.buildFileAnnotationsContainer
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.realPsi
@@ -188,18 +189,22 @@ object LowLevelFirApiFacadeForResolveOnAir {
fileAnnotation = annotationEntry,
replacement = replacement
)
val fileAnnotationsContainer = buildFileAnnotationsContainer {
moduleData = firFile.moduleData
containingFileSymbol = firFile.symbol
annotations += annotationCall
}
val llFirResolvableSession = firFile.llFirResolvableSession
?: buildErrorWithAttachment("FirFile session expected to be a resolvable session but was ${firFile.llFirSession::class.java}") {
withEntry("firSession", firFile.llFirSession) { it.toString() }
}
val declarationResolver = llFirResolvableSession.moduleComponents.firModuleLazyDeclarationResolver
declarationResolver.resolveFileAnnotations(
firFile = firFile,
annotations = listOf(annotationCall),
scopeSession = ScopeSession(),
declarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock(
FirDesignationWithFile(path = emptyList(), target = fileAnnotationsContainer, firFile),
checkPCE = true,
collector = collector
onAirCreatedDeclaration = true,
collector
)
return annotationCall
@@ -49,7 +49,7 @@ internal class FileStructure private constructor(
when {
structureElement == null -> createStructureElement(declaration)
structureElement is ReanalyzableStructureElement<KtDeclaration, *> && !structureElement.isUpToDate() -> {
structureElement.reanalyze(newKtDeclaration = declaration as KtDeclaration,)
structureElement.reanalyze(newKtDeclaration = declaration as KtDeclaration)
}
else -> structureElement
}
@@ -115,12 +115,13 @@ internal class FileStructure private constructor(
private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) {
is KtFile -> {
val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
moduleComponents.firModuleLazyDeclarationResolver.resolveFileAnnotations(
firFile = firFile,
annotations = firFile.annotations,
moduleComponents.firModuleLazyDeclarationResolver.lazyResolve(
target = firFile.annotationsContainer,
scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
FirResolvePhase.BODY_RESOLVE,
checkPCE = true
)
RootStructureElement(firFile, container, moduleComponents)
}
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.sessions.LLFirSessionInvalidator
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.LLFirLazyTransformerExecutor
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.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
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.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
@@ -38,57 +37,6 @@ import org.jetbrains.kotlin.util.SourceCodeAnalysisException
import org.jetbrains.kotlin.util.shouldIjPlatformExceptionBeRethrown
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) {
is FirDeclarationOrigin.Source,
@@ -173,10 +121,11 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
if (toPhase == FirResolvePhase.IMPORTS) return
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
val designations = validForResolveDeclarations.map {
@@ -213,14 +162,14 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
}
private fun fastTrackForImportsPhase(
firDeclarationToResolve: FirDeclaration,
target: FirElementWithResolvePhase,
checkPCE: Boolean,
): Boolean {
val provider = firDeclarationToResolve.moduleData.session.firProvider
val firFile = when (firDeclarationToResolve) {
is FirFile -> firDeclarationToResolve
is FirCallableDeclaration -> provider.getFirCallableContainerFile(firDeclarationToResolve.symbol)
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(firDeclarationToResolve.symbol)
val provider = target.moduleData.session.firProvider
val firFile = when (target) {
is FirFile -> target
is FirCallableDeclaration -> provider.getFirCallableContainerFile(target.symbol)
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(target.symbol)
else -> null
} ?: return false
resolveFileToImports(firFile, checkPCE)
@@ -230,58 +179,57 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
/**
* Run designated resolve only designation with fully resolved path (synchronized).
* Suitable for body resolve or/and on-air resolve.
* @see lazyResolveDeclaration for ordinary resolve
* @param firDeclarationToResolve target non-local declaration
* @see lazyResolve for ordinary resolve
* @param target target non-local declaration
*/
fun lazyResolveDeclaration(
firDeclarationToResolve: FirDeclaration,
fun lazyResolve(
target: FirElementWithResolvePhase,
scopeSession: ScopeSession,
toPhase: FirResolvePhase,
checkPCE: Boolean,
) {
val fromPhase = firDeclarationToResolve.resolvePhase
val fromPhase = target.resolvePhase
try {
doLazyResolveDeclaration(firDeclarationToResolve, scopeSession, toPhase, checkPCE)
doLazyResolve(target, scopeSession, toPhase, checkPCE)
} catch (e: Throwable) {
handleExceptionFromResolve(e, moduleComponents.sessionInvalidator, firDeclarationToResolve, fromPhase, toPhase)
handleExceptionFromResolve(e, moduleComponents.sessionInvalidator, target, fromPhase, toPhase)
}
}
private fun doLazyResolveDeclaration(
firDeclarationToResolve: FirDeclaration,
private fun doLazyResolve(
target: FirElementWithResolvePhase,
scopeSession: ScopeSession,
toPhase: FirResolvePhase,
checkPCE: Boolean,
) {
if (toPhase == FirResolvePhase.RAW_FIR) return
if (toPhase == FirResolvePhase.IMPORTS) {
if (fastTrackForImportsPhase(firDeclarationToResolve, checkPCE)) {
if (fastTrackForImportsPhase(target, checkPCE)) {
return
}
}
when (firDeclarationToResolve) {
when (target) {
is FirSyntheticPropertyAccessor -> {
lazyResolveDeclaration(firDeclarationToResolve.delegate, scopeSession, toPhase, checkPCE,)
lazyResolve(target.delegate, scopeSession, toPhase, checkPCE,)
return
}
is FirBackingField -> {
lazyResolveDeclaration(firDeclarationToResolve.propertySymbol.fir, scopeSession, toPhase, checkPCE,)
lazyResolve(target.propertySymbol.fir, scopeSession, toPhase, checkPCE,)
return
}
is FirFile -> {
lazyResolveFileDeclaration(firDeclarationToResolve, toPhase, scopeSession, checkPCE = checkPCE)
lazyResolveFileDeclaration(target, toPhase, scopeSession, checkPCE = checkPCE)
return
}
else -> {}
}
if (!firDeclarationToResolve.isValidForResolve()) return
if (firDeclarationToResolve.resolvePhase >= toPhase) return
if (target is FirDeclaration && !target.isValidForResolve()) return
if (target.resolvePhase >= toPhase) return
val requestedDeclarationDesignation = firDeclarationToResolve.tryCollectDesignationWithFile()
val requestedDeclarationDesignation = target.tryCollectDesignationWithFile()
val designation: FirDesignationWithFile
val neededPhase: FirResolvePhase
@@ -290,12 +238,12 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
designation = requestedDeclarationDesignation
neededPhase = toPhase
} else {
val possiblyLocalDeclaration = firDeclarationToResolve.getKtDeclarationForFirElement()
val possiblyLocalDeclaration = (target as FirDeclaration).getKtDeclarationForFirElement()
val nonLocalDeclaration = possiblyLocalDeclaration.getNonLocalContainingOrThisDeclaration()
?: error("Container for local declaration cannot be null")
val isLocalDeclarationResolveRequested =
possiblyLocalDeclaration != nonLocalDeclaration
val isValueParameterInsidePrimaryConstructor = firDeclarationToResolve is FirValueParameter
val isValueParameterInsidePrimaryConstructor = target is FirValueParameter
&& possiblyLocalDeclaration is KtPrimaryConstructor
val declarationToResolve: FirDeclaration
@@ -305,13 +253,13 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
declarationToResolve = enumEntry.findSourceNonLocalFirDeclaration(
moduleComponents.firFileBuilder,
firDeclarationToResolve.moduleData.session.firProvider,
target.moduleData.session.firProvider,
)
neededPhase = FirResolvePhase.BODY_RESOLVE
} else {
declarationToResolve = nonLocalDeclaration.findSourceNonLocalFirDeclaration(
moduleComponents.firFileBuilder,
firDeclarationToResolve.moduleData.session.firProvider,
target.moduleData.session.firProvider,
)
neededPhase = toPhase
}
@@ -413,7 +361,7 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
private fun handleExceptionFromResolve(
e: Throwable,
sessionInvalidator: LLFirSessionInvalidator,
firDeclarationToResolve: FirDeclaration,
firDeclarationToResolve: FirElementWithResolvePhase,
fromPhase: FirResolvePhase,
toPhase: FirResolvePhase?
): Nothing {
@@ -425,11 +373,11 @@ private fun handleExceptionFromResolve(
appendLine("Error while resolving ${firDeclarationToResolve::class.java.name} ")
appendLine("from $fromPhase to $toPhase")
appendLine("current declaration phase ${firDeclarationToResolve.resolvePhase}")
appendLine("declaration origin: ${firDeclarationToResolve.origin}")
appendLine("declaration session: ${firDeclarationToResolve.llFirSession::class}")
appendLine("declaration module data: ${moduleData::class}")
appendLine("declaration KtModule: ${moduleData.ktModule::class}")
appendLine("declaration platform: ${moduleData.ktModule.platform}")
appendLine("origin: ${(firDeclarationToResolve as? FirDeclaration)?.origin}")
appendLine("session: ${firDeclarationToResolve.llFirSession::class}")
appendLine("module data: ${moduleData::class}")
appendLine("KtModule: ${moduleData.ktModule::class}")
appendLine("platform: ${moduleData.ktModule.platform}")
},
cause = if (e is SourceCodeAnalysisException) e.cause else e,
) {
@@ -48,14 +48,14 @@ internal class LLFirDesignatedAnnotationArgumentsMappingTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING)
if (resolvable !is FirAnnotationContainer) return
for (annotation in resolvable.annotations) {
override fun checkIsResolved(target: FirElementWithResolvePhase) {
target.checkPhase(FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING)
if (target !is FirAnnotationContainer) return
for (annotation in target.annotations) {
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.checkTypeRefIsResolved
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.FirSession
import org.jetbrains.kotlin.fir.declarations.*
@@ -66,23 +67,23 @@ internal class LLFirDesignatedAnnotationArgumentsResolveTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
if (resolvable !is FirDeclaration) return
val unresolvedAnnotation = resolvable.annotations.firstOrNull { it.annotationTypeRef !is FirResolvedTypeRef }
override fun checkIsResolved(target: FirElementWithResolvePhase) {
if (target !is FirAnnotationContainer) return
val unresolvedAnnotation = target.annotations.firstOrNull { it.annotationTypeRef !is FirResolvedTypeRef }
check(unresolvedAnnotation == null) {
"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) {
checkTypeRefIsResolved(argument.typeRef, "annotation argument", resolvable) {
checkTypeRefIsResolved(argument.typeRef, "annotation argument", target) {
withFirEntry("firAnnotation", annotation)
withFirEntry("firArgument", argument)
}
}
}
checkNestedDeclarationsAreResolved(resolvable)
checkNestedDeclarationsAreResolved(target)
}
}
@@ -57,8 +57,8 @@ internal class LLFirDesignatedAnnotationsResolveTransformed(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
override fun checkIsResolved(target: FirElementWithResolvePhase) {
target.checkPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
// todo add proper check that COMPILER_REQUIRED_ANNOTATIONS are resolved
// checkNestedDeclarationsAreResolved(declaration)
}
@@ -64,9 +64,9 @@ internal class LLFirDesignatedBodyResolveTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.BODY_RESOLVE)
checkNestedDeclarationsAreResolved(resolvable)
override fun checkIsResolved(target: FirElementWithResolvePhase) {
target.checkPhase(FirResolvePhase.BODY_RESOLVE)
checkNestedDeclarationsAreResolved(target)
}
}
@@ -57,11 +57,11 @@ internal class LLFirDesignatedContractsResolveTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.CONTRACTS)
if (resolvable is FirContractDescriptionOwner) {
override fun checkIsResolved(target: FirElementWithResolvePhase) {
target.checkPhase(FirResolvePhase.CONTRACTS)
if (target is FirContractDescriptionOwner) {
// TODO checkContractDescriptionIsResolved(declaration)
}
checkNestedDeclarationsAreResolved(resolvable)
checkNestedDeclarationsAreResolved(target)
}
}
@@ -52,10 +52,10 @@ internal class LLFirDesignatedExpectActualMatcherTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING)
override fun checkIsResolved(target: FirElementWithResolvePhase) {
target.checkPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING)
// TODO check if expect-actual matching is present
checkNestedDeclarationsAreResolved(resolvable)
checkNestedDeclarationsAreResolved(target)
}
}
@@ -30,7 +30,7 @@ internal class LLFirDesignatedGeneratedCompanionObjectResolveTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
check(resolvable.resolvePhase >= FirResolvePhase.COMPANION_GENERATION)
override fun checkIsResolved(target: FirElementWithResolvePhase) {
check(target.resolvePhase >= FirResolvePhase.COMPANION_GENERATION)
}
}
@@ -64,11 +64,11 @@ internal class LLFirDesignatedImplicitTypesTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
if (resolvable is FirCallableDeclaration) {
checkReturnTypeRefIsResolved(resolvable)
override fun checkIsResolved(target: FirElementWithResolvePhase) {
target.checkPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
if (target is FirCallableDeclaration) {
checkReturnTypeRefIsResolved(target)
}
checkNestedDeclarationsAreResolved(resolvable)
checkNestedDeclarationsAreResolved(target)
}
}
@@ -51,13 +51,13 @@ internal class LLFirDesignatedStatusResolveTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
if (resolvable !is FirAnonymousInitializer) {
resolvable.checkPhase(FirResolvePhase.STATUS)
override fun checkIsResolved(target: FirElementWithResolvePhase) {
if (target !is FirAnonymousInitializer) {
target.checkPhase(FirResolvePhase.STATUS)
}
if (resolvable is FirMemberDeclaration) {
checkDeclarationStatusIsResolved(resolvable)
if (target is FirMemberDeclaration) {
checkDeclarationStatusIsResolved(target)
}
checkNestedDeclarationsAreResolved(resolvable)
checkNestedDeclarationsAreResolved(target)
}
}
@@ -153,21 +153,21 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
checkIsResolved(designation.target)
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.SUPER_TYPES)
when (resolvable) {
override fun checkIsResolved(target: FirElementWithResolvePhase) {
target.checkPhase(FirResolvePhase.SUPER_TYPES)
when (target) {
is FirClass -> {
for (superTypeRef in resolvable.superTypeRefs) {
checkTypeRefIsResolved(superTypeRef, "class super type", resolvable)
for (superTypeRef in target.superTypeRefs) {
checkTypeRefIsResolved(superTypeRef, "class super type", target)
}
}
is FirTypeAlias -> {
checkTypeRefIsResolved(resolvable.expandedTypeRef, typeRefName = "type alias expanded type", resolvable)
checkTypeRefIsResolved(target.expandedTypeRef, typeRefName = "type alias expanded type", target)
}
else -> {}
}
checkNestedDeclarationsAreResolved(resolvable)
checkNestedDeclarationsAreResolved(target)
}
}
@@ -53,23 +53,23 @@ internal class LLFirDesignatedTypeResolverTransformer(
(designation.target as? FirDeclaration)?.let { checkClassMembersAreResolved(it) }
}
override fun checkIsResolved(resolvable: FirElementWithResolvePhase) {
resolvable.checkPhase(FirResolvePhase.TYPES)
when (resolvable) {
override fun checkIsResolved(target: FirElementWithResolvePhase) {
target.checkPhase(FirResolvePhase.TYPES)
when (target) {
is FirCallableDeclaration -> {
checkReturnTypeRefIsResolved(resolvable, acceptImplicitTypeRef = true)
checkReceiverTypeRefIsResolved(resolvable)
checkReturnTypeRefIsResolved(target, acceptImplicitTypeRef = true)
checkReceiverTypeRefIsResolved(target)
}
is FirTypeParameter -> {
for (bound in resolvable.bounds) {
checkTypeRefIsResolved(bound, "type parameter bound", resolvable)
for (bound in target.bounds) {
checkTypeRefIsResolved(bound, "type parameter bound", target)
}
}
else -> {}
}
checkNestedDeclarationsAreResolved(resolvable)
(resolvable as? FirDeclaration)?.let { checkTypeParametersAreResolved(it) }
checkNestedDeclarationsAreResolved(target)
(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 {
fun transformDeclaration(phaseRunner: LLFirPhaseRunner)
fun checkIsResolved(resolvable: FirElementWithResolvePhase)
fun checkIsResolved(target: FirElementWithResolvePhase)
fun checkNestedDeclarationsAreResolved(resolvable: FirElementWithResolvePhase) {
if (resolvable !is FirDeclaration) return
checkFunctionParametersAreResolved(resolvable)
checkPropertyAccessorsAreResolved(resolvable)
checkClassMembersAreResolved(resolvable)
fun checkNestedDeclarationsAreResolved(target: FirElementWithResolvePhase) {
if (target !is FirDeclaration) return
checkFunctionParametersAreResolved(target)
checkPropertyAccessorsAreResolved(target)
checkClassMembersAreResolved(target)
}
fun checkClassMembersAreResolved(declaration: FirDeclaration) {
@@ -63,7 +63,7 @@ internal interface LLFirLazyTransformer {
companion object {
private object WholeTreePhaseUpdater : FirVisitor<Unit, FirResolvePhase>() {
override fun visitElement(element: FirElement, data: FirResolvePhase) {
if (element is FirDeclaration) {
if (element is FirElementWithResolvePhase) {
if (element.resolvePhase >= data && element !is FirDefaultPropertyAccessor) return
element.replaceResolvePhase(data)
}
@@ -114,7 +114,7 @@ internal interface LLFirLazyTransformer {
val DUMMY = object : LLFirLazyTransformer {
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.FirFileAnnotationsContainer
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
fun FirElementWithResolvePhase.getContainingFile(): FirFile? {
@@ -17,6 +15,9 @@ fun FirElementWithResolvePhase.getContainingFile(): FirFile? {
return when (this) {
is FirFile -> this
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 FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(symbol)
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.checkWithAttachmentBuilder
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.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.*
@@ -20,7 +21,7 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
internal inline fun checkTypeRefIsResolved(
typeRef: FirTypeRef,
typeRefName: String,
owner: FirDeclaration,
owner: FirElementWithResolvePhase,
acceptImplicitTypeRef: Boolean = false,
extraAttachment: ExceptionAttachmentBuilder.() -> Unit = {}
) {
@@ -32,7 +33,7 @@ internal inline fun checkTypeRefIsResolved(
if (acceptImplicitTypeRef) {
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")
}
}
) {