[LL FIR] FirElementBuilder: accept KtAnnotated instead of KtDeclaration as annotation owner
^KT-65780
This commit is contained in:
committed by
Space Team
parent
7796ef43db
commit
cca58f5c2a
+24
-12
@@ -14,14 +14,15 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStruct
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FirElementsRecorder
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FirElementsRecorder
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.requireTypeIntersectionWith
|
||||||
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.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||||
import org.jetbrains.kotlin.fir.correspondingProperty
|
import org.jetbrains.kotlin.fir.correspondingProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirReceiverParameter
|
import org.jetbrains.kotlin.fir.declarations.FirReceiverParameter
|
||||||
@@ -111,11 +112,11 @@ internal class FirElementBuilder(
|
|||||||
private inline fun <T : KtElement> getFirForNonBodyElement(
|
private inline fun <T : KtElement> getFirForNonBodyElement(
|
||||||
element: KtElement,
|
element: KtElement,
|
||||||
anchorElementProvider: (KtElement) -> T?,
|
anchorElementProvider: (KtElement) -> T?,
|
||||||
declarationProvider: (T) -> KtDeclaration?,
|
annotatedElementProvider: (T) -> KtAnnotated?,
|
||||||
resolveAndFindFirForAnchor: (FirDeclaration, T) -> FirElement?,
|
resolveAndFindFirForAnchor: (FirAnnotationContainer, T) -> FirElement?,
|
||||||
): FirElement? {
|
): FirElement? {
|
||||||
val anchorElement = anchorElementProvider(element) ?: return null
|
val anchorElement = anchorElementProvider(element) ?: return null
|
||||||
val declaration = declarationProvider(anchorElement) ?: return null
|
val declaration = annotatedElementProvider(anchorElement) ?: return null
|
||||||
val nonLocalDeclaration = declaration.getNonLocalContainingOrThisDeclaration()
|
val nonLocalDeclaration = declaration.getNonLocalContainingOrThisDeclaration()
|
||||||
if (declaration != nonLocalDeclaration) return null
|
if (declaration != nonLocalDeclaration) return null
|
||||||
|
|
||||||
@@ -131,23 +132,27 @@ internal class FirElementBuilder(
|
|||||||
return findElementInside(firElement = anchorFir, element = element, stopAt = anchorElement)
|
return findElementInside(firElement = anchorFir, element = element, stopAt = anchorElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnnotationEntry.owner(): KtDeclaration? {
|
private fun KtAnnotationEntry.owner(): KtAnnotated? {
|
||||||
val parent = parent
|
val modifierList = when (val parent = parent) {
|
||||||
val modifierList = parent as? KtModifierList ?: (parent as? KtAnnotation)?.parent as? KtModifierList ?: return null
|
is KtModifierList -> parent
|
||||||
return modifierList.owner as? KtDeclaration
|
is KtAnnotation -> parent.parent as? KtModifierList
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifierList?.owner as? KtDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFirForElementInsideAnnotations(element: KtElement): FirElement? = getFirForNonBodyElement(
|
private fun getFirForElementInsideAnnotations(element: KtElement): FirElement? = getFirForNonBodyElement(
|
||||||
element = element,
|
element = element,
|
||||||
anchorElementProvider = { it.parentOfType<KtAnnotationEntry>(withSelf = true) },
|
anchorElementProvider = { it.parentOfType<KtAnnotationEntry>(withSelf = true) },
|
||||||
declarationProvider = { it.owner() },
|
annotatedElementProvider = { it.owner() },
|
||||||
resolveAndFindFirForAnchor = { declaration, anchor -> declaration.resolveAndFindAnnotation(anchor, goDeep = true) },
|
resolveAndFindFirForAnchor = { declaration, anchor -> declaration.resolveAndFindAnnotation(anchor, goDeep = true) },
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun getFirForElementInsideTypes(element: KtElement): FirElement? = getFirForNonBodyElement(
|
private fun getFirForElementInsideTypes(element: KtElement): FirElement? = getFirForNonBodyElement(
|
||||||
element = element,
|
element = element,
|
||||||
anchorElementProvider = { it.parentsOfType<KtTypeReference>(withSelf = true).lastOrNull() },
|
anchorElementProvider = { it.parentsOfType<KtTypeReference>(withSelf = true).lastOrNull() },
|
||||||
declarationProvider = {
|
annotatedElementProvider = {
|
||||||
when (val parent = it.parent) {
|
when (val parent = it.parent) {
|
||||||
is KtDeclaration -> parent
|
is KtDeclaration -> parent
|
||||||
is KtSuperTypeListEntry, is KtConstructorCalleeExpression, is KtTypeConstraint -> parent.parentOfType<KtDeclaration>()
|
is KtSuperTypeListEntry, is KtConstructorCalleeExpression, is KtTypeConstraint -> parent.parentOfType<KtDeclaration>()
|
||||||
@@ -179,7 +184,9 @@ internal class FirElementBuilder(
|
|||||||
return firElement
|
return firElement
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirDeclaration.resolveAndFindTypeRefAnchor(typeReference: KtTypeReference): FirElement? {
|
private fun FirAnnotationContainer.resolveAndFindTypeRefAnchor(typeReference: KtTypeReference): FirElement? {
|
||||||
|
requireTypeIntersectionWith<FirElementWithResolveState>()
|
||||||
|
|
||||||
lazyResolveToPhase(FirResolvePhase.ANNOTATION_ARGUMENTS)
|
lazyResolveToPhase(FirResolvePhase.ANNOTATION_ARGUMENTS)
|
||||||
|
|
||||||
if (this is FirCallableDeclaration) {
|
if (this is FirCallableDeclaration) {
|
||||||
@@ -218,7 +225,12 @@ internal class FirElementBuilder(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirDeclaration.resolveAndFindAnnotation(annotationEntry: KtAnnotationEntry, goDeep: Boolean = false): FirAnnotation? {
|
private fun FirAnnotationContainer.resolveAndFindAnnotation(
|
||||||
|
annotationEntry: KtAnnotationEntry,
|
||||||
|
goDeep: Boolean = false,
|
||||||
|
): FirAnnotation? {
|
||||||
|
requireTypeIntersectionWith<FirElementWithResolveState>()
|
||||||
|
|
||||||
lazyResolveToPhase(FirResolvePhase.ANNOTATION_ARGUMENTS)
|
lazyResolveToPhase(FirResolvePhase.ANNOTATION_ARGUMENTS)
|
||||||
findAnnotation(annotationEntry)?.let { return it }
|
findAnnotation(annotationEntry)?.let { return it }
|
||||||
|
|
||||||
|
|||||||
+18
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2024 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -14,6 +14,9 @@ import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry
|
|||||||
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
||||||
import org.jetbrains.kotlin.utils.exceptions.ExceptionAttachmentBuilder
|
import org.jetbrains.kotlin.utils.exceptions.ExceptionAttachmentBuilder
|
||||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||||
|
import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
|
||||||
fun errorWithFirSpecificEntries(
|
fun errorWithFirSpecificEntries(
|
||||||
@@ -39,3 +42,17 @@ fun errorWithFirSpecificEntries(
|
|||||||
additionalInfos()
|
additionalInfos()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
inline fun <reified R> Any.requireTypeIntersectionWith() {
|
||||||
|
contract { returns() implies (this@requireTypeIntersectionWith is R) }
|
||||||
|
|
||||||
|
requireWithAttachment(
|
||||||
|
this is R,
|
||||||
|
{ "${this::class.simpleName} must be ${R::class.simpleName}" },
|
||||||
|
) {
|
||||||
|
if (this@requireTypeIntersectionWith is FirElement) {
|
||||||
|
withFirEntry("container", this@requireTypeIntersectionWith)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user