[AA FIR] fix contract violation for java Target annotation
^KT-57849 Fixed
This commit is contained in:
committed by
Space Team
parent
f540826207
commit
5d1c853adf
+43
-9
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.fir.annotations
|
||||
|
||||
import java.lang.annotation.ElementType
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.AnnotationUseSiteTargetFilter
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationInfo
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationWithArgumentsInfo
|
||||
@@ -68,6 +69,11 @@ internal fun annotationsByClassId(
|
||||
.mapIndexedToAnnotationApplication(useSiteTargetFilter, useSiteSession, classId) { index, annotation ->
|
||||
annotation.asKtAnnotationApplicationForTargetAnnotation(useSiteSession, index)
|
||||
}
|
||||
} else if (classId == StandardClassIds.Annotations.Java.Target && firSymbol.fir.resolvePhase < FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING) {
|
||||
annotationContainer.resolvedAnnotationsWithClassIds(firSymbol)
|
||||
.mapIndexedToAnnotationApplication(useSiteTargetFilter, useSiteSession, classId) { index, annotation ->
|
||||
annotation.asKtAnnotationApplicationForJavaTargetAnnotation(useSiteSession, index)
|
||||
}
|
||||
} else {
|
||||
annotationContainer.resolvedAnnotationsWithArguments(firSymbol)
|
||||
.mapIndexedToAnnotationApplication(useSiteTargetFilter, useSiteSession, classId) { index, annotation ->
|
||||
@@ -88,20 +94,26 @@ private inline fun List<FirAnnotation>.mapIndexedToAnnotationApplication(
|
||||
transformer(index, annotation)
|
||||
}
|
||||
|
||||
private fun FirAnnotation.asKtAnnotationApplicationForTargetAnnotation(
|
||||
private fun FirAnnotation.asKtAnnotationApplicationForAnnotationWithEnumArgument(
|
||||
useSiteSession: FirSession,
|
||||
index: Int,
|
||||
expectedEnumClassId: ClassId,
|
||||
annotationParameterName: Name,
|
||||
nameMapper: (String) -> String?,
|
||||
): KtAnnotationApplicationWithArgumentsInfo {
|
||||
val arguments = findAllowedTargets().ifNotEmpty {
|
||||
val arguments = findFromRawArguments(
|
||||
expectedEnumClass = expectedEnumClassId,
|
||||
nameMapper,
|
||||
).ifNotEmpty {
|
||||
listOf(
|
||||
KtNamedAnnotationValue(
|
||||
name = StandardClassIds.Annotations.ParameterNames.targetAllowedTargets,
|
||||
name = annotationParameterName,
|
||||
expression = KtArrayAnnotationValue(
|
||||
values = map {
|
||||
KtEnumEntryAnnotationValue(
|
||||
callableId = CallableId(
|
||||
classId = StandardClassIds.AnnotationTarget,
|
||||
callableName = Name.identifier(it.name),
|
||||
classId = expectedEnumClassId,
|
||||
callableName = Name.identifier(it),
|
||||
),
|
||||
sourcePsi = null,
|
||||
)
|
||||
@@ -115,16 +127,38 @@ private fun FirAnnotation.asKtAnnotationApplicationForTargetAnnotation(
|
||||
return toKtAnnotationApplication(useSiteSession, index, arguments)
|
||||
}
|
||||
|
||||
private fun FirAnnotation.findAllowedTargets(): Set<KotlinTarget> = buildSet {
|
||||
private fun FirAnnotation.asKtAnnotationApplicationForTargetAnnotation(
|
||||
useSiteSession: FirSession,
|
||||
index: Int,
|
||||
): KtAnnotationApplicationWithArgumentsInfo = asKtAnnotationApplicationForAnnotationWithEnumArgument(
|
||||
useSiteSession = useSiteSession,
|
||||
index = index,
|
||||
expectedEnumClassId = StandardClassIds.AnnotationTarget,
|
||||
annotationParameterName = StandardClassIds.Annotations.ParameterNames.targetAllowedTargets,
|
||||
nameMapper = { KotlinTarget.valueOrNull(it)?.name },
|
||||
)
|
||||
|
||||
private fun FirAnnotation.asKtAnnotationApplicationForJavaTargetAnnotation(
|
||||
useSiteSession: FirSession,
|
||||
index: Int,
|
||||
): KtAnnotationApplicationWithArgumentsInfo = asKtAnnotationApplicationForAnnotationWithEnumArgument(
|
||||
useSiteSession = useSiteSession,
|
||||
index = index,
|
||||
expectedEnumClassId = StandardClassIds.Annotations.Java.ElementType,
|
||||
annotationParameterName = StandardClassIds.Annotations.ParameterNames.value,
|
||||
nameMapper = { ElementType.values().firstOrNull { enumValue -> enumValue.name == it }?.name },
|
||||
)
|
||||
|
||||
private fun <T> FirAnnotation.findFromRawArguments(expectedEnumClass: ClassId, transformer: (String) -> T?): Set<T> = buildSet {
|
||||
fun addIfMatching(arg: FirExpression) {
|
||||
if (arg !is FirQualifiedAccessExpression) return
|
||||
val callableSymbol = arg.calleeReference.toResolvedCallableSymbol() ?: return
|
||||
if (callableSymbol.containingClassLookupTag()?.classId != StandardClassIds.AnnotationTarget) return
|
||||
if (callableSymbol.containingClassLookupTag()?.classId != expectedEnumClass) return
|
||||
val identifier = callableSymbol.callableId.callableName.identifier
|
||||
KotlinTarget.values().firstOrNull { identifier == it.name }?.let(::add)
|
||||
transformer(identifier)?.let(::add)
|
||||
}
|
||||
|
||||
if (this@findAllowedTargets is FirAnnotationCall) {
|
||||
if (this@findFromRawArguments is FirAnnotationCall) {
|
||||
for (arg in argumentList.arguments) {
|
||||
arg.unwrapAndFlattenArgument().forEach(::addIfMatching)
|
||||
}
|
||||
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
// SKIP_WHEN_OUT_OF_CONTENT_ROOT
|
||||
// DISABLE_SEALED_INHERITOR_CALCULATOR
|
||||
// FILE: main.kt
|
||||
fun resolveMe(i: JavaInterface) = i.id
|
||||
|
||||
// FILE: JavaClass.java
|
||||
public interface JavaInterface {
|
||||
@KotlinAnnotation
|
||||
default int getId() {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: KotlinAnnotation.kt
|
||||
import java.lang.annotation.ElementType
|
||||
|
||||
@java.lang.annotation.Target(ElementType.TYPE_USE)
|
||||
annotation class KotlinAnnotation
|
||||
analysis/low-level-api-fir/testdata/lazyResolve/annotationFromImplicitJavaTypeWithJavaAnnotation.txt
Vendored
+79
@@ -0,0 +1,79 @@
|
||||
RAW_FIR:
|
||||
FILE: [ResolvedTo(RAW_FIR)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public? final? [ResolvedTo(RAW_FIR)] fun resolveMe([ResolvedTo(RAW_FIR)] i: JavaInterface): <implicit> { LAZY_BLOCK }
|
||||
|
||||
IMPORTS:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public? final? [ResolvedTo(RAW_FIR)] fun resolveMe([ResolvedTo(RAW_FIR)] i: JavaInterface): <implicit> { LAZY_BLOCK }
|
||||
|
||||
COMPILER_REQUIRED_ANNOTATIONS:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public? final? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] fun resolveMe([ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] i: JavaInterface): <implicit> { LAZY_BLOCK }
|
||||
|
||||
COMPANION_GENERATION:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public? final? [ResolvedTo(COMPANION_GENERATION)] fun resolveMe([ResolvedTo(COMPANION_GENERATION)] i: JavaInterface): <implicit> { LAZY_BLOCK }
|
||||
|
||||
SUPER_TYPES:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public? final? [ResolvedTo(SUPER_TYPES)] fun resolveMe([ResolvedTo(SUPER_TYPES)] i: JavaInterface): <implicit> { LAZY_BLOCK }
|
||||
|
||||
TYPES:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public? final? [ResolvedTo(TYPES)] fun resolveMe([ResolvedTo(TYPES)] i: R|JavaInterface|): <implicit> { LAZY_BLOCK }
|
||||
|
||||
STATUS:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public final [ResolvedTo(STATUS)] fun resolveMe([ResolvedTo(STATUS)] i: R|JavaInterface|): <implicit> { LAZY_BLOCK }
|
||||
|
||||
EXPECT_ACTUAL_MATCHING:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public final [ResolvedTo(EXPECT_ACTUAL_MATCHING)] fun resolveMe([ResolvedTo(EXPECT_ACTUAL_MATCHING)] i: R|JavaInterface|): <implicit> { LAZY_BLOCK }
|
||||
|
||||
ARGUMENTS_OF_ANNOTATIONS:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun resolveMe([ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] i: R|JavaInterface|): <implicit> { LAZY_BLOCK }
|
||||
|
||||
CONTRACTS:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public final [ResolvedTo(CONTRACTS)] fun resolveMe([ResolvedTo(CONTRACTS)] i: R|JavaInterface|): <implicit> {
|
||||
^resolveMe i#.id#
|
||||
}
|
||||
|
||||
IMPLICIT_TYPES_BODY_RESOLVE:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public final [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] fun resolveMe([ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] i: R|JavaInterface|): R|kotlin/Int| {
|
||||
^resolveMe R|<local>/i|.R|/JavaInterface.id|
|
||||
}
|
||||
|
||||
ANNOTATIONS_ARGUMENTS_MAPPING:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun resolveMe([ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] i: R|JavaInterface|): R|kotlin/Int| {
|
||||
^resolveMe R|<local>/i|.R|/JavaInterface.id|
|
||||
}
|
||||
|
||||
BODY_RESOLVE:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(RAW_FIR)] annotations container
|
||||
public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe([ResolvedTo(BODY_RESOLVE)] i: R|JavaInterface|): R|kotlin/Int| {
|
||||
^resolveMe R|<local>/i|.R|/JavaInterface.id|
|
||||
}
|
||||
|
||||
FILE RAW TO BODY:
|
||||
FILE: [ResolvedTo(IMPORTS)] main.kt
|
||||
[ResolvedTo(BODY_RESOLVE)] annotations container
|
||||
public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe([ResolvedTo(BODY_RESOLVE)] i: R|JavaInterface|): R|kotlin/Int| {
|
||||
^resolveMe R|<local>/i|.R|/JavaInterface.id|
|
||||
}
|
||||
+6
@@ -36,6 +36,12 @@ public class FirOutOfContentRootLazyDeclarationResolveTestGenerated extends Abst
|
||||
runTest("analysis/low-level-api-fir/testdata/lazyResolve/annotationFromImplicitJavaType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationFromImplicitJavaTypeWithJavaAnnotation.kt")
|
||||
public void testAnnotationFromImplicitJavaTypeWithJavaAnnotation() throws Exception {
|
||||
runTest("analysis/low-level-api-fir/testdata/lazyResolve/annotationFromImplicitJavaTypeWithJavaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationParameters.kt")
|
||||
public void testAnnotationParameters() throws Exception {
|
||||
|
||||
+6
@@ -36,6 +36,12 @@ public class FirSourceLazyDeclarationResolveTestGenerated extends AbstractFirSou
|
||||
runTest("analysis/low-level-api-fir/testdata/lazyResolve/annotationFromImplicitJavaType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationFromImplicitJavaTypeWithJavaAnnotation.kt")
|
||||
public void testAnnotationFromImplicitJavaTypeWithJavaAnnotation() throws Exception {
|
||||
runTest("analysis/low-level-api-fir/testdata/lazyResolve/annotationFromImplicitJavaTypeWithJavaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationParameters.kt")
|
||||
public void testAnnotationParameters() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user