Merge use-site targeted annotations into corresponding Annotations

Add PropertyDescriptor.backingField/delegateField to store annotations
on the field directly in an otherwise almost empty descriptor instance,
instead of storing them with use-sites in the corresponding property
descriptor. Instead of AnnotationWithTarget, create AnnotationDescriptor
instances in AnnotationSplitter. Change DescriptorRenderer to render
annotations on "related" declarations when needed, with the explicit
use-site target if applicable.

Most changes in diagnostic test data are related to the fact that
annotations which are known to have an incompatible use-site to the
declaration they're applied at (such as `@param:`-annotation on a
function), are now not loaded at all. It's fine because the code is
erroneous, so it doesn't really matter how do we load annotations with
invalid targets (some of this logic is also changed freely in subsequent
commits). Some changes are also explained by the fact that for example
an annotation on the property which is only applicable to FIELD is now
rendered with an explicit use-site target `@field:`, regardless of
whether it did have that use-site target syntactically or not.

Basically, after this change there's no point in calling
Annotations.getUseSiteTargetedAnnotations/getAllAnnotations anymore
because it's easier and more intuitive to just use Annotations of the
corresponding descriptor -- the backing / delegate field (introduced in
this commit) or the extension receiver / setter parameter (related
behavior was fixed in previous commits). Usages of
use-site-target-related methods will be refactored out in subsequent
commits
This commit is contained in:
Alexander Udalov
2018-08-14 16:45:11 +02:00
parent 8c21e86ded
commit fc87043cb3
68 changed files with 436 additions and 386 deletions
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.resolve.jvm.annotations
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.name.FqName
@@ -29,7 +31,7 @@ fun DeclarationDescriptor.findJvmOverloadsAnnotation(): AnnotationDescriptor? =
annotations.findAnnotation(JVM_OVERLOADS_FQ_NAME)
fun DeclarationDescriptor.findJvmFieldAnnotation(): AnnotationDescriptor? =
DescriptorUtils.getAnnotationByFqName(annotations, JVM_FIELD_ANNOTATION_FQ_NAME)
(this as? PropertyDescriptor)?.backingField?.annotations?.findAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME)
fun DeclarationDescriptor.hasJvmFieldAnnotation(): Boolean =
findJvmFieldAnnotation() != null
@@ -40,8 +42,9 @@ fun DeclarationDescriptor.isCallableMemberWithJvmDefaultAnnotation(): Boolean =
fun CallableMemberDescriptor.hasJvmDefaultAnnotation(): Boolean =
DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME)
fun DeclarationDescriptor.findJvmSyntheticAnnotation(): AnnotationDescriptor? =
private fun Annotated.findJvmSyntheticAnnotation(): AnnotationDescriptor? =
DescriptorUtils.getAnnotationByFqName(annotations, JVM_SYNTHETIC_ANNOTATION_FQ_NAME)
?: (this as? PropertyDescriptor)?.backingField?.annotations?.findAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME)
fun DeclarationDescriptor.hasJvmSyntheticAnnotation(): Boolean =
findJvmSyntheticAnnotation() != null
@@ -49,8 +52,5 @@ fun DeclarationDescriptor.hasJvmSyntheticAnnotation(): Boolean =
fun DeclarationDescriptor.findStrictfpAnnotation(): AnnotationDescriptor? =
DescriptorUtils.getAnnotationByFqName(annotations, STRICTFP_ANNOTATION_FQ_NAME)
fun DeclarationDescriptor.findVolatileAnnotation(): AnnotationDescriptor? =
DescriptorUtils.getAnnotationByFqName(annotations, VOLATILE_ANNOTATION_FQ_NAME)
fun DeclarationDescriptor.findSynchronizedAnnotation(): AnnotationDescriptor? =
DescriptorUtils.getAnnotationByFqName(annotations, SYNCHRONIZED_ANNOTATION_FQ_NAME)
@@ -50,10 +50,13 @@ class JvmFieldApplicabilityChecker : DeclarationChecker {
}
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val annotation = descriptor.findJvmFieldAnnotation() ?: return
if (descriptor !is PropertyDescriptor) return
val annotation = descriptor.findJvmFieldAnnotation()
?: descriptor.delegateField?.annotations?.findAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME)
?: return
val problem = when {
descriptor !is PropertyDescriptor -> return
declaration is KtProperty && declaration.hasDelegate() -> DELEGATE
!descriptor.hasBackingField(context.trace.bindingContext) -> return
descriptor.isOverridable -> NOT_FINAL
@@ -17,19 +17,18 @@
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmSyntheticAnnotation
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class JvmSyntheticApplicabilityChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val annotation = descriptor.findJvmSyntheticAnnotation() ?: return
if (declaration is KtProperty && descriptor is VariableDescriptor && declaration.hasDelegate()) {
val annotation = (descriptor as? PropertyDescriptor)?.delegateField?.annotations?.findAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME)
if (annotation != null) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
context.trace.report(ErrorsJvm.JVM_SYNTHETIC_ON_DELEGATE.on(annotationEntry))
}
@@ -34,9 +34,9 @@ import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithCorres
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.annotations.VOLATILE_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.jvm.annotations.findSynchronizedAnnotation
import org.jetbrains.kotlin.resolve.jvm.annotations.findVolatileAnnotation
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
@@ -156,16 +156,18 @@ class JvmNameAnnotationChecker : DeclarationChecker {
class VolatileAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val volatileAnnotation = descriptor.findVolatileAnnotation()
if (volatileAnnotation != null) {
if (descriptor is PropertyDescriptor && !descriptor.isVar) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return
context.trace.report(ErrorsJvm.VOLATILE_ON_VALUE.on(annotationEntry))
}
if (declaration is KtProperty && declaration.hasDelegate()) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return
context.trace.report(ErrorsJvm.VOLATILE_ON_DELEGATE.on(annotationEntry))
}
if (descriptor !is PropertyDescriptor) return
val fieldAnnotation = descriptor.backingField?.annotations?.findAnnotation(VOLATILE_ANNOTATION_FQ_NAME)
if (fieldAnnotation != null && !descriptor.isVar) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(fieldAnnotation) ?: return
context.trace.report(ErrorsJvm.VOLATILE_ON_VALUE.on(annotationEntry))
}
val delegateAnnotation = descriptor.delegateField?.annotations?.findAnnotation(VOLATILE_ANNOTATION_FQ_NAME)
if (delegateAnnotation != null) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(delegateAnnotation) ?: return
context.trace.report(ErrorsJvm.VOLATILE_ON_DELEGATE.on(annotationEntry))
}
}
}