Annotations
Annotations become plain values: the annotation's class name and its arguments by name. Scala annotations work as well as Java ones, because the compiler reads them, not the runtime.
Classes and properties
Arguments by name
A StaticAnnotation is invisible to runtime reflection, but not to a macro. The descriptor keeps it with the value it was given.
- customer.getAnnotation("demo.Label")
- Some(Annotation(demo.Label,Map(text -> Customer record)))
- name.getAnnotation("demo.Label")
- Some(Annotation(demo.Label,Map(text -> Full name)))
- name.getAnnotation("demo.Label").map(_.parameters("text"))
- Some(Full name)
scala
final class Label(val text: String) extends StaticAnnotation
@Label("Customer record")
case class Customer(@(Label @field)("Full name") name: String, email: String)
val customer = ReflectMacros.reflect[Customer]
customer.getAnnotation("demo.Label")
customer.getProperty("name").flatMap(_.getAnnotation("demo.Label")).map(_.parameters("text"))
Targets
Annotate the field
A plain annotation on a class parameter stays on the constructor parameter. @(Label @field) moves it onto the field, where the property descriptor finds it.
- @Label name: String
- On the constructor parameter only.
- @(Label @field) name: String
- On the field: found by getProperty("name").
- @Label class Customer
- On the class: found by descriptor.getAnnotation.
Use
Labels, validation, mapping
Because annotations survive into Scala.js, the browser can read the same rules as the server: a form label, a maximum length, a column name.
scala
def label(descriptor: ClassDescriptor, property: String): String =
descriptor.getProperty(property)
.flatMap(_.getAnnotation("demo.Label"))
.flatMap(_.parameters.get("text"))
.map(_.toString)
.getOrElse(property)