1 /*
2  * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 8187950
27  * @summary Handing of BadClassFile exceptions and CompletionFailures
28  * @library /tools/javac/lib /tools/lib
29  * @modules jdk.compiler/com.sun.tools.javac.api
30  *          jdk.compiler/com.sun.tools.javac.main
31  * @build JavacTestingAbstractProcessor MissingClassFile
32  * @run main MissingClassFile
33  */
34 
35 import java.io.OutputStream;
36 import java.nio.file.Files;
37 import java.nio.file.Path;
38 import java.nio.file.Paths;
39 import java.util.*;
40 import java.util.function.BiConsumer;
41 import java.util.function.Consumer;
42 
43 import javax.annotation.processing.*;
44 import javax.lang.model.SourceVersion;
45 import javax.lang.model.element.*;
46 import javax.lang.model.type.DeclaredType;
47 import javax.lang.model.type.ErrorType;
48 import javax.lang.model.type.TypeKind;
49 import javax.lang.model.type.TypeMirror;
50 import javax.tools.JavaCompiler;
51 import javax.tools.StandardJavaFileManager;
52 import javax.tools.ToolProvider;
53 
54 import toolbox.*;
55 import toolbox.Task.*;
56 
57 import com.sun.source.tree.Scope;
58 import com.sun.source.util.TaskEvent;
59 import com.sun.source.util.TaskListener;
60 import com.sun.source.util.TreePath;
61 import com.sun.source.util.Trees;
62 
63 @SupportedAnnotationTypes("*")
64 public class MissingClassFile {
65     ToolBox tb = new ToolBox();
66 
testPackageContent()67     void testPackageContent() throws Exception {
68         Path base = Paths.get(".");
69         Path libClasses = compileLib(base,
70                                      "package pkg;" +
71                                      "public class A {" +
72                                      "}",
73                                      "package pkg;" +
74                                      "public class B {" +
75                                      "}");
76 
77         Files.delete(libClasses.resolve("pkg/B.class"));
78         try (OutputStream out = Files.newOutputStream(libClasses.resolve("pkg/B.class"))) {
79             out.write(0);
80         }
81 
82         doRunTest(base,
83                   t -> {
84                       PackageElement pe = t.getElements().getPackageElement("pkg");
85                       for (Element el : pe.getEnclosedElements()) {
86                           verifyElement(t, el);
87                       }
88                   },
89                   "",
90                   "pkg.B b;");
91     }
92 
testPackageDirectAPI()93     void testPackageDirectAPI() throws Exception {
94         Path base = Paths.get(".");
95         Path libClasses = compileLib(base,
96                                      "package pkg;" +
97                                      "public class A {" +
98                                      "}",
99                                      "package pkg;" +
100                                      "public class B {" +
101                                      "}");
102 
103         Files.delete(libClasses.resolve("pkg/B.class"));
104         try (OutputStream out = Files.newOutputStream(libClasses.resolve("pkg/B.class"))) {
105             out.write(0);
106         }
107 
108         Path testSrc = base.resolve("test-src");
109         tb.createDirectories(testSrc);
110         tb.writeJavaFiles(testSrc,
111                           "package test;\n" +
112                           "public class Test {\n" +
113                           "    void t() {\n" +
114                           "        pkg.B b;\n" +
115                           "    }\n" +
116                           "}\n");
117         Path testClasses = base.resolve("test-classes");
118         tb.createDirectories(testClasses);
119 
120         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
121         List<String> errors = new ArrayList<>();
122 
123         try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
124             com.sun.source.util.JavacTask task = (com.sun.source.util.JavacTask)
125                     compiler.getTask(null,
126                                      null,
127                                      d -> errors.add(d.getCode()),
128                                      Arrays.asList("-XDrawDiagnostics",
129                                                    "-classpath",
130                                                    libClasses.toString()),
131                                      null,
132                                      fm.getJavaFileObjects(tb.findJavaFiles(testSrc)));
133             task.parse();
134             PackageElement pe = task.getElements().getPackageElement("pkg");
135             for (Element el : pe.getEnclosedElements()) {
136                 verifyElement(task, el);
137             }
138             task.analyze();
139         }
140 
141         List<String> expected = Arrays.asList("compiler.err.cant.access");
142 
143         if (!expected.equals(errors)) {
144             throw new IllegalStateException("Expected error not found!");
145         }
146     }
147 
testSuperClass()148     void testSuperClass() throws Exception {
149         doTestCombo("class Test {" +
150                     "}",
151                     "package pkg;" +
152                     "public class A extends # {" +
153                     "}",
154                     "pkg.A x;",
155                     "# a = null; a.toString();",
156                     (fqn, t) -> {
157                         TypeElement a = t.getElements()
158                                          .getTypeElement(t.getElements()
159                                                           .getModuleElement(""),
160                                                          "pkg.A");
161                         TypeMirror superclass = a.getSuperclass();
162                         verifyTypeMirror(t, superclass);
163                         assertEquals(TypeKind.ERROR, superclass.getKind());
164                         Element superclassEl = ((DeclaredType) superclass).asElement();
165                         assertEquals(ElementKind.CLASS, superclassEl.getKind());
166                         assertEquals(TypeKind.ERROR, superclassEl.asType().getKind());
167                         TypeMirror originalType = Trees.instance(t).getOriginalType((ErrorType) superclass);
168                         assertEquals(TypeKind.DECLARED, originalType.getKind());
169                         assertEquals(superclassEl, ((DeclaredType) originalType).asElement());
170                   });
171         doTestCombo("interface Test {" +
172                     "}",
173                     "package pkg;" +
174                     "public class A implements # {" +
175                     "}",
176                     "pkg.A x;",
177                     "# a = null; a.toString();",
178                     (fqn, t) -> {
179                         TypeElement a = t.getElements().getTypeElement("pkg.A");
180                         TypeMirror superintf = a.getInterfaces().get(0);
181                         verifyTypeMirror(t, superintf);
182                         assertEquals(TypeKind.ERROR, superintf.getKind());
183                         Element superintfEl = ((DeclaredType) superintf).asElement();
184                         //superintfEl.getKind() may be either CLASS or INTERFACE, depending on which class is missing
185                         assertEquals(TypeKind.ERROR, superintfEl.asType().getKind());
186                         TypeMirror originalType = Trees.instance(t).getOriginalType((ErrorType) superintf);
187                         assertEquals(TypeKind.DECLARED, originalType.getKind());
188                         assertEquals(superintfEl, ((DeclaredType) originalType).asElement());
189                   });
190         doTestCombo("class Test {" +
191                     "}",
192                     "package pkg;" +
193                     "public class A extends # {" +
194                     "}",
195                     "pkg.A x;",
196                     "# a = null; a.toString();",
197                     (fqn, t) -> {
198                         TypeElement a = t.getElements()
199                                          .getTypeElement(t.getElements()
200                                                           .getModuleElement(""),
201                                                          "pkg.A");
202                         DeclaredType superclass = (DeclaredType) a.getSuperclass();
203                         superclass.getTypeArguments();
204                   });
205         doTestCombo("class Test {" +
206                     "}",
207                     "package pkg;" +
208                     "public class A extends # {" +
209                     "}",
210                     "pkg.A x;",
211                     "# a = null; a.toString();",
212                     (fqn, t) -> {
213                         TypeElement a = t.getElements()
214                                          .getTypeElement(t.getElements()
215                                                           .getModuleElement(""),
216                                                          "pkg.A");
217                         DeclaredType superclass = (DeclaredType) a.getSuperclass();
218                         superclass.getEnclosingType();
219                   });
220     }
221 
testAnnotation()222     void testAnnotation() throws Exception {
223         doTestCombo("@interface Test {" +
224                     "}",
225                     "package pkg;" +
226                     "@#\n" +
227                     "public class A {" +
228                     "}",
229                     "",
230                     "# a = null; a.toString();",
231                     (fqn, t) -> {
232                       TypeElement a = t.getElements().getTypeElement("pkg.A");
233                       for (AnnotationMirror am : a.getAnnotationMirrors()) {
234                           verifyTypeMirror(t, am.getAnnotationType());
235                       }
236                   });
237         doTestCombo("@interface Test {" +
238                     "    public Class<?> value();" +
239                     "}",
240                     "package pkg;" +
241                     "@#(Object.class)\n" +
242                     "public class A {" +
243                     "}",
244                     "",
245                     "# a = null; a.toString();",
246                     (fqn, t) -> {
247                       TypeElement a = t.getElements().getTypeElement("pkg.A");
248                       for (AnnotationMirror am : a.getAnnotationMirrors()) {
249                           verifyTypeMirror(t, am.getAnnotationType());
250                           if (am.getAnnotationType().toString().equals(fqn)) {
251                               verifyTypeMirror(t, (TypeMirror) am.getElementValues().values()
252                                                                  .iterator().next().getValue());
253                           }
254                       }
255                   });
256         doTestCombo("class Test { }",
257                     "package pkg;" +
258                     "@Ann(#.class)\n" +
259                     "public class A {" +
260                     "}" +
261                     "@interface Ann {" +
262                     "    public Class<?> value();" +
263                     "}",
264                     "",
265                     "# a = null; a.toString();",
266                     (fqn, t) -> {
267                       TypeElement a = t.getElements().getTypeElement("pkg.A");
268                       for (AnnotationMirror am : a.getAnnotationMirrors()) {
269                           verifyTypeMirror(t, am.getAnnotationType());
270                           if (am.getAnnotationType().toString().equals(fqn)) {
271                               verifyTypeMirror(t, (TypeMirror) am.getElementValues().values()
272                                                                  .iterator().next().getValue());
273                           }
274                       }
275                   });
276     }
277 
testMethod()278     void testMethod() throws Exception {
279         doTestCombo("class Test {" +
280                     "}",
281                     "package pkg;" +
282                     "public class A {" +
283                     "    public void m1(# t) { }" +
284                     "    public # m2() { return null; }" +
285                     "}",
286                     "",
287                     "pkg.A a = null; a.m2().toString();",
288                     (fqn, t) -> {
289                       TypeElement a = t.getElements().getTypeElement("pkg.A");
290                       List<? extends Element> members = a.getEnclosedElements();
291                       if (members.size() != 3)
292                           throw new AssertionError("Unexpected number of members, " +
293                                                    "received members: " + members);
294                       for (Element e : members) {
295                           verifyElement(t, e);
296                       }
297                   });
298     }
299 
testAnnotationProcessing()300     void testAnnotationProcessing() throws Exception {
301         boolean[] superClass = new boolean[1];
302         boolean[] inInit = new boolean[1];
303         class TestAP extends AbstractProcessor {
304 
305             @Override
306             public void init(ProcessingEnvironment processingEnv) {
307                 super.init(processingEnv);
308                 if (inInit[0])
309                     doCheck();
310             }
311 
312             @Override
313             public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
314                 if (!inInit[0])
315                     doCheck();
316                 return false;
317             }
318 
319             private void doCheck() {
320                 com.sun.source.util.JavacTask t = com.sun.source.util.JavacTask.instance(processingEnv);
321                 TypeElement a = t.getElements().getTypeElement("pkg.A");
322                 if (superClass[0]) {
323                     verifyTypeMirror(t, a.getSuperclass());
324                 } else {
325                     verifyTypeMirror(t, a.getInterfaces().get(0));
326                 }
327             }
328 
329             @Override
330             public Set<String> getSupportedAnnotationTypes() {
331                 return Set.of("*");
332             }
333 
334             @Override
335             public SourceVersion getSupportedSourceVersion() {
336                 return SourceVersion.latest();
337             }
338         }
339 
340         for (boolean supClass : new boolean[] {false, true}) {
341             for (boolean init : new boolean[] {false, true}) {
342                 String decl = supClass ? "class Test { }" : "interface Test { }";
343                 String snip = supClass ? "extends #" : "implements #";
344 
345                 superClass[0] = supClass;
346                 inInit[0] = init;
347 
348                 doTestComboCallBack(decl,
349                                     "package pkg;" +
350                                     "public class A " + snip + " {" +
351                                     "}",
352                                     "",
353                                     "# a = null; a.toString();",
354                                     (fqn, t) -> t.setProcessors(List.of(new TestAP())));
355             }
356         }
357     }
358 
testGetTypeElement()359     void testGetTypeElement() throws Exception {
360         doTestCombo("class Test { }",
361                     "package pkg;" +
362                     "public class A extends # {" +
363                     "}",
364                     "",
365                     "pkg.A a = null; a.toString();", //should be generalized/in variant?
366                     (fqn, t) -> {
367                           TypeElement a = t.getElements().getTypeElement(fqn);
368                           if (a != null) {
369                               throw new IllegalStateException();
370                           }
371                       });
372     }
373 
testScope()374     void testScope() throws Exception {
375         class Variant {
376             private final String code;
377             private final String fqn;
378             public Variant(String code, String fqn) {
379                 this.code = code;
380                 this.fqn  = fqn;
381             }
382         }
383         Path base = Paths.get(".");
384         Path libClasses = compileLib(base,
385                                      "package pkg;" +
386                                      "public class A {" +
387                                      "    public static class I {}" +
388                                      "}",
389                                      "package pkg;" +
390                                      "public class B {" +
391                                      "}");
392         try (OutputStream out = Files.newOutputStream(libClasses.resolve("pkg/B.class"))) {
393             out.write(0);
394         }
395         try (OutputStream out = Files.newOutputStream(libClasses.resolve("pkg/A$I.class"))) {
396             out.write(0);
397         }
398 
399         Path testSrc = base.resolve("test-src");
400         tb.createDirectories(testSrc);
401         Path testClasses = base.resolve("test-classes");
402         tb.createDirectories(testClasses);
403 
404         Variant[] variants = new Variant[] {
405             //JDK-8198378:
406 //            new Variant("package test;\n" +
407 //                        "import pkg.B;\n" +
408 //                        "public class Test {}\n",
409 //                        "test.Test"),
410             new Variant("package test;\n" +
411                         "import pkg.*;\n" +
412                         "public class Test {}\n",
413                         "test.Test"),
414             new Variant("package test;\n" +
415                         "import pkg.A.*;\n" +
416                         "public class Test extends I {}\n",
417                         "test.Test"),
418             new Variant("package test;\n" +
419                         "import static pkg.A.*;\n" +
420                         "public class Test extends I {}\n",
421                         "test.Test"),
422             new Variant("package pkg;\n" +
423                         "public class Test {}\n",
424                         "pkg.Test")
425         };
426         for (Variant variant : variants) {
427             System.err.println("variant: " + variant.code);
428             tb.writeJavaFiles(testSrc, variant.code);
429             tb.cleanDirectory(testClasses);
430 
431             JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
432             List<String> errors = new ArrayList<>();
433 
434             try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
435                 com.sun.source.util.JavacTask task = (com.sun.source.util.JavacTask)
436                         compiler.getTask(null,
437                                          null,
438                                          d -> errors.add(d.getCode()),
439                                          Arrays.asList("-XDrawDiagnostics",
440                                                        "-classpath",
441                                                        libClasses.toString()),
442                                          null,
443                                          fm.getJavaFileObjects(tb.findJavaFiles(testSrc)));
444                 task.analyze();
445                 TypeElement a = task.getElements()
446                                     .getTypeElement(task.getElements()
447                                                         .getModuleElement(""),
448                                                     variant.fqn);
449                 Trees trees = Trees.instance(task);
450                 TreePath tpA = trees.getPath(a);
451                 Scope scope = trees.getScope(tpA);
452                 while (scope != null) {
453                     for (Element el : scope.getLocalElements()) {
454                         verifyElement(task, el);
455                     }
456                     scope = scope.getEnclosingScope();
457                 }
458             }
459         }
460     }
461 
testGetEnclosingOnMissingType()462     void testGetEnclosingOnMissingType() throws Exception {
463         Path base = Paths.get(".", "testGetEnclosingOnMissingType");
464         Path libClasses = compileLib(base,
465                                      "package pkg;\n" +
466                                      "public class A<E> {\n" +
467                                      "    public static class N<E> {}\n" +
468                                      "}\n",
469                                      "package pkg;\n" +
470                                      "public class T<E> {\n" +
471                                      "    T<A<T>> n;\n" +
472                                      "}\n");
473         try (OutputStream out = Files.newOutputStream(libClasses.resolve("pkg/A.class"))) {
474             out.write(0);
475         }
476 
477         Path testSrc = base.resolve("test-src");
478         tb.createDirectories(testSrc);
479         Path testClasses = base.resolve("test-classes");
480         tb.createDirectories(testClasses);
481 
482         tb.writeJavaFiles(testSrc, "class Test { }");
483         tb.cleanDirectory(testClasses);
484 
485         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
486 
487         List<Consumer<DeclaredType>> validators = Arrays.asList(
488                 dt -> { if (dt.getEnclosingType().getKind() != TypeKind.NONE)
489                             throw new AssertionError("Unexpected enclosing type: " +
490                                                      dt.getEnclosingType());
491                 },
492                 dt -> { if (!"pkg.T<pkg.A<pkg.T>>".equals(dt.toString()))
493                             throw new AssertionError("Unexpected toString: " +
494                                                      dt.toString());
495                 }
496         );
497 
498         try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
499             for (Consumer<DeclaredType> validator : validators) {
500                 com.sun.source.util.JavacTask task = (com.sun.source.util.JavacTask)
501                         compiler.getTask(null,
502                                          null,
503                                          null,
504                                          Arrays.asList("-XDrawDiagnostics",
505                                                        "-classpath",
506                                                        libClasses.toString()),
507                                          null,
508                                          fm.getJavaFileObjects(tb.findJavaFiles(testSrc)));
509                 task.analyze();
510                 TypeElement a = task.getElements()
511                                     .getTypeElement(task.getElements()
512                                                         .getModuleElement(""),
513                                                     "pkg.T");
514                 DeclaredType type = (DeclaredType) a.getEnclosedElements().get(0).asType();
515                 validator.accept(type);
516             }
517         }
518     }
519 
compileLib(Path base, String... sources)520     private Path compileLib(Path base, String... sources) throws Exception {
521         Path libSrc = base.resolve("lib-src");
522         tb.createDirectories(libSrc);
523         tb.writeJavaFiles(libSrc, sources);
524         Path libClasses = base.resolve("lib-classes");
525         tb.createDirectories(libClasses);
526         new JavacTask(tb).outdir(libClasses.toString())
527                          .sourcepath(libSrc.toString())
528                          .files(tb.findJavaFiles(libSrc))
529                          .run()
530                          .writeAll();
531 
532         return libClasses;
533     }
534 
doTestCombo(String decl, String use, String snippetInClass, String snippetInMethod, BiConsumer<String, com.sun.source.util.JavacTask> test)535     private void doTestCombo(String decl,
536                              String use,
537                              String snippetInClass,
538                              String snippetInMethod,
539                              BiConsumer<String, com.sun.source.util.JavacTask> test) throws Exception {
540         doTestComboCallBack(decl,
541                             use,
542                             snippetInClass,
543                             snippetInMethod,
544                             (fqn, t) -> {
545             t.addTaskListener(new TaskListener() {
546                 @Override
547                 public void finished(TaskEvent e) {
548                     if (e.getKind() == TaskEvent.Kind.ENTER) {
549                         test.accept(fqn, t);
550                     }
551                 }
552             });
553         });
554     }
555 
doTestComboCallBack(String decl, String use, String snippetInClass, String snippetInMethod, BiConsumer<String, com.sun.source.util.JavacTask> callback)556     private void doTestComboCallBack(String decl,
557                                      String use,
558                                      String snippetInClass,
559                                      String snippetInMethod,
560                                      BiConsumer<String, com.sun.source.util.JavacTask> callback) throws Exception {
561         List<TestVariant> variants = List.of(
562                 new TestVariant("package pkg; public #", "pkg.Test", "pkg/Test.class"),
563                 new TestVariant("package pkg; public class O { public static # }", "pkg.O.Test", "pkg/O$Test.class"),
564                 new TestVariant("package pkg; public class O { public static # }", "pkg.O.Test", "pkg/O.class"),
565                 new TestVariant("package pkg; public class O { public static class N { public static # } }", "pkg.O.N.Test", "pkg/O$N$Test.class"),
566                 new TestVariant("package pkg; public class O { public static class N { public static # } }", "pkg.O.N.Test", "pkg/O$N.class"),
567                 new TestVariant("package pkg; public class O { public static class N { public static # } }", "pkg.O.N.Test", "pkg/O.class")
568         );
569 
570         Path base = Paths.get(".");
571 
572         for (TestVariant v : variants) {
573             System.err.println("-----------------------------------------------------------------------");
574             System.err.println("variant: " + v.declarationStub + ", " + v.fqn + ", " + v.path);
575             Path libClasses = compileLib(base,
576                                          use.replace("#", v.fqn),
577                                          v.declarationStub.replace("#", decl));
578 
579             Files.delete(libClasses.resolve(v.path));
580 
581             doRunTestFullCallback(base,
582                                   t -> callback.accept(v.fqn, t),
583                                   snippetInClass.replace("#", v.fqn),
584                                   snippetInMethod.replace("#", v.fqn));
585         }
586     }
587 
doRunTest(Path base, Consumer<com.sun.source.util.JavacTask> test, String snippetInClass, String snippetInMethod)588     private void doRunTest(Path base,
589                            Consumer<com.sun.source.util.JavacTask> test,
590                            String snippetInClass,
591                            String snippetInMethod) throws Exception {
592         doRunTestFullCallback(base, t -> {
593             t.addTaskListener(new TaskListener() {
594                 @Override
595                 public void finished(TaskEvent e) {
596                     if (e.getKind() == TaskEvent.Kind.ENTER) {
597                         test.accept(t);
598                     }
599                 }
600             });
601         }, snippetInClass, snippetInMethod);
602     }
603 
doRunTestFullCallback(Path base, Consumer<com.sun.source.util.JavacTask> callback, String snippetInClass, String snippetInMethod)604     private void doRunTestFullCallback(Path base,
605                                        Consumer<com.sun.source.util.JavacTask> callback,
606                                        String snippetInClass,
607                                        String snippetInMethod) throws Exception {
608         Path libClasses = base.resolve("lib-classes");
609         Path testSrc = base.resolve("test-src");
610         tb.createDirectories(testSrc);
611         tb.writeJavaFiles(testSrc,
612                           "package test;\n" +
613                           "public class Test {\n" +
614                           snippetInClass + "\n" +
615                           "    void t() {\n" +
616                           snippetInMethod + "\n" +
617                           "    }\n" +
618                           "}\n");
619         System.err.println("content: " + "package test;\n" +
620                           "public class Test {\n" +
621                           snippetInClass + "\n" +
622                           "    void t() {\n" +
623                           snippetInMethod + "\n" +
624                           "    }\n" +
625                           "}\n");
626         Path testClasses = base.resolve("test-classes");
627         tb.createDirectories(testClasses);
628 
629         var expectedErrors = new JavacTask(tb).outdir(testClasses.toString())
630                                               .options("-XDrawDiagnostics",
631                                                        "-classpath",
632                                                        libClasses.toString())
633                                               .sourcepath(testSrc.toString())
634                                               .files(tb.findJavaFiles(testSrc))
635                                               .run(Expect.FAIL)
636                                               .writeAll()
637                                               .getOutputLines(OutputKind.DIRECT,
638                                                               OutputKind.STDERR,
639                                                               OutputKind.STDOUT);
640 
641         var errors = new JavacTask(tb).outdir(testClasses.toString())
642                                       .options("-XDrawDiagnostics",
643                                                "-classpath",
644                                                libClasses.toString())
645                                       .sourcepath(testSrc.toString())
646                                       .files(tb.findJavaFiles(testSrc))
647                                       .callback(callback)
648                                       .run(Expect.FAIL)
649                                       .writeAll()
650                                       .getOutputLines(OutputKind.DIRECT,
651                                                       OutputKind.STDERR,
652                                                       OutputKind.STDOUT);
653 
654         if (!expectedErrors.equals(errors)) {
655             throw new IllegalStateException("Expected error not found!");
656         }
657     }
658 
verifyTypeMirror(com.sun.source.util.JavacTask t, TypeMirror type)659     private void verifyTypeMirror(com.sun.source.util.JavacTask t, TypeMirror type) {
660         Element el = t.getTypes().asElement(type);
661 
662         if (el != null) {
663             verifyElement(t, el);
664         }
665     }
666 
verifyElement(com.sun.source.util.JavacTask t, Element el)667     private void verifyElement(com.sun.source.util.JavacTask t, Element el) {
668         el.getKind(); //forces completion
669     }
670 
assertEquals(Object expected, Object actual)671     private static void assertEquals(Object expected, Object actual) {
672         if (!Objects.equals(expected, actual)) {
673             throw new AssertionError("Unexpected value, expected: " + expected + ", actual: " + actual);
674         }
675     }
676 
main(String... args)677     public static void main(String... args) throws Exception {
678         MissingClassFile t = new MissingClassFile();
679         t.testPackageContent();
680         t.testPackageDirectAPI();
681         t.testSuperClass();
682         t.testAnnotation();
683         t.testAnnotationProcessing();
684         t.testGetTypeElement();
685         t.testScope();
686         t.testGetEnclosingOnMissingType();
687     }
688 
689     static class TestVariant {
690         public final String declarationStub;
691         public final String fqn;
692         public final String path;
693 
TestVariant(String declarationStub, String fqn, String path)694         public TestVariant(String declarationStub, String fqn, String path) {
695             this.declarationStub = declarationStub;
696             this.fqn = fqn;
697             this.path = path;
698         }
699 
700     }
701 }
702