50 import javax.lang.model.element.ModuleElement; 51 import javax.lang.model.element.TypeElement; 52 53 import com.sun.tools.classfile.Attribute; 54 import com.sun.tools.classfile.ClassFile; 55 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; 56 import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; 57 import toolbox.JavacTask; 58 import toolbox.Task.OutputKind; 59 60 public class AnnotationsOnModules extends ModuleTestBase { 61 62 public static void main(String... args) throws Exception { 63 AnnotationsOnModules t = new AnnotationsOnModules(); 64 t.runTests(); 65 } 66 67 @Test 68 public void testSimpleAnnotation(Path base) throws Exception { 69 Path moduleSrc = base.resolve("module-src"); 70 Path m1 = moduleSrc.resolve("m1"); 71 72 tb.writeJavaFiles(m1, 73 "@Deprecated module m1 { }"); 74 75 Path modulePath = base.resolve("module-path"); 76 77 Files.createDirectories(modulePath); 78 79 new JavacTask(tb) 80 .options("--module-source-path", moduleSrc.toString()) 81 .outdir(modulePath) 82 .files(findJavaFiles(m1)) 83 .run() 84 .writeAll(); 85 86 ClassFile cf = ClassFile.read(modulePath.resolve("m1").resolve("module-info.class")); 87 RuntimeVisibleAnnotations_attribute annotations = (RuntimeVisibleAnnotations_attribute) cf.attributes.map.get(Attribute.RuntimeVisibleAnnotations); 88 89 if (annotations == null || annotations.annotations.length != 1) { 90 throw new AssertionError("Annotations not correct!"); 91 } 92 } 93 94 @Test 95 public void testAnnotationWithImport(Path base) throws Exception { 96 Path moduleSrc = base.resolve("module-src"); 97 Path m1 = moduleSrc.resolve("m1"); 98 99 tb.writeJavaFiles(m1, 100 "import m1.A; @A module m1 { }", 101 "package m1; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface A {}"); 102 103 Path modulePath = base.resolve("module-path"); 104 105 Files.createDirectories(modulePath); 106 107 new JavacTask(tb) 108 .options("--module-source-path", moduleSrc.toString()) 109 .outdir(modulePath) 110 .files(findJavaFiles(m1)) 111 .run() 112 .writeAll(); 113 114 ClassFile cf = ClassFile.read(modulePath.resolve("m1").resolve("module-info.class")); 115 RuntimeInvisibleAnnotations_attribute annotations = (RuntimeInvisibleAnnotations_attribute) cf.attributes.map.get(Attribute.RuntimeInvisibleAnnotations); 116 117 if (annotations == null || annotations.annotations.length != 1) { 118 throw new AssertionError("Annotations not correct!"); 119 } 120 } 121 122 @Test 123 public void testModuleInfoAnnotationsInAPI(Path base) throws Exception { 124 Path moduleSrc = base.resolve("module-src"); 125 Path m1 = moduleSrc.resolve("m1"); 126 127 tb.writeJavaFiles(m1, 128 "import m1.*; @A @Deprecated @E @E module m1 { }", 129 "package m1; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface A {}", 130 "package m1; import java.lang.annotation.*; @Target(ElementType.MODULE) @Repeatable(C.class) public @interface E {}", 131 "package m1; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface C { public E[] value(); }"); 132 133 Path modulePath = base.resolve("module-path"); 134 135 Files.createDirectories(modulePath); 136 137 new JavacTask(tb) 138 .options("--module-source-path", moduleSrc.toString(), 139 "-processor", AP.class.getName()) 140 .outdir(modulePath) 141 .files(findJavaFiles(m1)) 142 .run() 143 .writeAll(); 144 145 Path src = base.resolve("src"); 146 147 tb.writeJavaFiles(src, 148 "class T {}"); 149 150 Path out = base.resolve("out"); 151 152 Files.createDirectories(out); 153 154 new JavacTask(tb) 155 .options("--module-path", modulePath.toString(), 156 "--add-modules", "m1", 157 "-processor", AP.class.getName()) 158 .outdir(out) 159 .files(findJavaFiles(src)) 160 .run() 161 .writeAll(); 162 163 new JavacTask(tb) 164 .options("--module-path", modulePath.toString() + File.pathSeparator + out.toString(), 165 "--add-modules", "m1", 166 "-processor", AP.class.getName(), 167 "-proc:only") 168 .classes("m1/m1.A") 169 .files(findJavaFiles(src)) 170 .run() 171 .writeAll(); 172 } 173 174 @SupportedAnnotationTypes("*") 175 public static final class AP extends AbstractProcessor { 176 177 @Override 178 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 179 ModuleElement m1 = processingEnv.getElementUtils().getModuleElement("m1"); 180 Set<String> actualAnnotations = new HashSet<>(); 181 Set<String> expectedAnnotations = 182 new HashSet<>(Arrays.asList("@m1.A", "@java.lang.Deprecated", "@m1.C({@m1.E, @m1.E})")); 183 184 for (AnnotationMirror am : m1.getAnnotationMirrors()) { 185 actualAnnotations.add(am.toString()); 186 } 187 188 if (!expectedAnnotations.equals(actualAnnotations)) { 189 throw new AssertionError("Incorrect annotations: " + actualAnnotations); 190 } 191 192 return false; 193 } 194 195 } 196 197 @Test 198 public void testModuleDeprecation(Path base) throws Exception { 199 Path moduleSrc = base.resolve("module-src"); 200 Path m1 = moduleSrc.resolve("m1"); 201 202 tb.writeJavaFiles(m1, 203 "@Deprecated module m1 { }"); 204 205 Path m2 = moduleSrc.resolve("m2"); 206 207 tb.writeJavaFiles(m2, 208 "@Deprecated module m2 { }"); 209 210 Path m3 = moduleSrc.resolve("m3"); 211 212 Path modulePath = base.resolve("module-path"); 213 214 Files.createDirectories(modulePath); 215 216 List<String> actual; 217 List<String> expected; 218 219 for (String suppress : new String[] {"", "@Deprecated ", "@SuppressWarnings(\"deprecation\") "}) { 220 tb.writeJavaFiles(m3, 221 suppress + "module m3 {\n" + 222 " requires m1;\n" + 223 " exports api to m1, m2;\n" + 224 "}", 225 "package api; public class Api { }"); 226 System.err.println("compile m3"); 227 actual = new JavacTask(tb) 228 .options("--module-source-path", moduleSrc.toString(), 229 "-XDrawDiagnostics") 230 .outdir(modulePath) 231 .files(findJavaFiles(moduleSrc)) 232 .run() 233 .writeAll() 234 .getOutputLines(OutputKind.DIRECT); 235 236 if (suppress.isEmpty()) { 237 expected = Arrays.asList( 238 "- compiler.note.deprecated.filename: module-info.java", 239 "- compiler.note.deprecated.recompile"); 240 } else { 241 expected = Arrays.asList(""); 242 } 243 244 if (!expected.equals(actual)) { 245 throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress); 246 } 247 248 System.err.println("compile m3 with -Xlint:-deprecation"); 249 actual = new JavacTask(tb) 250 .options("--module-source-path", moduleSrc.toString(), 251 "-XDrawDiagnostics", 252 "-Xlint:deprecation") 253 .outdir(modulePath) 254 .files(findJavaFiles(moduleSrc)) 255 .run() 256 .writeAll() 257 .getOutputLines(OutputKind.DIRECT); 258 259 if (suppress.isEmpty()) { 260 expected = Arrays.asList( 261 "module-info.java:2:14: compiler.warn.has.been.deprecated.module: m1", 262 "1 warning"); 263 } else { 264 expected = Arrays.asList(""); 265 } 266 267 if (!expected.equals(actual)) { 268 throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress); 269 } 270 271 //load the deprecated module-infos from classfile: 272 System.err.println("compile m3 with -Xlint:-deprecation, loading deprecated modules from classes"); 273 actual = new JavacTask(tb) 274 .options("--module-path", modulePath.toString(), 275 "-XDrawDiagnostics", 276 "-Xlint:deprecation") 277 .outdir(modulePath.resolve("m3")) 278 .files(findJavaFiles(moduleSrc.resolve("m3"))) 279 .run() 280 .writeAll() 281 .getOutputLines(OutputKind.DIRECT); 282 283 if (!expected.equals(actual)) { 284 throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress); 285 } 286 } 287 } 288 289 @Test 290 public void testAttributeValues(Path base) throws Exception { 291 class TestCase { 292 public final String extraDecl; 293 public final String decl; 294 public final String use; 295 public final String expectedAnnotations; 296 297 public TestCase(String extraDecl, String decl, String use, String expectedAnnotations) { 298 this.extraDecl = extraDecl; | 50 import javax.lang.model.element.ModuleElement; 51 import javax.lang.model.element.TypeElement; 52 53 import com.sun.tools.classfile.Attribute; 54 import com.sun.tools.classfile.ClassFile; 55 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; 56 import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; 57 import toolbox.JavacTask; 58 import toolbox.Task.OutputKind; 59 60 public class AnnotationsOnModules extends ModuleTestBase { 61 62 public static void main(String... args) throws Exception { 63 AnnotationsOnModules t = new AnnotationsOnModules(); 64 t.runTests(); 65 } 66 67 @Test 68 public void testSimpleAnnotation(Path base) throws Exception { 69 Path moduleSrc = base.resolve("module-src"); 70 Path m1 = moduleSrc.resolve("m1x"); 71 72 tb.writeJavaFiles(m1, 73 "@Deprecated module m1x { }"); 74 75 Path modulePath = base.resolve("module-path"); 76 77 Files.createDirectories(modulePath); 78 79 new JavacTask(tb) 80 .options("--module-source-path", moduleSrc.toString()) 81 .outdir(modulePath) 82 .files(findJavaFiles(m1)) 83 .run() 84 .writeAll(); 85 86 ClassFile cf = ClassFile.read(modulePath.resolve("m1x").resolve("module-info.class")); 87 RuntimeVisibleAnnotations_attribute annotations = (RuntimeVisibleAnnotations_attribute) cf.attributes.map.get(Attribute.RuntimeVisibleAnnotations); 88 89 if (annotations == null || annotations.annotations.length != 1) { 90 throw new AssertionError("Annotations not correct!"); 91 } 92 } 93 94 @Test 95 public void testAnnotationWithImport(Path base) throws Exception { 96 Path moduleSrc = base.resolve("module-src"); 97 Path m1 = moduleSrc.resolve("m1x"); 98 99 tb.writeJavaFiles(m1, 100 "import m1x.A; @A module m1x { }", 101 "package m1x; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface A {}"); 102 103 Path modulePath = base.resolve("module-path"); 104 105 Files.createDirectories(modulePath); 106 107 new JavacTask(tb) 108 .options("--module-source-path", moduleSrc.toString()) 109 .outdir(modulePath) 110 .files(findJavaFiles(m1)) 111 .run() 112 .writeAll(); 113 114 ClassFile cf = ClassFile.read(modulePath.resolve("m1x").resolve("module-info.class")); 115 RuntimeInvisibleAnnotations_attribute annotations = (RuntimeInvisibleAnnotations_attribute) cf.attributes.map.get(Attribute.RuntimeInvisibleAnnotations); 116 117 if (annotations == null || annotations.annotations.length != 1) { 118 throw new AssertionError("Annotations not correct!"); 119 } 120 } 121 122 @Test 123 public void testModuleInfoAnnotationsInAPI(Path base) throws Exception { 124 Path moduleSrc = base.resolve("module-src"); 125 Path m1 = moduleSrc.resolve("m1x"); 126 127 tb.writeJavaFiles(m1, 128 "import m1x.*; @A @Deprecated @E @E module m1x { }", 129 "package m1x; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface A {}", 130 "package m1x; import java.lang.annotation.*; @Target(ElementType.MODULE) @Repeatable(C.class) public @interface E {}", 131 "package m1x; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface C { public E[] value(); }"); 132 133 Path modulePath = base.resolve("module-path"); 134 135 Files.createDirectories(modulePath); 136 137 new JavacTask(tb) 138 .options("--module-source-path", moduleSrc.toString(), 139 "-processor", AP.class.getName()) 140 .outdir(modulePath) 141 .files(findJavaFiles(m1)) 142 .run() 143 .writeAll(); 144 145 Path src = base.resolve("src"); 146 147 tb.writeJavaFiles(src, 148 "class T {}"); 149 150 Path out = base.resolve("out"); 151 152 Files.createDirectories(out); 153 154 new JavacTask(tb) 155 .options("--module-path", modulePath.toString(), 156 "--add-modules", "m1x", 157 "-processor", AP.class.getName()) 158 .outdir(out) 159 .files(findJavaFiles(src)) 160 .run() 161 .writeAll(); 162 163 new JavacTask(tb) 164 .options("--module-path", modulePath.toString() + File.pathSeparator + out.toString(), 165 "--add-modules", "m1x", 166 "-processor", AP.class.getName(), 167 "-proc:only") 168 .classes("m1x/m1x.A") 169 .files(findJavaFiles(src)) 170 .run() 171 .writeAll(); 172 } 173 174 @SupportedAnnotationTypes("*") 175 public static final class AP extends AbstractProcessor { 176 177 @Override 178 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 179 ModuleElement m1 = processingEnv.getElementUtils().getModuleElement("m1x"); 180 Set<String> actualAnnotations = new HashSet<>(); 181 Set<String> expectedAnnotations = 182 new HashSet<>(Arrays.asList("@m1x.A", "@java.lang.Deprecated", "@m1x.C({@m1x.E, @m1x.E})")); 183 184 for (AnnotationMirror am : m1.getAnnotationMirrors()) { 185 actualAnnotations.add(am.toString()); 186 } 187 188 if (!expectedAnnotations.equals(actualAnnotations)) { 189 throw new AssertionError("Incorrect annotations: " + actualAnnotations); 190 } 191 192 return false; 193 } 194 195 } 196 197 @Test 198 public void testModuleDeprecation(Path base) throws Exception { 199 Path moduleSrc = base.resolve("module-src"); 200 Path m1 = moduleSrc.resolve("m1x"); 201 202 tb.writeJavaFiles(m1, 203 "@Deprecated module m1x { }"); 204 205 Path m2 = moduleSrc.resolve("m2x"); 206 207 tb.writeJavaFiles(m2, 208 "@Deprecated module m2x { }"); 209 210 Path m3 = moduleSrc.resolve("m3x"); 211 212 Path modulePath = base.resolve("module-path"); 213 214 Files.createDirectories(modulePath); 215 216 List<String> actual; 217 List<String> expected; 218 219 for (String suppress : new String[] {"", "@Deprecated ", "@SuppressWarnings(\"deprecation\") "}) { 220 tb.writeJavaFiles(m3, 221 suppress + "module m3x {\n" + 222 " requires m1x;\n" + 223 " exports api to m1x, m2x;\n" + 224 "}", 225 "package api; public class Api { }"); 226 System.err.println("compile m3x"); 227 actual = new JavacTask(tb) 228 .options("--module-source-path", moduleSrc.toString(), 229 "-XDrawDiagnostics") 230 .outdir(modulePath) 231 .files(findJavaFiles(moduleSrc)) 232 .run() 233 .writeAll() 234 .getOutputLines(OutputKind.DIRECT); 235 236 if (suppress.isEmpty()) { 237 expected = Arrays.asList( 238 "- compiler.note.deprecated.filename: module-info.java", 239 "- compiler.note.deprecated.recompile"); 240 } else { 241 expected = Arrays.asList(""); 242 } 243 244 if (!expected.equals(actual)) { 245 throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress); 246 } 247 248 System.err.println("compile m3x with -Xlint:-deprecation"); 249 actual = new JavacTask(tb) 250 .options("--module-source-path", moduleSrc.toString(), 251 "-XDrawDiagnostics", 252 "-Xlint:deprecation") 253 .outdir(modulePath) 254 .files(findJavaFiles(moduleSrc)) 255 .run() 256 .writeAll() 257 .getOutputLines(OutputKind.DIRECT); 258 259 if (suppress.isEmpty()) { 260 expected = Arrays.asList( 261 "module-info.java:2:14: compiler.warn.has.been.deprecated.module: m1x", 262 "1 warning"); 263 } else { 264 expected = Arrays.asList(""); 265 } 266 267 if (!expected.equals(actual)) { 268 throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress); 269 } 270 271 //load the deprecated module-infos from classfile: 272 System.err.println("compile m3x with -Xlint:-deprecation, loading deprecated modules from classes"); 273 actual = new JavacTask(tb) 274 .options("--module-path", modulePath.toString(), 275 "-XDrawDiagnostics", 276 "-Xlint:deprecation") 277 .outdir(modulePath.resolve("m3x")) 278 .files(findJavaFiles(moduleSrc.resolve("m3x"))) 279 .run() 280 .writeAll() 281 .getOutputLines(OutputKind.DIRECT); 282 283 if (!expected.equals(actual)) { 284 throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress); 285 } 286 } 287 } 288 289 @Test 290 public void testAttributeValues(Path base) throws Exception { 291 class TestCase { 292 public final String extraDecl; 293 public final String decl; 294 public final String use; 295 public final String expectedAnnotations; 296 297 public TestCase(String extraDecl, String decl, String use, String expectedAnnotations) { 298 this.extraDecl = extraDecl; |