[LL FIR] rewrite compiler required annotations transformer to avoid lazy resolve under locks
^KT-56551
This commit is contained in:
committed by
Space Team
parent
4b1dc4eee6
commit
8f82649529
+4
-1
@@ -220,11 +220,13 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
fileAnnotation = annotationEntry,
|
fileAnnotation = annotationEntry,
|
||||||
replacement = replacement
|
replacement = replacement
|
||||||
)
|
)
|
||||||
|
|
||||||
val fileAnnotationsContainer = buildFileAnnotationsContainer {
|
val fileAnnotationsContainer = buildFileAnnotationsContainer {
|
||||||
moduleData = firFile.moduleData
|
moduleData = firFile.moduleData
|
||||||
containingFileSymbol = firFile.symbol
|
containingFileSymbol = firFile.symbol
|
||||||
annotations += annotationCall
|
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() }
|
||||||
@@ -239,7 +241,8 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
|
|
||||||
collector?.addFileContext(firFile, firFile.createTowerDataContext(firResolveSession.getScopeSessionFor(llFirResolvableSession)))
|
collector?.addFileContext(firFile, firFile.createTowerDataContext(firResolveSession.getScopeSessionFor(llFirResolvableSession)))
|
||||||
|
|
||||||
return annotationCall
|
// We should return annotation from fileAnnotationsContainer because the original annotation can be replaced
|
||||||
|
return fileAnnotationsContainer.annotations.single()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runBodyResolveOnAir(
|
private fun runBodyResolveOnAir(
|
||||||
|
|||||||
+15
-15
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
|||||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.SinceKotlin
|
|
||||||
import org.jetbrains.kotlin.fir.types.customAnnotations
|
import org.jetbrains.kotlin.fir.types.customAnnotations
|
||||||
import org.jetbrains.kotlin.fir.types.forEachType
|
import org.jetbrains.kotlin.fir.types.forEachType
|
||||||
|
|
||||||
@@ -57,6 +56,18 @@ internal object FirLazyBodiesCalculator {
|
|||||||
FirLazyAnnotationTransformerData(firElement.moduleData.session, FirLazyAnnotationTransformerScope.COMPILER_ONLY)
|
FirLazyAnnotationTransformerData(firElement.moduleData.session, FirLazyAnnotationTransformerScope.COMPILER_ONLY)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun calculateLazyArgumentsForAnnotation(annotationCall: FirAnnotationCall, session: FirSession): FirArgumentList {
|
||||||
|
require(needCalculatingAnnotationCall(annotationCall))
|
||||||
|
val builder = RawFirBuilder(session, baseScopeProvider = session.kotlinScopeProvider)
|
||||||
|
val ktAnnotationEntry = annotationCall.psi as KtAnnotationEntry
|
||||||
|
builder.context.packageFqName = ktAnnotationEntry.containingKtFile.packageFqName
|
||||||
|
val newAnnotationCall = builder.buildAnnotationCall(ktAnnotationEntry)
|
||||||
|
return newAnnotationCall.argumentList
|
||||||
|
}
|
||||||
|
|
||||||
|
fun needCalculatingAnnotationCall(firAnnotationCall: FirAnnotationCall): Boolean =
|
||||||
|
firAnnotationCall.argumentList.arguments.any { it is FirLazyExpression }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun replaceValueParameterDefaultValues(valueParameters: List<FirValueParameter>, newValueParameters: List<FirValueParameter>) {
|
private fun replaceValueParameterDefaultValues(valueParameters: List<FirValueParameter>, newValueParameters: List<FirValueParameter>) {
|
||||||
@@ -68,15 +79,6 @@ private fun replaceValueParameterDefaultValues(valueParameters: List<FirValuePar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateLazyArgumentsForAnnotation(annotationCall: FirAnnotationCall, session: FirSession) {
|
|
||||||
require(needCalculatingAnnotationCall(annotationCall))
|
|
||||||
val builder = RawFirBuilder(session, baseScopeProvider = session.kotlinScopeProvider)
|
|
||||||
val ktAnnotationEntry = annotationCall.psi as KtAnnotationEntry
|
|
||||||
builder.context.packageFqName = ktAnnotationEntry.containingKtFile.packageFqName
|
|
||||||
val newAnnotationCall = builder.buildAnnotationCall(ktAnnotationEntry)
|
|
||||||
annotationCall.replaceArgumentList(newAnnotationCall.argumentList)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun calculateLazyBodiesForFunction(designation: FirDesignation) {
|
private fun calculateLazyBodiesForFunction(designation: FirDesignation) {
|
||||||
val simpleFunction = designation.target as FirSimpleFunction
|
val simpleFunction = designation.target as FirSimpleFunction
|
||||||
require(needCalculatingLazyBodyForFunction(simpleFunction))
|
require(needCalculatingLazyBodyForFunction(simpleFunction))
|
||||||
@@ -214,9 +216,6 @@ private fun needCalculatingLazyBodyForProperty(firProperty: FirProperty): Boolea
|
|||||||
|| (firProperty.delegate as? FirWrappedDelegateExpression)?.expression is FirLazyExpression
|
|| (firProperty.delegate as? FirWrappedDelegateExpression)?.expression is FirLazyExpression
|
||||||
|| firProperty.getExplicitBackingField()?.initializer is FirLazyExpression
|
|| firProperty.getExplicitBackingField()?.initializer is FirLazyExpression
|
||||||
|
|
||||||
private fun needCalculatingAnnotationCall(firAnnotationCall: FirAnnotationCall): Boolean =
|
|
||||||
firAnnotationCall.argumentList.arguments.any { it is FirLazyExpression }
|
|
||||||
|
|
||||||
private enum class FirLazyAnnotationTransformerScope {
|
private enum class FirLazyAnnotationTransformerScope {
|
||||||
ALL_ANNOTATIONS,
|
ALL_ANNOTATIONS,
|
||||||
COMPILER_ONLY;
|
COMPILER_ONLY;
|
||||||
@@ -287,8 +286,9 @@ private abstract class FirLazyAnnotationTransformer : FirTransformer<FirLazyAnno
|
|||||||
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: FirLazyAnnotationTransformerData): FirStatement {
|
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: FirLazyAnnotationTransformerData): FirStatement {
|
||||||
val shouldCalculate = data.compilerAnnotationsOnly == FirLazyAnnotationTransformerScope.ALL_ANNOTATIONS ||
|
val shouldCalculate = data.compilerAnnotationsOnly == FirLazyAnnotationTransformerScope.ALL_ANNOTATIONS ||
|
||||||
canBeCompilerAnnotation(annotationCall, data.session)
|
canBeCompilerAnnotation(annotationCall, data.session)
|
||||||
if (shouldCalculate && needCalculatingAnnotationCall(annotationCall)) {
|
if (shouldCalculate && FirLazyBodiesCalculator.needCalculatingAnnotationCall(annotationCall)) {
|
||||||
calculateLazyArgumentsForAnnotation(annotationCall, data.session)
|
val newArgumentList = FirLazyBodiesCalculator.calculateLazyArgumentsForAnnotation(annotationCall, data.session)
|
||||||
|
annotationCall.replaceArgumentList(newArgumentList)
|
||||||
}
|
}
|
||||||
|
|
||||||
super.transformAnnotationCall(annotationCall, data)
|
super.transformAnnotationCall(annotationCall, data)
|
||||||
|
|||||||
+221
-18
@@ -13,17 +13,26 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockPro
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDeprecationProviderIsResolved
|
||||||
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.utils.errors.requireIsInstance
|
||||||
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||||
|
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||||
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
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.FirAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCallCopy
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsComputationSession
|
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsComputationSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredAnnotationsResolveTransformer
|
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredAnnotationsResolveTransformer
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
|
||||||
|
|
||||||
internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) {
|
internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) {
|
||||||
override fun resolve(
|
override fun resolve(
|
||||||
@@ -43,8 +52,12 @@ internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirReso
|
|||||||
|
|
||||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||||
target.checkPhase(resolverPhase)
|
target.checkPhase(resolverPhase)
|
||||||
|
when (target) {
|
||||||
|
is FirClassLikeDeclaration -> checkDeprecationProviderIsResolved(target, target.deprecationsProvider)
|
||||||
|
is FirCallableDeclaration -> checkDeprecationProviderIsResolved(target, target.deprecationsProvider)
|
||||||
|
}
|
||||||
|
|
||||||
checkNestedDeclarationsAreResolved(target)
|
checkNestedDeclarationsAreResolved(target)
|
||||||
// TODO add proper check that COMPILER_REQUIRED_ANNOTATIONS are resolved
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +67,7 @@ private class LLFirCompilerRequiredAnnotationsTargetResolver(
|
|||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
computationSession: LLFirCompilerRequiredAnnotationsComputationSession? = null,
|
computationSession: LLFirCompilerRequiredAnnotationsComputationSession? = null,
|
||||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS, isJumpingPhase = true) {
|
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS, isJumpingPhase = false) {
|
||||||
inner class LLFirCompilerRequiredAnnotationsComputationSession : CompilerRequiredAnnotationsComputationSession() {
|
inner class LLFirCompilerRequiredAnnotationsComputationSession : CompilerRequiredAnnotationsComputationSession() {
|
||||||
override fun resolveAnnotationSymbol(symbol: FirRegularClassSymbol, scopeSession: ScopeSession) {
|
override fun resolveAnnotationSymbol(symbol: FirRegularClassSymbol, scopeSession: ScopeSession) {
|
||||||
val regularClass = symbol.fir
|
val regularClass = symbol.fir
|
||||||
@@ -80,6 +93,10 @@ private class LLFirCompilerRequiredAnnotationsTargetResolver(
|
|||||||
computationSession ?: LLFirCompilerRequiredAnnotationsComputationSession(),
|
computationSession ?: LLFirCompilerRequiredAnnotationsComputationSession(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@OptIn(PrivateForInline::class)
|
||||||
|
private val llFirComputationSession: LLFirCompilerRequiredAnnotationsComputationSession
|
||||||
|
get() = transformer.annotationTransformer.computationSession as LLFirCompilerRequiredAnnotationsComputationSession
|
||||||
|
|
||||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||||
transformer.annotationTransformer.withFileAndFileScopes(firFile) {
|
transformer.annotationTransformer.withFileAndFileScopes(firFile) {
|
||||||
action()
|
action()
|
||||||
@@ -93,25 +110,211 @@ private class LLFirCompilerRequiredAnnotationsTargetResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
override fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean {
|
||||||
FirLazyBodiesCalculator.calculateCompilerAnnotations(target)
|
if (target !is FirRegularClass && !target.isRegularDeclarationWithAnnotation) {
|
||||||
|
throwUnexpectedFirElementError(target)
|
||||||
|
}
|
||||||
|
|
||||||
when {
|
requireIsInstance<FirAnnotationContainer>(target)
|
||||||
target is FirRegularClass -> {
|
resolveTargetDeclaration(target)
|
||||||
transformer.annotationTransformer.resolveRegularClass(
|
|
||||||
target,
|
return true
|
||||||
transformChildren = {},
|
}
|
||||||
afterChildrenTransform = {
|
|
||||||
transformer.annotationTransformer.calculateDeprecations(target)
|
private fun <T> resolveTargetDeclaration(target: T) where T : FirAnnotationContainer, T : FirElementWithResolveState {
|
||||||
}
|
// 1. Check that we should process this target
|
||||||
)
|
if (llFirComputationSession.annotationsAreResolved(target, treatNonSourceDeclarationsAsResolved = false)) return
|
||||||
|
|
||||||
|
// 2. Mark this target as resolved to avoid cycle
|
||||||
|
llFirComputationSession.recordThatAnnotationsAreResolved(target)
|
||||||
|
|
||||||
|
// 3. Create annotation transformer for targets we want to transform (under read lock)
|
||||||
|
// Exit if another thread is already resolved this target
|
||||||
|
val annotationTransformer = target.createAnnotationTransformer() ?: return
|
||||||
|
|
||||||
|
// 4. Exit if there are no applicable annotations, so we can just update the phase
|
||||||
|
if (annotationTransformer.isNothingToResolve()) {
|
||||||
|
return performCustomResolveUnderLock(target) {
|
||||||
|
// just update deprecations
|
||||||
|
annotationTransformer.publishResult(target)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
target.isRegularDeclarationWithAnnotation -> {
|
// 5. Transform annotations in the air
|
||||||
target.transformSingle(transformer.annotationTransformer, null)
|
annotationTransformer.transformAnnotations()
|
||||||
}
|
|
||||||
|
|
||||||
else -> throwUnexpectedFirElementError(target)
|
// 6. Move some annotations to the proper positions
|
||||||
|
annotationTransformer.balanceAnnotations(target)
|
||||||
|
|
||||||
|
// 7. Calculate deprecations in the air
|
||||||
|
annotationTransformer.calculateDeprecations(target)
|
||||||
|
|
||||||
|
// 8. Publish result
|
||||||
|
performCustomResolveUnderLock(target) {
|
||||||
|
annotationTransformer.publishResult(target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T> T.createAnnotationTransformer(): AnnotationTransformer? where T : FirAnnotationContainer, T : FirElementWithResolveState {
|
||||||
|
if (!hasAnnotationsToResolve()) {
|
||||||
|
return (AnnotationTransformer(mutableMapOf()))
|
||||||
|
}
|
||||||
|
|
||||||
|
val map = hashMapOf<FirElementWithResolveState, List<FirAnnotation>>()
|
||||||
|
var isUnresolved = false
|
||||||
|
withReadLock(this) {
|
||||||
|
isUnresolved = true
|
||||||
|
annotationsForTransformationTo(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
return map.takeIf { isUnresolved }?.let(::AnnotationTransformer)
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class AnnotationTransformer(
|
||||||
|
private val annotationMap: MutableMap<FirElementWithResolveState, List<FirAnnotation>>,
|
||||||
|
) {
|
||||||
|
private val deprecations: MutableMap<FirElementWithResolveState, DeprecationsProvider> = hashMapOf()
|
||||||
|
|
||||||
|
fun isNothingToResolve(): Boolean = annotationMap.isEmpty()
|
||||||
|
|
||||||
|
fun transformAnnotations() {
|
||||||
|
for (annotations in annotationMap.values) {
|
||||||
|
for (annotation in annotations) {
|
||||||
|
if (annotation !is FirAnnotationCall) continue
|
||||||
|
val typeRef = annotation.annotationTypeRef as? FirUserTypeRef ?: continue
|
||||||
|
if (!transformer.annotationTransformer.shouldRunAnnotationResolve(typeRef)) continue
|
||||||
|
transformer.annotationTransformer.transformAnnotationCall(annotation, typeRef)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun balanceAnnotations(target: FirElementWithResolveState) {
|
||||||
|
if (target !is FirProperty) return
|
||||||
|
val backingField = target.backingField ?: return
|
||||||
|
val updatedAnnotations = transformer.annotationTransformer.extractBackingFieldAnnotationsFromProperty(
|
||||||
|
target,
|
||||||
|
annotationMap[target].orEmpty(),
|
||||||
|
annotationMap[backingField].orEmpty(),
|
||||||
|
) ?: return
|
||||||
|
|
||||||
|
annotationMap[target] = updatedAnnotations.propertyAnnotations
|
||||||
|
annotationMap[backingField] = updatedAnnotations.backingFieldAnnotations
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateDeprecations(target: FirElementWithResolveState) {
|
||||||
|
val session = target.llFirSession
|
||||||
|
val cacheFactory = session.firCachesFactory
|
||||||
|
if (target is FirProperty) {
|
||||||
|
deprecations[target] = target.extractDeprecationInfoPerUseSite(
|
||||||
|
session = session,
|
||||||
|
customAnnotations = annotationMap[target].orEmpty(),
|
||||||
|
getterAnnotations = target.getter?.let(annotationMap::get).orEmpty(),
|
||||||
|
setterAnnotations = target.setter?.let(annotationMap::get).orEmpty(),
|
||||||
|
).toDeprecationsProvider(cacheFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((declaration, annotations) in annotationMap) {
|
||||||
|
if (declaration is FirProperty || declaration is FirFileAnnotationsContainer) continue
|
||||||
|
|
||||||
|
requireIsInstance<FirAnnotationContainer>(declaration)
|
||||||
|
deprecations[declaration] = declaration.extractDeprecationInfoPerUseSite(
|
||||||
|
session = session,
|
||||||
|
customAnnotations = annotations,
|
||||||
|
).toDeprecationsProvider(cacheFactory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> publishResult(target: T) where T : FirElementWithResolveState, T : FirAnnotationContainer {
|
||||||
|
val newAnnotations = annotationMap[target]
|
||||||
|
if (newAnnotations != null) {
|
||||||
|
target.replaceAnnotations(newAnnotations)
|
||||||
|
}
|
||||||
|
|
||||||
|
val deprecationProvider = deprecations[target] ?: EmptyDeprecationsProvider
|
||||||
|
when (target) {
|
||||||
|
is FirClassLikeDeclaration -> target.replaceDeprecationsProvider(deprecationProvider)
|
||||||
|
is FirCallableDeclaration -> target.replaceDeprecationsProvider(deprecationProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (target) {
|
||||||
|
is FirFunction -> target.valueParameters.forEach(::publishResult)
|
||||||
|
is FirProperty -> {
|
||||||
|
target.getter?.let(::publishResult)
|
||||||
|
target.setter?.let(::publishResult)
|
||||||
|
target.backingField?.let(::publishResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if at least one applicable annotation is present
|
||||||
|
*/
|
||||||
|
private fun <T> T.annotationsForTransformationTo(
|
||||||
|
map: MutableMap<FirElementWithResolveState, List<FirAnnotation>>,
|
||||||
|
) where T : FirAnnotationContainer, T : FirElementWithResolveState {
|
||||||
|
when (this) {
|
||||||
|
is FirFunction -> {
|
||||||
|
valueParameters.forEach {
|
||||||
|
it.annotationsForTransformationTo(map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is FirProperty -> {
|
||||||
|
getter?.annotationsForTransformationTo(map)
|
||||||
|
setter?.annotationsForTransformationTo(map)
|
||||||
|
backingField?.annotationsForTransformationTo(map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotations.isEmpty()) return
|
||||||
|
|
||||||
|
var hasApplicableAnnotation = false
|
||||||
|
val containerForAnnotations = ArrayList<FirAnnotation>(annotations.size)
|
||||||
|
for (annotation in annotations) {
|
||||||
|
val userTypeRef = (annotation as? FirAnnotationCall)?.annotationTypeRef as? FirUserTypeRef
|
||||||
|
containerForAnnotations += if (userTypeRef != null && transformer.annotationTransformer.shouldRunAnnotationResolve(userTypeRef)) {
|
||||||
|
hasApplicableAnnotation = true
|
||||||
|
buildAnnotationCallCopy(annotation) {
|
||||||
|
/**
|
||||||
|
* CRA transformer won't modify this type reference,
|
||||||
|
* but we create a deep copy
|
||||||
|
* to be sure that no one another thread can't modify this reference during another phase,
|
||||||
|
* while we do deep copy during
|
||||||
|
* [org.jetbrains.kotlin.fir.resolve.transformers.plugin.AbstractFirSpecificAnnotationResolveTransformer.transformAnnotationCall]
|
||||||
|
* without lock
|
||||||
|
*/
|
||||||
|
annotationTypeRef = transformer.annotationTransformer.createDeepCopyOfTypeRef(userTypeRef)
|
||||||
|
|
||||||
|
// We assume that non-empty argument must be a lazy expression, or it is a copied declaration inside an on-air session
|
||||||
|
if (FirLazyBodiesCalculator.needCalculatingAnnotationCall(annotation)) {
|
||||||
|
argumentList = FirLazyBodiesCalculator.calculateLazyArgumentsForAnnotation(annotation, llFirSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
annotation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasApplicableAnnotation) {
|
||||||
|
map[this] = containerForAnnotations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||||
|
throwUnexpectedFirElementError(target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirAnnotationContainer.hasAnnotationsToResolve(): Boolean {
|
||||||
|
if (annotations.isNotEmpty()) return true
|
||||||
|
|
||||||
|
return when (this) {
|
||||||
|
is FirFunction -> valueParameters.any(FirAnnotationContainer::hasAnnotationsToResolve)
|
||||||
|
is FirProperty -> this.getter?.hasAnnotationsToResolve() == true ||
|
||||||
|
this.setter?.hasAnnotationsToResolve() == true ||
|
||||||
|
this.backingField?.hasAnnotationsToResolve() == true
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+9
@@ -105,6 +105,15 @@ internal fun checkDefaultValueIsResolved(parameter: FirValueParameter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun checkDeprecationProviderIsResolved(declaration: FirDeclaration, provider: DeprecationsProvider) {
|
||||||
|
checkWithAttachmentBuilder(
|
||||||
|
condition = provider !is UnresolvedDeprecationProvider,
|
||||||
|
message = { "Unresolved deprecation provider found for ${declaration::class.simpleName}" }
|
||||||
|
) {
|
||||||
|
withFirEntry("declaration", declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun checkReturnTypeRefIsResolved(declaration: FirCallableDeclaration, acceptImplicitTypeRef: Boolean = false) {
|
internal fun checkReturnTypeRefIsResolved(declaration: FirCallableDeclaration, acceptImplicitTypeRef: Boolean = false) {
|
||||||
checkTypeRefIsResolved(declaration.returnTypeRef, typeRefName = "return type", declaration, acceptImplicitTypeRef)
|
checkTypeRefIsResolved(declaration.returnTypeRef, typeRefName = "return type", declaration, acceptImplicitTypeRef)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
|||||||
|
|
||||||
COMPILER_REQUIRED_ANNOTATIONS:
|
COMPILER_REQUIRED_ANNOTATIONS:
|
||||||
FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
||||||
@FILE:Deprecated[Unresolved](String())
|
@FILE:R|kotlin/Deprecated|[CompilerRequiredAnnotations](String())
|
||||||
@FILE:Anno[Unresolved](LAZY_EXPRESSION)
|
@FILE:Anno[Unresolved](LAZY_EXPRESSION)
|
||||||
[ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] annotations container
|
[ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] annotations container
|
||||||
@Target[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| {
|
@Target[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| {
|
||||||
@@ -45,7 +45,7 @@ FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
|||||||
|
|
||||||
COMPANION_GENERATION:
|
COMPANION_GENERATION:
|
||||||
FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
||||||
@FILE:Deprecated[Unresolved](String())
|
@FILE:R|kotlin/Deprecated|[CompilerRequiredAnnotations](String())
|
||||||
@FILE:Anno[Unresolved](LAZY_EXPRESSION)
|
@FILE:Anno[Unresolved](LAZY_EXPRESSION)
|
||||||
[ResolvedTo(COMPANION_GENERATION)] annotations container
|
[ResolvedTo(COMPANION_GENERATION)] annotations container
|
||||||
@Target[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| {
|
@Target[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| {
|
||||||
@@ -60,7 +60,7 @@ FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
|||||||
|
|
||||||
SUPER_TYPES:
|
SUPER_TYPES:
|
||||||
FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
FILE: [ResolvedTo(IMPORTS)] fileAnnotations.kt
|
||||||
@FILE:Deprecated[Unresolved](String())
|
@FILE:R|kotlin/Deprecated|[CompilerRequiredAnnotations](String())
|
||||||
@FILE:Anno[Unresolved](LAZY_EXPRESSION)
|
@FILE:Anno[Unresolved](LAZY_EXPRESSION)
|
||||||
[ResolvedTo(SUPER_TYPES)] annotations container
|
[ResolvedTo(SUPER_TYPES)] annotations container
|
||||||
@Target[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| {
|
@Target[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| {
|
||||||
|
|||||||
+40
-25
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -95,13 +95,25 @@ fun FirAnnotationContainer.getDeprecationsProvider(session: FirSession): Depreca
|
|||||||
return extractDeprecationInfoPerUseSite(session).toDeprecationsProvider(session.firCachesFactory)
|
return extractDeprecationInfoPerUseSite(session).toDeprecationsProvider(session.firCachesFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirAnnotationContainer.extractDeprecationInfoPerUseSite(session: FirSession): DeprecationAnnotationInfoPerUseSiteStorage {
|
fun FirAnnotationContainer.extractDeprecationInfoPerUseSite(
|
||||||
|
session: FirSession,
|
||||||
|
customAnnotations: List<FirAnnotation>? = annotations,
|
||||||
|
getterAnnotations: List<FirAnnotation>? = null,
|
||||||
|
setterAnnotations: List<FirAnnotation>? = null,
|
||||||
|
): DeprecationAnnotationInfoPerUseSiteStorage {
|
||||||
val fromJava = this is FirDeclaration && this.isJavaOrEnhancement
|
val fromJava = this is FirDeclaration && this.isJavaOrEnhancement
|
||||||
|
|
||||||
return buildDeprecationAnnotationInfoPerUseSiteStorage {
|
return buildDeprecationAnnotationInfoPerUseSiteStorage {
|
||||||
add(annotations.extractDeprecationAnnotationInfoPerUseSite(session, fromJava))
|
add((customAnnotations ?: annotations).extractDeprecationAnnotationInfoPerUseSite(session, fromJava))
|
||||||
if (this@extractDeprecationInfoPerUseSite is FirProperty) {
|
if (this@extractDeprecationInfoPerUseSite is FirProperty) {
|
||||||
add(getDeprecationsAnnotationInfoByUseSiteFromAccessors(session, getter, setter))
|
add(
|
||||||
|
getDeprecationsAnnotationInfoByUseSiteFromAccessors(
|
||||||
|
session = session,
|
||||||
|
getter = getter,
|
||||||
|
getterAnnotations = getterAnnotations,
|
||||||
|
setter = setter,
|
||||||
|
setterAnnotations = setterAnnotations,
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,31 +122,34 @@ fun getDeprecationsProviderFromAccessors(
|
|||||||
session: FirSession,
|
session: FirSession,
|
||||||
getter: FirFunction?,
|
getter: FirFunction?,
|
||||||
setter: FirFunction?
|
setter: FirFunction?
|
||||||
): DeprecationsProvider {
|
): DeprecationsProvider = getDeprecationsAnnotationInfoByUseSiteFromAccessors(
|
||||||
return getDeprecationsAnnotationInfoByUseSiteFromAccessors(session, getter, setter).toDeprecationsProvider(session.firCachesFactory)
|
session = session,
|
||||||
}
|
getter = getter,
|
||||||
|
setter = setter,
|
||||||
|
).toDeprecationsProvider(session.firCachesFactory)
|
||||||
|
|
||||||
fun getDeprecationsAnnotationInfoByUseSiteFromAccessors(
|
fun getDeprecationsAnnotationInfoByUseSiteFromAccessors(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
getter: FirFunction?,
|
getter: FirFunction?,
|
||||||
setter: FirFunction?
|
getterAnnotations: List<FirAnnotation>? = getter?.annotations,
|
||||||
): DeprecationAnnotationInfoPerUseSiteStorage {
|
setter: FirFunction?,
|
||||||
return buildDeprecationAnnotationInfoPerUseSiteStorage {
|
setterAnnotations: List<FirAnnotation>? = setter?.annotations,
|
||||||
val setterDeprecations = setter?.extractDeprecationInfoPerUseSite(session)
|
): DeprecationAnnotationInfoPerUseSiteStorage = buildDeprecationAnnotationInfoPerUseSiteStorage {
|
||||||
setterDeprecations?.storage?.forEach { (useSite, infos) ->
|
val setterDeprecations = setter?.extractDeprecationInfoPerUseSite(session, customAnnotations = setterAnnotations)
|
||||||
if (useSite == null) {
|
setterDeprecations?.storage?.forEach { (useSite, infos) ->
|
||||||
add(AnnotationUseSiteTarget.PROPERTY_SETTER, infos)
|
if (useSite == null) {
|
||||||
} else {
|
add(AnnotationUseSiteTarget.PROPERTY_SETTER, infos)
|
||||||
add(useSite, infos)
|
} else {
|
||||||
}
|
add(useSite, infos)
|
||||||
}
|
}
|
||||||
val getterDeprecations = getter?.extractDeprecationInfoPerUseSite(session)
|
}
|
||||||
getterDeprecations?.storage?.forEach { (useSite, infos) ->
|
|
||||||
if (useSite == null) {
|
val getterDeprecations = getter?.extractDeprecationInfoPerUseSite(session, customAnnotations = getterAnnotations)
|
||||||
add(AnnotationUseSiteTarget.PROPERTY_GETTER, infos)
|
getterDeprecations?.storage?.forEach { (useSite, infos) ->
|
||||||
} else {
|
if (useSite == null) {
|
||||||
add(useSite, infos)
|
add(AnnotationUseSiteTarget.PROPERTY_GETTER, infos)
|
||||||
}
|
} else {
|
||||||
|
add(useSite, infos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-31
@@ -226,27 +226,28 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
|
|||||||
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Nothing?): FirStatement {
|
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Nothing?): FirStatement {
|
||||||
val annotationTypeRef = annotationCall.annotationTypeRef
|
val annotationTypeRef = annotationCall.annotationTypeRef
|
||||||
if (annotationTypeRef !is FirUserTypeRef) return annotationCall
|
if (annotationTypeRef !is FirUserTypeRef) return annotationCall
|
||||||
val name = annotationTypeRef.qualifier.last().name
|
if (!shouldRunAnnotationResolve(annotationTypeRef)) return annotationCall
|
||||||
|
transformAnnotationCall(annotationCall, annotationTypeRef)
|
||||||
if (!shouldRunAnnotationResolve(name)) return annotationCall
|
return annotationCall
|
||||||
|
}
|
||||||
|
|
||||||
|
fun transformAnnotationCall(annotationCall: FirAnnotationCall, typeRef: FirUserTypeRef) {
|
||||||
val transformedAnnotationType = typeResolverTransformer.transformUserTypeRef(
|
val transformedAnnotationType = typeResolverTransformer.transformUserTypeRef(
|
||||||
annotationTypeRef.createDeepCopy(),
|
userTypeRef = createDeepCopyOfTypeRef(typeRef),
|
||||||
ScopeClassDeclaration(scopes.asReversed(), classDeclarationsStack)
|
data = ScopeClassDeclaration(scopes.asReversed(), classDeclarationsStack),
|
||||||
) as? FirResolvedTypeRef ?: return annotationCall
|
) as? FirResolvedTypeRef ?: return
|
||||||
|
|
||||||
resolveAnnotationsOnAnnotationIfNeeded(transformedAnnotationType)
|
resolveAnnotationsOnAnnotationIfNeeded(transformedAnnotationType)
|
||||||
|
|
||||||
if (!transformedAnnotationType.requiredToSave()) return annotationCall
|
if (!transformedAnnotationType.requiredToSave()) return
|
||||||
|
|
||||||
annotationCall.replaceAnnotationTypeRef(transformedAnnotationType)
|
annotationCall.replaceAnnotationTypeRef(transformedAnnotationType)
|
||||||
annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.CompilerRequiredAnnotations)
|
annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.CompilerRequiredAnnotations)
|
||||||
|
|
||||||
// TODO: what if we have type alias here?
|
// TODO: what if we have type alias here?
|
||||||
if (transformedAnnotationType.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId in REQUIRED_ANNOTATIONS_WITH_ARGUMENTS) {
|
if (transformedAnnotationType.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId in REQUIRED_ANNOTATIONS_WITH_ARGUMENTS) {
|
||||||
argumentsTransformer.transformAnnotation(annotationCall, ResolutionMode.ContextDependent)
|
argumentsTransformer.transformAnnotation(annotationCall, ResolutionMode.ContextDependent)
|
||||||
}
|
}
|
||||||
|
|
||||||
return annotationCall
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveAnnotationsOnAnnotationIfNeeded(annotationTypeRef: FirResolvedTypeRef) {
|
private fun resolveAnnotationsOnAnnotationIfNeeded(annotationTypeRef: FirResolvedTypeRef) {
|
||||||
@@ -258,7 +259,8 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
|
|||||||
error("Should not be there")
|
error("Should not be there")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldRunAnnotationResolve(name: Name): Boolean {
|
fun shouldRunAnnotationResolve(typeRef: FirUserTypeRef): Boolean {
|
||||||
|
val name = typeRef.qualifier.last().name
|
||||||
if (metaAnnotationsFromPlugins.isNotEmpty()) return true
|
if (metaAnnotationsFromPlugins.isNotEmpty()) return true
|
||||||
return name in REQUIRED_ANNOTATION_NAMES || annotationsFromPlugins.any { it.shortName() == name }
|
return name in REQUIRED_ANNOTATION_NAMES || annotationsFromPlugins.any { it.shortName() == name }
|
||||||
}
|
}
|
||||||
@@ -420,20 +422,31 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FirProperty.moveJavaDeprecatedAnnotationToBackingField() {
|
private fun FirProperty.moveJavaDeprecatedAnnotationToBackingField() {
|
||||||
val annotations = this.annotations
|
val newPosition = extractBackingFieldAnnotationsFromProperty(this) ?: return
|
||||||
val backingField = this.backingField
|
this.replaceAnnotations(newPosition.propertyAnnotations)
|
||||||
if (annotations.isNotEmpty() && backingField != null) {
|
backingField?.replaceAnnotations(newPosition.backingFieldAnnotations)
|
||||||
val (backingFieldAnnotations, propertyAnnotations) = annotations.partition {
|
|
||||||
it.toAnnotationClassIdSafe(session) == Java.Deprecated
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backingFieldAnnotations.isNotEmpty()) {
|
|
||||||
this.replaceAnnotations(propertyAnnotations)
|
|
||||||
backingField.replaceAnnotations(backingField.annotations + backingFieldAnnotations)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun extractBackingFieldAnnotationsFromProperty(
|
||||||
|
property: FirProperty,
|
||||||
|
propertyAnnotations: List<FirAnnotation> = property.annotations,
|
||||||
|
backingFieldAnnotations: List<FirAnnotation> = property.backingField?.annotations.orEmpty(),
|
||||||
|
): AnnotationsPosition? {
|
||||||
|
if (propertyAnnotations.isEmpty() || property.backingField == null) return null
|
||||||
|
|
||||||
|
val (newBackingFieldAnnotations, newPropertyAnnotations) = propertyAnnotations.partition {
|
||||||
|
it.toAnnotationClassIdSafe(session) == Java.Deprecated
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newBackingFieldAnnotations.isEmpty()) return null
|
||||||
|
return AnnotationsPosition(
|
||||||
|
propertyAnnotations = newPropertyAnnotations,
|
||||||
|
backingFieldAnnotations = backingFieldAnnotations + newBackingFieldAnnotations,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnotationsPosition(val backingFieldAnnotations: List<FirAnnotation>, val propertyAnnotations: List<FirAnnotation>)
|
||||||
|
|
||||||
override fun transformSimpleFunction(
|
override fun transformSimpleFunction(
|
||||||
simpleFunction: FirSimpleFunction,
|
simpleFunction: FirSimpleFunction,
|
||||||
data: Nothing?
|
data: Nothing?
|
||||||
@@ -525,20 +538,18 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirUserTypeRef.createDeepCopy(): FirUserTypeRef {
|
fun createDeepCopyOfTypeRef(original: FirUserTypeRef): FirUserTypeRef = buildUserTypeRef {
|
||||||
val original = this
|
source = original.source
|
||||||
return buildUserTypeRef {
|
isMarkedNullable = original.isMarkedNullable
|
||||||
source = original.source
|
annotations.addAll(original.annotations)
|
||||||
isMarkedNullable = original.isMarkedNullable
|
original.qualifier.mapTo(qualifier) { it.createDeepCopy() }
|
||||||
annotations.addAll(original.annotations)
|
|
||||||
original.qualifier.mapTo(qualifier) { it.createDeepCopy() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirQualifierPart.createDeepCopy(): FirQualifierPart {
|
private fun FirQualifierPart.createDeepCopy(): FirQualifierPart {
|
||||||
val newArgumentList = FirTypeArgumentListImpl(typeArgumentList.source).apply {
|
val newArgumentList = FirTypeArgumentListImpl(typeArgumentList.source).apply {
|
||||||
typeArgumentList.typeArguments.mapTo(typeArguments) { it.createDeepCopy() }
|
typeArgumentList.typeArguments.mapTo(typeArguments) { it.createDeepCopy() }
|
||||||
}
|
}
|
||||||
|
|
||||||
return FirQualifierPartImpl(
|
return FirQualifierPartImpl(
|
||||||
source,
|
source,
|
||||||
name,
|
name,
|
||||||
@@ -551,7 +562,7 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
|
|||||||
is FirTypeProjectionWithVariance -> buildTypeProjectionWithVariance {
|
is FirTypeProjectionWithVariance -> buildTypeProjectionWithVariance {
|
||||||
source = original.source
|
source = original.source
|
||||||
typeRef = when (val originalTypeRef = original.typeRef) {
|
typeRef = when (val originalTypeRef = original.typeRef) {
|
||||||
is FirUserTypeRef -> originalTypeRef.createDeepCopy()
|
is FirUserTypeRef -> createDeepCopyOfTypeRef(originalTypeRef)
|
||||||
else -> originalTypeRef
|
else -> originalTypeRef
|
||||||
}
|
}
|
||||||
variance = original.variance
|
variance = original.variance
|
||||||
|
|||||||
+10
-6
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.transformers.plugin
|
package org.jetbrains.kotlin.fir.resolve.transformers.plugin
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||||
@@ -141,15 +142,18 @@ open class CompilerRequiredAnnotationsComputationSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val declarationsWithResolvedAnnotations = mutableSetOf<FirDeclaration>()
|
private val declarationsWithResolvedAnnotations = mutableSetOf<FirAnnotationContainer>()
|
||||||
|
|
||||||
fun annotationsAreResolved(declaration: FirDeclaration): Boolean {
|
fun annotationsAreResolved(declaration: FirAnnotationContainer, treatNonSourceDeclarationsAsResolved: Boolean): Boolean {
|
||||||
if (declaration is FirFile) return false
|
if (declaration is FirFile) return false
|
||||||
if (declaration.origin != FirDeclarationOrigin.Source) return true
|
if (treatNonSourceDeclarationsAsResolved && declaration is FirDeclaration && declaration.origin != FirDeclarationOrigin.Source) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return declaration in declarationsWithResolvedAnnotations
|
return declaration in declarationsWithResolvedAnnotations
|
||||||
}
|
}
|
||||||
|
|
||||||
fun recordThatAnnotationsAreResolved(declaration: FirDeclaration) {
|
fun recordThatAnnotationsAreResolved(declaration: FirAnnotationContainer) {
|
||||||
if (!declarationsWithResolvedAnnotations.add(declaration)) {
|
if (!declarationsWithResolvedAnnotations.add(declaration)) {
|
||||||
error("Annotations are resolved twice")
|
error("Annotations are resolved twice")
|
||||||
}
|
}
|
||||||
@@ -157,7 +161,7 @@ open class CompilerRequiredAnnotationsComputationSession {
|
|||||||
|
|
||||||
fun resolveAnnotationsOnAnnotationIfNeeded(symbol: FirRegularClassSymbol, scopeSession: ScopeSession) {
|
fun resolveAnnotationsOnAnnotationIfNeeded(symbol: FirRegularClassSymbol, scopeSession: ScopeSession) {
|
||||||
val regularClass = symbol.fir
|
val regularClass = symbol.fir
|
||||||
if (annotationsAreResolved(regularClass)) return
|
if (annotationsAreResolved(regularClass, treatNonSourceDeclarationsAsResolved = true)) return
|
||||||
|
|
||||||
resolveAnnotationSymbol(symbol, scopeSession)
|
resolveAnnotationSymbol(symbol, scopeSession)
|
||||||
}
|
}
|
||||||
@@ -199,7 +203,7 @@ class FirSpecificAnnotationResolveTransformer(
|
|||||||
) : AbstractFirSpecificAnnotationResolveTransformer(session, scopeSession, computationSession) {
|
) : AbstractFirSpecificAnnotationResolveTransformer(session, scopeSession, computationSession) {
|
||||||
override fun shouldTransformDeclaration(declaration: FirDeclaration): Boolean {
|
override fun shouldTransformDeclaration(declaration: FirDeclaration): Boolean {
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
return !computationSession.annotationsAreResolved(declaration)
|
return !computationSession.annotationsAreResolved(declaration, treatNonSourceDeclarationsAsResolved = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user