1 /* 2 * Copyright (C) 2015 Square, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.squareup.javapoet; 17 18 import java.lang.annotation.ElementType; 19 import java.lang.annotation.Target; 20 import java.util.List; 21 import java.util.Map; 22 import org.junit.Test; 23 24 import static com.google.common.truth.Truth.assertThat; 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertNotEquals; 28 import static org.junit.Assert.assertTrue; 29 30 public class AnnotatedTypeNameTest { 31 32 private final static String NN = NeverNull.class.getCanonicalName(); 33 private final AnnotationSpec NEVER_NULL = AnnotationSpec.builder(NeverNull.class).build(); 34 private final static String TUA = TypeUseAnnotation.class.getCanonicalName(); 35 private final AnnotationSpec TYPE_USE_ANNOTATION = 36 AnnotationSpec.builder(TypeUseAnnotation.class).build(); 37 38 @Target(ElementType.TYPE_USE) 39 public @interface NeverNull {} 40 41 @Target(ElementType.TYPE_USE) 42 public @interface TypeUseAnnotation {} 43 44 45 @Test(expected=NullPointerException.class) public void nullAnnotationArray() { 46 TypeName.BOOLEAN.annotated((AnnotationSpec[]) null); 47 } 48 49 @Test(expected=NullPointerException.class) public void nullAnnotationList() { 50 TypeName.DOUBLE.annotated((List<AnnotationSpec>) null); 51 } 52 53 @Test public void annotated() { 54 TypeName simpleString = TypeName.get(String.class); 55 assertFalse(simpleString.isAnnotated()); 56 assertEquals(simpleString, TypeName.get(String.class)); 57 58 TypeName annotated = simpleString.annotated(NEVER_NULL); 59 assertTrue(annotated.isAnnotated()); 60 assertEquals(annotated, annotated.annotated()); 61 } 62 63 @Test public void annotatedType() { 64 TypeName type = TypeName.get(String.class); 65 TypeName actual = type.annotated(TYPE_USE_ANNOTATION); 66 assertThat(actual.toString()).isEqualTo("java.lang. @" + TUA + " String"); 67 } 68 69 @Test public void annotatedTwice() { 70 TypeName type = TypeName.get(String.class); 71 TypeName actual = 72 type.annotated(NEVER_NULL) 73 .annotated(TYPE_USE_ANNOTATION); 74 assertThat(actual.toString()) 75 .isEqualTo("java.lang. @" + NN + " @" + TUA + " String"); 76 } 77 78 @Test public void annotatedParameterizedType() { 79 TypeName type = ParameterizedTypeName.get(List.class, String.class); 80 TypeName actual = type.annotated(TYPE_USE_ANNOTATION); 81 assertThat(actual.toString()).isEqualTo("java.util. @" + TUA + " List<java.lang.String>"); 82 } 83 84 @Test public void annotatedArgumentOfParameterizedType() { 85 TypeName type = TypeName.get(String.class).annotated(TYPE_USE_ANNOTATION); 86 TypeName actual = ParameterizedTypeName.get(ClassName.get(List.class), type); 87 assertThat(actual.toString()).isEqualTo("java.util.List<java.lang. @" + TUA + " String>"); 88 } 89 90 @Test public void annotatedWildcardTypeNameWithSuper() { 91 TypeName type = TypeName.get(String.class).annotated(TYPE_USE_ANNOTATION); 92 TypeName actual = WildcardTypeName.supertypeOf(type); 93 assertThat(actual.toString()).isEqualTo("? super java.lang. @" + TUA + " String"); 94 } 95 96 @Test public void annotatedWildcardTypeNameWithExtends() { 97 TypeName type = TypeName.get(String.class).annotated(TYPE_USE_ANNOTATION); 98 TypeName actual = WildcardTypeName.subtypeOf(type); 99 assertThat(actual.toString()).isEqualTo("? extends java.lang. @" + TUA + " String"); 100 } 101 102 @Test public void annotatedEquivalence() { 103 annotatedEquivalence(TypeName.VOID); 104 annotatedEquivalence(ArrayTypeName.get(Object[].class)); 105 annotatedEquivalence(ClassName.get(Object.class)); 106 annotatedEquivalence(ParameterizedTypeName.get(List.class, Object.class)); 107 annotatedEquivalence(TypeVariableName.get(Object.class)); 108 annotatedEquivalence(WildcardTypeName.get(Object.class)); 109 } 110 111 private void annotatedEquivalence(TypeName type) { 112 assertFalse(type.isAnnotated()); 113 assertEquals(type, type); 114 assertEquals(type.annotated(TYPE_USE_ANNOTATION), type.annotated(TYPE_USE_ANNOTATION)); 115 assertNotEquals(type, type.annotated(TYPE_USE_ANNOTATION)); 116 assertEquals(type.hashCode(), type.hashCode()); 117 assertEquals(type.annotated(TYPE_USE_ANNOTATION).hashCode(), 118 type.annotated(TYPE_USE_ANNOTATION).hashCode()); 119 assertNotEquals(type.hashCode(), type.annotated(TYPE_USE_ANNOTATION).hashCode()); 120 } 121 122 // https://github.com/square/javapoet/issues/431 123 @Test public void annotatedNestedType() { 124 TypeName type = TypeName.get(Map.Entry.class).annotated(TYPE_USE_ANNOTATION); 125 assertThat(type.toString()).isEqualTo("java.util.Map. @" + TUA + " Entry"); 126 } 127 128 @Test public void annotatedEnclosingAndNestedType() { 129 TypeName type = ((ClassName) TypeName.get(Map.class).annotated(TYPE_USE_ANNOTATION)) 130 .nestedClass("Entry").annotated(TYPE_USE_ANNOTATION); 131 assertThat(type.toString()).isEqualTo("java.util. @" + TUA + " Map. @" + TUA + " Entry"); 132 } 133 134 // https://github.com/square/javapoet/issues/431 135 @Test public void annotatedNestedParameterizedType() { 136 TypeName type = ParameterizedTypeName.get(Map.Entry.class, Byte.class, Byte.class) 137 .annotated(TYPE_USE_ANNOTATION); 138 assertThat(type.toString()) 139 .isEqualTo("java.util.Map. @" + TUA + " Entry<java.lang.Byte, java.lang.Byte>"); 140 } 141 142 @Test public void withoutAnnotationsOnAnnotatedEnclosingAndNestedType() { 143 TypeName type = ((ClassName) TypeName.get(Map.class).annotated(TYPE_USE_ANNOTATION)) 144 .nestedClass("Entry").annotated(TYPE_USE_ANNOTATION); 145 assertThat(type.isAnnotated()).isTrue(); 146 assertThat(type.withoutAnnotations()).isEqualTo(TypeName.get(Map.Entry.class)); 147 } 148 149 @Test public void withoutAnnotationsOnAnnotatedEnclosingType() { 150 TypeName type = ((ClassName) TypeName.get(Map.class).annotated(TYPE_USE_ANNOTATION)) 151 .nestedClass("Entry"); 152 assertThat(type.isAnnotated()).isTrue(); 153 assertThat(type.withoutAnnotations()).isEqualTo(TypeName.get(Map.Entry.class)); 154 } 155 156 @Test public void withoutAnnotationsOnAnnotatedNestedType() { 157 TypeName type = ((ClassName) TypeName.get(Map.class)) 158 .nestedClass("Entry").annotated(TYPE_USE_ANNOTATION); 159 assertThat(type.isAnnotated()).isTrue(); 160 assertThat(type.withoutAnnotations()).isEqualTo(TypeName.get(Map.Entry.class)); 161 } 162 163 // https://github.com/square/javapoet/issues/614 164 @Test public void annotatedArrayType() { 165 TypeName type = ArrayTypeName.of(ClassName.get(Object.class)).annotated(TYPE_USE_ANNOTATION); 166 assertThat(type.toString()).isEqualTo("java.lang.Object @" + TUA + " []"); 167 } 168 169 @Test public void annotatedArrayElementType() { 170 TypeName type = ArrayTypeName.of(ClassName.get(Object.class).annotated(TYPE_USE_ANNOTATION)); 171 assertThat(type.toString()).isEqualTo("java.lang. @" + TUA + " Object[]"); 172 } 173 174 // https://github.com/square/javapoet/issues/614 175 @Test public void annotatedOuterMultidimensionalArrayType() { 176 TypeName type = ArrayTypeName.of(ArrayTypeName.of(ClassName.get(Object.class))) 177 .annotated(TYPE_USE_ANNOTATION); 178 assertThat(type.toString()).isEqualTo("java.lang.Object @" + TUA + " [][]"); 179 } 180 181 // https://github.com/square/javapoet/issues/614 182 @Test public void annotatedInnerMultidimensionalArrayType() { 183 TypeName type = ArrayTypeName.of(ArrayTypeName.of(ClassName.get(Object.class)) 184 .annotated(TYPE_USE_ANNOTATION)); 185 assertThat(type.toString()).isEqualTo("java.lang.Object[] @" + TUA + " []"); 186 } 187 188 // https://github.com/square/javapoet/issues/614 189 @Test public void annotatedArrayTypeVarargsParameter() { 190 TypeName type = ArrayTypeName.of(ArrayTypeName.of(ClassName.get(Object.class))) 191 .annotated(TYPE_USE_ANNOTATION); 192 MethodSpec varargsMethod = MethodSpec.methodBuilder("m") 193 .addParameter( 194 ParameterSpec.builder(type, "p") 195 .build()) 196 .varargs() 197 .build(); 198 assertThat(varargsMethod.toString()).isEqualTo("" 199 + "void m(java.lang.Object @" + TUA + " []... p) {\n" 200 + "}\n"); 201 } 202 203 // https://github.com/square/javapoet/issues/614 204 @Test public void annotatedArrayTypeInVarargsParameter() { 205 TypeName type = ArrayTypeName.of(ArrayTypeName.of(ClassName.get(Object.class)) 206 .annotated(TYPE_USE_ANNOTATION)); 207 MethodSpec varargsMethod = MethodSpec.methodBuilder("m") 208 .addParameter( 209 ParameterSpec.builder(type, "p") 210 .build()) 211 .varargs() 212 .build(); 213 assertThat(varargsMethod.toString()).isEqualTo("" 214 + "void m(java.lang.Object[] @" + TUA + " ... p) {\n" 215 + "}\n"); 216 } 217 } 218