[
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "Contributing\n============\n\nIf you would like to contribute code you can do so through GitHub by forking\nthe repository and sending a pull request.\n\nWhen submitting code, please make every effort to follow existing conventions\nand style in order to keep the code as readable as possible. Please also make\nsure your code compiles by running `mvn clean verify`. Checkstyle failures\nduring compilation indicate errors in your style and can be viewed in the\n`checkstyle-result.xml` file.\n\nBefore your code can be accepted into the project you must also sign the\n[Individual Contributor License Agreement (CLA)][1].\n\n\n [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: build\n\non: [push, pull_request]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-java@v4\n        with:\n          distribution: 'zulu'\n          java-version: 8\n\n      - run: mvn --no-transfer-progress verify source:jar javadoc:jar\n\n      - run: mvn --no-transfer-progress deploy --settings=\".github/workflows/settings.xml\" -Dmaven.test.skip=true\n        if: ${{ github.ref == 'refs/heads/master' && github.repository == 'square/javapoet' }}\n"
  },
  {
    "path": ".github/workflows/settings.xml",
    "content": "<settings>\n  <servers>\n    <server>\n      <id>sonatype-nexus-snapshots</id>\n      <username>${env.SONATYPE_DEPLOY_USERNAME}</username>\n      <password>${env.SONATYPE_DEPLOY_PASSWORD}</password>\n    </server>\n  </servers>\n</settings>\n"
  },
  {
    "path": ".gitignore",
    "content": ".classpath\n.project\n.settings\n.checkstyle\neclipsebin\n\nbin\ngen\nbuild\nout\nlib\n\ntarget\npom.xml.*\nrelease.properties\n\n.idea\n*.iml\nclasses\n\nobj\n\n.DS_Store\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "Change Log\n==========\n\nJavaPoet 1.13.0 *(2020-06-18)*\n-----------------------------\n\n * New: Add support for explicit receiver parameters.\n * Fix: Don't copy parameter annotations when creating a `ParameterSpec`.\n\n\nJavaPoet 1.12.1 *(2020-01-20)*\n-----------------------------\n\n * Fix: Ignore parameter annotations in `MethodSpec.overriding()`.\n\n\nJavaPoet 1.12.0 *(2020-01-09)*\n-----------------------------\n\n * New: Add `JavaFile.writeToPath()` and `JavaFile.writeToFile()` methods that return paths to the \n   generated file as `Path` and `File` respectively.\n * New: Add `TypeSpec.alwaysQualify()` API to avoid clashes involving nested type names.\n * New: Add overloads accepting `CodeBlock`s to `MethodSpec`'s control flow methods.\n * New: Make list fields of all `Builder` types mutable.\n * New: Add `CodeBlock.clear()`.\n * New: Allow passing a custom `Charset` to `JavaFile.writeTo()`.\n * New: Improved performance of `ClassName.simpleNames()` by memoizing results.\n * New: Significant performance improvements for `CodeWriter.resolve()` as all nested simple names \n   of a `TypeSpec` get pre-computed.\n * New: Add `TypeName.Builder.setName()` to allow overriding names passed in the constructor.\n * New: Add `TypeName.canonicalName()`.\n * Fix: Use `\\\\R` instead of `\\n` as line separator in `CodeWriter.emitAndIndent()`.\n * Fix: Copy originating elements in `TypeSpec.toBuilder()`.\n * Fix: Ensure trailing newlines in Javadocs and method bodies.\n * Fix: Copy annotations when creating a `ParameterSpec` from a `VariableElement`.\n * Fix: Properly handle classes located in empty packages in `ClassName`.\n * Fix: Only allow `final` modifier on a `ParameterSpec`.\n * Fix: Use fully-qualified names for type names that are masked by type variable names.\n\n\nJavaPoet 1.11.1 *(2018-05-16)*\n-----------------------------\n\n * Fix: JavaPoet 1.11 had a regression where `TypeName.get()` would throw on error types, masking\n   other errors in an annotation processing round. This is fixed with a test to prevent future\n   regressions!\n\n\nJavaPoet 1.11.0 *(2018-04-29)*\n-----------------------------\n\n * New: Support `TYPE_USE` annotations on each enclosing `ClassName`.\n * New: Work around a compiler bug in `TypeName.get(TypeElement)`. There was a problem getting an\n   element's kind when building from source ABIs.\n\n\nJavaPoet 1.10.0 *(2018-01-27)*\n-----------------------------\n\n * **JavaPoet now requires Java 8 or newer.**\n * New: `$Z` as an optional newline (zero-width space) if a line may exceed 100 chars.\n * New: `CodeBlock.join()` and `CodeBlock.joining()` let you join codeblocks by delimiters.\n * New: Add `CodeBlock.Builder.isEmpty()`.\n * New: `addStatement(CodeBlock)` overloads for `CodeBlock` and `MethodSpec`.\n * Fix: Include annotations when emitting type variables.\n * Fix: Use the right imports for annotated type parameters.\n * Fix: Don't incorrectly escape classnames that start with `$`.\n\n\nJavaPoet 1.9.0 *(2017-05-13)*\n-----------------------------\n\n * Fix: Don't emit incorrect code when the declared type's signature references another type with\n   the same simple name.\n * Fix: Support anonymous inner classes in `ClassName.get()`.\n * New: `MethodSpec.Builder.addNamedCode()` and `TypeSpec.anonymousClassBuilder(CodeBlock)`.\n\n\nJavaPoet 1.8.0 *(2016-11-09)*\n-----------------------------\n\n * New: Basic support for line wrapping. Use `$W` to insert a Wrappable Whitespace character. It'll\n   emit either a single space or a newline with appropriate indentation.\n * New: Named arguments in `CodeBlock`. These are intended to make larger code snippets easier to\n   read:\n\n   ```\n    Map<String, Object> map = new LinkedHashMap<>();\n    map.put(\"count\", 3);\n    map.put(\"greeting\", \"Hello, \");\n    map.put(\"system\", System.class);\n\n    String template = \"\"\n        + \"for (int i = 0; i < $count:L; i++) {\\n\"\n        + \"  $system:T.out.println($greeting:S + list.get(i));\\n\"\n        + \"}\\n\";\n\n    CodeBlock.Builder builder = CodeBlock.builder();\n    builder.addNamed(template, map);\n   ```\n\n * New: `addJavadoc(CodeBlock)` overloads for TypeSpec, MethodSpec, and FieldSpec.\n * New: `MethodSpec.addComment()` makes it easy to add a `// single-line comment.`\n * New: `ClassName.getReflectionName()` returns a string like `java.util.Map$Entry`.\n * Fix: Always write UTF-8. Previously JavaPoet would use the system default charset which was\n   potentially inconsistent across environments.\n * Fix: Permit (constant) fields to be defined in annotation types.\n\n\nJavaPoet 1.7.0 *(2016-04-26)*\n-----------------------------\n\n * New: Support parameterized types that enclose other types, like `Outer<String>.Inner`.\n * New: `TypeName.isBoxedPrimitive()`.\n\n\nJavaPoet 1.6.1 *(2016-03-21)*\n-----------------------------\n\n * Fix: Double quotes and backslashes in string literals were not properly quoted in 1.6.0. This is\n   now fixed.\n\n\nJavaPoet 1.6.0 *(2016-03-19)*\n-----------------------------\n\n * New: Revive `CodeBlock.of()`, a handy factory method for building code blocks.\n * New: Add `TypeSpec` factory methods that take a `ClassName`.\n * New: `TypeName.annotated()` adds an annotation to a type.\n * New: `TypeVariableName.withBounds()` adds bounds to a type variable.\n * New: `TypeSpec.Builder.addInitializerBlock()` adds an instance initializer.\n * Fix: Make `TypeSpec.Kind` enum public. This can be used to check if a `TypeSpec` is a class,\n   interface, enum, or annotation.\n * Fix: Don’t break import resolution on annotated types.\n * Fix: Forbid unexpected modifiers like `private` on annotation members.\n * Fix: Deduplicate exceptions in `MethodSpec.Builder`.\n * Fix: Treat `ErrorType` like a regular `DeclaredType` in `TypeName.get()`. This should make it\n   easier to write annotation processors.\n\n\nJavaPoet 1.5.1 *(2016-01-10)*\n-----------------------------\n\n * Fix: Annotated `TypeName` instances are only equal if their annotations are equal.\n\nJavaPoet 1.5.0 *(2016-01-10)*\n-----------------------------\n\n * New: `import static`! See `JavaFile.Builder.addStaticImport()` variants.\n * New: Overload `NameAllocator.newName(String)` for creating a one-off name without a tag.\n * Fix: AnnotationSpec escapes character literals properly.\n * Fix: Don't stack overflow when `TypeVariableName` is part of `ParameterizedTypeName`.\n * Fix: Reporting not used indexed arguments in like `add(\"$1S\", \"a\", \"b\")`.\n * Fix: Prevent import of types located in the default package, i.e. have no package name.\n\n\nJavaPoet 1.4.0 *(2015-11-13)*\n-----------------------------\n\n * New: `AnnotationSpec.get(Annotation)`.\n * New: Type annotations! `TypeName.annotated()` can attach annotations like `@Nullable` directly to\n   types. This works for both top-level types and type parameters as in `List<@Nullable String>`.\n * New: `equals()` and `hashCode()` on `AnnotationSpec`, `CodeBlock`, `FieldSpec`, `JavaFile`,\n   `MethodSpec`, `ParameterSpec`, `TypeName`, and `TypeSpec`.\n * New: `NameAllocator.clone()` to refine a NameAllocator for use in an inner scope code block.\n * Fix: Don't stack overflow when `TypeVariableName` gets a self-referential type.\n * Fix: Better handling of name collisions on imports. Previously JavaPoet did the wrong thing when\n   a referenced type and a nested types had the same name.\n\n\nJavaPoet 1.3.0 *(2015-09-20)*\n-----------------------------\n\n * New: `NameAllocator` API makes it easy to declare non-conflicting names.\n * New: Support annotations on enum values.\n * Fix: Avoid infinite recursion in `TypeName.get(TypeMirror)`.\n * Fix: Use qualified name for conflicting simple names in the same file.\n * Fix: Better messages for parameter indexing errors.\n\n\nJavaPoet 1.2.0 *(2015-07-04)*\n-----------------------------\n\n * New: Arguments may have positional indexes like `$1T` and `$2N`. Indexes can be used to refer to\n   the same argument multiple times in a single format string.\n * New: Permit Javadoc on enum constants.\n * New: Class initializer blocks with `addStaticBlock()`.\n * Fix: `MethodSpec.overriding()` retains annotations.\n\n\nJavaPoet 1.1.0 *(2015-05-25)*\n-----------------------------\n\n * New: Eager validation of argument types like `$T` and `$N`.\n * New: `MethodSpec.varargs(boolean)` to generate varags methods.\n * New: `AnnotationSpec.get()` and `MethodSpec.overriding()` to create annotations and methods from\n   the `javax.lang.model` API.\n * New: `JavaFile.toJavaFileObject()`.\n * New: Java 8 `DEFAULT` modifier.\n * New: `toBuilder()` methods to build upon objects already constructed.\n * New: Generate `@interface` annotation types.\n * New: `TypeName.box()` and `TypeName.unbox()` convenience APIs.\n * Fix: `nextControlFlow()` accepts arguments.\n * Fix: Reject duplicate calls to set the superclass.\n * Fix: `WildcardTypeName.get(WildcardType)` no longer throws a `NullPointerException`.\n * Fix: Don't allow double field initialization.\n\nJavaPoet 1.0.0 *(2015-01-28)*\n-----------------------------\n\n * This update is a complete rewrite. The project name is now `javapoet`. We renamed the it so you\n   can simultaneously use the old JavaWriter API and our new builder-based APIs in one project.\n * Immutable value objects and builders. Instead of streaming the `.java` file from top to bottom,\n   you now define members in whatever way is convenient.\n * We now use our own models for type names.\n * Imports are now added automatically.\n\n\nJavaWriter 2.5.1 *(2014-12-03)*\n-------------------------------\n\n * New: `StringLiteral` type which encapsulates the behavior of `stringLiteral`.\n * Fix: Use canonical name when emitting a class import.\n * Fix: Apply type compression to varargs and array types.\n * Fix: Restore binary compatibility with pre-2.5 versions.\n\n\nJavaWriter 2.5.0 *(2014-04-18)*\n-------------------------------\n\n * New: Methods in interfaces will always have no body declaration.\n * New: Control flow begin declaration now supports String format arguments.\n * Fix: Truncate any generic type when emitting constructors.\n * Fix: Do not emit trailing whitespace after '=' at end-of-line.\n\n\nJavaWriter 2.4.0 *(2014-01-10)*\n-------------------------------\n\n * New: Properly indent hanging lines in field initializers.\n * New: `emitEnumValue` variant which exposes a boolean of whether the current value is the last.\n\n\nJavaWriter 2.3.1 *(2013-12-16)*\n-------------------------------\n\n * Fix: Properly handle subpackages of `java.lang` in `compressType`.\n\n\nJavaWriter 2.3.0 *(2013-11-24)*\n-------------------------------\n\n * New: Configurable indent level via `setIndent`.\n * New: `beginConstructor` method is a semantically clearer alternative for constructors.\n * New: `emitEnumValues` method emits a list of values followed by semicolon.\n * `emitImports` now supports `Class` arguments directly.\n * Previously-deprecated, `int`-based modifier methods have been removed.\n\n\nJavaWriter 2.2.1 *(2013-10-23)*\n-------------------------------\n\n * Fix: Do not emit trailing whitespace for empty Javadoc lines.\n\n\nJavaWriter 2.2.0 *(2013-09-25)*\n-------------------------------\n\n * `setCompressingTypes` controls whether types are emitted as fully-qualified or not.\n\n\nJavaWriter 2.1.2 *(2013-08-23)*\n-------------------------------\n\n * Attempt to keep annotations on a single line.\n\n\nJavaWriter 2.1.1 *(2013-07-23)*\n-------------------------------\n\n * Fix: `stringLiteral` now correctly handles escapes and control characters.\n\n\nJavaWriter 2.1.0 *(2013-07-15)*\n-------------------------------\n\n * New: All methods now take a `Set` of `Modifier`s rather than an `int`. The `int` methods are\n   now deprecated for removal in JavaPoet 1.0.\n * Annotations with a single \"value\" attribute will now omit the key.\n\n\nJavaWriter 2.0.1 *(2013-06-17)*\n-------------------------------\n\n * Correct casing of `emitSingleLineComment`.\n\n\nJavaWriter 2.0.0 *(2013-06-06)*\n-------------------------------\n\n * Package name is now `com.squareup.javawriter`.\n * Support declaring `throws` clause on methods.\n\n\nJavaWriter 1.0.5 *(2013-05-08)*\n-------------------------------\n\n * Fix: Fully qualify types whose simple name matches an import.\n\n\nJavaWriter 1.0.4 *(2013-03-15)*\n-------------------------------\n\n * Fix: Static import emit now properly supports method imports.\n\n\nJavaWriter 1.0.3 *(2013-02-21)*\n-------------------------------\n\n * Add support for emitting static imports.\n\n\nJavaWriter 1.0.2 *(2013-02-11)*\n-------------------------------\n\n * Add `type` API for helping build generic types.\n * Minor performance improvements.\n\n\nJavaWriter 1.0.1 *(2013-02-03)*\n-------------------------------\n\n * Expose `compressType` API.\n\n\nJavaWriter 1.0.0 *(2013-02-01)*\n-------------------------------\n\nInitial release.\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "JavaPoet\n========\n\n`JavaPoet` is a Java API for generating `.java` source files.\n\nSource file generation can be useful when doing things such as annotation processing or interacting\nwith metadata files (e.g., database schemas, protocol formats). By generating code, you eliminate\nthe need to write boilerplate while also keeping a single source of truth for the metadata.\n\n\nDeprecated\n----------\n\nAs of 2020-10-10, Square's JavaPoet project is deprecated. We're proud of our work but we haven't\nkept up on maintaining it.\n\nIf you'd like an alternative that supports the latest Java language features, one option is\n[Palantir's JavaPoet](https://github.com/palantir/javapoet).\n\nTo switch to that project, you'll need new Maven coordinates:\n\n```diff\n- javapoet = { module = \"com.squareup:javapoet\", version = \"1.13.0\" }\n+ javapoet = { module = \"com.palantir.javapoet:javapoet\", version = \"0.5.0\" }\n```\n\nAnd new imports:\n\n```\nsed -i \"\" \\\n  's/com.squareup.javapoet.\\([A-Za-z]*\\)/com.palantir.javapoet.\\1/g' \\\n  `find . -name \"*.kt\" -or -name \"*.java\"`\n```\n\nAnd you might need to track some API changes where fields became functions:\n\n```diff\n- javaFile.packageName\n+ javaFile.packageName()\n```\n\n### Example\n\nHere's a (boring) `HelloWorld` class:\n\n```java\npackage com.example.helloworld;\n\npublic final class HelloWorld {\n  public static void main(String[] args) {\n    System.out.println(\"Hello, JavaPoet!\");\n  }\n}\n```\n\nAnd this is the (exciting) code to generate it with JavaPoet:\n\n```java\nMethodSpec main = MethodSpec.methodBuilder(\"main\")\n    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n    .returns(void.class)\n    .addParameter(String[].class, \"args\")\n    .addStatement(\"$T.out.println($S)\", System.class, \"Hello, JavaPoet!\")\n    .build();\n\nTypeSpec helloWorld = TypeSpec.classBuilder(\"HelloWorld\")\n    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n    .addMethod(main)\n    .build();\n\nJavaFile javaFile = JavaFile.builder(\"com.example.helloworld\", helloWorld)\n    .build();\n\njavaFile.writeTo(System.out);\n```\n\nTo declare the main method, we've created a `MethodSpec` \"main\" configured with modifiers, return\ntype, parameters and code statements. We add the main method to a `HelloWorld` class, and then add\nthat to a `HelloWorld.java` file.\n\nIn this case we write the file to `System.out`, but we could also get it as a string\n(`JavaFile.toString()`) or write it to the file system (`JavaFile.writeTo()`).\n\nThe [Javadoc][javadoc] catalogs the complete JavaPoet API, which we explore below.\n\n### Code & Control Flow\n\nMost of JavaPoet's API uses plain old immutable Java objects. There's also builders, method chaining\nand varargs to make the API friendly. JavaPoet offers models for classes & interfaces (`TypeSpec`),\nfields (`FieldSpec`), methods & constructors (`MethodSpec`), parameters (`ParameterSpec`) and\nannotations (`AnnotationSpec`).\n\nBut the _body_ of methods and constructors is not modeled. There's no expression class, no\nstatement class or syntax tree nodes. Instead, JavaPoet uses strings for code blocks:\n\n```java\nMethodSpec main = MethodSpec.methodBuilder(\"main\")\n    .addCode(\"\"\n        + \"int total = 0;\\n\"\n        + \"for (int i = 0; i < 10; i++) {\\n\"\n        + \"  total += i;\\n\"\n        + \"}\\n\")\n    .build();\n```\n\nWhich generates this:\n\n```java\nvoid main() {\n  int total = 0;\n  for (int i = 0; i < 10; i++) {\n    total += i;\n  }\n}\n```\n\nThe manual semicolons, line wrapping, and indentation are tedious and so JavaPoet offers APIs to\nmake it easier. There's `addStatement()` which takes care of semicolons and newline, and\n`beginControlFlow()` + `endControlFlow()` which are used together for braces, newlines, and\nindentation:\n\n```java\nMethodSpec main = MethodSpec.methodBuilder(\"main\")\n    .addStatement(\"int total = 0\")\n    .beginControlFlow(\"for (int i = 0; i < 10; i++)\")\n    .addStatement(\"total += i\")\n    .endControlFlow()\n    .build();\n```\n\nThis example is lame because the generated code is constant! Suppose instead of just adding 0 to 10,\nwe want to make the operation and range configurable. Here's a method that generates a method:\n\n```java\nprivate MethodSpec computeRange(String name, int from, int to, String op) {\n  return MethodSpec.methodBuilder(name)\n      .returns(int.class)\n      .addStatement(\"int result = 1\")\n      .beginControlFlow(\"for (int i = \" + from + \"; i < \" + to + \"; i++)\")\n      .addStatement(\"result = result \" + op + \" i\")\n      .endControlFlow()\n      .addStatement(\"return result\")\n      .build();\n}\n```\n\nAnd here's what we get when we call `computeRange(\"multiply10to20\", 10, 20, \"*\")`:\n\n```java\nint multiply10to20() {\n  int result = 1;\n  for (int i = 10; i < 20; i++) {\n    result = result * i;\n  }\n  return result;\n}\n```\n\nMethods generating methods! And since JavaPoet generates source instead of bytecode, you can\nread through it to make sure it's right.\n\nSome control flow statements, such as `if/else`, can have unlimited control flow possibilities.\nYou can handle those options using `nextControlFlow()`:\n\n```java\nMethodSpec main = MethodSpec.methodBuilder(\"main\")\n    .addStatement(\"long now = $T.currentTimeMillis()\", System.class)\n    .beginControlFlow(\"if ($T.currentTimeMillis() < now)\", System.class)\n    .addStatement(\"$T.out.println($S)\", System.class, \"Time travelling, woo hoo!\")\n    .nextControlFlow(\"else if ($T.currentTimeMillis() == now)\", System.class)\n    .addStatement(\"$T.out.println($S)\", System.class, \"Time stood still!\")\n    .nextControlFlow(\"else\")\n    .addStatement(\"$T.out.println($S)\", System.class, \"Ok, time still moving forward\")\n    .endControlFlow()\n    .build();\n```\n\nWhich generates:\n\n```java\nvoid main() {\n  long now = System.currentTimeMillis();\n  if (System.currentTimeMillis() < now)  {\n    System.out.println(\"Time travelling, woo hoo!\");\n  } else if (System.currentTimeMillis() == now) {\n    System.out.println(\"Time stood still!\");\n  } else {\n    System.out.println(\"Ok, time still moving forward\");\n  }\n}\n``` \n\nCatching exceptions using `try/catch` is also a use case for `nextControlFlow()`:\n\n```java\nMethodSpec main = MethodSpec.methodBuilder(\"main\")\n    .beginControlFlow(\"try\")\n    .addStatement(\"throw new Exception($S)\", \"Failed\")\n    .nextControlFlow(\"catch ($T e)\", Exception.class)\n    .addStatement(\"throw new $T(e)\", RuntimeException.class)\n    .endControlFlow()\n    .build();\n```\n\nWhich produces:\n\n```java\nvoid main() {\n  try {\n    throw new Exception(\"Failed\");\n  } catch (Exception e) {\n    throw new RuntimeException(e);\n  }\n}\n```\n\n### $L for Literals\n\nThe string-concatenation in calls to `beginControlFlow()` and `addStatement` is distracting. Too\nmany operators. To address this, JavaPoet offers a syntax inspired-by but incompatible-with\n[`String.format()`][formatter]. It accepts **`$L`** to emit a **literal** value in the output. This\nworks just like `Formatter`'s `%s`:\n\n```java\nprivate MethodSpec computeRange(String name, int from, int to, String op) {\n  return MethodSpec.methodBuilder(name)\n      .returns(int.class)\n      .addStatement(\"int result = 0\")\n      .beginControlFlow(\"for (int i = $L; i < $L; i++)\", from, to)\n      .addStatement(\"result = result $L i\", op)\n      .endControlFlow()\n      .addStatement(\"return result\")\n      .build();\n}\n```\n\nLiterals are emitted directly to the output code with no escaping. Arguments for literals may be\nstrings, primitives, and a few JavaPoet types described below.\n\n### $S for Strings\n\nWhen emitting code that includes string literals, we can use **`$S`** to emit a **string**, complete\nwith wrapping quotation marks and escaping. Here's a program that emits 3 methods, each of which\nreturns its own name:\n\n```java\npublic static void main(String[] args) throws Exception {\n  TypeSpec helloWorld = TypeSpec.classBuilder(\"HelloWorld\")\n      .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n      .addMethod(whatsMyName(\"slimShady\"))\n      .addMethod(whatsMyName(\"eminem\"))\n      .addMethod(whatsMyName(\"marshallMathers\"))\n      .build();\n\n  JavaFile javaFile = JavaFile.builder(\"com.example.helloworld\", helloWorld)\n      .build();\n\n  javaFile.writeTo(System.out);\n}\n\nprivate static MethodSpec whatsMyName(String name) {\n  return MethodSpec.methodBuilder(name)\n      .returns(String.class)\n      .addStatement(\"return $S\", name)\n      .build();\n}\n```\n\nIn this case, using `$S` gives us quotation marks:\n\n```java\npublic final class HelloWorld {\n  String slimShady() {\n    return \"slimShady\";\n  }\n\n  String eminem() {\n    return \"eminem\";\n  }\n\n  String marshallMathers() {\n    return \"marshallMathers\";\n  }\n}\n```\n\n### $T for Types\n\nWe Java programmers love our types: they make our code easier to understand. And JavaPoet is on\nboard. It has rich built-in support for types, including automatic generation of `import`\nstatements. Just use **`$T`** to reference **types**:\n\n```java\nMethodSpec today = MethodSpec.methodBuilder(\"today\")\n    .returns(Date.class)\n    .addStatement(\"return new $T()\", Date.class)\n    .build();\n\nTypeSpec helloWorld = TypeSpec.classBuilder(\"HelloWorld\")\n    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n    .addMethod(today)\n    .build();\n\nJavaFile javaFile = JavaFile.builder(\"com.example.helloworld\", helloWorld)\n    .build();\n\njavaFile.writeTo(System.out);\n```\n\nThat generates the following `.java` file, complete with the necessary `import`:\n\n```java\npackage com.example.helloworld;\n\nimport java.util.Date;\n\npublic final class HelloWorld {\n  Date today() {\n    return new Date();\n  }\n}\n```\n\nWe passed `Date.class` to reference a class that just-so-happens to be available when we're\ngenerating code. This doesn't need to be the case. Here's a similar example, but this one\nreferences a class that doesn't exist (yet):\n\n```java\nClassName hoverboard = ClassName.get(\"com.mattel\", \"Hoverboard\");\n\nMethodSpec today = MethodSpec.methodBuilder(\"tomorrow\")\n    .returns(hoverboard)\n    .addStatement(\"return new $T()\", hoverboard)\n    .build();\n```\n\nAnd that not-yet-existent class is imported as well:\n\n```java\npackage com.example.helloworld;\n\nimport com.mattel.Hoverboard;\n\npublic final class HelloWorld {\n  Hoverboard tomorrow() {\n    return new Hoverboard();\n  }\n}\n```\n\nThe `ClassName` type is very important, and you'll need it frequently when you're using JavaPoet.\nIt can identify any _declared_ class. Declared types are just the beginning of Java's rich type\nsystem: we also have arrays, parameterized types, wildcard types, and type variables. JavaPoet has\nclasses for building each of these:\n\n```java\nClassName hoverboard = ClassName.get(\"com.mattel\", \"Hoverboard\");\nClassName list = ClassName.get(\"java.util\", \"List\");\nClassName arrayList = ClassName.get(\"java.util\", \"ArrayList\");\nTypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);\n\nMethodSpec beyond = MethodSpec.methodBuilder(\"beyond\")\n    .returns(listOfHoverboards)\n    .addStatement(\"$T result = new $T<>()\", listOfHoverboards, arrayList)\n    .addStatement(\"result.add(new $T())\", hoverboard)\n    .addStatement(\"result.add(new $T())\", hoverboard)\n    .addStatement(\"result.add(new $T())\", hoverboard)\n    .addStatement(\"return result\")\n    .build();\n```\n\nJavaPoet will decompose each type and import its components where possible.\n\n```java\npackage com.example.helloworld;\n\nimport com.mattel.Hoverboard;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class HelloWorld {\n  List<Hoverboard> beyond() {\n    List<Hoverboard> result = new ArrayList<>();\n    result.add(new Hoverboard());\n    result.add(new Hoverboard());\n    result.add(new Hoverboard());\n    return result;\n  }\n}\n```\n\n#### Import static\n\nJavaPoet supports `import static`. It does it via explicitly collecting type member names. Let's\nenhance the previous example with some static sugar:\n\n```java\n...\nClassName namedBoards = ClassName.get(\"com.mattel\", \"Hoverboard\", \"Boards\");\n\nMethodSpec beyond = MethodSpec.methodBuilder(\"beyond\")\n    .returns(listOfHoverboards)\n    .addStatement(\"$T result = new $T<>()\", listOfHoverboards, arrayList)\n    .addStatement(\"result.add($T.createNimbus(2000))\", hoverboard)\n    .addStatement(\"result.add($T.createNimbus(\\\"2001\\\"))\", hoverboard)\n    .addStatement(\"result.add($T.createNimbus($T.THUNDERBOLT))\", hoverboard, namedBoards)\n    .addStatement(\"$T.sort(result)\", Collections.class)\n    .addStatement(\"return result.isEmpty() ? $T.emptyList() : result\", Collections.class)\n    .build();\n\nTypeSpec hello = TypeSpec.classBuilder(\"HelloWorld\")\n    .addMethod(beyond)\n    .build();\n\nJavaFile.builder(\"com.example.helloworld\", hello)\n    .addStaticImport(hoverboard, \"createNimbus\")\n    .addStaticImport(namedBoards, \"*\")\n    .addStaticImport(Collections.class, \"*\")\n    .build();\n```\n\nJavaPoet will first add your `import static` block to the file as configured, match and mangle\nall calls accordingly and also import all other types as needed.\n\n```java\npackage com.example.helloworld;\n\nimport static com.mattel.Hoverboard.Boards.*;\nimport static com.mattel.Hoverboard.createNimbus;\nimport static java.util.Collections.*;\n\nimport com.mattel.Hoverboard;\nimport java.util.ArrayList;\nimport java.util.List;\n\nclass HelloWorld {\n  List<Hoverboard> beyond() {\n    List<Hoverboard> result = new ArrayList<>();\n    result.add(createNimbus(2000));\n    result.add(createNimbus(\"2001\"));\n    result.add(createNimbus(THUNDERBOLT));\n    sort(result);\n    return result.isEmpty() ? emptyList() : result;\n  }\n}\n```\n\n### $N for Names\n\nGenerated code is often self-referential. Use **`$N`** to refer to another generated declaration by\nits name. Here's a method that calls another:\n\n```java\npublic String byteToHex(int b) {\n  char[] result = new char[2];\n  result[0] = hexDigit((b >>> 4) & 0xf);\n  result[1] = hexDigit(b & 0xf);\n  return new String(result);\n}\n\npublic char hexDigit(int i) {\n  return (char) (i < 10 ? i + '0' : i - 10 + 'a');\n}\n```\n\nWhen generating the code above, we pass the `hexDigit()` method as an argument to the `byteToHex()`\nmethod using `$N`:\n\n```java\nMethodSpec hexDigit = MethodSpec.methodBuilder(\"hexDigit\")\n    .addParameter(int.class, \"i\")\n    .returns(char.class)\n    .addStatement(\"return (char) (i < 10 ? i + '0' : i - 10 + 'a')\")\n    .build();\n\nMethodSpec byteToHex = MethodSpec.methodBuilder(\"byteToHex\")\n    .addParameter(int.class, \"b\")\n    .returns(String.class)\n    .addStatement(\"char[] result = new char[2]\")\n    .addStatement(\"result[0] = $N((b >>> 4) & 0xf)\", hexDigit)\n    .addStatement(\"result[1] = $N(b & 0xf)\", hexDigit)\n    .addStatement(\"return new String(result)\")\n    .build();\n```\n\n### Code block format strings\n\nCode blocks may specify the values for their placeholders in a few ways. Only one style may be used\nfor each operation on a code block.\n\n#### Relative Arguments\n\nPass an argument value for each placeholder in the format string to `CodeBlock.add()`. In each\nexample, we generate code to say \"I ate 3 tacos\"\n\n```java\nCodeBlock.builder().add(\"I ate $L $L\", 3, \"tacos\")\n```\n\n#### Positional Arguments\n\nPlace an integer index (1-based) before the placeholder in the format string to specify which\n argument to use.\n\n```java\nCodeBlock.builder().add(\"I ate $2L $1L\", \"tacos\", 3)\n```\n\n#### Named Arguments\n\nUse the syntax `$argumentName:X` where `X` is the format character and call `CodeBlock.addNamed()`\nwith a map containing all argument keys in the format string. Argument names use characters in\n`a-z`, `A-Z`, `0-9`, and `_`, and must start with a lowercase character.\n\n```java\nMap<String, Object> map = new LinkedHashMap<>();\nmap.put(\"food\", \"tacos\");\nmap.put(\"count\", 3);\nCodeBlock.builder().addNamed(\"I ate $count:L $food:L\", map)\n```\n\n### Methods\n\nAll of the above methods have a code body. Use `Modifiers.ABSTRACT` to get a method without any\nbody. This is only legal if the enclosing class is either abstract or an interface.\n\n```java\nMethodSpec flux = MethodSpec.methodBuilder(\"flux\")\n    .addModifiers(Modifier.ABSTRACT, Modifier.PROTECTED)\n    .build();\n\nTypeSpec helloWorld = TypeSpec.classBuilder(\"HelloWorld\")\n    .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n    .addMethod(flux)\n    .build();\n```\n\nWhich generates this:\n\n```java\npublic abstract class HelloWorld {\n  protected abstract void flux();\n}\n```\n\nThe other modifiers work where permitted. Note that when specifying modifiers, JavaPoet uses\n[`javax.lang.model.element.Modifier`][modifier], a class that is not available on Android. This\nlimitation applies to code-generating-code only; the output code runs everywhere: JVMs, Android,\nand GWT.\n\nMethods also have parameters, exceptions, varargs, Javadoc, annotations, type variables, and a\nreturn type. All of these are configured with `MethodSpec.Builder`.\n\n### Constructors\n\n`MethodSpec` is a slight misnomer; it can also be used for constructors:\n\n```java\nMethodSpec flux = MethodSpec.constructorBuilder()\n    .addModifiers(Modifier.PUBLIC)\n    .addParameter(String.class, \"greeting\")\n    .addStatement(\"this.$N = $N\", \"greeting\", \"greeting\")\n    .build();\n\nTypeSpec helloWorld = TypeSpec.classBuilder(\"HelloWorld\")\n    .addModifiers(Modifier.PUBLIC)\n    .addField(String.class, \"greeting\", Modifier.PRIVATE, Modifier.FINAL)\n    .addMethod(flux)\n    .build();\n```\n\nWhich generates this:\n\n```java\npublic class HelloWorld {\n  private final String greeting;\n\n  public HelloWorld(String greeting) {\n    this.greeting = greeting;\n  }\n}\n```\n\nFor the most part, constructors work just like methods. When emitting code, JavaPoet will place\nconstructors before methods in the output file.\n\n### Parameters\n\nDeclare parameters on methods and constructors with either `ParameterSpec.builder()` or\n`MethodSpec`'s convenient `addParameter()` API:\n\n```java\nParameterSpec android = ParameterSpec.builder(String.class, \"android\")\n    .addModifiers(Modifier.FINAL)\n    .build();\n\nMethodSpec welcomeOverlords = MethodSpec.methodBuilder(\"welcomeOverlords\")\n    .addParameter(android)\n    .addParameter(String.class, \"robot\", Modifier.FINAL)\n    .build();\n```\n\nThough the code above to generate `android` and `robot` parameters is different, the output is the\nsame:\n\n```java\nvoid welcomeOverlords(final String android, final String robot) {\n}\n```\n\nThe extended `Builder` form is necessary when the parameter has annotations (such as `@Nullable`).\n\n### Fields\n\nLike parameters, fields can be created either with builders or by using convenient helper methods:\n\n```java\nFieldSpec android = FieldSpec.builder(String.class, \"android\")\n    .addModifiers(Modifier.PRIVATE, Modifier.FINAL)\n    .build();\n\nTypeSpec helloWorld = TypeSpec.classBuilder(\"HelloWorld\")\n    .addModifiers(Modifier.PUBLIC)\n    .addField(android)\n    .addField(String.class, \"robot\", Modifier.PRIVATE, Modifier.FINAL)\n    .build();\n```\n\nWhich generates:\n\n```java\npublic class HelloWorld {\n  private final String android;\n\n  private final String robot;\n}\n```\n\nThe extended `Builder` form is necessary when a field has Javadoc, annotations, or a field\ninitializer. Field initializers use the same [`String.format()`][formatter]-like syntax as the code\nblocks above:\n\n```java\nFieldSpec android = FieldSpec.builder(String.class, \"android\")\n    .addModifiers(Modifier.PRIVATE, Modifier.FINAL)\n    .initializer(\"$S + $L\", \"Lollipop v.\", 5.0d)\n    .build();\n```\n\nWhich generates:\n\n```java\nprivate final String android = \"Lollipop v.\" + 5.0;\n```\n\n### Interfaces\n\nJavaPoet has no trouble with interfaces. Note that interface methods must always be `PUBLIC\nABSTRACT` and interface fields must always be `PUBLIC STATIC FINAL`. These modifiers are necessary\nwhen defining the interface:\n\n```java\nTypeSpec helloWorld = TypeSpec.interfaceBuilder(\"HelloWorld\")\n    .addModifiers(Modifier.PUBLIC)\n    .addField(FieldSpec.builder(String.class, \"ONLY_THING_THAT_IS_CONSTANT\")\n        .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)\n        .initializer(\"$S\", \"change\")\n        .build())\n    .addMethod(MethodSpec.methodBuilder(\"beep\")\n        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n        .build())\n    .build();\n```\n\nBut these modifiers are omitted when the code is generated. These are the defaults so we don't need\nto include them for `javac`'s benefit!\n\n```java\npublic interface HelloWorld {\n  String ONLY_THING_THAT_IS_CONSTANT = \"change\";\n\n  void beep();\n}\n```\n\n### Enums\n\nUse `enumBuilder` to create the enum type, and `addEnumConstant()` for each value:\n\n```java\nTypeSpec helloWorld = TypeSpec.enumBuilder(\"Roshambo\")\n    .addModifiers(Modifier.PUBLIC)\n    .addEnumConstant(\"ROCK\")\n    .addEnumConstant(\"SCISSORS\")\n    .addEnumConstant(\"PAPER\")\n    .build();\n```\n\nTo generate this:\n\n```java\npublic enum Roshambo {\n  ROCK,\n\n  SCISSORS,\n\n  PAPER\n}\n```\n\nFancy enums are supported, where the enum values override methods or call a superclass constructor.\nHere's a comprehensive example:\n\n```java\nTypeSpec helloWorld = TypeSpec.enumBuilder(\"Roshambo\")\n    .addModifiers(Modifier.PUBLIC)\n    .addEnumConstant(\"ROCK\", TypeSpec.anonymousClassBuilder(\"$S\", \"fist\")\n        .addMethod(MethodSpec.methodBuilder(\"toString\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .addStatement(\"return $S\", \"avalanche!\")\n            .returns(String.class)\n            .build())\n        .build())\n    .addEnumConstant(\"SCISSORS\", TypeSpec.anonymousClassBuilder(\"$S\", \"peace\")\n        .build())\n    .addEnumConstant(\"PAPER\", TypeSpec.anonymousClassBuilder(\"$S\", \"flat\")\n        .build())\n    .addField(String.class, \"handsign\", Modifier.PRIVATE, Modifier.FINAL)\n    .addMethod(MethodSpec.constructorBuilder()\n        .addParameter(String.class, \"handsign\")\n        .addStatement(\"this.$N = $N\", \"handsign\", \"handsign\")\n        .build())\n    .build();\n```\n\nWhich generates this:\n\n```java\npublic enum Roshambo {\n  ROCK(\"fist\") {\n    @Override\n    public String toString() {\n      return \"avalanche!\";\n    }\n  },\n\n  SCISSORS(\"peace\"),\n\n  PAPER(\"flat\");\n\n  private final String handsign;\n\n  Roshambo(String handsign) {\n    this.handsign = handsign;\n  }\n}\n```\n\n### Anonymous Inner Classes\n\nIn the enum code, we used `TypeSpec.anonymousInnerClass()`. Anonymous inner classes can also be used in\ncode blocks. They are values that can be referenced with `$L`:\n\n```java\nTypeSpec comparator = TypeSpec.anonymousClassBuilder(\"\")\n    .addSuperinterface(ParameterizedTypeName.get(Comparator.class, String.class))\n    .addMethod(MethodSpec.methodBuilder(\"compare\")\n        .addAnnotation(Override.class)\n        .addModifiers(Modifier.PUBLIC)\n        .addParameter(String.class, \"a\")\n        .addParameter(String.class, \"b\")\n        .returns(int.class)\n        .addStatement(\"return $N.length() - $N.length()\", \"a\", \"b\")\n        .build())\n    .build();\n\nTypeSpec helloWorld = TypeSpec.classBuilder(\"HelloWorld\")\n    .addMethod(MethodSpec.methodBuilder(\"sortByLength\")\n        .addParameter(ParameterizedTypeName.get(List.class, String.class), \"strings\")\n        .addStatement(\"$T.sort($N, $L)\", Collections.class, \"strings\", comparator)\n        .build())\n    .build();\n```\n\nThis generates a method that contains a class that contains a method:\n\n```java\nvoid sortByLength(List<String> strings) {\n  Collections.sort(strings, new Comparator<String>() {\n    @Override\n    public int compare(String a, String b) {\n      return a.length() - b.length();\n    }\n  });\n}\n```\n\nOne particularly tricky part of defining anonymous inner classes is the arguments to the superclass\nconstructor. In the above code we're passing the empty string for no arguments:\n`TypeSpec.anonymousClassBuilder(\"\")`. To pass different parameters use JavaPoet's code block\nsyntax with commas to separate arguments.\n\n\n### Annotations\n\nSimple annotations are easy:\n\n```java\nMethodSpec toString = MethodSpec.methodBuilder(\"toString\")\n    .addAnnotation(Override.class)\n    .returns(String.class)\n    .addModifiers(Modifier.PUBLIC)\n    .addStatement(\"return $S\", \"Hoverboard\")\n    .build();\n```\n\nWhich generates this method with an `@Override` annotation:\n\n```java\n  @Override\n  public String toString() {\n    return \"Hoverboard\";\n  }\n```\n\nUse `AnnotationSpec.builder()` to set properties on annotations:\n\n```java\nMethodSpec logRecord = MethodSpec.methodBuilder(\"recordEvent\")\n    .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n    .addAnnotation(AnnotationSpec.builder(Headers.class)\n        .addMember(\"accept\", \"$S\", \"application/json; charset=utf-8\")\n        .addMember(\"userAgent\", \"$S\", \"Square Cash\")\n        .build())\n    .addParameter(LogRecord.class, \"logRecord\")\n    .returns(LogReceipt.class)\n    .build();\n```\n\nWhich generates this annotation with `accept` and `userAgent` properties:\n\n```java\n@Headers(\n    accept = \"application/json; charset=utf-8\",\n    userAgent = \"Square Cash\"\n)\nLogReceipt recordEvent(LogRecord logRecord);\n```\n\nWhen you get fancy, annotation values can be annotations themselves. Use `$L` for embedded\nannotations:\n\n```java\nMethodSpec logRecord = MethodSpec.methodBuilder(\"recordEvent\")\n    .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n    .addAnnotation(AnnotationSpec.builder(HeaderList.class)\n        .addMember(\"value\", \"$L\", AnnotationSpec.builder(Header.class)\n            .addMember(\"name\", \"$S\", \"Accept\")\n            .addMember(\"value\", \"$S\", \"application/json; charset=utf-8\")\n            .build())\n        .addMember(\"value\", \"$L\", AnnotationSpec.builder(Header.class)\n            .addMember(\"name\", \"$S\", \"User-Agent\")\n            .addMember(\"value\", \"$S\", \"Square Cash\")\n            .build())\n        .build())\n    .addParameter(LogRecord.class, \"logRecord\")\n    .returns(LogReceipt.class)\n    .build();\n```\n\nWhich generates this:\n\n```java\n@HeaderList({\n    @Header(name = \"Accept\", value = \"application/json; charset=utf-8\"),\n    @Header(name = \"User-Agent\", value = \"Square Cash\")\n})\nLogReceipt recordEvent(LogRecord logRecord);\n```\n\nNote that you can call `addMember()` multiple times with the same property name to populate a list\nof values for that property.\n\n### Javadoc\n\nFields, methods and types can be documented with Javadoc:\n\n```java\nMethodSpec dismiss = MethodSpec.methodBuilder(\"dismiss\")\n    .addJavadoc(\"Hides {@code message} from the caller's history. Other\\n\"\n        + \"participants in the conversation will continue to see the\\n\"\n        + \"message in their own history unless they also delete it.\\n\")\n    .addJavadoc(\"\\n\")\n    .addJavadoc(\"<p>Use {@link #delete($T)} to delete the entire\\n\"\n        + \"conversation for all participants.\\n\", Conversation.class)\n    .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n    .addParameter(Message.class, \"message\")\n    .build();\n```\n\nWhich generates this:\n\n```java\n  /**\n   * Hides {@code message} from the caller's history. Other\n   * participants in the conversation will continue to see the\n   * message in their own history unless they also delete it.\n   *\n   * <p>Use {@link #delete(Conversation)} to delete the entire\n   * conversation for all participants.\n   */\n  void dismiss(Message message);\n```\n\nUse `$T` when referencing types in Javadoc to get automatic imports.\n\nDownload\n--------\n\nDownload [the latest .jar][dl] or depend via Maven:\n```xml\n<dependency>\n  <groupId>com.squareup</groupId>\n  <artifactId>javapoet</artifactId>\n  <version>1.13.0</version>\n</dependency>\n```\nor Gradle:\n```groovy\ncompile 'com.squareup:javapoet:1.13.0'\n```\n\nSnapshots of the development version are available in [Sonatype's `snapshots` repository][snap].\n\n\n\nLicense\n-------\n\n    Copyright 2015 Square, Inc.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n\n\nJavaWriter\n==========\n\nJavaPoet is the successor to [JavaWriter][javawriter]. New projects should prefer JavaPoet because\nit has a stronger code model: it understands types and can manage imports automatically. JavaPoet is\nalso better suited to composition: rather than streaming the contents of a `.java` file\ntop-to-bottom in a single pass, a file can be assembled as a tree of declarations.\n\nJavaWriter continues to be available in [GitHub][javawriter] and [Maven Central][javawriter_maven].\n\n\n [dl]: https://search.maven.org/remote_content?g=com.squareup&a=javapoet&v=LATEST\n [snap]: https://oss.sonatype.org/content/repositories/snapshots/com/squareup/javapoet/\n [javadoc]: https://square.github.io/javapoet/1.x/javapoet/\n [javawriter]: https://github.com/square/javapoet/tree/javawriter_2\n [javawriter_maven]: https://search.maven.org/#artifactdetails%7Ccom.squareup%7Cjavawriter%7C2.5.1%7Cjar\n [formatter]: https://developer.android.com/reference/java/util/Formatter.html\n [modifier]: https://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Modifier.html\n"
  },
  {
    "path": "RELEASING.md",
    "content": "Releasing\n=========\n\n1. Update the CHANGELOG.md for the impending release.\n2. Update the README.md with the new version.\n3. `git commit -am \"Update changelog for X.Y.Z.\"` (where X.Y.Z is the new version).\n4. `mvn-release`.\n    * `What is the release version for \"JavaPoet\"? (com.squareup.javapoet) X.Y.Z:` - hit Enter.\n    * `What is SCM release tag or label for \"JavaPoet\"? (com.squareup.javapoet) javapoet-X.Y.Z:` - hit Enter.\n    * `What is the new development version for \"JavaPoet\"? (com.squareup.javapoet) X.Y.(Z + 1)-SNAPSHOT:` - enter `X.(Y + 1).0-SNAPSHOT`.\n    * Enter your GPG Passphrase when prompted.\n5. Visit Sonatype Nexus and promote the artifact.\n\nIf step 4 or 5 fails:\n\n  * Drop the Sonatype repo, \n  * Fix the problem,\n  * Manully revert the version change in `pom.xml` made by `mvn-release`,\n  * Commit,\n  * And start again at step 4.\n\nPrerequisites\n-------------\n\nIn `~/.m2/settings.xml`, set the following:\n\n```xml\n<settings>\n  <servers>\n    <server>\n      <id>sonatype-nexus-staging</id>\n      <username>your-nexus-username</username>\n      <password>your-nexus-password</password>\n    </server>\n  </servers>\n</settings>\n```\n\nIn your shell's `.rc` file, set the following:\n\n```\nalias mvn-release='mvn clean source:jar javadoc:jar verify && mvn clean release:clean && mvn release:prepare release:perform'\n```\n\nRefer to the [GPG Keys][gpg_keys] guide if you need to set up GPG keys for signing.\n\n [gpg_keys]: https://square.github.io/okio/releasing/#prerequisite-gpg-keys\n"
  },
  {
    "path": "checkstyle.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE module PUBLIC\n    \"-//Puppy Crawl//DTD Check Configuration 1.3//EN\"\n    \"http://www.puppycrawl.com/dtds/configuration_1_3.dtd\">\n\n<module name=\"Checker\">\n  <module name=\"SuppressWarningsFilter\"/>\n  <module name=\"NewlineAtEndOfFile\"/>\n  <module name=\"FileLength\"/>\n  <module name=\"FileTabCharacter\"/>\n\n  <!-- Trailing spaces -->\n  <module name=\"RegexpSingleline\">\n    <property name=\"format\" value=\"\\s+$\"/>\n    <property name=\"message\" value=\"Line has trailing spaces.\"/>\n  </module>\n\n  <!-- Space after 'for' and 'if' -->\n  <module name=\"RegexpSingleline\">\n    <property name=\"format\" value=\"^\\s*(for|if)\\b[^ ]\"/>\n    <property name=\"message\" value=\"Space needed before opening parenthesis.\"/>\n  </module>\n\n  <!-- For each spacing -->\n  <module name=\"RegexpSingleline\">\n    <property name=\"format\" value=\"^\\s*for \\(.*?([^ ]:|:[^ ])\"/>\n    <property name=\"message\" value=\"Space needed around ':' character.\"/>\n  </module>\n\n  <module name=\"TreeWalker\">\n    <property name=\"cacheFile\" value=\"${checkstyle.cache.file}\"/>\n\n    <!-- Checks for Javadoc comments.                     -->\n    <!-- See http://checkstyle.sf.net/config_javadoc.html -->\n    <!--module name=\"JavadocMethod\"/-->\n    <!--module name=\"JavadocType\"/-->\n    <!--module name=\"JavadocVariable\"/-->\n    <module name=\"JavadocStyle\"/>\n\n\n    <!-- Checks for Naming Conventions.                  -->\n    <!-- See http://checkstyle.sf.net/config_naming.html -->\n    <module name=\"ConstantName\"/>\n    <module name=\"LocalFinalVariableName\"/>\n    <module name=\"LocalVariableName\"/>\n    <module name=\"MemberName\"/>\n    <module name=\"MethodName\"/>\n    <module name=\"PackageName\"/>\n    <module name=\"ParameterName\"/>\n    <module name=\"StaticVariableName\"/>\n    <module name=\"TypeName\"/>\n\n\n    <!-- Checks for imports                              -->\n    <!-- See http://checkstyle.sf.net/config_import.html -->\n    <module name=\"AvoidStarImport\"/>\n    <module name=\"IllegalImport\"/>\n    <!-- defaults to sun.* packages -->\n    <module name=\"RedundantImport\"/>\n    <module name=\"UnusedImports\">\n      <property name=\"processJavadoc\" value=\"true\"/>\n    </module>\n\n\n    <!-- Checks for Size Violations.                    -->\n    <!-- See http://checkstyle.sf.net/config_sizes.html -->\n    <module name=\"LineLength\">\n      <property name=\"max\" value=\"100\"/>\n    </module>\n    <module name=\"MethodLength\">\n      <property name=\"max\" value=\"160\"/>\n    </module>\n    <module name=\"ParameterNumber\"/>\n\n\n    <!-- Checks for whitespace                               -->\n    <!-- See http://checkstyle.sf.net/config_whitespace.html -->\n    <module name=\"GenericWhitespace\"/>\n    <!--<module name=\"EmptyForIteratorPad\"/>-->\n    <module name=\"MethodParamPad\"/>\n    <module name=\"NoWhitespaceAfter\"/>\n    <module name=\"NoWhitespaceBefore\"/>\n    <module name=\"OperatorWrap\"/>\n    <module name=\"ParenPad\"/>\n    <module name=\"TypecastParenPad\"/>\n    <module name=\"WhitespaceAfter\"/>\n    <module name=\"WhitespaceAround\">\n      <property name=\"tokens\"\n          value=\"ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN,\n          COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_CATCH,\n          LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,\n          LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS,\n          MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, SL, SLIST,\n          SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND\"/>\n    </module>\n\n\n    <!-- Modifier Checks                                    -->\n    <!-- See http://checkstyle.sf.net/config_modifiers.html -->\n    <module name=\"ModifierOrder\"/>\n    <module name=\"RedundantModifier\"/>\n\n\n    <!-- Checks for blocks. You know, those {}'s         -->\n    <!-- See http://checkstyle.sf.net/config_blocks.html -->\n    <module name=\"AvoidNestedBlocks\"/>\n    <!--module name=\"EmptyBlock\"/-->\n    <module name=\"LeftCurly\"/>\n    <!--<module name=\"NeedBraces\"/>-->\n    <module name=\"RightCurly\"/>\n\n\n    <!-- Checks for common coding problems               -->\n    <!-- See http://checkstyle.sf.net/config_coding.html -->\n    <!--module name=\"AvoidInlineConditionals\"/-->\n    <module name=\"CovariantEquals\"/>\n    <module name=\"EmptyStatement\"/>\n    <!--<module name=\"EqualsAvoidNull\"/>-->\n    <module name=\"EqualsHashCode\"/>\n    <!--module name=\"HiddenField\"/-->\n    <module name=\"IllegalInstantiation\"/>\n    <module name=\"InnerAssignment\"/>\n    <!--<module name=\"MagicNumber\"/>-->\n    <module name=\"MissingSwitchDefault\"/>\n    <!--module name=\"RedundantThrows\"/-->\n    <module name=\"SimplifyBooleanExpression\"/>\n    <module name=\"SimplifyBooleanReturn\"/>\n\n    <!-- Checks for class design                         -->\n    <!-- See http://checkstyle.sf.net/config_design.html -->\n    <!--module name=\"DesignForExtension\"/-->\n    <module name=\"FinalClass\"/>\n    <module name=\"HideUtilityClassConstructor\"/>\n    <module name=\"InterfaceIsType\"/>\n    <!--module name=\"VisibilityModifier\"/-->\n\n\n    <!-- Miscellaneous other checks.                   -->\n    <!-- See http://checkstyle.sf.net/config_misc.html -->\n    <module name=\"ArrayTypeStyle\"/>\n    <!--module name=\"FinalParameters\"/-->\n    <module name=\"TodoComment\"/>\n    <module name=\"UpperEll\"/>\n\n    <!-- Make the @SuppressWarnings annotations available to Checkstyle -->\n    <module name=\"SuppressWarningsHolder\"/>\n  </module>\n</module>\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n\n  <parent>\n    <groupId>org.sonatype.oss</groupId>\n    <artifactId>oss-parent</artifactId>\n    <version>7</version>\n  </parent>\n\n  <groupId>com.squareup</groupId>\n  <artifactId>javapoet</artifactId>\n  <version>1.14.0-SNAPSHOT</version>\n\n  <name>JavaPoet</name>\n  <description>Use beautiful Java code to generate beautiful Java code.</description>\n  <url>http://github.com/square/javapoet/</url>\n\n  <properties>\n    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\n    <java.version>1.8</java.version>\n    <junit.version>4.13.2</junit.version>\n    <truth.version>1.4.4</truth.version>\n    <compile-testing.version>0.21.0</compile-testing.version>\n  </properties>\n\n  <scm>\n    <url>http://github.com/square/javapoet/</url>\n    <connection>scm:git:git://github.com/square/javapoet.git</connection>\n    <developerConnection>scm:git:ssh://git@github.com/square/javapoet.git</developerConnection>\n    <tag>HEAD</tag>\n  </scm>\n\n  <issueManagement>\n    <system>GitHub Issues</system>\n    <url>http://github.com/square/javapoet/issues</url>\n  </issueManagement>\n\n  <licenses>\n    <license>\n      <name>Apache 2.0</name>\n      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>\n    </license>\n  </licenses>\n\n  <organization>\n    <name>Square, Inc.</name>\n    <url>http://squareup.com</url>\n  </organization>\n\n  <dependencies>\n    <dependency>\n      <groupId>com.google.truth</groupId>\n      <artifactId>truth</artifactId>\n      <version>${truth.version}</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>com.google.testing.compile</groupId>\n      <artifactId>compile-testing</artifactId>\n      <version>${compile-testing.version}</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>junit</groupId>\n      <artifactId>junit</artifactId>\n      <version>${junit.version}</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>com.google.jimfs</groupId>\n      <artifactId>jimfs</artifactId>\n      <version>1.3.0</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <version>4.11.0</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.eclipse.jdt.core.compiler</groupId>\n      <artifactId>ecj</artifactId>\n      <version>4.6.1</version>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-compiler-plugin</artifactId>\n        <version>3.12.1</version>\n        <configuration>\n          <compilerId>javac-with-errorprone</compilerId>\n          <forceJavacCompilerUse>true</forceJavacCompilerUse>\n          <source>${java.version}</source>\n          <target>${java.version}</target>\n        </configuration>\n        <dependencies>\n          <dependency>\n            <groupId>org.codehaus.plexus</groupId>\n            <artifactId>plexus-compiler-javac-errorprone</artifactId>\n            <version>2.8.2</version>\n          </dependency>\n          <dependency>\n            <groupId>com.google.errorprone</groupId>\n            <artifactId>error_prone_core</artifactId>\n            <version>2.3.1</version>\n          </dependency>\n        </dependencies>\n      </plugin>\n\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-checkstyle-plugin</artifactId>\n        <version>3.5.0</version>\n        <dependencies>\n          <dependency>\n            <groupId>com.puppycrawl.tools</groupId>\n            <artifactId>checkstyle</artifactId>\n            <version>8.18</version>\n          </dependency>\n        </dependencies>\n        <configuration>\n          <failsOnError>true</failsOnError>\n          <configLocation>checkstyle.xml</configLocation>\n          <consoleOutput>true</consoleOutput>\n        </configuration>\n        <executions>\n          <execution>\n            <phase>verify</phase>\n            <goals>\n              <goal>checkstyle</goal>\n            </goals>\n          </execution>\n        </executions>\n      </plugin>\n\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-jar-plugin</artifactId>\n        <version>3.4.2</version>\n        <configuration>\n          <archive>\n            <manifestEntries>\n              <Automatic-Module-Name>com.squareup.javapoet</Automatic-Module-Name>\n            </manifestEntries>\n          </archive>\n        </configuration>\n      </plugin>\n\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "renovate.json",
    "content": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\n    \"config:base\"\n  ]\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/AnnotationSpec.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.annotation.Annotation;\nimport java.lang.reflect.Array;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.AnnotationMirror;\nimport javax.lang.model.element.AnnotationValue;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.element.VariableElement;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.util.SimpleAnnotationValueVisitor8;\n\nimport static com.squareup.javapoet.Util.characterLiteralWithoutSingleQuotes;\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\n\n/** A generated annotation on a declaration. */\npublic final class AnnotationSpec {\n  public static final String VALUE = \"value\";\n\n  public final TypeName type;\n  public final Map<String, List<CodeBlock>> members;\n\n  private AnnotationSpec(Builder builder) {\n    this.type = builder.type;\n    this.members = Util.immutableMultimap(builder.members);\n  }\n\n  void emit(CodeWriter codeWriter, boolean inline) throws IOException {\n    String whitespace = inline ? \"\" : \"\\n\";\n    String memberSeparator = inline ? \", \" : \",\\n\";\n    if (members.isEmpty()) {\n      // @Singleton\n      codeWriter.emit(\"@$T\", type);\n    } else if (members.size() == 1 && members.containsKey(\"value\")) {\n      // @Named(\"foo\")\n      codeWriter.emit(\"@$T(\", type);\n      emitAnnotationValues(codeWriter, whitespace, memberSeparator, members.get(\"value\"));\n      codeWriter.emit(\")\");\n    } else {\n      // Inline:\n      //   @Column(name = \"updated_at\", nullable = false)\n      //\n      // Not inline:\n      //   @Column(\n      //       name = \"updated_at\",\n      //       nullable = false\n      //   )\n      codeWriter.emit(\"@$T(\" + whitespace, type);\n      codeWriter.indent(2);\n      for (Iterator<Map.Entry<String, List<CodeBlock>>> i\n          = members.entrySet().iterator(); i.hasNext(); ) {\n        Map.Entry<String, List<CodeBlock>> entry = i.next();\n        codeWriter.emit(\"$L = \", entry.getKey());\n        emitAnnotationValues(codeWriter, whitespace, memberSeparator, entry.getValue());\n        if (i.hasNext()) codeWriter.emit(memberSeparator);\n      }\n      codeWriter.unindent(2);\n      codeWriter.emit(whitespace + \")\");\n    }\n  }\n\n  private void emitAnnotationValues(CodeWriter codeWriter, String whitespace,\n      String memberSeparator, List<CodeBlock> values) throws IOException {\n    if (values.size() == 1) {\n      codeWriter.indent(2);\n      codeWriter.emit(values.get(0));\n      codeWriter.unindent(2);\n      return;\n    }\n\n    codeWriter.emit(\"{\" + whitespace);\n    codeWriter.indent(2);\n    boolean first = true;\n    for (CodeBlock codeBlock : values) {\n      if (!first) codeWriter.emit(memberSeparator);\n      codeWriter.emit(codeBlock);\n      first = false;\n    }\n    codeWriter.unindent(2);\n    codeWriter.emit(whitespace + \"}\");\n  }\n\n  public static AnnotationSpec get(Annotation annotation) {\n    return get(annotation, false);\n  }\n\n  public static AnnotationSpec get(Annotation annotation, boolean includeDefaultValues) {\n    Builder builder = builder(annotation.annotationType());\n    try {\n      Method[] methods = annotation.annotationType().getDeclaredMethods();\n      Arrays.sort(methods, Comparator.comparing(Method::getName));\n      for (Method method : methods) {\n        Object value = method.invoke(annotation);\n        if (!includeDefaultValues) {\n          if (Objects.deepEquals(value, method.getDefaultValue())) {\n            continue;\n          }\n        }\n        if (value.getClass().isArray()) {\n          for (int i = 0; i < Array.getLength(value); i++) {\n            builder.addMemberForValue(method.getName(), Array.get(value, i));\n          }\n          continue;\n        }\n        if (value instanceof Annotation) {\n          builder.addMember(method.getName(), \"$L\", get((Annotation) value));\n          continue;\n        }\n        builder.addMemberForValue(method.getName(), value);\n      }\n    } catch (Exception e) {\n      throw new RuntimeException(\"Reflecting \" + annotation + \" failed!\", e);\n    }\n    return builder.build();\n  }\n\n  public static AnnotationSpec get(AnnotationMirror annotation) {\n    TypeElement element = (TypeElement) annotation.getAnnotationType().asElement();\n    AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassName.get(element));\n    Visitor visitor = new Visitor(builder);\n    for (ExecutableElement executableElement : annotation.getElementValues().keySet()) {\n      String name = executableElement.getSimpleName().toString();\n      AnnotationValue value = annotation.getElementValues().get(executableElement);\n      value.accept(visitor, name);\n    }\n    return builder.build();\n  }\n\n  public static Builder builder(ClassName type) {\n    checkNotNull(type, \"type == null\");\n    return new Builder(type);\n  }\n\n  public static Builder builder(Class<?> type) {\n    return builder(ClassName.get(type));\n  }\n\n  public Builder toBuilder() {\n    Builder builder = new Builder(type);\n    for (Map.Entry<String, List<CodeBlock>> entry : members.entrySet()) {\n      builder.members.put(entry.getKey(), new ArrayList<>(entry.getValue()));\n    }\n    return builder;\n  }\n\n  @Override public boolean equals(Object o) {\n    if (this == o) return true;\n    if (o == null) return false;\n    if (getClass() != o.getClass()) return false;\n    return toString().equals(o.toString());\n  }\n\n  @Override public int hashCode() {\n    return toString().hashCode();\n  }\n\n  @Override public String toString() {\n    StringBuilder out = new StringBuilder();\n    try {\n      CodeWriter codeWriter = new CodeWriter(out);\n      codeWriter.emit(\"$L\", this);\n      return out.toString();\n    } catch (IOException e) {\n      throw new AssertionError();\n    }\n  }\n\n  public static final class Builder {\n    private final TypeName type;\n\n    public final Map<String, List<CodeBlock>> members = new LinkedHashMap<>();\n\n    private Builder(TypeName type) {\n      this.type = type;\n    }\n\n    public Builder addMember(String name, String format, Object... args) {\n      return addMember(name, CodeBlock.of(format, args));\n    }\n\n    public Builder addMember(String name, CodeBlock codeBlock) {\n      List<CodeBlock> values = members.computeIfAbsent(name, k -> new ArrayList<>());\n      values.add(codeBlock);\n      return this;\n    }\n\n    /**\n     * Delegates to {@link #addMember(String, String, Object...)}, with parameter {@code format}\n     * depending on the given {@code value} object. Falls back to {@code \"$L\"} literal format if\n     * the class of the given {@code value} object is not supported.\n     */\n    Builder addMemberForValue(String memberName, Object value) {\n      checkNotNull(memberName, \"memberName == null\");\n      checkNotNull(value, \"value == null, constant non-null value expected for %s\", memberName);\n      checkArgument(SourceVersion.isName(memberName), \"not a valid name: %s\", memberName);\n      if (value instanceof Class<?>) {\n        return addMember(memberName, \"$T.class\", value);\n      }\n      if (value instanceof Enum) {\n        return addMember(memberName, \"$T.$L\", value.getClass(), ((Enum<?>) value).name());\n      }\n      if (value instanceof String) {\n        return addMember(memberName, \"$S\", value);\n      }\n      if (value instanceof Float) {\n        return addMember(memberName, \"$Lf\", value);\n      }\n      if (value instanceof Long) {\n        return addMember(memberName, \"$LL\", value);\n      }\n      if (value instanceof Character) {\n        return addMember(memberName, \"'$L'\", characterLiteralWithoutSingleQuotes((char) value));\n      }\n      return addMember(memberName, \"$L\", value);\n    }\n\n    public AnnotationSpec build() {\n      for (String name : members.keySet()) {\n        checkNotNull(name, \"name == null\");\n        checkArgument(SourceVersion.isName(name), \"not a valid name: %s\", name);\n      }\n      return new AnnotationSpec(this);\n    }\n  }\n\n  /**\n   * Annotation value visitor adding members to the given builder instance.\n   */\n  private static class Visitor extends SimpleAnnotationValueVisitor8<Builder, String> {\n    final Builder builder;\n\n    Visitor(Builder builder) {\n      super(builder);\n      this.builder = builder;\n    }\n\n    @Override protected Builder defaultAction(Object o, String name) {\n      return builder.addMemberForValue(name, o);\n    }\n\n    @Override public Builder visitAnnotation(AnnotationMirror a, String name) {\n      return builder.addMember(name, \"$L\", get(a));\n    }\n\n    @Override public Builder visitEnumConstant(VariableElement c, String name) {\n      return builder.addMember(name, \"$T.$L\", c.asType(), c.getSimpleName());\n    }\n\n    @Override public Builder visitType(TypeMirror t, String name) {\n      return builder.addMember(name, \"$T.class\", t);\n    }\n\n    @Override public Builder visitArray(List<? extends AnnotationValue> values, String name) {\n      for (AnnotationValue value : values) {\n        value.accept(this, name);\n      }\n      return builder;\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/ArrayTypeName.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.GenericArrayType;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport javax.lang.model.element.TypeParameterElement;\nimport javax.lang.model.type.ArrayType;\n\nimport static com.squareup.javapoet.Util.checkNotNull;\n\npublic final class ArrayTypeName extends TypeName {\n  public final TypeName componentType;\n\n  private ArrayTypeName(TypeName componentType) {\n    this(componentType, new ArrayList<>());\n  }\n\n  private ArrayTypeName(TypeName componentType, List<AnnotationSpec> annotations) {\n    super(annotations);\n    this.componentType = checkNotNull(componentType, \"rawType == null\");\n  }\n\n  @Override public ArrayTypeName annotated(List<AnnotationSpec> annotations) {\n    return new ArrayTypeName(componentType, concatAnnotations(annotations));\n  }\n\n  @Override public TypeName withoutAnnotations() {\n    return new ArrayTypeName(componentType);\n  }\n\n  @Override CodeWriter emit(CodeWriter out) throws IOException {\n    return emit(out, false);\n  }\n\n  CodeWriter emit(CodeWriter out, boolean varargs) throws IOException {\n    emitLeafType(out);\n    return emitBrackets(out, varargs);\n  }\n\n  private CodeWriter emitLeafType(CodeWriter out) throws IOException {\n    if (TypeName.asArray(componentType) != null) {\n      return TypeName.asArray(componentType).emitLeafType(out);\n    }\n    return componentType.emit(out);\n  }\n\n  private CodeWriter emitBrackets(CodeWriter out, boolean varargs) throws IOException {\n    if (isAnnotated()) {\n      out.emit(\" \");\n      emitAnnotations(out);\n    }\n\n    if (TypeName.asArray(componentType) == null) {\n      // Last bracket.\n      return out.emit(varargs ? \"...\" : \"[]\");\n    }\n    out.emit(\"[]\");\n    return TypeName.asArray(componentType) .emitBrackets(out, varargs);\n  }\n\n\n  /** Returns an array type whose elements are all instances of {@code componentType}. */\n  public static ArrayTypeName of(TypeName componentType) {\n    return new ArrayTypeName(componentType);\n  }\n\n  /** Returns an array type whose elements are all instances of {@code componentType}. */\n  public static ArrayTypeName of(Type componentType) {\n    return of(TypeName.get(componentType));\n  }\n\n  /** Returns an array type equivalent to {@code mirror}. */\n  public static ArrayTypeName get(ArrayType mirror) {\n    return get(mirror, new LinkedHashMap<>());\n  }\n\n  static ArrayTypeName get(\n      ArrayType mirror, Map<TypeParameterElement, TypeVariableName> typeVariables) {\n    return new ArrayTypeName(get(mirror.getComponentType(), typeVariables));\n  }\n\n  /** Returns an array type equivalent to {@code type}. */\n  public static ArrayTypeName get(GenericArrayType type) {\n    return get(type, new LinkedHashMap<>());\n  }\n\n  static ArrayTypeName get(GenericArrayType type, Map<Type, TypeVariableName> map) {\n    return ArrayTypeName.of(get(type.getGenericComponentType(), map));\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/ClassName.java",
    "content": "/*\n * Copyright (C) 2014 Google, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.PackageElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.util.SimpleElementVisitor8;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\n\n/** A fully-qualified class name for top-level and member classes. */\npublic final class ClassName extends TypeName implements Comparable<ClassName> {\n  public static final ClassName OBJECT = ClassName.get(Object.class);\n\n  /** The name representing the default Java package. */\n  private static final String NO_PACKAGE = \"\";\n\n  /** The package name of this class, or \"\" if this is in the default package. */\n  final String packageName;\n\n  /** The enclosing class, or null if this is not enclosed in another class. */\n  final ClassName enclosingClassName;\n\n  /** This class name, like \"Entry\" for java.util.Map.Entry. */\n  final String simpleName;\n\n  private List<String> simpleNames;\n\n  /** The full class name like \"java.util.Map.Entry\". */\n  final String canonicalName;\n\n  private ClassName(String packageName, ClassName enclosingClassName, String simpleName) {\n    this(packageName, enclosingClassName, simpleName, Collections.emptyList());\n  }\n\n  private ClassName(String packageName, ClassName enclosingClassName, String simpleName,\n      List<AnnotationSpec> annotations) {\n    super(annotations);\n    this.packageName = Objects.requireNonNull(packageName, \"packageName == null\");\n    this.enclosingClassName = enclosingClassName;\n    this.simpleName = simpleName;\n    this.canonicalName = enclosingClassName != null\n        ? (enclosingClassName.canonicalName + '.' + simpleName)\n        : (packageName.isEmpty() ? simpleName : packageName + '.' + simpleName);\n  }\n\n  @Override public ClassName annotated(List<AnnotationSpec> annotations) {\n    return new ClassName(packageName, enclosingClassName, simpleName,\n        concatAnnotations(annotations));\n  }\n\n  @Override public ClassName withoutAnnotations() {\n    if (!isAnnotated()) return this;\n    ClassName resultEnclosingClassName = enclosingClassName != null\n        ? enclosingClassName.withoutAnnotations()\n        : null;\n    return new ClassName(packageName, resultEnclosingClassName, simpleName);\n  }\n\n  @Override public boolean isAnnotated() {\n    return super.isAnnotated() || (enclosingClassName != null && enclosingClassName.isAnnotated());\n  }\n\n  /**\n   * Returns the package name, like {@code \"java.util\"} for {@code Map.Entry}. Returns the empty\n   * string for the default package.\n   */\n  public String packageName() {\n    return packageName;\n  }\n\n  /**\n   * Returns the enclosing class, like {@link Map} for {@code Map.Entry}. Returns null if this class\n   * is not nested in another class.\n   */\n  public ClassName enclosingClassName() {\n    return enclosingClassName;\n  }\n\n  /**\n   * Returns the top class in this nesting group. Equivalent to chained calls to {@link\n   * #enclosingClassName()} until the result's enclosing class is null.\n   */\n  public ClassName topLevelClassName() {\n    return enclosingClassName != null ? enclosingClassName.topLevelClassName() : this;\n  }\n\n  /** Return the binary name of a class. */\n  public String reflectionName() {\n    return enclosingClassName != null\n        ? (enclosingClassName.reflectionName() + '$' + simpleName)\n        : (packageName.isEmpty() ? simpleName : packageName + '.' + simpleName);\n  }\n\n  public List<String> simpleNames() {\n    if (simpleNames != null) {\n      return simpleNames;\n    }\n\n    if (enclosingClassName == null) {\n      simpleNames = Collections.singletonList(simpleName);\n    } else {\n      List<String> mutableNames = new ArrayList<>();\n      mutableNames.addAll(enclosingClassName().simpleNames());\n      mutableNames.add(simpleName);\n      simpleNames = Collections.unmodifiableList(mutableNames);\n    }\n    return simpleNames;\n  }\n\n  /**\n   * Returns a class that shares the same enclosing package or class. If this class is enclosed by\n   * another class, this is equivalent to {@code enclosingClassName().nestedClass(name)}. Otherwise\n   * it is equivalent to {@code get(packageName(), name)}.\n   */\n  public ClassName peerClass(String name) {\n    return new ClassName(packageName, enclosingClassName, name);\n  }\n\n  /**\n   * Returns a new {@link ClassName} instance for the specified {@code name} as nested inside this\n   * class.\n   */\n  public ClassName nestedClass(String name) {\n    return new ClassName(packageName, this, name);\n  }\n\n  /** Returns the simple name of this class, like {@code \"Entry\"} for {@link Map.Entry}. */\n  public String simpleName() {\n    return simpleName;\n  }\n\n  /**\n   * Returns the full class name of this class.\n   * Like {@code \"java.util.Map.Entry\"} for {@link Map.Entry}.\n   * */\n  public String canonicalName() {\n    return canonicalName;\n  }\n\n  public static ClassName get(Class<?> clazz) {\n    checkNotNull(clazz, \"clazz == null\");\n    checkArgument(!clazz.isPrimitive(), \"primitive types cannot be represented as a ClassName\");\n    checkArgument(!void.class.equals(clazz), \"'void' type cannot be represented as a ClassName\");\n    checkArgument(!clazz.isArray(), \"array types cannot be represented as a ClassName\");\n\n    String anonymousSuffix = \"\";\n    while (clazz.isAnonymousClass()) {\n      int lastDollar = clazz.getName().lastIndexOf('$');\n      anonymousSuffix = clazz.getName().substring(lastDollar) + anonymousSuffix;\n      clazz = clazz.getEnclosingClass();\n    }\n    String name = clazz.getSimpleName() + anonymousSuffix;\n\n    if (clazz.getEnclosingClass() == null) {\n      // Avoid unreliable Class.getPackage(). https://github.com/square/javapoet/issues/295\n      int lastDot = clazz.getName().lastIndexOf('.');\n      String packageName = (lastDot != -1) ? clazz.getName().substring(0, lastDot) : NO_PACKAGE;\n      return new ClassName(packageName, null, name);\n    }\n\n    return ClassName.get(clazz.getEnclosingClass()).nestedClass(name);\n  }\n\n  /**\n   * Returns a new {@link ClassName} instance for the given fully-qualified class name string. This\n   * method assumes that the input is ASCII and follows typical Java style (lowercase package\n   * names, UpperCamelCase class names) and may produce incorrect results or throw\n   * {@link IllegalArgumentException} otherwise. For that reason, {@link #get(Class)} and\n   * {@link #get(Class)} should be preferred as they can correctly create {@link ClassName}\n   * instances without such restrictions.\n   */\n  public static ClassName bestGuess(String classNameString) {\n    // Add the package name, like \"java.util.concurrent\", or \"\" for no package.\n    int p = 0;\n    while (p < classNameString.length() && Character.isLowerCase(classNameString.codePointAt(p))) {\n      p = classNameString.indexOf('.', p) + 1;\n      checkArgument(p != 0, \"couldn't make a guess for %s\", classNameString);\n    }\n    String packageName = p == 0 ? NO_PACKAGE : classNameString.substring(0, p - 1);\n\n    // Add class names like \"Map\" and \"Entry\".\n    ClassName className = null;\n    for (String simpleName : classNameString.substring(p).split(\"\\\\.\", -1)) {\n      checkArgument(!simpleName.isEmpty() && Character.isUpperCase(simpleName.codePointAt(0)),\n          \"couldn't make a guess for %s\", classNameString);\n      className = new ClassName(packageName, className, simpleName);\n    }\n\n    return className;\n  }\n\n  /**\n   * Returns a class name created from the given parts. For example, calling this with package name\n   * {@code \"java.util\"} and simple names {@code \"Map\"}, {@code \"Entry\"} yields {@link Map.Entry}.\n   */\n  public static ClassName get(String packageName, String simpleName, String... simpleNames) {\n    ClassName className = new ClassName(packageName, null, simpleName);\n    for (String name : simpleNames) {\n      className = className.nestedClass(name);\n    }\n    return className;\n  }\n\n  /** Returns the class name for {@code element}. */\n  public static ClassName get(TypeElement element) {\n    checkNotNull(element, \"element == null\");\n    String simpleName = element.getSimpleName().toString();\n\n    return element.getEnclosingElement().accept(new SimpleElementVisitor8<ClassName, Void>() {\n      @Override public ClassName visitPackage(PackageElement packageElement, Void p) {\n        return new ClassName(packageElement.getQualifiedName().toString(), null, simpleName);\n      }\n\n      @Override public ClassName visitType(TypeElement enclosingClass, Void p) {\n        return ClassName.get(enclosingClass).nestedClass(simpleName);\n      }\n\n      @Override public ClassName visitUnknown(Element unknown, Void p) {\n        return get(\"\", simpleName);\n      }\n\n      @Override public ClassName defaultAction(Element enclosingElement, Void p) {\n        throw new IllegalArgumentException(\"Unexpected type nesting: \" + element);\n      }\n    }, null);\n  }\n\n  @Override public int compareTo(ClassName o) {\n    return canonicalName.compareTo(o.canonicalName);\n  }\n\n  @Override CodeWriter emit(CodeWriter out) throws IOException {\n    boolean charsEmitted = false;\n    for (ClassName className : enclosingClasses()) {\n      String simpleName;\n      if (charsEmitted) {\n        // We've already emitted an enclosing class. Emit as we go.\n        out.emit(\".\");\n        simpleName = className.simpleName;\n\n      } else if (className.isAnnotated() || className == this) {\n        // We encountered the first enclosing class that must be emitted.\n        String qualifiedName = out.lookupName(className);\n        int dot = qualifiedName.lastIndexOf('.');\n        if (dot != -1) {\n          out.emitAndIndent(qualifiedName.substring(0, dot + 1));\n          simpleName = qualifiedName.substring(dot + 1);\n          charsEmitted = true;\n        } else {\n          simpleName = qualifiedName;\n        }\n\n      } else {\n        // Don't emit this enclosing type. Keep going so we can be more precise.\n        continue;\n      }\n\n      if (className.isAnnotated()) {\n        if (charsEmitted) out.emit(\" \");\n        className.emitAnnotations(out);\n      }\n\n      out.emit(simpleName);\n      charsEmitted = true;\n    }\n\n    return out;\n  }\n\n  /** Returns all enclosing classes in this, outermost first. */\n  private List<ClassName> enclosingClasses() {\n    List<ClassName> result = new ArrayList<>();\n    for (ClassName c = this; c != null; c = c.enclosingClassName) {\n      result.add(c);\n    }\n    Collections.reverse(result);\n    return result;\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/CodeBlock.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\nimport java.util.stream.Collector;\nimport java.util.stream.StreamSupport;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.type.TypeMirror;\n\nimport static com.squareup.javapoet.Util.checkArgument;\n\n/**\n * A fragment of a .java file, potentially containing declarations, statements, and documentation.\n * Code blocks are not necessarily well-formed Java code, and are not validated. This class assumes\n * javac will check correctness later!\n *\n * <p>Code blocks support placeholders like {@link java.text.Format}. Where {@link String#format}\n * uses percent {@code %} to reference target values, this class uses dollar sign {@code $} and has\n * its own set of permitted placeholders:\n *\n * <ul>\n *   <li>{@code $L} emits a <em>literal</em> value with no escaping. Arguments for literals may be\n *       strings, primitives, {@linkplain TypeSpec type declarations}, {@linkplain AnnotationSpec\n *       annotations} and even other code blocks.\n *   <li>{@code $N} emits a <em>name</em>, using name collision avoidance where necessary. Arguments\n *       for names may be strings (actually any {@linkplain CharSequence character sequence}),\n *       {@linkplain ParameterSpec parameters}, {@linkplain FieldSpec fields}, {@linkplain\n *       MethodSpec methods}, and {@linkplain TypeSpec types}.\n *   <li>{@code $S} escapes the value as a <em>string</em>, wraps it with double quotes, and emits\n *       that. For example, {@code 6\" sandwich} is emitted {@code \"6\\\" sandwich\"}.\n *   <li>{@code $T} emits a <em>type</em> reference. Types will be imported if possible. Arguments\n *       for types may be {@linkplain Class classes}, {@linkplain javax.lang.model.type.TypeMirror\n,*       type mirrors}, and {@linkplain javax.lang.model.element.Element elements}.\n *   <li>{@code $$} emits a dollar sign.\n *   <li>{@code $W} emits a space or a newline, depending on its position on the line. This prefers\n *       to wrap lines before 100 columns.\n *   <li>{@code $Z} acts as a zero-width space. This prefers to wrap lines before 100 columns.\n *   <li>{@code $>} increases the indentation level.\n *   <li>{@code $<} decreases the indentation level.\n *   <li>{@code $[} begins a statement. For multiline statements, every line after the first line\n *       is double-indented.\n *   <li>{@code $]} ends a statement.\n * </ul>\n */\npublic final class CodeBlock {\n  private static final Pattern NAMED_ARGUMENT =\n      Pattern.compile(\"\\\\$(?<argumentName>[\\\\w_]+):(?<typeChar>[\\\\w]).*\");\n  private static final Pattern LOWERCASE = Pattern.compile(\"[a-z]+[\\\\w_]*\");\n\n  /** A heterogeneous list containing string literals and value placeholders. */\n  final List<String> formatParts;\n  final List<Object> args;\n\n  private CodeBlock(Builder builder) {\n    this.formatParts = Util.immutableList(builder.formatParts);\n    this.args = Util.immutableList(builder.args);\n  }\n\n  public boolean isEmpty() {\n    return formatParts.isEmpty();\n  }\n\n  @Override public boolean equals(Object o) {\n    if (this == o) return true;\n    if (o == null) return false;\n    if (getClass() != o.getClass()) return false;\n    return toString().equals(o.toString());\n  }\n\n  @Override public int hashCode() {\n    return toString().hashCode();\n  }\n\n  @Override public String toString() {\n    StringBuilder out = new StringBuilder();\n    try {\n      new CodeWriter(out).emit(this);\n      return out.toString();\n    } catch (IOException e) {\n      throw new AssertionError();\n    }\n  }\n\n  public static CodeBlock of(String format, Object... args) {\n    return new Builder().add(format, args).build();\n  }\n\n  /**\n   * Joins {@code codeBlocks} into a single {@link CodeBlock}, each separated by {@code separator}.\n   * For example, joining {@code String s}, {@code Object o} and {@code int i} using {@code \", \"}\n   * would produce {@code String s, Object o, int i}.\n   */\n  public static CodeBlock join(Iterable<CodeBlock> codeBlocks, String separator) {\n    return StreamSupport.stream(codeBlocks.spliterator(), false).collect(joining(separator));\n  }\n\n  /**\n   * A {@link Collector} implementation that joins {@link CodeBlock} instances together into one\n   * separated by {@code separator}. For example, joining {@code String s}, {@code Object o} and\n   * {@code int i} using {@code \", \"} would produce {@code String s, Object o, int i}.\n   */\n  public static Collector<CodeBlock, ?, CodeBlock> joining(String separator) {\n    return Collector.of(\n        () -> new CodeBlockJoiner(separator, builder()),\n        CodeBlockJoiner::add,\n        CodeBlockJoiner::merge,\n        CodeBlockJoiner::join);\n  }\n\n  /**\n   * A {@link Collector} implementation that joins {@link CodeBlock} instances together into one\n   * separated by {@code separator}. For example, joining {@code String s}, {@code Object o} and\n   * {@code int i} using {@code \", \"} would produce {@code String s, Object o, int i}.\n   */\n  public static Collector<CodeBlock, ?, CodeBlock> joining(\n      String separator, String prefix, String suffix) {\n    Builder builder = builder().add(\"$N\", prefix);\n    return Collector.of(\n        () -> new CodeBlockJoiner(separator, builder),\n        CodeBlockJoiner::add,\n        CodeBlockJoiner::merge,\n        joiner -> {\n            builder.add(CodeBlock.of(\"$N\", suffix));\n            return joiner.join();\n        });\n  }\n\n  public static Builder builder() {\n    return new Builder();\n  }\n\n  public Builder toBuilder() {\n    Builder builder = new Builder();\n    builder.formatParts.addAll(formatParts);\n    builder.args.addAll(args);\n    return builder;\n  }\n\n  public static final class Builder {\n    final List<String> formatParts = new ArrayList<>();\n    final List<Object> args = new ArrayList<>();\n\n    private Builder() {\n    }\n\n    public boolean isEmpty() {\n      return formatParts.isEmpty();\n    }\n\n    /**\n     * Adds code using named arguments.\n     *\n     * <p>Named arguments specify their name after the '$' followed by : and the corresponding type\n     * character. Argument names consist of characters in {@code a-z, A-Z, 0-9, and _} and must\n     * start with a lowercase character.\n     *\n     * <p>For example, to refer to the type {@link java.lang.Integer} with the argument name {@code\n     * clazz} use a format string containing {@code $clazz:T} and include the key {@code clazz} with\n     * value {@code java.lang.Integer.class} in the argument map.\n     */\n    public Builder addNamed(String format, Map<String, ?> arguments) {\n      int p = 0;\n\n      for (String argument : arguments.keySet()) {\n        checkArgument(LOWERCASE.matcher(argument).matches(),\n            \"argument '%s' must start with a lowercase character\", argument);\n      }\n\n      while (p < format.length()) {\n        int nextP = format.indexOf(\"$\", p);\n        if (nextP == -1) {\n          formatParts.add(format.substring(p));\n          break;\n        }\n\n        if (p != nextP) {\n          formatParts.add(format.substring(p, nextP));\n          p = nextP;\n        }\n\n        Matcher matcher = null;\n        int colon = format.indexOf(':', p);\n        if (colon != -1) {\n          int endIndex = Math.min(colon + 2, format.length());\n          matcher = NAMED_ARGUMENT.matcher(format.substring(p, endIndex));\n        }\n        if (matcher != null && matcher.lookingAt()) {\n          String argumentName = matcher.group(\"argumentName\");\n          checkArgument(arguments.containsKey(argumentName), \"Missing named argument for $%s\",\n              argumentName);\n          char formatChar = matcher.group(\"typeChar\").charAt(0);\n          addArgument(format, formatChar, arguments.get(argumentName));\n          formatParts.add(\"$\" + formatChar);\n          p += matcher.regionEnd();\n        } else {\n          checkArgument(p < format.length() - 1, \"dangling $ at end\");\n          checkArgument(isNoArgPlaceholder(format.charAt(p + 1)),\n              \"unknown format $%s at %s in '%s'\", format.charAt(p + 1), p + 1, format);\n          formatParts.add(format.substring(p, p + 2));\n          p += 2;\n        }\n      }\n\n      return this;\n    }\n\n    /**\n     * Add code with positional or relative arguments.\n     *\n     * <p>Relative arguments map 1:1 with the placeholders in the format string.\n     *\n     * <p>Positional arguments use an index after the placeholder to identify which argument index\n     * to use. For example, for a literal to reference the 3rd argument: \"$3L\" (1 based index)\n     *\n     * <p>Mixing relative and positional arguments in a call to add is invalid and will result in an\n     * error.\n     */\n    public Builder add(String format, Object... args) {\n      boolean hasRelative = false;\n      boolean hasIndexed = false;\n\n      int relativeParameterCount = 0;\n      int[] indexedParameterCount = new int[args.length];\n\n      for (int p = 0; p < format.length(); ) {\n        if (format.charAt(p) != '$') {\n          int nextP = format.indexOf('$', p + 1);\n          if (nextP == -1) nextP = format.length();\n          formatParts.add(format.substring(p, nextP));\n          p = nextP;\n          continue;\n        }\n\n        p++; // '$'.\n\n        // Consume zero or more digits, leaving 'c' as the first non-digit char after the '$'.\n        int indexStart = p;\n        char c;\n        do {\n          checkArgument(p < format.length(), \"dangling format characters in '%s'\", format);\n          c = format.charAt(p++);\n        } while (c >= '0' && c <= '9');\n        int indexEnd = p - 1;\n\n        // If 'c' doesn't take an argument, we're done.\n        if (isNoArgPlaceholder(c)) {\n          checkArgument(\n              indexStart == indexEnd, \"$$, $>, $<, $[, $], $W, and $Z may not have an index\");\n          formatParts.add(\"$\" + c);\n          continue;\n        }\n\n        // Find either the indexed argument, or the relative argument. (0-based).\n        int index;\n        if (indexStart < indexEnd) {\n          index = Integer.parseInt(format.substring(indexStart, indexEnd)) - 1;\n          hasIndexed = true;\n          if (args.length > 0) {\n            indexedParameterCount[index % args.length]++; // modulo is needed, checked below anyway\n          }\n        } else {\n          index = relativeParameterCount;\n          hasRelative = true;\n          relativeParameterCount++;\n        }\n\n        checkArgument(index >= 0 && index < args.length,\n            \"index %d for '%s' not in range (received %s arguments)\",\n            index + 1, format.substring(indexStart - 1, indexEnd + 1), args.length);\n        checkArgument(!hasIndexed || !hasRelative, \"cannot mix indexed and positional parameters\");\n\n        addArgument(format, c, args[index]);\n\n        formatParts.add(\"$\" + c);\n      }\n\n      if (hasRelative) {\n        checkArgument(relativeParameterCount >= args.length,\n            \"unused arguments: expected %s, received %s\", relativeParameterCount, args.length);\n      }\n      if (hasIndexed) {\n        List<String> unused = new ArrayList<>();\n        for (int i = 0; i < args.length; i++) {\n          if (indexedParameterCount[i] == 0) {\n            unused.add(\"$\" + (i + 1));\n          }\n        }\n        String s = unused.size() == 1 ? \"\" : \"s\";\n        checkArgument(unused.isEmpty(), \"unused argument%s: %s\", s, String.join(\", \", unused));\n      }\n      return this;\n    }\n\n    private boolean isNoArgPlaceholder(char c) {\n      return c == '$' || c == '>' || c == '<' || c == '[' || c == ']' || c == 'W' || c == 'Z';\n    }\n\n    private void addArgument(String format, char c, Object arg) {\n      switch (c) {\n        case 'N':\n          this.args.add(argToName(arg));\n          break;\n        case 'L':\n          this.args.add(argToLiteral(arg));\n          break;\n        case 'S':\n          this.args.add(argToString(arg));\n          break;\n        case 'T':\n          this.args.add(argToType(arg));\n          break;\n        default:\n          throw new IllegalArgumentException(\n              String.format(\"invalid format string: '%s'\", format));\n      }\n    }\n\n    private String argToName(Object o) {\n      if (o instanceof CharSequence) return o.toString();\n      if (o instanceof ParameterSpec) return ((ParameterSpec) o).name;\n      if (o instanceof FieldSpec) return ((FieldSpec) o).name;\n      if (o instanceof MethodSpec) return ((MethodSpec) o).name;\n      if (o instanceof TypeSpec) return ((TypeSpec) o).name;\n      throw new IllegalArgumentException(\"expected name but was \" + o);\n    }\n\n    private Object argToLiteral(Object o) {\n      return o;\n    }\n\n    private String argToString(Object o) {\n      return o != null ? String.valueOf(o) : null;\n    }\n\n    private TypeName argToType(Object o) {\n      if (o instanceof TypeName) return (TypeName) o;\n      if (o instanceof TypeMirror) return TypeName.get((TypeMirror) o);\n      if (o instanceof Element) return TypeName.get(((Element) o).asType());\n      if (o instanceof Type) return TypeName.get((Type) o);\n      throw new IllegalArgumentException(\"expected type but was \" + o);\n    }\n\n    /**\n     * @param controlFlow the control flow construct and its code, such as \"if (foo == 5)\".\n     * Shouldn't contain braces or newline characters.\n     */\n    public Builder beginControlFlow(String controlFlow, Object... args) {\n      add(controlFlow + \" {\\n\", args);\n      indent();\n      return this;\n    }\n\n    /**\n     * @param controlFlow the control flow construct and its code, such as \"else if (foo == 10)\".\n     *     Shouldn't contain braces or newline characters.\n     */\n    public Builder nextControlFlow(String controlFlow, Object... args) {\n      unindent();\n      add(\"} \" + controlFlow + \" {\\n\", args);\n      indent();\n      return this;\n    }\n\n    public Builder endControlFlow() {\n      unindent();\n      add(\"}\\n\");\n      return this;\n    }\n\n    /**\n     * @param controlFlow the optional control flow construct and its code, such as\n     *     \"while(foo == 20)\". Only used for \"do/while\" control flows.\n     */\n    public Builder endControlFlow(String controlFlow, Object... args) {\n      unindent();\n      add(\"} \" + controlFlow + \";\\n\", args);\n      return this;\n    }\n\n    public Builder addStatement(String format, Object... args) {\n      add(\"$[\");\n      add(format, args);\n      add(\";\\n$]\");\n      return this;\n    }\n\n    public Builder addStatement(CodeBlock codeBlock) {\n      return addStatement(\"$L\", codeBlock);\n    }\n\n    public Builder add(CodeBlock codeBlock) {\n      formatParts.addAll(codeBlock.formatParts);\n      args.addAll(codeBlock.args);\n      return this;\n    }\n\n    public Builder indent() {\n      this.formatParts.add(\"$>\");\n      return this;\n    }\n\n    public Builder unindent() {\n      this.formatParts.add(\"$<\");\n      return this;\n    }\n\n    public Builder clear() {\n      formatParts.clear();\n      args.clear();\n      return this;\n    }\n\n    public CodeBlock build() {\n      return new CodeBlock(this);\n    }\n  }\n\n  private static final class CodeBlockJoiner {\n    private final String delimiter;\n    private final Builder builder;\n    private boolean first = true;\n\n    CodeBlockJoiner(String delimiter, Builder builder) {\n      this.delimiter = delimiter;\n      this.builder = builder;\n    }\n\n    CodeBlockJoiner add(CodeBlock codeBlock) {\n      if (!first) {\n        builder.add(delimiter);\n      }\n      first = false;\n\n      builder.add(codeBlock);\n      return this;\n    }\n\n    CodeBlockJoiner merge(CodeBlockJoiner other) {\n      CodeBlock otherBlock = other.builder.build();\n      if (!otherBlock.isEmpty()) {\n        add(otherBlock);\n      }\n      return this;\n    }\n\n    CodeBlock join() {\n      return builder.build();\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/CodeWriter.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.ListIterator;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.regex.Pattern;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.Modifier;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\nimport static com.squareup.javapoet.Util.checkState;\nimport static com.squareup.javapoet.Util.stringLiteralWithDoubleQuotes;\nimport static java.lang.String.join;\n\n/**\n * Converts a {@link JavaFile} to a string suitable to both human- and javac-consumption. This\n * honors imports, indentation, and deferred variable names.\n */\nfinal class CodeWriter {\n  /** Sentinel value that indicates that no user-provided package has been set. */\n  private static final String NO_PACKAGE = new String();\n  private static final Pattern LINE_BREAKING_PATTERN = Pattern.compile(\"\\\\R\");\n\n  private final String indent;\n  private final LineWrapper out;\n  private int indentLevel;\n\n  private boolean javadoc = false;\n  private boolean comment = false;\n  private String packageName = NO_PACKAGE;\n  private final List<TypeSpec> typeSpecStack = new ArrayList<>();\n  private final Set<String> staticImportClassNames;\n  private final Set<String> staticImports;\n  private final Set<String> alwaysQualify;\n  private final Map<String, ClassName> importedTypes;\n  private final Map<String, ClassName> importableTypes = new LinkedHashMap<>();\n  private final Set<String> referencedNames = new LinkedHashSet<>();\n  private final Multiset<String> currentTypeVariables = new Multiset<>();\n  private boolean trailingNewline;\n\n  /**\n   * When emitting a statement, this is the line of the statement currently being written. The first\n   * line of a statement is indented normally and subsequent wrapped lines are double-indented. This\n   * is -1 when the currently-written line isn't part of a statement.\n   */\n  int statementLine = -1;\n\n  CodeWriter(Appendable out) {\n    this(out, \"  \", Collections.emptySet(), Collections.emptySet());\n  }\n\n  CodeWriter(Appendable out, String indent, Set<String> staticImports, Set<String> alwaysQualify) {\n    this(out, indent, Collections.emptyMap(), staticImports, alwaysQualify);\n  }\n\n  CodeWriter(Appendable out,\n      String indent,\n      Map<String, ClassName> importedTypes,\n      Set<String> staticImports,\n      Set<String> alwaysQualify) {\n    this.out = new LineWrapper(out, indent, 100);\n    this.indent = checkNotNull(indent, \"indent == null\");\n    this.importedTypes = checkNotNull(importedTypes, \"importedTypes == null\");\n    this.staticImports = checkNotNull(staticImports, \"staticImports == null\");\n    this.alwaysQualify = checkNotNull(alwaysQualify, \"alwaysQualify == null\");\n    this.staticImportClassNames = new LinkedHashSet<>();\n    for (String signature : staticImports) {\n      staticImportClassNames.add(signature.substring(0, signature.lastIndexOf('.')));\n    }\n  }\n\n  public Map<String, ClassName> importedTypes() {\n    return importedTypes;\n  }\n\n  public CodeWriter indent() {\n    return indent(1);\n  }\n\n  public CodeWriter indent(int levels) {\n    indentLevel += levels;\n    return this;\n  }\n\n  public CodeWriter unindent() {\n    return unindent(1);\n  }\n\n  public CodeWriter unindent(int levels) {\n    checkArgument(indentLevel - levels >= 0, \"cannot unindent %s from %s\", levels, indentLevel);\n    indentLevel -= levels;\n    return this;\n  }\n\n  public CodeWriter pushPackage(String packageName) {\n    checkState(this.packageName == NO_PACKAGE, \"package already set: %s\", this.packageName);\n    this.packageName = checkNotNull(packageName, \"packageName == null\");\n    return this;\n  }\n\n  public CodeWriter popPackage() {\n    checkState(this.packageName != NO_PACKAGE, \"package not set\");\n    this.packageName = NO_PACKAGE;\n    return this;\n  }\n\n  public CodeWriter pushType(TypeSpec type) {\n    this.typeSpecStack.add(type);\n    return this;\n  }\n\n  public CodeWriter popType() {\n    this.typeSpecStack.remove(typeSpecStack.size() - 1);\n    return this;\n  }\n\n  public void emitComment(CodeBlock codeBlock) throws IOException {\n    trailingNewline = true; // Force the '//' prefix for the comment.\n    comment = true;\n    try {\n      emit(codeBlock);\n      emit(\"\\n\");\n    } finally {\n      comment = false;\n    }\n  }\n\n  public void emitJavadoc(CodeBlock javadocCodeBlock) throws IOException {\n    if (javadocCodeBlock.isEmpty()) return;\n\n    emit(\"/**\\n\");\n    javadoc = true;\n    try {\n      emit(javadocCodeBlock, true);\n    } finally {\n      javadoc = false;\n    }\n    emit(\" */\\n\");\n  }\n\n  public void emitAnnotations(List<AnnotationSpec> annotations, boolean inline) throws IOException {\n    for (AnnotationSpec annotationSpec : annotations) {\n      annotationSpec.emit(this, inline);\n      emit(inline ? \" \" : \"\\n\");\n    }\n  }\n\n  /**\n   * Emits {@code modifiers} in the standard order. Modifiers in {@code implicitModifiers} will not\n   * be emitted.\n   */\n  public void emitModifiers(Set<Modifier> modifiers, Set<Modifier> implicitModifiers)\n      throws IOException {\n    if (modifiers.isEmpty()) return;\n    for (Modifier modifier : EnumSet.copyOf(modifiers)) {\n      if (implicitModifiers.contains(modifier)) continue;\n      emitAndIndent(modifier.name().toLowerCase(Locale.US));\n      emitAndIndent(\" \");\n    }\n  }\n\n  public void emitModifiers(Set<Modifier> modifiers) throws IOException {\n    emitModifiers(modifiers, Collections.emptySet());\n  }\n\n  /**\n   * Emit type variables with their bounds. This should only be used when declaring type variables;\n   * everywhere else bounds are omitted.\n   */\n  public void emitTypeVariables(List<TypeVariableName> typeVariables) throws IOException {\n    if (typeVariables.isEmpty()) return;\n\n    typeVariables.forEach(typeVariable -> currentTypeVariables.add(typeVariable.name));\n\n    emit(\"<\");\n    boolean firstTypeVariable = true;\n    for (TypeVariableName typeVariable : typeVariables) {\n      if (!firstTypeVariable) emit(\", \");\n      emitAnnotations(typeVariable.annotations, true);\n      emit(\"$L\", typeVariable.name);\n      boolean firstBound = true;\n      for (TypeName bound : typeVariable.bounds) {\n        emit(firstBound ? \" extends $T\" : \" & $T\", bound);\n        firstBound = false;\n      }\n      firstTypeVariable = false;\n    }\n    emit(\">\");\n  }\n\n  public void popTypeVariables(List<TypeVariableName> typeVariables) throws IOException {\n    typeVariables.forEach(typeVariable -> currentTypeVariables.remove(typeVariable.name));\n  }\n\n  public CodeWriter emit(String s) throws IOException {\n    return emitAndIndent(s);\n  }\n\n  public CodeWriter emit(String format, Object... args) throws IOException {\n    return emit(CodeBlock.of(format, args));\n  }\n\n  public CodeWriter emit(CodeBlock codeBlock) throws IOException {\n    return emit(codeBlock, false);\n  }\n\n  public CodeWriter emit(CodeBlock codeBlock, boolean ensureTrailingNewline) throws IOException {\n    int a = 0;\n    ClassName deferredTypeName = null; // used by \"import static\" logic\n    ListIterator<String> partIterator = codeBlock.formatParts.listIterator();\n    while (partIterator.hasNext()) {\n      String part = partIterator.next();\n      switch (part) {\n        case \"$L\":\n          emitLiteral(codeBlock.args.get(a++));\n          break;\n\n        case \"$N\":\n          emitAndIndent((String) codeBlock.args.get(a++));\n          break;\n\n        case \"$S\":\n          String string = (String) codeBlock.args.get(a++);\n          // Emit null as a literal null: no quotes.\n          emitAndIndent(string != null\n              ? stringLiteralWithDoubleQuotes(string, indent)\n              : \"null\");\n          break;\n\n        case \"$T\":\n          TypeName typeName = (TypeName) codeBlock.args.get(a++);\n          // defer \"typeName.emit(this)\" if next format part will be handled by the default case\n          if (typeName instanceof ClassName && partIterator.hasNext()) {\n            if (!codeBlock.formatParts.get(partIterator.nextIndex()).startsWith(\"$\")) {\n              ClassName candidate = (ClassName) typeName;\n              if (staticImportClassNames.contains(candidate.canonicalName)) {\n                checkState(deferredTypeName == null, \"pending type for static import?!\");\n                deferredTypeName = candidate;\n                break;\n              }\n            }\n          }\n          typeName.emit(this);\n          break;\n\n        case \"$$\":\n          emitAndIndent(\"$\");\n          break;\n\n        case \"$>\":\n          indent();\n          break;\n\n        case \"$<\":\n          unindent();\n          break;\n\n        case \"$[\":\n          checkState(statementLine == -1, \"statement enter $[ followed by statement enter $[\");\n          statementLine = 0;\n          break;\n\n        case \"$]\":\n          checkState(statementLine != -1, \"statement exit $] has no matching statement enter $[\");\n          if (statementLine > 0) {\n            unindent(2); // End a multi-line statement. Decrease the indentation level.\n          }\n          statementLine = -1;\n          break;\n\n        case \"$W\":\n          out.wrappingSpace(indentLevel + 2);\n          break;\n\n        case \"$Z\":\n          out.zeroWidthSpace(indentLevel + 2);\n          break;\n\n        default:\n          // handle deferred type\n          if (deferredTypeName != null) {\n            if (part.startsWith(\".\")) {\n              if (emitStaticImportMember(deferredTypeName.canonicalName, part)) {\n                // okay, static import hit and all was emitted, so clean-up and jump to next part\n                deferredTypeName = null;\n                break;\n              }\n            }\n            deferredTypeName.emit(this);\n            deferredTypeName = null;\n          }\n          emitAndIndent(part);\n          break;\n      }\n    }\n    if (ensureTrailingNewline && out.lastChar() != '\\n') {\n      emit(\"\\n\");\n    }\n    return this;\n  }\n\n  public CodeWriter emitWrappingSpace() throws IOException {\n    out.wrappingSpace(indentLevel + 2);\n    return this;\n  }\n\n  private static String extractMemberName(String part) {\n    checkArgument(Character.isJavaIdentifierStart(part.charAt(0)), \"not an identifier: %s\", part);\n    for (int i = 1; i <= part.length(); i++) {\n      if (!SourceVersion.isIdentifier(part.substring(0, i))) {\n        return part.substring(0, i - 1);\n      }\n    }\n    return part;\n  }\n\n  private boolean emitStaticImportMember(String canonical, String part) throws IOException {\n    String partWithoutLeadingDot = part.substring(1);\n    if (partWithoutLeadingDot.isEmpty()) return false;\n    char first = partWithoutLeadingDot.charAt(0);\n    if (!Character.isJavaIdentifierStart(first)) return false;\n    String explicit = canonical + \".\" + extractMemberName(partWithoutLeadingDot);\n    String wildcard = canonical + \".*\";\n    if (staticImports.contains(explicit) || staticImports.contains(wildcard)) {\n      emitAndIndent(partWithoutLeadingDot);\n      return true;\n    }\n    return false;\n  }\n\n  private void emitLiteral(Object o) throws IOException {\n    if (o instanceof TypeSpec) {\n      TypeSpec typeSpec = (TypeSpec) o;\n      typeSpec.emit(this, null, Collections.emptySet());\n    } else if (o instanceof AnnotationSpec) {\n      AnnotationSpec annotationSpec = (AnnotationSpec) o;\n      annotationSpec.emit(this, true);\n    } else if (o instanceof CodeBlock) {\n      CodeBlock codeBlock = (CodeBlock) o;\n      emit(codeBlock);\n    } else {\n      emitAndIndent(String.valueOf(o));\n    }\n  }\n\n  /**\n   * Returns the best name to identify {@code className} with in the current context. This uses the\n   * available imports and the current scope to find the shortest name available. It does not honor\n   * names visible due to inheritance.\n   */\n  String lookupName(ClassName className) {\n    // If the top level simple name is masked by a current type variable, use the canonical name.\n    String topLevelSimpleName = className.topLevelClassName().simpleName();\n    if (currentTypeVariables.contains(topLevelSimpleName)) {\n      return className.canonicalName;\n    }\n\n    // Find the shortest suffix of className that resolves to className. This uses both local type\n    // names (so `Entry` in `Map` refers to `Map.Entry`). Also uses imports.\n    boolean nameResolved = false;\n    for (ClassName c = className; c != null; c = c.enclosingClassName()) {\n      ClassName resolved = resolve(c.simpleName());\n      nameResolved = resolved != null;\n\n      if (resolved != null && Objects.equals(resolved.canonicalName, c.canonicalName)) {\n        int suffixOffset = c.simpleNames().size() - 1;\n        return join(\".\", className.simpleNames().subList(\n            suffixOffset, className.simpleNames().size()));\n      }\n    }\n\n    // If the name resolved but wasn't a match, we're stuck with the fully qualified name.\n    if (nameResolved) {\n      return className.canonicalName;\n    }\n\n    // If the class is in the same package, we're done.\n    if (Objects.equals(packageName, className.packageName())) {\n      referencedNames.add(topLevelSimpleName);\n      return join(\".\", className.simpleNames());\n    }\n\n    // We'll have to use the fully-qualified name. Mark the type as importable for a future pass.\n    if (!javadoc) {\n      importableType(className);\n    }\n\n    return className.canonicalName;\n  }\n\n  private void importableType(ClassName className) {\n    if (className.packageName().isEmpty()) {\n      return;\n    } else if (alwaysQualify.contains(className.simpleName)) {\n      // TODO what about nested types like java.util.Map.Entry?\n      return;\n    }\n    ClassName topLevelClassName = className.topLevelClassName();\n    String simpleName = topLevelClassName.simpleName();\n    ClassName replaced = importableTypes.put(simpleName, topLevelClassName);\n    if (replaced != null) {\n      importableTypes.put(simpleName, replaced); // On collision, prefer the first inserted.\n    }\n  }\n\n  /**\n   * Returns the class referenced by {@code simpleName}, using the current nesting context and\n   * imports.\n   */\n  // TODO(jwilson): also honor superclass members when resolving names.\n  private ClassName resolve(String simpleName) {\n    // Match a child of the current (potentially nested) class.\n    for (int i = typeSpecStack.size() - 1; i >= 0; i--) {\n      TypeSpec typeSpec = typeSpecStack.get(i);\n      if (typeSpec.nestedTypesSimpleNames.contains(simpleName)) {\n        return stackClassName(i, simpleName);\n      }\n    }\n\n    // Match the top-level class.\n    if (typeSpecStack.size() > 0 && Objects.equals(typeSpecStack.get(0).name, simpleName)) {\n      return ClassName.get(packageName, simpleName);\n    }\n\n    // Match an imported type.\n    ClassName importedType = importedTypes.get(simpleName);\n    if (importedType != null) return importedType;\n\n    // No match.\n    return null;\n  }\n\n  /** Returns the class named {@code simpleName} when nested in the class at {@code stackDepth}. */\n  private ClassName stackClassName(int stackDepth, String simpleName) {\n    ClassName className = ClassName.get(packageName, typeSpecStack.get(0).name);\n    for (int i = 1; i <= stackDepth; i++) {\n      className = className.nestedClass(typeSpecStack.get(i).name);\n    }\n    return className.nestedClass(simpleName);\n  }\n\n  /**\n   * Emits {@code s} with indentation as required. It's important that all code that writes to\n   * {@link #out} does it through here, since we emit indentation lazily in order to avoid\n   * unnecessary trailing whitespace.\n   */\n  CodeWriter emitAndIndent(String s) throws IOException {\n    boolean first = true;\n    for (String line : LINE_BREAKING_PATTERN.split(s, -1)) {\n      // Emit a newline character. Make sure blank lines in Javadoc & comments look good.\n      if (!first) {\n        if ((javadoc || comment) && trailingNewline) {\n          emitIndentation();\n          out.append(javadoc ? \" *\" : \"//\");\n        }\n        out.append(\"\\n\");\n        trailingNewline = true;\n        if (statementLine != -1) {\n          if (statementLine == 0) {\n            indent(2); // Begin multiple-line statement. Increase the indentation level.\n          }\n          statementLine++;\n        }\n      }\n\n      first = false;\n      if (line.isEmpty()) continue; // Don't indent empty lines.\n\n      // Emit indentation and comment prefix if necessary.\n      if (trailingNewline) {\n        emitIndentation();\n        if (javadoc) {\n          out.append(\" * \");\n        } else if (comment) {\n          out.append(\"// \");\n        }\n      }\n\n      out.append(line);\n      trailingNewline = false;\n    }\n    return this;\n  }\n\n  private void emitIndentation() throws IOException {\n    for (int j = 0; j < indentLevel; j++) {\n      out.append(indent);\n    }\n  }\n\n  /**\n   * Returns the types that should have been imported for this code. If there were any simple name\n   * collisions, that type's first use is imported.\n   */\n  Map<String, ClassName> suggestedImports() {\n    Map<String, ClassName> result = new LinkedHashMap<>(importableTypes);\n    result.keySet().removeAll(referencedNames);\n    return result;\n  }\n\n  // A makeshift multi-set implementation\n  private static final class Multiset<T> {\n    private final Map<T, Integer> map = new LinkedHashMap<>();\n\n    void add(T t) {\n      int count = map.getOrDefault(t, 0);\n      map.put(t, count + 1);\n    }\n\n    void remove(T t) {\n      int count = map.getOrDefault(t, 0);\n      if (count == 0) {\n        throw new IllegalStateException(t + \" is not in the multiset\");\n      }\n      map.put(t, count - 1);\n    }\n\n    boolean contains(T t) {\n      return map.getOrDefault(t, 0) > 0;\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/FieldSpec.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.Modifier;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\nimport static com.squareup.javapoet.Util.checkState;\n\n/** A generated field declaration. */\npublic final class FieldSpec {\n  public final TypeName type;\n  public final String name;\n  public final CodeBlock javadoc;\n  public final List<AnnotationSpec> annotations;\n  public final Set<Modifier> modifiers;\n  public final CodeBlock initializer;\n\n  private FieldSpec(Builder builder) {\n    this.type = checkNotNull(builder.type, \"type == null\");\n    this.name = checkNotNull(builder.name, \"name == null\");\n    this.javadoc = builder.javadoc.build();\n    this.annotations = Util.immutableList(builder.annotations);\n    this.modifiers = Util.immutableSet(builder.modifiers);\n    this.initializer = (builder.initializer == null)\n        ? CodeBlock.builder().build()\n        : builder.initializer;\n  }\n\n  public boolean hasModifier(Modifier modifier) {\n    return modifiers.contains(modifier);\n  }\n\n  void emit(CodeWriter codeWriter, Set<Modifier> implicitModifiers) throws IOException {\n    codeWriter.emitJavadoc(javadoc);\n    codeWriter.emitAnnotations(annotations, false);\n    codeWriter.emitModifiers(modifiers, implicitModifiers);\n    codeWriter.emit(\"$T $L\", type, name);\n    if (!initializer.isEmpty()) {\n      codeWriter.emit(\" = \");\n      codeWriter.emit(initializer);\n    }\n    codeWriter.emit(\";\\n\");\n  }\n\n  @Override public boolean equals(Object o) {\n    if (this == o) return true;\n    if (o == null) return false;\n    if (getClass() != o.getClass()) return false;\n    return toString().equals(o.toString());\n  }\n\n  @Override public int hashCode() {\n    return toString().hashCode();\n  }\n\n  @Override public String toString() {\n    StringBuilder out = new StringBuilder();\n    try {\n      CodeWriter codeWriter = new CodeWriter(out);\n      emit(codeWriter, Collections.emptySet());\n      return out.toString();\n    } catch (IOException e) {\n      throw new AssertionError();\n    }\n  }\n\n  public static Builder builder(TypeName type, String name, Modifier... modifiers) {\n    checkNotNull(type, \"type == null\");\n    checkArgument(SourceVersion.isName(name), \"not a valid name: %s\", name);\n    return new Builder(type, name)\n        .addModifiers(modifiers);\n  }\n\n  public static Builder builder(Type type, String name, Modifier... modifiers) {\n    return builder(TypeName.get(type), name, modifiers);\n  }\n\n  public Builder toBuilder() {\n    Builder builder = new Builder(type, name);\n    builder.javadoc.add(javadoc);\n    builder.annotations.addAll(annotations);\n    builder.modifiers.addAll(modifiers);\n    builder.initializer = initializer.isEmpty() ? null : initializer;\n    return builder;\n  }\n\n  public static final class Builder {\n    private final TypeName type;\n    private final String name;\n\n    private final CodeBlock.Builder javadoc = CodeBlock.builder();\n    private CodeBlock initializer = null;\n\n    public final List<AnnotationSpec> annotations = new ArrayList<>();\n    public final List<Modifier> modifiers = new ArrayList<>();\n\n    private Builder(TypeName type, String name) {\n      this.type = type;\n      this.name = name;\n    }\n\n    public Builder addJavadoc(String format, Object... args) {\n      javadoc.add(format, args);\n      return this;\n    }\n\n    public Builder addJavadoc(CodeBlock block) {\n      javadoc.add(block);\n      return this;\n    }\n\n    public Builder addAnnotations(Iterable<AnnotationSpec> annotationSpecs) {\n      checkArgument(annotationSpecs != null, \"annotationSpecs == null\");\n      for (AnnotationSpec annotationSpec : annotationSpecs) {\n        this.annotations.add(annotationSpec);\n      }\n      return this;\n    }\n\n    public Builder addAnnotation(AnnotationSpec annotationSpec) {\n      this.annotations.add(annotationSpec);\n      return this;\n    }\n\n    public Builder addAnnotation(ClassName annotation) {\n      this.annotations.add(AnnotationSpec.builder(annotation).build());\n      return this;\n    }\n\n    public Builder addAnnotation(Class<?> annotation) {\n      return addAnnotation(ClassName.get(annotation));\n    }\n\n    public Builder addModifiers(Modifier... modifiers) {\n      Collections.addAll(this.modifiers, modifiers);\n      return this;\n    }\n\n    public Builder initializer(String format, Object... args) {\n      return initializer(CodeBlock.of(format, args));\n    }\n\n    public Builder initializer(CodeBlock codeBlock) {\n      checkState(this.initializer == null, \"initializer was already set\");\n      this.initializer = checkNotNull(codeBlock, \"codeBlock == null\");\n      return this;\n    }\n\n    public FieldSpec build() {\n      return new FieldSpec(this);\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/JavaFile.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStreamWriter;\nimport java.io.Writer;\nimport java.net.URI;\nimport java.nio.charset.Charset;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport javax.annotation.processing.Filer;\nimport javax.lang.model.element.Element;\nimport javax.tools.JavaFileObject;\nimport javax.tools.JavaFileObject.Kind;\nimport javax.tools.SimpleJavaFileObject;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\n/** A Java file containing a single top level class. */\npublic final class JavaFile {\n  private static final Appendable NULL_APPENDABLE = new Appendable() {\n    @Override public Appendable append(CharSequence charSequence) {\n      return this;\n    }\n    @Override public Appendable append(CharSequence charSequence, int start, int end) {\n      return this;\n    }\n    @Override public Appendable append(char c) {\n      return this;\n    }\n  };\n\n  public final CodeBlock fileComment;\n  public final String packageName;\n  public final TypeSpec typeSpec;\n  public final boolean skipJavaLangImports;\n  private final Set<String> staticImports;\n  private final Set<String> alwaysQualify;\n  private final String indent;\n\n  private JavaFile(Builder builder) {\n    this.fileComment = builder.fileComment.build();\n    this.packageName = builder.packageName;\n    this.typeSpec = builder.typeSpec;\n    this.skipJavaLangImports = builder.skipJavaLangImports;\n    this.staticImports = Util.immutableSet(builder.staticImports);\n    this.indent = builder.indent;\n\n    Set<String> alwaysQualifiedNames = new LinkedHashSet<>();\n    fillAlwaysQualifiedNames(builder.typeSpec, alwaysQualifiedNames);\n    this.alwaysQualify = Util.immutableSet(alwaysQualifiedNames);\n  }\n\n  private void fillAlwaysQualifiedNames(TypeSpec spec, Set<String> alwaysQualifiedNames) {\n    alwaysQualifiedNames.addAll(spec.alwaysQualifiedNames);\n    for (TypeSpec nested : spec.typeSpecs) {\n      fillAlwaysQualifiedNames(nested, alwaysQualifiedNames);\n    }\n  }\n\n  public void writeTo(Appendable out) throws IOException {\n    // First pass: emit the entire class, just to collect the types we'll need to import.\n    CodeWriter importsCollector = new CodeWriter(\n        NULL_APPENDABLE,\n        indent,\n        staticImports,\n        alwaysQualify\n    );\n    emit(importsCollector);\n    Map<String, ClassName> suggestedImports = importsCollector.suggestedImports();\n\n    // Second pass: write the code, taking advantage of the imports.\n    CodeWriter codeWriter\n        = new CodeWriter(out, indent, suggestedImports, staticImports, alwaysQualify);\n    emit(codeWriter);\n  }\n\n  /** Writes this to {@code directory} as UTF-8 using the standard directory structure. */\n  public void writeTo(Path directory) throws IOException {\n    writeToPath(directory);\n  }\n\n  /**\n   * Writes this to {@code directory} with the provided {@code charset} using the standard directory\n   * structure.\n   */\n  public void writeTo(Path directory, Charset charset) throws IOException {\n    writeToPath(directory, charset);\n  }\n\n  /**\n   * Writes this to {@code directory} as UTF-8 using the standard directory structure.\n   * Returns the {@link Path} instance to which source is actually written.\n   */\n  public Path writeToPath(Path directory) throws IOException {\n    return writeToPath(directory, UTF_8);\n  }\n\n  /**\n   * Writes this to {@code directory} with the provided {@code charset} using the standard directory\n   * structure.\n   * Returns the {@link Path} instance to which source is actually written.\n   */\n  public Path writeToPath(Path directory, Charset charset) throws IOException {\n    checkArgument(Files.notExists(directory) || Files.isDirectory(directory),\n        \"path %s exists but is not a directory.\", directory);\n    Path outputDirectory = directory;\n    if (!packageName.isEmpty()) {\n      for (String packageComponent : packageName.split(\"\\\\.\")) {\n        outputDirectory = outputDirectory.resolve(packageComponent);\n      }\n      Files.createDirectories(outputDirectory);\n    }\n\n    Path outputPath = outputDirectory.resolve(typeSpec.name + \".java\");\n    try (Writer writer = new OutputStreamWriter(Files.newOutputStream(outputPath), charset)) {\n      writeTo(writer);\n    }\n\n    return outputPath;\n  }\n\n  /** Writes this to {@code directory} as UTF-8 using the standard directory structure. */\n  public void writeTo(File directory) throws IOException {\n    writeTo(directory.toPath());\n  }\n\n  /**\n   * Writes this to {@code directory} as UTF-8 using the standard directory structure.\n   * Returns the {@link File} instance to which source is actually written.\n   */\n  public File writeToFile(File directory) throws IOException {\n    final Path outputPath = writeToPath(directory.toPath());\n    return outputPath.toFile();\n  }\n\n  /** Writes this to {@code filer}. */\n  public void writeTo(Filer filer) throws IOException {\n    String fileName = packageName.isEmpty()\n        ? typeSpec.name\n        : packageName + \".\" + typeSpec.name;\n    List<Element> originatingElements = typeSpec.originatingElements;\n    JavaFileObject filerSourceFile = filer.createSourceFile(fileName,\n        originatingElements.toArray(new Element[originatingElements.size()]));\n    try (Writer writer = filerSourceFile.openWriter()) {\n      writeTo(writer);\n    } catch (Exception e) {\n      try {\n        filerSourceFile.delete();\n      } catch (Exception ignored) {\n      }\n      throw e;\n    }\n  }\n\n  private void emit(CodeWriter codeWriter) throws IOException {\n    codeWriter.pushPackage(packageName);\n\n    if (!fileComment.isEmpty()) {\n      codeWriter.emitComment(fileComment);\n    }\n\n    if (!packageName.isEmpty()) {\n      codeWriter.emit(\"package $L;\\n\", packageName);\n      codeWriter.emit(\"\\n\");\n    }\n\n    if (!staticImports.isEmpty()) {\n      for (String signature : staticImports) {\n        codeWriter.emit(\"import static $L;\\n\", signature);\n      }\n      codeWriter.emit(\"\\n\");\n    }\n\n    int importedTypesCount = 0;\n    for (ClassName className : new TreeSet<>(codeWriter.importedTypes().values())) {\n      // TODO what about nested types like java.util.Map.Entry?\n      if (skipJavaLangImports\n          && className.packageName().equals(\"java.lang\")\n          && !alwaysQualify.contains(className.simpleName)) {\n        continue;\n      }\n      codeWriter.emit(\"import $L;\\n\", className.withoutAnnotations());\n      importedTypesCount++;\n    }\n\n    if (importedTypesCount > 0) {\n      codeWriter.emit(\"\\n\");\n    }\n\n    typeSpec.emit(codeWriter, null, Collections.emptySet());\n\n    codeWriter.popPackage();\n  }\n\n  @Override public boolean equals(Object o) {\n    if (this == o) return true;\n    if (o == null) return false;\n    if (getClass() != o.getClass()) return false;\n    return toString().equals(o.toString());\n  }\n\n  @Override public int hashCode() {\n    return toString().hashCode();\n  }\n\n  @Override public String toString() {\n    try {\n      StringBuilder result = new StringBuilder();\n      writeTo(result);\n      return result.toString();\n    } catch (IOException e) {\n      throw new AssertionError();\n    }\n  }\n\n  public JavaFileObject toJavaFileObject() {\n    URI uri = URI.create((packageName.isEmpty()\n        ? typeSpec.name\n        : packageName.replace('.', '/') + '/' + typeSpec.name)\n        + Kind.SOURCE.extension);\n    return new SimpleJavaFileObject(uri, Kind.SOURCE) {\n      private final long lastModified = System.currentTimeMillis();\n      @Override public String getCharContent(boolean ignoreEncodingErrors) {\n        return JavaFile.this.toString();\n      }\n      @Override public InputStream openInputStream() throws IOException {\n        return new ByteArrayInputStream(getCharContent(true).getBytes(UTF_8));\n      }\n      @Override public long getLastModified() {\n        return lastModified;\n      }\n    };\n  }\n\n  public static Builder builder(String packageName, TypeSpec typeSpec) {\n    checkNotNull(packageName, \"packageName == null\");\n    checkNotNull(typeSpec, \"typeSpec == null\");\n    return new Builder(packageName, typeSpec);\n  }\n\n  public Builder toBuilder() {\n    Builder builder = new Builder(packageName, typeSpec);\n    builder.fileComment.add(fileComment);\n    builder.skipJavaLangImports = skipJavaLangImports;\n    builder.indent = indent;\n    return builder;\n  }\n\n  public static final class Builder {\n    private final String packageName;\n    private final TypeSpec typeSpec;\n    private final CodeBlock.Builder fileComment = CodeBlock.builder();\n    private boolean skipJavaLangImports;\n    private String indent = \"  \";\n\n    public final Set<String> staticImports = new TreeSet<>();\n\n    private Builder(String packageName, TypeSpec typeSpec) {\n      this.packageName = packageName;\n      this.typeSpec = typeSpec;\n    }\n\n    public Builder addFileComment(String format, Object... args) {\n      this.fileComment.add(format, args);\n      return this;\n    }\n\n    public Builder addStaticImport(Enum<?> constant) {\n      return addStaticImport(ClassName.get(constant.getDeclaringClass()), constant.name());\n    }\n\n    public Builder addStaticImport(Class<?> clazz, String... names) {\n      return addStaticImport(ClassName.get(clazz), names);\n    }\n\n    public Builder addStaticImport(ClassName className, String... names) {\n      checkArgument(className != null, \"className == null\");\n      checkArgument(names != null, \"names == null\");\n      checkArgument(names.length > 0, \"names array is empty\");\n      for (String name : names) {\n        checkArgument(name != null, \"null entry in names array: %s\", Arrays.toString(names));\n        staticImports.add(className.canonicalName + \".\" + name);\n      }\n      return this;\n    }\n\n    /**\n     * Call this to omit imports for classes in {@code java.lang}, such as {@code java.lang.String}.\n     *\n     * <p>By default, JavaPoet explicitly imports types in {@code java.lang} to defend against\n     * naming conflicts. Suppose an (ill-advised) class is named {@code com.example.String}. When\n     * {@code java.lang} imports are skipped, generated code in {@code com.example} that references\n     * {@code java.lang.String} will get {@code com.example.String} instead.\n     */\n    public Builder skipJavaLangImports(boolean skipJavaLangImports) {\n      this.skipJavaLangImports = skipJavaLangImports;\n      return this;\n    }\n\n    public Builder indent(String indent) {\n      this.indent = indent;\n      return this;\n    }\n\n    public JavaFile build() {\n      return new JavaFile(this);\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/LineWrapper.java",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\n\nimport static com.squareup.javapoet.Util.checkNotNull;\n\n/**\n * Implements soft line wrapping on an appendable. To use, append characters using {@link #append}\n * or soft-wrapping spaces using {@link #wrappingSpace}.\n */\nfinal class LineWrapper {\n  private final RecordingAppendable out;\n  private final String indent;\n  private final int columnLimit;\n  private boolean closed;\n\n  /** Characters written since the last wrapping space that haven't yet been flushed. */\n  private final StringBuilder buffer = new StringBuilder();\n\n  /** The number of characters since the most recent newline. Includes both out and the buffer. */\n  private int column = 0;\n\n  /**\n   * -1 if we have no buffering; otherwise the number of {@code indent}s to write after wrapping.\n   */\n  private int indentLevel = -1;\n\n  /**\n   * Null if we have no buffering; otherwise the type to pass to the next call to {@link #flush}.\n   */\n  private FlushType nextFlush;\n\n  LineWrapper(Appendable out, String indent, int columnLimit) {\n    checkNotNull(out, \"out == null\");\n    this.out = new RecordingAppendable(out);\n    this.indent = indent;\n    this.columnLimit = columnLimit;\n  }\n\n  /** @return the last emitted char or {@link Character#MIN_VALUE} if nothing emitted yet. */\n  char lastChar() {\n    return out.lastChar;\n  }\n\n  /** Emit {@code s}. This may be buffered to permit line wraps to be inserted. */\n  void append(String s) throws IOException {\n    if (closed) throw new IllegalStateException(\"closed\");\n\n    if (nextFlush != null) {\n      int nextNewline = s.indexOf('\\n');\n\n      // If s doesn't cause the current line to cross the limit, buffer it and return. We'll decide\n      // whether or not we have to wrap it later.\n      if (nextNewline == -1 && column + s.length() <= columnLimit) {\n        buffer.append(s);\n        column += s.length();\n        return;\n      }\n\n      // Wrap if appending s would overflow the current line.\n      boolean wrap = nextNewline == -1 || column + nextNewline > columnLimit;\n      flush(wrap ? FlushType.WRAP : nextFlush);\n    }\n\n    out.append(s);\n    int lastNewline = s.lastIndexOf('\\n');\n    column = lastNewline != -1\n        ? s.length() - lastNewline - 1\n        : column + s.length();\n  }\n\n  /** Emit either a space or a newline character. */\n  void wrappingSpace(int indentLevel) throws IOException {\n    if (closed) throw new IllegalStateException(\"closed\");\n\n    if (this.nextFlush != null) flush(nextFlush);\n    column++; // Increment the column even though the space is deferred to next call to flush().\n    this.nextFlush = FlushType.SPACE;\n    this.indentLevel = indentLevel;\n  }\n\n  /** Emit a newline character if the line will exceed it's limit, otherwise do nothing. */\n  void zeroWidthSpace(int indentLevel) throws IOException {\n    if (closed) throw new IllegalStateException(\"closed\");\n\n    if (column == 0) return;\n    if (this.nextFlush != null) flush(nextFlush);\n    this.nextFlush = FlushType.EMPTY;\n    this.indentLevel = indentLevel;\n  }\n\n  /** Flush any outstanding text and forbid future writes to this line wrapper. */\n  void close() throws IOException {\n    if (nextFlush != null) flush(nextFlush);\n    closed = true;\n  }\n\n  /** Write the space followed by any buffered text that follows it. */\n  private void flush(FlushType flushType) throws IOException {\n    switch (flushType) {\n      case WRAP:\n        out.append('\\n');\n        for (int i = 0; i < indentLevel; i++) {\n          out.append(indent);\n        }\n        column = indentLevel * indent.length();\n        column += buffer.length();\n        break;\n      case SPACE:\n        out.append(' ');\n        break;\n      case EMPTY:\n        break;\n      default:\n        throw new IllegalArgumentException(\"Unknown FlushType: \" + flushType);\n    }\n\n    out.append(buffer);\n    buffer.delete(0, buffer.length());\n    indentLevel = -1;\n    nextFlush = null;\n  }\n\n  private enum FlushType {\n    WRAP, SPACE, EMPTY;\n  }\n\n  /** A delegating {@link Appendable} that records info about the chars passing through it. */\n  static final class RecordingAppendable implements Appendable {\n    private final Appendable delegate;\n\n    char lastChar = Character.MIN_VALUE;\n\n    RecordingAppendable(Appendable delegate) {\n      this.delegate = delegate;\n    }\n\n    @Override public Appendable append(CharSequence csq) throws IOException {\n      int length = csq.length();\n      if (length != 0) {\n        lastChar = csq.charAt(length - 1);\n      }\n      return delegate.append(csq);\n    }\n\n    @Override public Appendable append(CharSequence csq, int start, int end) throws IOException {\n      CharSequence sub = csq.subSequence(start, end);\n      return append(sub);\n    }\n\n    @Override public Appendable append(char c) throws IOException {\n      lastChar = c;\n      return delegate.append(c);\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/MethodSpec.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.TypeParameterElement;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.type.ExecutableType;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.type.TypeVariable;\nimport javax.lang.model.util.Types;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\nimport static com.squareup.javapoet.Util.checkState;\n\n/** A generated constructor or method declaration. */\npublic final class MethodSpec {\n  static final String CONSTRUCTOR = \"<init>\";\n\n  public final String name;\n  public final CodeBlock javadoc;\n  public final List<AnnotationSpec> annotations;\n  public final Set<Modifier> modifiers;\n  public final List<TypeVariableName> typeVariables;\n  public final TypeName returnType;\n  public final List<ParameterSpec> parameters;\n  public final boolean varargs;\n  public final List<TypeName> exceptions;\n  public final CodeBlock code;\n  public final CodeBlock defaultValue;\n\n  private MethodSpec(Builder builder) {\n    CodeBlock code = builder.code.build();\n    checkArgument(code.isEmpty() || !builder.modifiers.contains(Modifier.ABSTRACT),\n        \"abstract method %s cannot have code\", builder.name);\n    checkArgument(!builder.varargs || lastParameterIsArray(builder.parameters),\n        \"last parameter of varargs method %s must be an array\", builder.name);\n\n    this.name = checkNotNull(builder.name, \"name == null\");\n    this.javadoc = builder.javadoc.build();\n    this.annotations = Util.immutableList(builder.annotations);\n    this.modifiers = Util.immutableSet(builder.modifiers);\n    this.typeVariables = Util.immutableList(builder.typeVariables);\n    this.returnType = builder.returnType;\n    this.parameters = Util.immutableList(builder.parameters);\n    this.varargs = builder.varargs;\n    this.exceptions = Util.immutableList(builder.exceptions);\n    this.defaultValue = builder.defaultValue;\n    this.code = code;\n  }\n\n  private boolean lastParameterIsArray(List<ParameterSpec> parameters) {\n    return !parameters.isEmpty()\n        && TypeName.asArray((parameters.get(parameters.size() - 1).type)) != null;\n  }\n\n  void emit(CodeWriter codeWriter, String enclosingName, Set<Modifier> implicitModifiers)\n      throws IOException {\n    codeWriter.emitJavadoc(javadocWithParameters());\n    codeWriter.emitAnnotations(annotations, false);\n    codeWriter.emitModifiers(modifiers, implicitModifiers);\n\n    if (!typeVariables.isEmpty()) {\n      codeWriter.emitTypeVariables(typeVariables);\n      codeWriter.emit(\" \");\n    }\n\n    if (isConstructor()) {\n      codeWriter.emit(\"$L($Z\", enclosingName);\n    } else {\n      codeWriter.emit(\"$T $L($Z\", returnType, name);\n    }\n\n    boolean firstParameter = true;\n    for (Iterator<ParameterSpec> i = parameters.iterator(); i.hasNext(); ) {\n      ParameterSpec parameter = i.next();\n      if (!firstParameter) codeWriter.emit(\",\").emitWrappingSpace();\n      parameter.emit(codeWriter, !i.hasNext() && varargs);\n      firstParameter = false;\n    }\n\n    codeWriter.emit(\")\");\n\n    if (defaultValue != null && !defaultValue.isEmpty()) {\n      codeWriter.emit(\" default \");\n      codeWriter.emit(defaultValue);\n    }\n\n    if (!exceptions.isEmpty()) {\n      codeWriter.emitWrappingSpace().emit(\"throws\");\n      boolean firstException = true;\n      for (TypeName exception : exceptions) {\n        if (!firstException) codeWriter.emit(\",\");\n        codeWriter.emitWrappingSpace().emit(\"$T\", exception);\n        firstException = false;\n      }\n    }\n\n    if (hasModifier(Modifier.ABSTRACT)) {\n      codeWriter.emit(\";\\n\");\n    } else if (hasModifier(Modifier.NATIVE)) {\n      // Code is allowed to support stuff like GWT JSNI.\n      codeWriter.emit(code);\n      codeWriter.emit(\";\\n\");\n    } else {\n      codeWriter.emit(\" {\\n\");\n\n      codeWriter.indent();\n      codeWriter.emit(code, true);\n      codeWriter.unindent();\n\n      codeWriter.emit(\"}\\n\");\n    }\n    codeWriter.popTypeVariables(typeVariables);\n  }\n\n  private CodeBlock javadocWithParameters() {\n    CodeBlock.Builder builder = javadoc.toBuilder();\n    boolean emitTagNewline = true;\n    for (ParameterSpec parameterSpec : parameters) {\n      if (!parameterSpec.javadoc.isEmpty()) {\n        // Emit a new line before @param section only if the method javadoc is present.\n        if (emitTagNewline && !javadoc.isEmpty()) builder.add(\"\\n\");\n        emitTagNewline = false;\n        builder.add(\"@param $L $L\", parameterSpec.name, parameterSpec.javadoc);\n      }\n    }\n    return builder.build();\n  }\n\n  public boolean hasModifier(Modifier modifier) {\n    return modifiers.contains(modifier);\n  }\n\n  public boolean isConstructor() {\n    return name.equals(CONSTRUCTOR);\n  }\n\n  @Override public boolean equals(Object o) {\n    if (this == o) return true;\n    if (o == null) return false;\n    if (getClass() != o.getClass()) return false;\n    return toString().equals(o.toString());\n  }\n\n  @Override public int hashCode() {\n    return toString().hashCode();\n  }\n\n  @Override public String toString() {\n    StringBuilder out = new StringBuilder();\n    try {\n      CodeWriter codeWriter = new CodeWriter(out);\n      emit(codeWriter, \"Constructor\", Collections.emptySet());\n      return out.toString();\n    } catch (IOException e) {\n      throw new AssertionError();\n    }\n  }\n\n  public static Builder methodBuilder(String name) {\n    return new Builder(name);\n  }\n\n  public static Builder constructorBuilder() {\n    return new Builder(CONSTRUCTOR);\n  }\n\n  /**\n   * Returns a new method spec builder that overrides {@code method}.\n   *\n   * <p>This will copy its visibility modifiers, type parameters, return type, name, parameters, and\n   * throws declarations. An {@link Override} annotation will be added.\n   *\n   * <p>Note that in JavaPoet 1.2 through 1.7 this method retained annotations from the method and\n   * parameters of the overridden method. Since JavaPoet 1.8 annotations must be added separately.\n   */\n  public static Builder overriding(ExecutableElement method) {\n    checkNotNull(method, \"method == null\");\n\n    Element enclosingClass = method.getEnclosingElement();\n    if (enclosingClass.getModifiers().contains(Modifier.FINAL)) {\n      throw new IllegalArgumentException(\"Cannot override method on final class \" + enclosingClass);\n    }\n\n    Set<Modifier> modifiers = method.getModifiers();\n    if (modifiers.contains(Modifier.PRIVATE)\n        || modifiers.contains(Modifier.FINAL)\n        || modifiers.contains(Modifier.STATIC)) {\n      throw new IllegalArgumentException(\"cannot override method with modifiers: \" + modifiers);\n    }\n\n    String methodName = method.getSimpleName().toString();\n    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(methodName);\n\n    methodBuilder.addAnnotation(Override.class);\n\n    modifiers = new LinkedHashSet<>(modifiers);\n    modifiers.remove(Modifier.ABSTRACT);\n    modifiers.remove(Modifier.DEFAULT);\n    methodBuilder.addModifiers(modifiers);\n\n    for (TypeParameterElement typeParameterElement : method.getTypeParameters()) {\n      TypeVariable var = (TypeVariable) typeParameterElement.asType();\n      methodBuilder.addTypeVariable(TypeVariableName.get(var));\n    }\n\n    methodBuilder.returns(TypeName.get(method.getReturnType()));\n    methodBuilder.addParameters(ParameterSpec.parametersOf(method));\n    methodBuilder.varargs(method.isVarArgs());\n\n    for (TypeMirror thrownType : method.getThrownTypes()) {\n      methodBuilder.addException(TypeName.get(thrownType));\n    }\n\n    return methodBuilder;\n  }\n\n  /**\n   * Returns a new method spec builder that overrides {@code method} as a member of {@code\n   * enclosing}. This will resolve type parameters: for example overriding {@link\n   * Comparable#compareTo} in a type that implements {@code Comparable<Movie>}, the {@code T}\n   * parameter will be resolved to {@code Movie}.\n   *\n   * <p>This will copy its visibility modifiers, type parameters, return type, name, parameters, and\n   * throws declarations. An {@link Override} annotation will be added.\n   *\n   * <p>Note that in JavaPoet 1.2 through 1.7 this method retained annotations from the method and\n   * parameters of the overridden method. Since JavaPoet 1.8 annotations must be added separately.\n   */\n  public static Builder overriding(\n      ExecutableElement method, DeclaredType enclosing, Types types) {\n    ExecutableType executableType = (ExecutableType) types.asMemberOf(enclosing, method);\n    List<? extends TypeMirror> resolvedParameterTypes = executableType.getParameterTypes();\n    List<? extends TypeMirror> resolvedThrownTypes = executableType.getThrownTypes();\n    TypeMirror resolvedReturnType = executableType.getReturnType();\n\n    Builder builder = overriding(method);\n    builder.returns(TypeName.get(resolvedReturnType));\n    for (int i = 0, size = builder.parameters.size(); i < size; i++) {\n      ParameterSpec parameter = builder.parameters.get(i);\n      TypeName type = TypeName.get(resolvedParameterTypes.get(i));\n      builder.parameters.set(i, parameter.toBuilder(type, parameter.name).build());\n    }\n    builder.exceptions.clear();\n    for (int i = 0, size = resolvedThrownTypes.size(); i < size; i++) {\n      builder.addException(TypeName.get(resolvedThrownTypes.get(i)));\n    }\n\n    return builder;\n  }\n\n  public Builder toBuilder() {\n    Builder builder = new Builder(name);\n    builder.javadoc.add(javadoc);\n    builder.annotations.addAll(annotations);\n    builder.modifiers.addAll(modifiers);\n    builder.typeVariables.addAll(typeVariables);\n    builder.returnType = returnType;\n    builder.parameters.addAll(parameters);\n    builder.exceptions.addAll(exceptions);\n    builder.code.add(code);\n    builder.varargs = varargs;\n    builder.defaultValue = defaultValue;\n    return builder;\n  }\n\n  public static final class Builder {\n    private String name;\n\n    private final CodeBlock.Builder javadoc = CodeBlock.builder();\n    private TypeName returnType;\n    private final Set<TypeName> exceptions = new LinkedHashSet<>();\n    private final CodeBlock.Builder code = CodeBlock.builder();\n    private boolean varargs;\n    private CodeBlock defaultValue;\n\n    public final List<TypeVariableName> typeVariables = new ArrayList<>();\n    public final List<AnnotationSpec> annotations = new ArrayList<>();\n    public final List<Modifier> modifiers = new ArrayList<>();\n    public final List<ParameterSpec> parameters = new ArrayList<>();\n\n    private Builder(String name) {\n      setName(name);\n    }\n\n    public Builder setName(String name) {\n      checkNotNull(name, \"name == null\");\n      checkArgument(name.equals(CONSTRUCTOR) || SourceVersion.isName(name),\n          \"not a valid name: %s\", name);\n      this.name = name;\n      this.returnType = name.equals(CONSTRUCTOR) ? null : TypeName.VOID;\n      return this;\n    }\n\n    public Builder addJavadoc(String format, Object... args) {\n      javadoc.add(format, args);\n      return this;\n    }\n\n    public Builder addJavadoc(CodeBlock block) {\n      javadoc.add(block);\n      return this;\n    }\n\n    public Builder addAnnotations(Iterable<AnnotationSpec> annotationSpecs) {\n      checkArgument(annotationSpecs != null, \"annotationSpecs == null\");\n      for (AnnotationSpec annotationSpec : annotationSpecs) {\n        this.annotations.add(annotationSpec);\n      }\n      return this;\n    }\n\n    public Builder addAnnotation(AnnotationSpec annotationSpec) {\n      this.annotations.add(annotationSpec);\n      return this;\n    }\n\n    public Builder addAnnotation(ClassName annotation) {\n      this.annotations.add(AnnotationSpec.builder(annotation).build());\n      return this;\n    }\n\n    public Builder addAnnotation(Class<?> annotation) {\n      return addAnnotation(ClassName.get(annotation));\n    }\n\n    public Builder addModifiers(Modifier... modifiers) {\n      checkNotNull(modifiers, \"modifiers == null\");\n      Collections.addAll(this.modifiers, modifiers);\n      return this;\n    }\n\n    public Builder addModifiers(Iterable<Modifier> modifiers) {\n      checkNotNull(modifiers, \"modifiers == null\");\n      for (Modifier modifier : modifiers) {\n        this.modifiers.add(modifier);\n      }\n      return this;\n    }\n\n    public Builder addTypeVariables(Iterable<TypeVariableName> typeVariables) {\n      checkArgument(typeVariables != null, \"typeVariables == null\");\n      for (TypeVariableName typeVariable : typeVariables) {\n        this.typeVariables.add(typeVariable);\n      }\n      return this;\n    }\n\n    public Builder addTypeVariable(TypeVariableName typeVariable) {\n      typeVariables.add(typeVariable);\n      return this;\n    }\n\n    public Builder returns(TypeName returnType) {\n      checkState(!name.equals(CONSTRUCTOR), \"constructor cannot have return type.\");\n      this.returnType = returnType;\n      return this;\n    }\n\n    public Builder returns(Type returnType) {\n      return returns(TypeName.get(returnType));\n    }\n\n    public Builder addParameters(Iterable<ParameterSpec> parameterSpecs) {\n      checkArgument(parameterSpecs != null, \"parameterSpecs == null\");\n      for (ParameterSpec parameterSpec : parameterSpecs) {\n        this.parameters.add(parameterSpec);\n      }\n      return this;\n    }\n\n    public Builder addParameter(ParameterSpec parameterSpec) {\n      this.parameters.add(parameterSpec);\n      return this;\n    }\n\n    public Builder addParameter(TypeName type, String name, Modifier... modifiers) {\n      return addParameter(ParameterSpec.builder(type, name, modifiers).build());\n    }\n\n    public Builder addParameter(Type type, String name, Modifier... modifiers) {\n      return addParameter(TypeName.get(type), name, modifiers);\n    }\n\n    public Builder varargs() {\n      return varargs(true);\n    }\n\n    public Builder varargs(boolean varargs) {\n      this.varargs = varargs;\n      return this;\n    }\n\n    public Builder addExceptions(Iterable<? extends TypeName> exceptions) {\n      checkArgument(exceptions != null, \"exceptions == null\");\n      for (TypeName exception : exceptions) {\n        this.exceptions.add(exception);\n      }\n      return this;\n    }\n\n    public Builder addException(TypeName exception) {\n      this.exceptions.add(exception);\n      return this;\n    }\n\n    public Builder addException(Type exception) {\n      return addException(TypeName.get(exception));\n    }\n\n    public Builder addCode(String format, Object... args) {\n      code.add(format, args);\n      return this;\n    }\n\n    public Builder addNamedCode(String format, Map<String, ?> args) {\n      code.addNamed(format, args);\n      return this;\n    }\n\n    public Builder addCode(CodeBlock codeBlock) {\n      code.add(codeBlock);\n      return this;\n    }\n\n    public Builder addComment(String format, Object... args) {\n      code.add(\"// \" + format + \"\\n\", args);\n      return this;\n    }\n\n    public Builder defaultValue(String format, Object... args) {\n      return defaultValue(CodeBlock.of(format, args));\n    }\n\n    public Builder defaultValue(CodeBlock codeBlock) {\n      checkState(this.defaultValue == null, \"defaultValue was already set\");\n      this.defaultValue = checkNotNull(codeBlock, \"codeBlock == null\");\n      return this;\n    }\n\n    /**\n     * @param controlFlow the control flow construct and its code, such as \"if (foo == 5)\".\n     * Shouldn't contain braces or newline characters.\n     */\n    public Builder beginControlFlow(String controlFlow, Object... args) {\n      code.beginControlFlow(controlFlow, args);\n      return this;\n    }\n\n    /**\n     * @param codeBlock the control flow construct and its code, such as \"if (foo == 5)\".\n     * Shouldn't contain braces or newline characters.\n     */\n    public Builder beginControlFlow(CodeBlock codeBlock) {\n      return beginControlFlow(\"$L\", codeBlock);\n    }\n\n    /**\n     * @param controlFlow the control flow construct and its code, such as \"else if (foo == 10)\".\n     *     Shouldn't contain braces or newline characters.\n     */\n    public Builder nextControlFlow(String controlFlow, Object... args) {\n      code.nextControlFlow(controlFlow, args);\n      return this;\n    }\n\n    /**\n     * @param codeBlock the control flow construct and its code, such as \"else if (foo == 10)\".\n     *     Shouldn't contain braces or newline characters.\n     */\n    public Builder nextControlFlow(CodeBlock codeBlock) {\n      return nextControlFlow(\"$L\", codeBlock);\n    }\n\n    public Builder endControlFlow() {\n      code.endControlFlow();\n      return this;\n    }\n\n    /**\n     * @param controlFlow the optional control flow construct and its code, such as\n     *     \"while(foo == 20)\". Only used for \"do/while\" control flows.\n     */\n    public Builder endControlFlow(String controlFlow, Object... args) {\n      code.endControlFlow(controlFlow, args);\n      return this;\n    }\n\n    /**\n     * @param codeBlock the optional control flow construct and its code, such as\n     *     \"while(foo == 20)\". Only used for \"do/while\" control flows.\n     */\n    public Builder endControlFlow(CodeBlock codeBlock) {\n      return endControlFlow(\"$L\", codeBlock);\n    }\n\n    public Builder addStatement(String format, Object... args) {\n      code.addStatement(format, args);\n      return this;\n    }\n\n    public Builder addStatement(CodeBlock codeBlock) {\n      code.addStatement(codeBlock);\n      return this;\n    }\n\n    public MethodSpec build() {\n      return new MethodSpec(this);\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/NameAllocator.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.UUID;\nimport javax.lang.model.SourceVersion;\n\nimport static com.squareup.javapoet.Util.checkNotNull;\n\n/**\n * Assigns Java identifier names to avoid collisions, keywords, and invalid characters. To use,\n * first create an instance and allocate all of the names that you need. Typically this is a\n * mix of user-supplied names and constants: <pre>   {@code\n *\n *   NameAllocator nameAllocator = new NameAllocator();\n *   for (MyProperty property : properties) {\n *     nameAllocator.newName(property.name(), property);\n *   }\n *   nameAllocator.newName(\"sb\", \"string builder\");\n * }</pre>\n *\n * Pass a unique tag object to each allocation. The tag scopes the name, and can be used to look up\n * the allocated name later. Typically the tag is the object that is being named. In the above\n * example we use {@code property} for the user-supplied property names, and {@code \"string\n * builder\"} for our constant string builder.\n *\n * <p>Once we've allocated names we can use them when generating code: <pre>   {@code\n *\n *   MethodSpec.Builder builder = MethodSpec.methodBuilder(\"toString\")\n *       .addAnnotation(Override.class)\n *       .addModifiers(Modifier.PUBLIC)\n *       .returns(String.class);\n *\n *   builder.addStatement(\"$1T $2N = new $1T()\",\n *       StringBuilder.class, nameAllocator.get(\"string builder\"));\n *   for (MyProperty property : properties) {\n *     builder.addStatement(\"$N.append($N)\",\n *         nameAllocator.get(\"string builder\"), nameAllocator.get(property));\n *   }\n *   builder.addStatement(\"return $N\", nameAllocator.get(\"string builder\"));\n *   return builder.build();\n * }</pre>\n *\n * The above code generates unique names if presented with conflicts. Given user-supplied properties\n * with names {@code ab} and {@code sb} this generates the following:  <pre>   {@code\n *\n *   &#64;Override\n *   public String toString() {\n *     StringBuilder sb_ = new StringBuilder();\n *     sb_.append(ab);\n *     sb_.append(sb);\n *     return sb_.toString();\n *   }\n * }</pre>\n *\n * The underscore is appended to {@code sb} to avoid conflicting with the user-supplied {@code sb}\n * property. Underscores are also prefixed for names that start with a digit, and used to replace\n * name-unsafe characters like space or dash.\n *\n * <p>When dealing with multiple independent inner scopes, use a {@link #clone()} of the\n * NameAllocator used for the outer scope to further refine name allocation for a specific inner\n * scope.\n */\npublic final class NameAllocator implements Cloneable {\n  private final Set<String> allocatedNames;\n  private final Map<Object, String> tagToName;\n\n  public NameAllocator() {\n    this(new LinkedHashSet<>(), new LinkedHashMap<>());\n  }\n\n  private NameAllocator(LinkedHashSet<String> allocatedNames,\n                        LinkedHashMap<Object, String> tagToName) {\n    this.allocatedNames = allocatedNames;\n    this.tagToName = tagToName;\n  }\n\n  /**\n   * Return a new name using {@code suggestion} that will not be a Java identifier or clash with\n   * other names.\n   */\n  public String newName(String suggestion) {\n    return newName(suggestion, UUID.randomUUID().toString());\n  }\n\n  /**\n   * Return a new name using {@code suggestion} that will not be a Java identifier or clash with\n   * other names. The returned value can be queried multiple times by passing {@code tag} to\n   * {@link #get(Object)}.\n   */\n  public String newName(String suggestion, Object tag) {\n    checkNotNull(suggestion, \"suggestion\");\n    checkNotNull(tag, \"tag\");\n\n    suggestion = toJavaIdentifier(suggestion);\n\n    while (SourceVersion.isKeyword(suggestion) || !allocatedNames.add(suggestion)) {\n      suggestion = suggestion + \"_\";\n    }\n\n    String replaced = tagToName.put(tag, suggestion);\n    if (replaced != null) {\n      tagToName.put(tag, replaced); // Put things back as they were!\n      throw new IllegalArgumentException(\"tag \" + tag + \" cannot be used for both '\" + replaced\n          + \"' and '\" + suggestion + \"'\");\n    }\n\n    return suggestion;\n  }\n\n  public static String toJavaIdentifier(String suggestion) {\n    StringBuilder result = new StringBuilder();\n    for (int i = 0; i < suggestion.length(); ) {\n      int codePoint = suggestion.codePointAt(i);\n      if (i == 0\n          && !Character.isJavaIdentifierStart(codePoint)\n          && Character.isJavaIdentifierPart(codePoint)) {\n        result.append(\"_\");\n      }\n\n      int validCodePoint = Character.isJavaIdentifierPart(codePoint) ? codePoint : '_';\n      result.appendCodePoint(validCodePoint);\n      i += Character.charCount(codePoint);\n    }\n    return result.toString();\n  }\n\n  /** Retrieve a name created with {@link #newName(String, Object)}. */\n  public String get(Object tag) {\n    String result = tagToName.get(tag);\n    if (result == null) {\n      throw new IllegalArgumentException(\"unknown tag: \" + tag);\n    }\n    return result;\n  }\n\n  /**\n   * Create a deep copy of this NameAllocator. Useful to create multiple independent refinements\n   * of a NameAllocator to be used in the respective definition of multiples, independently-scoped,\n   * inner code blocks.\n   *\n   * @return A deep copy of this NameAllocator.\n   */\n  @Override\n  public NameAllocator clone() {\n    return new NameAllocator(\n        new LinkedHashSet<>(this.allocatedNames),\n        new LinkedHashMap<>(this.tagToName));\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/ParameterSpec.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.ElementKind;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.VariableElement;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\n\n/** A generated parameter declaration. */\npublic final class ParameterSpec {\n  public final String name;\n  public final List<AnnotationSpec> annotations;\n  public final Set<Modifier> modifiers;\n  public final TypeName type;\n  public final CodeBlock javadoc;\n\n  private ParameterSpec(Builder builder) {\n    this.name = checkNotNull(builder.name, \"name == null\");\n    this.annotations = Util.immutableList(builder.annotations);\n    this.modifiers = Util.immutableSet(builder.modifiers);\n    this.type = checkNotNull(builder.type, \"type == null\");\n    this.javadoc = builder.javadoc.build();\n  }\n\n  public boolean hasModifier(Modifier modifier) {\n    return modifiers.contains(modifier);\n  }\n\n  void emit(CodeWriter codeWriter, boolean varargs) throws IOException {\n    codeWriter.emitAnnotations(annotations, true);\n    codeWriter.emitModifiers(modifiers);\n    if (varargs) {\n      TypeName.asArray(type).emit(codeWriter, true);\n    } else {\n      type.emit(codeWriter);\n    }\n    codeWriter.emit(\" $L\", name);\n  }\n\n  @Override public boolean equals(Object o) {\n    if (this == o) return true;\n    if (o == null) return false;\n    if (getClass() != o.getClass()) return false;\n    return toString().equals(o.toString());\n  }\n\n  @Override public int hashCode() {\n    return toString().hashCode();\n  }\n\n  @Override public String toString() {\n    StringBuilder out = new StringBuilder();\n    try {\n      CodeWriter codeWriter = new CodeWriter(out);\n      emit(codeWriter, false);\n      return out.toString();\n    } catch (IOException e) {\n      throw new AssertionError();\n    }\n  }\n\n  public static ParameterSpec get(VariableElement element) {\n    checkArgument(element.getKind().equals(ElementKind.PARAMETER), \"element is not a parameter\");\n\n    TypeName type = TypeName.get(element.asType());\n    String name = element.getSimpleName().toString();\n    // Copying parameter annotations can be incorrect so we're deliberately not including them.\n    // See https://github.com/square/javapoet/issues/482.\n    return ParameterSpec.builder(type, name)\n        .addModifiers(element.getModifiers())\n        .build();\n  }\n\n  static List<ParameterSpec> parametersOf(ExecutableElement method) {\n    List<ParameterSpec> result = new ArrayList<>();\n    for (VariableElement parameter : method.getParameters()) {\n      result.add(ParameterSpec.get(parameter));\n    }\n    return result;\n  }\n\n  private static boolean isValidParameterName(String name) {\n    // Allow \"this\" for explicit receiver parameters\n    // See https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.1.\n    if (name.endsWith(\".this\")) {\n      return SourceVersion.isIdentifier(name.substring(0, name.length() - \".this\".length()));\n    }\n    return name.equals(\"this\") || SourceVersion.isName(name);\n  }\n\n  public static Builder builder(TypeName type, String name, Modifier... modifiers) {\n    checkNotNull(type, \"type == null\");\n    checkArgument(isValidParameterName(name), \"not a valid name: %s\", name);\n    return new Builder(type, name)\n        .addModifiers(modifiers);\n  }\n\n  public static Builder builder(Type type, String name, Modifier... modifiers) {\n    return builder(TypeName.get(type), name, modifiers);\n  }\n\n  public Builder toBuilder() {\n    return toBuilder(type, name);\n  }\n\n  Builder toBuilder(TypeName type, String name) {\n    Builder builder = new Builder(type, name);\n    builder.annotations.addAll(annotations);\n    builder.modifiers.addAll(modifiers);\n    return builder;\n  }\n\n  public static final class Builder {\n    private final TypeName type;\n    private final String name;\n    private final CodeBlock.Builder javadoc = CodeBlock.builder();\n\n    public final List<AnnotationSpec> annotations = new ArrayList<>();\n    public final List<Modifier> modifiers = new ArrayList<>();\n\n    private Builder(TypeName type, String name) {\n      this.type = type;\n      this.name = name;\n    }\n\n    public Builder addJavadoc(String format, Object... args) {\n      javadoc.add(format, args);\n      return this;\n    }\n\n    public Builder addJavadoc(CodeBlock block) {\n      javadoc.add(block);\n      return this;\n    }\n\n    public Builder addAnnotations(Iterable<AnnotationSpec> annotationSpecs) {\n      checkArgument(annotationSpecs != null, \"annotationSpecs == null\");\n      for (AnnotationSpec annotationSpec : annotationSpecs) {\n        this.annotations.add(annotationSpec);\n      }\n      return this;\n    }\n\n    public Builder addAnnotation(AnnotationSpec annotationSpec) {\n      this.annotations.add(annotationSpec);\n      return this;\n    }\n\n    public Builder addAnnotation(ClassName annotation) {\n      this.annotations.add(AnnotationSpec.builder(annotation).build());\n      return this;\n    }\n\n    public Builder addAnnotation(Class<?> annotation) {\n      return addAnnotation(ClassName.get(annotation));\n    }\n\n    public Builder addModifiers(Modifier... modifiers) {\n      Collections.addAll(this.modifiers, modifiers);\n      return this;\n    }\n\n    public Builder addModifiers(Iterable<Modifier> modifiers) {\n      checkNotNull(modifiers, \"modifiers == null\");\n      for (Modifier modifier : modifiers) {\n        if (!modifier.equals(Modifier.FINAL)) {\n          throw new IllegalStateException(\"unexpected parameter modifier: \" + modifier);\n        }\n        this.modifiers.add(modifier);\n      }\n      return this;\n    }\n\n    public ParameterSpec build() {\n      return new ParameterSpec(this);\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/ParameterizedTypeName.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.Modifier;\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\n\npublic final class ParameterizedTypeName extends TypeName {\n  private final ParameterizedTypeName enclosingType;\n  public final ClassName rawType;\n  public final List<TypeName> typeArguments;\n\n  ParameterizedTypeName(ParameterizedTypeName enclosingType, ClassName rawType,\n      List<TypeName> typeArguments) {\n    this(enclosingType, rawType, typeArguments, new ArrayList<>());\n  }\n\n  private ParameterizedTypeName(ParameterizedTypeName enclosingType, ClassName rawType,\n      List<TypeName> typeArguments, List<AnnotationSpec> annotations) {\n    super(annotations);\n    this.rawType = checkNotNull(rawType, \"rawType == null\").annotated(annotations);\n    this.enclosingType = enclosingType;\n    this.typeArguments = Util.immutableList(typeArguments);\n\n    checkArgument(!this.typeArguments.isEmpty() || enclosingType != null,\n        \"no type arguments: %s\", rawType);\n    for (TypeName typeArgument : this.typeArguments) {\n      checkArgument(!typeArgument.isPrimitive() && typeArgument != VOID,\n          \"invalid type parameter: %s\", typeArgument);\n    }\n  }\n\n  @Override public ParameterizedTypeName annotated(List<AnnotationSpec> annotations) {\n    return new ParameterizedTypeName(\n        enclosingType, rawType, typeArguments, concatAnnotations(annotations));\n  }\n\n  @Override\n  public TypeName withoutAnnotations() {\n    return new ParameterizedTypeName(\n        enclosingType, rawType.withoutAnnotations(), typeArguments, new ArrayList<>());\n  }\n\n  @Override CodeWriter emit(CodeWriter out) throws IOException {\n    if (enclosingType != null) {\n      enclosingType.emit(out);\n      out.emit(\".\");\n      if (isAnnotated()) {\n        out.emit(\" \");\n        emitAnnotations(out);\n      }\n      out.emit(rawType.simpleName());\n    } else {\n      rawType.emit(out);\n    }\n    if (!typeArguments.isEmpty()) {\n      out.emitAndIndent(\"<\");\n      boolean firstParameter = true;\n      for (TypeName parameter : typeArguments) {\n        if (!firstParameter) out.emitAndIndent(\", \");\n        parameter.emit(out);\n        firstParameter = false;\n      }\n      out.emitAndIndent(\">\");\n    }\n    return out;\n  }\n\n  /**\n   * Returns a new {@link ParameterizedTypeName} instance for the specified {@code name} as nested\n   * inside this class.\n   */\n  public ParameterizedTypeName nestedClass(String name) {\n    checkNotNull(name, \"name == null\");\n    return new ParameterizedTypeName(this, rawType.nestedClass(name), new ArrayList<>(),\n        new ArrayList<>());\n  }\n\n  /**\n   * Returns a new {@link ParameterizedTypeName} instance for the specified {@code name} as nested\n   * inside this class, with the specified {@code typeArguments}.\n   */\n  public ParameterizedTypeName nestedClass(String name, List<TypeName> typeArguments) {\n    checkNotNull(name, \"name == null\");\n    return new ParameterizedTypeName(this, rawType.nestedClass(name), typeArguments,\n        new ArrayList<>());\n  }\n\n  /** Returns a parameterized type, applying {@code typeArguments} to {@code rawType}. */\n  public static ParameterizedTypeName get(ClassName rawType, TypeName... typeArguments) {\n    return new ParameterizedTypeName(null, rawType, Arrays.asList(typeArguments));\n  }\n\n  /** Returns a parameterized type, applying {@code typeArguments} to {@code rawType}. */\n  public static ParameterizedTypeName get(Class<?> rawType, Type... typeArguments) {\n    return new ParameterizedTypeName(null, ClassName.get(rawType), list(typeArguments));\n  }\n\n  /** Returns a parameterized type equivalent to {@code type}. */\n  public static ParameterizedTypeName get(ParameterizedType type) {\n    return get(type, new LinkedHashMap<>());\n  }\n\n  /** Returns a parameterized type equivalent to {@code type}. */\n  static ParameterizedTypeName get(ParameterizedType type, Map<Type, TypeVariableName> map) {\n    ClassName rawType = ClassName.get((Class<?>) type.getRawType());\n    ParameterizedType ownerType = (type.getOwnerType() instanceof ParameterizedType)\n        && !Modifier.isStatic(((Class<?>) type.getRawType()).getModifiers())\n        ? (ParameterizedType) type.getOwnerType() : null;\n    List<TypeName> typeArguments = TypeName.list(type.getActualTypeArguments(), map);\n    return (ownerType != null)\n        ? get(ownerType, map).nestedClass(rawType.simpleName(), typeArguments)\n        : new ParameterizedTypeName(null, rawType, typeArguments);\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/TypeName.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.GenericArrayType;\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\nimport java.lang.reflect.TypeVariable;\nimport java.lang.reflect.WildcardType;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.element.TypeParameterElement;\nimport javax.lang.model.type.ArrayType;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.type.ErrorType;\nimport javax.lang.model.type.NoType;\nimport javax.lang.model.type.PrimitiveType;\nimport javax.lang.model.type.TypeKind;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.util.SimpleTypeVisitor8;\n\n/**\n * Any type in Java's type system, plus {@code void}. This class is an identifier for primitive\n * types like {@code int} and raw reference types like {@code String} and {@code List}. It also\n * identifies composite types like {@code char[]} and {@code Set<Long>}.\n *\n * <p>Type names are dumb identifiers only and do not model the values they name. For example, the\n * type name for {@code java.util.List} doesn't know about the {@code size()} method, the fact that\n * lists are collections, or even that it accepts a single type parameter.\n *\n * <p>Instances of this class are immutable value objects that implement {@code equals()} and {@code\n * hashCode()} properly.\n *\n * <h3>Referencing existing types</h3>\n *\n * <p>Primitives and void are constants that you can reference directly: see {@link #INT}, {@link\n * #DOUBLE}, and {@link #VOID}.\n *\n * <p>In an annotation processor you can get a type name instance for a type mirror by calling\n * {@link #get(TypeMirror)}. In reflection code, you can use {@link #get(Type)}.\n *\n * <h3>Defining new types</h3>\n *\n * <p>Create new reference types like {@code com.example.HelloWorld} with {@link\n * ClassName#get(String, String, String...)}. To build composite types like {@code char[]} and\n * {@code Set<Long>}, use the factory methods on {@link ArrayTypeName}, {@link\n * ParameterizedTypeName}, {@link TypeVariableName}, and {@link WildcardTypeName}.\n */\npublic class TypeName {\n  public static final TypeName VOID = new TypeName(\"void\");\n  public static final TypeName BOOLEAN = new TypeName(\"boolean\");\n  public static final TypeName BYTE = new TypeName(\"byte\");\n  public static final TypeName SHORT = new TypeName(\"short\");\n  public static final TypeName INT = new TypeName(\"int\");\n  public static final TypeName LONG = new TypeName(\"long\");\n  public static final TypeName CHAR = new TypeName(\"char\");\n  public static final TypeName FLOAT = new TypeName(\"float\");\n  public static final TypeName DOUBLE = new TypeName(\"double\");\n  public static final ClassName OBJECT = ClassName.get(\"java.lang\", \"Object\");\n\n  private static final ClassName BOXED_VOID = ClassName.get(\"java.lang\", \"Void\");\n  private static final ClassName BOXED_BOOLEAN = ClassName.get(\"java.lang\", \"Boolean\");\n  private static final ClassName BOXED_BYTE = ClassName.get(\"java.lang\", \"Byte\");\n  private static final ClassName BOXED_SHORT = ClassName.get(\"java.lang\", \"Short\");\n  private static final ClassName BOXED_INT = ClassName.get(\"java.lang\", \"Integer\");\n  private static final ClassName BOXED_LONG = ClassName.get(\"java.lang\", \"Long\");\n  private static final ClassName BOXED_CHAR = ClassName.get(\"java.lang\", \"Character\");\n  private static final ClassName BOXED_FLOAT = ClassName.get(\"java.lang\", \"Float\");\n  private static final ClassName BOXED_DOUBLE = ClassName.get(\"java.lang\", \"Double\");\n\n  /** The name of this type if it is a keyword, or null. */\n  private final String keyword;\n  public final List<AnnotationSpec> annotations;\n\n  /** Lazily-initialized toString of this type name. */\n  private String cachedString;\n\n  private TypeName(String keyword) {\n    this(keyword, new ArrayList<>());\n  }\n\n  private TypeName(String keyword, List<AnnotationSpec> annotations) {\n    this.keyword = keyword;\n    this.annotations = Util.immutableList(annotations);\n  }\n\n  // Package-private constructor to prevent third-party subclasses.\n  TypeName(List<AnnotationSpec> annotations) {\n    this(null, annotations);\n  }\n\n  public final TypeName annotated(AnnotationSpec... annotations) {\n    return annotated(Arrays.asList(annotations));\n  }\n\n  public TypeName annotated(List<AnnotationSpec> annotations) {\n    Util.checkNotNull(annotations, \"annotations == null\");\n    return new TypeName(keyword, concatAnnotations(annotations));\n  }\n\n  public TypeName withoutAnnotations() {\n    if (annotations.isEmpty()) {\n      return this;\n    }\n    return new TypeName(keyword);\n  }\n\n  protected final List<AnnotationSpec> concatAnnotations(List<AnnotationSpec> annotations) {\n    List<AnnotationSpec> allAnnotations = new ArrayList<>(this.annotations);\n    allAnnotations.addAll(annotations);\n    return allAnnotations;\n  }\n\n  public boolean isAnnotated() {\n    return !annotations.isEmpty();\n  }\n\n  /**\n   * Returns true if this is a primitive type like {@code int}. Returns false for all other types\n   * types including boxed primitives and {@code void}.\n   */\n  public boolean isPrimitive() {\n    return keyword != null && this != VOID;\n  }\n\n  /**\n   * Returns true if this is a boxed primitive type like {@code Integer}. Returns false for all\n   * other types types including unboxed primitives and {@code java.lang.Void}.\n   */\n  public boolean isBoxedPrimitive() {\n    TypeName thisWithoutAnnotations = withoutAnnotations();\n    return thisWithoutAnnotations.equals(BOXED_BOOLEAN)\n        || thisWithoutAnnotations.equals(BOXED_BYTE)\n        || thisWithoutAnnotations.equals(BOXED_SHORT)\n        || thisWithoutAnnotations.equals(BOXED_INT)\n        || thisWithoutAnnotations.equals(BOXED_LONG)\n        || thisWithoutAnnotations.equals(BOXED_CHAR)\n        || thisWithoutAnnotations.equals(BOXED_FLOAT)\n        || thisWithoutAnnotations.equals(BOXED_DOUBLE);\n  }\n\n  /**\n   * Returns a boxed type if this is a primitive type (like {@code Integer} for {@code int}) or\n   * {@code void}. Returns this type if boxing doesn't apply.\n   */\n  public TypeName box() {\n    if (keyword == null) return this; // Doesn't need boxing.\n    TypeName boxed = null;\n    if (keyword.equals(VOID.keyword)) boxed = BOXED_VOID;\n    else if (keyword.equals(BOOLEAN.keyword)) boxed = BOXED_BOOLEAN;\n    else if (keyword.equals(BYTE.keyword)) boxed = BOXED_BYTE;\n    else if (keyword.equals(SHORT.keyword)) boxed = BOXED_SHORT;\n    else if (keyword.equals(INT.keyword)) boxed = BOXED_INT;\n    else if (keyword.equals(LONG.keyword)) boxed = BOXED_LONG;\n    else if (keyword.equals(CHAR.keyword)) boxed = BOXED_CHAR;\n    else if (keyword.equals(FLOAT.keyword)) boxed = BOXED_FLOAT;\n    else if (keyword.equals(DOUBLE.keyword)) boxed = BOXED_DOUBLE;\n    else throw new AssertionError(keyword);\n    return annotations.isEmpty() ? boxed : boxed.annotated(annotations);\n  }\n\n  /**\n   * Returns an unboxed type if this is a boxed primitive type (like {@code int} for {@code\n   * Integer}) or {@code Void}. Returns this type if it is already unboxed.\n   *\n   * @throws UnsupportedOperationException if this type isn't eligible for unboxing.\n   */\n  public TypeName unbox() {\n    if (keyword != null) return this; // Already unboxed.\n    TypeName thisWithoutAnnotations = withoutAnnotations();\n    TypeName unboxed = null;\n    if (thisWithoutAnnotations.equals(BOXED_VOID)) unboxed = VOID;\n    else if (thisWithoutAnnotations.equals(BOXED_BOOLEAN)) unboxed = BOOLEAN;\n    else if (thisWithoutAnnotations.equals(BOXED_BYTE)) unboxed = BYTE;\n    else if (thisWithoutAnnotations.equals(BOXED_SHORT)) unboxed = SHORT;\n    else if (thisWithoutAnnotations.equals(BOXED_INT)) unboxed = INT;\n    else if (thisWithoutAnnotations.equals(BOXED_LONG)) unboxed = LONG;\n    else if (thisWithoutAnnotations.equals(BOXED_CHAR)) unboxed = CHAR;\n    else if (thisWithoutAnnotations.equals(BOXED_FLOAT)) unboxed = FLOAT;\n    else if (thisWithoutAnnotations.equals(BOXED_DOUBLE)) unboxed = DOUBLE;\n    else throw new UnsupportedOperationException(\"cannot unbox \" + this);\n    return annotations.isEmpty() ? unboxed : unboxed.annotated(annotations);\n  }\n\n  @Override public final boolean equals(Object o) {\n    if (this == o) return true;\n    if (o == null) return false;\n    if (getClass() != o.getClass()) return false;\n    return toString().equals(o.toString());\n  }\n\n  @Override public final int hashCode() {\n    return toString().hashCode();\n  }\n\n  @Override public final String toString() {\n    String result = cachedString;\n    if (result == null) {\n      try {\n        StringBuilder resultBuilder = new StringBuilder();\n        CodeWriter codeWriter = new CodeWriter(resultBuilder);\n        emit(codeWriter);\n        result = resultBuilder.toString();\n        cachedString = result;\n      } catch (IOException e) {\n        throw new AssertionError();\n      }\n    }\n    return result;\n  }\n\n  CodeWriter emit(CodeWriter out) throws IOException {\n    if (keyword == null) throw new AssertionError();\n\n    if (isAnnotated()) {\n      out.emit(\"\");\n      emitAnnotations(out);\n    }\n    return out.emitAndIndent(keyword);\n  }\n\n  CodeWriter emitAnnotations(CodeWriter out) throws IOException {\n    for (AnnotationSpec annotation : annotations) {\n      annotation.emit(out, true);\n      out.emit(\" \");\n    }\n    return out;\n  }\n\n\n  /** Returns a type name equivalent to {@code mirror}. */\n  public static TypeName get(TypeMirror mirror) {\n    return get(mirror, new LinkedHashMap<>());\n  }\n\n  static TypeName get(TypeMirror mirror,\n      final Map<TypeParameterElement, TypeVariableName> typeVariables) {\n    return mirror.accept(new SimpleTypeVisitor8<TypeName, Void>() {\n      @Override public TypeName visitPrimitive(PrimitiveType t, Void p) {\n        switch (t.getKind()) {\n          case BOOLEAN:\n            return TypeName.BOOLEAN;\n          case BYTE:\n            return TypeName.BYTE;\n          case SHORT:\n            return TypeName.SHORT;\n          case INT:\n            return TypeName.INT;\n          case LONG:\n            return TypeName.LONG;\n          case CHAR:\n            return TypeName.CHAR;\n          case FLOAT:\n            return TypeName.FLOAT;\n          case DOUBLE:\n            return TypeName.DOUBLE;\n          default:\n            throw new AssertionError();\n        }\n      }\n\n      @Override public TypeName visitDeclared(DeclaredType t, Void p) {\n        ClassName rawType = ClassName.get((TypeElement) t.asElement());\n        TypeMirror enclosingType = t.getEnclosingType();\n        TypeName enclosing =\n            (enclosingType.getKind() != TypeKind.NONE)\n                    && !t.asElement().getModifiers().contains(Modifier.STATIC)\n                ? enclosingType.accept(this, null)\n                : null;\n        if (t.getTypeArguments().isEmpty() && !(enclosing instanceof ParameterizedTypeName)) {\n          return rawType;\n        }\n\n        List<TypeName> typeArgumentNames = new ArrayList<>();\n        for (TypeMirror mirror : t.getTypeArguments()) {\n          typeArgumentNames.add(get(mirror, typeVariables));\n        }\n        return enclosing instanceof ParameterizedTypeName\n            ? ((ParameterizedTypeName) enclosing).nestedClass(\n            rawType.simpleName(), typeArgumentNames)\n            : new ParameterizedTypeName(null, rawType, typeArgumentNames);\n      }\n\n      @Override public TypeName visitError(ErrorType t, Void p) {\n        return visitDeclared(t, p);\n      }\n\n      @Override public ArrayTypeName visitArray(ArrayType t, Void p) {\n        return ArrayTypeName.get(t, typeVariables);\n      }\n\n      @Override public TypeName visitTypeVariable(javax.lang.model.type.TypeVariable t, Void p) {\n        return TypeVariableName.get(t, typeVariables);\n      }\n\n      @Override public TypeName visitWildcard(javax.lang.model.type.WildcardType t, Void p) {\n        return WildcardTypeName.get(t, typeVariables);\n      }\n\n      @Override public TypeName visitNoType(NoType t, Void p) {\n        if (t.getKind() == TypeKind.VOID) return TypeName.VOID;\n        return super.visitUnknown(t, p);\n      }\n\n      @Override protected TypeName defaultAction(TypeMirror e, Void p) {\n        throw new IllegalArgumentException(\"Unexpected type mirror: \" + e);\n      }\n    }, null);\n  }\n\n  /** Returns a type name equivalent to {@code type}. */\n  public static TypeName get(Type type) {\n    return get(type, new LinkedHashMap<>());\n  }\n\n  static TypeName get(Type type, Map<Type, TypeVariableName> map) {\n    if (type instanceof Class<?>) {\n      Class<?> classType = (Class<?>) type;\n      if (type == void.class) return VOID;\n      if (type == boolean.class) return BOOLEAN;\n      if (type == byte.class) return BYTE;\n      if (type == short.class) return SHORT;\n      if (type == int.class) return INT;\n      if (type == long.class) return LONG;\n      if (type == char.class) return CHAR;\n      if (type == float.class) return FLOAT;\n      if (type == double.class) return DOUBLE;\n      if (classType.isArray()) return ArrayTypeName.of(get(classType.getComponentType(), map));\n      return ClassName.get(classType);\n\n    } else if (type instanceof ParameterizedType) {\n      return ParameterizedTypeName.get((ParameterizedType) type, map);\n\n    } else if (type instanceof WildcardType) {\n      return WildcardTypeName.get((WildcardType) type, map);\n\n    } else if (type instanceof TypeVariable<?>) {\n      return TypeVariableName.get((TypeVariable<?>) type, map);\n\n    } else if (type instanceof GenericArrayType) {\n      return ArrayTypeName.get((GenericArrayType) type, map);\n\n    } else {\n      throw new IllegalArgumentException(\"unexpected type: \" + type);\n    }\n  }\n\n  /** Converts an array of types to a list of type names. */\n  static List<TypeName> list(Type[] types) {\n    return list(types, new LinkedHashMap<>());\n  }\n\n  static List<TypeName> list(Type[] types, Map<Type, TypeVariableName> map) {\n    List<TypeName> result = new ArrayList<>(types.length);\n    for (Type type : types) {\n      result.add(get(type, map));\n    }\n    return result;\n  }\n\n  /** Returns the array component of {@code type}, or null if {@code type} is not an array. */\n  static TypeName arrayComponent(TypeName type) {\n    return type instanceof ArrayTypeName\n        ? ((ArrayTypeName) type).componentType\n        : null;\n  }\n\n  /** Returns {@code type} as an array, or null if {@code type} is not an array. */\n  static ArrayTypeName asArray(TypeName type) {\n    return type instanceof ArrayTypeName\n        ? ((ArrayTypeName) type)\n        : null;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/TypeSpec.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.type.NoType;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.util.ElementFilter;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\nimport static com.squareup.javapoet.Util.checkState;\nimport static com.squareup.javapoet.Util.requireExactlyOneOf;\n\n/** A generated class, interface, or enum declaration. */\npublic final class TypeSpec {\n  public final Kind kind;\n  public final String name;\n  public final CodeBlock anonymousTypeArguments;\n  public final CodeBlock javadoc;\n  public final List<AnnotationSpec> annotations;\n  public final Set<Modifier> modifiers;\n  public final List<TypeVariableName> typeVariables;\n  public final TypeName superclass;\n  public final List<TypeName> superinterfaces;\n  public final Map<String, TypeSpec> enumConstants;\n  public final List<FieldSpec> fieldSpecs;\n  public final CodeBlock staticBlock;\n  public final CodeBlock initializerBlock;\n  public final List<MethodSpec> methodSpecs;\n  public final List<TypeSpec> typeSpecs;\n  final Set<String> nestedTypesSimpleNames;\n  public final List<Element> originatingElements;\n  public final Set<String> alwaysQualifiedNames;\n\n  private TypeSpec(Builder builder) {\n    this.kind = builder.kind;\n    this.name = builder.name;\n    this.anonymousTypeArguments = builder.anonymousTypeArguments;\n    this.javadoc = builder.javadoc.build();\n    this.annotations = Util.immutableList(builder.annotations);\n    this.modifiers = Util.immutableSet(builder.modifiers);\n    this.typeVariables = Util.immutableList(builder.typeVariables);\n    this.superclass = builder.superclass;\n    this.superinterfaces = Util.immutableList(builder.superinterfaces);\n    this.enumConstants = Util.immutableMap(builder.enumConstants);\n    this.fieldSpecs = Util.immutableList(builder.fieldSpecs);\n    this.staticBlock = builder.staticBlock.build();\n    this.initializerBlock = builder.initializerBlock.build();\n    this.methodSpecs = Util.immutableList(builder.methodSpecs);\n    this.typeSpecs = Util.immutableList(builder.typeSpecs);\n    this.alwaysQualifiedNames = Util.immutableSet(builder.alwaysQualifiedNames);\n\n    nestedTypesSimpleNames = new HashSet<>(builder.typeSpecs.size());\n    List<Element> originatingElementsMutable = new ArrayList<>();\n    originatingElementsMutable.addAll(builder.originatingElements);\n    for (TypeSpec typeSpec : builder.typeSpecs) {\n      nestedTypesSimpleNames.add(typeSpec.name);\n      originatingElementsMutable.addAll(typeSpec.originatingElements);\n    }\n\n    this.originatingElements = Util.immutableList(originatingElementsMutable);\n  }\n\n  /**\n   * Creates a dummy type spec for type-resolution only (in CodeWriter)\n   * while emitting the type declaration but before entering the type body.\n   */\n  private TypeSpec(TypeSpec type) {\n    assert type.anonymousTypeArguments == null;\n    this.kind = type.kind;\n    this.name = type.name;\n    this.anonymousTypeArguments = null;\n    this.javadoc = type.javadoc;\n    this.annotations = Collections.emptyList();\n    this.modifiers = Collections.emptySet();\n    this.typeVariables = Collections.emptyList();\n    this.superclass = null;\n    this.superinterfaces = Collections.emptyList();\n    this.enumConstants = Collections.emptyMap();\n    this.fieldSpecs = Collections.emptyList();\n    this.staticBlock = type.staticBlock;\n    this.initializerBlock = type.initializerBlock;\n    this.methodSpecs = Collections.emptyList();\n    this.typeSpecs = Collections.emptyList();\n    this.originatingElements = Collections.emptyList();\n    this.nestedTypesSimpleNames = Collections.emptySet();\n    this.alwaysQualifiedNames = Collections.emptySet();\n  }\n\n  public boolean hasModifier(Modifier modifier) {\n    return modifiers.contains(modifier);\n  }\n\n  public static Builder classBuilder(String name) {\n    return new Builder(Kind.CLASS, checkNotNull(name, \"name == null\"), null);\n  }\n\n  public static Builder classBuilder(ClassName className) {\n    return classBuilder(checkNotNull(className, \"className == null\").simpleName());\n  }\n\n  public static Builder interfaceBuilder(String name) {\n    return new Builder(Kind.INTERFACE, checkNotNull(name, \"name == null\"), null);\n  }\n\n  public static Builder interfaceBuilder(ClassName className) {\n    return interfaceBuilder(checkNotNull(className, \"className == null\").simpleName());\n  }\n\n  public static Builder enumBuilder(String name) {\n    return new Builder(Kind.ENUM, checkNotNull(name, \"name == null\"), null);\n  }\n\n  public static Builder enumBuilder(ClassName className) {\n    return enumBuilder(checkNotNull(className, \"className == null\").simpleName());\n  }\n\n  public static Builder anonymousClassBuilder(String typeArgumentsFormat, Object... args) {\n    return anonymousClassBuilder(CodeBlock.of(typeArgumentsFormat, args));\n  }\n\n  public static Builder anonymousClassBuilder(CodeBlock typeArguments) {\n    return new Builder(Kind.CLASS, null, typeArguments);\n  }\n\n  public static Builder annotationBuilder(String name) {\n    return new Builder(Kind.ANNOTATION, checkNotNull(name, \"name == null\"), null);\n  }\n\n  public static Builder annotationBuilder(ClassName className) {\n    return annotationBuilder(checkNotNull(className, \"className == null\").simpleName());\n  }\n\n  public Builder toBuilder() {\n    Builder builder = new Builder(kind, name, anonymousTypeArguments);\n    builder.javadoc.add(javadoc);\n    builder.annotations.addAll(annotations);\n    builder.modifiers.addAll(modifiers);\n    builder.typeVariables.addAll(typeVariables);\n    builder.superclass = superclass;\n    builder.superinterfaces.addAll(superinterfaces);\n    builder.enumConstants.putAll(enumConstants);\n    builder.fieldSpecs.addAll(fieldSpecs);\n    builder.methodSpecs.addAll(methodSpecs);\n    builder.typeSpecs.addAll(typeSpecs);\n    builder.initializerBlock.add(initializerBlock);\n    builder.staticBlock.add(staticBlock);\n    builder.originatingElements.addAll(originatingElements);\n    builder.alwaysQualifiedNames.addAll(alwaysQualifiedNames);\n    return builder;\n  }\n\n  void emit(CodeWriter codeWriter, String enumName, Set<Modifier> implicitModifiers)\n      throws IOException {\n    // Nested classes interrupt wrapped line indentation. Stash the current wrapping state and put\n    // it back afterwards when this type is complete.\n    int previousStatementLine = codeWriter.statementLine;\n    codeWriter.statementLine = -1;\n\n    try {\n      if (enumName != null) {\n        codeWriter.emitJavadoc(javadoc);\n        codeWriter.emitAnnotations(annotations, false);\n        codeWriter.emit(\"$L\", enumName);\n        if (!anonymousTypeArguments.formatParts.isEmpty()) {\n          codeWriter.emit(\"(\");\n          codeWriter.emit(anonymousTypeArguments);\n          codeWriter.emit(\")\");\n        }\n        if (fieldSpecs.isEmpty() && methodSpecs.isEmpty() && typeSpecs.isEmpty()) {\n          return; // Avoid unnecessary braces \"{}\".\n        }\n        codeWriter.emit(\" {\\n\");\n      } else if (anonymousTypeArguments != null) {\n        TypeName supertype = !superinterfaces.isEmpty() ? superinterfaces.get(0) : superclass;\n        codeWriter.emit(\"new $T(\", supertype);\n        codeWriter.emit(anonymousTypeArguments);\n        codeWriter.emit(\") {\\n\");\n      } else {\n        // Push an empty type (specifically without nested types) for type-resolution.\n        codeWriter.pushType(new TypeSpec(this));\n\n        codeWriter.emitJavadoc(javadoc);\n        codeWriter.emitAnnotations(annotations, false);\n        codeWriter.emitModifiers(modifiers, Util.union(implicitModifiers, kind.asMemberModifiers));\n        if (kind == Kind.ANNOTATION) {\n          codeWriter.emit(\"$L $L\", \"@interface\", name);\n        } else {\n          codeWriter.emit(\"$L $L\", kind.name().toLowerCase(Locale.US), name);\n        }\n        codeWriter.emitTypeVariables(typeVariables);\n\n        List<TypeName> extendsTypes;\n        List<TypeName> implementsTypes;\n        if (kind == Kind.INTERFACE) {\n          extendsTypes = superinterfaces;\n          implementsTypes = Collections.emptyList();\n        } else {\n          extendsTypes = superclass.equals(ClassName.OBJECT)\n              ? Collections.emptyList()\n              : Collections.singletonList(superclass);\n          implementsTypes = superinterfaces;\n        }\n\n        if (!extendsTypes.isEmpty()) {\n          codeWriter.emit(\" extends\");\n          boolean firstType = true;\n          for (TypeName type : extendsTypes) {\n            if (!firstType) codeWriter.emit(\",\");\n            codeWriter.emit(\" $T\", type);\n            firstType = false;\n          }\n        }\n\n        if (!implementsTypes.isEmpty()) {\n          codeWriter.emit(\" implements\");\n          boolean firstType = true;\n          for (TypeName type : implementsTypes) {\n            if (!firstType) codeWriter.emit(\",\");\n            codeWriter.emit(\" $T\", type);\n            firstType = false;\n          }\n        }\n\n        codeWriter.popType();\n\n        codeWriter.emit(\" {\\n\");\n      }\n\n      codeWriter.pushType(this);\n      codeWriter.indent();\n      boolean firstMember = true;\n      boolean needsSeparator = kind == Kind.ENUM\n              && (!fieldSpecs.isEmpty() || !methodSpecs.isEmpty() || !typeSpecs.isEmpty());\n      for (Iterator<Map.Entry<String, TypeSpec>> i = enumConstants.entrySet().iterator();\n          i.hasNext(); ) {\n        Map.Entry<String, TypeSpec> enumConstant = i.next();\n        if (!firstMember) codeWriter.emit(\"\\n\");\n        enumConstant.getValue().emit(codeWriter, enumConstant.getKey(), Collections.emptySet());\n        firstMember = false;\n        if (i.hasNext()) {\n          codeWriter.emit(\",\\n\");\n        } else if (!needsSeparator) {\n          codeWriter.emit(\"\\n\");\n        }\n      }\n\n      if (needsSeparator) codeWriter.emit(\";\\n\");\n\n      // Static fields.\n      for (FieldSpec fieldSpec : fieldSpecs) {\n        if (!fieldSpec.hasModifier(Modifier.STATIC)) continue;\n        if (!firstMember) codeWriter.emit(\"\\n\");\n        fieldSpec.emit(codeWriter, kind.implicitFieldModifiers);\n        firstMember = false;\n      }\n\n      if (!staticBlock.isEmpty()) {\n        if (!firstMember) codeWriter.emit(\"\\n\");\n        codeWriter.emit(staticBlock);\n        firstMember = false;\n      }\n\n      // Non-static fields.\n      for (FieldSpec fieldSpec : fieldSpecs) {\n        if (fieldSpec.hasModifier(Modifier.STATIC)) continue;\n        if (!firstMember) codeWriter.emit(\"\\n\");\n        fieldSpec.emit(codeWriter, kind.implicitFieldModifiers);\n        firstMember = false;\n      }\n\n      // Initializer block.\n      if (!initializerBlock.isEmpty()) {\n        if (!firstMember) codeWriter.emit(\"\\n\");\n        codeWriter.emit(initializerBlock);\n        firstMember = false;\n      }\n\n      // Constructors.\n      for (MethodSpec methodSpec : methodSpecs) {\n        if (!methodSpec.isConstructor()) continue;\n        if (!firstMember) codeWriter.emit(\"\\n\");\n        methodSpec.emit(codeWriter, name, kind.implicitMethodModifiers);\n        firstMember = false;\n      }\n\n      // Methods (static and non-static).\n      for (MethodSpec methodSpec : methodSpecs) {\n        if (methodSpec.isConstructor()) continue;\n        if (!firstMember) codeWriter.emit(\"\\n\");\n        methodSpec.emit(codeWriter, name, kind.implicitMethodModifiers);\n        firstMember = false;\n      }\n\n      // Types.\n      for (TypeSpec typeSpec : typeSpecs) {\n        if (!firstMember) codeWriter.emit(\"\\n\");\n        typeSpec.emit(codeWriter, null, kind.implicitTypeModifiers);\n        firstMember = false;\n      }\n\n      codeWriter.unindent();\n      codeWriter.popType();\n      codeWriter.popTypeVariables(typeVariables);\n\n      codeWriter.emit(\"}\");\n      if (enumName == null && anonymousTypeArguments == null) {\n        codeWriter.emit(\"\\n\"); // If this type isn't also a value, include a trailing newline.\n      }\n    } finally {\n      codeWriter.statementLine = previousStatementLine;\n    }\n  }\n\n  @Override public boolean equals(Object o) {\n    if (this == o) return true;\n    if (o == null) return false;\n    if (getClass() != o.getClass()) return false;\n    return toString().equals(o.toString());\n  }\n\n  @Override public int hashCode() {\n    return toString().hashCode();\n  }\n\n  @Override public String toString() {\n    StringBuilder out = new StringBuilder();\n    try {\n      CodeWriter codeWriter = new CodeWriter(out);\n      emit(codeWriter, null, Collections.emptySet());\n      return out.toString();\n    } catch (IOException e) {\n      throw new AssertionError();\n    }\n  }\n\n  public enum Kind {\n    CLASS(\n        Collections.emptySet(),\n        Collections.emptySet(),\n        Collections.emptySet(),\n        Collections.emptySet()),\n\n    INTERFACE(\n        Util.immutableSet(Arrays.asList(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)),\n        Util.immutableSet(Arrays.asList(Modifier.PUBLIC, Modifier.ABSTRACT)),\n        Util.immutableSet(Arrays.asList(Modifier.PUBLIC, Modifier.STATIC)),\n        Util.immutableSet(Collections.singletonList(Modifier.STATIC))),\n\n    ENUM(\n        Collections.emptySet(),\n        Collections.emptySet(),\n        Collections.emptySet(),\n        Collections.singleton(Modifier.STATIC)),\n\n    ANNOTATION(\n        Util.immutableSet(Arrays.asList(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)),\n        Util.immutableSet(Arrays.asList(Modifier.PUBLIC, Modifier.ABSTRACT)),\n        Util.immutableSet(Arrays.asList(Modifier.PUBLIC, Modifier.STATIC)),\n        Util.immutableSet(Collections.singletonList(Modifier.STATIC)));\n\n    private final Set<Modifier> implicitFieldModifiers;\n    private final Set<Modifier> implicitMethodModifiers;\n    private final Set<Modifier> implicitTypeModifiers;\n    private final Set<Modifier> asMemberModifiers;\n\n    Kind(Set<Modifier> implicitFieldModifiers,\n        Set<Modifier> implicitMethodModifiers,\n        Set<Modifier> implicitTypeModifiers,\n        Set<Modifier> asMemberModifiers) {\n      this.implicitFieldModifiers = implicitFieldModifiers;\n      this.implicitMethodModifiers = implicitMethodModifiers;\n      this.implicitTypeModifiers = implicitTypeModifiers;\n      this.asMemberModifiers = asMemberModifiers;\n    }\n  }\n\n  public static final class Builder {\n    private final Kind kind;\n    private final String name;\n    private final CodeBlock anonymousTypeArguments;\n\n    private final CodeBlock.Builder javadoc = CodeBlock.builder();\n    private TypeName superclass = ClassName.OBJECT;\n    private final CodeBlock.Builder staticBlock = CodeBlock.builder();\n    private final CodeBlock.Builder initializerBlock = CodeBlock.builder();\n\n    public final Map<String, TypeSpec> enumConstants = new LinkedHashMap<>();\n    public final List<AnnotationSpec> annotations = new ArrayList<>();\n    public final List<Modifier> modifiers = new ArrayList<>();\n    public final List<TypeVariableName> typeVariables = new ArrayList<>();\n    public final List<TypeName> superinterfaces = new ArrayList<>();\n    public final List<FieldSpec> fieldSpecs = new ArrayList<>();\n    public final List<MethodSpec> methodSpecs = new ArrayList<>();\n    public final List<TypeSpec> typeSpecs = new ArrayList<>();\n    public final List<Element> originatingElements = new ArrayList<>();\n    public final Set<String> alwaysQualifiedNames = new LinkedHashSet<>();\n\n    private Builder(Kind kind, String name,\n        CodeBlock anonymousTypeArguments) {\n      checkArgument(name == null || SourceVersion.isName(name), \"not a valid name: %s\", name);\n      this.kind = kind;\n      this.name = name;\n      this.anonymousTypeArguments = anonymousTypeArguments;\n    }\n\n    public Builder addJavadoc(String format, Object... args) {\n      javadoc.add(format, args);\n      return this;\n    }\n\n    public Builder addJavadoc(CodeBlock block) {\n      javadoc.add(block);\n      return this;\n    }\n\n    public Builder addAnnotations(Iterable<AnnotationSpec> annotationSpecs) {\n      checkArgument(annotationSpecs != null, \"annotationSpecs == null\");\n      for (AnnotationSpec annotationSpec : annotationSpecs) {\n        this.annotations.add(annotationSpec);\n      }\n      return this;\n    }\n\n    public Builder addAnnotation(AnnotationSpec annotationSpec) {\n      checkNotNull(annotationSpec, \"annotationSpec == null\");\n      this.annotations.add(annotationSpec);\n      return this;\n    }\n\n    public Builder addAnnotation(ClassName annotation) {\n      return addAnnotation(AnnotationSpec.builder(annotation).build());\n    }\n\n    public Builder addAnnotation(Class<?> annotation) {\n      return addAnnotation(ClassName.get(annotation));\n    }\n\n    public Builder addModifiers(Modifier... modifiers) {\n      Collections.addAll(this.modifiers, modifiers);\n      return this;\n    }\n\n    public Builder addTypeVariables(Iterable<TypeVariableName> typeVariables) {\n      checkArgument(typeVariables != null, \"typeVariables == null\");\n      for (TypeVariableName typeVariable : typeVariables) {\n        this.typeVariables.add(typeVariable);\n      }\n      return this;\n    }\n\n    public Builder addTypeVariable(TypeVariableName typeVariable) {\n      typeVariables.add(typeVariable);\n      return this;\n    }\n\n    public Builder superclass(TypeName superclass) {\n      checkState(this.kind == Kind.CLASS, \"only classes have super classes, not \" + this.kind);\n      checkState(this.superclass == ClassName.OBJECT,\n          \"superclass already set to \" + this.superclass);\n      checkArgument(!superclass.isPrimitive(), \"superclass may not be a primitive\");\n      this.superclass = superclass;\n      return this;\n    }\n\n    public Builder superclass(Type superclass) {\n      return superclass(superclass, true);\n    }\n\n    public Builder superclass(Type superclass, boolean avoidNestedTypeNameClashes) {\n      superclass(TypeName.get(superclass));\n      if (avoidNestedTypeNameClashes) {\n        Class<?> clazz = getRawType(superclass);\n        if (clazz != null) {\n          avoidClashesWithNestedClasses(clazz);\n        }\n      }\n      return this;\n    }\n\n    public Builder superclass(TypeMirror superclass) {\n      return superclass(superclass, true);\n    }\n\n    public Builder superclass(TypeMirror superclass, boolean avoidNestedTypeNameClashes) {\n      superclass(TypeName.get(superclass));\n      if (avoidNestedTypeNameClashes && superclass instanceof DeclaredType) {\n        TypeElement superInterfaceElement =\n            (TypeElement) ((DeclaredType) superclass).asElement();\n        avoidClashesWithNestedClasses(superInterfaceElement);\n      }\n      return this;\n    }\n\n    public Builder addSuperinterfaces(Iterable<? extends TypeName> superinterfaces) {\n      checkArgument(superinterfaces != null, \"superinterfaces == null\");\n      for (TypeName superinterface : superinterfaces) {\n        addSuperinterface(superinterface);\n      }\n      return this;\n    }\n\n    public Builder addSuperinterface(TypeName superinterface) {\n      checkArgument(superinterface != null, \"superinterface == null\");\n      this.superinterfaces.add(superinterface);\n      return this;\n    }\n\n    public Builder addSuperinterface(Type superinterface) {\n      return addSuperinterface(superinterface, true);\n    }\n\n    public Builder addSuperinterface(Type superinterface, boolean avoidNestedTypeNameClashes) {\n      addSuperinterface(TypeName.get(superinterface));\n      if (avoidNestedTypeNameClashes) {\n        Class<?> clazz = getRawType(superinterface);\n        if (clazz != null) {\n          avoidClashesWithNestedClasses(clazz);\n        }\n      }\n      return this;\n    }\n\n    private Class<?> getRawType(Type type) {\n      if (type instanceof Class<?>) {\n        return (Class<?>) type;\n      } else if (type instanceof ParameterizedType) {\n        return getRawType(((ParameterizedType) type).getRawType());\n      } else {\n        return null;\n      }\n    }\n\n    public Builder addSuperinterface(TypeMirror superinterface) {\n      return addSuperinterface(superinterface, true);\n    }\n\n    public Builder addSuperinterface(TypeMirror superinterface,\n        boolean avoidNestedTypeNameClashes) {\n      addSuperinterface(TypeName.get(superinterface));\n      if (avoidNestedTypeNameClashes && superinterface instanceof DeclaredType) {\n        TypeElement superInterfaceElement =\n            (TypeElement) ((DeclaredType) superinterface).asElement();\n        avoidClashesWithNestedClasses(superInterfaceElement);\n      }\n      return this;\n    }\n\n    public Builder addEnumConstant(String name) {\n      return addEnumConstant(name, anonymousClassBuilder(\"\").build());\n    }\n\n    public Builder addEnumConstant(String name, TypeSpec typeSpec) {\n      enumConstants.put(name, typeSpec);\n      return this;\n    }\n\n    public Builder addFields(Iterable<FieldSpec> fieldSpecs) {\n      checkArgument(fieldSpecs != null, \"fieldSpecs == null\");\n      for (FieldSpec fieldSpec : fieldSpecs) {\n        addField(fieldSpec);\n      }\n      return this;\n    }\n\n    public Builder addField(FieldSpec fieldSpec) {\n      fieldSpecs.add(fieldSpec);\n      return this;\n    }\n\n    public Builder addField(TypeName type, String name, Modifier... modifiers) {\n      return addField(FieldSpec.builder(type, name, modifiers).build());\n    }\n\n    public Builder addField(Type type, String name, Modifier... modifiers) {\n      return addField(TypeName.get(type), name, modifiers);\n    }\n\n    public Builder addStaticBlock(CodeBlock block) {\n      staticBlock.beginControlFlow(\"static\").add(block).endControlFlow();\n      return this;\n    }\n\n    public Builder addInitializerBlock(CodeBlock block) {\n      if ((kind != Kind.CLASS && kind != Kind.ENUM)) {\n        throw new UnsupportedOperationException(kind + \" can't have initializer blocks\");\n      }\n      initializerBlock.add(\"{\\n\")\n          .indent()\n          .add(block)\n          .unindent()\n          .add(\"}\\n\");\n      return this;\n    }\n\n    public Builder addMethods(Iterable<MethodSpec> methodSpecs) {\n      checkArgument(methodSpecs != null, \"methodSpecs == null\");\n      for (MethodSpec methodSpec : methodSpecs) {\n        addMethod(methodSpec);\n      }\n      return this;\n    }\n\n    public Builder addMethod(MethodSpec methodSpec) {\n      methodSpecs.add(methodSpec);\n      return this;\n    }\n\n    public Builder addTypes(Iterable<TypeSpec> typeSpecs) {\n      checkArgument(typeSpecs != null, \"typeSpecs == null\");\n      for (TypeSpec typeSpec : typeSpecs) {\n        addType(typeSpec);\n      }\n      return this;\n    }\n\n    public Builder addType(TypeSpec typeSpec) {\n      typeSpecs.add(typeSpec);\n      return this;\n    }\n\n    public Builder addOriginatingElement(Element originatingElement) {\n      originatingElements.add(originatingElement);\n      return this;\n    }\n\n    public Builder alwaysQualify(String... simpleNames) {\n      checkArgument(simpleNames != null, \"simpleNames == null\");\n      for (String name : simpleNames) {\n        checkArgument(\n            name != null,\n            \"null entry in simpleNames array: %s\",\n            Arrays.toString(simpleNames)\n        );\n        alwaysQualifiedNames.add(name);\n      }\n      return this;\n    }\n\n    /**\n     * Call this to always fully qualify any types that would conflict with possibly nested types of\n     * this {@code typeElement}. For example - if the following type was passed in as the\n     * typeElement:\n     *\n     * <pre><code>\n     *   class Foo {\n     *     class NestedTypeA {\n     *\n     *     }\n     *     class NestedTypeB {\n     *\n     *     }\n     *   }\n     * </code></pre>\n     *\n     * <p>\n     * Then this would add {@code \"NestedTypeA\"} and {@code \"NestedTypeB\"} as names that should\n     * always be qualified via {@link #alwaysQualify(String...)}. This way they would avoid\n     * possible import conflicts when this JavaFile is written.\n     *\n     * @param typeElement the {@link TypeElement} with nested types to avoid clashes with.\n     * @return this builder instance.\n     */\n    public Builder avoidClashesWithNestedClasses(TypeElement typeElement) {\n      checkArgument(typeElement != null, \"typeElement == null\");\n      for (TypeElement nestedType : ElementFilter.typesIn(typeElement.getEnclosedElements())) {\n        alwaysQualify(nestedType.getSimpleName().toString());\n      }\n      TypeMirror superclass = typeElement.getSuperclass();\n      if (!(superclass instanceof NoType) && superclass instanceof DeclaredType) {\n        TypeElement superclassElement = (TypeElement) ((DeclaredType) superclass).asElement();\n        avoidClashesWithNestedClasses(superclassElement);\n      }\n      for (TypeMirror superinterface : typeElement.getInterfaces()) {\n        if (superinterface instanceof DeclaredType) {\n          TypeElement superinterfaceElement\n              = (TypeElement) ((DeclaredType) superinterface).asElement();\n          avoidClashesWithNestedClasses(superinterfaceElement);\n        }\n      }\n      return this;\n    }\n\n    /**\n     * Call this to always fully qualify any types that would conflict with possibly nested types of\n     * this {@code typeElement}. For example - if the following type was passed in as the\n     * typeElement:\n     *\n     * <pre><code>\n     *   class Foo {\n     *     class NestedTypeA {\n     *\n     *     }\n     *     class NestedTypeB {\n     *\n     *     }\n     *   }\n     * </code></pre>\n     *\n     * <p>\n     * Then this would add {@code \"NestedTypeA\"} and {@code \"NestedTypeB\"} as names that should\n     * always be qualified via {@link #alwaysQualify(String...)}. This way they would avoid\n     * possible import conflicts when this JavaFile is written.\n     *\n     * @param clazz the {@link Class} with nested types to avoid clashes with.\n     * @return this builder instance.\n     */\n    public Builder avoidClashesWithNestedClasses(Class<?> clazz) {\n      checkArgument(clazz != null, \"clazz == null\");\n      for (Class<?> nestedType : clazz.getDeclaredClasses()) {\n        alwaysQualify(nestedType.getSimpleName());\n      }\n      Class<?> superclass = clazz.getSuperclass();\n      if (superclass != null && !Object.class.equals(superclass)) {\n        avoidClashesWithNestedClasses(superclass);\n      }\n      for (Class<?> superinterface : clazz.getInterfaces()) {\n        avoidClashesWithNestedClasses(superinterface);\n      }\n      return this;\n    }\n\n    public TypeSpec build() {\n      for (AnnotationSpec annotationSpec : annotations) {\n        checkNotNull(annotationSpec, \"annotationSpec == null\");\n      }\n\n      if (!modifiers.isEmpty()) {\n        checkState(anonymousTypeArguments == null, \"forbidden on anonymous types.\");\n        for (Modifier modifier : modifiers) {\n          checkArgument(modifier != null, \"modifiers contain null\");\n        }\n      }\n\n      for (TypeName superinterface : superinterfaces) {\n        checkArgument(superinterface != null, \"superinterfaces contains null\");\n      }\n\n      if (!typeVariables.isEmpty()) {\n        checkState(anonymousTypeArguments == null,\n            \"typevariables are forbidden on anonymous types.\");\n        for (TypeVariableName typeVariableName : typeVariables) {\n          checkArgument(typeVariableName != null, \"typeVariables contain null\");\n        }\n      }\n\n      for (Map.Entry<String, TypeSpec> enumConstant : enumConstants.entrySet()) {\n        checkState(kind == Kind.ENUM, \"%s is not enum\", this.name);\n        checkArgument(enumConstant.getValue().anonymousTypeArguments != null,\n            \"enum constants must have anonymous type arguments\");\n        checkArgument(SourceVersion.isName(name), \"not a valid enum constant: %s\", name);\n      }\n\n      for (FieldSpec fieldSpec : fieldSpecs) {\n        if (kind == Kind.INTERFACE || kind == Kind.ANNOTATION) {\n          requireExactlyOneOf(fieldSpec.modifiers, Modifier.PUBLIC, Modifier.PRIVATE);\n          Set<Modifier> check = EnumSet.of(Modifier.STATIC, Modifier.FINAL);\n          checkState(fieldSpec.modifiers.containsAll(check), \"%s %s.%s requires modifiers %s\",\n              kind, name, fieldSpec.name, check);\n        }\n      }\n\n      for (MethodSpec methodSpec : methodSpecs) {\n        if (kind == Kind.INTERFACE) {\n          requireExactlyOneOf(methodSpec.modifiers, Modifier.PUBLIC, Modifier.PRIVATE);\n          if (methodSpec.modifiers.contains(Modifier.PRIVATE)) {\n            checkState(!methodSpec.hasModifier(Modifier.DEFAULT),\n                \"%s %s.%s cannot be private and default\", kind, name, methodSpec.name);\n            checkState(!methodSpec.hasModifier(Modifier.ABSTRACT),\n                \"%s %s.%s cannot be private and abstract\", kind, name, methodSpec.name);\n          } else {\n            requireExactlyOneOf(methodSpec.modifiers, Modifier.ABSTRACT, Modifier.STATIC,\n                Modifier.DEFAULT);\n          }\n        } else if (kind == Kind.ANNOTATION) {\n          checkState(methodSpec.modifiers.equals(kind.implicitMethodModifiers),\n              \"%s %s.%s requires modifiers %s\",\n              kind, name, methodSpec.name, kind.implicitMethodModifiers);\n        }\n        if (kind != Kind.ANNOTATION) {\n          checkState(methodSpec.defaultValue == null, \"%s %s.%s cannot have a default value\",\n              kind, name, methodSpec.name);\n        }\n        if (kind != Kind.INTERFACE) {\n          checkState(!methodSpec.hasModifier(Modifier.DEFAULT), \"%s %s.%s cannot be default\",\n              kind, name, methodSpec.name);\n        }\n      }\n\n      for (TypeSpec typeSpec : typeSpecs) {\n        checkArgument(typeSpec.modifiers.containsAll(kind.implicitTypeModifiers),\n            \"%s %s.%s requires modifiers %s\", kind, name, typeSpec.name,\n            kind.implicitTypeModifiers);\n      }\n\n      boolean isAbstract = modifiers.contains(Modifier.ABSTRACT) || kind != Kind.CLASS;\n      for (MethodSpec methodSpec : methodSpecs) {\n        checkArgument(isAbstract || !methodSpec.hasModifier(Modifier.ABSTRACT),\n            \"non-abstract type %s cannot declare abstract method %s\", name, methodSpec.name);\n      }\n\n      boolean superclassIsObject = superclass.equals(ClassName.OBJECT);\n      int interestingSupertypeCount = (superclassIsObject ? 0 : 1) + superinterfaces.size();\n      checkArgument(anonymousTypeArguments == null || interestingSupertypeCount <= 1,\n          \"anonymous type has too many supertypes\");\n\n      return new TypeSpec(this);\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/TypeVariableName.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.lang.model.element.TypeParameterElement;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.type.TypeVariable;\n\nimport static com.squareup.javapoet.Util.checkArgument;\nimport static com.squareup.javapoet.Util.checkNotNull;\n\npublic final class TypeVariableName extends TypeName {\n  public final String name;\n  public final List<TypeName> bounds;\n\n  private TypeVariableName(String name, List<TypeName> bounds) {\n    this(name, bounds, new ArrayList<>());\n  }\n\n  private TypeVariableName(String name, List<TypeName> bounds, List<AnnotationSpec> annotations) {\n    super(annotations);\n    this.name = checkNotNull(name, \"name == null\");\n    this.bounds = bounds;\n\n    for (TypeName bound : this.bounds) {\n      checkArgument(!bound.isPrimitive() && bound != VOID, \"invalid bound: %s\", bound);\n    }\n  }\n\n  @Override public TypeVariableName annotated(List<AnnotationSpec> annotations) {\n    return new TypeVariableName(name, bounds, annotations);\n  }\n\n  @Override public TypeName withoutAnnotations() {\n    return new TypeVariableName(name, bounds);\n  }\n\n  public TypeVariableName withBounds(Type... bounds) {\n    return withBounds(TypeName.list(bounds));\n  }\n\n  public TypeVariableName withBounds(TypeName... bounds) {\n    return withBounds(Arrays.asList(bounds));\n  }\n\n  public TypeVariableName withBounds(List<? extends TypeName> bounds) {\n    ArrayList<TypeName> newBounds = new ArrayList<>();\n    newBounds.addAll(this.bounds);\n    newBounds.addAll(bounds);\n    return new TypeVariableName(name, newBounds, annotations);\n  }\n\n  private static TypeVariableName of(String name, List<TypeName> bounds) {\n    // Strip java.lang.Object from bounds if it is present.\n    List<TypeName> boundsNoObject = new ArrayList<>(bounds);\n    boundsNoObject.remove(OBJECT);\n    return new TypeVariableName(name, Collections.unmodifiableList(boundsNoObject));\n  }\n\n  @Override CodeWriter emit(CodeWriter out) throws IOException {\n    emitAnnotations(out);\n    return out.emitAndIndent(name);\n  }\n\n  /** Returns type variable named {@code name} without bounds. */\n  public static TypeVariableName get(String name) {\n    return TypeVariableName.of(name, Collections.emptyList());\n  }\n\n  /** Returns type variable named {@code name} with {@code bounds}. */\n  public static TypeVariableName get(String name, TypeName... bounds) {\n    return TypeVariableName.of(name, Arrays.asList(bounds));\n  }\n\n  /** Returns type variable named {@code name} with {@code bounds}. */\n  public static TypeVariableName get(String name, Type... bounds) {\n    return TypeVariableName.of(name, TypeName.list(bounds));\n  }\n\n  /** Returns type variable equivalent to {@code mirror}. */\n  public static TypeVariableName get(TypeVariable mirror) {\n    return get((TypeParameterElement) mirror.asElement());\n  }\n\n  /**\n   * Make a TypeVariableName for the given TypeMirror. This form is used internally to avoid\n   * infinite recursion in cases like {@code Enum<E extends Enum<E>>}. When we encounter such a\n   * thing, we will make a TypeVariableName without bounds and add that to the {@code typeVariables}\n   * map before looking up the bounds. Then if we encounter this TypeVariable again while\n   * constructing the bounds, we can just return it from the map. And, the code that put the entry\n   * in {@code variables} will make sure that the bounds are filled in before returning.\n   */\n  static TypeVariableName get(\n      TypeVariable mirror, Map<TypeParameterElement, TypeVariableName> typeVariables) {\n    TypeParameterElement element = (TypeParameterElement) mirror.asElement();\n    TypeVariableName typeVariableName = typeVariables.get(element);\n    if (typeVariableName == null) {\n      // Since the bounds field is public, we need to make it an unmodifiableList. But we control\n      // the List that that wraps, which means we can change it before returning.\n      List<TypeName> bounds = new ArrayList<>();\n      List<TypeName> visibleBounds = Collections.unmodifiableList(bounds);\n      typeVariableName = new TypeVariableName(element.getSimpleName().toString(), visibleBounds);\n      typeVariables.put(element, typeVariableName);\n      for (TypeMirror typeMirror : element.getBounds()) {\n        bounds.add(TypeName.get(typeMirror, typeVariables));\n      }\n      bounds.remove(OBJECT);\n    }\n    return typeVariableName;\n  }\n\n  /** Returns type variable equivalent to {@code element}. */\n  public static TypeVariableName get(TypeParameterElement element) {\n    String name = element.getSimpleName().toString();\n    List<? extends TypeMirror> boundsMirrors = element.getBounds();\n\n    List<TypeName> boundsTypeNames = new ArrayList<>();\n    for (TypeMirror typeMirror : boundsMirrors) {\n      boundsTypeNames.add(TypeName.get(typeMirror));\n    }\n\n    return TypeVariableName.of(name, boundsTypeNames);\n  }\n\n  /** Returns type variable equivalent to {@code type}. */\n  public static TypeVariableName get(java.lang.reflect.TypeVariable<?> type) {\n    return get(type, new LinkedHashMap<>());\n  }\n\n  /** @see #get(java.lang.reflect.TypeVariable, Map) */\n  static TypeVariableName get(java.lang.reflect.TypeVariable<?> type,\n      Map<Type, TypeVariableName> map) {\n    TypeVariableName result = map.get(type);\n    if (result == null) {\n      List<TypeName> bounds = new ArrayList<>();\n      List<TypeName> visibleBounds = Collections.unmodifiableList(bounds);\n      result = new TypeVariableName(type.getName(), visibleBounds);\n      map.put(type, result);\n      for (Type bound : type.getBounds()) {\n        bounds.add(TypeName.get(bound, map));\n      }\n      bounds.remove(OBJECT);\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/Util.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.lang.model.element.Modifier;\n\nimport static java.lang.Character.isISOControl;\n\n/**\n * Like Guava, but worse and standalone. This makes it easier to mix JavaPoet with libraries that\n * bring their own version of Guava.\n */\nfinal class Util {\n  private Util() {\n  }\n\n  static <K, V> Map<K, List<V>> immutableMultimap(Map<K, List<V>> multimap) {\n    LinkedHashMap<K, List<V>> result = new LinkedHashMap<>();\n    for (Map.Entry<K, List<V>> entry : multimap.entrySet()) {\n      if (entry.getValue().isEmpty()) continue;\n      result.put(entry.getKey(), immutableList(entry.getValue()));\n    }\n    return Collections.unmodifiableMap(result);\n  }\n\n  static <K, V> Map<K, V> immutableMap(Map<K, V> map) {\n    return Collections.unmodifiableMap(new LinkedHashMap<>(map));\n  }\n\n  static void checkArgument(boolean condition, String format, Object... args) {\n    if (!condition) throw new IllegalArgumentException(String.format(format, args));\n  }\n\n  static <T> T checkNotNull(T reference, String format, Object... args) {\n    if (reference == null) throw new NullPointerException(String.format(format, args));\n    return reference;\n  }\n\n  static void checkState(boolean condition, String format, Object... args) {\n    if (!condition) throw new IllegalStateException(String.format(format, args));\n  }\n\n  static <T> List<T> immutableList(Collection<T> collection) {\n    return Collections.unmodifiableList(new ArrayList<>(collection));\n  }\n\n  static <T> Set<T> immutableSet(Collection<T> set) {\n    return Collections.unmodifiableSet(new LinkedHashSet<>(set));\n  }\n\n  static <T> Set<T> union(Set<T> a, Set<T> b) {\n    Set<T> result = new LinkedHashSet<>();\n    result.addAll(a);\n    result.addAll(b);\n    return result;\n  }\n\n  static void requireExactlyOneOf(Set<Modifier> modifiers, Modifier... mutuallyExclusive) {\n    int count = 0;\n    for (Modifier modifier : mutuallyExclusive) {\n      if (modifiers.contains(modifier)) count++;\n    }\n    checkArgument(count == 1, \"modifiers %s must contain one of %s\",\n        modifiers, Arrays.toString(mutuallyExclusive));\n  }\n\n  static String characterLiteralWithoutSingleQuotes(char c) {\n    // see https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6\n    switch (c) {\n      case '\\b': return \"\\\\b\"; /* \\u0008: backspace (BS) */\n      case '\\t': return \"\\\\t\"; /* \\u0009: horizontal tab (HT) */\n      case '\\n': return \"\\\\n\"; /* \\u000a: linefeed (LF) */\n      case '\\f': return \"\\\\f\"; /* \\u000c: form feed (FF) */\n      case '\\r': return \"\\\\r\"; /* \\u000d: carriage return (CR) */\n      case '\\\"': return \"\\\"\";  /* \\u0022: double quote (\") */\n      case '\\'': return \"\\\\'\"; /* \\u0027: single quote (') */\n      case '\\\\': return \"\\\\\\\\\";  /* \\u005c: backslash (\\) */\n      default:\n        return isISOControl(c) ? String.format(\"\\\\u%04x\", (int) c) : Character.toString(c);\n    }\n  }\n\n  /** Returns the string literal representing {@code value}, including wrapping double quotes. */\n  static String stringLiteralWithDoubleQuotes(String value, String indent) {\n    StringBuilder result = new StringBuilder(value.length() + 2);\n    result.append('\"');\n    for (int i = 0; i < value.length(); i++) {\n      char c = value.charAt(i);\n      // trivial case: single quote must not be escaped\n      if (c == '\\'') {\n        result.append(\"'\");\n        continue;\n      }\n      // trivial case: double quotes must be escaped\n      if (c == '\\\"') {\n        result.append(\"\\\\\\\"\");\n        continue;\n      }\n      // default case: just let character literal do its work\n      result.append(characterLiteralWithoutSingleQuotes(c));\n      // need to append indent after linefeed?\n      if (c == '\\n' && i + 1 < value.length()) {\n        result.append(\"\\\"\\n\").append(indent).append(indent).append(\"+ \\\"\");\n      }\n    }\n    result.append('\"');\n    return result.toString();\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/squareup/javapoet/WildcardTypeName.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.lang.reflect.WildcardType;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport javax.lang.model.element.TypeParameterElement;\nimport javax.lang.model.type.TypeMirror;\n\nimport static com.squareup.javapoet.Util.checkArgument;\n\npublic final class WildcardTypeName extends TypeName {\n  public final List<TypeName> upperBounds;\n  public final List<TypeName> lowerBounds;\n\n  private WildcardTypeName(List<TypeName> upperBounds, List<TypeName> lowerBounds) {\n    this(upperBounds, lowerBounds, new ArrayList<>());\n  }\n\n  private WildcardTypeName(List<TypeName> upperBounds, List<TypeName> lowerBounds,\n      List<AnnotationSpec> annotations) {\n    super(annotations);\n    this.upperBounds = Util.immutableList(upperBounds);\n    this.lowerBounds = Util.immutableList(lowerBounds);\n\n    checkArgument(this.upperBounds.size() == 1, \"unexpected extends bounds: %s\", upperBounds);\n    for (TypeName upperBound : this.upperBounds) {\n      checkArgument(!upperBound.isPrimitive() && upperBound != VOID,\n          \"invalid upper bound: %s\", upperBound);\n    }\n    for (TypeName lowerBound : this.lowerBounds) {\n      checkArgument(!lowerBound.isPrimitive() && lowerBound != VOID,\n          \"invalid lower bound: %s\", lowerBound);\n    }\n  }\n\n  @Override public WildcardTypeName annotated(List<AnnotationSpec> annotations) {\n    return new WildcardTypeName(upperBounds, lowerBounds, concatAnnotations(annotations));\n  }\n\n  @Override public TypeName withoutAnnotations() {\n    return new WildcardTypeName(upperBounds, lowerBounds);\n  }\n\n  @Override CodeWriter emit(CodeWriter out) throws IOException {\n    if (lowerBounds.size() == 1) {\n      return out.emit(\"? super $T\", lowerBounds.get(0));\n    }\n    return upperBounds.get(0).equals(TypeName.OBJECT)\n        ? out.emit(\"?\")\n        : out.emit(\"? extends $T\", upperBounds.get(0));\n  }\n\n  /**\n   * Returns a type that represents an unknown type that extends {@code bound}. For example, if\n   * {@code bound} is {@code CharSequence.class}, this returns {@code ? extends CharSequence}. If\n   * {@code bound} is {@code Object.class}, this returns {@code ?}, which is shorthand for {@code\n   * ? extends Object}.\n   */\n  public static WildcardTypeName subtypeOf(TypeName upperBound) {\n    return new WildcardTypeName(Collections.singletonList(upperBound), Collections.emptyList());\n  }\n\n  public static WildcardTypeName subtypeOf(Type upperBound) {\n    return subtypeOf(TypeName.get(upperBound));\n  }\n\n  /**\n   * Returns a type that represents an unknown supertype of {@code bound}. For example, if {@code\n   * bound} is {@code String.class}, this returns {@code ? super String}.\n   */\n  public static WildcardTypeName supertypeOf(TypeName lowerBound) {\n    return new WildcardTypeName(Collections.singletonList(OBJECT),\n        Collections.singletonList(lowerBound));\n  }\n\n  public static WildcardTypeName supertypeOf(Type lowerBound) {\n    return supertypeOf(TypeName.get(lowerBound));\n  }\n\n  public static TypeName get(javax.lang.model.type.WildcardType mirror) {\n    return get(mirror, new LinkedHashMap<>());\n  }\n\n  static TypeName get(\n      javax.lang.model.type.WildcardType mirror,\n      Map<TypeParameterElement, TypeVariableName> typeVariables) {\n    TypeMirror extendsBound = mirror.getExtendsBound();\n    if (extendsBound == null) {\n      TypeMirror superBound = mirror.getSuperBound();\n      if (superBound == null) {\n        return subtypeOf(Object.class);\n      } else {\n        return supertypeOf(TypeName.get(superBound, typeVariables));\n      }\n    } else {\n      return subtypeOf(TypeName.get(extendsBound, typeVariables));\n    }\n  }\n\n  public static TypeName get(WildcardType wildcardName) {\n    return get(wildcardName, new LinkedHashMap<>());\n  }\n\n  static TypeName get(WildcardType wildcardName, Map<Type, TypeVariableName> map) {\n    return new WildcardTypeName(\n        list(wildcardName.getUpperBounds(), map),\n        list(wildcardName.getLowerBounds(), map));\n  }\n}\n"
  },
  {
    "path": "src/test/java/ClassNameNoPackageTest.java",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport static com.google.common.truth.Truth.assertThat;\n\nimport com.squareup.javapoet.ClassName;\nimport org.junit.Test;\n\n/**\n * Since it is impossible to import classes from the default package into other\n * modules, this test must live in this package.\n */\npublic final class ClassNameNoPackageTest {\n  @Test public void shouldSupportClassInDefaultPackage() {\n    ClassName className = ClassName.get(ClassNameNoPackageTest.class);\n    assertThat(className.packageName()).isEqualTo(\"\");\n    assertThat(className.simpleName()).isEqualTo(\"ClassNameNoPackageTest\");\n    assertThat(className.toString()).isEqualTo(\"ClassNameNoPackageTest\");\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/AbstractTypesTest.java",
    "content": "/*\n * Copyright (C) 2014 Google, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static com.google.testing.compile.CompilationSubject.assertThat;\nimport static com.google.testing.compile.Compiler.javac;\nimport static javax.lang.model.util.ElementFilter.fieldsIn;\nimport static org.junit.Assert.*;\n\nimport com.google.testing.compile.Compilation;\nimport com.google.testing.compile.JavaFileObjects;\nimport java.io.Serializable;\nimport java.lang.annotation.Annotation;\nimport java.nio.charset.Charset;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.annotation.processing.AbstractProcessor;\nimport javax.annotation.processing.RoundEnvironment;\nimport javax.lang.model.element.AnnotationMirror;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.element.TypeParameterElement;\nimport javax.lang.model.element.VariableElement;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.type.ErrorType;\nimport javax.lang.model.type.TypeKind;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.type.TypeVisitor;\nimport javax.lang.model.type.WildcardType;\nimport javax.lang.model.util.Elements;\nimport javax.lang.model.util.Types;\nimport javax.tools.JavaFileObject;\n\nimport org.junit.Test;\n\npublic abstract class AbstractTypesTest {\n  protected abstract Elements getElements();\n  protected abstract Types getTypes();\n\n  private TypeElement getElement(Class<?> clazz) {\n    return getElements().getTypeElement(clazz.getCanonicalName());\n  }\n\n  private TypeMirror getMirror(Class<?> clazz) {\n    return getElement(clazz).asType();\n  }\n\n  @Test public void getBasicTypeMirror() {\n    assertThat(TypeName.get(getMirror(Object.class)))\n        .isEqualTo(ClassName.get(Object.class));\n    assertThat(TypeName.get(getMirror(Charset.class)))\n        .isEqualTo(ClassName.get(Charset.class));\n    assertThat(TypeName.get(getMirror(AbstractTypesTest.class)))\n        .isEqualTo(ClassName.get(AbstractTypesTest.class));\n  }\n\n  @Test public void getParameterizedTypeMirror() {\n    DeclaredType setType =\n        getTypes().getDeclaredType(getElement(Set.class), getMirror(Object.class));\n    assertThat(TypeName.get(setType))\n        .isEqualTo(ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.OBJECT));\n  }\n\n  @Test public void errorTypes() {\n    JavaFileObject hasErrorTypes =\n        JavaFileObjects.forSourceLines(\n            \"com.squareup.tacos.ErrorTypes\",\n            \"package com.squareup.tacos;\",\n            \"\",\n            \"@SuppressWarnings(\\\"hook-into-compiler\\\")\",\n            \"class ErrorTypes {\",\n            \"  Tacos tacos;\",\n            \"  Ingredients.Guacamole guacamole;\",\n            \"}\");\n    Compilation compilation = javac().withProcessors(new AbstractProcessor() {\n      @Override\n      public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {\n        TypeElement classFile =\n            processingEnv.getElementUtils().getTypeElement(\"com.squareup.tacos.ErrorTypes\");\n        List<VariableElement> fields = fieldsIn(classFile.getEnclosedElements());\n        ErrorType topLevel = (ErrorType) fields.get(0).asType();\n        ErrorType member = (ErrorType) fields.get(1).asType();\n\n        assertThat(TypeName.get(topLevel)).isEqualTo(ClassName.get(\"\", \"Tacos\"));\n        assertThat(TypeName.get(member)).isEqualTo(ClassName.get(\"Ingredients\", \"Guacamole\"));\n        return false;\n      }\n\n      @Override\n      public Set<String> getSupportedAnnotationTypes() {\n        return Collections.singleton(\"*\");\n      }\n    }).compile(hasErrorTypes);\n\n    assertThat(compilation).failed();\n  }\n\n  static class Parameterized<\n      Simple,\n      ExtendsClass extends Number,\n      ExtendsInterface extends Runnable,\n      ExtendsTypeVariable extends Simple,\n      Intersection extends Number & Runnable,\n      IntersectionOfInterfaces extends Runnable & Serializable> {}\n\n  @Test public void getTypeVariableTypeMirror() {\n    List<? extends TypeParameterElement> typeVariables =\n        getElement(Parameterized.class).getTypeParameters();\n\n    // Members of converted types use ClassName and not Class<?>.\n    ClassName number = ClassName.get(Number.class);\n    ClassName runnable = ClassName.get(Runnable.class);\n    ClassName serializable = ClassName.get(Serializable.class);\n\n    assertThat(TypeName.get(typeVariables.get(0).asType()))\n        .isEqualTo(TypeVariableName.get(\"Simple\"));\n    assertThat(TypeName.get(typeVariables.get(1).asType()))\n        .isEqualTo(TypeVariableName.get(\"ExtendsClass\", number));\n    assertThat(TypeName.get(typeVariables.get(2).asType()))\n        .isEqualTo(TypeVariableName.get(\"ExtendsInterface\", runnable));\n    assertThat(TypeName.get(typeVariables.get(3).asType()))\n        .isEqualTo(TypeVariableName.get(\"ExtendsTypeVariable\", TypeVariableName.get(\"Simple\")));\n    assertThat(TypeName.get(typeVariables.get(4).asType()))\n        .isEqualTo(TypeVariableName.get(\"Intersection\", number, runnable));\n    assertThat(TypeName.get(typeVariables.get(5).asType()))\n        .isEqualTo(TypeVariableName.get(\"IntersectionOfInterfaces\", runnable, serializable));\n    assertThat(((TypeVariableName) TypeName.get(typeVariables.get(4).asType())).bounds)\n        .containsExactly(number, runnable);\n  }\n\n  static class Recursive<T extends Map<List<T>, Set<T[]>>> {}\n\n  @Test\n  public void getTypeVariableTypeMirrorRecursive() {\n    TypeMirror typeMirror = getElement(Recursive.class).asType();\n    ParameterizedTypeName typeName = (ParameterizedTypeName) TypeName.get(typeMirror);\n    String className = Recursive.class.getCanonicalName();\n    assertThat(typeName.toString()).isEqualTo(className + \"<T>\");\n\n    TypeVariableName typeVariableName = (TypeVariableName) typeName.typeArguments.get(0);\n\n    try {\n      typeVariableName.bounds.set(0, null);\n      fail(\"Expected UnsupportedOperationException\");\n    } catch (UnsupportedOperationException expected) {\n    }\n\n    assertThat(typeVariableName.toString()).isEqualTo(\"T\");\n    assertThat(typeVariableName.bounds.toString())\n        .isEqualTo(\"[java.util.Map<java.util.List<T>, java.util.Set<T[]>>]\");\n  }\n\n  @Test public void getPrimitiveTypeMirror() {\n    assertThat(TypeName.get(getTypes().getPrimitiveType(TypeKind.BOOLEAN)))\n        .isEqualTo(TypeName.BOOLEAN);\n    assertThat(TypeName.get(getTypes().getPrimitiveType(TypeKind.BYTE)))\n        .isEqualTo(TypeName.BYTE);\n    assertThat(TypeName.get(getTypes().getPrimitiveType(TypeKind.SHORT)))\n        .isEqualTo(TypeName.SHORT);\n    assertThat(TypeName.get(getTypes().getPrimitiveType(TypeKind.INT)))\n        .isEqualTo(TypeName.INT);\n    assertThat(TypeName.get(getTypes().getPrimitiveType(TypeKind.LONG)))\n        .isEqualTo(TypeName.LONG);\n    assertThat(TypeName.get(getTypes().getPrimitiveType(TypeKind.CHAR)))\n        .isEqualTo(TypeName.CHAR);\n    assertThat(TypeName.get(getTypes().getPrimitiveType(TypeKind.FLOAT)))\n        .isEqualTo(TypeName.FLOAT);\n    assertThat(TypeName.get(getTypes().getPrimitiveType(TypeKind.DOUBLE)))\n        .isEqualTo(TypeName.DOUBLE);\n  }\n\n  @Test public void getArrayTypeMirror() {\n    assertThat(TypeName.get(getTypes().getArrayType(getMirror(Object.class))))\n        .isEqualTo(ArrayTypeName.of(ClassName.OBJECT));\n  }\n\n  @Test public void getVoidTypeMirror() {\n    assertThat(TypeName.get(getTypes().getNoType(TypeKind.VOID)))\n        .isEqualTo(TypeName.VOID);\n  }\n\n  @Test public void getNullTypeMirror() {\n    try {\n      TypeName.get(getTypes().getNullType());\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void parameterizedType() throws Exception {\n    ParameterizedTypeName type = ParameterizedTypeName.get(Map.class, String.class, Long.class);\n    assertThat(type.toString()).isEqualTo(\"java.util.Map<java.lang.String, java.lang.Long>\");\n  }\n\n  @Test public void arrayType() throws Exception {\n    ArrayTypeName type = ArrayTypeName.of(String.class);\n    assertThat(type.toString()).isEqualTo(\"java.lang.String[]\");\n  }\n\n  @Test public void wildcardExtendsType() throws Exception {\n    WildcardTypeName type = WildcardTypeName.subtypeOf(CharSequence.class);\n    assertThat(type.toString()).isEqualTo(\"? extends java.lang.CharSequence\");\n  }\n\n  @Test public void wildcardExtendsObject() throws Exception {\n    WildcardTypeName type = WildcardTypeName.subtypeOf(Object.class);\n    assertThat(type.toString()).isEqualTo(\"?\");\n  }\n\n  @Test public void wildcardSuperType() throws Exception {\n    WildcardTypeName type = WildcardTypeName.supertypeOf(String.class);\n    assertThat(type.toString()).isEqualTo(\"? super java.lang.String\");\n  }\n\n  @Test public void wildcardMirrorNoBounds() throws Exception {\n    WildcardType wildcard = getTypes().getWildcardType(null, null);\n    TypeName type = TypeName.get(wildcard);\n    assertThat(type.toString()).isEqualTo(\"?\");\n  }\n\n  @Test public void wildcardMirrorExtendsType() throws Exception {\n    Types types = getTypes();\n    Elements elements = getElements();\n    TypeMirror charSequence = elements.getTypeElement(CharSequence.class.getName()).asType();\n    WildcardType wildcard = types.getWildcardType(charSequence, null);\n    TypeName type = TypeName.get(wildcard);\n    assertThat(type.toString()).isEqualTo(\"? extends java.lang.CharSequence\");\n  }\n\n  @Test public void wildcardMirrorSuperType() throws Exception {\n    Types types = getTypes();\n    Elements elements = getElements();\n    TypeMirror string = elements.getTypeElement(String.class.getName()).asType();\n    WildcardType wildcard = types.getWildcardType(null, string);\n    TypeName type = TypeName.get(wildcard);\n    assertThat(type.toString()).isEqualTo(\"? super java.lang.String\");\n  }\n\n  @Test public void typeVariable() throws Exception {\n    TypeVariableName type = TypeVariableName.get(\"T\", CharSequence.class);\n    assertThat(type.toString()).isEqualTo(\"T\"); // (Bounds are only emitted in declaration.)\n  }\n\n  @Test public void box() throws Exception {\n    assertThat(TypeName.INT.box()).isEqualTo(ClassName.get(Integer.class));\n    assertThat(TypeName.VOID.box()).isEqualTo(ClassName.get(Void.class));\n    assertThat(ClassName.get(Integer.class).box()).isEqualTo(ClassName.get(Integer.class));\n    assertThat(ClassName.get(Void.class).box()).isEqualTo(ClassName.get(Void.class));\n    assertThat(TypeName.OBJECT.box()).isEqualTo(TypeName.OBJECT);\n    assertThat(ClassName.get(String.class).box()).isEqualTo(ClassName.get(String.class));\n  }\n\n  @Test public void unbox() throws Exception {\n    assertThat(TypeName.INT).isEqualTo(TypeName.INT.unbox());\n    assertThat(TypeName.VOID).isEqualTo(TypeName.VOID.unbox());\n    assertThat(ClassName.get(Integer.class).unbox()).isEqualTo(TypeName.INT.unbox());\n    assertThat(ClassName.get(Void.class).unbox()).isEqualTo(TypeName.VOID.unbox());\n    try {\n      TypeName.OBJECT.unbox();\n      fail();\n    } catch (UnsupportedOperationException expected) {\n    }\n    try {\n      ClassName.get(String.class).unbox();\n      fail();\n    } catch (UnsupportedOperationException expected) {\n    }\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/AnnotatedTypeNameTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Target;\nimport java.util.List;\nimport java.util.Map;\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertTrue;\n\npublic class AnnotatedTypeNameTest {\n\n  private final static String NN = NeverNull.class.getCanonicalName();\n  private final AnnotationSpec NEVER_NULL = AnnotationSpec.builder(NeverNull.class).build();\n  private final static String TUA = TypeUseAnnotation.class.getCanonicalName();\n  private final AnnotationSpec TYPE_USE_ANNOTATION =\n      AnnotationSpec.builder(TypeUseAnnotation.class).build();\n\n  @Target(ElementType.TYPE_USE)\n  public @interface NeverNull {}\n\n  @Target(ElementType.TYPE_USE)\n  public @interface TypeUseAnnotation {}\n\n\n  @Test(expected=NullPointerException.class) public void nullAnnotationArray() {\n    TypeName.BOOLEAN.annotated((AnnotationSpec[]) null);\n  }\n\n  @Test(expected=NullPointerException.class) public void nullAnnotationList() {\n    TypeName.DOUBLE.annotated((List<AnnotationSpec>) null);\n  }\n\n  @Test public void annotated() {\n    TypeName simpleString = TypeName.get(String.class);\n    assertFalse(simpleString.isAnnotated());\n    assertEquals(simpleString, TypeName.get(String.class));\n\n    TypeName annotated = simpleString.annotated(NEVER_NULL);\n    assertTrue(annotated.isAnnotated());\n    assertEquals(annotated, annotated.annotated());\n  }\n\n  @Test public void annotatedType() {\n    TypeName type = TypeName.get(String.class);\n    TypeName actual = type.annotated(TYPE_USE_ANNOTATION);\n    assertThat(actual.toString()).isEqualTo(\"java.lang. @\" + TUA + \" String\");\n  }\n\n  @Test public void annotatedTwice() {\n    TypeName type = TypeName.get(String.class);\n    TypeName actual =\n        type.annotated(NEVER_NULL)\n            .annotated(TYPE_USE_ANNOTATION);\n    assertThat(actual.toString())\n        .isEqualTo(\"java.lang. @\" + NN + \" @\" + TUA + \" String\");\n  }\n\n  @Test public void annotatedParameterizedType() {\n    TypeName type = ParameterizedTypeName.get(List.class, String.class);\n    TypeName actual = type.annotated(TYPE_USE_ANNOTATION);\n    assertThat(actual.toString()).isEqualTo(\"java.util. @\" + TUA + \" List<java.lang.String>\");\n  }\n\n  @Test public void annotatedArgumentOfParameterizedType() {\n    TypeName type = TypeName.get(String.class).annotated(TYPE_USE_ANNOTATION);\n    TypeName actual = ParameterizedTypeName.get(ClassName.get(List.class), type);\n    assertThat(actual.toString()).isEqualTo(\"java.util.List<java.lang. @\" + TUA + \" String>\");\n  }\n\n  @Test public void annotatedWildcardTypeNameWithSuper() {\n    TypeName type = TypeName.get(String.class).annotated(TYPE_USE_ANNOTATION);\n    TypeName actual = WildcardTypeName.supertypeOf(type);\n    assertThat(actual.toString()).isEqualTo(\"? super java.lang. @\" + TUA + \" String\");\n  }\n\n  @Test public void annotatedWildcardTypeNameWithExtends() {\n    TypeName type = TypeName.get(String.class).annotated(TYPE_USE_ANNOTATION);\n    TypeName actual = WildcardTypeName.subtypeOf(type);\n    assertThat(actual.toString()).isEqualTo(\"? extends java.lang. @\" + TUA + \" String\");\n  }\n\n  @Test public void annotatedEquivalence() {\n    annotatedEquivalence(TypeName.VOID);\n    annotatedEquivalence(ArrayTypeName.get(Object[].class));\n    annotatedEquivalence(ClassName.get(Object.class));\n    annotatedEquivalence(ParameterizedTypeName.get(List.class, Object.class));\n    annotatedEquivalence(TypeVariableName.get(Object.class));\n    annotatedEquivalence(WildcardTypeName.get(Object.class));\n  }\n\n  private void annotatedEquivalence(TypeName type) {\n    assertFalse(type.isAnnotated());\n    assertEquals(type, type);\n    assertEquals(type.annotated(TYPE_USE_ANNOTATION), type.annotated(TYPE_USE_ANNOTATION));\n    assertNotEquals(type, type.annotated(TYPE_USE_ANNOTATION));\n    assertEquals(type.hashCode(), type.hashCode());\n    assertEquals(type.annotated(TYPE_USE_ANNOTATION).hashCode(),\n        type.annotated(TYPE_USE_ANNOTATION).hashCode());\n    assertNotEquals(type.hashCode(), type.annotated(TYPE_USE_ANNOTATION).hashCode());\n  }\n\n  // https://github.com/square/javapoet/issues/431\n  @Test public void annotatedNestedType() {\n    TypeName type = TypeName.get(Map.Entry.class).annotated(TYPE_USE_ANNOTATION);\n    assertThat(type.toString()).isEqualTo(\"java.util.Map. @\" + TUA + \" Entry\");\n  }\n\n  @Test public void annotatedEnclosingAndNestedType() {\n    TypeName type = ((ClassName) TypeName.get(Map.class).annotated(TYPE_USE_ANNOTATION))\n        .nestedClass(\"Entry\").annotated(TYPE_USE_ANNOTATION);\n    assertThat(type.toString()).isEqualTo(\"java.util. @\" + TUA + \" Map. @\" + TUA + \" Entry\");\n  }\n\n  // https://github.com/square/javapoet/issues/431\n  @Test public void annotatedNestedParameterizedType() {\n    TypeName type = ParameterizedTypeName.get(Map.Entry.class, Byte.class, Byte.class)\n        .annotated(TYPE_USE_ANNOTATION);\n    assertThat(type.toString())\n        .isEqualTo(\"java.util.Map. @\" + TUA + \" Entry<java.lang.Byte, java.lang.Byte>\");\n  }\n\n  @Test public void withoutAnnotationsOnAnnotatedEnclosingAndNestedType() {\n    TypeName type = ((ClassName) TypeName.get(Map.class).annotated(TYPE_USE_ANNOTATION))\n        .nestedClass(\"Entry\").annotated(TYPE_USE_ANNOTATION);\n    assertThat(type.isAnnotated()).isTrue();\n    assertThat(type.withoutAnnotations()).isEqualTo(TypeName.get(Map.Entry.class));\n  }\n\n  @Test public void withoutAnnotationsOnAnnotatedEnclosingType() {\n    TypeName type = ((ClassName) TypeName.get(Map.class).annotated(TYPE_USE_ANNOTATION))\n        .nestedClass(\"Entry\");\n    assertThat(type.isAnnotated()).isTrue();\n    assertThat(type.withoutAnnotations()).isEqualTo(TypeName.get(Map.Entry.class));\n  }\n\n  @Test public void withoutAnnotationsOnAnnotatedNestedType() {\n    TypeName type = ((ClassName) TypeName.get(Map.class))\n        .nestedClass(\"Entry\").annotated(TYPE_USE_ANNOTATION);\n    assertThat(type.isAnnotated()).isTrue();\n    assertThat(type.withoutAnnotations()).isEqualTo(TypeName.get(Map.Entry.class));\n  }\n\n  // https://github.com/square/javapoet/issues/614\n   @Test public void annotatedArrayType() {\n    TypeName type = ArrayTypeName.of(ClassName.get(Object.class)).annotated(TYPE_USE_ANNOTATION);\n    assertThat(type.toString()).isEqualTo(\"java.lang.Object @\" + TUA + \" []\");\n  }\n\n  @Test public void annotatedArrayElementType() {\n    TypeName type = ArrayTypeName.of(ClassName.get(Object.class).annotated(TYPE_USE_ANNOTATION));\n    assertThat(type.toString()).isEqualTo(\"java.lang. @\" + TUA + \" Object[]\");\n  }\n\n  // https://github.com/square/javapoet/issues/614\n  @Test public void annotatedOuterMultidimensionalArrayType() {\n    TypeName type = ArrayTypeName.of(ArrayTypeName.of(ClassName.get(Object.class)))\n        .annotated(TYPE_USE_ANNOTATION);\n    assertThat(type.toString()).isEqualTo(\"java.lang.Object @\" + TUA + \" [][]\");\n  }\n\n  // https://github.com/square/javapoet/issues/614\n  @Test public void annotatedInnerMultidimensionalArrayType() {\n    TypeName type = ArrayTypeName.of(ArrayTypeName.of(ClassName.get(Object.class))\n        .annotated(TYPE_USE_ANNOTATION));\n    assertThat(type.toString()).isEqualTo(\"java.lang.Object[] @\" + TUA + \" []\");\n  }\n\n  // https://github.com/square/javapoet/issues/614\n  @Test public void annotatedArrayTypeVarargsParameter() {\n    TypeName type = ArrayTypeName.of(ArrayTypeName.of(ClassName.get(Object.class)))\n        .annotated(TYPE_USE_ANNOTATION);\n    MethodSpec varargsMethod = MethodSpec.methodBuilder(\"m\")\n        .addParameter(\n            ParameterSpec.builder(type, \"p\")\n                .build())\n        .varargs()\n        .build();\n    assertThat(varargsMethod.toString()).isEqualTo(\"\"\n        + \"void m(java.lang.Object @\" + TUA + \" []... p) {\\n\"\n        + \"}\\n\");\n  }\n\n  // https://github.com/square/javapoet/issues/614\n  @Test public void annotatedArrayTypeInVarargsParameter() {\n    TypeName type = ArrayTypeName.of(ArrayTypeName.of(ClassName.get(Object.class))\n        .annotated(TYPE_USE_ANNOTATION));\n    MethodSpec varargsMethod = MethodSpec.methodBuilder(\"m\")\n        .addParameter(\n            ParameterSpec.builder(type, \"p\")\n                .build())\n        .varargs()\n        .build();\n    assertThat(varargsMethod.toString()).isEqualTo(\"\"\n        + \"void m(java.lang.Object[] @\" + TUA + \" ... p) {\\n\"\n        + \"}\\n\");\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/AnnotationSpecTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport com.google.testing.compile.CompilationRule;\nimport java.lang.annotation.Annotation;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.util.Arrays;\n\nimport javax.lang.model.element.TypeElement;\nimport org.junit.Rule;\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.junit.Assert.fail;\n\npublic final class AnnotationSpecTest {\n\n  @Retention(RetentionPolicy.RUNTIME)\n  public @interface AnnotationA {\n  }\n\n  @Inherited\n  @Retention(RetentionPolicy.RUNTIME)\n  public @interface AnnotationB {\n  }\n\n  @Retention(RetentionPolicy.RUNTIME)\n  public @interface AnnotationC {\n    String value();\n  }\n\n  public enum Breakfast {\n    WAFFLES, PANCAKES;\n    public String toString() { return name() + \" with cherries!\"; };\n  }\n\n  @Retention(RetentionPolicy.RUNTIME)\n  public @interface HasDefaultsAnnotation {\n\n    byte a() default 5;\n\n    short b() default 6;\n\n    int c() default 7;\n\n    long d() default 12345678910L;\n\n    float e() default 9.0f;\n\n    double f() default 10.0;\n\n    char[] g() default {0, 0xCAFE, 'z', '€', 'ℕ', '\"', '\\'', '\\t', '\\n'};\n\n    boolean h() default true;\n\n    Breakfast i() default Breakfast.WAFFLES;\n\n    AnnotationA j() default @AnnotationA();\n\n    String k() default \"maple\";\n\n    Class<? extends Annotation> l() default AnnotationB.class;\n\n    int[] m() default {1, 2, 3};\n\n    Breakfast[] n() default {Breakfast.WAFFLES, Breakfast.PANCAKES};\n\n    Breakfast o();\n\n    int p();\n\n    AnnotationC q() default @AnnotationC(\"foo\");\n\n    Class<? extends Number>[] r() default {Byte.class, Short.class, Integer.class, Long.class};\n\n  }\n\n  @HasDefaultsAnnotation(\n      o = Breakfast.PANCAKES,\n      p = 1701,\n      f = 11.1,\n      m = {9, 8, 1},\n      l = Override.class,\n      j = @AnnotationA,\n      q = @AnnotationC(\"bar\"),\n      r = {Float.class, Double.class})\n  public class IsAnnotated {\n    // empty\n  }\n\n  @Rule public final CompilationRule compilation = new CompilationRule();\n\n  @Test public void equalsAndHashCode() {\n    AnnotationSpec a = AnnotationSpec.builder(AnnotationC.class).build();\n    AnnotationSpec b = AnnotationSpec.builder(AnnotationC.class).build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    a = AnnotationSpec.builder(AnnotationC.class).addMember(\"value\", \"$S\", \"123\").build();\n    b = AnnotationSpec.builder(AnnotationC.class).addMember(\"value\", \"$S\", \"123\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n  }\n\n  @Test public void defaultAnnotation() {\n    String name = IsAnnotated.class.getCanonicalName();\n    TypeElement element = compilation.getElements().getTypeElement(name);\n    AnnotationSpec annotation = AnnotationSpec.get(element.getAnnotationMirrors().get(0));\n\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addAnnotation(annotation)\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.squareup.javapoet.AnnotationSpecTest;\\n\"\n        + \"import java.lang.Double;\\n\"\n        + \"import java.lang.Float;\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"\\n\"\n        + \"@AnnotationSpecTest.HasDefaultsAnnotation(\\n\"\n        + \"    o = AnnotationSpecTest.Breakfast.PANCAKES,\\n\"\n        + \"    p = 1701,\\n\"\n        + \"    f = 11.1,\\n\"\n        + \"    m = {\\n\"\n        + \"        9,\\n\"\n        + \"        8,\\n\"\n        + \"        1\\n\"\n        + \"    },\\n\"\n        + \"    l = Override.class,\\n\"\n        + \"    j = @AnnotationSpecTest.AnnotationA,\\n\"\n        + \"    q = @AnnotationSpecTest.AnnotationC(\\\"bar\\\"),\\n\"\n        + \"    r = {\\n\"\n        + \"        Float.class,\\n\"\n        + \"        Double.class\\n\"\n        + \"    }\\n\"\n        + \")\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void defaultAnnotationWithImport() {\n    String name = IsAnnotated.class.getCanonicalName();\n    TypeElement element = compilation.getElements().getTypeElement(name);\n    AnnotationSpec annotation = AnnotationSpec.get(element.getAnnotationMirrors().get(0));\n    TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(IsAnnotated.class.getSimpleName());\n    typeBuilder.addAnnotation(annotation);\n    JavaFile file = JavaFile.builder(\"com.squareup.javapoet\", typeBuilder.build()).build();\n    assertThat(file.toString()).isEqualTo(\n        \"package com.squareup.javapoet;\\n\"\n            + \"\\n\"\n            + \"import java.lang.Double;\\n\"\n            + \"import java.lang.Float;\\n\"\n            + \"import java.lang.Override;\\n\"\n            + \"\\n\"\n            + \"@AnnotationSpecTest.HasDefaultsAnnotation(\\n\"\n            + \"    o = AnnotationSpecTest.Breakfast.PANCAKES,\\n\"\n            + \"    p = 1701,\\n\"\n            + \"    f = 11.1,\\n\"\n            + \"    m = {\\n\"\n            + \"        9,\\n\"\n            + \"        8,\\n\"\n            + \"        1\\n\"\n            + \"    },\\n\"\n            + \"    l = Override.class,\\n\"\n            + \"    j = @AnnotationSpecTest.AnnotationA,\\n\"\n            + \"    q = @AnnotationSpecTest.AnnotationC(\\\"bar\\\"),\\n\"\n            + \"    r = {\\n\"\n            + \"        Float.class,\\n\"\n            + \"        Double.class\\n\"\n            + \"    }\\n\"\n            + \")\\n\"\n            + \"class IsAnnotated {\\n\"\n            + \"}\\n\"\n    );\n  }\n\n  @Test public void emptyArray() {\n    AnnotationSpec.Builder builder = AnnotationSpec.builder(HasDefaultsAnnotation.class);\n    builder.addMember(\"n\", \"$L\", \"{}\");\n    assertThat(builder.build().toString()).isEqualTo(\n        \"@com.squareup.javapoet.AnnotationSpecTest.HasDefaultsAnnotation(\" + \"n = {}\" + \")\");\n    builder.addMember(\"m\", \"$L\", \"{}\");\n    assertThat(builder.build().toString())\n        .isEqualTo(\n            \"@com.squareup.javapoet.AnnotationSpecTest.HasDefaultsAnnotation(\"\n                + \"n = {}, m = {}\"\n                + \")\");\n  }\n\n  @Test public void dynamicArrayOfEnumConstants() {\n    AnnotationSpec.Builder builder = AnnotationSpec.builder(HasDefaultsAnnotation.class);\n    builder.addMember(\"n\", \"$T.$L\", Breakfast.class, Breakfast.PANCAKES.name());\n    assertThat(builder.build().toString()).isEqualTo(\n        \"@com.squareup.javapoet.AnnotationSpecTest.HasDefaultsAnnotation(\"\n            + \"n = com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES\"\n            + \")\");\n\n    // builder = AnnotationSpec.builder(HasDefaultsAnnotation.class);\n    builder.addMember(\"n\", \"$T.$L\", Breakfast.class, Breakfast.WAFFLES.name());\n    builder.addMember(\"n\", \"$T.$L\", Breakfast.class, Breakfast.PANCAKES.name());\n    assertThat(builder.build().toString()).isEqualTo(\n        \"@com.squareup.javapoet.AnnotationSpecTest.HasDefaultsAnnotation(\"\n            + \"n = {\"\n            + \"com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES\"\n            + \", com.squareup.javapoet.AnnotationSpecTest.Breakfast.WAFFLES\"\n            + \", com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES\"\n            + \"})\");\n\n    builder = builder.build().toBuilder(); // idempotent\n    assertThat(builder.build().toString()).isEqualTo(\n        \"@com.squareup.javapoet.AnnotationSpecTest.HasDefaultsAnnotation(\"\n            + \"n = {\"\n            + \"com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES\"\n            + \", com.squareup.javapoet.AnnotationSpecTest.Breakfast.WAFFLES\"\n            + \", com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES\"\n            + \"})\");\n\n    builder.addMember(\"n\", \"$T.$L\", Breakfast.class, Breakfast.WAFFLES.name());\n    assertThat(builder.build().toString()).isEqualTo(\n        \"@com.squareup.javapoet.AnnotationSpecTest.HasDefaultsAnnotation(\"\n            + \"n = {\"\n            + \"com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES\"\n            + \", com.squareup.javapoet.AnnotationSpecTest.Breakfast.WAFFLES\"\n            + \", com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES\"\n            + \", com.squareup.javapoet.AnnotationSpecTest.Breakfast.WAFFLES\"\n            + \"})\");\n  }\n\n  @Test public void defaultAnnotationToBuilder() {\n    String name = IsAnnotated.class.getCanonicalName();\n    TypeElement element = compilation.getElements().getTypeElement(name);\n    AnnotationSpec.Builder builder = AnnotationSpec.get(element.getAnnotationMirrors().get(0))\n        .toBuilder();\n    builder.addMember(\"m\", \"$L\", 123);\n    assertThat(builder.build().toString()).isEqualTo(\n        \"@com.squareup.javapoet.AnnotationSpecTest.HasDefaultsAnnotation(\"\n            + \"o = com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES\"\n            + \", p = 1701\"\n            + \", f = 11.1\"\n            + \", m = {9, 8, 1, 123}\"\n            + \", l = java.lang.Override.class\"\n            + \", j = @com.squareup.javapoet.AnnotationSpecTest.AnnotationA\"\n            + \", q = @com.squareup.javapoet.AnnotationSpecTest.AnnotationC(\\\"bar\\\")\"\n            + \", r = {java.lang.Float.class, java.lang.Double.class}\"\n            + \")\");\n  }\n\n  @Test public void reflectAnnotation() {\n    HasDefaultsAnnotation annotation = IsAnnotated.class.getAnnotation(HasDefaultsAnnotation.class);\n    AnnotationSpec spec = AnnotationSpec.get(annotation);\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addAnnotation(spec)\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.squareup.javapoet.AnnotationSpecTest;\\n\"\n        + \"import java.lang.Double;\\n\"\n        + \"import java.lang.Float;\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"\\n\"\n        + \"@AnnotationSpecTest.HasDefaultsAnnotation(\\n\"\n        + \"    f = 11.1,\\n\"\n        + \"    l = Override.class,\\n\"\n        + \"    m = {\\n\"\n        + \"        9,\\n\"\n        + \"        8,\\n\"\n        + \"        1\\n\"\n        + \"    },\\n\"\n        + \"    o = AnnotationSpecTest.Breakfast.PANCAKES,\\n\"\n        + \"    p = 1701,\\n\"\n        + \"    q = @AnnotationSpecTest.AnnotationC(\\\"bar\\\"),\\n\"\n        + \"    r = {\\n\"\n        + \"        Float.class,\\n\"\n        + \"        Double.class\\n\"\n        + \"    }\\n\"\n        + \")\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void reflectAnnotationWithDefaults() {\n    HasDefaultsAnnotation annotation = IsAnnotated.class.getAnnotation(HasDefaultsAnnotation.class);\n    AnnotationSpec spec = AnnotationSpec.get(annotation, true);\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addAnnotation(spec)\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.squareup.javapoet.AnnotationSpecTest;\\n\"\n        + \"import java.lang.Double;\\n\"\n        + \"import java.lang.Float;\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"\\n\"\n        + \"@AnnotationSpecTest.HasDefaultsAnnotation(\\n\"\n        + \"    a = 5,\\n\"\n        + \"    b = 6,\\n\"\n        + \"    c = 7,\\n\"\n        + \"    d = 12345678910L,\\n\"\n        + \"    e = 9.0f,\\n\"\n        + \"    f = 11.1,\\n\"\n        + \"    g = {\\n\"\n        + \"        '\\\\u0000',\\n\"\n        + \"        '쫾',\\n\"\n        + \"        'z',\\n\"\n        + \"        '€',\\n\"\n        + \"        'ℕ',\\n\"\n        + \"        '\\\"',\\n\"\n        + \"        '\\\\'',\\n\"\n        + \"        '\\\\t',\\n\"\n        + \"        '\\\\n'\\n\"\n        + \"    },\\n\"\n        + \"    h = true,\\n\"\n        + \"    i = AnnotationSpecTest.Breakfast.WAFFLES,\\n\"\n        + \"    j = @AnnotationSpecTest.AnnotationA,\\n\"\n        + \"    k = \\\"maple\\\",\\n\"\n        + \"    l = Override.class,\\n\"\n        + \"    m = {\\n\"\n        + \"        9,\\n\"\n        + \"        8,\\n\"\n        + \"        1\\n\"\n        + \"    },\\n\"\n        + \"    n = {\\n\"\n        + \"        AnnotationSpecTest.Breakfast.WAFFLES,\\n\"\n        + \"        AnnotationSpecTest.Breakfast.PANCAKES\\n\"\n        + \"    },\\n\"\n        + \"    o = AnnotationSpecTest.Breakfast.PANCAKES,\\n\"\n        + \"    p = 1701,\\n\"\n        + \"    q = @AnnotationSpecTest.AnnotationC(\\\"bar\\\"),\\n\"\n        + \"    r = {\\n\"\n        + \"        Float.class,\\n\"\n        + \"        Double.class\\n\"\n        + \"    }\\n\"\n        + \")\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void disallowsNullMemberName() {\n    AnnotationSpec.Builder builder = AnnotationSpec.builder(HasDefaultsAnnotation.class);\n    try {\n      AnnotationSpec.Builder $L = builder.addMember(null, \"$L\", \"\");\n      fail($L.build().toString());\n    } catch (NullPointerException e) {\n      assertThat(e).hasMessageThat().isEqualTo(\"name == null\");\n    }\n  }\n\n  @Test public void requiresValidMemberName() {\n    AnnotationSpec.Builder builder = AnnotationSpec.builder(HasDefaultsAnnotation.class);\n    try {\n      AnnotationSpec.Builder $L = builder.addMember(\"@\", \"$L\", \"\");\n      fail($L.build().toString());\n    } catch (IllegalArgumentException e) {\n      assertThat(e).hasMessageThat().isEqualTo(\"not a valid name: @\");\n    }\n  }\n\n  @Test public void modifyMembers() {\n    AnnotationSpec.Builder builder = AnnotationSpec.builder(SuppressWarnings.class)\n            .addMember(\"value\", \"$S\", \"Foo\");\n    \n    builder.members.clear();\n    builder.members.put(\"value\", Arrays.asList(CodeBlock.of(\"$S\", \"Bar\")));\n\n    assertThat(builder.build().toString()).isEqualTo(\"@java.lang.SuppressWarnings(\\\"Bar\\\")\");\n  }\n\n  private String toString(TypeSpec typeSpec) {\n    return JavaFile.builder(\"com.squareup.tacos\", typeSpec).build().toString();\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/ClassNameTest.java",
    "content": "/*\n * Copyright (C) 2014 Google, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport com.google.testing.compile.CompilationRule;\nimport java.util.Map;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.util.Elements;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mockito;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\nimport static org.mockito.Mockito.when;\n\n@RunWith(JUnit4.class)\npublic final class ClassNameTest {\n  @Rule public CompilationRule compilationRule = new CompilationRule();\n\n  @Test public void bestGuessForString_simpleClass() {\n    assertThat(ClassName.bestGuess(String.class.getName()))\n        .isEqualTo(ClassName.get(\"java.lang\", \"String\"));\n  }\n\n  @Test public void bestGuessNonAscii() {\n    ClassName className = ClassName.bestGuess(\n        \"com.\\ud835\\udc1andro\\ud835\\udc22d.\\ud835\\udc00ctiv\\ud835\\udc22ty\");\n    assertEquals(\"com.\\ud835\\udc1andro\\ud835\\udc22d\", className.packageName());\n    assertEquals(\"\\ud835\\udc00ctiv\\ud835\\udc22ty\", className.simpleName());\n  }\n\n  static class OuterClass {\n    static class InnerClass {}\n  }\n\n  @Test public void bestGuessForString_nestedClass() {\n    assertThat(ClassName.bestGuess(Map.Entry.class.getCanonicalName()))\n        .isEqualTo(ClassName.get(\"java.util\", \"Map\", \"Entry\"));\n    assertThat(ClassName.bestGuess(OuterClass.InnerClass.class.getCanonicalName()))\n        .isEqualTo(ClassName.get(\"com.squareup.javapoet\",\n            \"ClassNameTest\", \"OuterClass\", \"InnerClass\"));\n  }\n\n  @Test public void bestGuessForString_defaultPackage() {\n    assertThat(ClassName.bestGuess(\"SomeClass\"))\n        .isEqualTo(ClassName.get(\"\", \"SomeClass\"));\n    assertThat(ClassName.bestGuess(\"SomeClass.Nested\"))\n        .isEqualTo(ClassName.get(\"\", \"SomeClass\", \"Nested\"));\n    assertThat(ClassName.bestGuess(\"SomeClass.Nested.EvenMore\"))\n        .isEqualTo(ClassName.get(\"\", \"SomeClass\", \"Nested\", \"EvenMore\"));\n  }\n\n  @Test public void bestGuessForString_confusingInput() {\n    assertBestGuessThrows(\"\");\n    assertBestGuessThrows(\".\");\n    assertBestGuessThrows(\".Map\");\n    assertBestGuessThrows(\"java\");\n    assertBestGuessThrows(\"java.util\");\n    assertBestGuessThrows(\"java.util.\");\n    assertBestGuessThrows(\"java..util.Map.Entry\");\n    assertBestGuessThrows(\"java.util..Map.Entry\");\n    assertBestGuessThrows(\"java.util.Map..Entry\");\n    assertBestGuessThrows(\"com.test.$\");\n    assertBestGuessThrows(\"com.test.LooksLikeAClass.pkg\");\n    assertBestGuessThrows(\"!@#$gibberish%^&*\");\n  }\n\n  private void assertBestGuessThrows(String s) {\n    try {\n      ClassName.bestGuess(s);\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void createNestedClass() {\n    ClassName foo = ClassName.get(\"com.example\", \"Foo\");\n    ClassName bar = foo.nestedClass(\"Bar\");\n    assertThat(bar).isEqualTo(ClassName.get(\"com.example\", \"Foo\", \"Bar\"));\n    ClassName baz = bar.nestedClass(\"Baz\");\n    assertThat(baz).isEqualTo(ClassName.get(\"com.example\", \"Foo\", \"Bar\", \"Baz\"));\n  }\n\n  static class $Outer {\n    static class $Inner {}\n  }\n\n  @Test public void classNameFromTypeElement() {\n    Elements elements = compilationRule.getElements();\n    TypeElement object = elements.getTypeElement(Object.class.getCanonicalName());\n    assertThat(ClassName.get(object).toString()).isEqualTo(\"java.lang.Object\");\n    TypeElement outer = elements.getTypeElement($Outer.class.getCanonicalName());\n    assertThat(ClassName.get(outer).toString()).isEqualTo(\"com.squareup.javapoet.ClassNameTest.$Outer\");\n    TypeElement inner = elements.getTypeElement($Outer.$Inner.class.getCanonicalName());\n    assertThat(ClassName.get(inner).toString()).isEqualTo(\"com.squareup.javapoet.ClassNameTest.$Outer.$Inner\");\n  }\n\n  /**\n   * Buck builds with \"source-based ABI generation\" and those builds don't support\n   * {@link TypeElement#getKind()}. Test to confirm that we don't use that API.\n   */\n  @Test public void classNameFromTypeElementDoesntUseGetKind() {\n    Elements elements = compilationRule.getElements();\n    TypeElement object = elements.getTypeElement(Object.class.getCanonicalName());\n    assertThat(ClassName.get(preventGetKind(object)).toString())\n        .isEqualTo(\"java.lang.Object\");\n    TypeElement outer = elements.getTypeElement($Outer.class.getCanonicalName());\n    assertThat(ClassName.get(preventGetKind(outer)).toString())\n        .isEqualTo(\"com.squareup.javapoet.ClassNameTest.$Outer\");\n    TypeElement inner = elements.getTypeElement($Outer.$Inner.class.getCanonicalName());\n    assertThat(ClassName.get(preventGetKind(inner)).toString())\n        .isEqualTo(\"com.squareup.javapoet.ClassNameTest.$Outer.$Inner\");\n  }\n\n  /** Returns a new instance like {@code object} that throws on {@code getKind()}. */\n  private TypeElement preventGetKind(TypeElement object) {\n    TypeElement spy = Mockito.spy(object);\n    when(spy.getKind()).thenThrow(new AssertionError());\n    when(spy.getEnclosingElement()).thenAnswer(invocation -> {\n      Object enclosingElement = invocation.callRealMethod();\n      return enclosingElement instanceof TypeElement\n          ? preventGetKind((TypeElement) enclosingElement)\n          : enclosingElement;\n    });\n    return spy;\n  }\n\n  @Test public void classNameFromClass() {\n    assertThat(ClassName.get(Object.class).toString())\n        .isEqualTo(\"java.lang.Object\");\n    assertThat(ClassName.get(OuterClass.InnerClass.class).toString())\n        .isEqualTo(\"com.squareup.javapoet.ClassNameTest.OuterClass.InnerClass\");\n    assertThat((ClassName.get(new Object() {}.getClass())).toString())\n        .isEqualTo(\"com.squareup.javapoet.ClassNameTest$1\");\n    assertThat((ClassName.get(new Object() { Object inner = new Object() {}; }.inner.getClass())).toString())\n        .isEqualTo(\"com.squareup.javapoet.ClassNameTest$2$1\");\n    assertThat((ClassName.get($Outer.class)).toString())\n        .isEqualTo(\"com.squareup.javapoet.ClassNameTest.$Outer\");\n    assertThat((ClassName.get($Outer.$Inner.class)).toString())\n        .isEqualTo(\"com.squareup.javapoet.ClassNameTest.$Outer.$Inner\");\n  }\n\n  @Test public void peerClass() {\n    assertThat(ClassName.get(Double.class).peerClass(\"Short\"))\n        .isEqualTo(ClassName.get(Short.class));\n    assertThat(ClassName.get(\"\", \"Double\").peerClass(\"Short\"))\n        .isEqualTo(ClassName.get(\"\", \"Short\"));\n    assertThat(ClassName.get(\"a.b\", \"Combo\", \"Taco\").peerClass(\"Burrito\"))\n        .isEqualTo(ClassName.get(\"a.b\", \"Combo\", \"Burrito\"));\n  }\n\n  @Test public void fromClassRejectionTypes() {\n    try {\n      ClassName.get(int.class);\n      fail();\n    } catch (IllegalArgumentException ignored) {\n    }\n    try {\n      ClassName.get(void.class);\n      fail();\n    } catch (IllegalArgumentException ignored) {\n    }\n    try {\n      ClassName.get(Object[].class);\n      fail();\n    } catch (IllegalArgumentException ignored) {\n    }\n  }\n\n  @Test\n  public void reflectionName() {\n    assertEquals(\"java.lang.Object\", TypeName.OBJECT.reflectionName());\n    assertEquals(\"java.lang.Thread$State\", ClassName.get(Thread.State.class).reflectionName());\n    assertEquals(\"java.util.Map$Entry\", ClassName.get(Map.Entry.class).reflectionName());\n    assertEquals(\"Foo\", ClassName.get(\"\", \"Foo\").reflectionName());\n    assertEquals(\"Foo$Bar$Baz\", ClassName.get(\"\", \"Foo\", \"Bar\", \"Baz\").reflectionName());\n    assertEquals(\"a.b.c.Foo$Bar$Baz\", ClassName.get(\"a.b.c\", \"Foo\", \"Bar\", \"Baz\").reflectionName());\n  }\n\n  @Test\n  public void canonicalName() {\n    assertEquals(\"java.lang.Object\", TypeName.OBJECT.canonicalName());\n    assertEquals(\"java.lang.Thread.State\", ClassName.get(Thread.State.class).canonicalName());\n    assertEquals(\"java.util.Map.Entry\", ClassName.get(Map.Entry.class).canonicalName());\n    assertEquals(\"Foo\", ClassName.get(\"\", \"Foo\").canonicalName());\n    assertEquals(\"Foo.Bar.Baz\", ClassName.get(\"\", \"Foo\", \"Bar\", \"Baz\").canonicalName());\n    assertEquals(\"a.b.c.Foo.Bar.Baz\", ClassName.get(\"a.b.c\", \"Foo\", \"Bar\", \"Baz\").canonicalName());\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/CodeBlockTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\npublic final class CodeBlockTest {\n  @Test public void equalsAndHashCode() {\n    CodeBlock a = CodeBlock.builder().build();\n    CodeBlock b = CodeBlock.builder().build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    a = CodeBlock.builder().add(\"$L\", \"taco\").build();\n    b = CodeBlock.builder().add(\"$L\", \"taco\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n  }\n\n  @Test public void of() {\n    CodeBlock a = CodeBlock.of(\"$L taco\", \"delicious\");\n    assertThat(a.toString()).isEqualTo(\"delicious taco\");\n  }\n\n  @Test public void isEmpty() {\n    assertTrue(CodeBlock.builder().isEmpty());\n    assertTrue(CodeBlock.builder().add(\"\").isEmpty());\n    assertFalse(CodeBlock.builder().add(\" \").isEmpty());\n  }\n\n  @Test public void indentCannotBeIndexed() {\n    try {\n      CodeBlock.builder().add(\"$1>\", \"taco\").build();\n      fail();\n    } catch (IllegalArgumentException exp) {\n      assertThat(exp)\n          .hasMessageThat()\n          .isEqualTo(\"$$, $>, $<, $[, $], $W, and $Z may not have an index\");\n    }\n  }\n\n  @Test public void deindentCannotBeIndexed() {\n    try {\n      CodeBlock.builder().add(\"$1<\", \"taco\").build();\n      fail();\n    } catch (IllegalArgumentException exp) {\n      assertThat(exp)\n          .hasMessageThat()\n          .isEqualTo(\"$$, $>, $<, $[, $], $W, and $Z may not have an index\");\n    }\n  }\n\n  @Test public void dollarSignEscapeCannotBeIndexed() {\n    try {\n      CodeBlock.builder().add(\"$1$\", \"taco\").build();\n      fail();\n    } catch (IllegalArgumentException exp) {\n      assertThat(exp)\n          .hasMessageThat()\n          .isEqualTo(\"$$, $>, $<, $[, $], $W, and $Z may not have an index\");\n    }\n  }\n\n  @Test public void statementBeginningCannotBeIndexed() {\n    try {\n      CodeBlock.builder().add(\"$1[\", \"taco\").build();\n      fail();\n    } catch (IllegalArgumentException exp) {\n      assertThat(exp)\n          .hasMessageThat()\n          .isEqualTo(\"$$, $>, $<, $[, $], $W, and $Z may not have an index\");\n    }\n  }\n\n  @Test public void statementEndingCannotBeIndexed() {\n    try {\n      CodeBlock.builder().add(\"$1]\", \"taco\").build();\n      fail();\n    } catch (IllegalArgumentException exp) {\n      assertThat(exp)\n          .hasMessageThat()\n          .isEqualTo(\"$$, $>, $<, $[, $], $W, and $Z may not have an index\");\n    }\n  }\n\n  @Test public void nameFormatCanBeIndexed() {\n    CodeBlock block = CodeBlock.builder().add(\"$1N\", \"taco\").build();\n    assertThat(block.toString()).isEqualTo(\"taco\");\n  }\n\n  @Test public void literalFormatCanBeIndexed() {\n    CodeBlock block = CodeBlock.builder().add(\"$1L\", \"taco\").build();\n    assertThat(block.toString()).isEqualTo(\"taco\");\n  }\n\n  @Test public void stringFormatCanBeIndexed() {\n    CodeBlock block = CodeBlock.builder().add(\"$1S\", \"taco\").build();\n    assertThat(block.toString()).isEqualTo(\"\\\"taco\\\"\");\n  }\n\n  @Test public void typeFormatCanBeIndexed() {\n    CodeBlock block = CodeBlock.builder().add(\"$1T\", String.class).build();\n    assertThat(block.toString()).isEqualTo(\"java.lang.String\");\n  }\n\n  @Test public void simpleNamedArgument() {\n    Map<String, Object> map = new LinkedHashMap<>();\n    map.put(\"text\", \"taco\");\n    CodeBlock block = CodeBlock.builder().addNamed(\"$text:S\", map).build();\n    assertThat(block.toString()).isEqualTo(\"\\\"taco\\\"\");\n  }\n\n  @Test public void repeatedNamedArgument() {\n    Map<String, Object> map = new LinkedHashMap<>();\n    map.put(\"text\", \"tacos\");\n    CodeBlock block = CodeBlock.builder()\n        .addNamed(\"\\\"I like \\\" + $text:S + \\\". Do you like \\\" + $text:S + \\\"?\\\"\", map)\n        .build();\n    assertThat(block.toString()).isEqualTo(\n        \"\\\"I like \\\" + \\\"tacos\\\" + \\\". Do you like \\\" + \\\"tacos\\\" + \\\"?\\\"\");\n  }\n\n  @Test public void namedAndNoArgFormat() {\n    Map<String, Object> map = new LinkedHashMap<>();\n    map.put(\"text\", \"tacos\");\n    CodeBlock block = CodeBlock.builder()\n        .addNamed(\"$>\\n$text:L for $$3.50\", map).build();\n    assertThat(block.toString()).isEqualTo(\"\\n  tacos for $3.50\");\n  }\n\n  @Test public void missingNamedArgument() {\n    try {\n      Map<String, Object> map = new LinkedHashMap<>();\n      CodeBlock.builder().addNamed(\"$text:S\", map).build();\n      fail();\n    } catch(IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"Missing named argument for $text\");\n    }\n  }\n\n  @Test public void lowerCaseNamed() {\n    try {\n      Map<String, Object> map = new LinkedHashMap<>();\n      map.put(\"Text\", \"tacos\");\n      CodeBlock block = CodeBlock.builder().addNamed(\"$Text:S\", map).build();\n      fail();\n    } catch(IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"argument 'Text' must start with a lowercase character\");\n    }\n  }\n\n  @Test public void multipleNamedArguments() {\n    Map<String, Object> map = new LinkedHashMap<>();\n    map.put(\"pipe\", System.class);\n    map.put(\"text\", \"tacos\");\n\n    CodeBlock block = CodeBlock.builder()\n        .addNamed(\"$pipe:T.out.println(\\\"Let's eat some $text:L\\\");\", map)\n        .build();\n\n    assertThat(block.toString()).isEqualTo(\n        \"java.lang.System.out.println(\\\"Let's eat some tacos\\\");\");\n  }\n\n  @Test public void namedNewline() {\n    Map<String, Object> map = new LinkedHashMap<>();\n    map.put(\"clazz\", Integer.class);\n    CodeBlock block = CodeBlock.builder().addNamed(\"$clazz:T\\n\", map).build();\n    assertThat(block.toString()).isEqualTo(\"java.lang.Integer\\n\");\n  }\n\n  @Test public void danglingNamed() {\n    Map<String, Object> map = new LinkedHashMap<>();\n    map.put(\"clazz\", Integer.class);\n    try {\n      CodeBlock.builder().addNamed(\"$clazz:T$\", map).build();\n      fail();\n    } catch(IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"dangling $ at end\");\n    }\n  }\n\n  @Test public void indexTooHigh() {\n    try {\n      CodeBlock.builder().add(\"$2T\", String.class).build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"index 2 for '$2T' not in range (received 1 arguments)\");\n    }\n  }\n\n  @Test public void indexIsZero() {\n    try {\n      CodeBlock.builder().add(\"$0T\", String.class).build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"index 0 for '$0T' not in range (received 1 arguments)\");\n    }\n  }\n\n  @Test public void indexIsNegative() {\n    try {\n      CodeBlock.builder().add(\"$-1T\", String.class).build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"invalid format string: '$-1T'\");\n    }\n  }\n\n  @Test public void indexWithoutFormatType() {\n    try {\n      CodeBlock.builder().add(\"$1\", String.class).build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"dangling format characters in '$1'\");\n    }\n  }\n\n  @Test public void indexWithoutFormatTypeNotAtStringEnd() {\n    try {\n      CodeBlock.builder().add(\"$1 taco\", String.class).build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"invalid format string: '$1 taco'\");\n    }\n  }\n\n  @Test public void indexButNoArguments() {\n    try {\n      CodeBlock.builder().add(\"$1T\").build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"index 1 for '$1T' not in range (received 0 arguments)\");\n    }\n  }\n\n  @Test public void formatIndicatorAlone() {\n    try {\n      CodeBlock.builder().add(\"$\", String.class).build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"dangling format characters in '$'\");\n    }\n  }\n\n  @Test public void formatIndicatorWithoutIndexOrFormatType() {\n    try {\n      CodeBlock.builder().add(\"$ tacoString\", String.class).build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"invalid format string: '$ tacoString'\");\n    }\n  }\n\n  @Test public void sameIndexCanBeUsedWithDifferentFormats() {\n    CodeBlock block = CodeBlock.builder()\n        .add(\"$1T.out.println($1S)\", ClassName.get(System.class))\n        .build();\n    assertThat(block.toString()).isEqualTo(\"java.lang.System.out.println(\\\"java.lang.System\\\")\");\n  }\n\n  @Test public void tooManyStatementEnters() {\n    CodeBlock codeBlock = CodeBlock.builder().add(\"$[$[\").build();\n    try {\n      // We can't report this error until rendering type because code blocks might be composed.\n      codeBlock.toString();\n      fail();\n    } catch (IllegalStateException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"statement enter $[ followed by statement enter $[\");\n    }\n  }\n\n  @Test public void statementExitWithoutStatementEnter() {\n    CodeBlock codeBlock = CodeBlock.builder().add(\"$]\").build();\n    try {\n      // We can't report this error until rendering type because code blocks might be composed.\n      codeBlock.toString();\n      fail();\n    } catch (IllegalStateException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"statement exit $] has no matching statement enter $[\");\n    }\n  }\n\n  @Test public void join() {\n    List<CodeBlock> codeBlocks = new ArrayList<>();\n    codeBlocks.add(CodeBlock.of(\"$S\", \"hello\"));\n    codeBlocks.add(CodeBlock.of(\"$T\", ClassName.get(\"world\", \"World\")));\n    codeBlocks.add(CodeBlock.of(\"need tacos\"));\n\n    CodeBlock joined = CodeBlock.join(codeBlocks, \" || \");\n    assertThat(joined.toString()).isEqualTo(\"\\\"hello\\\" || world.World || need tacos\");\n  }\n\n  @Test public void joining() {\n    List<CodeBlock> codeBlocks = new ArrayList<>();\n    codeBlocks.add(CodeBlock.of(\"$S\", \"hello\"));\n    codeBlocks.add(CodeBlock.of(\"$T\", ClassName.get(\"world\", \"World\")));\n    codeBlocks.add(CodeBlock.of(\"need tacos\"));\n\n    CodeBlock joined = codeBlocks.stream().collect(CodeBlock.joining(\" || \"));\n    assertThat(joined.toString()).isEqualTo(\"\\\"hello\\\" || world.World || need tacos\");\n  }\n\n  @Test public void joiningSingle() {\n    List<CodeBlock> codeBlocks = new ArrayList<>();\n    codeBlocks.add(CodeBlock.of(\"$S\", \"hello\"));\n\n    CodeBlock joined = codeBlocks.stream().collect(CodeBlock.joining(\" || \"));\n    assertThat(joined.toString()).isEqualTo(\"\\\"hello\\\"\");\n  }\n\n  @Test public void joiningWithPrefixAndSuffix() {\n    List<CodeBlock> codeBlocks = new ArrayList<>();\n    codeBlocks.add(CodeBlock.of(\"$S\", \"hello\"));\n    codeBlocks.add(CodeBlock.of(\"$T\", ClassName.get(\"world\", \"World\")));\n    codeBlocks.add(CodeBlock.of(\"need tacos\"));\n\n    CodeBlock joined = codeBlocks.stream().collect(CodeBlock.joining(\" || \", \"start {\", \"} end\"));\n    assertThat(joined.toString()).isEqualTo(\"start {\\\"hello\\\" || world.World || need tacos} end\");\n  }\n\n  @Test public void clear() {\n    CodeBlock block = CodeBlock.builder()\n        .addStatement(\"$S\", \"Test string\")\n        .clear()\n        .build();\n\n    assertThat(block.toString()).isEmpty();\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/CodeWriterTest.java",
    "content": "package com.squareup.javapoet;\n\nimport org.junit.Test;\n\nimport java.io.IOException;\n\nimport static com.google.common.truth.Truth.assertThat;\n\npublic class CodeWriterTest {\n\n    @Test\n    public void emptyLineInJavaDocDosEndings() throws IOException {\n        CodeBlock javadocCodeBlock = CodeBlock.of(\"A\\r\\n\\r\\nB\\r\\n\");\n        StringBuilder out = new StringBuilder();\n        new CodeWriter(out).emitJavadoc(javadocCodeBlock);\n        assertThat(out.toString()).isEqualTo(\n                \"/**\\n\" +\n                        \" * A\\n\" +\n                        \" *\\n\" +\n                        \" * B\\n\" +\n                        \" */\\n\");\n    }\n}"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/FieldSpecTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.junit.Assert.fail;\n\nimport javax.lang.model.element.Modifier;\n\npublic class FieldSpecTest {\n  @Test public void equalsAndHashCode() {\n    FieldSpec a = FieldSpec.builder(int.class, \"foo\").build();\n    FieldSpec b = FieldSpec.builder(int.class, \"foo\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    assertThat(a.toString()).isEqualTo(b.toString());\n    a = FieldSpec.builder(int.class, \"FOO\", Modifier.PUBLIC, Modifier.STATIC).build();\n    b = FieldSpec.builder(int.class, \"FOO\", Modifier.PUBLIC, Modifier.STATIC).build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    assertThat(a.toString()).isEqualTo(b.toString());\n  }\n\n  @Test public void nullAnnotationsAddition() {\n    try {\n      FieldSpec.builder(int.class, \"foo\").addAnnotations(null);\n      fail();\n    }\n    catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"annotationSpecs == null\");\n    }\n  }\n\n  @Test public void modifyAnnotations() {\n    FieldSpec.Builder builder = FieldSpec.builder(int.class, \"foo\")\n          .addAnnotation(Override.class)\n          .addAnnotation(SuppressWarnings.class);\n\n    builder.annotations.remove(1);\n    assertThat(builder.build().annotations).hasSize(1);\n  }\n\n  @Test public void modifyModifiers() {\n    FieldSpec.Builder builder = FieldSpec.builder(int.class, \"foo\")\n          .addModifiers(Modifier.PUBLIC, Modifier.STATIC);\n\n    builder.modifiers.remove(1);\n    assertThat(builder.build().modifiers).containsExactly(Modifier.PUBLIC);\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/FileReadingTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport com.google.common.io.ByteStreams;\nimport java.io.IOException;\nimport java.net.URI;\nimport java.util.Collections;\nimport java.util.Locale;\nimport java.util.concurrent.Callable;\nimport javax.lang.model.element.Modifier;\nimport javax.tools.DiagnosticCollector;\nimport javax.tools.JavaCompiler;\nimport javax.tools.JavaCompiler.CompilationTask;\nimport javax.tools.JavaFileObject;\nimport javax.tools.JavaFileObject.Kind;\nimport javax.tools.StandardJavaFileManager;\nimport javax.tools.StandardLocation;\nimport javax.tools.ToolProvider;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.TemporaryFolder;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\n@RunWith(JUnit4.class)\npublic class FileReadingTest {\n  \n  // Used for storing compilation output.\n  @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();\n\n  @Test public void javaFileObjectUri() {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    assertThat(JavaFile.builder(\"\", type).build().toJavaFileObject().toUri())\n        .isEqualTo(URI.create(\"Test.java\"));\n    assertThat(JavaFile.builder(\"foo\", type).build().toJavaFileObject().toUri())\n        .isEqualTo(URI.create(\"foo/Test.java\"));\n    assertThat(JavaFile.builder(\"com.example\", type).build().toJavaFileObject().toUri())\n        .isEqualTo(URI.create(\"com/example/Test.java\"));\n  }\n  \n  @Test public void javaFileObjectKind() {\n    JavaFile javaFile = JavaFile.builder(\"\", TypeSpec.classBuilder(\"Test\").build()).build();\n    assertThat(javaFile.toJavaFileObject().getKind()).isEqualTo(Kind.SOURCE);\n  }\n  \n  @Test public void javaFileObjectCharacterContent() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\")\n        .addJavadoc(\"Pi\\u00f1ata\\u00a1\")\n        .addMethod(MethodSpec.methodBuilder(\"fooBar\").build())\n        .build();\n    JavaFile javaFile = JavaFile.builder(\"foo\", type).build();\n    JavaFileObject javaFileObject = javaFile.toJavaFileObject();\n    \n    // We can never have encoding issues (everything is in process)\n    assertThat(javaFileObject.getCharContent(true)).isEqualTo(javaFile.toString());\n    assertThat(javaFileObject.getCharContent(false)).isEqualTo(javaFile.toString());\n  }\n  \n  @Test public void javaFileObjectInputStreamIsUtf8() throws IOException {\n    JavaFile javaFile = JavaFile.builder(\"foo\", TypeSpec.classBuilder(\"Test\").build())\n        .addFileComment(\"Pi\\u00f1ata\\u00a1\")\n        .build();\n    byte[] bytes = ByteStreams.toByteArray(javaFile.toJavaFileObject().openInputStream());\n    \n    // JavaPoet always uses UTF-8.\n    assertThat(bytes).isEqualTo(javaFile.toString().getBytes(UTF_8));\n  }\n  \n  @Test public void compileJavaFile() throws Exception {\n    final String value = \"Hello World!\";\n    TypeSpec type = TypeSpec.classBuilder(\"Test\")\n        .addModifiers(Modifier.PUBLIC)\n        .addSuperinterface(ParameterizedTypeName.get(Callable.class, String.class))\n        .addMethod(MethodSpec.methodBuilder(\"call\")\n            .returns(String.class)\n            .addModifiers(Modifier.PUBLIC)\n            .addStatement(\"return $S\", value)\n            .build())\n        .build();\n    JavaFile javaFile = JavaFile.builder(\"foo\", type).build();\n\n    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();\n    DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();\n    StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticCollector, \n        Locale.getDefault(), UTF_8);\n    fileManager.setLocation(StandardLocation.CLASS_OUTPUT,\n        Collections.singleton(temporaryFolder.newFolder()));\n    CompilationTask task = compiler.getTask(null, \n        fileManager,\n        diagnosticCollector,\n        Collections.emptySet(),\n        Collections.emptySet(),\n        Collections.singleton(javaFile.toJavaFileObject()));\n    \n    assertThat(task.call()).isTrue();\n    assertThat(diagnosticCollector.getDiagnostics()).isEmpty();\n\n    ClassLoader loader = fileManager.getClassLoader(StandardLocation.CLASS_OUTPUT);\n    Callable<?> test = Class.forName(\"foo.Test\", true, loader)\n            .asSubclass(Callable.class)\n            .getDeclaredConstructor()\n            .newInstance();\n    assertThat(Callable.class.getMethod(\"call\").invoke(test)).isEqualTo(value);\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/FileWritingTest.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport com.google.common.jimfs.Configuration;\nimport com.google.common.jimfs.Jimfs;\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.file.FileSystem;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.Date;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.Modifier;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.TemporaryFolder;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mockito;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static org.junit.Assert.fail;\n\n@RunWith(JUnit4.class)\npublic final class FileWritingTest {\n  // Used for testing java.io File behavior.\n  @Rule public final TemporaryFolder tmp = new TemporaryFolder();\n\n  // Used for testing java.nio.file Path behavior.\n  private final FileSystem fs = Jimfs.newFileSystem(Configuration.unix());\n  private final Path fsRoot = fs.getRootDirectories().iterator().next();\n\n  // Used for testing annotation processor Filer behavior.\n  private final TestFiler filer = new TestFiler(fs, fsRoot);\n\n  @Test public void pathNotDirectory() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    JavaFile javaFile = JavaFile.builder(\"example\", type).build();\n    Path path = fs.getPath(\"/foo/bar\");\n    Files.createDirectories(path.getParent());\n    Files.createFile(path);\n    try {\n      javaFile.writeTo(path);\n      fail();\n    } catch (IllegalArgumentException e) {\n      assertThat(e.getMessage()).isEqualTo(\"path /foo/bar exists but is not a directory.\");\n    }\n  }\n\n  @Test public void fileNotDirectory() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    JavaFile javaFile = JavaFile.builder(\"example\", type).build();\n    File file = new File(tmp.newFolder(\"foo\"), \"bar\");\n    file.createNewFile();\n    try {\n      javaFile.writeTo(file);\n      fail();\n    } catch (IllegalArgumentException e) {\n      assertThat(e.getMessage()).isEqualTo(\n          \"path \" + file.getPath() + \" exists but is not a directory.\");\n    }\n  }\n\n  @Test public void pathDefaultPackage() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    JavaFile.builder(\"\", type).build().writeTo(fsRoot);\n\n    Path testPath = fsRoot.resolve(\"Test.java\");\n    assertThat(Files.exists(testPath)).isTrue();\n  }\n\n  @Test public void fileDefaultPackage() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    JavaFile.builder(\"\", type).build().writeTo(tmp.getRoot());\n\n    File testFile = new File(tmp.getRoot(), \"Test.java\");\n    assertThat(testFile.exists()).isTrue();\n  }\n\n  @Test public void filerDefaultPackage() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    JavaFile.builder(\"\", type).build().writeTo(filer);\n\n    Path testPath = fsRoot.resolve(\"Test.java\");\n    assertThat(Files.exists(testPath)).isTrue();\n  }\n\n  @Test public void pathNestedClasses() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    JavaFile.builder(\"foo\", type).build().writeTo(fsRoot);\n    JavaFile.builder(\"foo.bar\", type).build().writeTo(fsRoot);\n    JavaFile.builder(\"foo.bar.baz\", type).build().writeTo(fsRoot);\n\n    Path fooPath = fsRoot.resolve(fs.getPath(\"foo\", \"Test.java\"));\n    Path barPath = fsRoot.resolve(fs.getPath(\"foo\", \"bar\", \"Test.java\"));\n    Path bazPath = fsRoot.resolve(fs.getPath(\"foo\", \"bar\", \"baz\", \"Test.java\"));\n    assertThat(Files.exists(fooPath)).isTrue();\n    assertThat(Files.exists(barPath)).isTrue();\n    assertThat(Files.exists(bazPath)).isTrue();\n  }\n\n  @Test public void fileNestedClasses() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    JavaFile.builder(\"foo\", type).build().writeTo(tmp.getRoot());\n    JavaFile.builder(\"foo.bar\", type).build().writeTo(tmp.getRoot());\n    JavaFile.builder(\"foo.bar.baz\", type).build().writeTo(tmp.getRoot());\n\n    File fooDir = new File(tmp.getRoot(), \"foo\");\n    File fooFile = new File(fooDir, \"Test.java\");\n    File barDir = new File(fooDir, \"bar\");\n    File barFile = new File(barDir, \"Test.java\");\n    File bazDir = new File(barDir, \"baz\");\n    File bazFile = new File(bazDir, \"Test.java\");\n    assertThat(fooFile.exists()).isTrue();\n    assertThat(barFile.exists()).isTrue();\n    assertThat(bazFile.exists()).isTrue();\n  }\n\n  @Test public void filerNestedClasses() throws IOException {\n    TypeSpec type = TypeSpec.classBuilder(\"Test\").build();\n    JavaFile.builder(\"foo\", type).build().writeTo(filer);\n    JavaFile.builder(\"foo.bar\", type).build().writeTo(filer);\n    JavaFile.builder(\"foo.bar.baz\", type).build().writeTo(filer);\n\n    Path fooPath = fsRoot.resolve(fs.getPath(\"foo\", \"Test.java\"));\n    Path barPath = fsRoot.resolve(fs.getPath(\"foo\", \"bar\", \"Test.java\"));\n    Path bazPath = fsRoot.resolve(fs.getPath(\"foo\", \"bar\", \"baz\", \"Test.java\"));\n    assertThat(Files.exists(fooPath)).isTrue();\n    assertThat(Files.exists(barPath)).isTrue();\n    assertThat(Files.exists(bazPath)).isTrue();\n  }\n\n  @Test public void filerPassesOriginatingElements() throws IOException {\n    Element element1_1 = Mockito.mock(Element.class);\n    TypeSpec test1 = TypeSpec.classBuilder(\"Test1\")\n        .addOriginatingElement(element1_1)\n        .build();\n\n    Element element2_1 = Mockito.mock(Element.class);\n    Element element2_2 = Mockito.mock(Element.class);\n    TypeSpec test2 = TypeSpec.classBuilder(\"Test2\")\n        .addOriginatingElement(element2_1)\n        .addOriginatingElement(element2_2)\n        .build();\n\n    JavaFile.builder(\"example\", test1).build().writeTo(filer);\n    JavaFile.builder(\"example\", test2).build().writeTo(filer);\n\n    Path testPath1 = fsRoot.resolve(fs.getPath(\"example\", \"Test1.java\"));\n    assertThat(filer.getOriginatingElements(testPath1)).containsExactly(element1_1);\n    Path testPath2 = fsRoot.resolve(fs.getPath(\"example\", \"Test2.java\"));\n    assertThat(filer.getOriginatingElements(testPath2)).containsExactly(element2_1, element2_2);\n  }\n\n  @Test public void filerClassesWithTabIndent() throws IOException {\n    TypeSpec test = TypeSpec.classBuilder(\"Test\")\n        .addField(Date.class, \"madeFreshDate\")\n        .addMethod(MethodSpec.methodBuilder(\"main\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n            .addParameter(String[].class, \"args\")\n            .addCode(\"$T.out.println($S);\\n\", System.class, \"Hello World!\")\n            .build())\n        .build();\n    JavaFile.builder(\"foo\", test).indent(\"\\t\").build().writeTo(filer);\n\n    Path fooPath = fsRoot.resolve(fs.getPath(\"foo\", \"Test.java\"));\n    assertThat(Files.exists(fooPath)).isTrue();\n    String source = new String(Files.readAllBytes(fooPath));\n\n    assertThat(source).isEqualTo(\"\"\n        + \"package foo;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"import java.lang.System;\\n\"\n        + \"import java.util.Date;\\n\"\n        + \"\\n\"\n        + \"class Test {\\n\"\n        + \"\\tDate madeFreshDate;\\n\"\n        + \"\\n\"\n        + \"\\tpublic static void main(String[] args) {\\n\"\n        + \"\\t\\tSystem.out.println(\\\"Hello World!\\\");\\n\"\n        + \"\\t}\\n\"\n        + \"}\\n\");\n  }\n\n  /**\n   * This test confirms that JavaPoet ignores the host charset and always uses UTF-8. The host\n   * charset is customized with {@code -Dfile.encoding=ISO-8859-1}.\n   */\n  @Test public void fileIsUtf8() throws IOException {\n    JavaFile javaFile = JavaFile.builder(\"foo\", TypeSpec.classBuilder(\"Taco\").build())\n        .addFileComment(\"Pi\\u00f1ata\\u00a1\")\n        .build();\n    javaFile.writeTo(fsRoot);\n\n    Path fooPath = fsRoot.resolve(fs.getPath(\"foo\", \"Taco.java\"));\n    assertThat(new String(Files.readAllBytes(fooPath), UTF_8)).isEqualTo(\"\"\n        + \"// Pi\\u00f1ata\\u00a1\\n\"\n        + \"package foo;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void writeToPathReturnsPath() throws IOException {\n    JavaFile javaFile = JavaFile.builder(\"foo\", TypeSpec.classBuilder(\"Taco\").build()).build();\n    Path filePath = javaFile.writeToPath(fsRoot);\n    // Cast to avoid ambiguity between assertThat(Path) and assertThat(Iterable<?>)\n    assertThat((Iterable<?>) filePath).isEqualTo(fsRoot.resolve(fs.getPath(\"foo\", \"Taco.java\")));\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/JavaFileTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.File;\nimport com.google.testing.compile.CompilationRule;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport java.util.regex.Pattern;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.TypeElement;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic final class JavaFileTest {\n\n  @Rule public final CompilationRule compilation = new CompilationRule();\n\n  private TypeElement getElement(Class<?> clazz) {\n    return compilation.getElements().getTypeElement(clazz.getCanonicalName());\n  }\n\n  @Test public void importStaticReadmeExample() {\n    ClassName hoverboard = ClassName.get(\"com.mattel\", \"Hoverboard\");\n    ClassName namedBoards = ClassName.get(\"com.mattel\", \"Hoverboard\", \"Boards\");\n    ClassName list = ClassName.get(\"java.util\", \"List\");\n    ClassName arrayList = ClassName.get(\"java.util\", \"ArrayList\");\n    TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);\n    MethodSpec beyond = MethodSpec.methodBuilder(\"beyond\")\n        .returns(listOfHoverboards)\n        .addStatement(\"$T result = new $T<>()\", listOfHoverboards, arrayList)\n        .addStatement(\"result.add($T.createNimbus(2000))\", hoverboard)\n        .addStatement(\"result.add($T.createNimbus(\\\"2001\\\"))\", hoverboard)\n        .addStatement(\"result.add($T.createNimbus($T.THUNDERBOLT))\", hoverboard, namedBoards)\n        .addStatement(\"$T.sort(result)\", Collections.class)\n        .addStatement(\"return result.isEmpty() ? $T.emptyList() : result\", Collections.class)\n        .build();\n    TypeSpec hello = TypeSpec.classBuilder(\"HelloWorld\")\n        .addMethod(beyond)\n        .build();\n    JavaFile example = JavaFile.builder(\"com.example.helloworld\", hello)\n        .addStaticImport(hoverboard, \"createNimbus\")\n        .addStaticImport(namedBoards, \"*\")\n        .addStaticImport(Collections.class, \"*\")\n        .build();\n    assertThat(example.toString()).isEqualTo(\"\"\n        + \"package com.example.helloworld;\\n\"\n        + \"\\n\"\n        + \"import static com.mattel.Hoverboard.Boards.*;\\n\"\n        + \"import static com.mattel.Hoverboard.createNimbus;\\n\"\n        + \"import static java.util.Collections.*;\\n\"\n        + \"\\n\"\n        + \"import com.mattel.Hoverboard;\\n\"\n        + \"import java.util.ArrayList;\\n\"\n        + \"import java.util.List;\\n\"\n        + \"\\n\"\n        + \"class HelloWorld {\\n\"\n        + \"  List<Hoverboard> beyond() {\\n\"\n        + \"    List<Hoverboard> result = new ArrayList<>();\\n\"\n        + \"    result.add(createNimbus(2000));\\n\"\n        + \"    result.add(createNimbus(\\\"2001\\\"));\\n\"\n        + \"    result.add(createNimbus(THUNDERBOLT));\\n\"\n        + \"    sort(result);\\n\"\n        + \"    return result.isEmpty() ? emptyList() : result;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n  @Test public void importStaticForCrazyFormatsWorks() {\n    MethodSpec method = MethodSpec.methodBuilder(\"method\").build();\n    JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addStaticBlock(CodeBlock.builder()\n                .addStatement(\"$T\", Runtime.class)\n                .addStatement(\"$T.a()\", Runtime.class)\n                .addStatement(\"$T.X\", Runtime.class)\n                .addStatement(\"$T$T\", Runtime.class, Runtime.class)\n                .addStatement(\"$T.$T\", Runtime.class, Runtime.class)\n                .addStatement(\"$1T$1T\", Runtime.class)\n                .addStatement(\"$1T$2L$1T\", Runtime.class, \"?\")\n                .addStatement(\"$1T$2L$2S$1T\", Runtime.class, \"?\")\n                .addStatement(\"$1T$2L$2S$1T$3N$1T\", Runtime.class, \"?\", method)\n                .addStatement(\"$T$L\", Runtime.class, \"?\")\n                .addStatement(\"$T$S\", Runtime.class, \"?\")\n                .addStatement(\"$T$N\", Runtime.class, method)\n                .build())\n            .build())\n        .addStaticImport(Runtime.class, \"*\")\n        .build()\n        .toString(); // don't look at the generated code...\n  }\n\n  @Test public void importStaticMixed() {\n    JavaFile source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addStaticBlock(CodeBlock.builder()\n                .addStatement(\"assert $1T.valueOf(\\\"BLOCKED\\\") == $1T.BLOCKED\", Thread.State.class)\n                .addStatement(\"$T.gc()\", System.class)\n                .addStatement(\"$1T.out.println($1T.nanoTime())\", System.class)\n                .build())\n            .addMethod(MethodSpec.constructorBuilder()\n                .addParameter(Thread.State[].class, \"states\")\n                .varargs(true)\n                .build())\n            .build())\n        .addStaticImport(Thread.State.BLOCKED)\n        .addStaticImport(System.class, \"*\")\n        .addStaticImport(Thread.State.class, \"valueOf\")\n        .build();\n    assertThat(source.toString()).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import static java.lang.System.*;\\n\"\n        + \"import static java.lang.Thread.State.BLOCKED;\\n\"\n        + \"import static java.lang.Thread.State.valueOf;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Thread;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  static {\\n\"\n        + \"    assert valueOf(\\\"BLOCKED\\\") == BLOCKED;\\n\"\n        + \"    gc();\\n\"\n        + \"    out.println(nanoTime());\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  Taco(Thread.State... states) {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Ignore(\"addStaticImport doesn't support members with $L\")\n  @Test public void importStaticDynamic() {\n    JavaFile source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addMethod(MethodSpec.methodBuilder(\"main\")\n                .addStatement(\"$T.$L.println($S)\", System.class, \"out\", \"hello\")\n                .build())\n            .build())\n        .addStaticImport(System.class, \"out\")\n        .build();\n    assertThat(source.toString()).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import static java.lang.System.out;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  void main() {\\n\"\n        + \"    out.println(\\\"hello\\\");\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void importStaticNone() {\n    assertThat(JavaFile.builder(\"readme\", importStaticTypeSpec(\"Util\"))\n        .build().toString()).isEqualTo(\"\"\n        + \"package readme;\\n\"\n        + \"\\n\"\n        + \"import java.lang.System;\\n\"\n        + \"import java.util.concurrent.TimeUnit;\\n\"\n        + \"\\n\"\n        + \"class Util {\\n\"\n        + \"  public static long minutesToSeconds(long minutes) {\\n\"\n        + \"    System.gc();\\n\"\n        + \"    return TimeUnit.SECONDS.convert(minutes, TimeUnit.MINUTES);\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void importStaticOnce() {\n    assertThat(JavaFile.builder(\"readme\", importStaticTypeSpec(\"Util\"))\n        .addStaticImport(TimeUnit.SECONDS)\n        .build().toString()).isEqualTo(\"\"\n        + \"package readme;\\n\"\n        + \"\\n\"\n        + \"import static java.util.concurrent.TimeUnit.SECONDS;\\n\"\n        + \"\\n\"\n        + \"import java.lang.System;\\n\"\n        + \"import java.util.concurrent.TimeUnit;\\n\"\n        + \"\\n\"\n        + \"class Util {\\n\"\n        + \"  public static long minutesToSeconds(long minutes) {\\n\"\n        + \"    System.gc();\\n\"\n        + \"    return SECONDS.convert(minutes, TimeUnit.MINUTES);\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void importStaticTwice() {\n    assertThat(JavaFile.builder(\"readme\", importStaticTypeSpec(\"Util\"))\n        .addStaticImport(TimeUnit.SECONDS)\n        .addStaticImport(TimeUnit.MINUTES)\n        .build().toString()).isEqualTo(\"\"\n            + \"package readme;\\n\"\n            + \"\\n\"\n            + \"import static java.util.concurrent.TimeUnit.MINUTES;\\n\"\n            + \"import static java.util.concurrent.TimeUnit.SECONDS;\\n\"\n            + \"\\n\"\n            + \"import java.lang.System;\\n\"\n            + \"\\n\"\n            + \"class Util {\\n\"\n            + \"  public static long minutesToSeconds(long minutes) {\\n\"\n            + \"    System.gc();\\n\"\n            + \"    return SECONDS.convert(minutes, MINUTES);\\n\"\n            + \"  }\\n\"\n            + \"}\\n\");\n  }\n\n  @Test public void importStaticUsingWildcards() {\n    assertThat(JavaFile.builder(\"readme\", importStaticTypeSpec(\"Util\"))\n        .addStaticImport(TimeUnit.class, \"*\")\n        .addStaticImport(System.class, \"*\")\n        .build().toString()).isEqualTo(\"\"\n            + \"package readme;\\n\"\n            + \"\\n\"\n            + \"import static java.lang.System.*;\\n\"\n            + \"import static java.util.concurrent.TimeUnit.*;\\n\"\n            + \"\\n\"\n            + \"class Util {\\n\"\n            + \"  public static long minutesToSeconds(long minutes) {\\n\"\n            + \"    gc();\\n\"\n            + \"    return SECONDS.convert(minutes, MINUTES);\\n\"\n            + \"  }\\n\"\n            + \"}\\n\");\n  }\n\n  private TypeSpec importStaticTypeSpec(String name) {\n    MethodSpec method = MethodSpec.methodBuilder(\"minutesToSeconds\")\n        .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n        .returns(long.class)\n        .addParameter(long.class, \"minutes\")\n        .addStatement(\"$T.gc()\", System.class)\n        .addStatement(\"return $1T.SECONDS.convert(minutes, $1T.MINUTES)\", TimeUnit.class)\n        .build();\n    return TypeSpec.classBuilder(name).addMethod(method).build();\n\n  }\n  @Test public void noImports() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\").build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void singleImport() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addField(Date.class, \"madeFreshDate\")\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.util.Date;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  Date madeFreshDate;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void conflictingImports() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addField(Date.class, \"madeFreshDate\")\n            .addField(ClassName.get(\"java.sql\", \"Date\"), \"madeFreshDatabaseDate\")\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.util.Date;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  Date madeFreshDate;\\n\"\n        + \"\\n\"\n        + \"  java.sql.Date madeFreshDatabaseDate;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void annotatedTypeParam() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addField(ParameterizedTypeName.get(ClassName.get(List.class),\n                ClassName.get(\"com.squareup.meat\", \"Chorizo\")\n                    .annotated(AnnotationSpec.builder(ClassName.get(\"com.squareup.tacos\", \"Spicy\"))\n                        .build())), \"chorizo\")\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.squareup.meat.Chorizo;\\n\"\n        + \"import java.util.List;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  List<@Spicy Chorizo> chorizo;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void skipJavaLangImportsWithConflictingClassLast() throws Exception {\n    // Whatever is used first wins! In this case the Float in java.lang is imported.\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addField(ClassName.get(\"java.lang\", \"Float\"), \"litres\")\n            .addField(ClassName.get(\"com.squareup.soda\", \"Float\"), \"beverage\")\n            .build())\n        .skipJavaLangImports(true)\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  Float litres;\\n\"\n        + \"\\n\"\n        + \"  com.squareup.soda.Float beverage;\\n\" // Second 'Float' is fully qualified.\n        + \"}\\n\");\n  }\n\n  @Test public void skipJavaLangImportsWithConflictingClassFirst() throws Exception {\n    // Whatever is used first wins! In this case the Float in com.squareup.soda is imported.\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addField(ClassName.get(\"com.squareup.soda\", \"Float\"), \"beverage\")\n            .addField(ClassName.get(\"java.lang\", \"Float\"), \"litres\")\n            .build())\n        .skipJavaLangImports(true)\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.squareup.soda.Float;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  Float beverage;\\n\"\n        + \"\\n\"\n        + \"  java.lang.Float litres;\\n\" // Second 'Float' is fully qualified.\n        + \"}\\n\");\n  }\n\n  @Test public void conflictingParentName() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"A\")\n            .addType(TypeSpec.classBuilder(\"B\")\n                .addType(TypeSpec.classBuilder(\"Twin\").build())\n                .addType(TypeSpec.classBuilder(\"C\")\n                    .addField(ClassName.get(\"com.squareup.tacos\", \"A\", \"Twin\", \"D\"), \"d\")\n                    .build())\n                .build())\n            .addType(TypeSpec.classBuilder(\"Twin\")\n                .addType(TypeSpec.classBuilder(\"D\")\n                    .build())\n                .build())\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class A {\\n\"\n        + \"  class B {\\n\"\n        + \"    class Twin {\\n\"\n        + \"    }\\n\"\n        + \"\\n\"\n        + \"    class C {\\n\"\n        + \"      A.Twin.D d;\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  class Twin {\\n\"\n        + \"    class D {\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void conflictingChildName() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"A\")\n            .addType(TypeSpec.classBuilder(\"B\")\n                .addType(TypeSpec.classBuilder(\"C\")\n                    .addField(ClassName.get(\"com.squareup.tacos\", \"A\", \"Twin\", \"D\"), \"d\")\n                    .addType(TypeSpec.classBuilder(\"Twin\").build())\n                    .build())\n                .build())\n            .addType(TypeSpec.classBuilder(\"Twin\")\n                .addType(TypeSpec.classBuilder(\"D\")\n                    .build())\n                .build())\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class A {\\n\"\n        + \"  class B {\\n\"\n        + \"    class C {\\n\"\n        + \"      A.Twin.D d;\\n\"\n        + \"\\n\"\n        + \"      class Twin {\\n\"\n        + \"      }\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  class Twin {\\n\"\n        + \"    class D {\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void conflictingNameOutOfScope() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"A\")\n            .addType(TypeSpec.classBuilder(\"B\")\n                .addType(TypeSpec.classBuilder(\"C\")\n                    .addField(ClassName.get(\"com.squareup.tacos\", \"A\", \"Twin\", \"D\"), \"d\")\n                    .addType(TypeSpec.classBuilder(\"Nested\")\n                        .addType(TypeSpec.classBuilder(\"Twin\").build())\n                        .build())\n                    .build())\n                .build())\n            .addType(TypeSpec.classBuilder(\"Twin\")\n                .addType(TypeSpec.classBuilder(\"D\")\n                    .build())\n                .build())\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class A {\\n\"\n        + \"  class B {\\n\"\n        + \"    class C {\\n\"\n        + \"      Twin.D d;\\n\"\n        + \"\\n\"\n        + \"      class Nested {\\n\"\n        + \"        class Twin {\\n\"\n        + \"        }\\n\"\n        + \"      }\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  class Twin {\\n\"\n        + \"    class D {\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nestedClassAndSuperclassShareName() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .superclass(ClassName.get(\"com.squareup.wire\", \"Message\"))\n            .addType(TypeSpec.classBuilder(\"Builder\")\n                .superclass(ClassName.get(\"com.squareup.wire\", \"Message\", \"Builder\"))\n                .build())\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.squareup.wire.Message;\\n\"\n        + \"\\n\"\n        + \"class Taco extends Message {\\n\"\n        + \"  class Builder extends Message.Builder {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void classAndSuperclassShareName() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .superclass(ClassName.get(\"com.taco.bell\", \"Taco\"))\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco extends com.taco.bell.Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void conflictingAnnotation() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addAnnotation(ClassName.get(\"com.taco.bell\", \"Taco\"))\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"@com.taco.bell.Taco\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void conflictingAnnotationReferencedClass() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addAnnotation(AnnotationSpec.builder(ClassName.get(\"com.squareup.tacos\", \"MyAnno\"))\n                .addMember(\"value\", \"$T.class\", ClassName.get(\"com.taco.bell\", \"Taco\"))\n                .build())\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"@MyAnno(com.taco.bell.Taco.class)\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void conflictingTypeVariableBound() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addTypeVariable(\n                TypeVariableName.get(\"T\", ClassName.get(\"com.taco.bell\", \"Taco\")))\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco<T extends com.taco.bell.Taco> {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void superclassReferencesSelf() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .superclass(ParameterizedTypeName.get(\n                ClassName.get(Comparable.class), ClassName.get(\"com.squareup.tacos\", \"Taco\")))\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Comparable;\\n\"\n        + \"\\n\"\n        + \"class Taco extends Comparable<Taco> {\\n\"\n        + \"}\\n\");\n  }\n\n  /** https://github.com/square/javapoet/issues/366 */\n  @Test public void annotationIsNestedClass() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"TestComponent\")\n            .addAnnotation(ClassName.get(\"dagger\", \"Component\"))\n            .addType(TypeSpec.classBuilder(\"Builder\")\n                .addAnnotation(ClassName.get(\"dagger\", \"Component\", \"Builder\"))\n                .build())\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import dagger.Component;\\n\"\n        + \"\\n\"\n        + \"@Component\\n\"\n        + \"class TestComponent {\\n\"\n        + \"  @Component.Builder\\n\"\n        + \"  class Builder {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void defaultPackage() throws Exception {\n    String source = JavaFile.builder(\"\",\n        TypeSpec.classBuilder(\"HelloWorld\")\n            .addMethod(MethodSpec.methodBuilder(\"main\")\n                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n                .addParameter(String[].class, \"args\")\n                .addCode(\"$T.out.println($S);\\n\", System.class, \"Hello World!\")\n                .build())\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"import java.lang.String;\\n\"\n        + \"import java.lang.System;\\n\"\n        + \"\\n\"\n        + \"class HelloWorld {\\n\"\n        + \"  public static void main(String[] args) {\\n\"\n        + \"    System.out.println(\\\"Hello World!\\\");\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void defaultPackageTypesAreNotImported() throws Exception {\n    String source = JavaFile.builder(\"hello\",\n          TypeSpec.classBuilder(\"World\").addSuperinterface(ClassName.get(\"\", \"Test\")).build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package hello;\\n\"\n        + \"\\n\"\n        + \"class World implements Test {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void topOfFileComment() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\").build())\n        .addFileComment(\"Generated $L by JavaPoet. DO NOT EDIT!\", \"2015-01-13\")\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"// Generated 2015-01-13 by JavaPoet. DO NOT EDIT!\\n\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void emptyLinesInTopOfFileComment() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\").build())\n        .addFileComment(\"\\nGENERATED FILE:\\n\\nDO NOT EDIT!\\n\")\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"//\\n\"\n        + \"// GENERATED FILE:\\n\"\n        + \"//\\n\"\n        + \"// DO NOT EDIT!\\n\"\n        + \"//\\n\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void packageClassConflictsWithNestedClass() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addField(ClassName.get(\"com.squareup.tacos\", \"A\"), \"a\")\n            .addType(TypeSpec.classBuilder(\"A\").build())\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  com.squareup.tacos.A a;\\n\"\n        + \"\\n\"\n        + \"  class A {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void packageClassConflictsWithSuperlass() throws Exception {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .superclass(ClassName.get(\"com.taco.bell\", \"A\"))\n            .addField(ClassName.get(\"com.squareup.tacos\", \"A\"), \"a\")\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco extends com.taco.bell.A {\\n\"\n        + \"  A a;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void modifyStaticImports() throws Exception {\n    JavaFile.Builder builder = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .build())\n            .addStaticImport(File.class, \"separator\");\n\n    builder.staticImports.clear();\n    builder.staticImports.add(File.class.getCanonicalName() + \".separatorChar\");\n\n    String source = builder.build().toString();\n\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import static java.io.File.separatorChar;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void alwaysQualifySimple() {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addField(Thread.class, \"thread\")\n            .alwaysQualify(\"Thread\")\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  java.lang.Thread thread;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void alwaysQualifySupersedesJavaLangImports() {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            .addField(Thread.class, \"thread\")\n            .alwaysQualify(\"Thread\")\n            .build())\n        .skipJavaLangImports(true)\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  java.lang.Thread thread;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void avoidClashesWithNestedClasses_viaClass() {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            // These two should get qualified\n            .addField(ClassName.get(\"other\", \"NestedTypeA\"), \"nestedA\")\n            .addField(ClassName.get(\"other\", \"NestedTypeB\"), \"nestedB\")\n            // This one shouldn't since it's not a nested type of Foo\n            .addField(ClassName.get(\"other\", \"NestedTypeC\"), \"nestedC\")\n            // This one shouldn't since we only look at nested types\n            .addField(ClassName.get(\"other\", \"Foo\"), \"foo\")\n            .avoidClashesWithNestedClasses(Foo.class)\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import other.Foo;\\n\"\n        + \"import other.NestedTypeC;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  other.NestedTypeA nestedA;\\n\"\n        + \"\\n\"\n        + \"  other.NestedTypeB nestedB;\\n\"\n        + \"\\n\"\n        + \"  NestedTypeC nestedC;\\n\"\n        + \"\\n\"\n        + \"  Foo foo;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void avoidClashesWithNestedClasses_viaTypeElement() {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            // These two should get qualified\n            .addField(ClassName.get(\"other\", \"NestedTypeA\"), \"nestedA\")\n            .addField(ClassName.get(\"other\", \"NestedTypeB\"), \"nestedB\")\n            // This one shouldn't since it's not a nested type of Foo\n            .addField(ClassName.get(\"other\", \"NestedTypeC\"), \"nestedC\")\n            // This one shouldn't since we only look at nested types\n            .addField(ClassName.get(\"other\", \"Foo\"), \"foo\")\n            .avoidClashesWithNestedClasses(getElement(Foo.class))\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import other.Foo;\\n\"\n        + \"import other.NestedTypeC;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  other.NestedTypeA nestedA;\\n\"\n        + \"\\n\"\n        + \"  other.NestedTypeB nestedB;\\n\"\n        + \"\\n\"\n        + \"  NestedTypeC nestedC;\\n\"\n        + \"\\n\"\n        + \"  Foo foo;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void avoidClashesWithNestedClasses_viaSuperinterfaceType() {\n    String source = JavaFile.builder(\"com.squareup.tacos\",\n        TypeSpec.classBuilder(\"Taco\")\n            // These two should get qualified\n            .addField(ClassName.get(\"other\", \"NestedTypeA\"), \"nestedA\")\n            .addField(ClassName.get(\"other\", \"NestedTypeB\"), \"nestedB\")\n            // This one shouldn't since it's not a nested type of Foo\n            .addField(ClassName.get(\"other\", \"NestedTypeC\"), \"nestedC\")\n            // This one shouldn't since we only look at nested types\n            .addField(ClassName.get(\"other\", \"Foo\"), \"foo\")\n            .addType(TypeSpec.classBuilder(\"NestedTypeA\").build())\n            .addType(TypeSpec.classBuilder(\"NestedTypeB\").build())\n            .addSuperinterface(FooInterface.class)\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.squareup.javapoet.JavaFileTest;\\n\"\n        + \"import other.Foo;\\n\"\n        + \"import other.NestedTypeC;\\n\"\n        + \"\\n\"\n        + \"class Taco implements JavaFileTest.FooInterface {\\n\"\n        + \"  other.NestedTypeA nestedA;\\n\"\n        + \"\\n\"\n        + \"  other.NestedTypeB nestedB;\\n\"\n        + \"\\n\"\n        + \"  NestedTypeC nestedC;\\n\"\n        + \"\\n\"\n        + \"  Foo foo;\\n\"\n        + \"\\n\"\n        + \"  class NestedTypeA {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  class NestedTypeB {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  static class Foo {\n    static class NestedTypeA {\n\n    }\n    static class NestedTypeB {\n\n    }\n  }\n\n  interface FooInterface {\n    class NestedTypeA {\n\n    }\n    class NestedTypeB {\n\n    }\n  }\n\n  private TypeSpec.Builder childTypeBuilder() {\n    return TypeSpec.classBuilder(\"Child\")\n        .addMethod(MethodSpec.methodBuilder(\"optionalString\")\n            .returns(ParameterizedTypeName.get(Optional.class, String.class))\n            .addStatement(\"return $T.empty()\", Optional.class)\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"pattern\")\n            .returns(Pattern.class)\n            .addStatement(\"return null\")\n            .build());\n  }\n\n  @Test\n  public void avoidClashes_parentChild_superclass_type() {\n    String source = JavaFile.builder(\"com.squareup.javapoet\",\n        childTypeBuilder().superclass(Parent.class).build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"package com.squareup.javapoet;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Child extends JavaFileTest.Parent {\\n\"\n        + \"  java.util.Optional<String> optionalString() {\\n\"\n        + \"    return java.util.Optional.empty();\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  java.util.regex.Pattern pattern() {\\n\"\n        + \"    return null;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test\n  public void avoidClashes_parentChild_superclass_typeMirror() {\n    String source = JavaFile.builder(\"com.squareup.javapoet\",\n        childTypeBuilder().superclass(getElement(Parent.class).asType()).build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"package com.squareup.javapoet;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Child extends JavaFileTest.Parent {\\n\"\n        + \"  java.util.Optional<String> optionalString() {\\n\"\n        + \"    return java.util.Optional.empty();\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  java.util.regex.Pattern pattern() {\\n\"\n        + \"    return null;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test\n  public void avoidClashes_parentChild_superinterface_type() {\n    String source = JavaFile.builder(\"com.squareup.javapoet\",\n        childTypeBuilder().addSuperinterface(ParentInterface.class).build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"package com.squareup.javapoet;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"import java.util.regex.Pattern;\\n\"\n        + \"\\n\"\n        + \"class Child implements JavaFileTest.ParentInterface {\\n\"\n        + \"  java.util.Optional<String> optionalString() {\\n\"\n        + \"    return java.util.Optional.empty();\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  Pattern pattern() {\\n\"\n        + \"    return null;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test\n  public void avoidClashes_parentChild_superinterface_typeMirror() {\n    String source = JavaFile.builder(\"com.squareup.javapoet\",\n        childTypeBuilder().addSuperinterface(getElement(ParentInterface.class).asType()).build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"package com.squareup.javapoet;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"import java.util.regex.Pattern;\\n\"\n        + \"\\n\"\n        + \"class Child implements JavaFileTest.ParentInterface {\\n\"\n        + \"  java.util.Optional<String> optionalString() {\\n\"\n        + \"    return java.util.Optional.empty();\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  Pattern pattern() {\\n\"\n        + \"    return null;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  // Regression test for https://github.com/square/javapoet/issues/77\n  // This covers class and inheritance\n  static class Parent implements ParentInterface {\n    static class Pattern {\n\n    }\n  }\n\n  interface ParentInterface {\n    class Optional {\n\n    }\n  }\n\n  // Regression test for case raised here: https://github.com/square/javapoet/issues/77#issuecomment-519972404\n  @Test\n  public void avoidClashes_mapEntry() {\n    String source = JavaFile.builder(\"com.squareup.javapoet\",\n        TypeSpec.classBuilder(\"MapType\")\n            .addMethod(MethodSpec.methodBuilder(\"optionalString\")\n                .returns(ClassName.get(\"com.foo\", \"Entry\"))\n                .addStatement(\"return null\")\n                .build())\n            .addSuperinterface(Map.class)\n            .build())\n        .build()\n        .toString();\n    assertThat(source).isEqualTo(\"package com.squareup.javapoet;\\n\"\n        + \"\\n\"\n        + \"import java.util.Map;\\n\"\n        + \"\\n\"\n        + \"class MapType implements Map {\\n\"\n        + \"  com.foo.Entry optionalString() {\\n\"\n        + \"    return null;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/LineWrapperTest.java",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic final class LineWrapperTest {\n  @Test public void wrap() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"fghij\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcde\\n    fghij\");\n  }\n\n  @Test public void noWrap() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"fghi\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcde fghi\");\n  }\n\n  @Test public void zeroWidthNoWrap() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.zeroWidthSpace(2);\n    lineWrapper.append(\"fghij\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcdefghij\");\n  }\n\n  @Test public void nospaceWrapMax() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.zeroWidthSpace(2);\n    lineWrapper.append(\"fghijk\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcde\\n    fghijk\");\n  }\n\n  @Test public void multipleWrite() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"ab\");\n    lineWrapper.wrappingSpace(1);\n    lineWrapper.append(\"cd\");\n    lineWrapper.wrappingSpace(1);\n    lineWrapper.append(\"ef\");\n    lineWrapper.wrappingSpace(1);\n    lineWrapper.append(\"gh\");\n    lineWrapper.wrappingSpace(1);\n    lineWrapper.append(\"ij\");\n    lineWrapper.wrappingSpace(1);\n    lineWrapper.append(\"kl\");\n    lineWrapper.wrappingSpace(1);\n    lineWrapper.append(\"mn\");\n    lineWrapper.wrappingSpace(1);\n    lineWrapper.append(\"op\");\n    lineWrapper.wrappingSpace(1);\n    lineWrapper.append(\"qr\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"ab cd ef\\n  gh ij kl\\n  mn op qr\");\n  }\n\n  @Test public void fencepost() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.append(\"fghij\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"k\");\n    lineWrapper.append(\"lmnop\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcdefghij\\n    klmnop\");\n  }\n\n  @Test public void fencepostZeroWidth() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.append(\"fghij\");\n    lineWrapper.zeroWidthSpace(2);\n    lineWrapper.append(\"k\");\n    lineWrapper.append(\"lmnop\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcdefghij\\n    klmnop\");\n  }\n\n  @Test public void overlyLongLinesWithoutLeadingSpace() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcdefghijkl\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcdefghijkl\");\n  }\n\n  @Test public void overlyLongLinesWithLeadingSpace() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"abcdefghijkl\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"\\n    abcdefghijkl\");\n  }\n\n  @Test public void overlyLongLinesWithLeadingZeroWidth() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.zeroWidthSpace(2);\n    lineWrapper.append(\"abcdefghijkl\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcdefghijkl\");\n  }\n\n  @Test public void noWrapEmbeddedNewlines() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"fghi\\njklmn\");\n    lineWrapper.append(\"opqrstuvwxy\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcde fghi\\njklmnopqrstuvwxy\");\n  }\n\n  @Test public void wrapEmbeddedNewlines() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"fghij\\nklmn\");\n    lineWrapper.append(\"opqrstuvwxy\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcde\\n    fghij\\nklmnopqrstuvwxy\");\n  }\n\n  @Test public void noWrapEmbeddedNewlines_ZeroWidth() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.zeroWidthSpace(2);\n    lineWrapper.append(\"fghij\\nklmn\");\n    lineWrapper.append(\"opqrstuvwxyz\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcdefghij\\nklmnopqrstuvwxyz\");\n  }\n\n  @Test public void wrapEmbeddedNewlines_ZeroWidth() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.zeroWidthSpace(2);\n    lineWrapper.append(\"fghijk\\nlmn\");\n    lineWrapper.append(\"opqrstuvwxy\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcde\\n    fghijk\\nlmnopqrstuvwxy\");\n  }\n\n  @Test public void noWrapMultipleNewlines() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"fghi\\nklmnopq\\nr\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"stuvwxyz\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcde fghi\\nklmnopq\\nr stuvwxyz\");\n  }\n\n  @Test public void wrapMultipleNewlines() throws Exception {\n    StringBuffer out = new StringBuffer();\n    LineWrapper lineWrapper = new LineWrapper(out, \"  \", 10);\n    lineWrapper.append(\"abcde\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"fghi\\nklmnopq\\nrs\");\n    lineWrapper.wrappingSpace(2);\n    lineWrapper.append(\"tuvwxyz1\");\n    lineWrapper.close();\n    assertThat(out.toString()).isEqualTo(\"abcde fghi\\nklmnopq\\nrs\\n    tuvwxyz1\");\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/MethodSpecTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport com.google.testing.compile.Compilation;\nimport com.google.testing.compile.CompilationRule;\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Target;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.TimeoutException;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.util.ElementFilter;\nimport javax.lang.model.util.Elements;\nimport javax.lang.model.util.Types;\nimport javax.tools.JavaFileObject;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\n\nimport static com.google.common.collect.Iterables.getOnlyElement;\nimport static com.google.common.truth.Truth.assertThat;\nimport static com.google.testing.compile.CompilationSubject.assertThat;\nimport static com.google.testing.compile.Compiler.javac;\nimport static com.squareup.javapoet.TestUtil.findFirst;\nimport static javax.lang.model.util.ElementFilter.methodsIn;\nimport static org.junit.Assert.fail;\n\npublic final class MethodSpecTest {\n  @Rule public final CompilationRule compilation = new CompilationRule();\n\n  private Elements elements;\n  private Types types;\n\n  @Before public void setUp() {\n    elements = compilation.getElements();\n    types = compilation.getTypes();\n  }\n\n  private TypeElement getElement(Class<?> clazz) {\n    return elements.getTypeElement(clazz.getCanonicalName());\n  }\n\n  @Test public void nullAnnotationsAddition() {\n    try {\n      MethodSpec.methodBuilder(\"doSomething\").addAnnotations(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"annotationSpecs == null\");\n    }\n  }\n\n  @Test public void nullTypeVariablesAddition() {\n    try {\n      MethodSpec.methodBuilder(\"doSomething\").addTypeVariables(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"typeVariables == null\");\n    }\n  }\n\n  @Test public void nullParametersAddition() {\n    try {\n      MethodSpec.methodBuilder(\"doSomething\").addParameters(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"parameterSpecs == null\");\n    }\n  }\n\n  @Test public void nullExceptionsAddition() {\n    try {\n      MethodSpec.methodBuilder(\"doSomething\").addExceptions(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"exceptions == null\");\n    }\n  }\n\n  @Target(ElementType.PARAMETER)\n  @interface Nullable {\n  }\n\n  abstract static class Everything {\n    @Deprecated protected abstract <T extends Runnable & Closeable> Runnable everything(\n        @Nullable String thing, List<? extends T> things) throws IOException, SecurityException;\n  }\n\n  abstract static class Generics {\n    <T, R, V extends Throwable> T run(R param) throws V {\n      return null;\n    }\n  }\n\n  abstract static class HasAnnotation {\n    @Override public abstract String toString();\n  }\n\n  interface Throws<R extends RuntimeException> {\n    void fail() throws R;\n  }\n\n  interface ExtendsOthers extends Callable<Integer>, Comparable<ExtendsOthers>,\n      Throws<IllegalStateException> {\n  }\n\n  interface ExtendsIterableWithDefaultMethods extends Iterable<Object> {\n  }\n\n  final class FinalClass {\n    void method() {\n    }\n  }\n\n  abstract static class InvalidOverrideMethods {\n    final void finalMethod() {\n    }\n\n    private void privateMethod() {\n    }\n\n    static void staticMethod() {\n    }\n  }\n\n  @Test public void overrideEverything() {\n    TypeElement classElement = getElement(Everything.class);\n    ExecutableElement methodElement = getOnlyElement(methodsIn(classElement.getEnclosedElements()));\n    MethodSpec method = MethodSpec.overriding(methodElement).build();\n    assertThat(method.toString()).isEqualTo(\"\"\n        + \"@java.lang.Override\\n\"\n        + \"protected <T extends java.lang.Runnable & java.io.Closeable> java.lang.Runnable \"\n        + \"everything(\\n\"\n        + \"    java.lang.String arg0, java.util.List<? extends T> arg1) throws java.io.IOException,\\n\"\n        + \"    java.lang.SecurityException {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void overrideGenerics() {\n    TypeElement classElement = getElement(Generics.class);\n    ExecutableElement methodElement = getOnlyElement(methodsIn(classElement.getEnclosedElements()));\n    MethodSpec method = MethodSpec.overriding(methodElement)\n        .addStatement(\"return null\")\n        .build();\n    assertThat(method.toString()).isEqualTo(\"\"\n        + \"@java.lang.Override\\n\"\n        + \"<T, R, V extends java.lang.Throwable> T run(R param) throws V {\\n\"\n        + \"  return null;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void overrideDoesNotCopyOverrideAnnotation() {\n    TypeElement classElement = getElement(HasAnnotation.class);\n    ExecutableElement exec = getOnlyElement(methodsIn(classElement.getEnclosedElements()));\n    MethodSpec method = MethodSpec.overriding(exec).build();\n    assertThat(method.toString()).isEqualTo(\"\"\n        + \"@java.lang.Override\\n\"\n        + \"public java.lang.String toString() {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void overrideDoesNotCopyDefaultModifier() {\n    TypeElement classElement = getElement(ExtendsIterableWithDefaultMethods.class);\n    DeclaredType classType = (DeclaredType) classElement.asType();\n    List<ExecutableElement> methods = methodsIn(elements.getAllMembers(classElement));\n    ExecutableElement exec = findFirst(methods, \"spliterator\");\n    MethodSpec method = MethodSpec.overriding(exec, classType, types).build();\n    assertThat(method.toString()).isEqualTo(\"\"\n        + \"@java.lang.Override\\n\"\n        + \"public java.util.Spliterator<java.lang.Object> spliterator() {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void overrideExtendsOthersWorksWithActualTypeParameters() {\n    TypeElement classElement = getElement(ExtendsOthers.class);\n    DeclaredType classType = (DeclaredType) classElement.asType();\n    List<ExecutableElement> methods = methodsIn(elements.getAllMembers(classElement));\n    ExecutableElement exec = findFirst(methods, \"call\");\n    MethodSpec method = MethodSpec.overriding(exec, classType, types).build();\n    assertThat(method.toString()).isEqualTo(\"\"\n        + \"@java.lang.Override\\n\"\n        + \"public java.lang.Integer call() throws java.lang.Exception {\\n\"\n        + \"}\\n\");\n    exec = findFirst(methods, \"compareTo\");\n    method = MethodSpec.overriding(exec, classType, types).build();\n    assertThat(method.toString()).isEqualTo(\"\"\n        + \"@java.lang.Override\\n\"\n        + \"public int compareTo(\" + ExtendsOthers.class.getCanonicalName() + \" arg0) {\\n\"\n        + \"}\\n\");\n    exec = findFirst(methods, \"fail\");\n    method = MethodSpec.overriding(exec, classType, types).build();\n    assertThat(method.toString()).isEqualTo(\"\"\n        + \"@java.lang.Override\\n\"\n        + \"public void fail() throws java.lang.IllegalStateException {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void overrideFinalClassMethod() {\n    TypeElement classElement = getElement(FinalClass.class);\n    List<ExecutableElement> methods = methodsIn(elements.getAllMembers(classElement));\n    try {\n      MethodSpec.overriding(findFirst(methods, \"method\"));\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\n          \"Cannot override method on final class com.squareup.javapoet.MethodSpecTest.FinalClass\");\n    }\n  }\n\n  @Test public void overrideInvalidModifiers() {\n    TypeElement classElement = getElement(InvalidOverrideMethods.class);\n    List<ExecutableElement> methods = methodsIn(elements.getAllMembers(classElement));\n    try {\n      MethodSpec.overriding(findFirst(methods, \"finalMethod\"));\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"cannot override method with modifiers: [final]\");\n    }\n    try {\n      MethodSpec.overriding(findFirst(methods, \"privateMethod\"));\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"cannot override method with modifiers: [private]\");\n    }\n    try {\n      MethodSpec.overriding(findFirst(methods, \"staticMethod\"));\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"cannot override method with modifiers: [static]\");\n    }\n  }\n\n  abstract static class AbstractClassWithPrivateAnnotation {\n\n    private @interface PrivateAnnotation{ }\n\n    abstract void foo(@PrivateAnnotation final String bar);\n  }\n\n  @Test public void overrideDoesNotCopyParameterAnnotations() {\n    TypeElement abstractTypeElement = getElement(AbstractClassWithPrivateAnnotation.class);\n    ExecutableElement fooElement = ElementFilter.methodsIn(abstractTypeElement.getEnclosedElements()).get(0);\n    ClassName implClassName = ClassName.get(\"com.squareup.javapoet\", \"Impl\");\n    TypeSpec type = TypeSpec.classBuilder(implClassName)\n            .superclass(abstractTypeElement.asType())\n            .addMethod(MethodSpec.overriding(fooElement).build())\n            .build();\n    JavaFileObject jfo = JavaFile.builder(implClassName.packageName, type).build().toJavaFileObject();\n    Compilation compilation = javac().compile(jfo);\n    assertThat(compilation).succeeded();\n  }\n\n  @Test public void equalsAndHashCode() {\n    MethodSpec a = MethodSpec.constructorBuilder().build();\n    MethodSpec b = MethodSpec.constructorBuilder().build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    a = MethodSpec.methodBuilder(\"taco\").build();\n    b = MethodSpec.methodBuilder(\"taco\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    TypeElement classElement = getElement(Everything.class);\n    ExecutableElement methodElement = getOnlyElement(methodsIn(classElement.getEnclosedElements()));\n    a = MethodSpec.overriding(methodElement).build();\n    b = MethodSpec.overriding(methodElement).build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n  }\n\n  @Test public void withoutParameterJavaDoc() {\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"getTaco\")\n        .addModifiers(Modifier.PRIVATE)\n        .addParameter(TypeName.DOUBLE, \"money\")\n        .addJavadoc(\"Gets the best Taco\\n\")\n        .build();\n    assertThat(methodSpec.toString()).isEqualTo(\"\"\n        + \"/**\\n\"\n        + \" * Gets the best Taco\\n\"\n        + \" */\\n\"\n        + \"private void getTaco(double money) {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void withParameterJavaDoc() {\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"getTaco\")\n        .addParameter(ParameterSpec.builder(TypeName.DOUBLE, \"money\")\n            .addJavadoc(\"the amount required to buy the taco.\\n\")\n            .build())\n        .addParameter(ParameterSpec.builder(TypeName.INT, \"count\")\n            .addJavadoc(\"the number of Tacos to buy.\\n\")\n            .build())\n        .addJavadoc(\"Gets the best Taco money can buy.\\n\")\n        .build();\n    assertThat(methodSpec.toString()).isEqualTo(\"\"\n        + \"/**\\n\"\n        + \" * Gets the best Taco money can buy.\\n\"\n        + \" *\\n\"\n        + \" * @param money the amount required to buy the taco.\\n\"\n        + \" * @param count the number of Tacos to buy.\\n\"\n        + \" */\\n\"\n        + \"void getTaco(double money, int count) {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void withParameterJavaDocAndWithoutMethodJavadoc() {\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"getTaco\")\n        .addParameter(ParameterSpec.builder(TypeName.DOUBLE, \"money\")\n            .addJavadoc(\"the amount required to buy the taco.\\n\")\n            .build())\n        .addParameter(ParameterSpec.builder(TypeName.INT, \"count\")\n            .addJavadoc(\"the number of Tacos to buy.\\n\")\n            .build())\n        .build();\n    assertThat(methodSpec.toString()).isEqualTo(\"\"\n        + \"/**\\n\"\n        + \" * @param money the amount required to buy the taco.\\n\"\n        + \" * @param count the number of Tacos to buy.\\n\"\n        + \" */\\n\"\n        + \"void getTaco(double money, int count) {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void duplicateExceptionsIgnored() {\n    ClassName ioException = ClassName.get(IOException.class);\n    ClassName timeoutException = ClassName.get(TimeoutException.class);\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"duplicateExceptions\")\n      .addException(ioException)\n      .addException(timeoutException)\n      .addException(timeoutException)\n      .addException(ioException)\n      .build();\n    assertThat(methodSpec.exceptions).isEqualTo(Arrays.asList(ioException, timeoutException));\n    assertThat(methodSpec.toBuilder().addException(ioException).build().exceptions)\n      .isEqualTo(Arrays.asList(ioException, timeoutException));\n  }\n\n  @Test public void nullIsNotAValidMethodName() {\n    try {\n      MethodSpec.methodBuilder(null);\n      fail(\"NullPointerException expected\");\n    } catch (NullPointerException e) {\n      assertThat(e.getMessage()).isEqualTo(\"name == null\");\n    }\n  }\n\n  @Test public void addModifiersVarargsShouldNotBeNull() {\n    try {\n      MethodSpec.methodBuilder(\"taco\")\n              .addModifiers((Modifier[]) null);\n      fail(\"NullPointerException expected\");\n    } catch (NullPointerException e) {\n      assertThat(e.getMessage()).isEqualTo(\"modifiers == null\");\n    }\n  }\n\n  @Test public void modifyMethodName() {\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"initialMethod\")\n        .build()\n        .toBuilder()\n        .setName(\"revisedMethod\")\n        .build();\n\n    assertThat(methodSpec.toString()).isEqualTo(\"\" + \"void revisedMethod() {\\n\" + \"}\\n\");\n  }\n\n  @Test public void modifyAnnotations() {\n    MethodSpec.Builder builder = MethodSpec.methodBuilder(\"foo\")\n            .addAnnotation(Override.class)\n            .addAnnotation(SuppressWarnings.class);\n\n    builder.annotations.remove(1);\n    assertThat(builder.build().annotations).hasSize(1);\n  }\n\n  @Test public void modifyModifiers() {\n    MethodSpec.Builder builder = MethodSpec.methodBuilder(\"foo\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC);\n\n    builder.modifiers.remove(1);\n    assertThat(builder.build().modifiers).containsExactly(Modifier.PUBLIC);\n  }\n\n  @Test public void modifyParameters() {\n    MethodSpec.Builder builder = MethodSpec.methodBuilder(\"foo\")\n            .addParameter(int.class, \"source\");\n\n    builder.parameters.remove(0);\n    assertThat(builder.build().parameters).isEmpty();\n  }\n\n  @Test public void modifyTypeVariables() {\n    TypeVariableName t = TypeVariableName.get(\"T\");\n    MethodSpec.Builder builder = MethodSpec.methodBuilder(\"foo\")\n            .addTypeVariable(t)\n            .addTypeVariable(TypeVariableName.get(\"V\"));\n\n    builder.typeVariables.remove(1);\n    assertThat(builder.build().typeVariables).containsExactly(t);\n  }\n\n  @Test public void ensureTrailingNewline() {\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"method\")\n        .addCode(\"codeWithNoNewline();\")\n        .build();\n\n    assertThat(methodSpec.toString()).isEqualTo(\"\"\n        + \"void method() {\\n\"\n        + \"  codeWithNoNewline();\\n\"\n        + \"}\\n\");\n  }\n\n  /** Ensures that we don't add a duplicate newline if one is already present. */\n  @Test public void ensureTrailingNewlineWithExistingNewline() {\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"method\")\n        .addCode(\"codeWithNoNewline();\\n\") // Have a newline already, so ensure we're not adding one\n        .build();\n\n    assertThat(methodSpec.toString()).isEqualTo(\"\"\n        + \"void method() {\\n\"\n        + \"  codeWithNoNewline();\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void controlFlowWithNamedCodeBlocks() {\n    Map<String, Object> m = new HashMap<>();\n    m.put(\"field\", \"valueField\");\n    m.put(\"threshold\", \"5\");\n\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"method\")\n        .beginControlFlow(named(\"if ($field:N > $threshold:L)\", m))\n        .nextControlFlow(named(\"else if ($field:N == $threshold:L)\", m))\n        .endControlFlow()\n        .build();\n\n    assertThat(methodSpec.toString()).isEqualTo(\"\"\n        + \"void method() {\\n\"\n        + \"  if (valueField > 5) {\\n\"\n        + \"  } else if (valueField == 5) {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void doWhileWithNamedCodeBlocks() {\n    Map<String, Object> m = new HashMap<>();\n    m.put(\"field\", \"valueField\");\n    m.put(\"threshold\", \"5\");\n\n    MethodSpec methodSpec = MethodSpec.methodBuilder(\"method\")\n        .beginControlFlow(\"do\")\n        .addStatement(named(\"$field:N--\", m))\n        .endControlFlow(named(\"while ($field:N > $threshold:L)\", m))\n        .build();\n\n    assertThat(methodSpec.toString()).isEqualTo(\"\"\n        + \"void method() {\\n\" +\n        \"  do {\\n\" +\n        \"    valueField--;\\n\" +\n        \"  } while (valueField > 5);\\n\" +\n        \"}\\n\");\n  }\n\n  private static CodeBlock named(String format, Map<String, ?> args){\n    return CodeBlock.builder().addNamed(format, args).build();\n  }\n\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/NameAllocatorTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\npublic final class NameAllocatorTest {\n\n  @Test public void usage() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    assertThat(nameAllocator.newName(\"foo\", 1)).isEqualTo(\"foo\");\n    assertThat(nameAllocator.newName(\"bar\", 2)).isEqualTo(\"bar\");\n    assertThat(nameAllocator.get(1)).isEqualTo(\"foo\");\n    assertThat(nameAllocator.get(2)).isEqualTo(\"bar\");\n  }\n\n  @Test public void nameCollision() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    assertThat(nameAllocator.newName(\"foo\")).isEqualTo(\"foo\");\n    assertThat(nameAllocator.newName(\"foo\")).isEqualTo(\"foo_\");\n    assertThat(nameAllocator.newName(\"foo\")).isEqualTo(\"foo__\");\n  }\n\n  @Test public void nameCollisionWithTag() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    assertThat(nameAllocator.newName(\"foo\", 1)).isEqualTo(\"foo\");\n    assertThat(nameAllocator.newName(\"foo\", 2)).isEqualTo(\"foo_\");\n    assertThat(nameAllocator.newName(\"foo\", 3)).isEqualTo(\"foo__\");\n    assertThat(nameAllocator.get(1)).isEqualTo(\"foo\");\n    assertThat(nameAllocator.get(2)).isEqualTo(\"foo_\");\n    assertThat(nameAllocator.get(3)).isEqualTo(\"foo__\");\n  }\n\n  @Test public void characterMappingSubstitute() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    assertThat(nameAllocator.newName(\"a-b\", 1)).isEqualTo(\"a_b\");\n  }\n\n  @Test public void characterMappingSurrogate() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    assertThat(nameAllocator.newName(\"a\\uD83C\\uDF7Ab\", 1)).isEqualTo(\"a_b\");\n  }\n\n  @Test public void characterMappingInvalidStartButValidPart() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    assertThat(nameAllocator.newName(\"1ab\", 1)).isEqualTo(\"_1ab\");\n    assertThat(nameAllocator.newName(\"a-1\", 2)).isEqualTo(\"a_1\");\n  }\n\n  @Test public void characterMappingInvalidStartIsInvalidPart() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    assertThat(nameAllocator.newName(\"&ab\", 1)).isEqualTo(\"_ab\");\n  }\n\n  @Test public void javaKeyword() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    assertThat(nameAllocator.newName(\"public\", 1)).isEqualTo(\"public_\");\n    assertThat(nameAllocator.get(1)).isEqualTo(\"public_\");\n  }\n\n  @Test public void tagReuseForbidden() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    nameAllocator.newName(\"foo\", 1);\n    try {\n      nameAllocator.newName(\"bar\", 1);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"tag 1 cannot be used for both 'foo' and 'bar'\");\n    }\n  }\n\n  @Test public void useBeforeAllocateForbidden() throws Exception {\n    NameAllocator nameAllocator = new NameAllocator();\n    try {\n      nameAllocator.get(1);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"unknown tag: 1\");\n    }\n  }\n\n  @Test public void cloneUsage() throws Exception {\n    NameAllocator outterAllocator = new NameAllocator();\n    outterAllocator.newName(\"foo\", 1);\n\n    NameAllocator innerAllocator1 = outterAllocator.clone();\n    assertThat(innerAllocator1.newName(\"bar\", 2)).isEqualTo(\"bar\");\n    assertThat(innerAllocator1.newName(\"foo\", 3)).isEqualTo(\"foo_\");\n\n    NameAllocator innerAllocator2 = outterAllocator.clone();\n    assertThat(innerAllocator2.newName(\"foo\", 2)).isEqualTo(\"foo_\");\n    assertThat(innerAllocator2.newName(\"bar\", 3)).isEqualTo(\"bar\");\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/ParameterSpecTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport com.google.testing.compile.CompilationRule;\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nullable;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.element.VariableElement;\nimport javax.lang.model.util.Elements;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport javax.lang.model.element.Modifier;\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static com.squareup.javapoet.TestUtil.findFirst;\nimport static javax.lang.model.util.ElementFilter.fieldsIn;\nimport static javax.lang.model.util.ElementFilter.methodsIn;\nimport static org.junit.Assert.fail;\n\npublic class ParameterSpecTest {\n  @Rule public final CompilationRule compilation = new CompilationRule();\n\n  private Elements elements;\n\n  @Before public void setUp() {\n    elements = compilation.getElements();\n  }\n\n  private TypeElement getElement(Class<?> clazz) {\n    return elements.getTypeElement(clazz.getCanonicalName());\n  }\n\n  @Test public void equalsAndHashCode() {\n    ParameterSpec a = ParameterSpec.builder(int.class, \"foo\").build();\n    ParameterSpec b = ParameterSpec.builder(int.class, \"foo\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    assertThat(a.toString()).isEqualTo(b.toString());\n    a = ParameterSpec.builder(int.class, \"i\").addModifiers(Modifier.STATIC).build();\n    b = ParameterSpec.builder(int.class, \"i\").addModifiers(Modifier.STATIC).build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    assertThat(a.toString()).isEqualTo(b.toString());\n  }\n\n  @Test public void receiverParameterInstanceMethod() {\n    ParameterSpec.Builder builder = ParameterSpec.builder(int.class, \"this\");\n    assertThat(builder.build().name).isEqualTo(\"this\");\n  }\n\n  @Test public void receiverParameterNestedClass() {\n    ParameterSpec.Builder builder = ParameterSpec.builder(int.class, \"Foo.this\");\n    assertThat(builder.build().name).isEqualTo(\"Foo.this\");\n  }\n\n  @Test public void keywordName() {\n    try {\n      ParameterSpec.builder(int.class, \"super\");\n      fail();\n    } catch (Exception e) {\n      assertThat(e.getMessage()).isEqualTo(\"not a valid name: super\");\n    }\n  }\n\n  @Test public void nullAnnotationsAddition() {\n    try {\n      ParameterSpec.builder(int.class, \"foo\").addAnnotations(null);\n      fail();\n    } catch (Exception e) {\n      assertThat(e.getMessage())\n          .isEqualTo(\"annotationSpecs == null\");\n    }\n  }\n\n  final class VariableElementFieldClass {\n    String name;\n  }\n\n  @Test public void fieldVariableElement() {\n    TypeElement classElement = getElement(VariableElementFieldClass.class);\n    List<VariableElement> methods = fieldsIn(elements.getAllMembers(classElement));\n    VariableElement element = findFirst(methods, \"name\");\n\n    try {\n      ParameterSpec.get(element);\n      fail();\n    } catch (IllegalArgumentException exception) {\n      assertThat(exception).hasMessageThat().isEqualTo(\"element is not a parameter\");\n    }\n  }\n\n  final class VariableElementParameterClass {\n    public void foo(@Nullable final String bar) {\n    }\n  }\n\n  @Test public void parameterVariableElement() {\n    TypeElement classElement = getElement(VariableElementParameterClass.class);\n    List<ExecutableElement> methods = methodsIn(elements.getAllMembers(classElement));\n    ExecutableElement element = findFirst(methods, \"foo\");\n    VariableElement parameterElement = element.getParameters().get(0);\n\n    assertThat(ParameterSpec.get(parameterElement).toString())\n        .isEqualTo(\"java.lang.String arg0\");\n  }\n\n  @Test public void addNonFinalModifier() {\n    List<Modifier> modifiers = new ArrayList<>();\n    modifiers.add(Modifier.FINAL);\n    modifiers.add(Modifier.PUBLIC);\n\n    try {\n      ParameterSpec.builder(int.class, \"foo\")\n          .addModifiers(modifiers);\n      fail();\n    } catch (Exception e) {\n      assertThat(e.getMessage()).isEqualTo(\"unexpected parameter modifier: public\");\n    }\n  }\n\n  @Test public void modifyAnnotations() {\n    ParameterSpec.Builder builder = ParameterSpec.builder(int.class, \"foo\")\n            .addAnnotation(Override.class)\n            .addAnnotation(SuppressWarnings.class);\n\n    builder.annotations.remove(1);\n    assertThat(builder.build().annotations).hasSize(1);\n  }\n\n  @Test public void modifyModifiers() {\n    ParameterSpec.Builder builder = ParameterSpec.builder(int.class, \"foo\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC);\n\n    builder.modifiers.remove(1);\n    assertThat(builder.build().modifiers).containsExactly(Modifier.PUBLIC);\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/TestFiler.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.nio.file.FileSystem;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.spi.FileSystemProvider;\nimport java.util.Arrays;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.annotation.processing.Filer;\nimport javax.lang.model.element.Element;\nimport javax.tools.FileObject;\nimport javax.tools.JavaFileManager;\nimport javax.tools.JavaFileObject;\nimport javax.tools.SimpleJavaFileObject;\n\nfinal class TestFiler implements Filer {\n  class Source extends SimpleJavaFileObject {\n    private final Path path;\n    protected Source(Path path) {\n      super(path.toUri(), Kind.SOURCE);\n      this.path = path;\n    }\n    @Override public OutputStream openOutputStream() throws IOException {\n      Path parent = path.getParent();\n      if (!Files.exists(parent)) fileSystemProvider.createDirectory(parent);\n      return fileSystemProvider.newOutputStream(path);\n    }\n  }\n\n  private final String separator;\n  private final Path fileSystemRoot;\n  private final FileSystemProvider fileSystemProvider;\n  private final Map<Path, Set<Element>> originatingElementsMap;\n\n  public TestFiler(FileSystem fileSystem, Path fsRoot) {\n    separator = fileSystem.getSeparator();\n    fileSystemRoot = fsRoot;\n    fileSystemProvider = fileSystem.provider();\n    originatingElementsMap = new LinkedHashMap<>();\n  }\n\n  public Set<Element> getOriginatingElements(Path path) {\n    return originatingElementsMap.get(path);\n  }\n\n  @Override public JavaFileObject createSourceFile(\n      CharSequence name, Element... originatingElements) throws IOException {\n    String relative = name.toString().replace(\".\", separator) + \".java\"; // Assumes well-formed.\n    Path path = fileSystemRoot.resolve(relative);\n    originatingElementsMap.put(path, Util.immutableSet(Arrays.asList(originatingElements)));\n    return new Source(path);\n  }\n\n  @Override public JavaFileObject createClassFile(CharSequence name, Element... originatingElements)\n      throws IOException {\n    throw new UnsupportedOperationException(\"Not implemented.\");\n  }\n\n  @Override public FileObject createResource(JavaFileManager.Location location, CharSequence pkg,\n      CharSequence relativeName, Element... originatingElements) throws IOException {\n    throw new UnsupportedOperationException(\"Not implemented.\");\n  }\n\n  @Override public FileObject getResource(JavaFileManager.Location location, CharSequence pkg,\n      CharSequence relativeName) throws IOException {\n    throw new UnsupportedOperationException(\"Not implemented.\");\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/TestUtil.java",
    "content": "package com.squareup.javapoet;\n\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.VariableElement;\nimport java.util.Collection;\n\nfinal class TestUtil {\n  static <E extends Element> E findFirst(Collection<E> elements, String name) {\n    for (E element : elements) {\n      if (element.getSimpleName().toString().equals(name)) {\n        return element;\n      }\n    }\n    throw new IllegalArgumentException(name + \" not found in \" + elements);\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/TypeNameTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport java.io.Serializable;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Type;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.UUID;\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotEquals;\n\npublic class TypeNameTest {\n\n  private static final AnnotationSpec ANNOTATION_SPEC = AnnotationSpec.builder(ClassName.OBJECT).build();\n\n  protected <E extends Enum<E>> E generic(E[] values) {\n    return values[0];\n  }\n\n  protected static class TestGeneric<T> {\n    class Inner {}\n\n    class InnerGeneric<T2> {}\n\n    static class NestedNonGeneric {}\n  }\n\n  protected static TestGeneric<String>.Inner testGenericStringInner() {\n    return null;\n  }\n\n  protected static TestGeneric<Integer>.Inner testGenericIntInner() {\n    return null;\n  }\n\n  protected static TestGeneric<Short>.InnerGeneric<Long> testGenericInnerLong() {\n    return null;\n  }\n\n  protected static TestGeneric<Short>.InnerGeneric<Integer> testGenericInnerInt() {\n    return null;\n  }\n\n  protected static TestGeneric.NestedNonGeneric testNestedNonGeneric() {\n    return null;\n  }\n\n  @Test public void genericType() throws Exception {\n    Method recursiveEnum = getClass().getDeclaredMethod(\"generic\", Enum[].class);\n    TypeName.get(recursiveEnum.getReturnType());\n    TypeName.get(recursiveEnum.getGenericReturnType());\n    TypeName genericTypeName = TypeName.get(recursiveEnum.getParameterTypes()[0]);\n    TypeName.get(recursiveEnum.getGenericParameterTypes()[0]);\n\n    // Make sure the generic argument is present\n    assertThat(genericTypeName.toString()).contains(\"Enum\");\n  }\n\n  @Test public void innerClassInGenericType() throws Exception {\n    Method genericStringInner = getClass().getDeclaredMethod(\"testGenericStringInner\");\n    TypeName.get(genericStringInner.getReturnType());\n    TypeName genericTypeName = TypeName.get(genericStringInner.getGenericReturnType());\n    assertNotEquals(TypeName.get(genericStringInner.getGenericReturnType()),\n        TypeName.get(getClass().getDeclaredMethod(\"testGenericIntInner\").getGenericReturnType()));\n\n    // Make sure the generic argument is present\n    assertThat(genericTypeName.toString()).isEqualTo(\n        TestGeneric.class.getCanonicalName() + \"<java.lang.String>.Inner\");\n  }\n\n  @Test public void innerGenericInGenericType() throws Exception {\n    Method genericStringInner = getClass().getDeclaredMethod(\"testGenericInnerLong\");\n    TypeName.get(genericStringInner.getReturnType());\n    TypeName genericTypeName = TypeName.get(genericStringInner.getGenericReturnType());\n    assertNotEquals(TypeName.get(genericStringInner.getGenericReturnType()),\n        TypeName.get(getClass().getDeclaredMethod(\"testGenericInnerInt\").getGenericReturnType()));\n\n    // Make sure the generic argument is present\n    assertThat(genericTypeName.toString()).isEqualTo(\n        TestGeneric.class.getCanonicalName() + \"<java.lang.Short>.InnerGeneric<java.lang.Long>\");\n  }\n\n  @Test public void innerStaticInGenericType() throws Exception {\n    Method staticInGeneric = getClass().getDeclaredMethod(\"testNestedNonGeneric\");\n    TypeName.get(staticInGeneric.getReturnType());\n    TypeName typeName = TypeName.get(staticInGeneric.getGenericReturnType());\n\n    // Make sure there are no generic arguments\n    assertThat(typeName.toString()).isEqualTo(\n        TestGeneric.class.getCanonicalName() + \".NestedNonGeneric\");\n  }\n\n  @Test public void equalsAndHashCodePrimitive() {\n    assertEqualsHashCodeAndToString(TypeName.BOOLEAN, TypeName.BOOLEAN);\n    assertEqualsHashCodeAndToString(TypeName.BYTE, TypeName.BYTE);\n    assertEqualsHashCodeAndToString(TypeName.CHAR, TypeName.CHAR);\n    assertEqualsHashCodeAndToString(TypeName.DOUBLE, TypeName.DOUBLE);\n    assertEqualsHashCodeAndToString(TypeName.FLOAT, TypeName.FLOAT);\n    assertEqualsHashCodeAndToString(TypeName.INT, TypeName.INT);\n    assertEqualsHashCodeAndToString(TypeName.LONG, TypeName.LONG);\n    assertEqualsHashCodeAndToString(TypeName.SHORT, TypeName.SHORT);\n    assertEqualsHashCodeAndToString(TypeName.VOID, TypeName.VOID);\n  }\n\n  @Test public void equalsAndHashCodeArrayTypeName() {\n    assertEqualsHashCodeAndToString(ArrayTypeName.of(Object.class),\n        ArrayTypeName.of(Object.class));\n    assertEqualsHashCodeAndToString(TypeName.get(Object[].class),\n        ArrayTypeName.of(Object.class));\n  }\n\n  @Test public void equalsAndHashCodeClassName() {\n    assertEqualsHashCodeAndToString(ClassName.get(Object.class), ClassName.get(Object.class));\n    assertEqualsHashCodeAndToString(TypeName.get(Object.class), ClassName.get(Object.class));\n    assertEqualsHashCodeAndToString(ClassName.bestGuess(\"java.lang.Object\"),\n        ClassName.get(Object.class));\n  }\n\n  @Test public void equalsAndHashCodeParameterizedTypeName() {\n    assertEqualsHashCodeAndToString(ParameterizedTypeName.get(Object.class),\n        ParameterizedTypeName.get(Object.class));\n    assertEqualsHashCodeAndToString(ParameterizedTypeName.get(Set.class, UUID.class),\n        ParameterizedTypeName.get(Set.class, UUID.class));\n    assertNotEquals(ClassName.get(List.class), ParameterizedTypeName.get(List.class,\n        String.class));\n  }\n\n  @Test public void equalsAndHashCodeTypeVariableName() {\n    assertEqualsHashCodeAndToString(TypeVariableName.get(Object.class),\n        TypeVariableName.get(Object.class));\n    TypeVariableName typeVar1 = TypeVariableName.get(\"T\", Comparator.class, Serializable.class);\n    TypeVariableName typeVar2 = TypeVariableName.get(\"T\", Comparator.class, Serializable.class);\n    assertEqualsHashCodeAndToString(typeVar1, typeVar2);\n  }\n\n  @Test public void equalsAndHashCodeWildcardTypeName() {\n    assertEqualsHashCodeAndToString(WildcardTypeName.subtypeOf(Object.class),\n        WildcardTypeName.subtypeOf(Object.class));\n    assertEqualsHashCodeAndToString(WildcardTypeName.subtypeOf(Serializable.class),\n        WildcardTypeName.subtypeOf(Serializable.class));\n    assertEqualsHashCodeAndToString(WildcardTypeName.supertypeOf(String.class),\n        WildcardTypeName.supertypeOf(String.class));\n  }\n\n  @Test public void isPrimitive() throws Exception {\n    assertThat(TypeName.INT.isPrimitive()).isTrue();\n    assertThat(ClassName.get(\"java.lang\", \"Integer\").isPrimitive()).isFalse();\n    assertThat(ClassName.get(\"java.lang\", \"String\").isPrimitive()).isFalse();\n    assertThat(TypeName.VOID.isPrimitive()).isFalse();\n    assertThat(ClassName.get(\"java.lang\", \"Void\").isPrimitive()).isFalse();\n  }\n\n  @Test public void isBoxedPrimitive() throws Exception {\n    assertThat(TypeName.INT.isBoxedPrimitive()).isFalse();\n    assertThat(ClassName.get(\"java.lang\", \"Integer\").isBoxedPrimitive()).isTrue();\n    assertThat(ClassName.get(\"java.lang\", \"String\").isBoxedPrimitive()).isFalse();\n    assertThat(TypeName.VOID.isBoxedPrimitive()).isFalse();\n    assertThat(ClassName.get(\"java.lang\", \"Void\").isBoxedPrimitive()).isFalse();\n    assertThat(ClassName.get(\"java.lang\", \"Integer\")\n            .annotated(ANNOTATION_SPEC).isBoxedPrimitive()).isTrue();\n  }\n\n  @Test public void canBoxAnnotatedPrimitive() throws Exception {\n    assertThat(TypeName.BOOLEAN.annotated(ANNOTATION_SPEC).box()).isEqualTo(\n            ClassName.get(\"java.lang\", \"Boolean\").annotated(ANNOTATION_SPEC));\n  }\n\n  @Test public void canUnboxAnnotatedPrimitive() throws Exception {\n    assertThat(ClassName.get(\"java.lang\", \"Boolean\").annotated(ANNOTATION_SPEC)\n            .unbox()).isEqualTo(TypeName.BOOLEAN.annotated(ANNOTATION_SPEC));\n  }\n\n  private void assertEqualsHashCodeAndToString(TypeName a, TypeName b) {\n    assertEquals(a.toString(), b.toString());\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    assertFalse(a.equals(null));\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/TypeSpecTest.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport com.google.common.collect.ImmutableMap;\nimport com.google.testing.compile.CompilationRule;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.util.AbstractSet;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.EventListener;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.concurrent.Callable;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.type.TypeMirror;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mockito;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\n@RunWith(JUnit4.class)\npublic final class TypeSpecTest {\n  private final String tacosPackage = \"com.squareup.tacos\";\n  private static final String donutsPackage = \"com.squareup.donuts\";\n\n  @Rule public final CompilationRule compilation = new CompilationRule();\n\n  private TypeElement getElement(Class<?> clazz) {\n    return compilation.getElements().getTypeElement(clazz.getCanonicalName());\n  }\n\n  @Test public void basic() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"toString\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n            .returns(String.class)\n            .addCode(\"return $S;\\n\", \"taco\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  @Override\\n\"\n        + \"  public final String toString() {\\n\"\n        + \"    return \\\"taco\\\";\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n    assertEquals(472949424, taco.hashCode()); // update expected number if source changes\n  }\n\n  @Test public void interestingTypes() throws Exception {\n    TypeName listOfAny = ParameterizedTypeName.get(\n        ClassName.get(List.class), WildcardTypeName.subtypeOf(Object.class));\n    TypeName listOfExtends = ParameterizedTypeName.get(\n        ClassName.get(List.class), WildcardTypeName.subtypeOf(Serializable.class));\n    TypeName listOfSuper = ParameterizedTypeName.get(ClassName.get(List.class),\n        WildcardTypeName.supertypeOf(String.class));\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(listOfAny, \"extendsObject\")\n        .addField(listOfExtends, \"extendsSerializable\")\n        .addField(listOfSuper, \"superString\")\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.io.Serializable;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"import java.util.List;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  List<?> extendsObject;\\n\"\n        + \"\\n\"\n        + \"  List<? extends Serializable> extendsSerializable;\\n\"\n        + \"\\n\"\n        + \"  List<? super String> superString;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void anonymousInnerClass() throws Exception {\n    ClassName foo = ClassName.get(tacosPackage, \"Foo\");\n    ClassName bar = ClassName.get(tacosPackage, \"Bar\");\n    ClassName thingThang = ClassName.get(tacosPackage, \"Thing\", \"Thang\");\n    TypeName thingThangOfFooBar = ParameterizedTypeName.get(thingThang, foo, bar);\n    ClassName thung = ClassName.get(tacosPackage, \"Thung\");\n    ClassName simpleThung = ClassName.get(tacosPackage, \"SimpleThung\");\n    TypeName thungOfSuperBar = ParameterizedTypeName.get(thung, WildcardTypeName.supertypeOf(bar));\n    TypeName thungOfSuperFoo = ParameterizedTypeName.get(thung, WildcardTypeName.supertypeOf(foo));\n    TypeName simpleThungOfBar = ParameterizedTypeName.get(simpleThung, bar);\n\n    ParameterSpec thungParameter = ParameterSpec.builder(thungOfSuperFoo, \"thung\")\n        .addModifiers(Modifier.FINAL)\n        .build();\n    TypeSpec aSimpleThung = TypeSpec.anonymousClassBuilder(CodeBlock.of(\"$N\", thungParameter))\n        .superclass(simpleThungOfBar)\n        .addMethod(MethodSpec.methodBuilder(\"doSomething\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .addParameter(bar, \"bar\")\n            .addCode(\"/* code snippets */\\n\")\n            .build())\n        .build();\n    TypeSpec aThingThang = TypeSpec.anonymousClassBuilder(\"\")\n        .superclass(thingThangOfFooBar)\n        .addMethod(MethodSpec.methodBuilder(\"call\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(thungOfSuperBar)\n            .addParameter(thungParameter)\n            .addCode(\"return $L;\\n\", aSimpleThung)\n            .build())\n        .build();\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(FieldSpec.builder(thingThangOfFooBar, \"NAME\")\n            .addModifiers(Modifier.STATIC, Modifier.FINAL, Modifier.FINAL)\n            .initializer(\"$L\", aThingThang)\n            .build())\n        .build();\n\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  static final Thing.Thang<Foo, Bar> NAME = new Thing.Thang<Foo, Bar>() {\\n\"\n        + \"    @Override\\n\"\n        + \"    public Thung<? super Bar> call(final Thung<? super Foo> thung) {\\n\"\n        + \"      return new SimpleThung<Bar>(thung) {\\n\"\n        + \"        @Override\\n\"\n        + \"        public void doSomething(Bar bar) {\\n\"\n        + \"          /* code snippets */\\n\"\n        + \"        }\\n\"\n        + \"      };\\n\"\n        + \"    }\\n\"\n        + \"  };\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void annotatedParameters() throws Exception {\n    TypeSpec service = TypeSpec.classBuilder(\"Foo\")\n        .addMethod(MethodSpec.constructorBuilder()\n            .addModifiers(Modifier.PUBLIC)\n            .addParameter(long.class, \"id\")\n            .addParameter(ParameterSpec.builder(String.class, \"one\")\n                .addAnnotation(ClassName.get(tacosPackage, \"Ping\"))\n                .build())\n            .addParameter(ParameterSpec.builder(String.class, \"two\")\n                .addAnnotation(ClassName.get(tacosPackage, \"Ping\"))\n                .build())\n            .addParameter(ParameterSpec.builder(String.class, \"three\")\n                .addAnnotation(AnnotationSpec.builder(ClassName.get(tacosPackage, \"Pong\"))\n                    .addMember(\"value\", \"$S\", \"pong\")\n                    .build())\n                .build())\n            .addParameter(ParameterSpec.builder(String.class, \"four\")\n                .addAnnotation(ClassName.get(tacosPackage, \"Ping\"))\n                .build())\n            .addCode(\"/* code snippets */\\n\")\n            .build())\n        .build();\n\n    assertThat(toString(service)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Foo {\\n\"\n        + \"  public Foo(long id, @Ping String one, @Ping String two, @Pong(\\\"pong\\\") String three,\\n\"\n        + \"      @Ping String four) {\\n\"\n        + \"    /* code snippets */\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  /**\n   * We had a bug where annotations were preventing us from doing the right thing when resolving\n   * imports. https://github.com/square/javapoet/issues/422\n   */\n  @Test public void annotationsAndJavaLangTypes() throws Exception {\n    ClassName freeRange = ClassName.get(\"javax.annotation\", \"FreeRange\");\n    TypeSpec taco = TypeSpec.classBuilder(\"EthicalTaco\")\n        .addField(ClassName.get(String.class)\n            .annotated(AnnotationSpec.builder(freeRange).build()), \"meat\")\n        .build();\n\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"import javax.annotation.FreeRange;\\n\"\n        + \"\\n\"\n        + \"class EthicalTaco {\\n\"\n        + \"  @FreeRange String meat;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void retrofitStyleInterface() throws Exception {\n    ClassName observable = ClassName.get(tacosPackage, \"Observable\");\n    ClassName fooBar = ClassName.get(tacosPackage, \"FooBar\");\n    ClassName thing = ClassName.get(tacosPackage, \"Thing\");\n    ClassName things = ClassName.get(tacosPackage, \"Things\");\n    ClassName map = ClassName.get(\"java.util\", \"Map\");\n    ClassName string = ClassName.get(\"java.lang\", \"String\");\n    ClassName headers = ClassName.get(tacosPackage, \"Headers\");\n    ClassName post = ClassName.get(tacosPackage, \"POST\");\n    ClassName body = ClassName.get(tacosPackage, \"Body\");\n    ClassName queryMap = ClassName.get(tacosPackage, \"QueryMap\");\n    ClassName header = ClassName.get(tacosPackage, \"Header\");\n    TypeSpec service = TypeSpec.interfaceBuilder(\"Service\")\n        .addMethod(MethodSpec.methodBuilder(\"fooBar\")\n            .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n            .addAnnotation(AnnotationSpec.builder(headers)\n                .addMember(\"value\", \"$S\", \"Accept: application/json\")\n                .addMember(\"value\", \"$S\", \"User-Agent: foobar\")\n                .build())\n            .addAnnotation(AnnotationSpec.builder(post)\n                .addMember(\"value\", \"$S\", \"/foo/bar\")\n                .build())\n            .returns(ParameterizedTypeName.get(observable, fooBar))\n            .addParameter(ParameterSpec.builder(ParameterizedTypeName.get(things, thing), \"things\")\n                .addAnnotation(body)\n                .build())\n            .addParameter(ParameterSpec.builder(\n                ParameterizedTypeName.get(map, string, string), \"query\")\n                .addAnnotation(AnnotationSpec.builder(queryMap)\n                    .addMember(\"encodeValues\", \"false\")\n                    .build())\n                .build())\n            .addParameter(ParameterSpec.builder(string, \"authorization\")\n                .addAnnotation(AnnotationSpec.builder(header)\n                    .addMember(\"value\", \"$S\", \"Authorization\")\n                    .build())\n                .build())\n            .build())\n        .build();\n\n    assertThat(toString(service)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"import java.util.Map;\\n\"\n        + \"\\n\"\n        + \"interface Service {\\n\"\n        + \"  @Headers({\\n\"\n        + \"      \\\"Accept: application/json\\\",\\n\"\n        + \"      \\\"User-Agent: foobar\\\"\\n\"\n        + \"  })\\n\"\n        + \"  @POST(\\\"/foo/bar\\\")\\n\"\n        + \"  Observable<FooBar> fooBar(@Body Things<Thing> things,\\n\"\n        + \"      @QueryMap(encodeValues = false) Map<String, String> query,\\n\"\n        + \"      @Header(\\\"Authorization\\\") String authorization);\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void annotatedField() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(FieldSpec.builder(String.class, \"thing\", Modifier.PRIVATE, Modifier.FINAL)\n            .addAnnotation(AnnotationSpec.builder(ClassName.get(tacosPackage, \"JsonAdapter\"))\n                .addMember(\"value\", \"$T.class\", ClassName.get(tacosPackage, \"Foo\"))\n                .build())\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  @JsonAdapter(Foo.class)\\n\"\n        + \"  private final String thing;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void annotatedClass() throws Exception {\n    ClassName someType = ClassName.get(tacosPackage, \"SomeType\");\n    TypeSpec taco = TypeSpec.classBuilder(\"Foo\")\n        .addAnnotation(AnnotationSpec.builder(ClassName.get(tacosPackage, \"Something\"))\n            .addMember(\"hi\", \"$T.$N\", someType, \"FIELD\")\n            .addMember(\"hey\", \"$L\", 12)\n            .addMember(\"hello\", \"$S\", \"goodbye\")\n            .build())\n        .addModifiers(Modifier.PUBLIC)\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"@Something(\\n\"\n        + \"    hi = SomeType.FIELD,\\n\"\n        + \"    hey = 12,\\n\"\n        + \"    hello = \\\"goodbye\\\"\\n\"\n        + \")\\n\"\n        + \"public class Foo {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void addAnnotationDisallowsNull() {\n    try {\n      TypeSpec.classBuilder(\"Foo\").addAnnotation((AnnotationSpec) null);\n      fail();\n    } catch (NullPointerException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"annotationSpec == null\");\n    }\n    try {\n      TypeSpec.classBuilder(\"Foo\").addAnnotation((ClassName) null);\n      fail();\n    } catch (NullPointerException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"type == null\");\n    }\n    try {\n      TypeSpec.classBuilder(\"Foo\").addAnnotation((Class<?>) null);\n      fail();\n    } catch (NullPointerException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"clazz == null\");\n    }\n  }\n\n  @Test public void enumWithSubclassing() throws Exception {\n    TypeSpec roshambo = TypeSpec.enumBuilder(\"Roshambo\")\n        .addModifiers(Modifier.PUBLIC)\n        .addEnumConstant(\"ROCK\", TypeSpec.anonymousClassBuilder(\"\")\n            .addJavadoc(\"Avalanche!\\n\")\n            .build())\n        .addEnumConstant(\"PAPER\", TypeSpec.anonymousClassBuilder(\"$S\", \"flat\")\n            .addMethod(MethodSpec.methodBuilder(\"toString\")\n                .addAnnotation(Override.class)\n                .addModifiers(Modifier.PUBLIC)\n                .returns(String.class)\n                .addCode(\"return $S;\\n\", \"paper airplane!\")\n                .build())\n            .build())\n        .addEnumConstant(\"SCISSORS\", TypeSpec.anonymousClassBuilder(\"$S\", \"peace sign\")\n            .build())\n        .addField(String.class, \"handPosition\", Modifier.PRIVATE, Modifier.FINAL)\n        .addMethod(MethodSpec.constructorBuilder()\n            .addParameter(String.class, \"handPosition\")\n            .addCode(\"this.handPosition = handPosition;\\n\")\n            .build())\n        .addMethod(MethodSpec.constructorBuilder()\n            .addCode(\"this($S);\\n\", \"fist\")\n            .build())\n        .build();\n    assertThat(toString(roshambo)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"public enum Roshambo {\\n\"\n        + \"  /**\\n\"\n        + \"   * Avalanche!\\n\"\n        + \"   */\\n\"\n        + \"  ROCK,\\n\"\n        + \"\\n\"\n        + \"  PAPER(\\\"flat\\\") {\\n\"\n        + \"    @Override\\n\"\n        + \"    public String toString() {\\n\"\n        + \"      return \\\"paper airplane!\\\";\\n\"\n        + \"    }\\n\"\n        + \"  },\\n\"\n        + \"\\n\"\n        + \"  SCISSORS(\\\"peace sign\\\");\\n\"\n        + \"\\n\"\n        + \"  private final String handPosition;\\n\"\n        + \"\\n\"\n        + \"  Roshambo(String handPosition) {\\n\"\n        + \"    this.handPosition = handPosition;\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  Roshambo() {\\n\"\n        + \"    this(\\\"fist\\\");\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  /** https://github.com/square/javapoet/issues/193 */\n  @Test public void enumsMayDefineAbstractMethods() throws Exception {\n    TypeSpec roshambo = TypeSpec.enumBuilder(\"Tortilla\")\n        .addModifiers(Modifier.PUBLIC)\n        .addEnumConstant(\"CORN\", TypeSpec.anonymousClassBuilder(\"\")\n            .addMethod(MethodSpec.methodBuilder(\"fold\")\n                .addAnnotation(Override.class)\n                .addModifiers(Modifier.PUBLIC)\n                .build())\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"fold\")\n            .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n            .build())\n        .build();\n    assertThat(toString(roshambo)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"\\n\"\n        + \"public enum Tortilla {\\n\"\n        + \"  CORN {\\n\"\n        + \"    @Override\\n\"\n        + \"    public void fold() {\\n\"\n        + \"    }\\n\"\n        + \"  };\\n\"\n        + \"\\n\"\n        + \"  public abstract void fold();\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void noEnumConstants() throws Exception {\n    TypeSpec roshambo = TypeSpec.enumBuilder(\"Roshambo\")\n            .addField(String.class, \"NO_ENUM\", Modifier.STATIC)\n            .build();\n    assertThat(toString(roshambo)).isEqualTo(\"\"\n            + \"package com.squareup.tacos;\\n\"\n            + \"\\n\"\n            + \"import java.lang.String;\\n\"\n            + \"\\n\"\n            + \"enum Roshambo {\\n\"\n            + \"  ;\\n\"\n            + \"  static String NO_ENUM;\\n\"\n            + \"}\\n\");\n  }\n\n  @Test public void onlyEnumsMayHaveEnumConstants() throws Exception {\n    try {\n      TypeSpec.classBuilder(\"Roshambo\")\n          .addEnumConstant(\"ROCK\")\n          .build();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void enumWithMembersButNoConstructorCall() throws Exception {\n    TypeSpec roshambo = TypeSpec.enumBuilder(\"Roshambo\")\n        .addEnumConstant(\"SPOCK\", TypeSpec.anonymousClassBuilder(\"\")\n            .addMethod(MethodSpec.methodBuilder(\"toString\")\n                .addAnnotation(Override.class)\n                .addModifiers(Modifier.PUBLIC)\n                .returns(String.class)\n                .addCode(\"return $S;\\n\", \"west side\")\n                .build())\n            .build())\n        .build();\n    assertThat(toString(roshambo)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"enum Roshambo {\\n\"\n        + \"  SPOCK {\\n\"\n        + \"    @Override\\n\"\n        + \"    public String toString() {\\n\"\n        + \"      return \\\"west side\\\";\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  /** https://github.com/square/javapoet/issues/253 */\n  @Test public void enumWithAnnotatedValues() throws Exception {\n    TypeSpec roshambo = TypeSpec.enumBuilder(\"Roshambo\")\n        .addModifiers(Modifier.PUBLIC)\n        .addEnumConstant(\"ROCK\", TypeSpec.anonymousClassBuilder(\"\")\n            .addAnnotation(Deprecated.class)\n            .build())\n        .addEnumConstant(\"PAPER\")\n        .addEnumConstant(\"SCISSORS\")\n        .build();\n    assertThat(toString(roshambo)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Deprecated;\\n\"\n        + \"\\n\"\n        + \"public enum Roshambo {\\n\"\n        + \"  @Deprecated\\n\"\n        + \"  ROCK,\\n\"\n        + \"\\n\"\n        + \"  PAPER,\\n\"\n        + \"\\n\"\n        + \"  SCISSORS\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void methodThrows() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addModifiers(Modifier.ABSTRACT)\n        .addMethod(MethodSpec.methodBuilder(\"throwOne\")\n            .addException(IOException.class)\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"throwTwo\")\n            .addException(IOException.class)\n            .addException(ClassName.get(tacosPackage, \"SourCreamException\"))\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"abstractThrow\")\n            .addModifiers(Modifier.ABSTRACT)\n            .addException(IOException.class)\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"nativeThrow\")\n            .addModifiers(Modifier.NATIVE)\n            .addException(IOException.class)\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.io.IOException;\\n\"\n        + \"\\n\"\n        + \"abstract class Taco {\\n\"\n        + \"  void throwOne() throws IOException {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  void throwTwo() throws IOException, SourCreamException {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  abstract void abstractThrow() throws IOException;\\n\"\n        + \"\\n\"\n        + \"  native void nativeThrow() throws IOException;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void typeVariables() throws Exception {\n    TypeVariableName t = TypeVariableName.get(\"T\");\n    TypeVariableName p = TypeVariableName.get(\"P\", Number.class);\n    ClassName location = ClassName.get(tacosPackage, \"Location\");\n    TypeSpec typeSpec = TypeSpec.classBuilder(\"Location\")\n        .addTypeVariable(t)\n        .addTypeVariable(p)\n        .addSuperinterface(ParameterizedTypeName.get(ClassName.get(Comparable.class), p))\n        .addField(t, \"label\")\n        .addField(p, \"x\")\n        .addField(p, \"y\")\n        .addMethod(MethodSpec.methodBuilder(\"compareTo\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(int.class)\n            .addParameter(p, \"p\")\n            .addCode(\"return 0;\\n\")\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"of\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n            .addTypeVariable(t)\n            .addTypeVariable(p)\n            .returns(ParameterizedTypeName.get(location, t, p))\n            .addParameter(t, \"label\")\n            .addParameter(p, \"x\")\n            .addParameter(p, \"y\")\n            .addCode(\"throw new $T($S);\\n\", UnsupportedOperationException.class, \"TODO\")\n            .build())\n        .build();\n    assertThat(toString(typeSpec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Comparable;\\n\"\n        + \"import java.lang.Number;\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.UnsupportedOperationException;\\n\"\n        + \"\\n\"\n        + \"class Location<T, P extends Number> implements Comparable<P> {\\n\"\n        + \"  T label;\\n\"\n        + \"\\n\"\n        + \"  P x;\\n\"\n        + \"\\n\"\n        + \"  P y;\\n\"\n        + \"\\n\"\n        + \"  @Override\\n\"\n        + \"  public int compareTo(P p) {\\n\"\n        + \"    return 0;\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  public static <T, P extends Number> Location<T, P> of(T label, P x, P y) {\\n\"\n        + \"    throw new UnsupportedOperationException(\\\"TODO\\\");\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void typeVariableWithBounds() {\n    AnnotationSpec a = AnnotationSpec.builder(ClassName.get(\"com.squareup.tacos\", \"A\")).build();\n    TypeVariableName p = TypeVariableName.get(\"P\", Number.class);\n    TypeVariableName q = (TypeVariableName) TypeVariableName.get(\"Q\", Number.class).annotated(a);\n    TypeSpec typeSpec = TypeSpec.classBuilder(\"Location\")\n        .addTypeVariable(p.withBounds(Comparable.class))\n        .addTypeVariable(q.withBounds(Comparable.class))\n        .addField(p, \"x\")\n        .addField(q, \"y\")\n        .build();\n    assertThat(toString(typeSpec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Comparable;\\n\"\n        + \"import java.lang.Number;\\n\"\n        + \"\\n\"\n        + \"class Location<P extends Number & Comparable, @A Q extends Number & Comparable> {\\n\"\n        + \"  P x;\\n\"\n        + \"\\n\"\n        + \"  @A Q y;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void classImplementsExtends() throws Exception {\n    ClassName taco = ClassName.get(tacosPackage, \"Taco\");\n    ClassName food = ClassName.get(\"com.squareup.tacos\", \"Food\");\n    TypeSpec typeSpec = TypeSpec.classBuilder(\"Taco\")\n        .addModifiers(Modifier.ABSTRACT)\n        .superclass(ParameterizedTypeName.get(ClassName.get(AbstractSet.class), food))\n        .addSuperinterface(Serializable.class)\n        .addSuperinterface(ParameterizedTypeName.get(ClassName.get(Comparable.class), taco))\n        .build();\n    assertThat(toString(typeSpec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.io.Serializable;\\n\"\n        + \"import java.lang.Comparable;\\n\"\n        + \"import java.util.AbstractSet;\\n\"\n        + \"\\n\"\n        + \"abstract class Taco extends AbstractSet<Food> \"\n        + \"implements Serializable, Comparable<Taco> {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void classImplementsNestedClass() throws Exception {\n    ClassName outer = ClassName.get(tacosPackage, \"Outer\");\n    ClassName inner = outer.nestedClass(\"Inner\");\n    ClassName callable = ClassName.get(Callable.class);\n    TypeSpec typeSpec = TypeSpec.classBuilder(\"Outer\")\n        .superclass(ParameterizedTypeName.get(callable,\n            inner))\n        .addType(TypeSpec.classBuilder(\"Inner\")\n            .addModifiers(Modifier.STATIC)\n            .build())\n        .build();\n\n    assertThat(toString(typeSpec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.util.concurrent.Callable;\\n\"\n        + \"\\n\"\n        + \"class Outer extends Callable<Outer.Inner> {\\n\"\n        + \"  static class Inner {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void enumImplements() throws Exception {\n    TypeSpec typeSpec = TypeSpec.enumBuilder(\"Food\")\n        .addSuperinterface(Serializable.class)\n        .addSuperinterface(Cloneable.class)\n        .addEnumConstant(\"LEAN_GROUND_BEEF\")\n        .addEnumConstant(\"SHREDDED_CHEESE\")\n        .build();\n    assertThat(toString(typeSpec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.io.Serializable;\\n\"\n        + \"import java.lang.Cloneable;\\n\"\n        + \"\\n\"\n        + \"enum Food implements Serializable, Cloneable {\\n\"\n        + \"  LEAN_GROUND_BEEF,\\n\"\n        + \"\\n\"\n        + \"  SHREDDED_CHEESE\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void interfaceExtends() throws Exception {\n    ClassName taco = ClassName.get(tacosPackage, \"Taco\");\n    TypeSpec typeSpec = TypeSpec.interfaceBuilder(\"Taco\")\n        .addSuperinterface(Serializable.class)\n        .addSuperinterface(ParameterizedTypeName.get(ClassName.get(Comparable.class), taco))\n        .build();\n    assertThat(toString(typeSpec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.io.Serializable;\\n\"\n        + \"import java.lang.Comparable;\\n\"\n        + \"\\n\"\n        + \"interface Taco extends Serializable, Comparable<Taco> {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nestedClasses() throws Exception {\n    ClassName taco = ClassName.get(tacosPackage, \"Combo\", \"Taco\");\n    ClassName topping = ClassName.get(tacosPackage, \"Combo\", \"Taco\", \"Topping\");\n    ClassName chips = ClassName.get(tacosPackage, \"Combo\", \"Chips\");\n    ClassName sauce = ClassName.get(tacosPackage, \"Combo\", \"Sauce\");\n    TypeSpec typeSpec = TypeSpec.classBuilder(\"Combo\")\n        .addField(taco, \"taco\")\n        .addField(chips, \"chips\")\n        .addType(TypeSpec.classBuilder(taco.simpleName())\n            .addModifiers(Modifier.STATIC)\n            .addField(ParameterizedTypeName.get(ClassName.get(List.class), topping), \"toppings\")\n            .addField(sauce, \"sauce\")\n            .addType(TypeSpec.enumBuilder(topping.simpleName())\n                .addEnumConstant(\"SHREDDED_CHEESE\")\n                .addEnumConstant(\"LEAN_GROUND_BEEF\")\n                .build())\n            .build())\n        .addType(TypeSpec.classBuilder(chips.simpleName())\n            .addModifiers(Modifier.STATIC)\n            .addField(topping, \"topping\")\n            .addField(sauce, \"dippingSauce\")\n            .build())\n        .addType(TypeSpec.enumBuilder(sauce.simpleName())\n            .addEnumConstant(\"SOUR_CREAM\")\n            .addEnumConstant(\"SALSA\")\n            .addEnumConstant(\"QUESO\")\n            .addEnumConstant(\"MILD\")\n            .addEnumConstant(\"FIRE\")\n            .build())\n        .build();\n\n    assertThat(toString(typeSpec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.util.List;\\n\"\n        + \"\\n\"\n        + \"class Combo {\\n\"\n        + \"  Taco taco;\\n\"\n        + \"\\n\"\n        + \"  Chips chips;\\n\"\n        + \"\\n\"\n        + \"  static class Taco {\\n\"\n        + \"    List<Topping> toppings;\\n\"\n        + \"\\n\"\n        + \"    Sauce sauce;\\n\"\n        + \"\\n\"\n        + \"    enum Topping {\\n\"\n        + \"      SHREDDED_CHEESE,\\n\"\n        + \"\\n\"\n        + \"      LEAN_GROUND_BEEF\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  static class Chips {\\n\"\n        + \"    Taco.Topping topping;\\n\"\n        + \"\\n\"\n        + \"    Sauce dippingSauce;\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  enum Sauce {\\n\"\n        + \"    SOUR_CREAM,\\n\"\n        + \"\\n\"\n        + \"    SALSA,\\n\"\n        + \"\\n\"\n        + \"    QUESO,\\n\"\n        + \"\\n\"\n        + \"    MILD,\\n\"\n        + \"\\n\"\n        + \"    FIRE\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void annotation() throws Exception {\n    TypeSpec annotation = TypeSpec.annotationBuilder(\"MyAnnotation\")\n        .addModifiers(Modifier.PUBLIC)\n        .addMethod(MethodSpec.methodBuilder(\"test\")\n            .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n            .defaultValue(\"$L\", 0)\n            .returns(int.class)\n            .build())\n        .build();\n\n    assertThat(toString(annotation)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"public @interface MyAnnotation {\\n\"\n        + \"  int test() default 0;\\n\"\n        + \"}\\n\"\n    );\n  }\n\n  @Test public void innerAnnotationInAnnotationDeclaration() throws Exception {\n    TypeSpec bar = TypeSpec.annotationBuilder(\"Bar\")\n        .addMethod(MethodSpec.methodBuilder(\"value\")\n            .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n            .defaultValue(\"@$T\", Deprecated.class)\n            .returns(Deprecated.class)\n            .build())\n        .build();\n\n    assertThat(toString(bar)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Deprecated;\\n\"\n        + \"\\n\"\n        + \"@interface Bar {\\n\"\n        + \"  Deprecated value() default @Deprecated;\\n\"\n        + \"}\\n\"\n    );\n  }\n\n  @Test public void annotationWithFields() {\n    FieldSpec field = FieldSpec.builder(int.class, \"FOO\")\n        .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)\n        .initializer(\"$L\", 101)\n        .build();\n\n    TypeSpec anno = TypeSpec.annotationBuilder(\"Anno\")\n        .addField(field)\n        .build();\n\n    assertThat(toString(anno)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"@interface Anno {\\n\"\n        + \"  int FOO = 101;\\n\"\n        + \"}\\n\"\n    );\n  }\n\n  @Test\n  public void classCannotHaveDefaultValueForMethod() throws Exception {\n    try {\n      TypeSpec.classBuilder(\"Tacos\")\n          .addMethod(MethodSpec.methodBuilder(\"test\")\n              .addModifiers(Modifier.PUBLIC)\n              .defaultValue(\"0\")\n              .returns(int.class)\n              .build())\n          .build();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test\n  public void classCannotHaveDefaultMethods() throws Exception {\n    try {\n      TypeSpec.classBuilder(\"Tacos\")\n          .addMethod(MethodSpec.methodBuilder(\"test\")\n              .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)\n              .returns(int.class)\n              .addCode(CodeBlock.builder().addStatement(\"return 0\").build())\n              .build())\n          .build();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test\n  public void interfaceStaticMethods() throws Exception {\n    TypeSpec bar = TypeSpec.interfaceBuilder(\"Tacos\")\n        .addMethod(MethodSpec.methodBuilder(\"test\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n            .returns(int.class)\n            .addCode(CodeBlock.builder().addStatement(\"return 0\").build())\n            .build())\n        .build();\n\n    assertThat(toString(bar)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"interface Tacos {\\n\"\n        + \"  static int test() {\\n\"\n        + \"    return 0;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\"\n    );\n  }\n\n  @Test\n  public void interfaceDefaultMethods() throws Exception {\n    TypeSpec bar = TypeSpec.interfaceBuilder(\"Tacos\")\n        .addMethod(MethodSpec.methodBuilder(\"test\")\n            .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)\n            .returns(int.class)\n            .addCode(CodeBlock.builder().addStatement(\"return 0\").build())\n            .build())\n        .build();\n\n    assertThat(toString(bar)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"interface Tacos {\\n\"\n        + \"  default int test() {\\n\"\n        + \"    return 0;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\"\n    );\n  }\n\n  @Test\n  public void invalidInterfacePrivateMethods() {\n    try {\n      TypeSpec.interfaceBuilder(\"Tacos\")\n          .addMethod(MethodSpec.methodBuilder(\"test\")\n              .addModifiers(Modifier.PRIVATE, Modifier.DEFAULT)\n              .returns(int.class)\n              .addCode(CodeBlock.builder().addStatement(\"return 0\").build())\n              .build())\n          .build();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n\n    try {\n      TypeSpec.interfaceBuilder(\"Tacos\")\n          .addMethod(MethodSpec.methodBuilder(\"test\")\n              .addModifiers(Modifier.PRIVATE, Modifier.ABSTRACT)\n              .returns(int.class)\n              .build())\n          .build();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n\n    try {\n      TypeSpec.interfaceBuilder(\"Tacos\")\n          .addMethod(MethodSpec.methodBuilder(\"test\")\n              .addModifiers(Modifier.PRIVATE, Modifier.PUBLIC)\n              .returns(int.class)\n              .addCode(CodeBlock.builder().addStatement(\"return 0\").build())\n              .build())\n          .build();\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test\n  public void interfacePrivateMethods() {\n    TypeSpec bar = TypeSpec.interfaceBuilder(\"Tacos\")\n        .addMethod(MethodSpec.methodBuilder(\"test\")\n            .addModifiers(Modifier.PRIVATE)\n            .returns(int.class)\n            .addCode(CodeBlock.builder().addStatement(\"return 0\").build())\n            .build())\n        .build();\n\n    assertThat(toString(bar)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"interface Tacos {\\n\"\n        + \"  private int test() {\\n\"\n        + \"    return 0;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\"\n    );\n\n    bar = TypeSpec.interfaceBuilder(\"Tacos\")\n        .addMethod(MethodSpec.methodBuilder(\"test\")\n            .addModifiers(Modifier.PRIVATE, Modifier.STATIC)\n            .returns(int.class)\n            .addCode(CodeBlock.builder().addStatement(\"return 0\").build())\n            .build())\n        .build();\n\n    assertThat(toString(bar)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"interface Tacos {\\n\"\n        + \"  private static int test() {\\n\"\n        + \"    return 0;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\"\n    );\n  }\n\n  @Test public void referencedAndDeclaredSimpleNamesConflict() throws Exception {\n    FieldSpec internalTop = FieldSpec.builder(\n        ClassName.get(tacosPackage, \"Top\"), \"internalTop\").build();\n    FieldSpec internalBottom = FieldSpec.builder(\n        ClassName.get(tacosPackage, \"Top\", \"Middle\", \"Bottom\"), \"internalBottom\").build();\n    FieldSpec externalTop = FieldSpec.builder(\n        ClassName.get(donutsPackage, \"Top\"), \"externalTop\").build();\n    FieldSpec externalBottom = FieldSpec.builder(\n        ClassName.get(donutsPackage, \"Bottom\"), \"externalBottom\").build();\n    TypeSpec top = TypeSpec.classBuilder(\"Top\")\n        .addField(internalTop)\n        .addField(internalBottom)\n        .addField(externalTop)\n        .addField(externalBottom)\n        .addType(TypeSpec.classBuilder(\"Middle\")\n            .addField(internalTop)\n            .addField(internalBottom)\n            .addField(externalTop)\n            .addField(externalBottom)\n            .addType(TypeSpec.classBuilder(\"Bottom\")\n                .addField(internalTop)\n                .addField(internalBottom)\n                .addField(externalTop)\n                .addField(externalBottom)\n                .build())\n            .build())\n        .build();\n    assertThat(toString(top)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.squareup.donuts.Bottom;\\n\"\n        + \"\\n\"\n        + \"class Top {\\n\"\n        + \"  Top internalTop;\\n\"\n        + \"\\n\"\n        + \"  Middle.Bottom internalBottom;\\n\"\n        + \"\\n\"\n        + \"  com.squareup.donuts.Top externalTop;\\n\"\n        + \"\\n\"\n        + \"  Bottom externalBottom;\\n\"\n        + \"\\n\"\n        + \"  class Middle {\\n\"\n        + \"    Top internalTop;\\n\"\n        + \"\\n\"\n        + \"    Bottom internalBottom;\\n\"\n        + \"\\n\"\n        + \"    com.squareup.donuts.Top externalTop;\\n\"\n        + \"\\n\"\n        + \"    com.squareup.donuts.Bottom externalBottom;\\n\"\n        + \"\\n\"\n        + \"    class Bottom {\\n\"\n        + \"      Top internalTop;\\n\"\n        + \"\\n\"\n        + \"      Bottom internalBottom;\\n\"\n        + \"\\n\"\n        + \"      com.squareup.donuts.Top externalTop;\\n\"\n        + \"\\n\"\n        + \"      com.squareup.donuts.Bottom externalBottom;\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void simpleNamesConflictInThisAndOtherPackage() throws Exception {\n    FieldSpec internalOther = FieldSpec.builder(\n        ClassName.get(tacosPackage, \"Other\"), \"internalOther\").build();\n    FieldSpec externalOther = FieldSpec.builder(\n        ClassName.get(donutsPackage, \"Other\"), \"externalOther\").build();\n    TypeSpec gen = TypeSpec.classBuilder(\"Gen\")\n        .addField(internalOther)\n        .addField(externalOther)\n        .build();\n    assertThat(toString(gen)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Gen {\\n\"\n        + \"  Other internalOther;\\n\"\n        + \"\\n\"\n        + \"  com.squareup.donuts.Other externalOther;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void simpleNameConflictsWithTypeVariable() {\n    ClassName inPackage = ClassName.get(\"com.squareup.tacos\", \"InPackage\");\n    ClassName otherType = ClassName.get(\"com.other\", \"OtherType\");\n    ClassName methodInPackage = ClassName.get(\"com.squareup.tacos\", \"MethodInPackage\");\n    ClassName methodOtherType = ClassName.get(\"com.other\", \"MethodOtherType\");\n    TypeSpec gen = TypeSpec.classBuilder(\"Gen\")\n        .addTypeVariable(TypeVariableName.get(\"InPackage\"))\n        .addTypeVariable(TypeVariableName.get(\"OtherType\"))\n        .addField(FieldSpec.builder(inPackage, \"inPackage\").build())\n        .addField(FieldSpec.builder(otherType, \"otherType\").build())\n        .addMethod(MethodSpec.methodBuilder(\"withTypeVariables\")\n            .addTypeVariable(TypeVariableName.get(\"MethodInPackage\"))\n            .addTypeVariable(TypeVariableName.get(\"MethodOtherType\"))\n            .addStatement(\"$T inPackage = null\", methodInPackage)\n            .addStatement(\"$T otherType = null\", methodOtherType)\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"withoutTypeVariables\")\n            .addStatement(\"$T inPackage = null\", methodInPackage)\n            .addStatement(\"$T otherType = null\", methodOtherType)\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"againWithTypeVariables\")\n            .addTypeVariable(TypeVariableName.get(\"MethodInPackage\"))\n            .addTypeVariable(TypeVariableName.get(\"MethodOtherType\"))\n            .addStatement(\"$T inPackage = null\", methodInPackage)\n            .addStatement(\"$T otherType = null\", methodOtherType)\n            .build())\n        // https://github.com/square/javapoet/pull/657#discussion_r205514292\n        .addMethod(MethodSpec.methodBuilder(\"masksEnclosingTypeVariable\")\n            .addTypeVariable(TypeVariableName.get(\"InPackage\"))\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"hasSimpleNameThatWasPreviouslyMasked\")\n            .addStatement(\"$T inPackage = null\", inPackage)\n            .build())\n        .build();\n    assertThat(toString(gen)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.other.MethodOtherType;\\n\"\n        + \"\\n\"\n        + \"class Gen<InPackage, OtherType> {\\n\"\n        + \"  com.squareup.tacos.InPackage inPackage;\\n\"\n        + \"\\n\"\n        + \"  com.other.OtherType otherType;\\n\"\n        + \"\\n\"\n        + \"  <MethodInPackage, MethodOtherType> void withTypeVariables() {\\n\"\n        + \"    com.squareup.tacos.MethodInPackage inPackage = null;\\n\"\n        + \"    com.other.MethodOtherType otherType = null;\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  void withoutTypeVariables() {\\n\"\n        + \"    MethodInPackage inPackage = null;\\n\"\n        + \"    MethodOtherType otherType = null;\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  <MethodInPackage, MethodOtherType> void againWithTypeVariables() {\\n\"\n        + \"    com.squareup.tacos.MethodInPackage inPackage = null;\\n\"\n        + \"    com.other.MethodOtherType otherType = null;\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  <InPackage> void masksEnclosingTypeVariable() {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  void hasSimpleNameThatWasPreviouslyMasked() {\\n\"\n        + \"    com.squareup.tacos.InPackage inPackage = null;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void originatingElementsIncludesThoseOfNestedTypes() {\n    Element outerElement = Mockito.mock(Element.class);\n    Element innerElement = Mockito.mock(Element.class);\n    TypeSpec outer = TypeSpec.classBuilder(\"Outer\")\n        .addOriginatingElement(outerElement)\n        .addType(TypeSpec.classBuilder(\"Inner\")\n            .addOriginatingElement(innerElement)\n            .build())\n        .build();\n    assertThat(outer.originatingElements).containsExactly(outerElement, innerElement);\n  }\n\n  @Test public void intersectionType() {\n    TypeVariableName typeVariable = TypeVariableName.get(\"T\", Comparator.class, Serializable.class);\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"getComparator\")\n            .addTypeVariable(typeVariable)\n            .returns(typeVariable)\n            .addCode(\"return null;\\n\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.io.Serializable;\\n\"\n        + \"import java.util.Comparator;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  <T extends Comparator & Serializable> T getComparator() {\\n\"\n        + \"    return null;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void arrayType() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(int[].class, \"ints\")\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  int[] ints;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void javadoc() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addJavadoc(\"A hard or soft tortilla, loosely folded and filled with whatever {@link \\n\")\n        .addJavadoc(\"{@link $T random} tex-mex stuff we could find in the pantry\\n\", Random.class)\n        .addJavadoc(CodeBlock.of(\"and some {@link $T} cheese.\\n\", String.class))\n        .addField(FieldSpec.builder(boolean.class, \"soft\")\n            .addJavadoc(\"True for a soft flour tortilla; false for a crunchy corn tortilla.\\n\")\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"refold\")\n            .addJavadoc(\"Folds the back of this taco to reduce sauce leakage.\\n\"\n                + \"\\n\"\n                + \"<p>For {@link $T#KOREAN}, the front may also be folded.\\n\", Locale.class)\n            .addParameter(Locale.class, \"locale\")\n            .build())\n        .build();\n    // Mentioning a type in Javadoc will not cause an import to be added (java.util.Random here),\n    // but the short name will be used if it's already imported (java.util.Locale here).\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.util.Locale;\\n\"\n        + \"\\n\"\n        + \"/**\\n\"\n        + \" * A hard or soft tortilla, loosely folded and filled with whatever {@link \\n\"\n        + \" * {@link java.util.Random random} tex-mex stuff we could find in the pantry\\n\"\n        + \" * and some {@link java.lang.String} cheese.\\n\"\n        + \" */\\n\"\n        + \"class Taco {\\n\"\n        + \"  /**\\n\"\n        + \"   * True for a soft flour tortilla; false for a crunchy corn tortilla.\\n\"\n        + \"   */\\n\"\n        + \"  boolean soft;\\n\"\n        + \"\\n\"\n        + \"  /**\\n\"\n        + \"   * Folds the back of this taco to reduce sauce leakage.\\n\"\n        + \"   *\\n\"\n        + \"   * <p>For {@link Locale#KOREAN}, the front may also be folded.\\n\"\n        + \"   */\\n\"\n        + \"  void refold(Locale locale) {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void annotationsInAnnotations() throws Exception {\n    ClassName beef = ClassName.get(tacosPackage, \"Beef\");\n    ClassName chicken = ClassName.get(tacosPackage, \"Chicken\");\n    ClassName option = ClassName.get(tacosPackage, \"Option\");\n    ClassName mealDeal = ClassName.get(tacosPackage, \"MealDeal\");\n    TypeSpec menu = TypeSpec.classBuilder(\"Menu\")\n        .addAnnotation(AnnotationSpec.builder(mealDeal)\n            .addMember(\"price\", \"$L\", 500)\n            .addMember(\"options\", \"$L\", AnnotationSpec.builder(option)\n                .addMember(\"name\", \"$S\", \"taco\")\n                .addMember(\"meat\", \"$T.class\", beef)\n                .build())\n            .addMember(\"options\", \"$L\", AnnotationSpec.builder(option)\n                .addMember(\"name\", \"$S\", \"quesadilla\")\n                .addMember(\"meat\", \"$T.class\", chicken)\n                .build())\n            .build())\n        .build();\n    assertThat(toString(menu)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"@MealDeal(\\n\"\n        + \"    price = 500,\\n\"\n        + \"    options = {\\n\"\n        + \"        @Option(name = \\\"taco\\\", meat = Beef.class),\\n\"\n        + \"        @Option(name = \\\"quesadilla\\\", meat = Chicken.class)\\n\"\n        + \"    }\\n\"\n        + \")\\n\"\n        + \"class Menu {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void varargs() throws Exception {\n    TypeSpec taqueria = TypeSpec.classBuilder(\"Taqueria\")\n        .addMethod(MethodSpec.methodBuilder(\"prepare\")\n            .addParameter(int.class, \"workers\")\n            .addParameter(Runnable[].class, \"jobs\")\n            .varargs()\n            .build())\n        .build();\n    assertThat(toString(taqueria)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Runnable;\\n\"\n        + \"\\n\"\n        + \"class Taqueria {\\n\"\n        + \"  void prepare(int workers, Runnable... jobs) {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void codeBlocks() throws Exception {\n    CodeBlock ifBlock = CodeBlock.builder()\n        .beginControlFlow(\"if (!a.equals(b))\")\n        .addStatement(\"return i\")\n        .endControlFlow()\n        .build();\n    CodeBlock methodBody = CodeBlock.builder()\n        .addStatement(\"$T size = $T.min(listA.size(), listB.size())\", int.class, Math.class)\n        .beginControlFlow(\"for ($T i = 0; i < size; i++)\", int.class)\n        .addStatement(\"$T $N = $N.get(i)\", String.class, \"a\", \"listA\")\n        .addStatement(\"$T $N = $N.get(i)\", String.class, \"b\", \"listB\")\n        .add(\"$L\", ifBlock)\n        .endControlFlow()\n        .addStatement(\"return size\")\n        .build();\n    CodeBlock fieldBlock = CodeBlock.builder()\n        .add(\"$>$>\")\n        .add(\"\\n$T.<$T, $T>builder()$>$>\", ImmutableMap.class, String.class, String.class)\n        .add(\"\\n.add($S, $S)\", '\\'', \"&#39;\")\n        .add(\"\\n.add($S, $S)\", '&', \"&amp;\")\n        .add(\"\\n.add($S, $S)\", '<', \"&lt;\")\n        .add(\"\\n.add($S, $S)\", '>', \"&gt;\")\n        .add(\"\\n.build()$<$<\")\n        .add(\"$<$<\")\n        .build();\n    FieldSpec escapeHtml = FieldSpec.builder(ParameterizedTypeName.get(\n        Map.class, String.class, String.class), \"ESCAPE_HTML\")\n        .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)\n        .initializer(fieldBlock)\n        .build();\n    TypeSpec util = TypeSpec.classBuilder(\"Util\")\n        .addField(escapeHtml)\n        .addMethod(MethodSpec.methodBuilder(\"commonPrefixLength\")\n            .returns(int.class)\n            .addParameter(ParameterizedTypeName.get(List.class, String.class), \"listA\")\n            .addParameter(ParameterizedTypeName.get(List.class, String.class), \"listB\")\n            .addCode(methodBody)\n            .build())\n        .build();\n    assertThat(toString(util)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import com.google.common.collect.ImmutableMap;\\n\"\n        + \"import java.lang.Math;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"import java.util.List;\\n\"\n        + \"import java.util.Map;\\n\"\n        + \"\\n\"\n        + \"class Util {\\n\"\n        + \"  private static final Map<String, String> ESCAPE_HTML = \\n\"\n        + \"      ImmutableMap.<String, String>builder()\\n\"\n        + \"          .add(\\\"\\'\\\", \\\"&#39;\\\")\\n\"\n        + \"          .add(\\\"&\\\", \\\"&amp;\\\")\\n\"\n        + \"          .add(\\\"<\\\", \\\"&lt;\\\")\\n\"\n        + \"          .add(\\\">\\\", \\\"&gt;\\\")\\n\"\n        + \"          .build();\\n\"\n        + \"\\n\"\n        + \"  int commonPrefixLength(List<String> listA, List<String> listB) {\\n\"\n        + \"    int size = Math.min(listA.size(), listB.size());\\n\"\n        + \"    for (int i = 0; i < size; i++) {\\n\"\n        + \"      String a = listA.get(i);\\n\"\n        + \"      String b = listB.get(i);\\n\"\n        + \"      if (!a.equals(b)) {\\n\"\n        + \"        return i;\\n\"\n        + \"      }\\n\"\n        + \"    }\\n\"\n        + \"    return size;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void indexedElseIf() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"choices\")\n            .beginControlFlow(\"if ($1L != null || $1L == $2L)\", \"taco\", \"otherTaco\")\n            .addStatement(\"$T.out.println($S)\", System.class, \"only one taco? NOO!\")\n            .nextControlFlow(\"else if ($1L.$3L && $2L.$3L)\", \"taco\", \"otherTaco\", \"isSupreme()\")\n            .addStatement(\"$T.out.println($S)\", System.class, \"taco heaven\")\n            .endControlFlow()\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.System;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  void choices() {\\n\"\n        + \"    if (taco != null || taco == otherTaco) {\\n\"\n        + \"      System.out.println(\\\"only one taco? NOO!\\\");\\n\"\n        + \"    } else if (taco.isSupreme() && otherTaco.isSupreme()) {\\n\"\n        + \"      System.out.println(\\\"taco heaven\\\");\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void elseIf() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"choices\")\n            .beginControlFlow(\"if (5 < 4) \")\n            .addStatement(\"$T.out.println($S)\", System.class, \"wat\")\n            .nextControlFlow(\"else if (5 < 6)\")\n            .addStatement(\"$T.out.println($S)\", System.class, \"hello\")\n            .endControlFlow()\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.System;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  void choices() {\\n\"\n        + \"    if (5 < 4)  {\\n\"\n        + \"      System.out.println(\\\"wat\\\");\\n\"\n        + \"    } else if (5 < 6) {\\n\"\n        + \"      System.out.println(\\\"hello\\\");\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void doWhile() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"loopForever\")\n            .beginControlFlow(\"do\")\n            .addStatement(\"$T.out.println($S)\", System.class, \"hello\")\n            .endControlFlow(\"while (5 < 6)\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.System;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  void loopForever() {\\n\"\n        + \"    do {\\n\"\n        + \"      System.out.println(\\\"hello\\\");\\n\"\n        + \"    } while (5 < 6);\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void inlineIndent() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"inlineIndent\")\n            .addCode(\"if (3 < 4) {\\n$>$T.out.println($S);\\n$<}\\n\", System.class, \"hello\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.System;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  void inlineIndent() {\\n\"\n        + \"    if (3 < 4) {\\n\"\n        + \"      System.out.println(\\\"hello\\\");\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void defaultModifiersForInterfaceMembers() throws Exception {\n    TypeSpec taco = TypeSpec.interfaceBuilder(\"Taco\")\n        .addField(FieldSpec.builder(String.class, \"SHELL\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)\n            .initializer(\"$S\", \"crunchy corn\")\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"fold\")\n            .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)\n            .build())\n        .addType(TypeSpec.classBuilder(\"Topping\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"interface Taco {\\n\"\n        + \"  String SHELL = \\\"crunchy corn\\\";\\n\"\n        + \"\\n\"\n        + \"  void fold();\\n\"\n        + \"\\n\"\n        + \"  class Topping {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void defaultModifiersForMemberInterfacesAndEnums() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addType(TypeSpec.classBuilder(\"Meat\")\n            .addModifiers(Modifier.STATIC)\n            .build())\n        .addType(TypeSpec.interfaceBuilder(\"Tortilla\")\n            .addModifiers(Modifier.STATIC)\n            .build())\n        .addType(TypeSpec.enumBuilder(\"Topping\")\n            .addModifiers(Modifier.STATIC)\n            .addEnumConstant(\"SALSA\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  static class Meat {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  interface Tortilla {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  enum Topping {\\n\"\n        + \"    SALSA\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void membersOrdering() throws Exception {\n    // Hand out names in reverse-alphabetical order to defend against unexpected sorting.\n    TypeSpec taco = TypeSpec.classBuilder(\"Members\")\n        .addType(TypeSpec.classBuilder(\"Z\").build())\n        .addType(TypeSpec.classBuilder(\"Y\").build())\n        .addField(String.class, \"X\", Modifier.STATIC)\n        .addField(String.class, \"W\")\n        .addField(String.class, \"V\", Modifier.STATIC)\n        .addField(String.class, \"U\")\n        .addMethod(MethodSpec.methodBuilder(\"T\").addModifiers(Modifier.STATIC).build())\n        .addMethod(MethodSpec.methodBuilder(\"S\").build())\n        .addMethod(MethodSpec.methodBuilder(\"R\").addModifiers(Modifier.STATIC).build())\n        .addMethod(MethodSpec.methodBuilder(\"Q\").build())\n        .addMethod(MethodSpec.constructorBuilder().addParameter(int.class, \"p\").build())\n        .addMethod(MethodSpec.constructorBuilder().addParameter(long.class, \"o\").build())\n        .build();\n    // Static fields, instance fields, constructors, methods, classes.\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Members {\\n\"\n        + \"  static String X;\\n\"\n        + \"\\n\"\n        + \"  static String V;\\n\"\n        + \"\\n\"\n        + \"  String W;\\n\"\n        + \"\\n\"\n        + \"  String U;\\n\"\n        + \"\\n\"\n        + \"  Members(int p) {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  Members(long o) {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  static void T() {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  void S() {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  static void R() {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  void Q() {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  class Z {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  class Y {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nativeMethods() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"nativeInt\")\n            .addModifiers(Modifier.NATIVE)\n            .returns(int.class)\n            .build())\n        // GWT JSNI\n        .addMethod(MethodSpec.methodBuilder(\"alert\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.NATIVE)\n            .addParameter(String.class, \"msg\")\n            .addCode(CodeBlock.builder()\n                .add(\" /*-{\\n\")\n                .indent()\n                .addStatement(\"$$wnd.alert(msg)\")\n                .unindent()\n                .add(\"}-*/\")\n                .build())\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  native int nativeInt();\\n\"\n        + \"\\n\"\n        + \"  public static native void alert(String msg) /*-{\\n\"\n        + \"    $wnd.alert(msg);\\n\"\n        + \"  }-*/;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nullStringLiteral() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(FieldSpec.builder(String.class, \"NULL\")\n            .initializer(\"$S\", (Object) null)\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  String NULL = null;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void annotationToString() throws Exception {\n    AnnotationSpec annotation = AnnotationSpec.builder(SuppressWarnings.class)\n        .addMember(\"value\", \"$S\", \"unused\")\n        .build();\n    assertThat(annotation.toString()).isEqualTo(\"@java.lang.SuppressWarnings(\\\"unused\\\")\");\n  }\n\n  @Test public void codeBlockToString() throws Exception {\n    CodeBlock codeBlock = CodeBlock.builder()\n        .addStatement(\"$T $N = $S.substring(0, 3)\", String.class, \"s\", \"taco\")\n        .build();\n    assertThat(codeBlock.toString()).isEqualTo(\"java.lang.String s = \\\"taco\\\".substring(0, 3);\\n\");\n  }\n\n  @Test public void codeBlockAddStatementOfCodeBlockToString() throws Exception {\n    CodeBlock contents = CodeBlock.of(\"$T $N = $S.substring(0, 3)\", String.class, \"s\", \"taco\");\n    CodeBlock statement = CodeBlock.builder().addStatement(contents).build();\n    assertThat(statement.toString()).isEqualTo(\"java.lang.String s = \\\"taco\\\".substring(0, 3);\\n\");\n  }\n\n  @Test public void fieldToString() throws Exception {\n    FieldSpec field = FieldSpec.builder(String.class, \"s\", Modifier.FINAL)\n        .initializer(\"$S.substring(0, 3)\", \"taco\")\n        .build();\n    assertThat(field.toString())\n        .isEqualTo(\"final java.lang.String s = \\\"taco\\\".substring(0, 3);\\n\");\n  }\n\n  @Test public void methodToString() throws Exception {\n    MethodSpec method = MethodSpec.methodBuilder(\"toString\")\n        .addAnnotation(Override.class)\n        .addModifiers(Modifier.PUBLIC)\n        .returns(String.class)\n        .addStatement(\"return $S\", \"taco\")\n        .build();\n    assertThat(method.toString()).isEqualTo(\"\"\n        + \"@java.lang.Override\\n\"\n        + \"public java.lang.String toString() {\\n\"\n        + \"  return \\\"taco\\\";\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void constructorToString() throws Exception {\n    MethodSpec constructor = MethodSpec.constructorBuilder()\n        .addModifiers(Modifier.PUBLIC)\n        .addParameter(ClassName.get(tacosPackage, \"Taco\"), \"taco\")\n        .addStatement(\"this.$N = $N\", \"taco\", \"taco\")\n        .build();\n    assertThat(constructor.toString()).isEqualTo(\"\"\n        + \"public Constructor(com.squareup.tacos.Taco taco) {\\n\"\n        + \"  this.taco = taco;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void parameterToString() throws Exception {\n    ParameterSpec parameter = ParameterSpec.builder(ClassName.get(tacosPackage, \"Taco\"), \"taco\")\n        .addModifiers(Modifier.FINAL)\n        .addAnnotation(ClassName.get(\"javax.annotation\", \"Nullable\"))\n        .build();\n    assertThat(parameter.toString())\n        .isEqualTo(\"@javax.annotation.Nullable final com.squareup.tacos.Taco taco\");\n  }\n\n  @Test public void classToString() throws Exception {\n    TypeSpec type = TypeSpec.classBuilder(\"Taco\")\n        .build();\n    assertThat(type.toString()).isEqualTo(\"\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void anonymousClassToString() throws Exception {\n    TypeSpec type = TypeSpec.anonymousClassBuilder(\"\")\n        .addSuperinterface(Runnable.class)\n        .addMethod(MethodSpec.methodBuilder(\"run\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .build())\n        .build();\n    assertThat(type.toString()).isEqualTo(\"\"\n        + \"new java.lang.Runnable() {\\n\"\n        + \"  @java.lang.Override\\n\"\n        + \"  public void run() {\\n\"\n        + \"  }\\n\"\n        + \"}\");\n  }\n\n  @Test public void interfaceClassToString() throws Exception {\n    TypeSpec type = TypeSpec.interfaceBuilder(\"Taco\")\n        .build();\n    assertThat(type.toString()).isEqualTo(\"\"\n        + \"interface Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void annotationDeclarationToString() throws Exception {\n    TypeSpec type = TypeSpec.annotationBuilder(\"Taco\")\n        .build();\n    assertThat(type.toString()).isEqualTo(\"\"\n        + \"@interface Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  private String toString(TypeSpec typeSpec) {\n    return JavaFile.builder(tacosPackage, typeSpec).build().toString();\n  }\n\n  @Test public void multilineStatement() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"toString\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(String.class)\n            .addStatement(\"return $S\\n+ $S\\n+ $S\\n+ $S\\n+ $S\",\n                \"Taco(\", \"beef,\", \"lettuce,\", \"cheese\", \")\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  @Override\\n\"\n        + \"  public String toString() {\\n\"\n        + \"    return \\\"Taco(\\\"\\n\"\n        + \"        + \\\"beef,\\\"\\n\"\n        + \"        + \\\"lettuce,\\\"\\n\"\n        + \"        + \\\"cheese\\\"\\n\"\n        + \"        + \\\")\\\";\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void multilineStatementWithAnonymousClass() throws Exception {\n    TypeName stringComparator = ParameterizedTypeName.get(Comparator.class, String.class);\n    TypeName listOfString = ParameterizedTypeName.get(List.class, String.class);\n    TypeSpec prefixComparator = TypeSpec.anonymousClassBuilder(\"\")\n        .addSuperinterface(stringComparator)\n        .addMethod(MethodSpec.methodBuilder(\"compare\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(int.class)\n            .addParameter(String.class, \"a\")\n            .addParameter(String.class, \"b\")\n            .addStatement(\"return a.substring(0, length)\\n\"\n                + \".compareTo(b.substring(0, length))\")\n            .build())\n        .build();\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"comparePrefix\")\n            .returns(stringComparator)\n            .addParameter(int.class, \"length\", Modifier.FINAL)\n            .addStatement(\"return $L\", prefixComparator)\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"sortPrefix\")\n            .addParameter(listOfString, \"list\")\n            .addParameter(int.class, \"length\", Modifier.FINAL)\n            .addStatement(\"$T.sort(\\nlist,\\n$L)\", Collections.class, prefixComparator)\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"import java.util.Collections;\\n\"\n        + \"import java.util.Comparator;\\n\"\n        + \"import java.util.List;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  Comparator<String> comparePrefix(final int length) {\\n\"\n        + \"    return new Comparator<String>() {\\n\"\n        + \"      @Override\\n\"\n        + \"      public int compare(String a, String b) {\\n\"\n        + \"        return a.substring(0, length)\\n\"\n        + \"            .compareTo(b.substring(0, length));\\n\"\n        + \"      }\\n\"\n        + \"    };\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  void sortPrefix(List<String> list, final int length) {\\n\"\n        + \"    Collections.sort(\\n\"\n        + \"        list,\\n\"\n        + \"        new Comparator<String>() {\\n\"\n        + \"          @Override\\n\"\n        + \"          public int compare(String a, String b) {\\n\"\n        + \"            return a.substring(0, length)\\n\"\n        + \"                .compareTo(b.substring(0, length));\\n\"\n        + \"          }\\n\"\n        + \"        });\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void multilineStrings() throws Exception {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(FieldSpec.builder(String.class, \"toppings\")\n            .initializer(\"$S\", \"shell\\nbeef\\nlettuce\\ncheese\\n\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  String toppings = \\\"shell\\\\n\\\"\\n\"\n        + \"      + \\\"beef\\\\n\\\"\\n\"\n        + \"      + \\\"lettuce\\\\n\\\"\\n\"\n        + \"      + \\\"cheese\\\\n\\\";\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void doubleFieldInitialization() {\n    try {\n      FieldSpec.builder(String.class, \"listA\")\n          .initializer(\"foo\")\n          .initializer(\"bar\")\n          .build();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n\n    try {\n      FieldSpec.builder(String.class, \"listA\")\n          .initializer(CodeBlock.builder().add(\"foo\").build())\n          .initializer(CodeBlock.builder().add(\"bar\").build())\n          .build();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void nullAnnotationsAddition() {\n    try {\n      TypeSpec.classBuilder(\"Taco\").addAnnotations(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"annotationSpecs == null\");\n    }\n  }\n\n  @Test public void multipleAnnotationAddition() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addAnnotations(Arrays.asList(\n            AnnotationSpec.builder(SuppressWarnings.class)\n                .addMember(\"value\", \"$S\", \"unchecked\")\n                .build(),\n            AnnotationSpec.builder(Deprecated.class).build()))\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Deprecated;\\n\"\n        + \"import java.lang.SuppressWarnings;\\n\"\n        + \"\\n\"\n        + \"@SuppressWarnings(\\\"unchecked\\\")\\n\"\n        + \"@Deprecated\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nullFieldsAddition() {\n    try {\n      TypeSpec.classBuilder(\"Taco\").addFields(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"fieldSpecs == null\");\n    }\n  }\n\n  @Test public void multipleFieldAddition() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addFields(Arrays.asList(\n            FieldSpec.builder(int.class, \"ANSWER\", Modifier.STATIC, Modifier.FINAL).build(),\n            FieldSpec.builder(BigDecimal.class, \"price\", Modifier.PRIVATE).build()))\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.math.BigDecimal;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  static final int ANSWER;\\n\"\n        + \"\\n\"\n        + \"  private BigDecimal price;\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nullMethodsAddition() {\n    try {\n      TypeSpec.classBuilder(\"Taco\").addMethods(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"methodSpecs == null\");\n    }\n  }\n\n  @Test public void multipleMethodAddition() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethods(Arrays.asList(\n            MethodSpec.methodBuilder(\"getAnswer\")\n                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n                .returns(int.class)\n                .addStatement(\"return $L\", 42)\n                .build(),\n            MethodSpec.methodBuilder(\"getRandomQuantity\")\n                .addModifiers(Modifier.PUBLIC)\n                .returns(int.class)\n                .addJavadoc(\"chosen by fair dice roll ;)\")\n                .addStatement(\"return $L\", 4)\n                .build()))\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  public static int getAnswer() {\\n\"\n        + \"    return 42;\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  /**\\n\"\n        + \"   * chosen by fair dice roll ;)\\n\"\n        + \"   */\\n\"\n        + \"  public int getRandomQuantity() {\\n\"\n        + \"    return 4;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nullSuperinterfacesAddition() {\n    try {\n      TypeSpec.classBuilder(\"Taco\").addSuperinterfaces(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"superinterfaces == null\");\n    }\n  }\n\n  @Test public void nullSingleSuperinterfaceAddition() {\n    try {\n      TypeSpec.classBuilder(\"Taco\").addSuperinterface((TypeName) null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"superinterface == null\");\n    }\n  }\n\n  @Test public void nullInSuperinterfaceIterableAddition() {\n    List<TypeName> superinterfaces = new ArrayList<>();\n    superinterfaces.add(TypeName.get(List.class));\n    superinterfaces.add(null);\n\n    try {\n      TypeSpec.classBuilder(\"Taco\").addSuperinterfaces(superinterfaces);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"superinterface == null\");\n    }\n  }\n\n  @Test public void multipleSuperinterfaceAddition() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addSuperinterfaces(Arrays.asList(\n            TypeName.get(Serializable.class),\n            TypeName.get(EventListener.class)))\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.io.Serializable;\\n\"\n        + \"import java.util.EventListener;\\n\"\n        + \"\\n\"\n        + \"class Taco implements Serializable, EventListener {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nullModifiersAddition() {\n    try {\n      TypeSpec.classBuilder(\"Taco\").addModifiers((Modifier) null).build();\n      fail();\n    } catch(IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"modifiers contain null\");\n    }\n  }\n\n  @Test public void nullTypeVariablesAddition() {\n    try {\n      TypeSpec.classBuilder(\"Taco\").addTypeVariables(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"typeVariables == null\");\n    }\n  }\n\n  @Test public void multipleTypeVariableAddition() {\n    TypeSpec location = TypeSpec.classBuilder(\"Location\")\n        .addTypeVariables(Arrays.asList(\n            TypeVariableName.get(\"T\"),\n            TypeVariableName.get(\"P\", Number.class)))\n        .build();\n    assertThat(toString(location)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Number;\\n\"\n        + \"\\n\"\n        + \"class Location<T, P extends Number> {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void nullTypesAddition() {\n    try {\n      TypeSpec.classBuilder(\"Taco\").addTypes(null);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected.getMessage())\n          .isEqualTo(\"typeSpecs == null\");\n    }\n  }\n\n  @Test public void multipleTypeAddition() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addTypes(Arrays.asList(\n            TypeSpec.classBuilder(\"Topping\").build(),\n            TypeSpec.classBuilder(\"Sauce\").build()))\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  class Topping {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  class Sauce {\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void tryCatch() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"addTopping\")\n            .addParameter(ClassName.get(\"com.squareup.tacos\", \"Topping\"), \"topping\")\n            .beginControlFlow(\"try\")\n            .addCode(\"/* do something tricky with the topping */\\n\")\n            .nextControlFlow(\"catch ($T e)\",\n                ClassName.get(\"com.squareup.tacos\", \"IllegalToppingException\"))\n            .endControlFlow()\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  void addTopping(Topping topping) {\\n\"\n        + \"    try {\\n\"\n        + \"      /* do something tricky with the topping */\\n\"\n        + \"    } catch (IllegalToppingException e) {\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void ifElse() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(\n            MethodSpec.methodBuilder(\"isDelicious\")\n                .addParameter(TypeName.INT, \"count\")\n                .returns(TypeName.BOOLEAN)\n                .beginControlFlow(\"if (count > 0)\")\n                .addStatement(\"return true\")\n                .nextControlFlow(\"else\")\n                .addStatement(\"return false\")\n                .endControlFlow()\n                .build()\n        )\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  boolean isDelicious(int count) {\\n\"\n        + \"    if (count > 0) {\\n\"\n        + \"      return true;\\n\"\n        + \"    } else {\\n\"\n        + \"      return false;\\n\"\n        + \"    }\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void literalFromAnything() {\n    Object value = new Object() {\n      @Override public String toString() {\n        return \"foo\";\n      }\n    };\n    assertThat(CodeBlock.of(\"$L\", value).toString()).isEqualTo(\"foo\");\n  }\n\n  @Test public void nameFromCharSequence() {\n    assertThat(CodeBlock.of(\"$N\", \"text\").toString()).isEqualTo(\"text\");\n  }\n\n  @Test public void nameFromField() {\n    FieldSpec field = FieldSpec.builder(String.class, \"field\").build();\n    assertThat(CodeBlock.of(\"$N\", field).toString()).isEqualTo(\"field\");\n  }\n\n  @Test public void nameFromParameter() {\n    ParameterSpec parameter = ParameterSpec.builder(String.class, \"parameter\").build();\n    assertThat(CodeBlock.of(\"$N\", parameter).toString()).isEqualTo(\"parameter\");\n  }\n\n  @Test public void nameFromMethod() {\n    MethodSpec method = MethodSpec.methodBuilder(\"method\")\n        .addModifiers(Modifier.ABSTRACT)\n        .returns(String.class)\n        .build();\n    assertThat(CodeBlock.of(\"$N\", method).toString()).isEqualTo(\"method\");\n  }\n\n  @Test public void nameFromType() {\n    TypeSpec type = TypeSpec.classBuilder(\"Type\").build();\n    assertThat(CodeBlock.of(\"$N\", type).toString()).isEqualTo(\"Type\");\n  }\n\n  @Test public void nameFromUnsupportedType() {\n    try {\n      CodeBlock.builder().add(\"$N\", String.class);\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"expected name but was \" + String.class);\n    }\n  }\n\n  @Test public void stringFromAnything() {\n    Object value = new Object() {\n      @Override public String toString() {\n        return \"foo\";\n      }\n    };\n    assertThat(CodeBlock.of(\"$S\", value).toString()).isEqualTo(\"\\\"foo\\\"\");\n  }\n\n  @Test public void stringFromNull() {\n    assertThat(CodeBlock.of(\"$S\", new Object[] {null}).toString()).isEqualTo(\"null\");\n  }\n\n  @Test public void typeFromTypeName() {\n    TypeName typeName = TypeName.get(String.class);\n    assertThat(CodeBlock.of(\"$T\", typeName).toString()).isEqualTo(\"java.lang.String\");\n  }\n\n  @Test public void typeFromTypeMirror() {\n    TypeMirror mirror = getElement(String.class).asType();\n    assertThat(CodeBlock.of(\"$T\", mirror).toString()).isEqualTo(\"java.lang.String\");\n  }\n\n  @Test public void typeFromTypeElement() {\n    TypeElement element = getElement(String.class);\n    assertThat(CodeBlock.of(\"$T\", element).toString()).isEqualTo(\"java.lang.String\");\n  }\n\n  @Test public void typeFromReflectType() {\n    assertThat(CodeBlock.of(\"$T\", String.class).toString()).isEqualTo(\"java.lang.String\");\n  }\n\n  @Test public void typeFromUnsupportedType() {\n    try {\n      CodeBlock.builder().add(\"$T\", \"java.lang.String\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"expected type but was java.lang.String\");\n    }\n  }\n\n  @Test public void tooFewArguments() {\n    try {\n      CodeBlock.builder().add(\"$S\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"index 1 for '$S' not in range (received 0 arguments)\");\n    }\n  }\n\n  @Test public void unusedArgumentsRelative() {\n    try {\n      CodeBlock.builder().add(\"$L $L\", \"a\", \"b\", \"c\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"unused arguments: expected 2, received 3\");\n    }\n  }\n\n  @Test public void unusedArgumentsIndexed() {\n    try {\n      CodeBlock.builder().add(\"$1L $2L\", \"a\", \"b\", \"c\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"unused argument: $3\");\n    }\n    try {\n      CodeBlock.builder().add(\"$1L $1L $1L\", \"a\", \"b\", \"c\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"unused arguments: $2, $3\");\n    }\n    try {\n      CodeBlock.builder().add(\"$3L $1L $3L $1L $3L\", \"a\", \"b\", \"c\", \"d\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertThat(expected).hasMessageThat().isEqualTo(\"unused arguments: $2, $4\");\n    }\n  }\n\n  @Test public void superClassOnlyValidForClasses() {\n    try {\n      TypeSpec.annotationBuilder(\"A\").superclass(ClassName.get(Object.class));\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n    try {\n      TypeSpec.enumBuilder(\"E\").superclass(ClassName.get(Object.class));\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n    try {\n      TypeSpec.interfaceBuilder(\"I\").superclass(ClassName.get(Object.class));\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void invalidSuperClass() {\n    try {\n      TypeSpec.classBuilder(\"foo\")\n          .superclass(ClassName.get(List.class))\n          .superclass(ClassName.get(Map.class));\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n    try {\n      TypeSpec.classBuilder(\"foo\")\n          .superclass(TypeName.INT);\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void staticCodeBlock() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(String.class, \"foo\", Modifier.PRIVATE)\n        .addField(String.class, \"FOO\", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)\n        .addStaticBlock(CodeBlock.builder()\n            .addStatement(\"FOO = $S\", \"FOO\")\n            .build())\n        .addMethod(MethodSpec.methodBuilder(\"toString\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(String.class)\n            .addCode(\"return FOO;\\n\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  private static final String FOO;\\n\"\n        + \"\\n\"\n        + \"  static {\\n\"\n        + \"    FOO = \\\"FOO\\\";\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  private String foo;\\n\"\n        + \"\\n\"\n        + \"  @Override\\n\"\n        + \"  public String toString() {\\n\"\n        + \"    return FOO;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void initializerBlockInRightPlace() {\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(String.class, \"foo\", Modifier.PRIVATE)\n        .addField(String.class, \"FOO\", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)\n        .addStaticBlock(CodeBlock.builder()\n            .addStatement(\"FOO = $S\", \"FOO\")\n            .build())\n        .addMethod(MethodSpec.constructorBuilder().build())\n        .addMethod(MethodSpec.methodBuilder(\"toString\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(String.class)\n            .addCode(\"return FOO;\\n\")\n            .build())\n        .addInitializerBlock(CodeBlock.builder()\n            .addStatement(\"foo = $S\", \"FOO\")\n            .build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  private static final String FOO;\\n\"\n        + \"\\n\"\n        + \"  static {\\n\"\n        + \"    FOO = \\\"FOO\\\";\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  private String foo;\\n\"\n        + \"\\n\"\n        + \"  {\\n\"\n        + \"    foo = \\\"FOO\\\";\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  Taco() {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  @Override\\n\"\n        + \"  public String toString() {\\n\"\n        + \"    return FOO;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void initializersToBuilder() {\n    // Tests if toBuilder() contains correct static and instance initializers\n    Element originatingElement = getElement(TypeSpecTest.class);\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addField(String.class, \"foo\", Modifier.PRIVATE)\n        .addField(String.class, \"FOO\", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)\n        .addStaticBlock(CodeBlock.builder()\n            .addStatement(\"FOO = $S\", \"FOO\")\n            .build())\n        .addMethod(MethodSpec.constructorBuilder().build())\n        .addMethod(MethodSpec.methodBuilder(\"toString\")\n            .addAnnotation(Override.class)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(String.class)\n            .addCode(\"return FOO;\\n\")\n            .build())\n        .addInitializerBlock(CodeBlock.builder()\n            .addStatement(\"foo = $S\", \"FOO\")\n            .build())\n        .addOriginatingElement(originatingElement)\n        .alwaysQualify(\"com.example.AlwaysQualified\")\n        .build();\n\n    TypeSpec recreatedTaco = taco.toBuilder().build();\n    assertThat(toString(taco)).isEqualTo(toString(recreatedTaco));\n    assertThat(taco.originatingElements)\n        .containsExactlyElementsIn(recreatedTaco.originatingElements);\n    assertThat(taco.alwaysQualifiedNames)\n        .containsExactlyElementsIn(recreatedTaco.alwaysQualifiedNames);\n\n    TypeSpec initializersAdded = taco.toBuilder()\n        .addInitializerBlock(CodeBlock.builder()\n            .addStatement(\"foo = $S\", \"instanceFoo\")\n            .build())\n        .addStaticBlock(CodeBlock.builder()\n            .addStatement(\"FOO = $S\", \"staticFoo\")\n            .build())\n        .build();\n\n    assertThat(toString(initializersAdded)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.Override;\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  private static final String FOO;\\n\"\n        + \"\\n\"\n        + \"  static {\\n\"\n        + \"    FOO = \\\"FOO\\\";\\n\"\n        + \"  }\\n\"\n        + \"  static {\\n\"\n        + \"    FOO = \\\"staticFoo\\\";\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  private String foo;\\n\"\n        + \"\\n\"\n        + \"  {\\n\"\n        + \"    foo = \\\"FOO\\\";\\n\"\n        + \"  }\\n\"\n        + \"  {\\n\"\n        + \"    foo = \\\"instanceFoo\\\";\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  Taco() {\\n\"\n        + \"  }\\n\"\n        + \"\\n\"\n        + \"  @Override\\n\"\n        + \"  public String toString() {\\n\"\n        + \"    return FOO;\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void initializerBlockUnsupportedExceptionOnInterface() {\n    TypeSpec.Builder interfaceBuilder = TypeSpec.interfaceBuilder(\"Taco\");\n    try {\n      interfaceBuilder.addInitializerBlock(CodeBlock.builder().build());\n      fail(\"Exception expected\");\n    } catch (UnsupportedOperationException e) {\n    }\n  }\n\n  @Test public void initializerBlockUnsupportedExceptionOnAnnotation() {\n    TypeSpec.Builder annotationBuilder = TypeSpec.annotationBuilder(\"Taco\");\n    try {\n      annotationBuilder.addInitializerBlock(CodeBlock.builder().build());\n      fail(\"Exception expected\");\n    } catch (UnsupportedOperationException e) {\n    }\n  }\n\n  @Test public void lineWrapping() {\n    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(\"call\");\n    methodBuilder.addCode(\"$[call(\");\n    for (int i = 0; i < 32; i++) {\n      methodBuilder.addParameter(String.class, \"s\" + i);\n      methodBuilder.addCode(i > 0 ? \",$W$S\" : \"$S\", i);\n    }\n    methodBuilder.addCode(\");$]\\n\");\n\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(methodBuilder.build())\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"import java.lang.String;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  void call(String s0, String s1, String s2, String s3, String s4, String s5, String s6, String s7,\\n\"\n        + \"      String s8, String s9, String s10, String s11, String s12, String s13, String s14, String s15,\\n\"\n        + \"      String s16, String s17, String s18, String s19, String s20, String s21, String s22,\\n\"\n        + \"      String s23, String s24, String s25, String s26, String s27, String s28, String s29,\\n\"\n        + \"      String s30, String s31) {\\n\"\n        + \"    call(\\\"0\\\", \\\"1\\\", \\\"2\\\", \\\"3\\\", \\\"4\\\", \\\"5\\\", \\\"6\\\", \\\"7\\\", \\\"8\\\", \\\"9\\\", \\\"10\\\", \\\"11\\\", \\\"12\\\", \\\"13\\\", \\\"14\\\", \\\"15\\\", \\\"16\\\",\\n\"\n        + \"        \\\"17\\\", \\\"18\\\", \\\"19\\\", \\\"20\\\", \\\"21\\\", \\\"22\\\", \\\"23\\\", \\\"24\\\", \\\"25\\\", \\\"26\\\", \\\"27\\\", \\\"28\\\", \\\"29\\\", \\\"30\\\", \\\"31\\\");\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void lineWrappingWithZeroWidthSpace() {\n    MethodSpec method = MethodSpec.methodBuilder(\"call\")\n        .addCode(\"$[iAmSickOfWaitingInLine($Z\")\n        .addCode(\"it, has, been, far, too, long, of, a, wait, and, i, would, like, to, eat, \")\n        .addCode(\"this, is, a, run, on, sentence\")\n        .addCode(\");$]\\n\")\n        .build();\n\n    TypeSpec taco = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(method)\n        .build();\n    assertThat(toString(taco)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"class Taco {\\n\"\n        + \"  void call() {\\n\"\n        + \"    iAmSickOfWaitingInLine(\\n\"\n        + \"        it, has, been, far, too, long, of, a, wait, and, i, would, like, to, eat, this, is, a, run, on, sentence);\\n\"\n        + \"  }\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void equalsAndHashCode() {\n    TypeSpec a = TypeSpec.interfaceBuilder(\"taco\").build();\n    TypeSpec b = TypeSpec.interfaceBuilder(\"taco\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    a = TypeSpec.classBuilder(\"taco\").build();\n    b = TypeSpec.classBuilder(\"taco\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    a = TypeSpec.enumBuilder(\"taco\").addEnumConstant(\"SALSA\").build();\n    b = TypeSpec.enumBuilder(\"taco\").addEnumConstant(\"SALSA\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n    a = TypeSpec.annotationBuilder(\"taco\").build();\n    b = TypeSpec.annotationBuilder(\"taco\").build();\n    assertThat(a.equals(b)).isTrue();\n    assertThat(a.hashCode()).isEqualTo(b.hashCode());\n  }\n\n  @Test public void classNameFactories() {\n    ClassName className = ClassName.get(\"com.example\", \"Example\");\n    assertThat(TypeSpec.classBuilder(className).build().name).isEqualTo(\"Example\");\n    assertThat(TypeSpec.interfaceBuilder(className).build().name).isEqualTo(\"Example\");\n    assertThat(TypeSpec.enumBuilder(className).addEnumConstant(\"A\").build().name).isEqualTo(\"Example\");\n    assertThat(TypeSpec.annotationBuilder(className).build().name).isEqualTo(\"Example\");\n  }\n\n  @Test\n  public void modifyAnnotations() {\n    TypeSpec.Builder builder =\n        TypeSpec.classBuilder(\"Taco\")\n            .addAnnotation(Override.class)\n            .addAnnotation(SuppressWarnings.class);\n\n    builder.annotations.remove(1);\n    assertThat(builder.build().annotations).hasSize(1);\n  }\n\n  @Test\n  public void modifyModifiers() {\n    TypeSpec.Builder builder =\n        TypeSpec.classBuilder(\"Taco\").addModifiers(Modifier.PUBLIC, Modifier.FINAL);\n\n    builder.modifiers.remove(1);\n    assertThat(builder.build().modifiers).containsExactly(Modifier.PUBLIC);\n  }\n\n  @Test\n  public void modifyFields() {\n    TypeSpec.Builder builder = TypeSpec.classBuilder(\"Taco\")\n        .addField(int.class, \"source\");\n\n    builder.fieldSpecs.remove(0);\n    assertThat(builder.build().fieldSpecs).isEmpty();\n  }\n\n  @Test\n  public void modifyTypeVariables() {\n    TypeVariableName t = TypeVariableName.get(\"T\");\n    TypeSpec.Builder builder =\n        TypeSpec.classBuilder(\"Taco\")\n            .addTypeVariable(t)\n            .addTypeVariable(TypeVariableName.get(\"V\"));\n\n    builder.typeVariables.remove(1);\n    assertThat(builder.build().typeVariables).containsExactly(t);\n  }\n\n  @Test\n  public void modifySuperinterfaces() {\n    TypeSpec.Builder builder = TypeSpec.classBuilder(\"Taco\")\n        .addSuperinterface(File.class);\n\n    builder.superinterfaces.clear();\n    assertThat(builder.build().superinterfaces).isEmpty();\n  }\n\n  @Test\n  public void modifyMethods() {\n    TypeSpec.Builder builder = TypeSpec.classBuilder(\"Taco\")\n        .addMethod(MethodSpec.methodBuilder(\"bell\").build());\n\n    builder.methodSpecs.clear();\n    assertThat(builder.build().methodSpecs).isEmpty();\n  }\n\n  @Test\n  public void modifyTypes() {\n    TypeSpec.Builder builder = TypeSpec.classBuilder(\"Taco\")\n        .addType(TypeSpec.classBuilder(\"Bell\").build());\n\n    builder.typeSpecs.clear();\n    assertThat(builder.build().typeSpecs).isEmpty();\n  }\n\n  @Test\n  public void modifyEnumConstants() {\n    TypeSpec constantType = TypeSpec.anonymousClassBuilder(\"\").build();\n    TypeSpec.Builder builder = TypeSpec.enumBuilder(\"Taco\")\n        .addEnumConstant(\"BELL\", constantType)\n        .addEnumConstant(\"WUT\", TypeSpec.anonymousClassBuilder(\"\").build());\n\n    builder.enumConstants.remove(\"WUT\");\n    assertThat(builder.build().enumConstants).containsExactly(\"BELL\", constantType);\n  }\n\n  @Test\n  public void modifyOriginatingElements() {\n    TypeSpec.Builder builder = TypeSpec.classBuilder(\"Taco\")\n        .addOriginatingElement(Mockito.mock(Element.class));\n\n    builder.originatingElements.clear();\n    assertThat(builder.build().originatingElements).isEmpty();\n  }\n    \n  @Test public void javadocWithTrailingLineDoesNotAddAnother() {\n    TypeSpec spec = TypeSpec.classBuilder(\"Taco\")\n        .addJavadoc(\"Some doc with a newline\\n\")\n        .build();\n\n    assertThat(toString(spec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"/**\\n\"\n        + \" * Some doc with a newline\\n\"\n        + \" */\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n\n  @Test public void javadocEnsuresTrailingLine() {\n    TypeSpec spec = TypeSpec.classBuilder(\"Taco\")\n        .addJavadoc(\"Some doc with a newline\")\n        .build();\n\n    assertThat(toString(spec)).isEqualTo(\"\"\n        + \"package com.squareup.tacos;\\n\"\n        + \"\\n\"\n        + \"/**\\n\"\n        + \" * Some doc with a newline\\n\"\n        + \" */\\n\"\n        + \"class Taco {\\n\"\n        + \"}\\n\");\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/TypesEclipseTest.java",
    "content": "/*\n * Copyright (C) 2014 Google, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport static com.google.common.base.Charsets.*;\nimport static com.google.common.base.Preconditions.*;\n\nimport java.util.Locale;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport javax.annotation.processing.AbstractProcessor;\nimport javax.annotation.processing.ProcessingEnvironment;\nimport javax.annotation.processing.Processor;\nimport javax.annotation.processing.RoundEnvironment;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.util.Elements;\nimport javax.lang.model.util.Types;\nimport javax.tools.DiagnosticCollector;\nimport javax.tools.JavaCompiler;\nimport javax.tools.JavaFileManager;\nimport javax.tools.JavaFileObject;\n\nimport org.eclipse.jdt.internal.compiler.tool.EclipseCompiler;\nimport org.junit.Rule;\nimport org.junit.rules.TestRule;\nimport org.junit.runner.Description;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.junit.runners.model.Statement;\n\nimport com.google.common.collect.ImmutableList;\nimport com.google.common.collect.ImmutableSet;\n\n@RunWith(JUnit4.class)\npublic final class TypesEclipseTest extends AbstractTypesTest {\n  /**\n   * A {@link JUnit4} {@link Rule} that executes tests such that a instances of {@link Elements} and\n   * {@link Types} are available during execution.\n   *\n   * <p>To use this rule in a test, just add the following field: <pre>   {@code\n   *   @Rule public CompilationRule compilationRule = new CompilationRule();}\n   *\n   * @author Gregory Kick\n   */\n  public static final class CompilationRule implements TestRule {\n    private Elements elements;\n    private Types types;\n\n    @Override\n    public Statement apply(final Statement base, Description description) {\n      return new Statement() {\n        @Override public void evaluate() throws Throwable {\n          final AtomicReference<Throwable> thrown = new AtomicReference<>();\n          boolean successful = compile(ImmutableList.of(new AbstractProcessor() {\n            @Override\n            public SourceVersion getSupportedSourceVersion() {\n              return SourceVersion.latest();\n            }\n\n            @Override\n            public Set<String> getSupportedAnnotationTypes() {\n              return ImmutableSet.of(\"*\");\n            }\n\n            @Override\n            public synchronized void init(ProcessingEnvironment processingEnv) {\n              super.init(processingEnv);\n              elements = processingEnv.getElementUtils();\n              types = processingEnv.getTypeUtils();\n            }\n\n            @Override\n            public boolean process(Set<? extends TypeElement> annotations,\n                RoundEnvironment roundEnv) {\n              // just run the test on the last round after compilation is over\n              if (roundEnv.processingOver()) {\n                try {\n                  base.evaluate();\n                } catch (Throwable e) {\n                  thrown.set(e);\n                }\n              }\n              return false;\n            }\n          }));\n          checkState(successful);\n          Throwable t = thrown.get();\n          if (t != null) {\n            throw t;\n          }\n        }\n      };\n    }\n\n    /**\n     * Returns the {@link Elements} instance associated with the current execution of the rule.\n     *\n     * @throws IllegalStateException if this method is invoked outside the execution of the rule.\n     */\n    public Elements getElements() {\n      checkState(elements != null, \"Not running within the rule\");\n      return elements;\n    }\n\n    /**\n     * Returns the {@link Types} instance associated with the current execution of the rule.\n     *\n     * @throws IllegalStateException if this method is invoked outside the execution of the rule.\n     */\n    public Types getTypes() {\n      checkState(elements != null, \"Not running within the rule\");\n      return types;\n    }\n\n    static private boolean compile(Iterable<? extends Processor> processors) {\n      JavaCompiler compiler = new EclipseCompiler();\n      DiagnosticCollector<JavaFileObject> diagnosticCollector =\n          new DiagnosticCollector<>();\n      JavaFileManager fileManager = compiler.getStandardFileManager(diagnosticCollector, Locale.getDefault(), UTF_8);\n      JavaCompiler.CompilationTask task = compiler.getTask(\n          null,\n          fileManager,\n          diagnosticCollector,\n          ImmutableSet.of(),\n          ImmutableSet.of(TypesEclipseTest.class.getCanonicalName()),\n          ImmutableSet.of());\n      task.setProcessors(processors);\n      return task.call();\n    }\n  }\n\n  @Rule public final CompilationRule compilation = new CompilationRule();\n\n  @Override\n  protected Elements getElements() {\n    return compilation.getElements();\n  }\n\n  @Override\n  protected Types getTypes() {\n    return compilation.getTypes();\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/TypesTest.java",
    "content": "/*\n * Copyright (C) 2014 Google, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport javax.lang.model.util.Elements;\nimport javax.lang.model.util.Types;\n\nimport org.junit.Rule;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport com.google.testing.compile.CompilationRule;\n\n@RunWith(JUnit4.class)\npublic final class TypesTest extends AbstractTypesTest {\n  @Rule public final CompilationRule compilation = new CompilationRule();\n\n  @Override\n  protected Elements getElements() {\n    return compilation.getElements();\n  }\n\n  @Override\n  protected Types getTypes() {\n    return compilation.getTypes();\n  }\n}\n"
  },
  {
    "path": "src/test/java/com/squareup/javapoet/UtilTest.java",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.javapoet;\n\nimport static org.junit.Assert.assertEquals;\n\nimport org.junit.Test;\n\npublic class UtilTest {\n  @Test public void characterLiteral() {\n    assertEquals(\"a\", Util.characterLiteralWithoutSingleQuotes('a'));\n    assertEquals(\"b\", Util.characterLiteralWithoutSingleQuotes('b'));\n    assertEquals(\"c\", Util.characterLiteralWithoutSingleQuotes('c'));\n    assertEquals(\"%\", Util.characterLiteralWithoutSingleQuotes('%'));\n    // common escapes\n    assertEquals(\"\\\\b\", Util.characterLiteralWithoutSingleQuotes('\\b'));\n    assertEquals(\"\\\\t\", Util.characterLiteralWithoutSingleQuotes('\\t'));\n    assertEquals(\"\\\\n\", Util.characterLiteralWithoutSingleQuotes('\\n'));\n    assertEquals(\"\\\\f\", Util.characterLiteralWithoutSingleQuotes('\\f'));\n    assertEquals(\"\\\\r\", Util.characterLiteralWithoutSingleQuotes('\\r'));\n    assertEquals(\"\\\"\", Util.characterLiteralWithoutSingleQuotes('\"'));\n    assertEquals(\"\\\\'\", Util.characterLiteralWithoutSingleQuotes('\\''));\n    assertEquals(\"\\\\\\\\\", Util.characterLiteralWithoutSingleQuotes('\\\\'));\n    // octal escapes\n    assertEquals(\"\\\\u0000\", Util.characterLiteralWithoutSingleQuotes('\\0'));\n    assertEquals(\"\\\\u0007\", Util.characterLiteralWithoutSingleQuotes('\\7'));\n    assertEquals(\"?\", Util.characterLiteralWithoutSingleQuotes('\\77'));\n    assertEquals(\"\\\\u007f\", Util.characterLiteralWithoutSingleQuotes('\\177'));\n    assertEquals(\"¿\", Util.characterLiteralWithoutSingleQuotes('\\277'));\n    assertEquals(\"ÿ\", Util.characterLiteralWithoutSingleQuotes('\\377'));\n    // unicode escapes\n    assertEquals(\"\\\\u0000\", Util.characterLiteralWithoutSingleQuotes('\\u0000'));\n    assertEquals(\"\\\\u0001\", Util.characterLiteralWithoutSingleQuotes('\\u0001'));\n    assertEquals(\"\\\\u0002\", Util.characterLiteralWithoutSingleQuotes('\\u0002'));\n    assertEquals(\"€\", Util.characterLiteralWithoutSingleQuotes('\\u20AC'));\n    assertEquals(\"☃\", Util.characterLiteralWithoutSingleQuotes('\\u2603'));\n    assertEquals(\"♠\", Util.characterLiteralWithoutSingleQuotes('\\u2660'));\n    assertEquals(\"♣\", Util.characterLiteralWithoutSingleQuotes('\\u2663'));\n    assertEquals(\"♥\", Util.characterLiteralWithoutSingleQuotes('\\u2665'));\n    assertEquals(\"♦\", Util.characterLiteralWithoutSingleQuotes('\\u2666'));\n    assertEquals(\"✵\", Util.characterLiteralWithoutSingleQuotes('\\u2735'));\n    assertEquals(\"✺\", Util.characterLiteralWithoutSingleQuotes('\\u273A'));\n    assertEquals(\"／\", Util.characterLiteralWithoutSingleQuotes('\\uFF0F'));\n  }\n\n  @Test public void stringLiteral() {\n    stringLiteral(\"abc\");\n    stringLiteral(\"♦♥♠♣\");\n    stringLiteral(\"€\\\\t@\\\\t$\", \"€\\t@\\t$\", \" \");\n    stringLiteral(\"abc();\\\\n\\\"\\n  + \\\"def();\", \"abc();\\ndef();\", \" \");\n    stringLiteral(\"This is \\\\\\\"quoted\\\\\\\"!\", \"This is \\\"quoted\\\"!\", \" \");\n    stringLiteral(\"e^{i\\\\\\\\pi}+1=0\", \"e^{i\\\\pi}+1=0\", \" \");\n  }\n\n  void stringLiteral(String string) {\n    stringLiteral(string, string, \" \");\n  }\n\n  void stringLiteral(String expected, String value, String indent) {\n    assertEquals(\"\\\"\" + expected + \"\\\"\", Util.stringLiteralWithDoubleQuotes(value, indent));\n  }\n}\n"
  }
]