diff options
Diffstat (limited to 'src')
7 files changed, 200 insertions, 6 deletions
diff --git a/src/main/java/com/squareup/javapoet/ArrayTypeName.java b/src/main/java/com/squareup/javapoet/ArrayTypeName.java index 46653ea..6f1e2c4 100644 --- a/src/main/java/com/squareup/javapoet/ArrayTypeName.java +++ b/src/main/java/com/squareup/javapoet/ArrayTypeName.java @@ -18,7 +18,10 @@ 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.Arrays; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import javax.lang.model.element.TypeParameterElement; @@ -30,9 +33,22 @@ public final class ArrayTypeName extends TypeName { public final TypeName componentType; private ArrayTypeName(TypeName componentType) { + this(componentType, new ArrayList<AnnotationSpec>()); + } + + private ArrayTypeName(TypeName componentType, List<AnnotationSpec> annotations) { + super(annotations); this.componentType = checkNotNull(componentType, "rawType == null"); } + @Override public ArrayTypeName annotated(AnnotationSpec... annotations) { + return annotated(Arrays.asList(annotations)); + } + + @Override public ArrayTypeName annotated(List<AnnotationSpec> annotations) { + return new ArrayTypeName(componentType, annotations); + } + @Override public boolean equals(Object o) { return o instanceof ArrayTypeName && ((ArrayTypeName) o).componentType.equals(componentType); @@ -43,7 +59,7 @@ public final class ArrayTypeName extends TypeName { } @Override CodeWriter emit(CodeWriter out) throws IOException { - return out.emit("$T[]", componentType); + return emitAnnotations(out).emit("$T[]", componentType); } /** Returns an array type whose elements are all instances of {@code componentType}. */ diff --git a/src/main/java/com/squareup/javapoet/ClassName.java b/src/main/java/com/squareup/javapoet/ClassName.java index fdfe81f..0f6d7ce 100644 --- a/src/main/java/com/squareup/javapoet/ClassName.java +++ b/src/main/java/com/squareup/javapoet/ClassName.java @@ -17,6 +17,7 @@ package com.squareup.javapoet; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -40,6 +41,11 @@ public final class ClassName extends TypeName implements Comparable<ClassName> { final String canonicalName; private ClassName(List<String> names) { + this(names, new ArrayList<AnnotationSpec>()); + } + + 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)); } @@ -49,6 +55,14 @@ public final class ClassName extends TypeName implements Comparable<ClassName> { : Util.join(".", names); } + @Override public ClassName annotated(AnnotationSpec... annotations) { + return annotated(Arrays.asList(annotations)); + } + + @Override public ClassName annotated(List<AnnotationSpec> annotations) { + return new ClassName(names, annotations); + } + /** Returns the package name, like {@code "java.util"} for {@code Map.Entry}. */ public String packageName() { return names.get(0); @@ -203,6 +217,6 @@ public final class ClassName extends TypeName implements Comparable<ClassName> { } @Override CodeWriter emit(CodeWriter out) throws IOException { - return out.emitAndIndent(out.lookupName(this)); + return emitAnnotations(out).emitAndIndent(out.lookupName(this)); } } diff --git a/src/main/java/com/squareup/javapoet/ParameterizedTypeName.java b/src/main/java/com/squareup/javapoet/ParameterizedTypeName.java index f285144..6cdccfa 100644 --- a/src/main/java/com/squareup/javapoet/ParameterizedTypeName.java +++ b/src/main/java/com/squareup/javapoet/ParameterizedTypeName.java @@ -18,6 +18,7 @@ package com.squareup.javapoet; import java.io.IOException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -29,6 +30,12 @@ public final class ParameterizedTypeName extends TypeName { public final List<TypeName> typeArguments; ParameterizedTypeName(ClassName rawType, List<TypeName> typeArguments) { + this(rawType, typeArguments, new ArrayList<AnnotationSpec>()); + } + + ParameterizedTypeName(ClassName rawType, List<TypeName> typeArguments, + List<AnnotationSpec> annotations) { + super(annotations); this.rawType = checkNotNull(rawType, "rawType == null"); this.typeArguments = Util.immutableList(typeArguments); @@ -39,6 +46,14 @@ public final class ParameterizedTypeName extends TypeName { } } + @Override public ParameterizedTypeName annotated(AnnotationSpec... annotations) { + return annotated(Arrays.asList(annotations)); + } + + @Override public ParameterizedTypeName annotated(List<AnnotationSpec> annotations) { + return new ParameterizedTypeName(rawType, typeArguments, annotations); + } + @Override public boolean equals(Object o) { return o instanceof ParameterizedTypeName && ((ParameterizedTypeName) o).rawType.equals(rawType) @@ -50,6 +65,7 @@ public final class ParameterizedTypeName extends TypeName { } @Override CodeWriter emit(CodeWriter out) throws IOException { + emitAnnotations(out); rawType.emit(out); out.emitAndIndent("<"); boolean firstParameter = true; diff --git a/src/main/java/com/squareup/javapoet/TypeName.java b/src/main/java/com/squareup/javapoet/TypeName.java index 8ee2772..2758bbe 100644 --- a/src/main/java/com/squareup/javapoet/TypeName.java +++ b/src/main/java/com/squareup/javapoet/TypeName.java @@ -22,6 +22,7 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -87,14 +88,34 @@ public class TypeName { /** The name of this type if it is a keyword, or null. */ private final String keyword; + public final List<AnnotationSpec> annotations; private TypeName(String keyword) { + this(keyword, new ArrayList<AnnotationSpec>()); + } + + private TypeName(String keyword, List<AnnotationSpec> annotations) { this.keyword = keyword; + this.annotations = Util.immutableList(annotations); } // Package-private constructor to prevent third-party subclasses. - TypeName() { - this(null); + TypeName(List<AnnotationSpec> annotations) { + this(null, annotations); + } + + public TypeName annotated(AnnotationSpec... annotations) { + Util.checkNotNull(annotations, "annotations == null"); + return new TypeName(keyword, Arrays.asList(annotations)); + } + + public TypeName annotated(List<AnnotationSpec> annotations) { + Util.checkNotNull(annotations, "annotations == null"); + return new TypeName(keyword, annotations); + } + + public boolean isAnnotated() { + return !annotations.isEmpty(); } public boolean isPrimitive() { @@ -162,7 +183,15 @@ public class TypeName { CodeWriter emit(CodeWriter out) throws IOException { if (keyword == null) throw new AssertionError(); - return out.emitAndIndent(keyword); + return emitAnnotations(out).emitAndIndent(keyword); + } + + CodeWriter emitAnnotations(CodeWriter out) throws IOException { + for (AnnotationSpec annotation : annotations) { + annotation.emit(out, true); + out.emit(" "); + } + return out; } /** Returns a type name equivalent to {@code mirror}. */ diff --git a/src/main/java/com/squareup/javapoet/TypeVariableName.java b/src/main/java/com/squareup/javapoet/TypeVariableName.java index ac861f3..b4e1ac0 100644 --- a/src/main/java/com/squareup/javapoet/TypeVariableName.java +++ b/src/main/java/com/squareup/javapoet/TypeVariableName.java @@ -35,6 +35,11 @@ public final class TypeVariableName extends TypeName { public final List<TypeName> bounds; private TypeVariableName(String name, List<TypeName> bounds) { + this(name, bounds, new ArrayList<AnnotationSpec>()); + } + + private TypeVariableName(String name, List<TypeName> bounds, List<AnnotationSpec> annotations) { + super(annotations); this.name = checkNotNull(name, "name == null"); this.bounds = bounds; @@ -43,6 +48,14 @@ public final class TypeVariableName extends TypeName { } } + @Override public TypeVariableName annotated(AnnotationSpec... annotations) { + return annotated(Arrays.asList(annotations)); + } + + @Override public TypeVariableName annotated(List<AnnotationSpec> annotations) { + return new TypeVariableName(name, bounds, annotations); + } + private static TypeVariableName of(String name, List<TypeName> bounds) { // Strip java.lang.Object from bounds if it is present. List<TypeName> boundsNoObject = new ArrayList<>(bounds); @@ -61,7 +74,7 @@ public final class TypeVariableName extends TypeName { } @Override CodeWriter emit(CodeWriter out) throws IOException { - return out.emitAndIndent(name); + return emitAnnotations(out).emitAndIndent(name); } /** Returns type variable named {@code name} without bounds. */ diff --git a/src/main/java/com/squareup/javapoet/WildcardTypeName.java b/src/main/java/com/squareup/javapoet/WildcardTypeName.java index 5e55fbb..fc11867 100644 --- a/src/main/java/com/squareup/javapoet/WildcardTypeName.java +++ b/src/main/java/com/squareup/javapoet/WildcardTypeName.java @@ -18,6 +18,7 @@ package com.squareup.javapoet; import java.io.IOException; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; @@ -33,6 +34,12 @@ public final class WildcardTypeName extends TypeName { public final List<TypeName> lowerBounds; private WildcardTypeName(List<TypeName> upperBounds, List<TypeName> lowerBounds) { + this(upperBounds, lowerBounds, new ArrayList<AnnotationSpec>()); + } + + private WildcardTypeName(List<TypeName> upperBounds, List<TypeName> lowerBounds, + List<AnnotationSpec> annotations) { + super(annotations); this.upperBounds = Util.immutableList(upperBounds); this.lowerBounds = Util.immutableList(lowerBounds); @@ -47,6 +54,14 @@ public final class WildcardTypeName extends TypeName { } } + @Override public WildcardTypeName annotated(AnnotationSpec... annotations) { + return annotated(Arrays.asList(annotations)); + } + + @Override public WildcardTypeName annotated(List<AnnotationSpec> annotations) { + return new WildcardTypeName(upperBounds, lowerBounds, annotations); + } + @Override public boolean equals(Object o) { return o instanceof WildcardTypeName && ((WildcardTypeName) o).upperBounds.equals(upperBounds) @@ -58,6 +73,7 @@ public final class WildcardTypeName extends TypeName { } @Override CodeWriter emit(CodeWriter out) throws IOException { + emitAnnotations(out); if (lowerBounds.size() == 1) { return out.emit("? super $T", lowerBounds.get(0)); } diff --git a/src/test/java/com/squareup/javapoet/AnnotatedTypeNameTest.java b/src/test/java/com/squareup/javapoet/AnnotatedTypeNameTest.java new file mode 100644 index 0000000..2573264 --- /dev/null +++ b/src/test/java/com/squareup/javapoet/AnnotatedTypeNameTest.java @@ -0,0 +1,90 @@ +/* + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import org.junit.Test; + +public class AnnotatedTypeNameTest { + + private final static String NN = NeverNull.class.getCanonicalName(); + + public @interface NeverNull {} + + @Test(expected=NullPointerException.class) public void nullAnnotationArray() { + TypeName.BOOLEAN.annotated((AnnotationSpec[]) null); + } + + @Test(expected=NullPointerException.class) public void nullAnnotationList() { + TypeName.DOUBLE.annotated((List<AnnotationSpec>) null); + } + + @Test public void annotated() { + TypeName simpleString = TypeName.get(String.class); + assertFalse(simpleString.isAnnotated()); + assertEquals(simpleString, TypeName.get(String.class)); + TypeName annotated = simpleString.annotated(AnnotationSpec.builder(NeverNull.class).build()); + assertTrue(annotated.isAnnotated()); + assertEquals(simpleString, annotated.annotated()); + assertFalse(annotated.annotated().isAnnotated()); + } + + @Test public void annotatedType() { + String expected = "@" + NN + " java.lang.String"; + AnnotationSpec annotation = AnnotationSpec.builder(NeverNull.class).build(); + TypeName type = TypeName.get(String.class); + String actual = type.annotated(annotation).toString(); + assertEquals(expected, actual); + } + + @Test public void annotatedParameterizedType() { + String expected = "@" + NN + " java.util.List<java.lang.String>"; + AnnotationSpec annotation = AnnotationSpec.builder(NeverNull.class).build(); + TypeName type = ParameterizedTypeName.get(List.class, String.class); + String actual = type.annotated(annotation).toString(); + assertEquals(expected, actual); + } + + @Test public void annotatedArgumentOfParameterizedType() { + String expected = "java.util.List<@" + NN + " java.lang.String>"; + AnnotationSpec annotation = AnnotationSpec.builder(NeverNull.class).build(); + TypeName type = TypeName.get(String.class).annotated(annotation); + ClassName list = ClassName.get(List.class); + String actual = ParameterizedTypeName.get(list, type).toString(); + assertEquals(expected, actual); + } + + @Test public void annotatedWildcardTypeNameWithSuper() { + String expected = "? super @" + NN + " java.lang.String"; + AnnotationSpec annotation = AnnotationSpec.builder(NeverNull.class).build(); + TypeName type = TypeName.get(String.class).annotated(annotation); + String actual = WildcardTypeName.supertypeOf(type).toString(); + assertEquals(expected, actual); + } + + @Test public void annotatedWildcardTypeNameWithExtends() { + String expected = "? extends @" + NN + " java.lang.String"; + AnnotationSpec annotation = AnnotationSpec.builder(NeverNull.class).build(); + TypeName type = TypeName.get(String.class).annotated(annotation); + String actual = WildcardTypeName.subtypeOf(type).toString(); + assertEquals(expected, actual); + } + +} |