pax_global_header 0000666 0000000 0000000 00000000064 13355454760 0014526 g ustar 00root root 0000000 0000000 52 comment=2f4182ec303e020e592d8893cf612214df5bf96a
javapoet-1.11.1/ 0000775 0000000 0000000 00000000000 13355454760 0013420 5 ustar 00root root 0000000 0000000 javapoet-1.11.1/.buildscript/ 0000775 0000000 0000000 00000000000 13355454760 0016022 5 ustar 00root root 0000000 0000000 javapoet-1.11.1/.buildscript/deploy_snapshot.sh 0000775 0000000 0000000 00000001761 13355454760 0021601 0 ustar 00root root 0000000 0000000 #!/bin/bash
#
# Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo.
#
# Adapted from https://coderwall.com/p/9b_lfq and
# https://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/
SLUG="square/javapoet"
JDK="oraclejdk8"
BRANCH="master"
set -e
if [ "$TRAVIS_REPO_SLUG" != "$SLUG" ]; then
echo "Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'."
elif [ "$TRAVIS_JDK_VERSION" != "$JDK" ]; then
echo "Skipping snapshot deployment: wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'."
elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
echo "Skipping snapshot deployment: was pull request."
elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then
echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'."
else
echo "Deploying snapshot..."
mvn clean source:jar javadoc:jar deploy --settings=".buildscript/settings.xml" -Dmaven.test.skip=true
echo "Snapshot deployed!"
fi
javapoet-1.11.1/.buildscript/settings.xml 0000664 0000000 0000000 00000000335 13355454760 0020405 0 ustar 00root root 0000000 0000000 sonatype-nexus-snapshots${env.CI_DEPLOY_USERNAME}${env.CI_DEPLOY_PASSWORD}
javapoet-1.11.1/.gitignore 0000664 0000000 0000000 00000000226 13355454760 0015410 0 ustar 00root root 0000000 0000000 .classpath
.project
.settings
.checkstyle
eclipsebin
bin
gen
build
out
lib
target
pom.xml.*
release.properties
.idea
*.iml
classes
obj
.DS_Store
javapoet-1.11.1/.travis.yml 0000664 0000000 0000000 00000002515 13355454760 0015534 0 ustar 00root root 0000000 0000000 language: java
matrix:
include:
- env: JDK='Oracle JDK 8'
jdk: oraclejdk8
- env: JDK='Oracle JDK 9'
jdk: oraclejdk9
- env: JDK='Oracle JDK 10'
install: . ./install-jdk.sh -F 10 -L BCL
- env: JDK='OpenJDK 10'
install: . ./install-jdk.sh -F 10 -L GPL
- env: JDK='Oracle JDK 11'
install: . ./install-jdk.sh -F 11 -L BCL
- env: JDK='OpenJDK 11'
install: . ./install-jdk.sh -F 11 -L GPL
allow_failures:
# ErrorProne/javac is not yet working on JDK 11
- env: JDK='Oracle JDK 11'
- env: JDK='OpenJDK 11'
# Direct usage of `install-jdk.sh` might be superseded by https://github.com/travis-ci/travis-build/pull/1347
before_install:
- unset _JAVA_OPTIONS
- wget https://github.com/sormuras/bach/raw/1.0.1/install-jdk.sh
after_success:
- .buildscript/deploy_snapshot.sh
env:
global:
- secure: "nkVNCk8H2orIZOmow0t+Qub1lFQCYpJgNZf17zYI5x0JVqQNCqkcTYYDHqzwkvkmixXFCrfYZQuXy7x2qg9zjCX+vmhlmiMWwe8dNa34OLTseuuR2irS0C8nRGRYxKM7EGenRZSqbFVUksKRm2iWnHKxtmCzeDaS7MoMit2wdUo="
- secure: "j8+hPaZnyM+UlOBYOEA96fPbVWbN6bMQ28SGQnFMwxo2axHi9ww9Au1N7002HzHnxX8iyesdWFBigArnEL8zKEoXH9Bmur0sn3Ys4bu72C3ozscP4cjXfYSHj8aVLp1EIMdQPDF7MkCccx9l7ONdsW0ltmdiVUtDxzqkH+63WLU="
branches:
except:
- gh-pages
notifications:
email: false
sudo: false
cache:
directories:
- $HOME/.m2
javapoet-1.11.1/CHANGELOG.md 0000664 0000000 0000000 00000025101 13355454760 0015230 0 ustar 00root root 0000000 0000000 Change Log
==========
JavaPoet 1.11.1 *(2018-05-16)*
-----------------------------
* Fix: JavaPoet 1.11 had a regression where `TypeName.get()` would throw on error types, masking
other errors in an annotation processing round. This is fixed with a test to prevent future
regressions!
JavaPoet 1.11.0 *(2018-04-29)*
-----------------------------
* New: Support `TYPE_USE` annotations on each enclosing `ClassName`.
* New: Work around a compiler bug in `TypeName.get(TypeElement)`. There was a problem getting an
element's kind when building from source ABIs.
JavaPoet 1.10.0 *(2018-01-27)*
-----------------------------
* **JavaPoet now requires Java 8 or newer.**
* New: `$Z` as an optional newline (zero-width space) if a line may exceed 100 chars.
* New: `CodeBlock.join()` and `CodeBlock.joining()` let you join codeblocks by delimiters.
* New: Add `CodeBlock.Builder.isEmpty()`.
* New: `addStatement(CodeBlock)` overloads for `CodeBlock` and `MethodSpec`.
* Fix: Include annotations when emitting type variables.
* Fix: Use the right imports for annotated type parameters.
* Fix: Don't incorrectly escape classnames that start with `$`.
JavaPoet 1.9.0 *(2017-05-13)*
-----------------------------
* Fix: Don't emit incorrect code when the declared type's signature references another type with
the same simple name.
* Fix: Support anonymous inner classes in `ClassName.get()`.
* New: `MethodSpec.Builder.addNamedCode()` and `TypeSpec.anonymousClassBuilder(CodeBlock)`.
JavaPoet 1.8.0 *(2016-11-09)*
-----------------------------
* New: Basic support for line wrapping. Use `$W` to insert a Wrappable Whitespace character. It'll
emit either a single space or a newline with appropriate indentation.
* New: Named arguments in `CodeBlock`. These are intended to make larger code snippets easier to
read:
```
Map map = new LinkedHashMap<>();
map.put("count", 3);
map.put("greeting", "Hello, ");
map.put("system", System.class);
String template = ""
+ "for (int i = 0; i < $count:L; i++) {\n"
+ " $system:T.out.println($greeting:S + list.get(i));\n"
+ "}\n";
CodeBlock.Builder builder = CodeBlock.builder();
builder.addNamed(template, map);
```
* New: `addJavadoc(CodeBlock)` overloads for TypeSpec, MethodSpec, and FieldSpec.
* New: `MethodSpec.addComment()` makes it easy to add a `// single-line comment.`
* New: `ClassName.getReflectionName()` returns a string like `java.util.Map$Entry`.
* Fix: Always write UTF-8. Previously JavaPoet would use the system default charset which was
potentially inconsistent across environments.
* Fix: Permit (constant) fields to be defined in annotation types.
JavaPoet 1.7.0 *(2016-04-26)*
-----------------------------
* New: Support parameterized types that enclose other types, like `Outer.Inner`.
* New: `TypeName.isBoxedPrimitive()`.
JavaPoet 1.6.1 *(2016-03-21)*
-----------------------------
* Fix: Double quotes and backslashes in string literals were not properly quoted in 1.6.0. This is
now fixed.
JavaPoet 1.6.0 *(2016-03-19)*
-----------------------------
* New: Revive `CodeBlock.of()`, a handy factory method for building code blocks.
* New: Add `TypeSpec` factory methods that take a `ClassName`.
* New: `TypeName.annotated()` adds an annotation to a type.
* New: `TypeVariableName.withBounds()` adds bounds to a type variable.
* New: `TypeSpec.Builder.addInitializerBlock()` adds an instance initializer.
* Fix: Make `TypeSpec.Kind` enum public. This can be used to check if a `TypeSpec` is a class,
interface, enum, or annotation.
* Fix: Don’t break import resolution on annotated types.
* Fix: Forbid unexpected modifiers like `private` on annotation members.
* Fix: Deduplicate exceptions in `MethodSpec.Builder`.
* Fix: Treat `ErrorType` like a regular `DeclaredType` in `TypeName.get()`. This should make it
easier to write annotation processors.
JavaPoet 1.5.1 *(2016-01-10)*
-----------------------------
* Fix: Annotated `TypeName` instances are only equal if their annotations are equal.
JavaPoet 1.5.0 *(2016-01-10)*
-----------------------------
* New: `import static`! See `JavaFile.Builder.addStaticImport()` variants.
* New: Overload `NameAllocator.newName(String)` for creating a one-off name without a tag.
* Fix: AnnotationSpec escapes character literals properly.
* Fix: Don't stack overflow when `TypeVariableName` is part of `ParameterizedTypeName`.
* Fix: Reporting not used indexed arguments in like `add("$1S", "a", "b")`.
* Fix: Prevent import of types located in the default package, i.e. have no package name.
JavaPoet 1.4.0 *(2015-11-13)*
-----------------------------
* New: `AnnotationSpec.get(Annotation)`.
* New: Type annotations! `TypeName.annotated()` can attach annotations like `@Nullable` directly to
types. This works for both top-level types and type parameters as in `List<@Nullable String>`.
* New: `equals()` and `hashCode()` on `AnnotationSpec`, `CodeBlock`, `FieldSpec`, `JavaFile`,
`MethodSpec`, `ParameterSpec`, `TypeName`, and `TypeSpec`.
* New: `NameAllocator.clone()` to refine a NameAllocator for use in an inner scope code block.
* Fix: Don't stack overflow when `TypeVariableName` gets a self-referential type.
* Fix: Better handling of name collisions on imports. Previously JavaPoet did the wrong thing when
a referenced type and a nested types had the same name.
JavaPoet 1.3.0 *(2015-09-20)*
-----------------------------
* New: `NameAllocator` API makes it easy to declare non-conflicting names.
* New: Support annotations on enum values.
* Fix: Avoid infinite recursion in `TypeName.get(TypeMirror)`.
* Fix: Use qualified name for conflicting simple names in the same file.
* Fix: Better messages for parameter indexing errors.
JavaPoet 1.2.0 *(2015-07-04)*
-----------------------------
* New: Arguments may have positional indexes like `$1T` and `$2N`. Indexes can be used to refer to
the same argument multiple times in a single format string.
* New: Permit Javadoc on enum constants.
* New: Class initializer blocks with `addStaticBlock()`.
* Fix: `MethodSpec.overriding()` retains annotations.
JavaPoet 1.1.0 *(2015-05-25)*
-----------------------------
* New: Eager validation of argument types like `$T` and `$N`.
* New: `MethodSpec.varargs(boolean)` to generate varags methods.
* New: `AnnotationSpec.get()` and `MethodSpec.overriding()` to create annotations and methods from
the `javax.lang.model` API.
* New: `JavaFile.toJavaFileObject()`.
* New: Java 8 `DEFAULT` modifier.
* New: `toBuilder()` methods to build upon objects already constructed.
* New: Generate `@interface` annotation types.
* New: `TypeName.box()` and `TypeName.unbox()` convenience APIs.
* Fix: `nextControlFlow()` accepts arguments.
* Fix: Reject duplicate calls to set the superclass.
* Fix: `WildcardTypeName.get(WildcardType)` no longer throws a `NullPointerException`.
* Fix: Don't allow double field initialization.
JavaPoet 1.0.0 *(2015-01-28)*
-----------------------------
* This update is a complete rewrite. The project name is now `javapoet`. We renamed the it so you
can simultaneously use the old JavaWriter API and our new builder-based APIs in one project.
* Immutable value objects and builders. Instead of streaming the `.java` file from top to bottom,
you now define members in whatever way is convenient.
* We now use our own models for type names.
* Imports are now added automatically.
JavaWriter 2.5.1 *(2014-12-03)*
-------------------------------
* New: `StringLiteral` type which encapsulates the behavior of `stringLiteral`.
* Fix: Use canonical name when emitting a class import.
* Fix: Apply type compression to varargs and array types.
* Fix: Restore binary compatibility with pre-2.5 versions.
JavaWriter 2.5.0 *(2014-04-18)*
-------------------------------
* New: Methods in interfaces will always have no body declaration.
* New: Control flow begin declaration now supports String format arguments.
* Fix: Truncate any generic type when emitting constructors.
* Fix: Do not emit trailing whitespace after '=' at end-of-line.
JavaWriter 2.4.0 *(2014-01-10)*
-------------------------------
* New: Properly indent hanging lines in field initializers.
* New: `emitEnumValue` variant which exposes a boolean of whether the current value is the last.
JavaWriter 2.3.1 *(2013-12-16)*
-------------------------------
* Fix: Properly handle subpackages of `java.lang` in `compressType`.
JavaWriter 2.3.0 *(2013-11-24)*
-------------------------------
* New: Configurable indent level via `setIndent`.
* New: `beginConstructor` method is a semantically clearer alternative for constructors.
* New: `emitEnumValues` method emits a list of values followed by semicolon.
* `emitImports` now supports `Class` arguments directly.
* Previously-deprecated, `int`-based modifier methods have been removed.
JavaWriter 2.2.1 *(2013-10-23)*
-------------------------------
* Fix: Do not emit trailing whitespace for empty Javadoc lines.
JavaWriter 2.2.0 *(2013-09-25)*
-------------------------------
* `setCompressingTypes` controls whether types are emitted as fully-qualified or not.
JavaWriter 2.1.2 *(2013-08-23)*
-------------------------------
* Attempt to keep annotations on a single line.
JavaWriter 2.1.1 *(2013-07-23)*
-------------------------------
* Fix: `stringLiteral` now correctly handles escapes and control characters.
JavaWriter 2.1.0 *(2013-07-15)*
-------------------------------
* New: All methods now take a `Set` of `Modifier`s rather than an `int`. The `int` methods are
now deprecated for removal in JavaPoet 1.0.
* Annotations with a single "value" attribute will now omit the key.
JavaWriter 2.0.1 *(2013-06-17)*
-------------------------------
* Correct casing of `emitSingleLineComment`.
JavaWriter 2.0.0 *(2013-06-06)*
-------------------------------
* Package name is now `com.squareup.javawriter`.
* Support declaring `throws` clause on methods.
JavaWriter 1.0.5 *(2013-05-08)*
-------------------------------
* Fix: Fully qualify types whose simple name matches an import.
JavaWriter 1.0.4 *(2013-03-15)*
-------------------------------
* Fix: Static import emit now properly supports method imports.
JavaWriter 1.0.3 *(2013-02-21)*
-------------------------------
* Add support for emitting static imports.
JavaWriter 1.0.2 *(2013-02-11)*
-------------------------------
* Add `type` API for helping build generic types.
* Minor performance improvements.
JavaWriter 1.0.1 *(2013-02-03)*
-------------------------------
* Expose `compressType` API.
JavaWriter 1.0.0 *(2013-02-01)*
-------------------------------
Initial release.
javapoet-1.11.1/CONTRIBUTING.md 0000664 0000000 0000000 00000001322 13355454760 0015647 0 ustar 00root root 0000000 0000000 Contributing
============
If you would like to contribute code you can do so through GitHub by forking
the repository and sending a pull request.
When submitting code, please make every effort to follow existing conventions
and style in order to keep the code as readable as possible. Please also make
sure your code compiles by running `mvn clean verify`. Checkstyle failures
during compilation indicate errors in your style and can be viewed in the
`checkstyle-result.xml` file.
Before your code can be accepted into the project you must also sign the
[Individual Contributor License Agreement (CLA)][1].
[1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1
javapoet-1.11.1/LICENSE.txt 0000664 0000000 0000000 00000026136 13355454760 0015253 0 ustar 00root root 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
javapoet-1.11.1/README.md 0000664 0000000 0000000 00000063477 13355454760 0014720 0 ustar 00root root 0000000 0000000 JavaPoet
========
`JavaPoet` is a Java API for generating `.java` source files.
Source file generation can be useful when doing things such as annotation processing or interacting
with metadata files (e.g., database schemas, protocol formats). By generating code, you eliminate
the need to write boilerplate while also keeping a single source of truth for the metadata.
### Example
Here's a (boring) `HelloWorld` class:
```java
package com.example.helloworld;
public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, JavaPoet!");
}
}
```
And this is the (exciting) code to generate it with JavaPoet:
```java
MethodSpec main = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build();
javaFile.writeTo(System.out);
```
To declare the main method, we've created a `MethodSpec` "main" configured with modifiers, return
type, parameters and code statements. We add the main method to a `HelloWorld` class, and then add
that to a `HelloWorld.java` file.
In this case we write the file to `System.out`, but we could also get it as a string
(`JavaFile.toString()`) or write it to the file system (`JavaFile.writeTo()`).
The [Javadoc][javadoc] catalogs the complete JavaPoet API, which we explore below.
### Code & Control Flow
Most of JavaPoet's API uses plain old immutable Java objects. There's also builders, method chaining
and varargs to make the API friendly. JavaPoet offers models for classes & interfaces (`TypeSpec`),
fields (`FieldSpec`), methods & constructors (`MethodSpec`), parameters (`ParameterSpec`) and
annotations (`AnnotationSpec`).
But the _body_ of methods and constructors is not modeled. There's no expression class, no
statement class or syntax tree nodes. Instead, JavaPoet uses strings for code blocks:
```java
MethodSpec main = MethodSpec.methodBuilder("main")
.addCode(""
+ "int total = 0;\n"
+ "for (int i = 0; i < 10; i++) {\n"
+ " total += i;\n"
+ "}\n")
.build();
```
Which generates this:
```java
void main() {
int total = 0;
for (int i = 0; i < 10; i++) {
total += i;
}
}
```
The manual semicolons, line wrapping, and indentation are tedious and so JavaPoet offers APIs to
make it easier. There's `addStatement()` which takes care of semicolons and newline, and
`beginControlFlow()` + `endControlFlow()` which are used together for braces, newlines, and
indentation:
```java
MethodSpec main = MethodSpec.methodBuilder("main")
.addStatement("int total = 0")
.beginControlFlow("for (int i = 0; i < 10; i++)")
.addStatement("total += i")
.endControlFlow()
.build();
```
This example is lame because the generated code is constant! Suppose instead of just adding 0 to 10,
we want to make the operation and range configurable. Here's a method that generates a method:
```java
private MethodSpec computeRange(String name, int from, int to, String op) {
return MethodSpec.methodBuilder(name)
.returns(int.class)
.addStatement("int result = 1")
.beginControlFlow("for (int i = " + from + "; i < " + to + "; i++)")
.addStatement("result = result " + op + " i")
.endControlFlow()
.addStatement("return result")
.build();
}
```
And here's what we get when we call `computeRange("multiply10to20", 10, 20, "*")`:
```java
int multiply10to20() {
int result = 1;
for (int i = 10; i < 20; i++) {
result = result * i;
}
return result;
}
```
Methods generating methods! And since JavaPoet generates source instead of bytecode, you can
read through it to make sure it's right.
### $L for Literals
The string-concatenation in calls to `beginControlFlow()` and `addStatement` is distracting. Too
many operators. To address this, JavaPoet offers a syntax inspired-by but incompatible-with
[`String.format()`][formatter]. It accepts **`$L`** to emit a **literal** value in the output. This
works just like `Formatter`'s `%s`:
```java
private MethodSpec computeRange(String name, int from, int to, String op) {
return MethodSpec.methodBuilder(name)
.returns(int.class)
.addStatement("int result = 0")
.beginControlFlow("for (int i = $L; i < $L; i++)", from, to)
.addStatement("result = result $L i", op)
.endControlFlow()
.addStatement("return result")
.build();
}
```
Literals are emitted directly to the output code with no escaping. Arguments for literals may be
strings, primitives, and a few JavaPoet types described below.
### $S for Strings
When emitting code that includes string literals, we can use **`$S`** to emit a **string**, complete
with wrapping quotation marks and escaping. Here's a program that emits 3 methods, each of which
returns its own name:
```java
public static void main(String[] args) throws Exception {
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(whatsMyName("slimShady"))
.addMethod(whatsMyName("eminem"))
.addMethod(whatsMyName("marshallMathers"))
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build();
javaFile.writeTo(System.out);
}
private static MethodSpec whatsMyName(String name) {
return MethodSpec.methodBuilder(name)
.returns(String.class)
.addStatement("return $S", name)
.build();
}
```
In this case, using `$S` gives us quotation marks:
```java
public final class HelloWorld {
String slimShady() {
return "slimShady";
}
String eminem() {
return "eminem";
}
String marshallMathers() {
return "marshallMathers";
}
}
```
### $T for Types
We Java programmers love our types: they make our code easier to understand. And JavaPoet is on
board. It has rich built-in support for types, including automatic generation of `import`
statements. Just use **`$T`** to reference **types**:
```java
MethodSpec today = MethodSpec.methodBuilder("today")
.returns(Date.class)
.addStatement("return new $T()", Date.class)
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(today)
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build();
javaFile.writeTo(System.out);
```
That generates the following `.java` file, complete with the necessary `import`:
```java
package com.example.helloworld;
import java.util.Date;
public final class HelloWorld {
Date today() {
return new Date();
}
}
```
We passed `Date.class` to reference a class that just-so-happens to be available when we're
generating code. This doesn't need to be the case. Here's a similar example, but this one
references a class that doesn't exist (yet):
```java
ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
MethodSpec today = MethodSpec.methodBuilder("tomorrow")
.returns(hoverboard)
.addStatement("return new $T()", hoverboard)
.build();
```
And that not-yet-existent class is imported as well:
```java
package com.example.helloworld;
import com.mattel.Hoverboard;
public final class HelloWorld {
Hoverboard tomorrow() {
return new Hoverboard();
}
}
```
The `ClassName` type is very important, and you'll need it frequently when you're using JavaPoet.
It can identify any _declared_ class. Declared types are just the beginning of Java's rich type
system: we also have arrays, parameterized types, wildcard types, and type variables. JavaPoet has
classes for building each of these:
```java
ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
ClassName list = ClassName.get("java.util", "List");
ClassName arrayList = ClassName.get("java.util", "ArrayList");
TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);
MethodSpec beyond = MethodSpec.methodBuilder("beyond")
.returns(listOfHoverboards)
.addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)
.addStatement("result.add(new $T())", hoverboard)
.addStatement("result.add(new $T())", hoverboard)
.addStatement("result.add(new $T())", hoverboard)
.addStatement("return result")
.build();
```
JavaPoet will decompose each type and import its components where possible.
```java
package com.example.helloworld;
import com.mattel.Hoverboard;
import java.util.ArrayList;
import java.util.List;
public final class HelloWorld {
List beyond() {
List result = new ArrayList<>();
result.add(new Hoverboard());
result.add(new Hoverboard());
result.add(new Hoverboard());
return result;
}
}
```
#### Import static
JavaPoet supports `import static`. It does it via explicitly collecting type member names. Let's
enhance the previous example with some static sugar:
```java
...
ClassName namedBoards = ClassName.get("com.mattel", "Hoverboard", "Boards");
MethodSpec beyond = MethodSpec.methodBuilder("beyond")
.returns(listOfHoverboards)
.addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)
.addStatement("result.add($T.createNimbus(2000))", hoverboard)
.addStatement("result.add($T.createNimbus(\"2001\"))", hoverboard)
.addStatement("result.add($T.createNimbus($T.THUNDERBOLT))", hoverboard, namedBoards)
.addStatement("$T.sort(result)", Collections.class)
.addStatement("return result.isEmpty() ? $T.emptyList() : result", Collections.class)
.build();
TypeSpec hello = TypeSpec.classBuilder("HelloWorld")
.addMethod(beyond)
.build();
JavaFile.builder("com.example.helloworld", hello)
.addStaticImport(hoverboard, "createNimbus")
.addStaticImport(namedBoards, "*")
.addStaticImport(Collections.class, "*")
.build();
```
JavaPoet will first add your `import static` block to the file as configured, match and mangle
all calls accordingly and also import all other types as needed.
```java
package com.example.helloworld;
import static com.mattel.Hoverboard.Boards.*;
import static com.mattel.Hoverboard.createNimbus;
import static java.util.Collections.*;
import com.mattel.Hoverboard;
import java.util.ArrayList;
import java.util.List;
class HelloWorld {
List beyond() {
List result = new ArrayList<>();
result.add(createNimbus(2000));
result.add(createNimbus("2001"));
result.add(createNimbus(THUNDERBOLT));
sort(result);
return result.isEmpty() ? emptyList() : result;
}
}
```
### $N for Names
Generated code is often self-referential. Use **`$N`** to refer to another generated declaration by
its name. Here's a method that calls another:
```java
public String byteToHex(int b) {
char[] result = new char[2];
result[0] = hexDigit((b >>> 4) & 0xf);
result[1] = hexDigit(b & 0xf);
return new String(result);
}
public char hexDigit(int i) {
return (char) (i < 10 ? i + '0' : i - 10 + 'a');
}
```
When generating the code above, we pass the `hexDigit()` method as an argument to the `byteToHex()`
method using `$N`:
```java
MethodSpec hexDigit = MethodSpec.methodBuilder("hexDigit")
.addParameter(int.class, "i")
.returns(char.class)
.addStatement("return (char) (i < 10 ? i + '0' : i - 10 + 'a')")
.build();
MethodSpec byteToHex = MethodSpec.methodBuilder("byteToHex")
.addParameter(int.class, "b")
.returns(String.class)
.addStatement("char[] result = new char[2]")
.addStatement("result[0] = $N((b >>> 4) & 0xf)", hexDigit)
.addStatement("result[1] = $N(b & 0xf)", hexDigit)
.addStatement("return new String(result)")
.build();
```
### Code block format strings
Code blocks may specify the values for their placeholders in a few ways. Only one style may be used
for each operation on a code block.
#### Relative Arguments
Pass an argument value for each placeholder in the format string to `CodeBlock.add()`. In each
example, we generate code to say "I ate 3 tacos"
```java
CodeBlock.builder().add("I ate $L $L", 3, "tacos")
```
#### Positional Arguments
Place an integer index (1-based) before the placeholder in the format string to specify which
argument to use.
```java
CodeBlock.builder().add("I ate $2L $1L", "tacos", 3)
```
#### Named Arguments
Use the syntax `$argumentName:X` where `X` is the format character and call `CodeBlock.addNamed()`
with a map containing all argument keys in the format string. Argument names use characters in
`a-z`, `A-Z`, `0-9`, and `_`, and must start with a lowercase character.
```java
Map map = new LinkedHashMap<>();
map.put("food", "tacos");
map.put("count", 3);
CodeBlock.builder().addNamed("I ate $count:L $food:L", map)
```
### Methods
All of the above methods have a code body. Use `Modifiers.ABSTRACT` to get a method without any
body. This is only legal if the enclosing class is either abstract or an interface.
```java
MethodSpec flux = MethodSpec.methodBuilder("flux")
.addModifiers(Modifier.ABSTRACT, Modifier.PROTECTED)
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addMethod(flux)
.build();
```
Which generates this:
```java
public abstract class HelloWorld {
protected abstract void flux();
}
```
The other modifiers work where permitted. Note that when specifying modifiers, JavaPoet uses
[`javax.lang.model.element.Modifier`][modifier], a class that is not available on Android. This
limitation applies to code-generating-code only; the output code runs everywhere: JVMs, Android,
and GWT.
Methods also have parameters, exceptions, varargs, Javadoc, annotations, type variables, and a
return type. All of these are configured with `MethodSpec.Builder`.
### Constructors
`MethodSpec` is a slight misnomer; it can also be used for constructors:
```java
MethodSpec flux = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class, "greeting")
.addStatement("this.$N = $N", "greeting", "greeting")
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC)
.addField(String.class, "greeting", Modifier.PRIVATE, Modifier.FINAL)
.addMethod(flux)
.build();
```
Which generates this:
```java
public class HelloWorld {
private final String greeting;
public HelloWorld(String greeting) {
this.greeting = greeting;
}
}
```
For the most part, constructors work just like methods. When emitting code, JavaPoet will place
constructors before methods in the output file.
### Parameters
Declare parameters on methods and constructors with either `ParameterSpec.builder()` or
`MethodSpec`'s convenient `addParameter()` API:
```java
ParameterSpec android = ParameterSpec.builder(String.class, "android")
.addModifiers(Modifier.FINAL)
.build();
MethodSpec welcomeOverlords = MethodSpec.methodBuilder("welcomeOverlords")
.addParameter(android)
.addParameter(String.class, "robot", Modifier.FINAL)
.build();
```
Though the code above to generate `android` and `robot` parameters is different, the output is the
same:
```java
void welcomeOverlords(final String android, final String robot) {
}
```
The extended `Builder` form is necessary when the parameter has annotations (such as `@Nullable`).
### Fields
Like parameters, fields can be created either with builders or by using convenient helper methods:
```java
FieldSpec android = FieldSpec.builder(String.class, "android")
.addModifiers(Modifier.PRIVATE, Modifier.FINAL)
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC)
.addField(android)
.addField(String.class, "robot", Modifier.PRIVATE, Modifier.FINAL)
.build();
```
Which generates:
```java
public class HelloWorld {
private final String android;
private final String robot;
}
```
The extended `Builder` form is necessary when a field has Javadoc, annotations, or a field
initializer. Field initializers use the same [`String.format()`][formatter]-like syntax as the code
blocks above:
```java
FieldSpec android = FieldSpec.builder(String.class, "android")
.addModifiers(Modifier.PRIVATE, Modifier.FINAL)
.initializer("$S + $L", "Lollipop v.", 5.0d)
.build();
```
Which generates:
```java
private final String android = "Lollipop v." + 5.0;
```
### Interfaces
JavaPoet has no trouble with interfaces. Note that interface methods must always be `PUBLIC
ABSTRACT` and interface fields must always be `PUBLIC STATIC FINAL`. These modifiers are necessary
when defining the interface:
```java
TypeSpec helloWorld = TypeSpec.interfaceBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC)
.addField(FieldSpec.builder(String.class, "ONLY_THING_THAT_IS_CONSTANT")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.initializer("$S", "change")
.build())
.addMethod(MethodSpec.methodBuilder("beep")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.build())
.build();
```
But these modifiers are omitted when the code is generated. These are the defaults so we don't need
to include them for `javac`'s benefit!
```java
public interface HelloWorld {
String ONLY_THING_THAT_IS_CONSTANT = "change";
void beep();
}
```
### Enums
Use `enumBuilder` to create the enum type, and `addEnumConstant()` for each value:
```java
TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo")
.addModifiers(Modifier.PUBLIC)
.addEnumConstant("ROCK")
.addEnumConstant("SCISSORS")
.addEnumConstant("PAPER")
.build();
```
To generate this:
```java
public enum Roshambo {
ROCK,
SCISSORS,
PAPER
}
```
Fancy enums are supported, where the enum values override methods or call a superclass constructor.
Here's a comprehensive example:
```java
TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo")
.addModifiers(Modifier.PUBLIC)
.addEnumConstant("ROCK", TypeSpec.anonymousClassBuilder("$S", "fist")
.addMethod(MethodSpec.methodBuilder("toString")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.addStatement("return $S", "avalanche!")
.returns(String.class)
.build())
.build())
.addEnumConstant("SCISSORS", TypeSpec.anonymousClassBuilder("$S", "peace")
.build())
.addEnumConstant("PAPER", TypeSpec.anonymousClassBuilder("$S", "flat")
.build())
.addField(String.class, "handsign", Modifier.PRIVATE, Modifier.FINAL)
.addMethod(MethodSpec.constructorBuilder()
.addParameter(String.class, "handsign")
.addStatement("this.$N = $N", "handsign", "handsign")
.build())
.build();
```
Which generates this:
```java
public enum Roshambo {
ROCK("fist") {
@Override
public String toString() {
return "avalanche!";
}
},
SCISSORS("peace"),
PAPER("flat");
private final String handsign;
Roshambo(String handsign) {
this.handsign = handsign;
}
}
```
### Anonymous Inner Classes
In the enum code, we used `Types.anonymousInnerClass()`. Anonymous inner classes can also be used in
code blocks. They are values that can be referenced with `$L`:
```java
TypeSpec comparator = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(ParameterizedTypeName.get(Comparator.class, String.class))
.addMethod(MethodSpec.methodBuilder("compare")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class, "a")
.addParameter(String.class, "b")
.returns(int.class)
.addStatement("return $N.length() - $N.length()", "a", "b")
.build())
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addMethod(MethodSpec.methodBuilder("sortByLength")
.addParameter(ParameterizedTypeName.get(List.class, String.class), "strings")
.addStatement("$T.sort($N, $L)", Collections.class, "strings", comparator)
.build())
.build();
```
This generates a method that contains a class that contains a method:
```java
void sortByLength(List strings) {
Collections.sort(strings, new Comparator() {
@Override
public int compare(String a, String b) {
return a.length() - b.length();
}
});
}
```
One particularly tricky part of defining anonymous inner classes is the arguments to the superclass
constructor. In the above code we're passing the empty string for no arguments:
`TypeSpec.anonymousClassBuilder("")`. To pass different parameters use JavaPoet's code block
syntax with commas to separate arguments.
### Annotations
Simple annotations are easy:
```java
MethodSpec toString = MethodSpec.methodBuilder("toString")
.addAnnotation(Override.class)
.returns(String.class)
.addModifiers(Modifier.PUBLIC)
.addStatement("return $S", "Hoverboard")
.build();
```
Which generates this method with an `@Override` annotation:
```java
@Override
public String toString() {
return "Hoverboard";
}
```
Use `AnnotationSpec.builder()` to set properties on annotations:
```java
MethodSpec logRecord = MethodSpec.methodBuilder("recordEvent")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addAnnotation(AnnotationSpec.builder(Headers.class)
.addMember("accept", "$S", "application/json; charset=utf-8")
.addMember("userAgent", "$S", "Square Cash")
.build())
.addParameter(LogRecord.class, "logRecord")
.returns(LogReceipt.class)
.build();
```
Which generates this annotation with `accept` and `userAgent` properties:
```java
@Headers(
accept = "application/json; charset=utf-8",
userAgent = "Square Cash"
)
LogReceipt recordEvent(LogRecord logRecord);
```
When you get fancy, annotation values can be annotations themselves. Use `$L` for embedded
annotations:
```java
MethodSpec logRecord = MethodSpec.methodBuilder("recordEvent")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addAnnotation(AnnotationSpec.builder(HeaderList.class)
.addMember("value", "$L", AnnotationSpec.builder(Header.class)
.addMember("name", "$S", "Accept")
.addMember("value", "$S", "application/json; charset=utf-8")
.build())
.addMember("value", "$L", AnnotationSpec.builder(Header.class)
.addMember("name", "$S", "User-Agent")
.addMember("value", "$S", "Square Cash")
.build())
.build())
.addParameter(LogRecord.class, "logRecord")
.returns(LogReceipt.class)
.build();
```
Which generates this:
```java
@HeaderList({
@Header(name = "Accept", value = "application/json; charset=utf-8"),
@Header(name = "User-Agent", value = "Square Cash")
})
LogReceipt recordEvent(LogRecord logRecord);
```
Note that you can call `addMember()` multiple times with the same property name to populate a list
of values for that property.
### Javadoc
Fields, methods and types can be documented with Javadoc:
```java
MethodSpec dismiss = MethodSpec.methodBuilder("dismiss")
.addJavadoc("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")
.addJavadoc("\n")
.addJavadoc("
Use {@link #delete($T)} to delete the entire\n"
+ "conversation for all participants.\n", Conversation.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(Message.class, "message")
.build();
```
Which generates this:
```java
/**
* Hides {@code message} from the caller's history. Other
* participants in the conversation will continue to see the
* message in their own history unless they also delete it.
*
*
Use {@link #delete(Conversation)} to delete the entire
* conversation for all participants.
*/
void dismiss(Message message);
```
Use `$T` when referencing types in Javadoc to get automatic imports.
Download
--------
Download [the latest .jar][dl] or depend via Maven:
```xml
com.squareupjavapoet1.11.1
```
or Gradle:
```groovy
compile 'com.squareup:javapoet:1.11.1'
```
Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap].
License
-------
Copyright 2015 Square, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
JavaWriter
==========
JavaPoet is the successor to [JavaWriter][javawriter]. New projects should prefer JavaPoet because
it has a stronger code model: it understands types and can manage imports automatically. JavaPoet is
also better suited to composition: rather than streaming the contents of a `.java` file
top-to-bottom in a single pass, a file can be assembled as a tree of declarations.
JavaWriter continues to be available in [GitHub][javawriter] and [Maven Central][javawriter_maven].
[dl]: https://search.maven.org/remote_content?g=com.squareup&a=javapoet&v=LATEST
[snap]: https://oss.sonatype.org/content/repositories/snapshots/com/squareup/javapoet/
[javadoc]: https://square.github.io/javapoet/1.x/javapoet/
[javawriter]: https://github.com/square/javapoet/tree/javawriter_2
[javawriter_maven]: https://search.maven.org/#artifactdetails%7Ccom.squareup%7Cjavawriter%7C2.5.1%7Cjar
[formatter]: https://developer.android.com/reference/java/util/Formatter.html
[modifier]: https://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Modifier.html
javapoet-1.11.1/checkstyle.xml 0000664 0000000 0000000 00000012562 13355454760 0016306 0 ustar 00root root 0000000 0000000
javapoet-1.11.1/pom.xml 0000664 0000000 0000000 00000011360 13355454760 0014736 0 ustar 00root root 0000000 0000000
4.0.0org.sonatype.ossoss-parent7com.squareupjavapoet1.11.1JavaPoetUse beautiful Java code to generate beautiful Java code.http://github.com/square/javapoet/UTF-81.84.120.390.15http://github.com/square/javapoet/scm:git:git://github.com/square/javapoet.gitscm:git:ssh://git@github.com/square/javapoet.gitHEADGitHub Issueshttp://github.com/square/javapoet/issuesApache 2.0http://www.apache.org/licenses/LICENSE-2.0.txtSquare, Inc.http://squareup.comcom.google.truthtruth${truth.version}testcom.google.testing.compilecompile-testing${compile-testing.version}testjunitjunit${junit.version}testcom.google.jimfsjimfs1.1testorg.mockitomockito-core2.13.0testorg.eclipse.jdt.core.compilerecj4.6.1testorg.apache.maven.pluginsmaven-compiler-plugin3.7.0javac-with-errorpronetrue${java.version}${java.version}org.codehaus.plexusplexus-compiler-javac-errorprone2.8.2com.google.errorproneerror_prone_core2.3.1org.apache.maven.pluginsmaven-checkstyle-plugin2.17com.puppycrawl.toolscheckstyle8.7truecheckstyle.xmltrueverifycheckstyleorg.apache.maven.pluginsmaven-jar-plugin3.0.2com.squareup.javapoet
javapoet-1.11.1/src/ 0000775 0000000 0000000 00000000000 13355454760 0014207 5 ustar 00root root 0000000 0000000 javapoet-1.11.1/src/main/ 0000775 0000000 0000000 00000000000 13355454760 0015133 5 ustar 00root root 0000000 0000000 javapoet-1.11.1/src/main/java/ 0000775 0000000 0000000 00000000000 13355454760 0016054 5 ustar 00root root 0000000 0000000 javapoet-1.11.1/src/main/java/com/ 0000775 0000000 0000000 00000000000 13355454760 0016632 5 ustar 00root root 0000000 0000000 javapoet-1.11.1/src/main/java/com/squareup/ 0000775 0000000 0000000 00000000000 13355454760 0020477 5 ustar 00root root 0000000 0000000 javapoet-1.11.1/src/main/java/com/squareup/javapoet/ 0000775 0000000 0000000 00000000000 13355454760 0022310 5 ustar 00root root 0000000 0000000 javapoet-1.11.1/src/main/java/com/squareup/javapoet/AnnotationSpec.java 0000664 0000000 0000000 00000022675 13355454760 0026114 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.javapoet;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleAnnotationValueVisitor8;
import static com.squareup.javapoet.Util.characterLiteralWithoutSingleQuotes;
import static com.squareup.javapoet.Util.checkArgument;
import static com.squareup.javapoet.Util.checkNotNull;
/** A generated annotation on a declaration. */
public final class AnnotationSpec {
public final TypeName type;
public final Map> members;
private AnnotationSpec(Builder builder) {
this.type = builder.type;
this.members = Util.immutableMultimap(builder.members);
}
void emit(CodeWriter codeWriter, boolean inline) throws IOException {
String whitespace = inline ? "" : "\n";
String memberSeparator = inline ? ", " : ",\n";
if (members.isEmpty()) {
// @Singleton
codeWriter.emit("@$T", type);
} else if (members.size() == 1 && members.containsKey("value")) {
// @Named("foo")
codeWriter.emit("@$T(", type);
emitAnnotationValues(codeWriter, whitespace, memberSeparator, members.get("value"));
codeWriter.emit(")");
} else {
// Inline:
// @Column(name = "updated_at", nullable = false)
//
// Not inline:
// @Column(
// name = "updated_at",
// nullable = false
// )
codeWriter.emit("@$T(" + whitespace, type);
codeWriter.indent(2);
for (Iterator>> i
= members.entrySet().iterator(); i.hasNext(); ) {
Map.Entry> entry = i.next();
codeWriter.emit("$L = ", entry.getKey());
emitAnnotationValues(codeWriter, whitespace, memberSeparator, entry.getValue());
if (i.hasNext()) codeWriter.emit(memberSeparator);
}
codeWriter.unindent(2);
codeWriter.emit(whitespace + ")");
}
}
private void emitAnnotationValues(CodeWriter codeWriter, String whitespace,
String memberSeparator, List values) throws IOException {
if (values.size() == 1) {
codeWriter.indent(2);
codeWriter.emit(values.get(0));
codeWriter.unindent(2);
return;
}
codeWriter.emit("{" + whitespace);
codeWriter.indent(2);
boolean first = true;
for (CodeBlock codeBlock : values) {
if (!first) codeWriter.emit(memberSeparator);
codeWriter.emit(codeBlock);
first = false;
}
codeWriter.unindent(2);
codeWriter.emit(whitespace + "}");
}
public static AnnotationSpec get(Annotation annotation) {
return get(annotation, false);
}
public static AnnotationSpec get(Annotation annotation, boolean includeDefaultValues) {
Builder builder = builder(annotation.annotationType());
try {
Method[] methods = annotation.annotationType().getDeclaredMethods();
Arrays.sort(methods, Comparator.comparing(Method::getName));
for (Method method : methods) {
Object value = method.invoke(annotation);
if (!includeDefaultValues) {
if (Objects.deepEquals(value, method.getDefaultValue())) {
continue;
}
}
if (value.getClass().isArray()) {
for (int i = 0; i < Array.getLength(value); i++) {
builder.addMemberForValue(method.getName(), Array.get(value, i));
}
continue;
}
if (value instanceof Annotation) {
builder.addMember(method.getName(), "$L", get((Annotation) value));
continue;
}
builder.addMemberForValue(method.getName(), value);
}
} catch (Exception e) {
throw new RuntimeException("Reflecting " + annotation + " failed!", e);
}
return builder.build();
}
public static AnnotationSpec get(AnnotationMirror annotation) {
TypeElement element = (TypeElement) annotation.getAnnotationType().asElement();
AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassName.get(element));
Visitor visitor = new Visitor(builder);
for (ExecutableElement executableElement : annotation.getElementValues().keySet()) {
String name = executableElement.getSimpleName().toString();
AnnotationValue value = annotation.getElementValues().get(executableElement);
value.accept(visitor, name);
}
return builder.build();
}
public static Builder builder(ClassName type) {
checkNotNull(type, "type == null");
return new Builder(type);
}
public static Builder builder(Class> type) {
return builder(ClassName.get(type));
}
public Builder toBuilder() {
Builder builder = new Builder(type);
for (Map.Entry> entry : members.entrySet()) {
builder.members.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
return builder;
}
@Override public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (getClass() != o.getClass()) return false;
return toString().equals(o.toString());
}
@Override public int hashCode() {
return toString().hashCode();
}
@Override public String toString() {
StringBuilder out = new StringBuilder();
try {
CodeWriter codeWriter = new CodeWriter(out);
codeWriter.emit("$L", this);
return out.toString();
} catch (IOException e) {
throw new AssertionError();
}
}
public static final class Builder {
private final TypeName type;
private final Map> members = new LinkedHashMap<>();
private Builder(TypeName type) {
this.type = type;
}
public Builder addMember(String name, String format, Object... args) {
return addMember(name, CodeBlock.of(format, args));
}
public Builder addMember(String name, CodeBlock codeBlock) {
checkNotNull(name, "name == null");
checkArgument(SourceVersion.isName(name), "not a valid name: %s", name);
List values = members.computeIfAbsent(name, k -> new ArrayList<>());
values.add(codeBlock);
return this;
}
/**
* Delegates to {@link #addMember(String, String, Object...)}, with parameter {@code format}
* depending on the given {@code value} object. Falls back to {@code "$L"} literal format if
* the class of the given {@code value} object is not supported.
*/
Builder addMemberForValue(String memberName, Object value) {
checkNotNull(memberName, "memberName == null");
checkNotNull(value, "value == null, constant non-null value expected for %s", memberName);
checkArgument(SourceVersion.isName(memberName), "not a valid name: %s", memberName);
if (value instanceof Class>) {
return addMember(memberName, "$T.class", value);
}
if (value instanceof Enum) {
return addMember(memberName, "$T.$L", value.getClass(), ((Enum>) value).name());
}
if (value instanceof String) {
return addMember(memberName, "$S", value);
}
if (value instanceof Float) {
return addMember(memberName, "$Lf", value);
}
if (value instanceof Character) {
return addMember(memberName, "'$L'", characterLiteralWithoutSingleQuotes((char) value));
}
return addMember(memberName, "$L", value);
}
public AnnotationSpec build() {
return new AnnotationSpec(this);
}
}
/**
* Annotation value visitor adding members to the given builder instance.
*/
private static class Visitor extends SimpleAnnotationValueVisitor8 {
final Builder builder;
Visitor(Builder builder) {
super(builder);
this.builder = builder;
}
@Override protected Builder defaultAction(Object o, String name) {
return builder.addMemberForValue(name, o);
}
@Override public Builder visitAnnotation(AnnotationMirror a, String name) {
return builder.addMember(name, "$L", get(a));
}
@Override public Builder visitEnumConstant(VariableElement c, String name) {
return builder.addMember(name, "$T.$L", c.asType(), c.getSimpleName());
}
@Override public Builder visitType(TypeMirror t, String name) {
return builder.addMember(name, "$T.class", t);
}
@Override public Builder visitArray(List extends AnnotationValue> values, String name) {
for (AnnotationValue value : values) {
value.accept(this, name);
}
return builder;
}
}
}
javapoet-1.11.1/src/main/java/com/squareup/javapoet/ArrayTypeName.java 0000664 0000000 0000000 00000006767 13355454760 0025714 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.javapoet;
import java.io.IOException;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.ArrayType;
import static com.squareup.javapoet.Util.checkNotNull;
public final class ArrayTypeName extends TypeName {
public final TypeName componentType;
private ArrayTypeName(TypeName componentType) {
this(componentType, new ArrayList<>());
}
private ArrayTypeName(TypeName componentType, List annotations) {
super(annotations);
this.componentType = checkNotNull(componentType, "rawType == null");
}
@Override public ArrayTypeName annotated(List annotations) {
return new ArrayTypeName(componentType, concatAnnotations(annotations));
}
@Override public TypeName withoutAnnotations() {
return new ArrayTypeName(componentType);
}
@Override CodeWriter emit(CodeWriter out) throws IOException {
return emit(out, false);
}
CodeWriter emit(CodeWriter out, boolean varargs) throws IOException {
emitLeafType(out);
return emitBrackets(out, varargs);
}
private CodeWriter emitLeafType(CodeWriter out) throws IOException {
if (TypeName.asArray(componentType) != null) {
return TypeName.asArray(componentType).emitLeafType(out);
}
return componentType.emit(out);
}
private CodeWriter emitBrackets(CodeWriter out, boolean varargs) throws IOException {
if (isAnnotated()) {
out.emit(" ");
emitAnnotations(out);
}
if (TypeName.asArray(componentType) == null) {
// Last bracket.
return out.emit(varargs ? "..." : "[]");
}
out.emit("[]");
return TypeName.asArray(componentType) .emitBrackets(out, varargs);
}
/** Returns an array type whose elements are all instances of {@code componentType}. */
public static ArrayTypeName of(TypeName componentType) {
return new ArrayTypeName(componentType);
}
/** Returns an array type whose elements are all instances of {@code componentType}. */
public static ArrayTypeName of(Type componentType) {
return of(TypeName.get(componentType));
}
/** Returns an array type equivalent to {@code mirror}. */
public static ArrayTypeName get(ArrayType mirror) {
return get(mirror, new LinkedHashMap<>());
}
static ArrayTypeName get(
ArrayType mirror, Map typeVariables) {
return new ArrayTypeName(get(mirror.getComponentType(), typeVariables));
}
/** Returns an array type equivalent to {@code type}. */
public static ArrayTypeName get(GenericArrayType type) {
return get(type, new LinkedHashMap<>());
}
static ArrayTypeName get(GenericArrayType type, Map map) {
return ArrayTypeName.of(get(type.getGenericComponentType(), map));
}
}
javapoet-1.11.1/src/main/java/com/squareup/javapoet/ClassName.java 0000664 0000000 0000000 00000024502 13355454760 0025024 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.javapoet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.SimpleElementVisitor8;
import static com.squareup.javapoet.Util.checkArgument;
import static com.squareup.javapoet.Util.checkNotNull;
/** A fully-qualified class name for top-level and member classes. */
public final class ClassName extends TypeName implements Comparable {
public static final ClassName OBJECT = ClassName.get(Object.class);
/** The package name of this class, or "" if this is in the default package. */
final String packageName;
/** The enclosing class, or null if this is not enclosed in another class. */
final ClassName enclosingClassName;
/** This class name, like "Entry" for java.util.Map.Entry. */
final String simpleName;
/** The full class name like "java.util.Map.Entry". */
final String canonicalName;
private ClassName(String packageName, ClassName enclosingClassName, String simpleName) {
this(packageName, enclosingClassName, simpleName, Collections.emptyList());
}
private ClassName(String packageName, ClassName enclosingClassName, String simpleName,
List annotations) {
super(annotations);
this.packageName = packageName;
this.enclosingClassName = enclosingClassName;
this.simpleName = simpleName;
this.canonicalName = enclosingClassName != null
? (enclosingClassName.canonicalName + '.' + simpleName)
: (packageName.isEmpty() ? simpleName : packageName + '.' + simpleName);
}
@Override public ClassName annotated(List annotations) {
return new ClassName(packageName, enclosingClassName, simpleName,
concatAnnotations(annotations));
}
@Override public ClassName withoutAnnotations() {
if (!isAnnotated()) return this;
ClassName resultEnclosingClassName = enclosingClassName != null
? enclosingClassName.withoutAnnotations()
: null;
return new ClassName(packageName, resultEnclosingClassName, simpleName);
}
@Override public boolean isAnnotated() {
return super.isAnnotated() || (enclosingClassName != null && enclosingClassName.isAnnotated());
}
/**
* Returns the package name, like {@code "java.util"} for {@code Map.Entry}. Returns the empty
* string for the default package.
*/
public String packageName() {
return packageName;
}
/**
* Returns the enclosing class, like {@link Map} for {@code Map.Entry}. Returns null if this class
* is not nested in another class.
*/
public ClassName enclosingClassName() {
return enclosingClassName;
}
/**
* Returns the top class in this nesting group. Equivalent to chained calls to {@link
* #enclosingClassName()} until the result's enclosing class is null.
*/
public ClassName topLevelClassName() {
return enclosingClassName != null ? enclosingClassName.topLevelClassName() : this;
}
/** Return the binary name of a class. */
public String reflectionName() {
return enclosingClassName != null
? (enclosingClassName.reflectionName() + '$' + simpleName)
: (packageName.isEmpty() ? simpleName : packageName + '.' + simpleName);
}
public List simpleNames() {
List simpleNames = new ArrayList<>();
if (enclosingClassName != null) {
simpleNames.addAll(enclosingClassName().simpleNames());
}
simpleNames.add(simpleName);
return simpleNames;
}
/**
* Returns a class that shares the same enclosing package or class. If this class is enclosed by
* another class, this is equivalent to {@code enclosingClassName().nestedClass(name)}. Otherwise
* it is equivalent to {@code get(packageName(), name)}.
*/
public ClassName peerClass(String name) {
return new ClassName(packageName, enclosingClassName, name);
}
/**
* Returns a new {@link ClassName} instance for the specified {@code name} as nested inside this
* class.
*/
public ClassName nestedClass(String name) {
return new ClassName(packageName, this, name);
}
/** Returns the simple name of this class, like {@code "Entry"} for {@link Map.Entry}. */
public String simpleName() {
return simpleName;
}
public static ClassName get(Class> clazz) {
checkNotNull(clazz, "clazz == null");
checkArgument(!clazz.isPrimitive(), "primitive types cannot be represented as a ClassName");
checkArgument(!void.class.equals(clazz), "'void' type cannot be represented as a ClassName");
checkArgument(!clazz.isArray(), "array types cannot be represented as a ClassName");
String anonymousSuffix = "";
while (clazz.isAnonymousClass()) {
int lastDollar = clazz.getName().lastIndexOf('$');
anonymousSuffix = clazz.getName().substring(lastDollar) + anonymousSuffix;
clazz = clazz.getEnclosingClass();
}
String name = clazz.getSimpleName() + anonymousSuffix;
if (clazz.getEnclosingClass() == null) {
// Avoid unreliable Class.getPackage(). https://github.com/square/javapoet/issues/295
int lastDot = clazz.getName().lastIndexOf('.');
String packageName = (lastDot != -1) ? clazz.getName().substring(0, lastDot) : null;
return new ClassName(packageName, null, name);
}
return ClassName.get(clazz.getEnclosingClass()).nestedClass(name);
}
/**
* Returns a new {@link ClassName} instance for the given fully-qualified class name string. This
* method assumes that the input is ASCII and follows typical Java style (lowercase package
* names, UpperCamelCase class names) and may produce incorrect results or throw
* {@link IllegalArgumentException} otherwise. For that reason, {@link #get(Class)} and
* {@link #get(Class)} should be preferred as they can correctly create {@link ClassName}
* instances without such restrictions.
*/
public static ClassName bestGuess(String classNameString) {
// Add the package name, like "java.util.concurrent", or "" for no package.
int p = 0;
while (p < classNameString.length() && Character.isLowerCase(classNameString.codePointAt(p))) {
p = classNameString.indexOf('.', p) + 1;
checkArgument(p != 0, "couldn't make a guess for %s", classNameString);
}
String packageName = p == 0 ? "" : classNameString.substring(0, p - 1);
// Add class names like "Map" and "Entry".
ClassName className = null;
for (String simpleName : classNameString.substring(p).split("\\.", -1)) {
checkArgument(!simpleName.isEmpty() && Character.isUpperCase(simpleName.codePointAt(0)),
"couldn't make a guess for %s", classNameString);
className = new ClassName(packageName, className, simpleName);
}
return className;
}
/**
* Returns a class name created from the given parts. For example, calling this with package name
* {@code "java.util"} and simple names {@code "Map"}, {@code "Entry"} yields {@link Map.Entry}.
*/
public static ClassName get(String packageName, String simpleName, String... simpleNames) {
ClassName className = new ClassName(packageName, null, simpleName);
for (String name : simpleNames) {
className = className.nestedClass(name);
}
return className;
}
/** Returns the class name for {@code element}. */
public static ClassName get(TypeElement element) {
checkNotNull(element, "element == null");
String simpleName = element.getSimpleName().toString();
return element.getEnclosingElement().accept(new SimpleElementVisitor8() {
@Override public ClassName visitPackage(PackageElement packageElement, Void p) {
return new ClassName(packageElement.getQualifiedName().toString(), null, simpleName);
}
@Override public ClassName visitType(TypeElement enclosingClass, Void p) {
return ClassName.get(enclosingClass).nestedClass(simpleName);
}
@Override public ClassName visitUnknown(Element unknown, Void p) {
return get("", simpleName);
}
@Override public ClassName defaultAction(Element enclosingElement, Void p) {
throw new IllegalArgumentException("Unexpected type nesting: " + element);
}
}, null);
}
@Override public int compareTo(ClassName o) {
return canonicalName.compareTo(o.canonicalName);
}
@Override CodeWriter emit(CodeWriter out) throws IOException {
boolean charsEmitted = false;
for (ClassName className : enclosingClasses()) {
String simpleName;
if (charsEmitted) {
// We've already emitted an enclosing class. Emit as we go.
out.emit(".");
simpleName = className.simpleName;
} else if (className.isAnnotated() || className == this) {
// We encountered the first enclosing class that must be emitted.
String qualifiedName = out.lookupName(className);
int dot = qualifiedName.lastIndexOf('.');
if (dot != -1) {
out.emitAndIndent(qualifiedName.substring(0, dot + 1));
simpleName = qualifiedName.substring(dot + 1);
charsEmitted = true;
} else {
simpleName = qualifiedName;
}
} else {
// Don't emit this enclosing type. Keep going so we can be more precise.
continue;
}
if (className.isAnnotated()) {
if (charsEmitted) out.emit(" ");
className.emitAnnotations(out);
}
out.emit(simpleName);
charsEmitted = true;
}
return out;
}
/** Returns all enclosing classes in this, outermost first. */
private List enclosingClasses() {
List result = new ArrayList<>();
for (ClassName c = this; c != null; c = c.enclosingClassName) {
result.add(c);
}
Collections.reverse(result);
return result;
}
}
javapoet-1.11.1/src/main/java/com/squareup/javapoet/CodeBlock.java 0000664 0000000 0000000 00000037534 13355454760 0025014 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.javapoet;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collector;
import java.util.stream.StreamSupport;
import javax.lang.model.element.Element;
import javax.lang.model.type.TypeMirror;
import static com.squareup.javapoet.Util.checkArgument;
/**
* A fragment of a .java file, potentially containing declarations, statements, and documentation.
* Code blocks are not necessarily well-formed Java code, and are not validated. This class assumes
* javac will check correctness later!
*
*
Code blocks support placeholders like {@link java.text.Format}. Where {@link String#format}
* uses percent {@code %} to reference target values, this class uses dollar sign {@code $} and has
* its own set of permitted placeholders:
*
*
*
{@code $L} emits a literal value with no escaping. Arguments for literals may be
* strings, primitives, {@linkplain TypeSpec type declarations}, {@linkplain AnnotationSpec
* annotations} and even other code blocks.
*
{@code $N} emits a name, using name collision avoidance where necessary. Arguments
* for names may be strings (actually any {@linkplain CharSequence character sequence}),
* {@linkplain ParameterSpec parameters}, {@linkplain FieldSpec fields}, {@linkplain
* MethodSpec methods}, and {@linkplain TypeSpec types}.
*
{@code $S} escapes the value as a string, wraps it with double quotes, and emits
* that. For example, {@code 6" sandwich} is emitted {@code "6\" sandwich"}.
*
{@code $T} emits a type reference. Types will be imported if possible. Arguments
* for types may be {@linkplain Class classes}, {@linkplain javax.lang.model.type.TypeMirror
,* type mirrors}, and {@linkplain javax.lang.model.element.Element elements}.
*
{@code $$} emits a dollar sign.
*
{@code $W} emits a space or a newline, depending on its position on the line. This prefers
* to wrap lines before 100 columns.
*
{@code $Z} acts as a zero-width space. This prefers to wrap lines before 100 columns.
*
{@code $>} increases the indentation level.
*
{@code $<} decreases the indentation level.
*
{@code $[} begins a statement. For multiline statements, every line after the first line
* is double-indented.
*
{@code $]} ends a statement.
*
*/
public final class CodeBlock {
private static final Pattern NAMED_ARGUMENT =
Pattern.compile("\\$(?[\\w_]+):(?[\\w]).*");
private static final Pattern LOWERCASE = Pattern.compile("[a-z]+[\\w_]*");
/** A heterogeneous list containing string literals and value placeholders. */
final List formatParts;
final List