[FE] Implement safe publishing in ARGUMENTS_OF_ANNOTATIONS

This commit is contained in:
Yan Zhulanow
2023-06-10 00:27:40 +09:00
committed by Space Team
parent 90977f6a8c
commit 89797815a4
@@ -5,13 +5,13 @@
package org.jetbrains.kotlin.fir.resolve.transformers.plugin package org.jetbrains.kotlin.fir.resolve.transformers.plugin
import org.jetbrains.kotlin.KtSourceElement
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.containingClassLookupTag import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguouslyResolvedAnnotationArgument import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguouslyResolvedAnnotationArgument
import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
open class FirAnnotationArgumentsResolveTransformer( open class FirAnnotationArgumentsResolveTransformer(
@@ -298,7 +299,7 @@ private class FirExpressionsResolveTransformerForSpecificAnnotations(transformer
if (calleeReference is FirResolvedNamedReference) { if (calleeReference is FirResolvedNamedReference) {
val resolvedSymbol = calleeReference.resolvedSymbol val resolvedSymbol = calleeReference.resolvedSymbol
if (resolvedSymbol is FirEnumEntrySymbol && resolvedSymbol.containingClassLookupTag()?.classId in classIdsToCheck) { if (resolvedSymbol is FirEnumEntrySymbol && resolvedSymbol.containingClassLookupTag()?.classId in classIdsToCheck) {
resolveSpecialPropertyAccess(qualifiedAccessExpression, calleeReference, resolvedSymbol, data) return resolveSpecialPropertyAccess(qualifiedAccessExpression, calleeReference, resolvedSymbol, data)
} }
} }
} }
@@ -307,31 +308,39 @@ private class FirExpressionsResolveTransformerForSpecificAnnotations(transformer
} }
private fun resolveSpecialPropertyAccess( private fun resolveSpecialPropertyAccess(
qualifiedAccessExpression: FirPropertyAccessExpression, originalAccess: FirPropertyAccessExpression,
calleeReference: FirResolvedNamedReference, originalCalleeReference: FirResolvedNamedReference,
resolvedSymbol: FirEnumEntrySymbol, originalResolvedSymbol: FirEnumEntrySymbol,
data: ResolutionMode, data: ResolutionMode,
): FirStatement { ): FirStatement {
(qualifiedAccessExpression.explicitReceiver as? FirResolvedQualifier)?.let { val accessCopyForResolution = buildPropertyAccessExpression {
qualifiedAccessExpression.replaceResolvedQualifierReceiver(it) source = originalAccess.source
} typeArguments.addAll(originalAccess.typeArguments)
qualifiedAccessExpression.replaceDispatchReceiver(FirNoReceiverExpression)
qualifiedAccessExpression.replaceTypeRef(noExpectedType)
qualifiedAccessExpression.replaceCalleeReference(buildSimpleNamedReference {
source = calleeReference.source
name = calleeReference.name
})
val resolved = super.transformQualifiedAccessExpression(qualifiedAccessExpression, data) val originalResolvedQualifier = originalAccess.explicitReceiver
if (originalResolvedQualifier is FirResolvedQualifier) {
val fqName = originalResolvedQualifier.classId
?.let { if (originalResolvedQualifier.isFullyQualified) it.asSingleFqName() else it.relativeClassName }
?: originalResolvedQualifier.packageFqName
explicitReceiver = generatePropertyAccessExpression(fqName, originalResolvedQualifier.source)
}
calleeReference = buildSimpleNamedReference {
source = originalCalleeReference.source
name = originalCalleeReference.name
}
}
val resolved = super.transformQualifiedAccessExpression(accessCopyForResolution, data)
if (resolved is FirQualifiedAccessExpression) { if (resolved is FirQualifiedAccessExpression) {
// The initial resolution must have been to an enum entry. Report ambiguity if symbolFromArgumentsPhase is different to // The initial resolution must have been to an enum entry. Report ambiguity if symbolFromArgumentsPhase is different to
// original symbol including null (meaning we would resolve to something other than an enum entry). // original symbol including null (meaning we would resolve to something other than an enum entry).
val symbolFromArgumentsPhase = resolved.calleeReference.toResolvedBaseSymbol() val symbolFromArgumentsPhase = resolved.calleeReference.toResolvedBaseSymbol()
if (resolvedSymbol != symbolFromArgumentsPhase) { if (originalResolvedSymbol != symbolFromArgumentsPhase) {
resolved.replaceCalleeReference(buildErrorNamedReference { resolved.replaceCalleeReference(buildErrorNamedReference {
source = resolved.calleeReference.source source = resolved.calleeReference.source
diagnostic = ConeAmbiguouslyResolvedAnnotationArgument(resolvedSymbol, symbolFromArgumentsPhase) diagnostic = ConeAmbiguouslyResolvedAnnotationArgument(originalResolvedSymbol, symbolFromArgumentsPhase)
}) })
} }
} }
@@ -339,23 +348,22 @@ private class FirExpressionsResolveTransformerForSpecificAnnotations(transformer
return resolved return resolved
} }
private fun FirQualifiedAccessExpression.replaceResolvedQualifierReceiver(receiver: FirResolvedQualifier) { private fun generatePropertyAccessExpression(fqName: FqName, accessSource: KtSourceElement?): FirPropertyAccessExpression {
var lastReceiver = buildPropertyAccessExpression { var result: FirPropertyAccessExpression? = null
source = receiver.source
this.calleeReference = buildSimpleNamedReference {
val classId = receiver.classId ?: return
name = classId.relativeClassName.shortName()
}
}
replaceExplicitReceiver(lastReceiver)
if (receiver.isFullyQualified) { val pathSegments = fqName.pathSegments()
for (segment in receiver.packageFqName.pathSegments().asReversed()) { for ((index, pathSegment) in pathSegments.withIndex()) {
lastReceiver.replaceExplicitReceiver(buildPropertyAccessExpression { result = buildPropertyAccessExpression {
this.calleeReference = buildSimpleNamedReference { name = segment } calleeReference = buildSimpleNamedReference { name = pathSegment }
}.also { lastReceiver = it }) explicitReceiver = result
if (index == pathSegments.lastIndex) {
source = accessSource
}
} }
} }
return result ?: error("Got an empty ClassId")
} }
override fun resolveQualifiedAccessAndSelectCandidate( override fun resolveQualifiedAccessAndSelectCandidate(