Consider property accessor non-default if it has annotations

Otherwise we're not trying to load annotations on the parameter of the
property setter in MemberDeserializer.loadProperty.

Note that after this commit, we could now also assume that if
getter/setter is default, it has no annotations, and thus use
Annotations.EMPTY for default getter/setter in loadProperty. However,
this would cause reflection to work incorrectly on classes compiled by
an older Kotlin compiler, so we'll still try to load annotations on
default accessors for an indefinite time.

 #KT-25499 Fixed
This commit is contained in:
Alexander Udalov
2018-08-31 19:06:42 +02:00
parent 06ce0cb0f0
commit ab3f8db743
5 changed files with 36 additions and 21 deletions
@@ -50,18 +50,18 @@ class JvmFieldApplicabilityChecker : DeclarationChecker {
}
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is PropertyDescriptor) return
if (descriptor !is PropertyDescriptor || declaration !is KtProperty) return
val annotation = descriptor.findJvmFieldAnnotation()
?: descriptor.delegateField?.annotations?.findAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME)
?: return
val problem = when {
declaration is KtProperty && declaration.hasDelegate() -> DELEGATE
declaration.hasDelegate() -> DELEGATE
!descriptor.hasBackingField(context.trace.bindingContext) -> return
descriptor.isOverridable -> NOT_FINAL
Visibilities.isPrivate(descriptor.visibility) -> PRIVATE
descriptor.hasCustomAccessor() -> CUSTOM_ACCESSOR
declaration.hasCustomAccessor() -> CUSTOM_ACCESSOR
descriptor.overriddenDescriptors.isNotEmpty() -> OVERRIDES
descriptor.isLateInit -> LATEINIT
descriptor.isConst -> CONST
@@ -95,7 +95,16 @@ class JvmFieldApplicabilityChecker : DeclarationChecker {
return true
}
private fun PropertyDescriptor.hasCustomAccessor() = !(getter?.isDefault ?: true) || !(setter?.isDefault ?: true)
// This logic has been effectively used since 1.0. It'd be nice to call [PropertyAccessorDescriptor.isDefault] here instead,
// but that would be a breaking change because in the following case:
//
// @JvmField
// @get:Anno
// val foo = 42
//
// we'd start considering foo as having a custom getter and disallow the JvmField annotation on it
private fun KtProperty.hasCustomAccessor(): Boolean =
getter != null || setter != null
private fun PropertyDescriptor.hasBackingField(bindingContext: BindingContext) =
bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, this) ?: false