8198552: Multiple javac plugins do not work at the same time.
Summary: Fixing handling of multiple -Xplugin, -Xdoclint: and -Xdoclint/packages: parameters.
Reviewed-by: jjg, vromero
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java Thu Mar 22 12:59:58 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java Thu Mar 22 12:13:08 2018 +0100
@@ -216,6 +216,7 @@
} catch (RuntimeException ex) {
throw new PropagatedException(ex);
}
+ break;
}
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Thu Mar 22 12:59:58 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Thu Mar 22 12:13:08 2018 +0100
@@ -836,9 +836,7 @@
String checkPackages = options.get(Option.XDOCLINT_PACKAGE);
if (checkPackages != null) {
- for (String s : checkPackages.split("\\s+")) {
- doclintOpts.add(DocLint.XCHECK_PACKAGE + s);
- }
+ doclintOpts.add(DocLint.XCHECK_PACKAGE + checkPackages);
}
String format = options.get(Option.DOCLINT_FORMAT);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Mar 22 12:59:58 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Mar 22 12:13:08 2018 +0100
@@ -134,9 +134,9 @@
}
@Override
- public void process(OptionHelper helper, String option) {
+ public void process(OptionHelper helper, String option, String arg) {
String prev = helper.get(XDOCLINT_CUSTOM);
- String next = (prev == null) ? option : (prev + " " + option);
+ String next = (prev == null) ? arg : (prev + " " + arg);
helper.put(XDOCLINT_CUSTOM.primaryName, next);
}
},
@@ -149,9 +149,9 @@
}
@Override
- public void process(OptionHelper helper, String option) {
+ public void process(OptionHelper helper, String option, String arg) {
String prev = helper.get(XDOCLINT_PACKAGE);
- String next = (prev == null) ? option : (prev + " " + option);
+ String next = (prev == null) ? arg : (prev + "," + arg);
helper.put(XDOCLINT_PACKAGE.primaryName, next);
}
},
@@ -512,8 +512,7 @@
PLUGIN("-Xplugin:", "opt.arg.plugin", "opt.plugin", EXTENDED, BASIC) {
@Override
- public void process(OptionHelper helper, String option) {
- String p = option.substring(option.indexOf(':') + 1).trim();
+ public void process(OptionHelper helper, String option, String p) {
String prev = helper.get(PLUGIN);
helper.put(PLUGIN.primaryName, (prev == null) ? p : prev + '\0' + p);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/doclint/MultipleDocLintOptionsTest.java Thu Mar 22 12:13:08 2018 +0100
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8198552
+ * @summary Check that -Xdoclint: option can be specified multiple times
+ * @compile/fail/ref=MultipleDocLintOptionsTest.out -Xdoclint:html -Xdoclint:syntax -XDrawDiagnostics MultipleDocLintOptionsTest.java
+ */
+
+/** <html> */
+public class MultipleDocLintOptionsTest {
+ /** @return */
+ int emptyReturn() { return -1; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/doclint/MultipleDocLintOptionsTest.out Thu Mar 22 12:13:08 2018 +0100
@@ -0,0 +1,5 @@
+MultipleDocLintOptionsTest.java:8:5: compiler.err.proc.messager: element not allowed in documentation comments: <html>
+MultipleDocLintOptionsTest.java:8:5: compiler.err.proc.messager: element not closed: html
+MultipleDocLintOptionsTest.java:10:9: compiler.warn.proc.messager: no description for @return
+2 errors
+1 warning
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/doclint/multipackage/MultiPackage.java Thu Mar 22 12:13:08 2018 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8198552
+ * @summary Check that -Xdoclint/package: option can be specified multiple times
+ * @compile/fail/ref=MultiPackage.out -Xdoclint:html -Xdoclint/package:p1 -Xdoclint/package:p2 -XDrawDiagnostics p1/Test1.java p2/Test2.java
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/doclint/multipackage/MultiPackage.out Thu Mar 22 12:13:08 2018 +0100
@@ -0,0 +1,5 @@
+Test1.java:4:4: compiler.err.proc.messager: element not allowed in documentation comments: <html>
+Test1.java:4:4: compiler.err.proc.messager: element not closed: html
+Test2.java:4:4: compiler.err.proc.messager: element not allowed in documentation comments: <html>
+Test2.java:4:4: compiler.err.proc.messager: element not closed: html
+4 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/doclint/multipackage/p1/Test1.java Thu Mar 22 12:13:08 2018 +0100
@@ -0,0 +1,5 @@
+/*/nodynamiccopyright/*/
+package p1;
+
+/**<html>*/
+public class Test1 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/doclint/multipackage/p2/Test2.java Thu Mar 22 12:13:08 2018 +0100
@@ -0,0 +1,5 @@
+/*/nodynamiccopyright/*/
+package p2;
+
+/**<html>*/
+public class Test2 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/plugin/MultiplePlugins.java Thu Mar 22 12:13:08 2018 +0100
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8198552
+ * @summary Check that multiple plugins can be specified when starting javac
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.JarTask
+ * @run main MultiplePlugins
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import toolbox.JarTask;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class MultiplePlugins {
+ public static void main(String... args) throws Exception {
+ new MultiplePlugins().run();
+ }
+
+ final File pluginClasses;
+ final File pluginModuleClasses;
+ final File pluginJar;
+ final JavaCompiler compiler;
+ final ToolBox tb = new ToolBox();
+
+ MultiplePlugins() throws Exception {
+ pluginClasses = new File("plugin");
+ tb.createDirectories(pluginClasses.toPath());
+ pluginModuleClasses = new File("plugin-modules");
+ pluginJar = new File("plugin.jar");
+ compiler = ToolProvider.getSystemJavaCompiler();
+ }
+
+ void run() throws Exception {
+ // compile the plugins:
+ new JavacTask(tb)
+ .options("-d", pluginClasses.getPath())
+ .sources(PLUGIN1, PLUGIN2)
+ .run();
+
+ File plugin = new File(pluginClasses.getPath(), "META-INF/services/com.sun.source.util.Plugin");
+ tb.writeFile(plugin.getPath(), "p1.Plugin1\np2.Plugin2\n");
+ new JarTask(tb)
+ .run("cf", pluginJar.getPath(), "-C", pluginClasses.getPath(), ".");
+
+ testCommandLine(EXPECTED, "--processor-path", pluginJar.toString(), "-Xplugin:plugin1", "-Xplugin:plugin2");
+ testAPI(EXPECTED, "--processor-path", pluginJar.toString(), "-Xplugin:plugin1", "-Xplugin:plugin2");
+
+ // compile the plugins as modules:
+ File m1 = new File(pluginModuleClasses, "m1");
+ tb.createDirectories(m1.toPath());
+ new JavacTask(tb)
+ .options("-d", m1.getPath())
+ .sources(MODULE1, PLUGIN1)
+ .run();
+
+ File m2 = new File(pluginModuleClasses, "m2");
+ tb.createDirectories(m2.toPath());
+ new JavacTask(tb)
+ .options("-d", m2.getPath())
+ .sources(MODULE2, PLUGIN2)
+ .run();
+
+ testCommandLine(EXPECTED, "--processor-module-path", pluginModuleClasses.toString(), "-Xplugin:plugin1", "-Xplugin:plugin2");
+ testAPI(EXPECTED, "--processor-module-path", pluginModuleClasses.toString(), "-Xplugin:plugin1", "-Xplugin:plugin2");
+
+ if (errors > 0)
+ throw new Exception(errors + " errors occurred");
+ }
+
+ void testAPI(List<String> ref, String... opts) throws Exception {
+ try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
+ fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(".")));
+
+ System.err.println("test api: " + List.of(opts));
+ Task.Result result = new JavacTask(tb, Task.Mode.API)
+ .fileManager(fm)
+ .options(opts)
+ .sources(TEST)
+ .run(Task.Expect.SUCCESS)
+ .writeAll();
+ List<String> out = result.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(out, ref);
+ }
+ }
+
+ void testCommandLine(List<String> ref,String... opt) throws IOException {
+ Path testJavaFile = Paths.get("Test.java");
+
+ tb.writeFile(testJavaFile, TEST);
+
+ List<String> args = new ArrayList<>();
+
+ args.add("-d"); args.add(".");
+ args.addAll(List.of(opt));
+
+ System.err.println("test command line: " + Arrays.asList(args));
+ Task.Result result = new JavacTask(tb, Task.Mode.CMDLINE)
+ .options(args)
+ .files(testJavaFile)
+ .run(Task.Expect.SUCCESS)
+ .writeAll();
+ List<String> out = result.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(out, ref);
+ }
+
+ private void checkOutput(List<String> lines, List<String> ref) {
+ if (!lines.equals(ref)) {
+ error("unexpected output");
+ }
+ }
+
+ private void error(String msg) {
+ System.err.println(msg);
+ errors++;
+ }
+
+ int errors;
+
+ private static final String MODULE1 =
+ "module m1 {\n" +
+ " requires jdk.compiler;\n" +
+ " provides com.sun.source.util.Plugin with p1.Plugin1;\n" +
+ "}\n";
+ private static final String PLUGIN1 =
+ "package p1;\n" +
+ "import com.sun.source.util.*;\n" +
+ "public class Plugin1 implements Plugin {\n" +
+ " public String getName() {\n" +
+ " return \"plugin1\";\n" +
+ " }\n" +
+ " public void init(JavacTask task, String... args) {\n" +
+ " System.err.println(\"plugin1\");\n" +
+ " }\n" +
+ "}";
+ private static final String MODULE2 =
+ "module m2 {\n" +
+ " requires jdk.compiler;\n" +
+ " provides com.sun.source.util.Plugin with p2.Plugin2;\n" +
+ "}\n";
+ private static final String PLUGIN2 =
+ "package p2;\n" +
+ "import com.sun.source.util.*;\n" +
+ "public class Plugin2 implements Plugin {\n" +
+ " public String getName() {\n" +
+ " return \"plugin2\";\n" +
+ " }\n" +
+ " public void init(JavacTask task, String... args) {\n" +
+ " System.err.println(\"plugin2\");\n" +
+ " }\n" +
+ "}";
+ private static final String TEST =
+ "public class Test {}";
+ private static final List<String> EXPECTED = List.of(
+ "plugin1",
+ "plugin2"
+ );
+
+}