aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorRoberto Lublinerman <rluble@gmail.com>2018-03-10 09:35:51 -0800
committerJesse Wilson <jesse@swank.ca>2018-03-10 12:35:51 -0500
commitd91f8e1374f7ccdb68d92c206c84864cd09c02f6 (patch)
tree45101d7ae61658b6dc553ec6eefb749eccd2f6ec /src/main
parentadced314c48865463594bf58022f509090eef7af (diff)
downloadjavapoet-d91f8e1374f7ccdb68d92c206c84864cd09c02f6.tar.gz
Add tests for Java 8 TYPE_USE annotations on arrays (#614). (#618)
* Add tests for Java 8 TYPE_USE annotations on arrays (#614). * Implement TYPE_USE annotations semantics. * Cleanup in AnnotatedTypeTest. * Nits from review
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/squareup/javapoet/ArrayTypeName.java29
-rw-r--r--src/main/java/com/squareup/javapoet/ClassName.java354
-rw-r--r--src/main/java/com/squareup/javapoet/CodeWriter.java4
-rw-r--r--src/main/java/com/squareup/javapoet/JavaFile.java2
-rw-r--r--src/main/java/com/squareup/javapoet/MethodSpec.java2
-rw-r--r--src/main/java/com/squareup/javapoet/ParameterSpec.java5
-rw-r--r--src/main/java/com/squareup/javapoet/ParameterizedTypeName.java18
-rw-r--r--src/main/java/com/squareup/javapoet/TypeName.java15
-rw-r--r--src/main/java/com/squareup/javapoet/TypeVariableName.java1
9 files changed, 313 insertions, 117 deletions
diff --git a/src/main/java/com/squareup/javapoet/ArrayTypeName.java b/src/main/java/com/squareup/javapoet/ArrayTypeName.java
index 7c54465..219c3f3 100644
--- a/src/main/java/com/squareup/javapoet/ArrayTypeName.java
+++ b/src/main/java/com/squareup/javapoet/ArrayTypeName.java
@@ -48,9 +48,36 @@ public final class ArrayTypeName extends TypeName {
}
@Override CodeWriter emit(CodeWriter out) throws IOException {
- return out.emit("$T[]", componentType);
+ 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);
diff --git a/src/main/java/com/squareup/javapoet/ClassName.java b/src/main/java/com/squareup/javapoet/ClassName.java
index c5c065d..6c10024 100644
--- a/src/main/java/com/squareup/javapoet/ClassName.java
+++ b/src/main/java/com/squareup/javapoet/ClassName.java
@@ -17,7 +17,7 @@ package com.squareup.javapoet;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.lang.model.SourceVersion;
@@ -32,106 +32,236 @@ import static javax.lang.model.element.NestingKind.MEMBER;
import static javax.lang.model.element.NestingKind.TOP_LEVEL;
/** A fully-qualified class name for top-level and member classes. */
-public final class ClassName extends TypeName implements Comparable<ClassName> {
- public static final ClassName OBJECT = ClassName.get(Object.class);
+public abstract class ClassName extends TypeName implements Comparable<ClassName> {
+ final String simpleName;
+ String canonicalName;
- /** From top to bottom. This will be ["java.util", "Map", "Entry"] for {@link Map.Entry}. */
- final List<String> names;
- final String canonicalName;
+ /** A fully-qualified class name for top-level classes. */
+ private static final class TopLevelClassName extends ClassName {
+ final String packageName;
- private ClassName(List<String> names) {
- this(names, new ArrayList<>());
- }
+ private TopLevelClassName(String packageName, String simpleName) {
+ this(packageName, simpleName, new ArrayList<>());
+ }
- private ClassName(List<String> names, List<AnnotationSpec> annotations) {
- super(annotations);
- for (int i = 1; i < names.size(); i++) {
- checkArgument(SourceVersion.isName(names.get(i)), "part '%s' is keyword", names.get(i));
+ private TopLevelClassName(
+ String packageName, String simpleName, List<AnnotationSpec> annotations) {
+ super(simpleName, annotations);
+ this.packageName = packageName == null ? "" : packageName;
+ this.canonicalName = isDefaultPackage(packageName)
+ ? simpleName : String.join(".", Arrays.asList(packageName, simpleName));
+ checkArgument(
+ isDefaultPackage(simpleName) || SourceVersion.isName(simpleName),
+ "part '%s' is keyword", simpleName);
+ }
+
+ @Override public TopLevelClassName annotated(List<AnnotationSpec> annotations) {
+ return new TopLevelClassName(packageName, simpleName, concatAnnotations(annotations));
+ }
+
+ @Override public TopLevelClassName withoutAnnotations() {
+ return new TopLevelClassName(packageName, simpleName);
+ }
+
+ public String packageName() {
+ return packageName;
+ }
+
+ @Override
+ public ClassName enclosingClassName() {
+ return null;
+ }
+
+ @Override
+ public TopLevelClassName topLevelClassName() {
+ return this;
+ }
+
+ @Override
+ public String reflectionName() {
+ return isDefaultPackage(packageName)
+ ? simpleName
+ : String.join(".", Arrays.asList(packageName, simpleName));
+ }
+
+ @Override
+ public List<String> simpleNames() {
+ return Arrays.asList(simpleName);
+ }
+
+ @Override
+ public ClassName peerClass(String name) {
+ return new TopLevelClassName(packageName, name);
+ }
+
+ @Override
+ ClassName prefixWithAtMostOneAnnotatedClass() {
+ return this;
+ }
+
+ @Override
+ boolean hasAnnotatedEnclosingClass() {
+ return false;
+ }
+
+ @Override
+ CodeWriter emitWithoutPrefix(CodeWriter out, ClassName unannotatedPrefix) {
+ return out;
}
- this.names = Util.immutableList(names);
- this.canonicalName = (names.get(0).isEmpty()
- ? String.join(".", names.subList(1, names.size()))
- : String.join(".", names));
}
- @Override public ClassName annotated(List<AnnotationSpec> annotations) {
- return new ClassName(names, concatAnnotations(annotations));
+ /** A fully-qualified class name for nested classes. */
+ private static final class NestedClassName extends ClassName {
+ /** From top to bottom. This will be ["java.util", "Map", "Entry"] for {@link Map.Entry}. */
+ final ClassName enclosingClassName;
+
+ private NestedClassName(ClassName enclosingClassName, String simpleName) {
+ this(enclosingClassName, simpleName, new ArrayList<>());
+ }
+
+ private NestedClassName(
+ ClassName enclosingClassName, String simpleName, List<AnnotationSpec> annotations) {
+ super(simpleName, annotations);
+ this.enclosingClassName = enclosingClassName;
+ this.canonicalName =
+ String.join(".", Arrays.asList(enclosingClassName.canonicalName, simpleName));
+ }
+
+ @Override public NestedClassName annotated(List<AnnotationSpec> annotations) {
+ return new NestedClassName(enclosingClassName, simpleName, concatAnnotations(annotations));
+ }
+
+ @Override public NestedClassName withoutAnnotations() {
+ return new NestedClassName(enclosingClassName.withoutAnnotations(), simpleName);
+ }
+
+ /** Returns the package name, like {@code "java.util"} for {@code Map.Entry}. */
+ public String packageName() {
+ return enclosingClassName.packageName();
+ }
+
+ @Override
+ public ClassName enclosingClassName() {
+ return enclosingClassName;
+ }
+
+ @Override
+ public ClassName topLevelClassName() {
+ return enclosingClassName.topLevelClassName();
+ }
+
+ @Override
+ public String reflectionName() {
+ return enclosingClassName.reflectionName() + "$" + simpleName;
+ }
+
+ @Override
+ public List<String> simpleNames() {
+ List<String> simpleNames = new ArrayList<>(enclosingClassName().simpleNames());
+ simpleNames.add(simpleName);
+ return simpleNames;
+ }
+
+ @Override
+ public ClassName peerClass(String name) {
+ return enclosingClassName.nestedClass(name);
+ }
+
+ @Override
+ ClassName prefixWithAtMostOneAnnotatedClass() {
+ if (hasAnnotatedEnclosingClass()) {
+ enclosingClassName.prefixWithAtMostOneAnnotatedClass();
+ }
+
+ return this;
+ }
+
+ @Override
+ CodeWriter emitWithoutPrefix(
+ CodeWriter out, ClassName unannotatedPrefix) throws IOException {
+
+ if (unannotatedPrefix.equals(this)) {
+ return out;
+ }
+
+ enclosingClassName.emitWithoutPrefix(out, unannotatedPrefix);
+ out.emit(".");
+ if (isAnnotated()) {
+ out.emit(" ");
+ emitAnnotations(out);
+ }
+ return out.emit(simpleName);
+ }
+
+ @Override
+ boolean hasAnnotatedEnclosingClass() {
+ return enclosingClassName.isAnnotated() || enclosingClassName.hasAnnotatedEnclosingClass();
+ }
}
- @Override public ClassName withoutAnnotations() {
- return new ClassName(names);
+ public static final ClassName OBJECT = ClassName.get(Object.class);
+
+ private ClassName(String simpleName, List<AnnotationSpec> annotations) {
+ super(annotations);
+ checkArgument(SourceVersion.isName(simpleName), "part '%s' is keyword", simpleName);
+ this.simpleName = simpleName;
}
+
/** Returns the package name, like {@code "java.util"} for {@code Map.Entry}. */
- public String packageName() {
- return names.get(0);
- }
+ public abstract String 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() {
- if (names.size() == 2) return null;
- return new ClassName(names.subList(0, names.size() - 1));
- }
+ public abstract ClassName 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 new ClassName(names.subList(0, 2));
- }
+ public abstract ClassName topLevelClassName();
- public String reflectionName() {
- // trivial case: no nested names
- if (names.size() == 2) {
- String packageName = packageName();
- if (packageName.isEmpty()) {
- return names.get(1);
- }
- return packageName + "." + names.get(1);
- }
- // concat top level class name and nested names
- StringBuilder builder = new StringBuilder();
- builder.append(topLevelClassName());
- for (String name : simpleNames().subList(1, simpleNames().size())) {
- builder.append('$').append(name);
- }
- return builder.toString();
- }
+ /**
+ * Return the binary name of a class.
+ */
+ public abstract String reflectionName();
+
+ public abstract ClassName withoutAnnotations();
/**
* Returns a new {@link ClassName} instance for the specified {@code name} as nested inside this
* class.
*/
public ClassName nestedClass(String name) {
- checkNotNull(name, "name == null");
- List<String> result = new ArrayList<>(names.size() + 1);
- result.addAll(names);
- result.add(name);
- return new ClassName(result);
+ return new NestedClassName(this, name);
}
- public List<String> simpleNames() {
- return names.subList(1, names.size());
+ @Override
+ public ClassName annotated(List<AnnotationSpec> annotations) {
+ return (ClassName) super.annotated(annotations);
}
+ public abstract List<String> 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) {
- List<String> result = new ArrayList<>(names);
- result.set(result.size() - 1, name);
- return new ClassName(result);
- }
+ public abstract ClassName peerClass(String name);
+
+ abstract ClassName prefixWithAtMostOneAnnotatedClass();
+
+ abstract boolean hasAnnotatedEnclosingClass();
+
+ abstract CodeWriter emitWithoutPrefix(
+ CodeWriter out, ClassName unannotatedPrefix) throws IOException;
/** Returns the simple name of this class, like {@code "Entry"} for {@link Map.Entry}. */
public String simpleName() {
- return names.get(names.size() - 1);
+ return simpleName;
}
public static ClassName get(Class<?> clazz) {
@@ -139,24 +269,23 @@ public final class ClassName extends TypeName implements Comparable<ClassName> {
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");
- List<String> names = new ArrayList<>();
- while (true) {
- String anonymousSuffix = "";
- while (clazz.isAnonymousClass()) {
- int lastDollar = clazz.getName().lastIndexOf('$');
- anonymousSuffix = clazz.getName().substring(lastDollar) + anonymousSuffix;
- clazz = clazz.getEnclosingClass();
- }
- names.add(clazz.getSimpleName() + anonymousSuffix);
- Class<?> enclosing = clazz.getEnclosingClass();
- if (enclosing == null) break;
- clazz = enclosing;
- }
- // Avoid unreliable Class.getPackage(). https://github.com/square/javapoet/issues/295
- int lastDot = clazz.getName().lastIndexOf('.');
- if (lastDot != -1) names.add(clazz.getName().substring(0, lastDot));
- Collections.reverse(names);
- return new ClassName(names);
+
+ 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 TopLevelClassName(packageName, name);
+ }
+
+ return ClassName.get(clazz.getEnclosingClass()).nestedClass(name);
}
/**
@@ -176,17 +305,24 @@ public final class ClassName extends TypeName implements Comparable<ClassName> {
p = classNameString.indexOf('.', p) + 1;
checkArgument(p != 0, "couldn't make a guess for %s", classNameString);
}
- names.add(p != 0 ? classNameString.substring(0, p - 1) : "");
+ String packageName = p == 0 ? null : classNameString.substring(0, p - 1);
+ String[] classNames = classNameString.substring(p).split("\\.", -1);
+
+ checkArgument(classNames.length >= 1, "couldn't make a guess for %s", classNameString);
+
+ String simpleName = classNames[0];
+ checkArgument(!simpleName.isEmpty() && Character.isUpperCase(simpleName.codePointAt(0)),
+ "couldn't make a guess for %s", classNameString);
+ ClassName className = new TopLevelClassName(packageName, simpleName);
// Add the class names, like "Map" and "Entry".
- for (String part : classNameString.substring(p).split("\\.", -1)) {
+ for (String part : Arrays.asList(classNames).subList(1, classNames.length)) {
checkArgument(!part.isEmpty() && Character.isUpperCase(part.codePointAt(0)),
"couldn't make a guess for %s", classNameString);
- names.add(part);
+ className = className.nestedClass(part);
}
- checkArgument(names.size() >= 2, "couldn't make a guess for %s", classNameString);
- return new ClassName(names);
+ return className;
}
/**
@@ -194,25 +330,26 @@ public final class ClassName extends TypeName implements Comparable<ClassName> {
* {@code "java.util"} and simple names {@code "Map"}, {@code "Entry"} yields {@link Map.Entry}.
*/
public static ClassName get(String packageName, String simpleName, String... simpleNames) {
- List<String> result = new ArrayList<>();
- result.add(packageName);
- result.add(simpleName);
- Collections.addAll(result, simpleNames);
- return new ClassName(result);
+ ClassName className = new TopLevelClassName(packageName, 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");
- List<String> names = new ArrayList<>();
- for (Element e = element; isClassOrInterface(e); e = e.getEnclosingElement()) {
- checkArgument(element.getNestingKind() == TOP_LEVEL || element.getNestingKind() == MEMBER,
- "unexpected type testing");
- names.add(e.getSimpleName().toString());
- }
- names.add(getPackage(element).getQualifiedName().toString());
- Collections.reverse(names);
- return new ClassName(names);
+ checkArgument(element.getNestingKind() == TOP_LEVEL || element.getNestingKind() == MEMBER,
+ "unexpected type nesting");
+ String simpleName = element.getSimpleName().toString();
+
+ if (isClassOrInterface(element.getEnclosingElement())) {
+ return ClassName.get((TypeElement) element.getEnclosingElement()).nestedClass(simpleName);
+ }
+
+ String packageName = getPackage(element.getEnclosingElement()).getQualifiedName().toString();
+ return new TopLevelClassName(packageName, simpleName);
}
private static boolean isClassOrInterface(Element e) {
@@ -227,10 +364,27 @@ public final class ClassName extends TypeName implements Comparable<ClassName> {
}
@Override public int compareTo(ClassName o) {
- return canonicalName.compareTo(o.canonicalName);
+ return reflectionName().compareTo(o.reflectionName());
}
@Override CodeWriter emit(CodeWriter out) throws IOException {
- return out.emitAndIndent(out.lookupName(this));
+ ClassName prefix = prefixWithAtMostOneAnnotatedClass();
+ String unqualifiedName = out.lookupName(prefix);
+ if (prefix.isAnnotated()) {
+ int dot = unqualifiedName.lastIndexOf(".");
+ out.emitAndIndent(unqualifiedName.substring(0, dot + 1));
+ if (dot != -1) {
+ out.emit(" ");
+ }
+ prefix.emitAnnotations(out);
+ out.emit(unqualifiedName.substring(dot + 1));
+ } else {
+ out.emitAndIndent(unqualifiedName);
+ }
+ return emitWithoutPrefix(out, prefix);
+ }
+
+ private static boolean isDefaultPackage(String packageName) {
+ return packageName == null || packageName.isEmpty();
}
}
diff --git a/src/main/java/com/squareup/javapoet/CodeWriter.java b/src/main/java/com/squareup/javapoet/CodeWriter.java
index 9468a08..542f434 100644
--- a/src/main/java/com/squareup/javapoet/CodeWriter.java
+++ b/src/main/java/com/squareup/javapoet/CodeWriter.java
@@ -236,10 +236,6 @@ final class CodeWriter {
case "$T":
TypeName typeName = (TypeName) codeBlock.args.get(a++);
- if (typeName.isAnnotated()) {
- typeName.emitAnnotations(this);
- typeName = typeName.withoutAnnotations();
- }
// defer "typeName.emit(this)" if next format part will be handled by the default case
if (typeName instanceof ClassName && partIterator.hasNext()) {
if (!codeBlock.formatParts.get(partIterator.nextIndex()).startsWith("$")) {
diff --git a/src/main/java/com/squareup/javapoet/JavaFile.java b/src/main/java/com/squareup/javapoet/JavaFile.java
index b6b5a75..e7662dd 100644
--- a/src/main/java/com/squareup/javapoet/JavaFile.java
+++ b/src/main/java/com/squareup/javapoet/JavaFile.java
@@ -145,7 +145,7 @@ public final class JavaFile {
int importedTypesCount = 0;
for (ClassName className : new TreeSet<>(codeWriter.importedTypes().values())) {
if (skipJavaLangImports && className.packageName().equals("java.lang")) continue;
- codeWriter.emit("import $L;\n", className);
+ codeWriter.emit("import $L;\n", className.withoutAnnotations());
importedTypesCount++;
}
diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java
index 453d64d..a2c7c43 100644
--- a/src/main/java/com/squareup/javapoet/MethodSpec.java
+++ b/src/main/java/com/squareup/javapoet/MethodSpec.java
@@ -77,7 +77,7 @@ public final class MethodSpec {
private boolean lastParameterIsArray(List<ParameterSpec> parameters) {
return !parameters.isEmpty()
- && TypeName.arrayComponent(parameters.get(parameters.size() - 1).type) != null;
+ && TypeName.asArray((parameters.get(parameters.size() - 1).type)) != null;
}
void emit(CodeWriter codeWriter, String enclosingName, Set<Modifier> implicitModifiers)
diff --git a/src/main/java/com/squareup/javapoet/ParameterSpec.java b/src/main/java/com/squareup/javapoet/ParameterSpec.java
index 4f52872..63da3f2 100644
--- a/src/main/java/com/squareup/javapoet/ParameterSpec.java
+++ b/src/main/java/com/squareup/javapoet/ParameterSpec.java
@@ -51,10 +51,11 @@ public final class ParameterSpec {
codeWriter.emitAnnotations(annotations, true);
codeWriter.emitModifiers(modifiers);
if (varargs) {
- codeWriter.emit("$T... $L", TypeName.arrayComponent(type), name);
+ TypeName.asArray(type).emit(codeWriter, true);
} else {
- codeWriter.emit("$T $L", type, name);
+ type.emit(codeWriter);
}
+ codeWriter.emit(" $L", name);
}
@Override public boolean equals(Object o) {
diff --git a/src/main/java/com/squareup/javapoet/ParameterizedTypeName.java b/src/main/java/com/squareup/javapoet/ParameterizedTypeName.java
index d46aba8..3a8bf62 100644
--- a/src/main/java/com/squareup/javapoet/ParameterizedTypeName.java
+++ b/src/main/java/com/squareup/javapoet/ParameterizedTypeName.java
@@ -41,7 +41,7 @@ public final class ParameterizedTypeName extends TypeName {
private ParameterizedTypeName(ParameterizedTypeName enclosingType, ClassName rawType,
List<TypeName> typeArguments, List<AnnotationSpec> annotations) {
super(annotations);
- this.rawType = checkNotNull(rawType, "rawType == null");
+ this.rawType = checkNotNull(rawType, "rawType == null").annotated(annotations);
this.enclosingType = enclosingType;
this.typeArguments = Util.immutableList(typeArguments);
@@ -58,17 +58,22 @@ public final class ParameterizedTypeName extends TypeName {
enclosingType, rawType, typeArguments, concatAnnotations(annotations));
}
- @Override public TypeName withoutAnnotations() {
- return new ParameterizedTypeName(enclosingType, rawType, typeArguments, new ArrayList<>());
+ @Override
+ public TypeName withoutAnnotations() {
+ return new ParameterizedTypeName(
+ enclosingType, rawType.withoutAnnotations(), typeArguments, new ArrayList<>());
}
@Override CodeWriter emit(CodeWriter out) throws IOException {
if (enclosingType != null) {
- enclosingType.emitAnnotations(out);
enclosingType.emit(out);
- out.emit("." + rawType.simpleName());
+ out.emit(".");
+ if (isAnnotated()) {
+ out.emit(" ");
+ emitAnnotations(out);
+ }
+ out.emit(rawType.simpleName());
} else {
- rawType.emitAnnotations(out);
rawType.emit(out);
}
if (!typeArguments.isEmpty()) {
@@ -76,7 +81,6 @@ public final class ParameterizedTypeName extends TypeName {
boolean firstParameter = true;
for (TypeName parameter : typeArguments) {
if (!firstParameter) out.emitAndIndent(", ");
- parameter.emitAnnotations(out);
parameter.emit(out);
firstParameter = false;
}
diff --git a/src/main/java/com/squareup/javapoet/TypeName.java b/src/main/java/com/squareup/javapoet/TypeName.java
index e09d785..38877f7 100644
--- a/src/main/java/com/squareup/javapoet/TypeName.java
+++ b/src/main/java/com/squareup/javapoet/TypeName.java
@@ -209,7 +209,6 @@ public class TypeName {
try {
StringBuilder resultBuilder = new StringBuilder();
CodeWriter codeWriter = new CodeWriter(resultBuilder);
- emitAnnotations(codeWriter);
emit(codeWriter);
result = resultBuilder.toString();
cachedString = result;
@@ -222,6 +221,11 @@ public class TypeName {
CodeWriter emit(CodeWriter out) throws IOException {
if (keyword == null) throw new AssertionError();
+
+ if (isAnnotated()) {
+ out.emit("");
+ emitAnnotations(out);
+ }
return out.emitAndIndent(keyword);
}
@@ -233,6 +237,7 @@ public class TypeName {
return out;
}
+
/** Returns a type name equivalent to {@code mirror}. */
public static TypeName get(TypeMirror mirror) {
return get(mirror, new LinkedHashMap<>());
@@ -369,4 +374,12 @@ public class TypeName {
? ((ArrayTypeName) type).componentType
: null;
}
+
+ /** Returns {@code type} as an array, or null if {@code type} is not an array. */
+ static ArrayTypeName asArray(TypeName type) {
+ return type instanceof ArrayTypeName
+ ? ((ArrayTypeName) type)
+ : null;
+ }
+
}
diff --git a/src/main/java/com/squareup/javapoet/TypeVariableName.java b/src/main/java/com/squareup/javapoet/TypeVariableName.java
index e0e54fb..54c2fa5 100644
--- a/src/main/java/com/squareup/javapoet/TypeVariableName.java
+++ b/src/main/java/com/squareup/javapoet/TypeVariableName.java
@@ -80,6 +80,7 @@ public final class TypeVariableName extends TypeName {
}
@Override CodeWriter emit(CodeWriter out) throws IOException {
+ emitAnnotations(out);
return out.emitAndIndent(name);
}