|
|
|
@@ -51,7 +51,7 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun checkExpression(expression: JetExpression, trace: BindingTrace) {
|
|
|
|
|
checkEntries(expression.getAnnotationEntries(), listOf(KotlinTarget.EXPRESSION), trace)
|
|
|
|
|
checkEntries(expression.getAnnotationEntries(), targetList(KotlinTarget.EXPRESSION), trace)
|
|
|
|
|
if (expression is JetFunctionLiteralExpression) {
|
|
|
|
|
for (parameter in expression.valueParameters) {
|
|
|
|
|
parameter.typeReference?.let { check(it, trace) }
|
|
|
|
@@ -59,7 +59,7 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun checkEntries(entries: List<JetAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
|
|
|
|
|
private fun checkEntries(entries: List<JetAnnotationEntry>, actualTargets: TargetList, trace: BindingTrace) {
|
|
|
|
|
val entryTypes: MutableSet<JetType> = hashSetOf()
|
|
|
|
|
for (entry in entries) {
|
|
|
|
|
checkAnnotationEntry(entry, actualTargets, trace)
|
|
|
|
@@ -69,26 +69,39 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
|
|
|
|
|
trace.report(Errors.REPEATED_ANNOTATION.on(entry));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
additionalCheckers.forEach { it.checkEntries(entries, actualTargets, trace) }
|
|
|
|
|
additionalCheckers.forEach { it.checkEntries(entries, actualTargets.declarationSite, trace) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
|
|
|
|
|
val possibleTargets = possibleTargetSet(entry, trace)
|
|
|
|
|
if (actualTargets.any { it in possibleTargets }) return
|
|
|
|
|
trace.report(Errors.WRONG_ANNOTATION_TARGET.on(entry, actualTargets.firstOrNull()?.description ?: "unidentified target"))
|
|
|
|
|
private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: TargetList, trace: BindingTrace) {
|
|
|
|
|
val applicableTargets = applicableTargetSet(entry, trace)
|
|
|
|
|
val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget()
|
|
|
|
|
|
|
|
|
|
if (actualTargets.declarationSite.any {
|
|
|
|
|
it in applicableTargets && (useSiteTarget == null || KotlinTarget.USE_SITE_MAPPING[useSiteTarget] == it)
|
|
|
|
|
}) return
|
|
|
|
|
|
|
|
|
|
if (useSiteTarget != null && actualTargets.useSite.any {
|
|
|
|
|
it in applicableTargets && KotlinTarget.USE_SITE_MAPPING[useSiteTarget] == it
|
|
|
|
|
}) return
|
|
|
|
|
|
|
|
|
|
trace.report(Errors.WRONG_ANNOTATION_TARGET.on(entry, actualTargets.declarationSite.firstOrNull()?.description ?: "unidentified target"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
|
|
|
|
|
private fun possibleTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set<KotlinTarget> {
|
|
|
|
|
private val PROPERTY_USE_SITE_TARGETS = listOf(
|
|
|
|
|
KotlinTarget.FIELD, KotlinTarget.PROPERTY_GETTER, KotlinTarget.PROPERTY_SETTER, KotlinTarget.VALUE_PARAMETER)
|
|
|
|
|
private val VALUE_PARAMETER_USE_SITE_TARGETS = PROPERTY_USE_SITE_TARGETS + KotlinTarget.PROPERTY
|
|
|
|
|
|
|
|
|
|
private fun applicableTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set<KotlinTarget> {
|
|
|
|
|
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET
|
|
|
|
|
// For descriptor with error type, all targets are considered as possible
|
|
|
|
|
if (descriptor.type.isError) return KotlinTarget.ALL_TARGET_SET
|
|
|
|
|
val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: return KotlinTarget.DEFAULT_TARGET_SET
|
|
|
|
|
return possibleTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
|
|
|
|
|
return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun possibleTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? {
|
|
|
|
|
public fun applicableTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? {
|
|
|
|
|
val targetEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.target)
|
|
|
|
|
?: return null
|
|
|
|
|
val valueArguments = targetEntryDescriptor.allValueArguments
|
|
|
|
@@ -98,41 +111,71 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
|
|
|
|
|
}.filterNotNull().toSet()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): List<KotlinTarget> {
|
|
|
|
|
public fun getDeclarationSiteActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): List<KotlinTarget> {
|
|
|
|
|
return getActualTargetList(annotated, descriptor).declarationSite
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): TargetList {
|
|
|
|
|
return when (annotated) {
|
|
|
|
|
is JetClassOrObject -> descriptor?.let { KotlinTarget.classActualTargets(it) } ?: listOf(CLASSIFIER)
|
|
|
|
|
is JetClassOrObject -> descriptor?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: targetList(CLASSIFIER)
|
|
|
|
|
is JetProperty ->
|
|
|
|
|
if (annotated.isLocal) {
|
|
|
|
|
listOf(LOCAL_VARIABLE)
|
|
|
|
|
extendedTargetList(PROPERTY_USE_SITE_TARGETS, LOCAL_VARIABLE)
|
|
|
|
|
}
|
|
|
|
|
else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) {
|
|
|
|
|
listOf(MEMBER_PROPERTY, PROPERTY, FIELD)
|
|
|
|
|
extendedTargetList(PROPERTY_USE_SITE_TARGETS, MEMBER_PROPERTY, PROPERTY, FIELD)
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
listOf(TOP_LEVEL_PROPERTY, PROPERTY, FIELD)
|
|
|
|
|
extendedTargetList(PROPERTY_USE_SITE_TARGETS, TOP_LEVEL_PROPERTY, PROPERTY, FIELD)
|
|
|
|
|
}
|
|
|
|
|
is JetParameter -> if (annotated.hasValOrVar()) listOf(PROPERTY_PARAMETER, MEMBER_PROPERTY, PROPERTY, FIELD) else listOf(VALUE_PARAMETER)
|
|
|
|
|
is JetConstructor<*> -> listOf(CONSTRUCTOR)
|
|
|
|
|
is JetFunction ->
|
|
|
|
|
is JetParameter -> {
|
|
|
|
|
if (annotated.hasValOrVar()) {
|
|
|
|
|
extendedTargetList(VALUE_PARAMETER_USE_SITE_TARGETS, PROPERTY_PARAMETER, MEMBER_PROPERTY, PROPERTY, FIELD)
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
extendedTargetList(VALUE_PARAMETER_USE_SITE_TARGETS, VALUE_PARAMETER)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
is JetConstructor<*> -> targetList(CONSTRUCTOR)
|
|
|
|
|
is JetFunction -> {
|
|
|
|
|
val extendedTargets = listOf(KotlinTarget.VALUE_PARAMETER)
|
|
|
|
|
if (annotated.isLocal) {
|
|
|
|
|
listOf(LOCAL_FUNCTION, FUNCTION)
|
|
|
|
|
extendedTargetList(extendedTargets, LOCAL_FUNCTION, FUNCTION)
|
|
|
|
|
}
|
|
|
|
|
else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) {
|
|
|
|
|
listOf(MEMBER_FUNCTION, FUNCTION)
|
|
|
|
|
extendedTargetList(extendedTargets, MEMBER_FUNCTION, FUNCTION)
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
listOf(TOP_LEVEL_FUNCTION, FUNCTION)
|
|
|
|
|
extendedTargetList(extendedTargets, TOP_LEVEL_FUNCTION, FUNCTION)
|
|
|
|
|
}
|
|
|
|
|
is JetPropertyAccessor -> if (annotated.isGetter) listOf(PROPERTY_GETTER) else listOf(PROPERTY_SETTER)
|
|
|
|
|
is JetPackageDirective -> listOf(PACKAGE)
|
|
|
|
|
is JetTypeReference -> listOf(TYPE)
|
|
|
|
|
is JetFile -> listOf(FILE)
|
|
|
|
|
is JetTypeParameter -> listOf(TYPE_PARAMETER)
|
|
|
|
|
is JetTypeProjection -> if (annotated.projectionKind == JetProjectionKind.STAR) listOf(STAR_PROJECTION) else listOf(TYPE_PROJECTION)
|
|
|
|
|
is JetClassInitializer -> listOf(INITIALIZER)
|
|
|
|
|
else -> listOf()
|
|
|
|
|
}
|
|
|
|
|
is JetPropertyAccessor -> if (annotated.isGetter) targetList(PROPERTY_GETTER) else targetList(PROPERTY_SETTER)
|
|
|
|
|
is JetPackageDirective -> targetList(PACKAGE)
|
|
|
|
|
is JetTypeReference -> targetList(TYPE)
|
|
|
|
|
is JetFile -> targetList(FILE)
|
|
|
|
|
is JetTypeParameter -> targetList(TYPE_PARAMETER)
|
|
|
|
|
is JetTypeProjection -> {
|
|
|
|
|
if (annotated.projectionKind == JetProjectionKind.STAR) {
|
|
|
|
|
targetList(STAR_PROJECTION)
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
targetList(TYPE_PROJECTION)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
is JetClassInitializer -> targetList(INITIALIZER)
|
|
|
|
|
else -> targetList()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class TargetList(val declarationSite: List<KotlinTarget>, val useSite: List<KotlinTarget> = emptyList())
|
|
|
|
|
|
|
|
|
|
private fun targetList(vararg target: KotlinTarget): TargetList {
|
|
|
|
|
return TargetList(listOf(*target), emptyList())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun extendedTargetList(extended: List<KotlinTarget>, vararg target: KotlinTarget): TargetList {
|
|
|
|
|
return TargetList(listOf(*target), extended)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|