OverwriteBetweenCompilations.java revision 3719:32c685715095
1/*
2 * Copyright (c) 2014, 2016, 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 8038455
27 * @summary Verify that annotation processor can overwrite source and class files it generated
28 *          during previous compilations, and that the Symbols are updated appropriately.
29 * @library /tools/lib /tools/javac/lib/
30 * @modules jdk.compiler/com.sun.tools.javac.api
31 *          jdk.compiler/com.sun.tools.javac.main
32 *          jdk.compiler/com.sun.tools.javac.processing
33 *          jdk.compiler/com.sun.tools.javac.util
34 *          jdk.jdeps/com.sun.tools.javap
35 * @clean *
36 * @build toolbox.ToolBox toolbox.JavacTask
37 * @build OverwriteBetweenCompilations JavacTestingAbstractProcessor
38 * @compile/ref=OverwriteBetweenCompilations_1.out -XDaccessInternalAPI -processor OverwriteBetweenCompilations -Apass=1 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
39 * @compile/ref=OverwriteBetweenCompilations_2.out -XDaccessInternalAPI -processor OverwriteBetweenCompilations -Apass=2 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
40 * @compile/ref=OverwriteBetweenCompilations_3.out -XDaccessInternalAPI -processor OverwriteBetweenCompilations -Apass=3 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
41 */
42
43import java.io.*;
44import java.util.*;
45
46import javax.annotation.processing.*;
47import javax.lang.model.element.*;
48import javax.tools.*;
49
50import com.sun.tools.javac.processing.JavacProcessingEnvironment;
51import com.sun.tools.javac.processing.PrintingProcessor.PrintingElementVisitor;
52import com.sun.tools.javac.util.Log;
53import com.sun.tools.javac.util.Log.WriterKind;
54
55import toolbox.JavacTask;
56import toolbox.ToolBox;
57
58@SupportedOptions("pass")
59public class OverwriteBetweenCompilations extends JavacTestingAbstractProcessor {
60    int round = 1;
61    @Override
62    public boolean process(Set<? extends TypeElement> annotations,
63                           RoundEnvironment roundEnv) {
64        Log log = Log.instance(((JavacProcessingEnvironment) processingEnv).getContext());
65        PrintWriter pw = log.getWriter(WriterKind.NOTICE);
66
67        pw.println("round: " + round);
68
69        TypeElement generatedSource =
70                processingEnv.getElementUtils().getTypeElement("GeneratedSource");
71
72        if (generatedSource != null) {
73            new PrintingElementVisitor(pw, processingEnv.getElementUtils()).visit(generatedSource);
74            pw.flush();
75        }
76
77        TypeElement generatedClass =
78                processingEnv.getElementUtils().getTypeElement("GeneratedClass");
79
80        if (generatedClass != null) {
81            new PrintingElementVisitor(pw, processingEnv.getElementUtils()).visit(generatedClass);
82            pw.flush();
83        }
84
85        int pass = Integer.parseInt(processingEnv.getOptions().get("pass"));
86
87        if (round++ == 1) {
88            try (Writer out = filer.createSourceFile("GeneratedSource").openWriter()) {
89                String code = pass != 2 ? GENERATED_INIT : GENERATED_UPDATE;
90                code = code.replace("NAME", "GeneratedSource");
91                out.write(code);
92            } catch (IOException e) {
93                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.toString());
94            }
95            try (OutputStream out = filer.createClassFile("GeneratedClass").openOutputStream()) {
96                String code = pass != 2 ? GENERATED_INIT : GENERATED_UPDATE;
97                code = code.replace("NAME", "GeneratedClass");
98
99                ToolBox tb = new ToolBox();
100                ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager();
101                new JavacTask(tb)
102                        .fileManager(mfm)
103                        .options("-parameters")
104                        .sources(code)
105                        .run();
106
107                out.write(mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, "GeneratedClass"));
108            } catch (IOException e) {
109                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.toString());
110            }
111        }
112
113        return false;
114    }
115
116    //the initial generated class - "NAME" will be replaced with either "GeneratedSource" or
117    //"GeneratedClass" while generating the class:
118    private static final String GENERATED_INIT =
119            "@Deprecated\n" +
120            "public class NAME<T extends CharSequence> extends java.util.ArrayList<String>\n" +
121            "                                          implements Runnable {\n" +
122            "    public void test(int a) { }\n" +
123            "    public void run() { }\n" +
124            "}";
125
126    //generated class update- "NAME" will be replaced with either "GeneratedSource" or
127    //"GeneratedClass" while generating the class:
128    private static final String GENERATED_UPDATE =
129            "@javax.annotation.processing.SupportedAnnotationTypes(\"*\")\n" +
130            "public abstract class NAME<E extends Number> extends java.util.LinkedList<Number>" +
131            "                                             implements Runnable, CharSequence {\n" +
132            "    public void test(long a) { }\n" +
133            "}";
134}
135