1*53ff1f6bSSadaf EbrahimiJavaPoet 2*53ff1f6bSSadaf Ebrahimi======== 3*53ff1f6bSSadaf Ebrahimi 4*53ff1f6bSSadaf Ebrahimi`JavaPoet` is a Java API for generating `.java` source files. 5*53ff1f6bSSadaf Ebrahimi 6*53ff1f6bSSadaf EbrahimiSource file generation can be useful when doing things such as annotation processing or interacting 7*53ff1f6bSSadaf Ebrahimiwith metadata files (e.g., database schemas, protocol formats). By generating code, you eliminate 8*53ff1f6bSSadaf Ebrahimithe need to write boilerplate while also keeping a single source of truth for the metadata. 9*53ff1f6bSSadaf Ebrahimi 10*53ff1f6bSSadaf Ebrahimi 11*53ff1f6bSSadaf Ebrahimi### Example 12*53ff1f6bSSadaf Ebrahimi 13*53ff1f6bSSadaf EbrahimiHere's a (boring) `HelloWorld` class: 14*53ff1f6bSSadaf Ebrahimi 15*53ff1f6bSSadaf Ebrahimi```java 16*53ff1f6bSSadaf Ebrahimipackage com.example.helloworld; 17*53ff1f6bSSadaf Ebrahimi 18*53ff1f6bSSadaf Ebrahimipublic final class HelloWorld { 19*53ff1f6bSSadaf Ebrahimi public static void main(String[] args) { 20*53ff1f6bSSadaf Ebrahimi System.out.println("Hello, JavaPoet!"); 21*53ff1f6bSSadaf Ebrahimi } 22*53ff1f6bSSadaf Ebrahimi} 23*53ff1f6bSSadaf Ebrahimi``` 24*53ff1f6bSSadaf Ebrahimi 25*53ff1f6bSSadaf EbrahimiAnd this is the (exciting) code to generate it with JavaPoet: 26*53ff1f6bSSadaf Ebrahimi 27*53ff1f6bSSadaf Ebrahimi```java 28*53ff1f6bSSadaf EbrahimiMethodSpec main = MethodSpec.methodBuilder("main") 29*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.STATIC) 30*53ff1f6bSSadaf Ebrahimi .returns(void.class) 31*53ff1f6bSSadaf Ebrahimi .addParameter(String[].class, "args") 32*53ff1f6bSSadaf Ebrahimi .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") 33*53ff1f6bSSadaf Ebrahimi .build(); 34*53ff1f6bSSadaf Ebrahimi 35*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") 36*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 37*53ff1f6bSSadaf Ebrahimi .addMethod(main) 38*53ff1f6bSSadaf Ebrahimi .build(); 39*53ff1f6bSSadaf Ebrahimi 40*53ff1f6bSSadaf EbrahimiJavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld) 41*53ff1f6bSSadaf Ebrahimi .build(); 42*53ff1f6bSSadaf Ebrahimi 43*53ff1f6bSSadaf EbrahimijavaFile.writeTo(System.out); 44*53ff1f6bSSadaf Ebrahimi``` 45*53ff1f6bSSadaf Ebrahimi 46*53ff1f6bSSadaf EbrahimiTo declare the main method, we've created a `MethodSpec` "main" configured with modifiers, return 47*53ff1f6bSSadaf Ebrahimitype, parameters and code statements. We add the main method to a `HelloWorld` class, and then add 48*53ff1f6bSSadaf Ebrahimithat to a `HelloWorld.java` file. 49*53ff1f6bSSadaf Ebrahimi 50*53ff1f6bSSadaf EbrahimiIn this case we write the file to `System.out`, but we could also get it as a string 51*53ff1f6bSSadaf Ebrahimi(`JavaFile.toString()`) or write it to the file system (`JavaFile.writeTo()`). 52*53ff1f6bSSadaf Ebrahimi 53*53ff1f6bSSadaf EbrahimiThe [Javadoc][javadoc] catalogs the complete JavaPoet API, which we explore below. 54*53ff1f6bSSadaf Ebrahimi 55*53ff1f6bSSadaf Ebrahimi### Code & Control Flow 56*53ff1f6bSSadaf Ebrahimi 57*53ff1f6bSSadaf EbrahimiMost of JavaPoet's API uses plain old immutable Java objects. There's also builders, method chaining 58*53ff1f6bSSadaf Ebrahimiand varargs to make the API friendly. JavaPoet offers models for classes & interfaces (`TypeSpec`), 59*53ff1f6bSSadaf Ebrahimifields (`FieldSpec`), methods & constructors (`MethodSpec`), parameters (`ParameterSpec`) and 60*53ff1f6bSSadaf Ebrahimiannotations (`AnnotationSpec`). 61*53ff1f6bSSadaf Ebrahimi 62*53ff1f6bSSadaf EbrahimiBut the _body_ of methods and constructors is not modeled. There's no expression class, no 63*53ff1f6bSSadaf Ebrahimistatement class or syntax tree nodes. Instead, JavaPoet uses strings for code blocks: 64*53ff1f6bSSadaf Ebrahimi 65*53ff1f6bSSadaf Ebrahimi```java 66*53ff1f6bSSadaf EbrahimiMethodSpec main = MethodSpec.methodBuilder("main") 67*53ff1f6bSSadaf Ebrahimi .addCode("" 68*53ff1f6bSSadaf Ebrahimi + "int total = 0;\n" 69*53ff1f6bSSadaf Ebrahimi + "for (int i = 0; i < 10; i++) {\n" 70*53ff1f6bSSadaf Ebrahimi + " total += i;\n" 71*53ff1f6bSSadaf Ebrahimi + "}\n") 72*53ff1f6bSSadaf Ebrahimi .build(); 73*53ff1f6bSSadaf Ebrahimi``` 74*53ff1f6bSSadaf Ebrahimi 75*53ff1f6bSSadaf EbrahimiWhich generates this: 76*53ff1f6bSSadaf Ebrahimi 77*53ff1f6bSSadaf Ebrahimi```java 78*53ff1f6bSSadaf Ebrahimivoid main() { 79*53ff1f6bSSadaf Ebrahimi int total = 0; 80*53ff1f6bSSadaf Ebrahimi for (int i = 0; i < 10; i++) { 81*53ff1f6bSSadaf Ebrahimi total += i; 82*53ff1f6bSSadaf Ebrahimi } 83*53ff1f6bSSadaf Ebrahimi} 84*53ff1f6bSSadaf Ebrahimi``` 85*53ff1f6bSSadaf Ebrahimi 86*53ff1f6bSSadaf EbrahimiThe manual semicolons, line wrapping, and indentation are tedious and so JavaPoet offers APIs to 87*53ff1f6bSSadaf Ebrahimimake it easier. There's `addStatement()` which takes care of semicolons and newline, and 88*53ff1f6bSSadaf Ebrahimi`beginControlFlow()` + `endControlFlow()` which are used together for braces, newlines, and 89*53ff1f6bSSadaf Ebrahimiindentation: 90*53ff1f6bSSadaf Ebrahimi 91*53ff1f6bSSadaf Ebrahimi```java 92*53ff1f6bSSadaf EbrahimiMethodSpec main = MethodSpec.methodBuilder("main") 93*53ff1f6bSSadaf Ebrahimi .addStatement("int total = 0") 94*53ff1f6bSSadaf Ebrahimi .beginControlFlow("for (int i = 0; i < 10; i++)") 95*53ff1f6bSSadaf Ebrahimi .addStatement("total += i") 96*53ff1f6bSSadaf Ebrahimi .endControlFlow() 97*53ff1f6bSSadaf Ebrahimi .build(); 98*53ff1f6bSSadaf Ebrahimi``` 99*53ff1f6bSSadaf Ebrahimi 100*53ff1f6bSSadaf EbrahimiThis example is lame because the generated code is constant! Suppose instead of just adding 0 to 10, 101*53ff1f6bSSadaf Ebrahimiwe want to make the operation and range configurable. Here's a method that generates a method: 102*53ff1f6bSSadaf Ebrahimi 103*53ff1f6bSSadaf Ebrahimi```java 104*53ff1f6bSSadaf Ebrahimiprivate MethodSpec computeRange(String name, int from, int to, String op) { 105*53ff1f6bSSadaf Ebrahimi return MethodSpec.methodBuilder(name) 106*53ff1f6bSSadaf Ebrahimi .returns(int.class) 107*53ff1f6bSSadaf Ebrahimi .addStatement("int result = 1") 108*53ff1f6bSSadaf Ebrahimi .beginControlFlow("for (int i = " + from + "; i < " + to + "; i++)") 109*53ff1f6bSSadaf Ebrahimi .addStatement("result = result " + op + " i") 110*53ff1f6bSSadaf Ebrahimi .endControlFlow() 111*53ff1f6bSSadaf Ebrahimi .addStatement("return result") 112*53ff1f6bSSadaf Ebrahimi .build(); 113*53ff1f6bSSadaf Ebrahimi} 114*53ff1f6bSSadaf Ebrahimi``` 115*53ff1f6bSSadaf Ebrahimi 116*53ff1f6bSSadaf EbrahimiAnd here's what we get when we call `computeRange("multiply10to20", 10, 20, "*")`: 117*53ff1f6bSSadaf Ebrahimi 118*53ff1f6bSSadaf Ebrahimi```java 119*53ff1f6bSSadaf Ebrahimiint multiply10to20() { 120*53ff1f6bSSadaf Ebrahimi int result = 1; 121*53ff1f6bSSadaf Ebrahimi for (int i = 10; i < 20; i++) { 122*53ff1f6bSSadaf Ebrahimi result = result * i; 123*53ff1f6bSSadaf Ebrahimi } 124*53ff1f6bSSadaf Ebrahimi return result; 125*53ff1f6bSSadaf Ebrahimi} 126*53ff1f6bSSadaf Ebrahimi``` 127*53ff1f6bSSadaf Ebrahimi 128*53ff1f6bSSadaf EbrahimiMethods generating methods! And since JavaPoet generates source instead of bytecode, you can 129*53ff1f6bSSadaf Ebrahimiread through it to make sure it's right. 130*53ff1f6bSSadaf Ebrahimi 131*53ff1f6bSSadaf EbrahimiSome control flow statements, such as `if/else`, can have unlimited control flow possibilities. 132*53ff1f6bSSadaf EbrahimiYou can handle those options using `nextControlFlow()`: 133*53ff1f6bSSadaf Ebrahimi 134*53ff1f6bSSadaf Ebrahimi```java 135*53ff1f6bSSadaf EbrahimiMethodSpec main = MethodSpec.methodBuilder("main") 136*53ff1f6bSSadaf Ebrahimi .addStatement("long now = $T.currentTimeMillis()", System.class) 137*53ff1f6bSSadaf Ebrahimi .beginControlFlow("if ($T.currentTimeMillis() < now)", System.class) 138*53ff1f6bSSadaf Ebrahimi .addStatement("$T.out.println($S)", System.class, "Time travelling, woo hoo!") 139*53ff1f6bSSadaf Ebrahimi .nextControlFlow("else if ($T.currentTimeMillis() == now)", System.class) 140*53ff1f6bSSadaf Ebrahimi .addStatement("$T.out.println($S)", System.class, "Time stood still!") 141*53ff1f6bSSadaf Ebrahimi .nextControlFlow("else") 142*53ff1f6bSSadaf Ebrahimi .addStatement("$T.out.println($S)", System.class, "Ok, time still moving forward") 143*53ff1f6bSSadaf Ebrahimi .endControlFlow() 144*53ff1f6bSSadaf Ebrahimi .build(); 145*53ff1f6bSSadaf Ebrahimi``` 146*53ff1f6bSSadaf Ebrahimi 147*53ff1f6bSSadaf EbrahimiWhich generates: 148*53ff1f6bSSadaf Ebrahimi 149*53ff1f6bSSadaf Ebrahimi```java 150*53ff1f6bSSadaf Ebrahimivoid main() { 151*53ff1f6bSSadaf Ebrahimi long now = System.currentTimeMillis(); 152*53ff1f6bSSadaf Ebrahimi if (System.currentTimeMillis() < now) { 153*53ff1f6bSSadaf Ebrahimi System.out.println("Time travelling, woo hoo!"); 154*53ff1f6bSSadaf Ebrahimi } else if (System.currentTimeMillis() == now) { 155*53ff1f6bSSadaf Ebrahimi System.out.println("Time stood still!"); 156*53ff1f6bSSadaf Ebrahimi } else { 157*53ff1f6bSSadaf Ebrahimi System.out.println("Ok, time still moving forward"); 158*53ff1f6bSSadaf Ebrahimi } 159*53ff1f6bSSadaf Ebrahimi} 160*53ff1f6bSSadaf Ebrahimi``` 161*53ff1f6bSSadaf Ebrahimi 162*53ff1f6bSSadaf EbrahimiCatching exceptions using `try/catch` is also a use case for `nextControlFlow()`: 163*53ff1f6bSSadaf Ebrahimi 164*53ff1f6bSSadaf Ebrahimi```java 165*53ff1f6bSSadaf EbrahimiMethodSpec main = MethodSpec.methodBuilder("main") 166*53ff1f6bSSadaf Ebrahimi .beginControlFlow("try") 167*53ff1f6bSSadaf Ebrahimi .addStatement("throw new Exception($S)", "Failed") 168*53ff1f6bSSadaf Ebrahimi .nextControlFlow("catch ($T e)", Exception.class) 169*53ff1f6bSSadaf Ebrahimi .addStatement("throw new $T(e)", RuntimeException.class) 170*53ff1f6bSSadaf Ebrahimi .endControlFlow() 171*53ff1f6bSSadaf Ebrahimi .build(); 172*53ff1f6bSSadaf Ebrahimi``` 173*53ff1f6bSSadaf Ebrahimi 174*53ff1f6bSSadaf EbrahimiWhich produces: 175*53ff1f6bSSadaf Ebrahimi 176*53ff1f6bSSadaf Ebrahimi```java 177*53ff1f6bSSadaf Ebrahimivoid main() { 178*53ff1f6bSSadaf Ebrahimi try { 179*53ff1f6bSSadaf Ebrahimi throw new Exception("Failed"); 180*53ff1f6bSSadaf Ebrahimi } catch (Exception e) { 181*53ff1f6bSSadaf Ebrahimi throw new RuntimeException(e); 182*53ff1f6bSSadaf Ebrahimi } 183*53ff1f6bSSadaf Ebrahimi} 184*53ff1f6bSSadaf Ebrahimi``` 185*53ff1f6bSSadaf Ebrahimi 186*53ff1f6bSSadaf Ebrahimi### $L for Literals 187*53ff1f6bSSadaf Ebrahimi 188*53ff1f6bSSadaf EbrahimiThe string-concatenation in calls to `beginControlFlow()` and `addStatement` is distracting. Too 189*53ff1f6bSSadaf Ebrahimimany operators. To address this, JavaPoet offers a syntax inspired-by but incompatible-with 190*53ff1f6bSSadaf Ebrahimi[`String.format()`][formatter]. It accepts **`$L`** to emit a **literal** value in the output. This 191*53ff1f6bSSadaf Ebrahimiworks just like `Formatter`'s `%s`: 192*53ff1f6bSSadaf Ebrahimi 193*53ff1f6bSSadaf Ebrahimi```java 194*53ff1f6bSSadaf Ebrahimiprivate MethodSpec computeRange(String name, int from, int to, String op) { 195*53ff1f6bSSadaf Ebrahimi return MethodSpec.methodBuilder(name) 196*53ff1f6bSSadaf Ebrahimi .returns(int.class) 197*53ff1f6bSSadaf Ebrahimi .addStatement("int result = 0") 198*53ff1f6bSSadaf Ebrahimi .beginControlFlow("for (int i = $L; i < $L; i++)", from, to) 199*53ff1f6bSSadaf Ebrahimi .addStatement("result = result $L i", op) 200*53ff1f6bSSadaf Ebrahimi .endControlFlow() 201*53ff1f6bSSadaf Ebrahimi .addStatement("return result") 202*53ff1f6bSSadaf Ebrahimi .build(); 203*53ff1f6bSSadaf Ebrahimi} 204*53ff1f6bSSadaf Ebrahimi``` 205*53ff1f6bSSadaf Ebrahimi 206*53ff1f6bSSadaf EbrahimiLiterals are emitted directly to the output code with no escaping. Arguments for literals may be 207*53ff1f6bSSadaf Ebrahimistrings, primitives, and a few JavaPoet types described below. 208*53ff1f6bSSadaf Ebrahimi 209*53ff1f6bSSadaf Ebrahimi### $S for Strings 210*53ff1f6bSSadaf Ebrahimi 211*53ff1f6bSSadaf EbrahimiWhen emitting code that includes string literals, we can use **`$S`** to emit a **string**, complete 212*53ff1f6bSSadaf Ebrahimiwith wrapping quotation marks and escaping. Here's a program that emits 3 methods, each of which 213*53ff1f6bSSadaf Ebrahimireturns its own name: 214*53ff1f6bSSadaf Ebrahimi 215*53ff1f6bSSadaf Ebrahimi```java 216*53ff1f6bSSadaf Ebrahimipublic static void main(String[] args) throws Exception { 217*53ff1f6bSSadaf Ebrahimi TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") 218*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 219*53ff1f6bSSadaf Ebrahimi .addMethod(whatsMyName("slimShady")) 220*53ff1f6bSSadaf Ebrahimi .addMethod(whatsMyName("eminem")) 221*53ff1f6bSSadaf Ebrahimi .addMethod(whatsMyName("marshallMathers")) 222*53ff1f6bSSadaf Ebrahimi .build(); 223*53ff1f6bSSadaf Ebrahimi 224*53ff1f6bSSadaf Ebrahimi JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld) 225*53ff1f6bSSadaf Ebrahimi .build(); 226*53ff1f6bSSadaf Ebrahimi 227*53ff1f6bSSadaf Ebrahimi javaFile.writeTo(System.out); 228*53ff1f6bSSadaf Ebrahimi} 229*53ff1f6bSSadaf Ebrahimi 230*53ff1f6bSSadaf Ebrahimiprivate static MethodSpec whatsMyName(String name) { 231*53ff1f6bSSadaf Ebrahimi return MethodSpec.methodBuilder(name) 232*53ff1f6bSSadaf Ebrahimi .returns(String.class) 233*53ff1f6bSSadaf Ebrahimi .addStatement("return $S", name) 234*53ff1f6bSSadaf Ebrahimi .build(); 235*53ff1f6bSSadaf Ebrahimi} 236*53ff1f6bSSadaf Ebrahimi``` 237*53ff1f6bSSadaf Ebrahimi 238*53ff1f6bSSadaf EbrahimiIn this case, using `$S` gives us quotation marks: 239*53ff1f6bSSadaf Ebrahimi 240*53ff1f6bSSadaf Ebrahimi```java 241*53ff1f6bSSadaf Ebrahimipublic final class HelloWorld { 242*53ff1f6bSSadaf Ebrahimi String slimShady() { 243*53ff1f6bSSadaf Ebrahimi return "slimShady"; 244*53ff1f6bSSadaf Ebrahimi } 245*53ff1f6bSSadaf Ebrahimi 246*53ff1f6bSSadaf Ebrahimi String eminem() { 247*53ff1f6bSSadaf Ebrahimi return "eminem"; 248*53ff1f6bSSadaf Ebrahimi } 249*53ff1f6bSSadaf Ebrahimi 250*53ff1f6bSSadaf Ebrahimi String marshallMathers() { 251*53ff1f6bSSadaf Ebrahimi return "marshallMathers"; 252*53ff1f6bSSadaf Ebrahimi } 253*53ff1f6bSSadaf Ebrahimi} 254*53ff1f6bSSadaf Ebrahimi``` 255*53ff1f6bSSadaf Ebrahimi 256*53ff1f6bSSadaf Ebrahimi### $T for Types 257*53ff1f6bSSadaf Ebrahimi 258*53ff1f6bSSadaf EbrahimiWe Java programmers love our types: they make our code easier to understand. And JavaPoet is on 259*53ff1f6bSSadaf Ebrahimiboard. It has rich built-in support for types, including automatic generation of `import` 260*53ff1f6bSSadaf Ebrahimistatements. Just use **`$T`** to reference **types**: 261*53ff1f6bSSadaf Ebrahimi 262*53ff1f6bSSadaf Ebrahimi```java 263*53ff1f6bSSadaf EbrahimiMethodSpec today = MethodSpec.methodBuilder("today") 264*53ff1f6bSSadaf Ebrahimi .returns(Date.class) 265*53ff1f6bSSadaf Ebrahimi .addStatement("return new $T()", Date.class) 266*53ff1f6bSSadaf Ebrahimi .build(); 267*53ff1f6bSSadaf Ebrahimi 268*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") 269*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 270*53ff1f6bSSadaf Ebrahimi .addMethod(today) 271*53ff1f6bSSadaf Ebrahimi .build(); 272*53ff1f6bSSadaf Ebrahimi 273*53ff1f6bSSadaf EbrahimiJavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld) 274*53ff1f6bSSadaf Ebrahimi .build(); 275*53ff1f6bSSadaf Ebrahimi 276*53ff1f6bSSadaf EbrahimijavaFile.writeTo(System.out); 277*53ff1f6bSSadaf Ebrahimi``` 278*53ff1f6bSSadaf Ebrahimi 279*53ff1f6bSSadaf EbrahimiThat generates the following `.java` file, complete with the necessary `import`: 280*53ff1f6bSSadaf Ebrahimi 281*53ff1f6bSSadaf Ebrahimi```java 282*53ff1f6bSSadaf Ebrahimipackage com.example.helloworld; 283*53ff1f6bSSadaf Ebrahimi 284*53ff1f6bSSadaf Ebrahimiimport java.util.Date; 285*53ff1f6bSSadaf Ebrahimi 286*53ff1f6bSSadaf Ebrahimipublic final class HelloWorld { 287*53ff1f6bSSadaf Ebrahimi Date today() { 288*53ff1f6bSSadaf Ebrahimi return new Date(); 289*53ff1f6bSSadaf Ebrahimi } 290*53ff1f6bSSadaf Ebrahimi} 291*53ff1f6bSSadaf Ebrahimi``` 292*53ff1f6bSSadaf Ebrahimi 293*53ff1f6bSSadaf EbrahimiWe passed `Date.class` to reference a class that just-so-happens to be available when we're 294*53ff1f6bSSadaf Ebrahimigenerating code. This doesn't need to be the case. Here's a similar example, but this one 295*53ff1f6bSSadaf Ebrahimireferences a class that doesn't exist (yet): 296*53ff1f6bSSadaf Ebrahimi 297*53ff1f6bSSadaf Ebrahimi```java 298*53ff1f6bSSadaf EbrahimiClassName hoverboard = ClassName.get("com.mattel", "Hoverboard"); 299*53ff1f6bSSadaf Ebrahimi 300*53ff1f6bSSadaf EbrahimiMethodSpec today = MethodSpec.methodBuilder("tomorrow") 301*53ff1f6bSSadaf Ebrahimi .returns(hoverboard) 302*53ff1f6bSSadaf Ebrahimi .addStatement("return new $T()", hoverboard) 303*53ff1f6bSSadaf Ebrahimi .build(); 304*53ff1f6bSSadaf Ebrahimi``` 305*53ff1f6bSSadaf Ebrahimi 306*53ff1f6bSSadaf EbrahimiAnd that not-yet-existent class is imported as well: 307*53ff1f6bSSadaf Ebrahimi 308*53ff1f6bSSadaf Ebrahimi```java 309*53ff1f6bSSadaf Ebrahimipackage com.example.helloworld; 310*53ff1f6bSSadaf Ebrahimi 311*53ff1f6bSSadaf Ebrahimiimport com.mattel.Hoverboard; 312*53ff1f6bSSadaf Ebrahimi 313*53ff1f6bSSadaf Ebrahimipublic final class HelloWorld { 314*53ff1f6bSSadaf Ebrahimi Hoverboard tomorrow() { 315*53ff1f6bSSadaf Ebrahimi return new Hoverboard(); 316*53ff1f6bSSadaf Ebrahimi } 317*53ff1f6bSSadaf Ebrahimi} 318*53ff1f6bSSadaf Ebrahimi``` 319*53ff1f6bSSadaf Ebrahimi 320*53ff1f6bSSadaf EbrahimiThe `ClassName` type is very important, and you'll need it frequently when you're using JavaPoet. 321*53ff1f6bSSadaf EbrahimiIt can identify any _declared_ class. Declared types are just the beginning of Java's rich type 322*53ff1f6bSSadaf Ebrahimisystem: we also have arrays, parameterized types, wildcard types, and type variables. JavaPoet has 323*53ff1f6bSSadaf Ebrahimiclasses for building each of these: 324*53ff1f6bSSadaf Ebrahimi 325*53ff1f6bSSadaf Ebrahimi```java 326*53ff1f6bSSadaf EbrahimiClassName hoverboard = ClassName.get("com.mattel", "Hoverboard"); 327*53ff1f6bSSadaf EbrahimiClassName list = ClassName.get("java.util", "List"); 328*53ff1f6bSSadaf EbrahimiClassName arrayList = ClassName.get("java.util", "ArrayList"); 329*53ff1f6bSSadaf EbrahimiTypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard); 330*53ff1f6bSSadaf Ebrahimi 331*53ff1f6bSSadaf EbrahimiMethodSpec beyond = MethodSpec.methodBuilder("beyond") 332*53ff1f6bSSadaf Ebrahimi .returns(listOfHoverboards) 333*53ff1f6bSSadaf Ebrahimi .addStatement("$T result = new $T<>()", listOfHoverboards, arrayList) 334*53ff1f6bSSadaf Ebrahimi .addStatement("result.add(new $T())", hoverboard) 335*53ff1f6bSSadaf Ebrahimi .addStatement("result.add(new $T())", hoverboard) 336*53ff1f6bSSadaf Ebrahimi .addStatement("result.add(new $T())", hoverboard) 337*53ff1f6bSSadaf Ebrahimi .addStatement("return result") 338*53ff1f6bSSadaf Ebrahimi .build(); 339*53ff1f6bSSadaf Ebrahimi``` 340*53ff1f6bSSadaf Ebrahimi 341*53ff1f6bSSadaf EbrahimiJavaPoet will decompose each type and import its components where possible. 342*53ff1f6bSSadaf Ebrahimi 343*53ff1f6bSSadaf Ebrahimi```java 344*53ff1f6bSSadaf Ebrahimipackage com.example.helloworld; 345*53ff1f6bSSadaf Ebrahimi 346*53ff1f6bSSadaf Ebrahimiimport com.mattel.Hoverboard; 347*53ff1f6bSSadaf Ebrahimiimport java.util.ArrayList; 348*53ff1f6bSSadaf Ebrahimiimport java.util.List; 349*53ff1f6bSSadaf Ebrahimi 350*53ff1f6bSSadaf Ebrahimipublic final class HelloWorld { 351*53ff1f6bSSadaf Ebrahimi List<Hoverboard> beyond() { 352*53ff1f6bSSadaf Ebrahimi List<Hoverboard> result = new ArrayList<>(); 353*53ff1f6bSSadaf Ebrahimi result.add(new Hoverboard()); 354*53ff1f6bSSadaf Ebrahimi result.add(new Hoverboard()); 355*53ff1f6bSSadaf Ebrahimi result.add(new Hoverboard()); 356*53ff1f6bSSadaf Ebrahimi return result; 357*53ff1f6bSSadaf Ebrahimi } 358*53ff1f6bSSadaf Ebrahimi} 359*53ff1f6bSSadaf Ebrahimi``` 360*53ff1f6bSSadaf Ebrahimi 361*53ff1f6bSSadaf Ebrahimi#### Import static 362*53ff1f6bSSadaf Ebrahimi 363*53ff1f6bSSadaf EbrahimiJavaPoet supports `import static`. It does it via explicitly collecting type member names. Let's 364*53ff1f6bSSadaf Ebrahimienhance the previous example with some static sugar: 365*53ff1f6bSSadaf Ebrahimi 366*53ff1f6bSSadaf Ebrahimi```java 367*53ff1f6bSSadaf Ebrahimi... 368*53ff1f6bSSadaf EbrahimiClassName namedBoards = ClassName.get("com.mattel", "Hoverboard", "Boards"); 369*53ff1f6bSSadaf Ebrahimi 370*53ff1f6bSSadaf EbrahimiMethodSpec beyond = MethodSpec.methodBuilder("beyond") 371*53ff1f6bSSadaf Ebrahimi .returns(listOfHoverboards) 372*53ff1f6bSSadaf Ebrahimi .addStatement("$T result = new $T<>()", listOfHoverboards, arrayList) 373*53ff1f6bSSadaf Ebrahimi .addStatement("result.add($T.createNimbus(2000))", hoverboard) 374*53ff1f6bSSadaf Ebrahimi .addStatement("result.add($T.createNimbus(\"2001\"))", hoverboard) 375*53ff1f6bSSadaf Ebrahimi .addStatement("result.add($T.createNimbus($T.THUNDERBOLT))", hoverboard, namedBoards) 376*53ff1f6bSSadaf Ebrahimi .addStatement("$T.sort(result)", Collections.class) 377*53ff1f6bSSadaf Ebrahimi .addStatement("return result.isEmpty() ? $T.emptyList() : result", Collections.class) 378*53ff1f6bSSadaf Ebrahimi .build(); 379*53ff1f6bSSadaf Ebrahimi 380*53ff1f6bSSadaf EbrahimiTypeSpec hello = TypeSpec.classBuilder("HelloWorld") 381*53ff1f6bSSadaf Ebrahimi .addMethod(beyond) 382*53ff1f6bSSadaf Ebrahimi .build(); 383*53ff1f6bSSadaf Ebrahimi 384*53ff1f6bSSadaf EbrahimiJavaFile.builder("com.example.helloworld", hello) 385*53ff1f6bSSadaf Ebrahimi .addStaticImport(hoverboard, "createNimbus") 386*53ff1f6bSSadaf Ebrahimi .addStaticImport(namedBoards, "*") 387*53ff1f6bSSadaf Ebrahimi .addStaticImport(Collections.class, "*") 388*53ff1f6bSSadaf Ebrahimi .build(); 389*53ff1f6bSSadaf Ebrahimi``` 390*53ff1f6bSSadaf Ebrahimi 391*53ff1f6bSSadaf EbrahimiJavaPoet will first add your `import static` block to the file as configured, match and mangle 392*53ff1f6bSSadaf Ebrahimiall calls accordingly and also import all other types as needed. 393*53ff1f6bSSadaf Ebrahimi 394*53ff1f6bSSadaf Ebrahimi```java 395*53ff1f6bSSadaf Ebrahimipackage com.example.helloworld; 396*53ff1f6bSSadaf Ebrahimi 397*53ff1f6bSSadaf Ebrahimiimport static com.mattel.Hoverboard.Boards.*; 398*53ff1f6bSSadaf Ebrahimiimport static com.mattel.Hoverboard.createNimbus; 399*53ff1f6bSSadaf Ebrahimiimport static java.util.Collections.*; 400*53ff1f6bSSadaf Ebrahimi 401*53ff1f6bSSadaf Ebrahimiimport com.mattel.Hoverboard; 402*53ff1f6bSSadaf Ebrahimiimport java.util.ArrayList; 403*53ff1f6bSSadaf Ebrahimiimport java.util.List; 404*53ff1f6bSSadaf Ebrahimi 405*53ff1f6bSSadaf Ebrahimiclass HelloWorld { 406*53ff1f6bSSadaf Ebrahimi List<Hoverboard> beyond() { 407*53ff1f6bSSadaf Ebrahimi List<Hoverboard> result = new ArrayList<>(); 408*53ff1f6bSSadaf Ebrahimi result.add(createNimbus(2000)); 409*53ff1f6bSSadaf Ebrahimi result.add(createNimbus("2001")); 410*53ff1f6bSSadaf Ebrahimi result.add(createNimbus(THUNDERBOLT)); 411*53ff1f6bSSadaf Ebrahimi sort(result); 412*53ff1f6bSSadaf Ebrahimi return result.isEmpty() ? emptyList() : result; 413*53ff1f6bSSadaf Ebrahimi } 414*53ff1f6bSSadaf Ebrahimi} 415*53ff1f6bSSadaf Ebrahimi``` 416*53ff1f6bSSadaf Ebrahimi 417*53ff1f6bSSadaf Ebrahimi### $N for Names 418*53ff1f6bSSadaf Ebrahimi 419*53ff1f6bSSadaf EbrahimiGenerated code is often self-referential. Use **`$N`** to refer to another generated declaration by 420*53ff1f6bSSadaf Ebrahimiits name. Here's a method that calls another: 421*53ff1f6bSSadaf Ebrahimi 422*53ff1f6bSSadaf Ebrahimi```java 423*53ff1f6bSSadaf Ebrahimipublic String byteToHex(int b) { 424*53ff1f6bSSadaf Ebrahimi char[] result = new char[2]; 425*53ff1f6bSSadaf Ebrahimi result[0] = hexDigit((b >>> 4) & 0xf); 426*53ff1f6bSSadaf Ebrahimi result[1] = hexDigit(b & 0xf); 427*53ff1f6bSSadaf Ebrahimi return new String(result); 428*53ff1f6bSSadaf Ebrahimi} 429*53ff1f6bSSadaf Ebrahimi 430*53ff1f6bSSadaf Ebrahimipublic char hexDigit(int i) { 431*53ff1f6bSSadaf Ebrahimi return (char) (i < 10 ? i + '0' : i - 10 + 'a'); 432*53ff1f6bSSadaf Ebrahimi} 433*53ff1f6bSSadaf Ebrahimi``` 434*53ff1f6bSSadaf Ebrahimi 435*53ff1f6bSSadaf EbrahimiWhen generating the code above, we pass the `hexDigit()` method as an argument to the `byteToHex()` 436*53ff1f6bSSadaf Ebrahimimethod using `$N`: 437*53ff1f6bSSadaf Ebrahimi 438*53ff1f6bSSadaf Ebrahimi```java 439*53ff1f6bSSadaf EbrahimiMethodSpec hexDigit = MethodSpec.methodBuilder("hexDigit") 440*53ff1f6bSSadaf Ebrahimi .addParameter(int.class, "i") 441*53ff1f6bSSadaf Ebrahimi .returns(char.class) 442*53ff1f6bSSadaf Ebrahimi .addStatement("return (char) (i < 10 ? i + '0' : i - 10 + 'a')") 443*53ff1f6bSSadaf Ebrahimi .build(); 444*53ff1f6bSSadaf Ebrahimi 445*53ff1f6bSSadaf EbrahimiMethodSpec byteToHex = MethodSpec.methodBuilder("byteToHex") 446*53ff1f6bSSadaf Ebrahimi .addParameter(int.class, "b") 447*53ff1f6bSSadaf Ebrahimi .returns(String.class) 448*53ff1f6bSSadaf Ebrahimi .addStatement("char[] result = new char[2]") 449*53ff1f6bSSadaf Ebrahimi .addStatement("result[0] = $N((b >>> 4) & 0xf)", hexDigit) 450*53ff1f6bSSadaf Ebrahimi .addStatement("result[1] = $N(b & 0xf)", hexDigit) 451*53ff1f6bSSadaf Ebrahimi .addStatement("return new String(result)") 452*53ff1f6bSSadaf Ebrahimi .build(); 453*53ff1f6bSSadaf Ebrahimi``` 454*53ff1f6bSSadaf Ebrahimi 455*53ff1f6bSSadaf Ebrahimi### Code block format strings 456*53ff1f6bSSadaf Ebrahimi 457*53ff1f6bSSadaf EbrahimiCode blocks may specify the values for their placeholders in a few ways. Only one style may be used 458*53ff1f6bSSadaf Ebrahimifor each operation on a code block. 459*53ff1f6bSSadaf Ebrahimi 460*53ff1f6bSSadaf Ebrahimi#### Relative Arguments 461*53ff1f6bSSadaf Ebrahimi 462*53ff1f6bSSadaf EbrahimiPass an argument value for each placeholder in the format string to `CodeBlock.add()`. In each 463*53ff1f6bSSadaf Ebrahimiexample, we generate code to say "I ate 3 tacos" 464*53ff1f6bSSadaf Ebrahimi 465*53ff1f6bSSadaf Ebrahimi```java 466*53ff1f6bSSadaf EbrahimiCodeBlock.builder().add("I ate $L $L", 3, "tacos") 467*53ff1f6bSSadaf Ebrahimi``` 468*53ff1f6bSSadaf Ebrahimi 469*53ff1f6bSSadaf Ebrahimi#### Positional Arguments 470*53ff1f6bSSadaf Ebrahimi 471*53ff1f6bSSadaf EbrahimiPlace an integer index (1-based) before the placeholder in the format string to specify which 472*53ff1f6bSSadaf Ebrahimi argument to use. 473*53ff1f6bSSadaf Ebrahimi 474*53ff1f6bSSadaf Ebrahimi```java 475*53ff1f6bSSadaf EbrahimiCodeBlock.builder().add("I ate $2L $1L", "tacos", 3) 476*53ff1f6bSSadaf Ebrahimi``` 477*53ff1f6bSSadaf Ebrahimi 478*53ff1f6bSSadaf Ebrahimi#### Named Arguments 479*53ff1f6bSSadaf Ebrahimi 480*53ff1f6bSSadaf EbrahimiUse the syntax `$argumentName:X` where `X` is the format character and call `CodeBlock.addNamed()` 481*53ff1f6bSSadaf Ebrahimiwith a map containing all argument keys in the format string. Argument names use characters in 482*53ff1f6bSSadaf Ebrahimi`a-z`, `A-Z`, `0-9`, and `_`, and must start with a lowercase character. 483*53ff1f6bSSadaf Ebrahimi 484*53ff1f6bSSadaf Ebrahimi```java 485*53ff1f6bSSadaf EbrahimiMap<String, Object> map = new LinkedHashMap<>(); 486*53ff1f6bSSadaf Ebrahimimap.put("food", "tacos"); 487*53ff1f6bSSadaf Ebrahimimap.put("count", 3); 488*53ff1f6bSSadaf EbrahimiCodeBlock.builder().addNamed("I ate $count:L $food:L", map) 489*53ff1f6bSSadaf Ebrahimi``` 490*53ff1f6bSSadaf Ebrahimi 491*53ff1f6bSSadaf Ebrahimi### Methods 492*53ff1f6bSSadaf Ebrahimi 493*53ff1f6bSSadaf EbrahimiAll of the above methods have a code body. Use `Modifiers.ABSTRACT` to get a method without any 494*53ff1f6bSSadaf Ebrahimibody. This is only legal if the enclosing class is either abstract or an interface. 495*53ff1f6bSSadaf Ebrahimi 496*53ff1f6bSSadaf Ebrahimi```java 497*53ff1f6bSSadaf EbrahimiMethodSpec flux = MethodSpec.methodBuilder("flux") 498*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.ABSTRACT, Modifier.PROTECTED) 499*53ff1f6bSSadaf Ebrahimi .build(); 500*53ff1f6bSSadaf Ebrahimi 501*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") 502*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) 503*53ff1f6bSSadaf Ebrahimi .addMethod(flux) 504*53ff1f6bSSadaf Ebrahimi .build(); 505*53ff1f6bSSadaf Ebrahimi``` 506*53ff1f6bSSadaf Ebrahimi 507*53ff1f6bSSadaf EbrahimiWhich generates this: 508*53ff1f6bSSadaf Ebrahimi 509*53ff1f6bSSadaf Ebrahimi```java 510*53ff1f6bSSadaf Ebrahimipublic abstract class HelloWorld { 511*53ff1f6bSSadaf Ebrahimi protected abstract void flux(); 512*53ff1f6bSSadaf Ebrahimi} 513*53ff1f6bSSadaf Ebrahimi``` 514*53ff1f6bSSadaf Ebrahimi 515*53ff1f6bSSadaf EbrahimiThe other modifiers work where permitted. Note that when specifying modifiers, JavaPoet uses 516*53ff1f6bSSadaf Ebrahimi[`javax.lang.model.element.Modifier`][modifier], a class that is not available on Android. This 517*53ff1f6bSSadaf Ebrahimilimitation applies to code-generating-code only; the output code runs everywhere: JVMs, Android, 518*53ff1f6bSSadaf Ebrahimiand GWT. 519*53ff1f6bSSadaf Ebrahimi 520*53ff1f6bSSadaf EbrahimiMethods also have parameters, exceptions, varargs, Javadoc, annotations, type variables, and a 521*53ff1f6bSSadaf Ebrahimireturn type. All of these are configured with `MethodSpec.Builder`. 522*53ff1f6bSSadaf Ebrahimi 523*53ff1f6bSSadaf Ebrahimi### Constructors 524*53ff1f6bSSadaf Ebrahimi 525*53ff1f6bSSadaf Ebrahimi`MethodSpec` is a slight misnomer; it can also be used for constructors: 526*53ff1f6bSSadaf Ebrahimi 527*53ff1f6bSSadaf Ebrahimi```java 528*53ff1f6bSSadaf EbrahimiMethodSpec flux = MethodSpec.constructorBuilder() 529*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 530*53ff1f6bSSadaf Ebrahimi .addParameter(String.class, "greeting") 531*53ff1f6bSSadaf Ebrahimi .addStatement("this.$N = $N", "greeting", "greeting") 532*53ff1f6bSSadaf Ebrahimi .build(); 533*53ff1f6bSSadaf Ebrahimi 534*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") 535*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 536*53ff1f6bSSadaf Ebrahimi .addField(String.class, "greeting", Modifier.PRIVATE, Modifier.FINAL) 537*53ff1f6bSSadaf Ebrahimi .addMethod(flux) 538*53ff1f6bSSadaf Ebrahimi .build(); 539*53ff1f6bSSadaf Ebrahimi``` 540*53ff1f6bSSadaf Ebrahimi 541*53ff1f6bSSadaf EbrahimiWhich generates this: 542*53ff1f6bSSadaf Ebrahimi 543*53ff1f6bSSadaf Ebrahimi```java 544*53ff1f6bSSadaf Ebrahimipublic class HelloWorld { 545*53ff1f6bSSadaf Ebrahimi private final String greeting; 546*53ff1f6bSSadaf Ebrahimi 547*53ff1f6bSSadaf Ebrahimi public HelloWorld(String greeting) { 548*53ff1f6bSSadaf Ebrahimi this.greeting = greeting; 549*53ff1f6bSSadaf Ebrahimi } 550*53ff1f6bSSadaf Ebrahimi} 551*53ff1f6bSSadaf Ebrahimi``` 552*53ff1f6bSSadaf Ebrahimi 553*53ff1f6bSSadaf EbrahimiFor the most part, constructors work just like methods. When emitting code, JavaPoet will place 554*53ff1f6bSSadaf Ebrahimiconstructors before methods in the output file. 555*53ff1f6bSSadaf Ebrahimi 556*53ff1f6bSSadaf Ebrahimi### Parameters 557*53ff1f6bSSadaf Ebrahimi 558*53ff1f6bSSadaf EbrahimiDeclare parameters on methods and constructors with either `ParameterSpec.builder()` or 559*53ff1f6bSSadaf Ebrahimi`MethodSpec`'s convenient `addParameter()` API: 560*53ff1f6bSSadaf Ebrahimi 561*53ff1f6bSSadaf Ebrahimi```java 562*53ff1f6bSSadaf EbrahimiParameterSpec android = ParameterSpec.builder(String.class, "android") 563*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.FINAL) 564*53ff1f6bSSadaf Ebrahimi .build(); 565*53ff1f6bSSadaf Ebrahimi 566*53ff1f6bSSadaf EbrahimiMethodSpec welcomeOverlords = MethodSpec.methodBuilder("welcomeOverlords") 567*53ff1f6bSSadaf Ebrahimi .addParameter(android) 568*53ff1f6bSSadaf Ebrahimi .addParameter(String.class, "robot", Modifier.FINAL) 569*53ff1f6bSSadaf Ebrahimi .build(); 570*53ff1f6bSSadaf Ebrahimi``` 571*53ff1f6bSSadaf Ebrahimi 572*53ff1f6bSSadaf EbrahimiThough the code above to generate `android` and `robot` parameters is different, the output is the 573*53ff1f6bSSadaf Ebrahimisame: 574*53ff1f6bSSadaf Ebrahimi 575*53ff1f6bSSadaf Ebrahimi```java 576*53ff1f6bSSadaf Ebrahimivoid welcomeOverlords(final String android, final String robot) { 577*53ff1f6bSSadaf Ebrahimi} 578*53ff1f6bSSadaf Ebrahimi``` 579*53ff1f6bSSadaf Ebrahimi 580*53ff1f6bSSadaf EbrahimiThe extended `Builder` form is necessary when the parameter has annotations (such as `@Nullable`). 581*53ff1f6bSSadaf Ebrahimi 582*53ff1f6bSSadaf Ebrahimi### Fields 583*53ff1f6bSSadaf Ebrahimi 584*53ff1f6bSSadaf EbrahimiLike parameters, fields can be created either with builders or by using convenient helper methods: 585*53ff1f6bSSadaf Ebrahimi 586*53ff1f6bSSadaf Ebrahimi```java 587*53ff1f6bSSadaf EbrahimiFieldSpec android = FieldSpec.builder(String.class, "android") 588*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PRIVATE, Modifier.FINAL) 589*53ff1f6bSSadaf Ebrahimi .build(); 590*53ff1f6bSSadaf Ebrahimi 591*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") 592*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 593*53ff1f6bSSadaf Ebrahimi .addField(android) 594*53ff1f6bSSadaf Ebrahimi .addField(String.class, "robot", Modifier.PRIVATE, Modifier.FINAL) 595*53ff1f6bSSadaf Ebrahimi .build(); 596*53ff1f6bSSadaf Ebrahimi``` 597*53ff1f6bSSadaf Ebrahimi 598*53ff1f6bSSadaf EbrahimiWhich generates: 599*53ff1f6bSSadaf Ebrahimi 600*53ff1f6bSSadaf Ebrahimi```java 601*53ff1f6bSSadaf Ebrahimipublic class HelloWorld { 602*53ff1f6bSSadaf Ebrahimi private final String android; 603*53ff1f6bSSadaf Ebrahimi 604*53ff1f6bSSadaf Ebrahimi private final String robot; 605*53ff1f6bSSadaf Ebrahimi} 606*53ff1f6bSSadaf Ebrahimi``` 607*53ff1f6bSSadaf Ebrahimi 608*53ff1f6bSSadaf EbrahimiThe extended `Builder` form is necessary when a field has Javadoc, annotations, or a field 609*53ff1f6bSSadaf Ebrahimiinitializer. Field initializers use the same [`String.format()`][formatter]-like syntax as the code 610*53ff1f6bSSadaf Ebrahimiblocks above: 611*53ff1f6bSSadaf Ebrahimi 612*53ff1f6bSSadaf Ebrahimi```java 613*53ff1f6bSSadaf EbrahimiFieldSpec android = FieldSpec.builder(String.class, "android") 614*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PRIVATE, Modifier.FINAL) 615*53ff1f6bSSadaf Ebrahimi .initializer("$S + $L", "Lollipop v.", 5.0d) 616*53ff1f6bSSadaf Ebrahimi .build(); 617*53ff1f6bSSadaf Ebrahimi``` 618*53ff1f6bSSadaf Ebrahimi 619*53ff1f6bSSadaf EbrahimiWhich generates: 620*53ff1f6bSSadaf Ebrahimi 621*53ff1f6bSSadaf Ebrahimi```java 622*53ff1f6bSSadaf Ebrahimiprivate final String android = "Lollipop v." + 5.0; 623*53ff1f6bSSadaf Ebrahimi``` 624*53ff1f6bSSadaf Ebrahimi 625*53ff1f6bSSadaf Ebrahimi### Interfaces 626*53ff1f6bSSadaf Ebrahimi 627*53ff1f6bSSadaf EbrahimiJavaPoet has no trouble with interfaces. Note that interface methods must always be `PUBLIC 628*53ff1f6bSSadaf EbrahimiABSTRACT` and interface fields must always be `PUBLIC STATIC FINAL`. These modifiers are necessary 629*53ff1f6bSSadaf Ebrahimiwhen defining the interface: 630*53ff1f6bSSadaf Ebrahimi 631*53ff1f6bSSadaf Ebrahimi```java 632*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.interfaceBuilder("HelloWorld") 633*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 634*53ff1f6bSSadaf Ebrahimi .addField(FieldSpec.builder(String.class, "ONLY_THING_THAT_IS_CONSTANT") 635*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) 636*53ff1f6bSSadaf Ebrahimi .initializer("$S", "change") 637*53ff1f6bSSadaf Ebrahimi .build()) 638*53ff1f6bSSadaf Ebrahimi .addMethod(MethodSpec.methodBuilder("beep") 639*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) 640*53ff1f6bSSadaf Ebrahimi .build()) 641*53ff1f6bSSadaf Ebrahimi .build(); 642*53ff1f6bSSadaf Ebrahimi``` 643*53ff1f6bSSadaf Ebrahimi 644*53ff1f6bSSadaf EbrahimiBut these modifiers are omitted when the code is generated. These are the defaults so we don't need 645*53ff1f6bSSadaf Ebrahimito include them for `javac`'s benefit! 646*53ff1f6bSSadaf Ebrahimi 647*53ff1f6bSSadaf Ebrahimi```java 648*53ff1f6bSSadaf Ebrahimipublic interface HelloWorld { 649*53ff1f6bSSadaf Ebrahimi String ONLY_THING_THAT_IS_CONSTANT = "change"; 650*53ff1f6bSSadaf Ebrahimi 651*53ff1f6bSSadaf Ebrahimi void beep(); 652*53ff1f6bSSadaf Ebrahimi} 653*53ff1f6bSSadaf Ebrahimi``` 654*53ff1f6bSSadaf Ebrahimi 655*53ff1f6bSSadaf Ebrahimi### Enums 656*53ff1f6bSSadaf Ebrahimi 657*53ff1f6bSSadaf EbrahimiUse `enumBuilder` to create the enum type, and `addEnumConstant()` for each value: 658*53ff1f6bSSadaf Ebrahimi 659*53ff1f6bSSadaf Ebrahimi```java 660*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo") 661*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 662*53ff1f6bSSadaf Ebrahimi .addEnumConstant("ROCK") 663*53ff1f6bSSadaf Ebrahimi .addEnumConstant("SCISSORS") 664*53ff1f6bSSadaf Ebrahimi .addEnumConstant("PAPER") 665*53ff1f6bSSadaf Ebrahimi .build(); 666*53ff1f6bSSadaf Ebrahimi``` 667*53ff1f6bSSadaf Ebrahimi 668*53ff1f6bSSadaf EbrahimiTo generate this: 669*53ff1f6bSSadaf Ebrahimi 670*53ff1f6bSSadaf Ebrahimi```java 671*53ff1f6bSSadaf Ebrahimipublic enum Roshambo { 672*53ff1f6bSSadaf Ebrahimi ROCK, 673*53ff1f6bSSadaf Ebrahimi 674*53ff1f6bSSadaf Ebrahimi SCISSORS, 675*53ff1f6bSSadaf Ebrahimi 676*53ff1f6bSSadaf Ebrahimi PAPER 677*53ff1f6bSSadaf Ebrahimi} 678*53ff1f6bSSadaf Ebrahimi``` 679*53ff1f6bSSadaf Ebrahimi 680*53ff1f6bSSadaf EbrahimiFancy enums are supported, where the enum values override methods or call a superclass constructor. 681*53ff1f6bSSadaf EbrahimiHere's a comprehensive example: 682*53ff1f6bSSadaf Ebrahimi 683*53ff1f6bSSadaf Ebrahimi```java 684*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo") 685*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 686*53ff1f6bSSadaf Ebrahimi .addEnumConstant("ROCK", TypeSpec.anonymousClassBuilder("$S", "fist") 687*53ff1f6bSSadaf Ebrahimi .addMethod(MethodSpec.methodBuilder("toString") 688*53ff1f6bSSadaf Ebrahimi .addAnnotation(Override.class) 689*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 690*53ff1f6bSSadaf Ebrahimi .addStatement("return $S", "avalanche!") 691*53ff1f6bSSadaf Ebrahimi .returns(String.class) 692*53ff1f6bSSadaf Ebrahimi .build()) 693*53ff1f6bSSadaf Ebrahimi .build()) 694*53ff1f6bSSadaf Ebrahimi .addEnumConstant("SCISSORS", TypeSpec.anonymousClassBuilder("$S", "peace") 695*53ff1f6bSSadaf Ebrahimi .build()) 696*53ff1f6bSSadaf Ebrahimi .addEnumConstant("PAPER", TypeSpec.anonymousClassBuilder("$S", "flat") 697*53ff1f6bSSadaf Ebrahimi .build()) 698*53ff1f6bSSadaf Ebrahimi .addField(String.class, "handsign", Modifier.PRIVATE, Modifier.FINAL) 699*53ff1f6bSSadaf Ebrahimi .addMethod(MethodSpec.constructorBuilder() 700*53ff1f6bSSadaf Ebrahimi .addParameter(String.class, "handsign") 701*53ff1f6bSSadaf Ebrahimi .addStatement("this.$N = $N", "handsign", "handsign") 702*53ff1f6bSSadaf Ebrahimi .build()) 703*53ff1f6bSSadaf Ebrahimi .build(); 704*53ff1f6bSSadaf Ebrahimi``` 705*53ff1f6bSSadaf Ebrahimi 706*53ff1f6bSSadaf EbrahimiWhich generates this: 707*53ff1f6bSSadaf Ebrahimi 708*53ff1f6bSSadaf Ebrahimi```java 709*53ff1f6bSSadaf Ebrahimipublic enum Roshambo { 710*53ff1f6bSSadaf Ebrahimi ROCK("fist") { 711*53ff1f6bSSadaf Ebrahimi @Override 712*53ff1f6bSSadaf Ebrahimi public String toString() { 713*53ff1f6bSSadaf Ebrahimi return "avalanche!"; 714*53ff1f6bSSadaf Ebrahimi } 715*53ff1f6bSSadaf Ebrahimi }, 716*53ff1f6bSSadaf Ebrahimi 717*53ff1f6bSSadaf Ebrahimi SCISSORS("peace"), 718*53ff1f6bSSadaf Ebrahimi 719*53ff1f6bSSadaf Ebrahimi PAPER("flat"); 720*53ff1f6bSSadaf Ebrahimi 721*53ff1f6bSSadaf Ebrahimi private final String handsign; 722*53ff1f6bSSadaf Ebrahimi 723*53ff1f6bSSadaf Ebrahimi Roshambo(String handsign) { 724*53ff1f6bSSadaf Ebrahimi this.handsign = handsign; 725*53ff1f6bSSadaf Ebrahimi } 726*53ff1f6bSSadaf Ebrahimi} 727*53ff1f6bSSadaf Ebrahimi``` 728*53ff1f6bSSadaf Ebrahimi 729*53ff1f6bSSadaf Ebrahimi### Anonymous Inner Classes 730*53ff1f6bSSadaf Ebrahimi 731*53ff1f6bSSadaf EbrahimiIn the enum code, we used `TypeSpec.anonymousInnerClass()`. Anonymous inner classes can also be used in 732*53ff1f6bSSadaf Ebrahimicode blocks. They are values that can be referenced with `$L`: 733*53ff1f6bSSadaf Ebrahimi 734*53ff1f6bSSadaf Ebrahimi```java 735*53ff1f6bSSadaf EbrahimiTypeSpec comparator = TypeSpec.anonymousClassBuilder("") 736*53ff1f6bSSadaf Ebrahimi .addSuperinterface(ParameterizedTypeName.get(Comparator.class, String.class)) 737*53ff1f6bSSadaf Ebrahimi .addMethod(MethodSpec.methodBuilder("compare") 738*53ff1f6bSSadaf Ebrahimi .addAnnotation(Override.class) 739*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 740*53ff1f6bSSadaf Ebrahimi .addParameter(String.class, "a") 741*53ff1f6bSSadaf Ebrahimi .addParameter(String.class, "b") 742*53ff1f6bSSadaf Ebrahimi .returns(int.class) 743*53ff1f6bSSadaf Ebrahimi .addStatement("return $N.length() - $N.length()", "a", "b") 744*53ff1f6bSSadaf Ebrahimi .build()) 745*53ff1f6bSSadaf Ebrahimi .build(); 746*53ff1f6bSSadaf Ebrahimi 747*53ff1f6bSSadaf EbrahimiTypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") 748*53ff1f6bSSadaf Ebrahimi .addMethod(MethodSpec.methodBuilder("sortByLength") 749*53ff1f6bSSadaf Ebrahimi .addParameter(ParameterizedTypeName.get(List.class, String.class), "strings") 750*53ff1f6bSSadaf Ebrahimi .addStatement("$T.sort($N, $L)", Collections.class, "strings", comparator) 751*53ff1f6bSSadaf Ebrahimi .build()) 752*53ff1f6bSSadaf Ebrahimi .build(); 753*53ff1f6bSSadaf Ebrahimi``` 754*53ff1f6bSSadaf Ebrahimi 755*53ff1f6bSSadaf EbrahimiThis generates a method that contains a class that contains a method: 756*53ff1f6bSSadaf Ebrahimi 757*53ff1f6bSSadaf Ebrahimi```java 758*53ff1f6bSSadaf Ebrahimivoid sortByLength(List<String> strings) { 759*53ff1f6bSSadaf Ebrahimi Collections.sort(strings, new Comparator<String>() { 760*53ff1f6bSSadaf Ebrahimi @Override 761*53ff1f6bSSadaf Ebrahimi public int compare(String a, String b) { 762*53ff1f6bSSadaf Ebrahimi return a.length() - b.length(); 763*53ff1f6bSSadaf Ebrahimi } 764*53ff1f6bSSadaf Ebrahimi }); 765*53ff1f6bSSadaf Ebrahimi} 766*53ff1f6bSSadaf Ebrahimi``` 767*53ff1f6bSSadaf Ebrahimi 768*53ff1f6bSSadaf EbrahimiOne particularly tricky part of defining anonymous inner classes is the arguments to the superclass 769*53ff1f6bSSadaf Ebrahimiconstructor. In the above code we're passing the empty string for no arguments: 770*53ff1f6bSSadaf Ebrahimi`TypeSpec.anonymousClassBuilder("")`. To pass different parameters use JavaPoet's code block 771*53ff1f6bSSadaf Ebrahimisyntax with commas to separate arguments. 772*53ff1f6bSSadaf Ebrahimi 773*53ff1f6bSSadaf Ebrahimi 774*53ff1f6bSSadaf Ebrahimi### Annotations 775*53ff1f6bSSadaf Ebrahimi 776*53ff1f6bSSadaf EbrahimiSimple annotations are easy: 777*53ff1f6bSSadaf Ebrahimi 778*53ff1f6bSSadaf Ebrahimi```java 779*53ff1f6bSSadaf EbrahimiMethodSpec toString = MethodSpec.methodBuilder("toString") 780*53ff1f6bSSadaf Ebrahimi .addAnnotation(Override.class) 781*53ff1f6bSSadaf Ebrahimi .returns(String.class) 782*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC) 783*53ff1f6bSSadaf Ebrahimi .addStatement("return $S", "Hoverboard") 784*53ff1f6bSSadaf Ebrahimi .build(); 785*53ff1f6bSSadaf Ebrahimi``` 786*53ff1f6bSSadaf Ebrahimi 787*53ff1f6bSSadaf EbrahimiWhich generates this method with an `@Override` annotation: 788*53ff1f6bSSadaf Ebrahimi 789*53ff1f6bSSadaf Ebrahimi```java 790*53ff1f6bSSadaf Ebrahimi @Override 791*53ff1f6bSSadaf Ebrahimi public String toString() { 792*53ff1f6bSSadaf Ebrahimi return "Hoverboard"; 793*53ff1f6bSSadaf Ebrahimi } 794*53ff1f6bSSadaf Ebrahimi``` 795*53ff1f6bSSadaf Ebrahimi 796*53ff1f6bSSadaf EbrahimiUse `AnnotationSpec.builder()` to set properties on annotations: 797*53ff1f6bSSadaf Ebrahimi 798*53ff1f6bSSadaf Ebrahimi```java 799*53ff1f6bSSadaf EbrahimiMethodSpec logRecord = MethodSpec.methodBuilder("recordEvent") 800*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) 801*53ff1f6bSSadaf Ebrahimi .addAnnotation(AnnotationSpec.builder(Headers.class) 802*53ff1f6bSSadaf Ebrahimi .addMember("accept", "$S", "application/json; charset=utf-8") 803*53ff1f6bSSadaf Ebrahimi .addMember("userAgent", "$S", "Square Cash") 804*53ff1f6bSSadaf Ebrahimi .build()) 805*53ff1f6bSSadaf Ebrahimi .addParameter(LogRecord.class, "logRecord") 806*53ff1f6bSSadaf Ebrahimi .returns(LogReceipt.class) 807*53ff1f6bSSadaf Ebrahimi .build(); 808*53ff1f6bSSadaf Ebrahimi``` 809*53ff1f6bSSadaf Ebrahimi 810*53ff1f6bSSadaf EbrahimiWhich generates this annotation with `accept` and `userAgent` properties: 811*53ff1f6bSSadaf Ebrahimi 812*53ff1f6bSSadaf Ebrahimi```java 813*53ff1f6bSSadaf Ebrahimi@Headers( 814*53ff1f6bSSadaf Ebrahimi accept = "application/json; charset=utf-8", 815*53ff1f6bSSadaf Ebrahimi userAgent = "Square Cash" 816*53ff1f6bSSadaf Ebrahimi) 817*53ff1f6bSSadaf EbrahimiLogReceipt recordEvent(LogRecord logRecord); 818*53ff1f6bSSadaf Ebrahimi``` 819*53ff1f6bSSadaf Ebrahimi 820*53ff1f6bSSadaf EbrahimiWhen you get fancy, annotation values can be annotations themselves. Use `$L` for embedded 821*53ff1f6bSSadaf Ebrahimiannotations: 822*53ff1f6bSSadaf Ebrahimi 823*53ff1f6bSSadaf Ebrahimi```java 824*53ff1f6bSSadaf EbrahimiMethodSpec logRecord = MethodSpec.methodBuilder("recordEvent") 825*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) 826*53ff1f6bSSadaf Ebrahimi .addAnnotation(AnnotationSpec.builder(HeaderList.class) 827*53ff1f6bSSadaf Ebrahimi .addMember("value", "$L", AnnotationSpec.builder(Header.class) 828*53ff1f6bSSadaf Ebrahimi .addMember("name", "$S", "Accept") 829*53ff1f6bSSadaf Ebrahimi .addMember("value", "$S", "application/json; charset=utf-8") 830*53ff1f6bSSadaf Ebrahimi .build()) 831*53ff1f6bSSadaf Ebrahimi .addMember("value", "$L", AnnotationSpec.builder(Header.class) 832*53ff1f6bSSadaf Ebrahimi .addMember("name", "$S", "User-Agent") 833*53ff1f6bSSadaf Ebrahimi .addMember("value", "$S", "Square Cash") 834*53ff1f6bSSadaf Ebrahimi .build()) 835*53ff1f6bSSadaf Ebrahimi .build()) 836*53ff1f6bSSadaf Ebrahimi .addParameter(LogRecord.class, "logRecord") 837*53ff1f6bSSadaf Ebrahimi .returns(LogReceipt.class) 838*53ff1f6bSSadaf Ebrahimi .build(); 839*53ff1f6bSSadaf Ebrahimi``` 840*53ff1f6bSSadaf Ebrahimi 841*53ff1f6bSSadaf EbrahimiWhich generates this: 842*53ff1f6bSSadaf Ebrahimi 843*53ff1f6bSSadaf Ebrahimi```java 844*53ff1f6bSSadaf Ebrahimi@HeaderList({ 845*53ff1f6bSSadaf Ebrahimi @Header(name = "Accept", value = "application/json; charset=utf-8"), 846*53ff1f6bSSadaf Ebrahimi @Header(name = "User-Agent", value = "Square Cash") 847*53ff1f6bSSadaf Ebrahimi}) 848*53ff1f6bSSadaf EbrahimiLogReceipt recordEvent(LogRecord logRecord); 849*53ff1f6bSSadaf Ebrahimi``` 850*53ff1f6bSSadaf Ebrahimi 851*53ff1f6bSSadaf EbrahimiNote that you can call `addMember()` multiple times with the same property name to populate a list 852*53ff1f6bSSadaf Ebrahimiof values for that property. 853*53ff1f6bSSadaf Ebrahimi 854*53ff1f6bSSadaf Ebrahimi### Javadoc 855*53ff1f6bSSadaf Ebrahimi 856*53ff1f6bSSadaf EbrahimiFields, methods and types can be documented with Javadoc: 857*53ff1f6bSSadaf Ebrahimi 858*53ff1f6bSSadaf Ebrahimi```java 859*53ff1f6bSSadaf EbrahimiMethodSpec dismiss = MethodSpec.methodBuilder("dismiss") 860*53ff1f6bSSadaf Ebrahimi .addJavadoc("Hides {@code message} from the caller's history. Other\n" 861*53ff1f6bSSadaf Ebrahimi + "participants in the conversation will continue to see the\n" 862*53ff1f6bSSadaf Ebrahimi + "message in their own history unless they also delete it.\n") 863*53ff1f6bSSadaf Ebrahimi .addJavadoc("\n") 864*53ff1f6bSSadaf Ebrahimi .addJavadoc("<p>Use {@link #delete($T)} to delete the entire\n" 865*53ff1f6bSSadaf Ebrahimi + "conversation for all participants.\n", Conversation.class) 866*53ff1f6bSSadaf Ebrahimi .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) 867*53ff1f6bSSadaf Ebrahimi .addParameter(Message.class, "message") 868*53ff1f6bSSadaf Ebrahimi .build(); 869*53ff1f6bSSadaf Ebrahimi``` 870*53ff1f6bSSadaf Ebrahimi 871*53ff1f6bSSadaf EbrahimiWhich generates this: 872*53ff1f6bSSadaf Ebrahimi 873*53ff1f6bSSadaf Ebrahimi```java 874*53ff1f6bSSadaf Ebrahimi /** 875*53ff1f6bSSadaf Ebrahimi * Hides {@code message} from the caller's history. Other 876*53ff1f6bSSadaf Ebrahimi * participants in the conversation will continue to see the 877*53ff1f6bSSadaf Ebrahimi * message in their own history unless they also delete it. 878*53ff1f6bSSadaf Ebrahimi * 879*53ff1f6bSSadaf Ebrahimi * <p>Use {@link #delete(Conversation)} to delete the entire 880*53ff1f6bSSadaf Ebrahimi * conversation for all participants. 881*53ff1f6bSSadaf Ebrahimi */ 882*53ff1f6bSSadaf Ebrahimi void dismiss(Message message); 883*53ff1f6bSSadaf Ebrahimi``` 884*53ff1f6bSSadaf Ebrahimi 885*53ff1f6bSSadaf EbrahimiUse `$T` when referencing types in Javadoc to get automatic imports. 886*53ff1f6bSSadaf Ebrahimi 887*53ff1f6bSSadaf EbrahimiDownload 888*53ff1f6bSSadaf Ebrahimi-------- 889*53ff1f6bSSadaf Ebrahimi 890*53ff1f6bSSadaf EbrahimiDownload [the latest .jar][dl] or depend via Maven: 891*53ff1f6bSSadaf Ebrahimi```xml 892*53ff1f6bSSadaf Ebrahimi<dependency> 893*53ff1f6bSSadaf Ebrahimi <groupId>com.squareup</groupId> 894*53ff1f6bSSadaf Ebrahimi <artifactId>javapoet</artifactId> 895*53ff1f6bSSadaf Ebrahimi <version>1.12.1</version> 896*53ff1f6bSSadaf Ebrahimi</dependency> 897*53ff1f6bSSadaf Ebrahimi``` 898*53ff1f6bSSadaf Ebrahimior Gradle: 899*53ff1f6bSSadaf Ebrahimi```groovy 900*53ff1f6bSSadaf Ebrahimicompile 'com.squareup:javapoet:1.12.1' 901*53ff1f6bSSadaf Ebrahimi``` 902*53ff1f6bSSadaf Ebrahimi 903*53ff1f6bSSadaf EbrahimiSnapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. 904*53ff1f6bSSadaf Ebrahimi 905*53ff1f6bSSadaf Ebrahimi 906*53ff1f6bSSadaf Ebrahimi 907*53ff1f6bSSadaf EbrahimiLicense 908*53ff1f6bSSadaf Ebrahimi------- 909*53ff1f6bSSadaf Ebrahimi 910*53ff1f6bSSadaf Ebrahimi Copyright 2015 Square, Inc. 911*53ff1f6bSSadaf Ebrahimi 912*53ff1f6bSSadaf Ebrahimi Licensed under the Apache License, Version 2.0 (the "License"); 913*53ff1f6bSSadaf Ebrahimi you may not use this file except in compliance with the License. 914*53ff1f6bSSadaf Ebrahimi You may obtain a copy of the License at 915*53ff1f6bSSadaf Ebrahimi 916*53ff1f6bSSadaf Ebrahimi http://www.apache.org/licenses/LICENSE-2.0 917*53ff1f6bSSadaf Ebrahimi 918*53ff1f6bSSadaf Ebrahimi Unless required by applicable law or agreed to in writing, software 919*53ff1f6bSSadaf Ebrahimi distributed under the License is distributed on an "AS IS" BASIS, 920*53ff1f6bSSadaf Ebrahimi WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 921*53ff1f6bSSadaf Ebrahimi See the License for the specific language governing permissions and 922*53ff1f6bSSadaf Ebrahimi limitations under the License. 923*53ff1f6bSSadaf Ebrahimi 924*53ff1f6bSSadaf Ebrahimi 925*53ff1f6bSSadaf Ebrahimi 926*53ff1f6bSSadaf EbrahimiJavaWriter 927*53ff1f6bSSadaf Ebrahimi========== 928*53ff1f6bSSadaf Ebrahimi 929*53ff1f6bSSadaf EbrahimiJavaPoet is the successor to [JavaWriter][javawriter]. New projects should prefer JavaPoet because 930*53ff1f6bSSadaf Ebrahimiit has a stronger code model: it understands types and can manage imports automatically. JavaPoet is 931*53ff1f6bSSadaf Ebrahimialso better suited to composition: rather than streaming the contents of a `.java` file 932*53ff1f6bSSadaf Ebrahimitop-to-bottom in a single pass, a file can be assembled as a tree of declarations. 933*53ff1f6bSSadaf Ebrahimi 934*53ff1f6bSSadaf EbrahimiJavaWriter continues to be available in [GitHub][javawriter] and [Maven Central][javawriter_maven]. 935*53ff1f6bSSadaf Ebrahimi 936*53ff1f6bSSadaf Ebrahimi 937*53ff1f6bSSadaf Ebrahimi [dl]: https://search.maven.org/remote_content?g=com.squareup&a=javapoet&v=LATEST 938*53ff1f6bSSadaf Ebrahimi [snap]: https://oss.sonatype.org/content/repositories/snapshots/com/squareup/javapoet/ 939*53ff1f6bSSadaf Ebrahimi [javadoc]: https://square.github.io/javapoet/1.x/javapoet/ 940*53ff1f6bSSadaf Ebrahimi [javawriter]: https://github.com/square/javapoet/tree/javawriter_2 941*53ff1f6bSSadaf Ebrahimi [javawriter_maven]: https://search.maven.org/#artifactdetails%7Ccom.squareup%7Cjavawriter%7C2.5.1%7Cjar 942*53ff1f6bSSadaf Ebrahimi [formatter]: https://developer.android.com/reference/java/util/Formatter.html 943*53ff1f6bSSadaf Ebrahimi [modifier]: https://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Modifier.html 944