xref: /aosp_15_r20/external/kotlinpoet/docs/annotations.md (revision 3c321d951dd070fb96f8ba59e952ffc3131379a0)
1*3c321d95SSadaf EbrahimiAnnotations
2*3c321d95SSadaf Ebrahimi===========
3*3c321d95SSadaf Ebrahimi
4*3c321d95SSadaf EbrahimiSimple annotations are easy:
5*3c321d95SSadaf Ebrahimi
6*3c321d95SSadaf Ebrahimi```kotlin
7*3c321d95SSadaf Ebrahimival test = FunSpec.builder("test string equality")
8*3c321d95SSadaf Ebrahimi  .addAnnotation(Test::class)
9*3c321d95SSadaf Ebrahimi  .addStatement("assertThat(%1S).isEqualTo(%1S)", "foo")
10*3c321d95SSadaf Ebrahimi  .build()
11*3c321d95SSadaf Ebrahimi```
12*3c321d95SSadaf Ebrahimi
13*3c321d95SSadaf EbrahimiWhich generates this function with an `@Test` annotation:
14*3c321d95SSadaf Ebrahimi
15*3c321d95SSadaf Ebrahimi```kotlin
16*3c321d95SSadaf Ebrahimi@Test
17*3c321d95SSadaf Ebrahimifun `test string equality`() {
18*3c321d95SSadaf Ebrahimi  assertThat("foo").isEqualTo("foo")
19*3c321d95SSadaf Ebrahimi}
20*3c321d95SSadaf Ebrahimi```
21*3c321d95SSadaf Ebrahimi
22*3c321d95SSadaf EbrahimiUse `AnnotationSpec.builder()` to set properties on annotations:
23*3c321d95SSadaf Ebrahimi
24*3c321d95SSadaf Ebrahimi```kotlin
25*3c321d95SSadaf Ebrahimival logRecord = FunSpec.builder("recordEvent")
26*3c321d95SSadaf Ebrahimi  .addModifiers(KModifier.ABSTRACT)
27*3c321d95SSadaf Ebrahimi  .addAnnotation(
28*3c321d95SSadaf Ebrahimi    AnnotationSpec.builder(Headers::class)
29*3c321d95SSadaf Ebrahimi      .addMember("accept = %S", "application/json; charset=utf-8")
30*3c321d95SSadaf Ebrahimi      .addMember("userAgent = %S", "Square Cash")
31*3c321d95SSadaf Ebrahimi      .build()
32*3c321d95SSadaf Ebrahimi  )
33*3c321d95SSadaf Ebrahimi  .addParameter("logRecord", LogRecord::class)
34*3c321d95SSadaf Ebrahimi  .returns(LogReceipt::class)
35*3c321d95SSadaf Ebrahimi  .build()
36*3c321d95SSadaf Ebrahimi```
37*3c321d95SSadaf Ebrahimi
38*3c321d95SSadaf EbrahimiWhich generates this annotation with `accept` and `userAgent` properties:
39*3c321d95SSadaf Ebrahimi
40*3c321d95SSadaf Ebrahimi```kotlin
41*3c321d95SSadaf Ebrahimi@Headers(
42*3c321d95SSadaf Ebrahimi  accept = "application/json; charset=utf-8",
43*3c321d95SSadaf Ebrahimi  userAgent = "Square Cash"
44*3c321d95SSadaf Ebrahimi)
45*3c321d95SSadaf Ebrahimiabstract fun recordEvent(logRecord: LogRecord): LogReceipt
46*3c321d95SSadaf Ebrahimi```
47*3c321d95SSadaf Ebrahimi
48*3c321d95SSadaf EbrahimiWhen you get fancy, annotation values can be annotations themselves. Use `%L` for embedded
49*3c321d95SSadaf Ebrahimiannotations:
50*3c321d95SSadaf Ebrahimi
51*3c321d95SSadaf Ebrahimi```kotlin
52*3c321d95SSadaf Ebrahimival headerList = ClassName("", "HeaderList")
53*3c321d95SSadaf Ebrahimival header = ClassName("", "Header")
54*3c321d95SSadaf Ebrahimival logRecord = FunSpec.builder("recordEvent")
55*3c321d95SSadaf Ebrahimi  .addModifiers(KModifier.ABSTRACT)
56*3c321d95SSadaf Ebrahimi  .addAnnotation(
57*3c321d95SSadaf Ebrahimi    AnnotationSpec.builder(headerList)
58*3c321d95SSadaf Ebrahimi      .addMember(
59*3c321d95SSadaf Ebrahimi        "[\n⇥%L,\n%L⇤\n]",
60*3c321d95SSadaf Ebrahimi        AnnotationSpec.builder(header)
61*3c321d95SSadaf Ebrahimi          .addMember("name = %S", "Accept")
62*3c321d95SSadaf Ebrahimi          .addMember("value = %S", "application/json; charset=utf-8")
63*3c321d95SSadaf Ebrahimi          .build(),
64*3c321d95SSadaf Ebrahimi        AnnotationSpec.builder(header)
65*3c321d95SSadaf Ebrahimi          .addMember("name = %S", "User-Agent")
66*3c321d95SSadaf Ebrahimi          .addMember("value = %S", "Square Cash")
67*3c321d95SSadaf Ebrahimi          .build()
68*3c321d95SSadaf Ebrahimi      )
69*3c321d95SSadaf Ebrahimi      .build()
70*3c321d95SSadaf Ebrahimi  )
71*3c321d95SSadaf Ebrahimi  .addParameter("logRecord", logRecordName)
72*3c321d95SSadaf Ebrahimi  .returns(logReceipt)
73*3c321d95SSadaf Ebrahimi  .build()
74*3c321d95SSadaf Ebrahimi```
75*3c321d95SSadaf Ebrahimi
76*3c321d95SSadaf EbrahimiWhich generates this:
77*3c321d95SSadaf Ebrahimi
78*3c321d95SSadaf Ebrahimi```kotlin
79*3c321d95SSadaf Ebrahimi@HeaderList(
80*3c321d95SSadaf Ebrahimi  [
81*3c321d95SSadaf Ebrahimi    Header(name = "Accept", value = "application/json; charset=utf-8"),
82*3c321d95SSadaf Ebrahimi    Header(name = "User-Agent", value = "Square Cash")
83*3c321d95SSadaf Ebrahimi  ]
84*3c321d95SSadaf Ebrahimi)
85*3c321d95SSadaf Ebrahimiabstract fun recordEvent(logRecord: LogRecord): LogReceipt
86*3c321d95SSadaf Ebrahimi```
87*3c321d95SSadaf Ebrahimi
88*3c321d95SSadaf EbrahimiKotlinPoet supports use-site targets for annotations:
89*3c321d95SSadaf Ebrahimi
90*3c321d95SSadaf Ebrahimi```kotlin
91*3c321d95SSadaf Ebrahimival utils = FileSpec.builder("com.example", "Utils")
92*3c321d95SSadaf Ebrahimi  .addAnnotation(
93*3c321d95SSadaf Ebrahimi    AnnotationSpec.builder(JvmName::class)
94*3c321d95SSadaf Ebrahimi      .useSiteTarget(UseSiteTarget.FILE)
95*3c321d95SSadaf Ebrahimi      .build()
96*3c321d95SSadaf Ebrahimi  )
97*3c321d95SSadaf Ebrahimi  .addFunction(
98*3c321d95SSadaf Ebrahimi    FunSpec.builder("abs")
99*3c321d95SSadaf Ebrahimi      .receiver(Int::class)
100*3c321d95SSadaf Ebrahimi      .returns(Int::class)
101*3c321d95SSadaf Ebrahimi      .addStatement("return if (this < 0) -this else this")
102*3c321d95SSadaf Ebrahimi      .build()
103*3c321d95SSadaf Ebrahimi  )
104*3c321d95SSadaf Ebrahimi  .build()
105*3c321d95SSadaf Ebrahimi```
106*3c321d95SSadaf Ebrahimi
107*3c321d95SSadaf EbrahimiWill output this:
108*3c321d95SSadaf Ebrahimi
109*3c321d95SSadaf Ebrahimi```kotlin
110*3c321d95SSadaf Ebrahimi@file:JvmName
111*3c321d95SSadaf Ebrahimi
112*3c321d95SSadaf Ebrahimipackage com.example
113*3c321d95SSadaf Ebrahimi
114*3c321d95SSadaf Ebrahimiimport kotlin.Int
115*3c321d95SSadaf Ebrahimiimport kotlin.jvm.JvmName
116*3c321d95SSadaf Ebrahimi
117*3c321d95SSadaf Ebrahimifun Int.abs(): Int = if (this < 0) -this else this
118*3c321d95SSadaf Ebrahimi```
119