1 /*
2 * Copyright (c) 2025, 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 * @summary check that annotation processor that depends on jdk.incubator.code can run normally
27 * @library /tools/lib
28 * @modules jdk.compiler/com.sun.tools.javac.api
29 * jdk.compiler/com.sun.tools.javac.main
30 * jdk.jlink
31 * @build toolbox.ToolBox toolbox.JavacTask toolbox.JarTask
32 * @run main/othervm TestCodeModelProcessors
33 */
34
35 import java.io.IOException;
36 import java.util.List;
37 import java.nio.file.Files;
38 import java.nio.file.Path;
39
40 import toolbox.JarTask;
41 import toolbox.JavacTask;
42 import toolbox.Task;
43 import toolbox.Task.OutputKind;
44 import toolbox.TestRunner;
45 import toolbox.ToolBox;
46
47 public class TestCodeModelProcessors extends TestRunner {
48 public static void main(String... args) throws Exception {
49 new TestCodeModelProcessors().run();
50 }
51
52 TestCodeModelProcessors() {
53 super(System.out);
54 }
55
56 ToolBox tb = new ToolBox();
57
58 Path pluginJar;
59 Path classes;
60 Path mclasses;
61
62 void run() throws Exception {
63 Path src = Path.of("src");
64 tb.writeJavaFiles(src,
65 """
66 package p;
67
68 import javax.annotation.processing.*;
69 import jdk.incubator.code.*;
70 import java.util.*;
71
72 public class TestProcessor extends AbstractProcessor {
73
74 @Override
75 public void init(ProcessingEnvironment processingEnv) {
76 try {
77 var processorClass = TestProcessor.class;
78 var testMethod = processorClass.getDeclaredMethod("test");
79 var op = Op.ofMethod(testMethod);
80 op.get(); // make sure that works
81 test();
82 } catch (Throwable ex) {
83 throw new AssertionError(ex);
84 }
85 }
86
87 @Override
88 public boolean process(Set<? extends javax.lang.model.element.TypeElement> annotations, RoundEnvironment roundEnv) {
89 return true;
90 }
91
92 @CodeReflection
93 void test() {
94 System.out.println("SUCCESS");
95 }
96 }
97 """);
98
99 Path msrc = Path.of("msrc");
100 tb.writeJavaFiles(msrc,
101 """
102 module m {
103 requires jdk.compiler;
104 requires jdk.incubator.code;
105 provides javax.annotation.processing.Processor with p.TestProcessor;
106 opens p to jdk.incubator.code;
107 }
108 """);
109
110 classes = Files.createDirectories(Path.of("classes"));
111 new JavacTask(tb)
112 .options("--add-modules", "jdk.incubator.code")
113 .outdir(classes)
114 .files(tb.findJavaFiles(src))
115 .run()
116 .writeAll();
117
118 tb.writeFile(classes.resolve("META-INF").resolve("services").resolve("javax.annotation.processing.Processor"),
119 "p.TestProcessor\n");
120
121 pluginJar = Path.of("plugin.jar");
122 new JarTask(tb, pluginJar)
123 .baseDir(classes)
124 .files(".")
125 .run();
126
127 mclasses = Files.createDirectories(Path.of("mclasses"));
128 new JavacTask(tb)
129 .options("--add-modules", "jdk.incubator.code")
130 .outdir(mclasses)
131 .sourcepath(msrc, src)
132 .files(tb.findJavaFiles(msrc))
133 .run()
134 .writeAll();
135
136 Path hw = Path.of("hw");
137 tb.writeJavaFiles(hw,
138 """
139 import jdk.incubator.code.*;
140
141 public class HelloWorld {
142 @CodeReflection
143 void testAnnos() { }
144 }
145 """);
146
147 runTests(m -> new Object[] { Path.of(m.getName()), ProcessorOptions.EXPLICIT });
148 runTests(m -> new Object[] { Path.of(m.getName()), ProcessorOptions.IMPLICIT });
149 }
150
151 record ProcessorOptions(String first, String second) {
152 static final ProcessorOptions IMPLICIT = new ProcessorOptions("-proc:full", "-proc:full");
153 static final ProcessorOptions EXPLICIT = new ProcessorOptions("-processor", "p.TestProcessor");
154 }
155
156 @Test
157 public void testClassPath(Path base, ProcessorOptions processorOptions) throws Exception {
158 var task = new JavacTask(tb)
159 .classpath(classes)
160 .options("--processor-path", classes.toString(),
161 processorOptions.first, processorOptions.second,
162 "--add-modules", "jdk.incubator.code")
163 .outdir(Files.createDirectories(base.resolve("out")))
164 .files(tb.findJavaFiles(Path.of("hw")))
165 .run()
166 .writeAll();
167 var stdout = task.getOutputLines(OutputKind.STDOUT);
168 tb.checkEqual(stdout, List.of("SUCCESS"));
169 }
170
171 @Test
172 public void testClassPathJar(Path base, ProcessorOptions processorOptions) throws Exception {
173 List<String> stdout = new JavacTask(tb)
174 .classpath(pluginJar)
175 .options(processorOptions.first, processorOptions.second,
176 "--add-modules", "jdk.incubator.code")
177 .outdir(Files.createDirectories(base.resolve("out")))
178 .files(tb.findJavaFiles(Path.of("hw")))
179 .run()
180 .writeAll()
181 .getOutputLines(Task.OutputKind.STDOUT);
182 tb.checkEqual(stdout, List.of("SUCCESS"));
183 }
184
185 @Test
186 public void testModulePath(Path base, ProcessorOptions processorOptions) throws IOException {
187 List<String> stdout = new JavacTask(tb)
188 .options("--processor-module-path", mclasses.toString(),
189 processorOptions.first, processorOptions.second,
190 "--add-modules", "jdk.incubator.code")
191 .outdir(Files.createDirectories(base.resolve("out")))
192 .files(tb.findJavaFiles(Path.of("hw")))
193 .run()
194 .writeAll()
195 .getOutputLines(Task.OutputKind.STDOUT);
196 tb.checkEqual(stdout, List.of("SUCCESS"));
197 }
198 }
199