@@ -306,44 +306,42 @@ trait MethodSynthesis {
306
306
307
307
result
308
308
}
309
+
309
310
final def derive (initial : List [AnnotationInfo ]): Tree = {
310
311
validate()
311
312
312
- // Which meta-annotation is associated with this kind of entity.
313
- // Presently one of: field, getter, setter, beanGetter, beanSetter, param.
314
- // For traits, getter must play role of field as there isn't one until Constructors (we'll triage there)
315
- val categories = this match {
316
- case _ : BaseGetter => if (owner.isTrait) List (FieldTargetClass , GetterTargetClass ) else List (GetterTargetClass )
317
- case _ : Setter => List (SetterTargetClass )
318
- case _ : BeanSetter => List (BeanSetterTargetClass )
319
- case _ : AnyBeanGetter => List (BeanGetterTargetClass )
320
- case _ : Param => List (ParamTargetClass )
321
- case _ : Field => List (FieldTargetClass )
322
- }
323
-
324
- // whether annotations whose definitions are not meta-annotated should be kept.
325
- val defaultRetention = this match {
326
- case _ : Param => true
327
- // By default annotations go to the field, except if the field is
328
- // generated for a class parameter (PARAMACCESSOR).
329
- case _ : Field => ! mods.isParamAccessor
330
- case _ : BaseGetter if owner.isTrait => true // like, Field, but cannot be a param accessor in a trait
331
- case _ => false
313
+ // see scala.annotation.meta's package class for more info
314
+ // Annotations on ValDefs can be targeted towards the following: field, getter, setter, beanGetter, beanSetter, param.
315
+ // The defaults are:
316
+ // - (`val`-, `var`- or plain) constructor parameter annotations end up on the parameter, not on any other entity.
317
+ // - val/var member annotations solely end up on the underlying field, except in traits (@since 2.12),
318
+ // where there is no field, and the getter thus holds annotations targetting both getter & field.
319
+ // As soon as there is a field/getter (in subclasses mixing in the trait), we triage the annotations.
320
+ //
321
+ // TODO: these defaults can be surprising for annotations not meant for accessors/fields -- should we revisit?
322
+ // (In order to have `@foo val X` result in the X getter being annotated with `@foo`, foo needs to be meta-annotated with @getter)
323
+ val annotFilter : AnnotationInfo => Boolean = this match {
324
+ case _ : Param => annotationFilter(ParamTargetClass , defaultRetention = true )
325
+ // By default annotations go to the field, except if the field is generated for a class parameter (PARAMACCESSOR).
326
+ case _ : Field => annotationFilter(FieldTargetClass , defaultRetention = ! mods.isParamAccessor)
327
+ case _ : BaseGetter if owner.isTrait => annotationFilter(List (FieldTargetClass , GetterTargetClass ), defaultRetention = true )
328
+ case _ : BaseGetter => annotationFilter(GetterTargetClass , defaultRetention = false )
329
+ case _ : Setter => annotationFilter(SetterTargetClass , defaultRetention = false )
330
+ case _ : BeanSetter => annotationFilter(BeanSetterTargetClass , defaultRetention = false )
331
+ case _ : AnyBeanGetter => annotationFilter(BeanGetterTargetClass , defaultRetention = false )
332
332
}
333
333
334
- val derivedAnnotations = initial filter annotationFilter(categories, defaultRetention)
335
- // println(s"annots for $derivedSym: $derivedAnnotations (out of $initial)")
336
334
// The annotations amongst those found on the original symbol which
337
335
// should be propagated to this kind of accessor.
338
- derivedSym setAnnotations derivedAnnotations
336
+ derivedSym setAnnotations (initial filter annotFilter)
339
337
340
338
if (derivedSym.isSetter && owner.isTrait && ! isDeferred)
341
339
derivedSym addAnnotation TraitSetterAnnotationClass
342
340
343
341
logDerived(derivedTree)
344
342
}
345
-
346
343
}
344
+
347
345
sealed trait DerivedGetter extends DerivedFromValDef {
348
346
def needsSetter = mods.isMutable
349
347
}
0 commit comments