1 /*
2  * Copyright (C) 2018 Square, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.squareup.kotlinpoet.jvm
17 
18 import com.google.common.truth.Truth.assertThat
19 import com.squareup.kotlinpoet.ClassName
20 import com.squareup.kotlinpoet.FileSpec
21 import com.squareup.kotlinpoet.FunSpec
22 import com.squareup.kotlinpoet.KModifier
23 import com.squareup.kotlinpoet.KModifier.DATA
24 import com.squareup.kotlinpoet.ParameterSpec
25 import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
26 import com.squareup.kotlinpoet.PropertySpec
27 import com.squareup.kotlinpoet.STRING
28 import com.squareup.kotlinpoet.TypeSpec
29 import com.squareup.kotlinpoet.asClassName
30 import com.squareup.kotlinpoet.asTypeName
31 import com.squareup.kotlinpoet.assertThrows
32 import java.io.IOException
33 import kotlin.test.Test
34 
35 class JvmAnnotationsTest {
36 
jvmFieldnull37   @Test fun jvmField() {
38     val file = FileSpec.builder("com.squareup.tacos", "Taco")
39       .addType(
40         TypeSpec.classBuilder("Taco")
41           .addProperty(
42             PropertySpec.builder("foo", String::class)
43               .jvmField()
44               .initializer("%S", "foo")
45               .build(),
46           )
47           .build(),
48       )
49       .build()
50     assertThat(file.toString()).isEqualTo(
51       """
52       |package com.squareup.tacos
53       |
54       |import kotlin.String
55       |import kotlin.jvm.JvmField
56       |
57       |public class Taco {
58       |  @JvmField
59       |  public val foo: String = "foo"
60       |}
61       |
62       """.trimMargin(),
63     )
64   }
65 
jvmFieldConstructorParameternull66   @Test fun jvmFieldConstructorParameter() {
67     val file = FileSpec.builder("com.squareup.tacos", "Taco")
68       .addType(
69         TypeSpec.classBuilder("Taco")
70           .primaryConstructor(
71             FunSpec.constructorBuilder()
72               .addParameter("foo", String::class)
73               .build(),
74           )
75           .addProperty(
76             PropertySpec.builder("foo", String::class)
77               .jvmField()
78               .initializer("foo")
79               .build(),
80           )
81           .build(),
82       )
83       .build()
84     assertThat(file.toString()).isEqualTo(
85       """
86       |package com.squareup.tacos
87       |
88       |import kotlin.String
89       |import kotlin.jvm.JvmField
90       |
91       |public class Taco(
92       |  @JvmField
93       |  public val foo: String,
94       |)
95       |
96       """.trimMargin(),
97     )
98   }
99 
jvmStaticPropertynull100   @Test fun jvmStaticProperty() {
101     val file = FileSpec.builder("com.squareup.tacos", "Taco")
102       .addType(
103         TypeSpec.classBuilder("Taco")
104           .addType(
105             TypeSpec.companionObjectBuilder()
106               .addProperty(
107                 PropertySpec.builder("foo", String::class)
108                   .jvmStatic()
109                   .initializer("%S", "foo")
110                   .build(),
111               )
112               .build(),
113           )
114           .build(),
115       )
116       .build()
117     assertThat(file.toString()).isEqualTo(
118       """
119       |package com.squareup.tacos
120       |
121       |import kotlin.String
122       |import kotlin.jvm.JvmStatic
123       |
124       |public class Taco {
125       |  public companion object {
126       |    @JvmStatic
127       |    public val foo: String = "foo"
128       |  }
129       |}
130       |
131       """.trimMargin(),
132     )
133   }
134 
jvmStaticFunctionnull135   @Test fun jvmStaticFunction() {
136     val file = FileSpec.builder("com.squareup.tacos", "Taco")
137       .addType(
138         TypeSpec.classBuilder("Taco")
139           .addType(
140             TypeSpec.companionObjectBuilder()
141               .addFunction(
142                 FunSpec.builder("foo")
143                   .jvmStatic()
144                   .addStatement("return %S", "foo")
145                   .returns(String::class)
146                   .build(),
147               )
148               .build(),
149           )
150           .build(),
151       )
152       .build()
153     assertThat(file.toString()).isEqualTo(
154       """
155       |package com.squareup.tacos
156       |
157       |import kotlin.String
158       |import kotlin.jvm.JvmStatic
159       |
160       |public class Taco {
161       |  public companion object {
162       |    @JvmStatic
163       |    public fun foo(): String = "foo"
164       |  }
165       |}
166       |
167       """.trimMargin(),
168     )
169   }
170 
jvmStaticGetternull171   @Test fun jvmStaticGetter() {
172     val file = FileSpec.builder("com.squareup.tacos", "Taco")
173       .addType(
174         TypeSpec.classBuilder("Taco")
175           .addType(
176             TypeSpec.companionObjectBuilder()
177               .addProperty(
178                 PropertySpec.builder("foo", String::class)
179                   .getter(
180                     FunSpec.getterBuilder()
181                       .jvmStatic()
182                       .addStatement("return %S", "foo")
183                       .build(),
184                   )
185                   .build(),
186               )
187               .build(),
188           )
189           .build(),
190       )
191       .build()
192     assertThat(file.toString()).isEqualTo(
193       """
194       |package com.squareup.tacos
195       |
196       |import kotlin.String
197       |import kotlin.jvm.JvmStatic
198       |
199       |public class Taco {
200       |  public companion object {
201       |    public val foo: String
202       |      @JvmStatic
203       |      get() = "foo"
204       |  }
205       |}
206       |
207       """.trimMargin(),
208     )
209   }
210 
jvmStaticSetternull211   @Test fun jvmStaticSetter() {
212     val file = FileSpec.builder("com.squareup.tacos", "Taco")
213       .addType(
214         TypeSpec.classBuilder("Taco")
215           .addType(
216             TypeSpec.companionObjectBuilder()
217               .addProperty(
218                 PropertySpec.builder("foo", String::class.asTypeName())
219                   .mutable()
220                   .setter(
221                     FunSpec.setterBuilder()
222                       .jvmStatic()
223                       .addParameter("value", String::class)
224                       .build(),
225                   )
226                   .initializer("%S", "foo")
227                   .build(),
228               )
229               .build(),
230           )
231           .build(),
232       )
233       .build()
234     assertThat(file.toString()).isEqualTo(
235       """
236       |package com.squareup.tacos
237       |
238       |import kotlin.String
239       |import kotlin.jvm.JvmStatic
240       |
241       |public class Taco {
242       |  public companion object {
243       |    public var foo: String = "foo"
244       |      @JvmStatic
245       |      set(`value`) {
246       |      }
247       |  }
248       |}
249       |
250       """.trimMargin(),
251     )
252   }
253 
jvmStaticForbiddenOnConstructornull254   @Test fun jvmStaticForbiddenOnConstructor() {
255     assertThrows<IllegalStateException> {
256       FunSpec.constructorBuilder()
257         .jvmStatic()
258     }.hasMessageThat().isEqualTo("Can't apply @JvmStatic to a constructor!")
259   }
260 
throwsFunctionnull261   @Test fun throwsFunction() {
262     val file = FileSpec.builder("com.squareup.tacos", "Taco")
263       .addFunction(
264         FunSpec.builder("foo")
265           .throws(IOException::class, IllegalArgumentException::class)
266           .build(),
267       )
268       .build()
269     assertThat(file.toString()).isEqualTo(
270       """
271       |package com.squareup.tacos
272       |
273       |import java.io.IOException
274       |import java.lang.IllegalArgumentException
275       |import kotlin.jvm.Throws
276       |
277       |@Throws(
278       |  IOException::class,
279       |  IllegalArgumentException::class,
280       |)
281       |public fun foo() {
282       |}
283       |
284       """.trimMargin(),
285     )
286   }
287 
throwsFunctionCustomExceptionnull288   @Test fun throwsFunctionCustomException() {
289     val file = FileSpec.builder("com.squareup.tacos", "Taco")
290       .addFunction(
291         FunSpec.builder("foo")
292           .throws(ClassName("com.squareup.tacos", "IllegalTacoException"))
293           .build(),
294       )
295       .build()
296     assertThat(file.toString()).isEqualTo(
297       """
298       |package com.squareup.tacos
299       |
300       |import kotlin.jvm.Throws
301       |
302       |@Throws(IllegalTacoException::class)
303       |public fun foo() {
304       |}
305       |
306       """.trimMargin(),
307     )
308   }
309 
throwsPrimaryConstructornull310   @Test fun throwsPrimaryConstructor() {
311     val file = FileSpec.builder("com.squareup.tacos", "Taco")
312       .addType(
313         TypeSpec.classBuilder("Taco")
314           .primaryConstructor(
315             FunSpec.constructorBuilder()
316               .throws(IOException::class)
317               .addParameter("foo", String::class)
318               .build(),
319           )
320           .build(),
321       )
322       .build()
323     assertThat(file.toString()).isEqualTo(
324       """
325       |package com.squareup.tacos
326       |
327       |import java.io.IOException
328       |import kotlin.String
329       |import kotlin.jvm.Throws
330       |
331       |public class Taco @Throws(IOException::class) constructor(
332       |  foo: String,
333       |)
334       |
335       """.trimMargin(),
336     )
337   }
338 
throwsGetternull339   @Test fun throwsGetter() {
340     val file = FileSpec.builder("com.squareup.tacos", "Taco")
341       .addProperty(
342         PropertySpec.builder("foo", String::class)
343           .getter(
344             FunSpec.getterBuilder()
345               .throws(IOException::class)
346               .addStatement("return %S", "foo")
347               .build(),
348           )
349           .build(),
350       )
351       .build()
352     assertThat(file.toString()).isEqualTo(
353       """
354       |package com.squareup.tacos
355       |
356       |import java.io.IOException
357       |import kotlin.String
358       |import kotlin.jvm.Throws
359       |
360       |public val foo: String
361       |  @Throws(IOException::class)
362       |  get() = "foo"
363       |
364       """.trimMargin(),
365     )
366   }
367 
throwsSetternull368   @Test fun throwsSetter() {
369     val file = FileSpec.builder("com.squareup.tacos", "Taco")
370       .addProperty(
371         PropertySpec.builder("foo", String::class)
372           .mutable()
373           .setter(
374             FunSpec.setterBuilder()
375               .throws(IOException::class)
376               .addParameter("value", String::class)
377               .addStatement("print(%S)", "foo")
378               .build(),
379           )
380           .build(),
381       )
382       .build()
383     assertThat(file.toString()).isEqualTo(
384       """
385       |package com.squareup.tacos
386       |
387       |import java.io.IOException
388       |import kotlin.String
389       |import kotlin.jvm.Throws
390       |
391       |public var foo: String
392       |  @Throws(IOException::class)
393       |  set(`value`) {
394       |    print("foo")
395       |  }
396       |
397       """.trimMargin(),
398     )
399   }
400 
jvmOverloadsFunctionnull401   @Test fun jvmOverloadsFunction() {
402     val file = FileSpec.builder("com.squareup.tacos", "Taco")
403       .addFunction(
404         FunSpec.builder("foo")
405           .jvmOverloads()
406           .addParameter("bar", Int::class)
407           .addParameter(
408             ParameterSpec.builder("baz", String::class)
409               .defaultValue("%S", "baz")
410               .build(),
411           )
412           .build(),
413       )
414       .build()
415     assertThat(file.toString()).isEqualTo(
416       """
417       |package com.squareup.tacos
418       |
419       |import kotlin.Int
420       |import kotlin.String
421       |import kotlin.jvm.JvmOverloads
422       |
423       |@JvmOverloads
424       |public fun foo(bar: Int, baz: String = "baz") {
425       |}
426       |
427       """.trimMargin(),
428     )
429   }
430 
jvmOverloadsPrimaryConstructornull431   @Test fun jvmOverloadsPrimaryConstructor() {
432     val file = FileSpec.builder("com.squareup.tacos", "Taco")
433       .addType(
434         TypeSpec.classBuilder("Taco")
435           .primaryConstructor(
436             FunSpec.constructorBuilder()
437               .jvmOverloads()
438               .addParameter("bar", Int::class)
439               .addParameter(
440                 ParameterSpec.builder("baz", String::class)
441                   .defaultValue("%S", "baz")
442                   .build(),
443               )
444               .build(),
445           )
446           .build(),
447       )
448       .build()
449     assertThat(file.toString()).isEqualTo(
450       """
451       |package com.squareup.tacos
452       |
453       |import kotlin.Int
454       |import kotlin.String
455       |import kotlin.jvm.JvmOverloads
456       |
457       |public class Taco @JvmOverloads constructor(
458       |  bar: Int,
459       |  baz: String = "baz",
460       |)
461       |
462       """.trimMargin(),
463     )
464   }
465 
jvmOverloadsOnGetterForbiddennull466   @Test fun jvmOverloadsOnGetterForbidden() {
467     assertThrows<IllegalStateException> {
468       FunSpec.getterBuilder()
469         .jvmOverloads()
470     }.hasMessageThat().isEqualTo("Can't apply @JvmOverloads to a getter!")
471   }
472 
jvmOverloadsOnSetterForbiddennull473   @Test fun jvmOverloadsOnSetterForbidden() {
474     assertThrows<IllegalStateException> {
475       FunSpec.setterBuilder()
476         .jvmOverloads()
477     }.hasMessageThat().isEqualTo("Can't apply @JvmOverloads to a setter!")
478   }
479 
jvmNameFilenull480   @Test fun jvmNameFile() {
481     val file = FileSpec.builder("com.squareup.tacos", "Taco")
482       .jvmName("TacoUtils")
483       .addProperty(
484         PropertySpec.builder("foo", String::class)
485           .initializer("%S", "foo")
486           .build(),
487       )
488       .build()
489     assertThat(file.toString()).isEqualTo(
490       """
491       |@file:JvmName("TacoUtils")
492       |
493       |package com.squareup.tacos
494       |
495       |import kotlin.String
496       |import kotlin.jvm.JvmName
497       |
498       |public val foo: String = "foo"
499       |
500       """.trimMargin(),
501     )
502   }
503 
jvmNameFunctionnull504   @Test fun jvmNameFunction() {
505     val file = FileSpec.builder("com.squareup.tacos", "Taco")
506       .addFunction(
507         FunSpec.builder("foo")
508           .jvmName("getFoo")
509           .build(),
510       )
511       .build()
512     assertThat(file.toString()).isEqualTo(
513       """
514       |package com.squareup.tacos
515       |
516       |import kotlin.jvm.JvmName
517       |
518       |@JvmName("getFoo")
519       |public fun foo() {
520       |}
521       |
522       """.trimMargin(),
523     )
524   }
525 
jvmNameGetternull526   @Test fun jvmNameGetter() {
527     val file = FileSpec.builder("com.squareup.tacos", "Taco")
528       .addProperty(
529         PropertySpec.builder("foo", String::class)
530           .getter(
531             FunSpec.getterBuilder()
532               .jvmName("foo")
533               .addStatement("return %S", "foo")
534               .build(),
535           )
536           .build(),
537       )
538       .build()
539     assertThat(file.toString()).isEqualTo(
540       """
541       |package com.squareup.tacos
542       |
543       |import kotlin.String
544       |import kotlin.jvm.JvmName
545       |
546       |public val foo: String
547       |  @JvmName("foo")
548       |  get() = "foo"
549       |
550       """.trimMargin(),
551     )
552   }
553 
jvmNameSetternull554   @Test fun jvmNameSetter() {
555     val file = FileSpec.builder("com.squareup.tacos", "Taco")
556       .addProperty(
557         PropertySpec.builder("foo", String::class.asTypeName())
558           .mutable()
559           .initializer("%S", "foo")
560           .setter(
561             FunSpec.setterBuilder()
562               .jvmName("foo")
563               .addParameter("value", String::class)
564               .build(),
565           )
566           .build(),
567       )
568       .build()
569     assertThat(file.toString()).isEqualTo(
570       """
571       |package com.squareup.tacos
572       |
573       |import kotlin.String
574       |import kotlin.jvm.JvmName
575       |
576       |public var foo: String = "foo"
577       |  @JvmName("foo")
578       |  set(`value`) {
579       |  }
580       |
581       """.trimMargin(),
582     )
583   }
584 
jvmNameForbiddenOnConstructornull585   @Test fun jvmNameForbiddenOnConstructor() {
586     assertThrows<IllegalStateException> {
587       FunSpec.constructorBuilder()
588         .jvmName("notAConstructor")
589     }.hasMessageThat().isEqualTo("Can't apply @JvmName to a constructor!")
590   }
591 
jvmMultifileClassnull592   @Test fun jvmMultifileClass() {
593     val file = FileSpec.builder("com.squareup.tacos", "Taco")
594       .jvmMultifileClass()
595       .addProperty(
596         PropertySpec.builder("foo", String::class)
597           .initializer("%S", "foo")
598           .build(),
599       )
600       .build()
601     assertThat(file.toString()).isEqualTo(
602       """
603       |@file:JvmMultifileClass
604       |
605       |package com.squareup.tacos
606       |
607       |import kotlin.String
608       |import kotlin.jvm.JvmMultifileClass
609       |
610       |public val foo: String = "foo"
611       |
612       """.trimMargin(),
613     )
614   }
615 
jvmSuppressWildcardsClassnull616   @Test fun jvmSuppressWildcardsClass() {
617     val file = FileSpec.builder("com.squareup.tacos", "Taco")
618       .addType(
619         TypeSpec.classBuilder("Taco")
620           .jvmSuppressWildcards()
621           .build(),
622       )
623       .build()
624     assertThat(file.toString()).isEqualTo(
625       """
626       |package com.squareup.tacos
627       |
628       |import kotlin.jvm.JvmSuppressWildcards
629       |
630       |@JvmSuppressWildcards
631       |public class Taco
632       |
633       """.trimMargin(),
634     )
635   }
636 
jvmSuppressWildcardsFunctionnull637   @Test fun jvmSuppressWildcardsFunction() {
638     val file = FileSpec.builder("com.squareup.tacos", "Taco")
639       .addFunction(
640         FunSpec.builder("foo")
641           .jvmSuppressWildcards(suppress = false)
642           .build(),
643       )
644       .build()
645     assertThat(file.toString()).isEqualTo(
646       """
647       |package com.squareup.tacos
648       |
649       |import kotlin.jvm.JvmSuppressWildcards
650       |
651       |@JvmSuppressWildcards(suppress = false)
652       |public fun foo() {
653       |}
654       |
655       """.trimMargin(),
656     )
657   }
658 
jvmSuppressWildcardsOnConstructorForbiddennull659   @Test fun jvmSuppressWildcardsOnConstructorForbidden() {
660     assertThrows<IllegalStateException> {
661       FunSpec.constructorBuilder()
662         .jvmSuppressWildcards()
663     }.hasMessageThat().isEqualTo("Can't apply @JvmSuppressWildcards to a constructor!")
664   }
665 
jvmSuppressWildcardsOnGetterForbiddennull666   @Test fun jvmSuppressWildcardsOnGetterForbidden() {
667     assertThrows<IllegalStateException> {
668       FunSpec.getterBuilder()
669         .jvmSuppressWildcards()
670     }.hasMessageThat().isEqualTo("Can't apply @JvmSuppressWildcards to a getter!")
671   }
672 
jvmSuppressWildcardsOnSetterForbiddennull673   @Test fun jvmSuppressWildcardsOnSetterForbidden() {
674     assertThrows<IllegalStateException> {
675       FunSpec.setterBuilder()
676         .jvmSuppressWildcards()
677     }.hasMessageThat().isEqualTo("Can't apply @JvmSuppressWildcards to a setter!")
678   }
679 
jvmSuppressWildcardsPropertynull680   @Test fun jvmSuppressWildcardsProperty() {
681     val file = FileSpec.builder("com.squareup.tacos", "Taco")
682       .addProperty(
683         PropertySpec.builder("foo", String::class)
684           .jvmSuppressWildcards(suppress = false)
685           .initializer("%S", "foo")
686           .build(),
687       )
688       .build()
689     assertThat(file.toString()).isEqualTo(
690       """
691       |package com.squareup.tacos
692       |
693       |import kotlin.String
694       |import kotlin.jvm.JvmSuppressWildcards
695       |
696       |@JvmSuppressWildcards(suppress = false)
697       |public val foo: String = "foo"
698       |
699       """.trimMargin(),
700     )
701   }
702 
jvmSuppressWildcardsTypenull703   @Test fun jvmSuppressWildcardsType() {
704     val file = FileSpec.builder("com.squareup.tacos", "Taco")
705       .addFunction(
706         FunSpec.builder("foo")
707           .addParameter(
708             "a",
709             List::class.asClassName()
710               .parameterizedBy(Int::class.asTypeName().jvmSuppressWildcards()),
711           )
712           .build(),
713       )
714       .build()
715     assertThat(file.toString()).isEqualTo(
716       """
717       |package com.squareup.tacos
718       |
719       |import kotlin.Int
720       |import kotlin.collections.List
721       |import kotlin.jvm.JvmSuppressWildcards
722       |
723       |public fun foo(a: List<@JvmSuppressWildcards Int>) {
724       |}
725       |
726       """.trimMargin(),
727     )
728   }
729 
jvmWildcardTypenull730   @Test fun jvmWildcardType() {
731     val file = FileSpec.builder("com.squareup.tacos", "Taco")
732       .addFunction(
733         FunSpec.builder("foo")
734           .addParameter(
735             "a",
736             List::class.asClassName()
737               .parameterizedBy(Int::class.asTypeName().jvmWildcard()),
738           )
739           .build(),
740       )
741       .build()
742     assertThat(file.toString()).isEqualTo(
743       """
744       |package com.squareup.tacos
745       |
746       |import kotlin.Int
747       |import kotlin.collections.List
748       |import kotlin.jvm.JvmWildcard
749       |
750       |public fun foo(a: List<@JvmWildcard Int>) {
751       |}
752       |
753       """.trimMargin(),
754     )
755   }
756 
synchronizedFunctionnull757   @Test fun synchronizedFunction() {
758     val file = FileSpec.builder("com.squareup.tacos", "Taco")
759       .addFunction(
760         FunSpec.builder("foo")
761           .synchronized()
762           .returns(STRING)
763           .addStatement("return %S", "foo")
764           .build(),
765       )
766       .build()
767     assertThat(file.toString()).isEqualTo(
768       """
769       |package com.squareup.tacos
770       |
771       |import kotlin.String
772       |import kotlin.jvm.Synchronized
773       |
774       |@Synchronized
775       |public fun foo(): String = "foo"
776       |
777       """.trimMargin(),
778     )
779   }
780 
synchronizedGetternull781   @Test fun synchronizedGetter() {
782     val file = FileSpec.builder("com.squareup.tacos", "Taco")
783       .addProperty(
784         PropertySpec.builder("foo", String::class)
785           .getter(
786             FunSpec.getterBuilder()
787               .synchronized()
788               .addStatement("return %S", "foo")
789               .build(),
790           )
791           .build(),
792       )
793       .build()
794     assertThat(file.toString()).isEqualTo(
795       """
796       |package com.squareup.tacos
797       |
798       |import kotlin.String
799       |import kotlin.jvm.Synchronized
800       |
801       |public val foo: String
802       |  @Synchronized
803       |  get() = "foo"
804       |
805       """.trimMargin(),
806     )
807   }
808 
synchronizedSetternull809   @Test fun synchronizedSetter() {
810     val file = FileSpec.builder("com.squareup.tacos", "Taco")
811       .addProperty(
812         PropertySpec.builder("foo", String::class.asTypeName())
813           .mutable()
814           .initializer("%S", "foo")
815           .setter(
816             FunSpec.setterBuilder()
817               .synchronized()
818               .addParameter("value", String::class)
819               .build(),
820           )
821           .build(),
822       )
823       .build()
824     assertThat(file.toString()).isEqualTo(
825       """
826       |package com.squareup.tacos
827       |
828       |import kotlin.String
829       |import kotlin.jvm.Synchronized
830       |
831       |public var foo: String = "foo"
832       |  @Synchronized
833       |  set(`value`) {
834       |  }
835       |
836       """.trimMargin(),
837     )
838   }
839 
synchronizedOnConstructorForbiddennull840   @Test fun synchronizedOnConstructorForbidden() {
841     assertThrows<IllegalStateException> {
842       FunSpec.constructorBuilder()
843         .synchronized()
844     }.hasMessageThat().isEqualTo("Can't apply @Synchronized to a constructor!")
845   }
846 
transientnull847   @Test fun transient() {
848     val file = FileSpec.builder("com.squareup.tacos", "Taco")
849       .addType(
850         TypeSpec.classBuilder("Taco")
851           .addProperty(
852             PropertySpec.builder("foo", String::class)
853               .transient()
854               .initializer("%S", "foo")
855               .build(),
856           )
857           .build(),
858       )
859       .build()
860     assertThat(file.toString()).isEqualTo(
861       """
862       |package com.squareup.tacos
863       |
864       |import kotlin.String
865       |import kotlin.jvm.Transient
866       |
867       |public class Taco {
868       |  @Transient
869       |  public val foo: String = "foo"
870       |}
871       |
872       """.trimMargin(),
873     )
874   }
875 
transientConstructorParameternull876   @Test fun transientConstructorParameter() {
877     val file = FileSpec.builder("com.squareup.tacos", "Taco")
878       .addType(
879         TypeSpec.classBuilder("Taco")
880           .primaryConstructor(
881             FunSpec.constructorBuilder()
882               .addParameter("foo", String::class)
883               .build(),
884           )
885           .addProperty(
886             PropertySpec.builder("foo", String::class)
887               .transient()
888               .initializer("foo")
889               .build(),
890           )
891           .build(),
892       )
893       .build()
894     assertThat(file.toString()).isEqualTo(
895       """
896       |package com.squareup.tacos
897       |
898       |import kotlin.String
899       |import kotlin.jvm.Transient
900       |
901       |public class Taco(
902       |  @Transient
903       |  public val foo: String,
904       |)
905       |
906       """.trimMargin(),
907     )
908   }
909 
volatilenull910   @Test fun volatile() {
911     val file = FileSpec.builder("com.squareup.tacos", "Taco")
912       .addType(
913         TypeSpec.classBuilder("Taco")
914           .addProperty(
915             PropertySpec.builder("foo", String::class)
916               .volatile()
917               .initializer("%S", "foo")
918               .build(),
919           )
920           .build(),
921       )
922       .build()
923     assertThat(file.toString()).isEqualTo(
924       """
925       |package com.squareup.tacos
926       |
927       |import kotlin.String
928       |import kotlin.jvm.Volatile
929       |
930       |public class Taco {
931       |  @Volatile
932       |  public val foo: String = "foo"
933       |}
934       |
935       """.trimMargin(),
936     )
937   }
938 
volatileConstructorParameternull939   @Test fun volatileConstructorParameter() {
940     val file = FileSpec.builder("com.squareup.tacos", "Taco")
941       .addType(
942         TypeSpec.classBuilder("Taco")
943           .primaryConstructor(
944             FunSpec.constructorBuilder()
945               .addParameter("foo", String::class)
946               .build(),
947           )
948           .addProperty(
949             PropertySpec.builder("foo", String::class)
950               .volatile()
951               .initializer("foo")
952               .build(),
953           )
954           .build(),
955       )
956       .build()
957     assertThat(file.toString()).isEqualTo(
958       """
959       |package com.squareup.tacos
960       |
961       |import kotlin.String
962       |import kotlin.jvm.Volatile
963       |
964       |public class Taco(
965       |  @Volatile
966       |  public val foo: String,
967       |)
968       |
969       """.trimMargin(),
970     )
971   }
972 
strictfpFunctionnull973   @Test fun strictfpFunction() {
974     val file = FileSpec.builder("com.squareup.tacos", "Taco")
975       .addFunction(
976         FunSpec.builder("foo")
977           .strictfp()
978           .build(),
979       )
980       .build()
981     assertThat(file.toString()).isEqualTo(
982       """
983       |package com.squareup.tacos
984       |
985       |import kotlin.jvm.Strictfp
986       |
987       |@Strictfp
988       |public fun foo() {
989       |}
990       |
991       """.trimMargin(),
992     )
993   }
994 
strictfpPrimaryConstructornull995   @Test fun strictfpPrimaryConstructor() {
996     val file = FileSpec.builder("com.squareup.tacos", "Taco")
997       .addType(
998         TypeSpec.classBuilder("Taco")
999           .primaryConstructor(
1000             FunSpec.constructorBuilder()
1001               .strictfp()
1002               .addParameter("foo", String::class)
1003               .build(),
1004           )
1005           .build(),
1006       )
1007       .build()
1008     assertThat(file.toString()).isEqualTo(
1009       """
1010       |package com.squareup.tacos
1011       |
1012       |import kotlin.String
1013       |import kotlin.jvm.Strictfp
1014       |
1015       |public class Taco @Strictfp constructor(
1016       |  foo: String,
1017       |)
1018       |
1019       """.trimMargin(),
1020     )
1021   }
1022 
strictfpGetternull1023   @Test fun strictfpGetter() {
1024     val file = FileSpec.builder("com.squareup.tacos", "Taco")
1025       .addProperty(
1026         PropertySpec.builder("foo", String::class)
1027           .getter(
1028             FunSpec.getterBuilder()
1029               .strictfp()
1030               .addStatement("return %S", "foo")
1031               .build(),
1032           )
1033           .build(),
1034       )
1035       .build()
1036     assertThat(file.toString()).isEqualTo(
1037       """
1038       |package com.squareup.tacos
1039       |
1040       |import kotlin.String
1041       |import kotlin.jvm.Strictfp
1042       |
1043       |public val foo: String
1044       |  @Strictfp
1045       |  get() = "foo"
1046       |
1047       """.trimMargin(),
1048     )
1049   }
1050 
strictfpSetternull1051   @Test fun strictfpSetter() {
1052     val file = FileSpec.builder("com.squareup.tacos", "Taco")
1053       .addProperty(
1054         PropertySpec.builder("foo", String::class)
1055           .mutable()
1056           .setter(
1057             FunSpec.setterBuilder()
1058               .strictfp()
1059               .addParameter("value", String::class)
1060               .addStatement("print(%S)", "foo")
1061               .build(),
1062           )
1063           .build(),
1064       )
1065       .build()
1066     assertThat(file.toString()).isEqualTo(
1067       """
1068       |package com.squareup.tacos
1069       |
1070       |import kotlin.String
1071       |import kotlin.jvm.Strictfp
1072       |
1073       |public var foo: String
1074       |  @Strictfp
1075       |  set(`value`) {
1076       |    print("foo")
1077       |  }
1078       |
1079       """.trimMargin(),
1080     )
1081   }
1082 
jvmInlineClassnull1083   @Test fun jvmInlineClass() {
1084     val file = FileSpec.builder("com.squareup.tacos", "Taco")
1085       .addType(
1086         TypeSpec.classBuilder("Taco")
1087           .addModifiers(KModifier.VALUE)
1088           .jvmInline()
1089           .primaryConstructor(
1090             FunSpec.constructorBuilder()
1091               .addParameter("value", STRING)
1092               .build(),
1093           )
1094           .addProperty(
1095             PropertySpec.builder("value", STRING)
1096               .initializer("value")
1097               .build(),
1098           )
1099           .build(),
1100       )
1101       .build()
1102     assertThat(file.toString()).isEqualTo(
1103       """
1104       |package com.squareup.tacos
1105       |
1106       |import kotlin.String
1107       |import kotlin.jvm.JvmInline
1108       |
1109       |@JvmInline
1110       |public value class Taco(
1111       |  public val `value`: String,
1112       |)
1113       |
1114       """.trimMargin(),
1115     )
1116   }
1117 
jvmRecordClassnull1118   @Test fun jvmRecordClass() {
1119     val file = FileSpec.builder("com.squareup.tacos", "Taco")
1120       .addType(
1121         TypeSpec.classBuilder("Taco")
1122           .jvmRecord()
1123           .addModifiers(DATA)
1124           .primaryConstructor(
1125             FunSpec.constructorBuilder()
1126               .addParameter("value", STRING)
1127               .build(),
1128           )
1129           .addProperty(
1130             PropertySpec.builder("value", STRING)
1131               .initializer("value")
1132               .build(),
1133           )
1134           .build(),
1135       )
1136       .build()
1137     assertThat(file.toString()).isEqualTo(
1138       """
1139       |package com.squareup.tacos
1140       |
1141       |import kotlin.String
1142       |import kotlin.jvm.JvmRecord
1143       |
1144       |@JvmRecord
1145       |public data class Taco(
1146       |  public val `value`: String,
1147       |)
1148       |
1149       """.trimMargin(),
1150     )
1151   }
1152 }
1153