8071851: Provide filtering of doclint checking based on packages
Summary: Introducing -Xdoclint/package:<packages> doclint option to enable/disable checking of specified packages.
Reviewed-by: jjg, darcy
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java Wed Mar 11 22:24:05 2015 +0100
@@ -144,6 +144,7 @@
}
public Void scan(DocCommentTree tree, TreePath p) {
+ env.initTypes();
env.setCurrent(p, tree);
boolean isOverridingMethod = !env.currOverriddenMethods.isEmpty();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java Wed Mar 11 22:24:05 2015 +0100
@@ -32,6 +32,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
+import java.util.regex.Pattern;
import javax.lang.model.element.Name;
import javax.tools.StandardLocation;
@@ -79,7 +80,8 @@
private static final String STATS = "-stats";
public static final String XIMPLICIT_HEADERS = "-XimplicitHeaders:";
public static final String XCUSTOM_TAGS_PREFIX = "-XcustomTags:";
- public static final String TAGS_SEPARATOR = ",";
+ public static final String XCHECK_PACKAGE = "-XcheckPackage:";
+ public static final String SEPARATOR = ",";
// <editor-fold defaultstate="collapsed" desc="Command-line entry point">
public static void main(String... args) {
@@ -156,7 +158,7 @@
env.init(task);
checker = new Checker(env);
- DeclScanner ds = new DeclScanner() {
+ DeclScanner ds = new DeclScanner(env) {
@Override
void visitDecl(Tree tree, Name name) {
TreePath p = getCurrentPath();
@@ -272,6 +274,8 @@
env.setImplicitHeaders(Character.digit(ch, 10));
} else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
+ } else if (arg.startsWith(XCHECK_PACKAGE)) {
+ env.setCheckPackages(arg.substring(arg.indexOf(":") + 1));
} else
throw new IllegalArgumentException(arg);
}
@@ -280,7 +284,7 @@
checker = new Checker(env);
if (addTaskListener) {
- final DeclScanner ds = new DeclScanner() {
+ final DeclScanner ds = new DeclScanner(env) {
@Override
void visitDecl(Tree tree, Name name) {
TreePath p = getCurrentPath();
@@ -337,6 +341,9 @@
return true;
if (opt.startsWith(XMSGS_CUSTOM_PREFIX))
return Messages.Options.isValidOptions(opt.substring(XMSGS_CUSTOM_PREFIX.length()));
+ if (opt.startsWith(XCHECK_PACKAGE)) {
+ return Env.validatePackages(opt.substring(opt.indexOf(":") + 1));
+ }
return false;
}
@@ -348,6 +355,12 @@
// <editor-fold defaultstate="collapsed" desc="DeclScanner">
static abstract class DeclScanner extends TreePathScanner<Void, Void> {
+ final Env env;
+
+ public DeclScanner(Env env) {
+ this.env = env;
+ }
+
abstract void visitDecl(Tree tree, Name name);
@Override @DefinedBy(Api.COMPILER_TREE)
@@ -373,6 +386,33 @@
visitDecl(tree, tree.getName());
return super.visitVariable(tree, ignore);
}
+
+ @Override @DefinedBy(Api.COMPILER_TREE)
+ public Void visitCompilationUnit(CompilationUnitTree node, Void p) {
+ if (env.includePackages != null) {
+ String packageName = node.getPackageName() != null
+ ? node.getPackageName().toString()
+ : "";
+ if (!env.includePackages.isEmpty()) {
+ boolean included = false;
+ for (Pattern pack : env.includePackages) {
+ if (pack.matcher(packageName).matches()) {
+ included = true;
+ break;
+ }
+ }
+ if (!included)
+ return null;
+ }
+ for (Pattern pack : env.excludePackages) {
+ if (pack.matcher(packageName).matches()) {
+ return null;
+ }
+ }
+ }
+ return super.visitCompilationUnit(node, p);
+ }
+
}
// </editor-fold>
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Env.java Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Env.java Wed Mar 11 22:24:05 2015 +0100
@@ -26,8 +26,12 @@
package com.sun.tools.doclint;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Set;
-import java.util.LinkedHashSet;
+import java.util.regex.Pattern;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
@@ -36,6 +40,7 @@
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
+import javax.tools.Diagnostic.Kind;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.util.DocTrees;
@@ -44,6 +49,7 @@
import com.sun.source.util.TreePath;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.util.MatchingUtils;
import com.sun.tools.javac.util.StringUtils;
/**
@@ -90,6 +96,9 @@
Set<String> customTags;
+ Set<Pattern> includePackages;
+ Set<Pattern> excludePackages;
+
// Utility classes
DocTrees trees;
Elements elements;
@@ -129,6 +138,12 @@
this.trees = trees;
this.elements = elements;
this.types = types;
+ }
+
+ void initTypes() {
+ if (java_lang_Error != null)
+ return ;
+
java_lang_Error = elements.getTypeElement("java.lang.Error").asType();
java_lang_RuntimeException = elements.getTypeElement("java.lang.RuntimeException").asType();
java_lang_Throwable = elements.getTypeElement("java.lang.Throwable").asType();
@@ -141,12 +156,43 @@
void setCustomTags(String cTags) {
customTags = new LinkedHashSet<>();
- for (String s : cTags.split(DocLint.TAGS_SEPARATOR)) {
+ for (String s : cTags.split(DocLint.SEPARATOR)) {
if (!s.isEmpty())
customTags.add(s);
}
}
+ void setCheckPackages(String packages) {
+ includePackages = new HashSet<>();
+ excludePackages = new HashSet<>();
+ for (String pack : packages.split(DocLint.SEPARATOR)) {
+ boolean excluded = false;
+ if (pack.startsWith("-")) {
+ pack = pack.substring(1);
+ excluded = true;
+ }
+ if (pack.isEmpty())
+ continue;
+ Pattern pattern = MatchingUtils.validImportStringToPattern(pack);
+ if (excluded) {
+ excludePackages.add(pattern);
+ } else {
+ includePackages.add(pattern);
+ }
+ }
+ }
+
+ static boolean validatePackages(String packages) {
+ for (String pack : packages.split(DocLint.SEPARATOR)) {
+ if (pack.startsWith("-")) {
+ pack = pack.substring(1);
+ }
+ if (!pack.isEmpty() && !MatchingUtils.isValidImportString(pack))
+ return false;
+ }
+ return true;
+ }
+
/** Set the current declaration and its doc comment. */
void setCurrent(TreePath path, DocCommentTree comment) {
currPath = path;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/resources/doclint.properties Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/resources/doclint.properties Wed Mar 11 22:24:05 2015 +0100
@@ -107,6 +107,13 @@
\ equivalent to -Xmsgs:all/protected, meaning that\n\
\ all messages are reported for protected and public\n\
\ declarations only. \n\
+\ -XcheckPackage:<packages>\n\
+\ Enable or disable checks in specific packages.\n\
+\ <packages> is a comma separated list of package specifiers.\n\
+\ Package specifier is either a qualified name of a package\n\
+\ or a package name prefix followed by ''.*'', which expands to\n\
+\ all sub-packages of the given package. Prefix the package specifier\n\
+\ with ''-'' to disable checks for the specified packages.\n\
\ -stats\n\
\ Report statistics on the reported issues.\n\
\ -h -help --help -usage -?\n\
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Wed Mar 11 22:24:05 2015 +0100
@@ -496,6 +496,14 @@
if (doclintOpts.equals(Collections.singleton(DocLint.XMSGS_CUSTOM_PREFIX + "none")))
return List.nil();
+ String checkPackages = options.get(Option.XDOCLINT_PACKAGE);
+
+ if (checkPackages != null) {
+ for (String s : checkPackages.split("\\s+")) {
+ doclintOpts.add(s.replace(Option.XDOCLINT_PACKAGE.text, DocLint.XCHECK_PACKAGE));
+ }
+ }
+
// standard doclet normally generates H1, H2,
// so for now, allow user comments to assume that
doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2");
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Wed Mar 11 22:24:05 2015 +0100
@@ -129,6 +129,22 @@
}
},
+ XDOCLINT_PACKAGE("-Xdoclint/package:", "opt.Xdoclint.package.args", "opt.Xdoclint.package.desc", EXTENDED, BASIC) {
+ @Override
+ public boolean matches(String option) {
+ return DocLint.isValidOption(
+ option.replace(XDOCLINT_PACKAGE.text, DocLint.XCHECK_PACKAGE));
+ }
+
+ @Override
+ public boolean process(OptionHelper helper, String option) {
+ String prev = helper.get(XDOCLINT_PACKAGE);
+ String next = (prev == null) ? option : (prev + " " + option);
+ helper.put(XDOCLINT_PACKAGE.text, next);
+ return false;
+ }
+ },
+
// -nowarn is retained for command-line backward compatibility
NOWARN("-nowarn", "opt.nowarn", STANDARD, BASIC) {
@Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Wed Mar 11 22:24:05 2015 +0100
@@ -70,6 +70,7 @@
import com.sun.tools.javac.util.JavacMessages;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.MatchingUtils;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Options;
@@ -1431,7 +1432,6 @@
return specifiedPackages;
}
- private static final Pattern allMatches = Pattern.compile(".*");
public static final Pattern noMatches = Pattern.compile("(\\P{all})+");
/**
@@ -1440,8 +1440,8 @@
* import-style string, return a regex that won't match anything.
*/
private static Pattern importStringToPattern(String s, Processor p, Log log) {
- if (isValidImportString(s)) {
- return validImportStringToPattern(s);
+ if (MatchingUtils.isValidImportString(s)) {
+ return MatchingUtils.validImportStringToPattern(s);
} else {
log.warning("proc.malformed.supported.string", s, p.getClass().getName());
return noMatches; // won't match any valid identifier
@@ -1449,54 +1449,6 @@
}
/**
- * Return true if the argument string is a valid import-style
- * string specifying claimed annotations; return false otherwise.
- */
- public static boolean isValidImportString(String s) {
- if (s.equals("*"))
- return true;
-
- boolean valid = true;
- String t = s;
- int index = t.indexOf('*');
-
- if (index != -1) {
- // '*' must be last character...
- if (index == t.length() -1) {
- // ... any and preceding character must be '.'
- if ( index-1 >= 0 ) {
- valid = t.charAt(index-1) == '.';
- // Strip off ".*$" for identifier checks
- t = t.substring(0, t.length()-2);
- }
- } else
- return false;
- }
-
- // Verify string is off the form (javaId \.)+ or javaId
- if (valid) {
- String[] javaIds = t.split("\\.", t.length()+2);
- for(String javaId: javaIds)
- valid &= SourceVersion.isIdentifier(javaId);
- }
- return valid;
- }
-
- public static Pattern validImportStringToPattern(String s) {
- if (s.equals("*")) {
- return allMatches;
- } else {
- String s_prime = s.replace(".", "\\.");
-
- if (s_prime.endsWith("*")) {
- s_prime = s_prime.substring(0, s_prime.length() - 1) + ".+";
- }
-
- return Pattern.compile(s_prime);
- }
- }
-
- /**
* For internal use only. This method may be removed without warning.
*/
public Context getContext() {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Wed Mar 11 22:24:05 2015 +0100
@@ -228,6 +228,17 @@
\ Enable or disable specific checks for problems in javadoc comments,\n\
\ where <group> is one of accessibility, html, missing, reference, or syntax,\n\
\ and <access> is one of public, protected, package, or private.
+
+javac.opt.Xdoclint.package.args = \
+ ([-]<packages>)
+
+javac.opt.Xdoclint.package.desc=\n\
+\ Enable or disable checks in specific packages. <packages> is a comma separated\n\
+\ list of package specifiers. Package specifier is either a qualified name of a package\n\
+\ or a package name prefix followed by '.*', which expands to all sub-packages of\n\
+\ the given package. Prefix the package specifier with '-' to disable checks for\n\
+\ the specified packages.
+
javac.opt.Xstdout=\
Redirect standard output
javac.opt.X=\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/MatchingUtils.java Wed Mar 11 22:24:05 2015 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005, 2015, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.tools.javac.util;
+
+import java.util.regex.Pattern;
+import javax.lang.model.SourceVersion;
+
+/**Utilities to convert an import-like string to a regexp.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class MatchingUtils {
+ private static final Pattern allMatches = Pattern.compile(".*");
+
+ /**
+ * Return true if the argument string is a valid import-style
+ * string specifying claimed annotations; return false otherwise.
+ */
+ public static boolean isValidImportString(String s) {
+ if (s.equals("*"))
+ return true;
+
+ boolean valid = true;
+ String t = s;
+ int index = t.indexOf('*');
+
+ if (index != -1) {
+ // '*' must be last character...
+ if (index == t.length() -1) {
+ // ... any and preceding character must be '.'
+ if ( index-1 >= 0 ) {
+ valid = t.charAt(index-1) == '.';
+ // Strip off ".*$" for identifier checks
+ t = t.substring(0, t.length()-2);
+ }
+ } else
+ return false;
+ }
+
+ // Verify string is off the form (javaId \.)+ or javaId
+ if (valid) {
+ String[] javaIds = t.split("\\.", t.length()+2);
+ for(String javaId: javaIds)
+ valid &= SourceVersion.isIdentifier(javaId);
+ }
+ return valid;
+ }
+
+ public static Pattern validImportStringToPattern(String s) {
+ if (s.equals("*")) {
+ return allMatches;
+ } else {
+ String s_prime = s.replace(".", "\\.");
+
+ if (s_prime.endsWith("*")) {
+ s_prime = s_prime.substring(0, s_prime.length() - 1) + ".+";
+ }
+
+ return Pattern.compile(s_prime);
+ }
+ }
+
+}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java Wed Mar 11 22:24:05 2015 +0100
@@ -833,7 +833,7 @@
for (String customTag : customTagNames) {
customTags.append(sep);
customTags.append(customTag);
- sep = DocLint.TAGS_SEPARATOR;
+ sep = DocLint.SEPARATOR;
}
doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags.toString());
--- a/langtools/test/tools/doclint/tool/HelpTest.out Wed Mar 11 12:25:37 2015 +0100
+++ b/langtools/test/tools/doclint/tool/HelpTest.out Wed Mar 11 22:24:05 2015 +0100
@@ -30,6 +30,13 @@
equivalent to -Xmsgs:all/protected, meaning that
all messages are reported for protected and public
declarations only.
+ -XcheckPackage:<packages>
+ Enable or disable checks in specific packages.
+ <packages> is a comma separated list of package specifiers.
+ Package specifier is either a qualified name of a package
+ or a package name prefix followed by '.*', which expands to
+ all sub-packages of the given package. Prefix the package specifier
+ with '-' to disable checks for the specified packages.
-stats
Report statistics on the reported issues.
-h -help --help -usage -?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doclint/IncludePackagesTest.java Wed Mar 11 22:24:05 2015 +0100
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2015, 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 8071851
+ * @summary Test the -Xdoclint/package option
+ */
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import static javax.tools.Diagnostic.Kind.*;
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.main.Main;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class IncludePackagesTest {
+ public static void main(String... args) throws Exception {
+ new IncludePackagesTest().run();
+ }
+
+ JavaCompiler javac;
+ StandardJavaFileManager fm;
+ List<JavaFileObject> files;
+
+ final String[] sources = new String[] {
+ "p1/p1T.java",
+ "package p1;\n" +
+ "/** Syntax < error. */\n" +
+ "public class p1T {\n" +
+ "}\n",
+ "p1/sp1/p1sp1T.java",
+ "package p1.sp1;\n" +
+ "/** Syntax < error. */\n" +
+ "public class p1sp1T {\n" +
+ "}\n",
+ "p1/sp1/sp2/p1sp1sp2T.java",
+ "package p1.sp1.sp2;\n" +
+ "/** Syntax < error. */\n" +
+ "public class p1sp1sp2T {\n" +
+ "}\n",
+ "p2/p2T.java",
+ "package p2;\n" +
+ "/** Syntax < error. */\n" +
+ "public class p2T {\n" +
+ "}\n",
+ "Default.java",
+ "/** Syntax < error. */\n" +
+ "public class Default {\n" +
+ "}\n",
+ };
+
+ final String rawDiags = "-XDrawDiagnostics";
+ private enum Message {
+ // doclint messages
+ p1T(ERROR, "p1T.java:2:12: compiler.err.proc.messager: malformed HTML"),
+ p1sp1T(ERROR, "p1sp1T.java:2:12: compiler.err.proc.messager: malformed HTML"),
+ p1sp1sp2T(ERROR, "p1sp1sp2T.java:2:12: compiler.err.proc.messager: malformed HTML"),
+ p2T(ERROR, "p2T.java:2:12: compiler.err.proc.messager: malformed HTML"),
+ Default(ERROR, "Default.java:1:12: compiler.err.proc.messager: malformed HTML"),
+ INVALID_PACKAGE_ERROR(ERROR, "invalid flag: -Xdoclint/package:wrong+package");
+
+ final Diagnostic.Kind kind;
+ final String text;
+
+ static Message get(String text) {
+ for (Message m: values()) {
+ if (m.text.equals(text))
+ return m;
+ }
+ return null;
+ }
+
+ Message(Diagnostic.Kind kind, String text) {
+ this.kind = kind;
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + kind + ",\"" + text + "\"]";
+ }
+ }
+ void run() throws Exception {
+ javac = ToolProvider.getSystemJavaCompiler();
+ fm = javac.getStandardFileManager(null, null, null);
+ try {
+ fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(".")));
+ files = new ArrayList<>();
+
+ for (int si = 0; si < sources.length; si += 2) {
+ files.add(new JFOImpl(sources[si], sources[si + 1]));
+ }
+
+ test(Arrays.asList(rawDiags, "-Xdoclint"),
+ Main.Result.ERROR,
+ EnumSet.of(Message.p1T, Message.p1sp1T, Message.p1sp1sp2T,
+ Message.p2T, Message.Default));
+
+ test(Arrays.asList(rawDiags, "-Xdoclint", "-Xdoclint/package:p1"),
+ Main.Result.ERROR,
+ EnumSet.of(Message.p1T));
+
+ test(Arrays.asList(rawDiags, "-Xdoclint", "-Xdoclint/package:p1.*"),
+ Main.Result.ERROR,
+ EnumSet.of(Message.p1sp1T, Message.p1sp1sp2T));
+
+ test(Arrays.asList(rawDiags, "-Xdoclint", "-Xdoclint/package:p1.*,-p1.sp1"),
+ Main.Result.ERROR,
+ EnumSet.of(Message.p1sp1sp2T));
+
+ test(Arrays.asList(rawDiags, "-Xdoclint", "-Xdoclint/package:-p1.sp1"),
+ Main.Result.ERROR,
+ EnumSet.of(Message.p1T, Message.p1sp1sp2T, Message.p2T, Message.Default));
+
+ test(Arrays.asList(rawDiags, "-Xdoclint", "-Xdoclint/package:wrong+package"),
+ Main.Result.CMDERR,
+ EnumSet.of(Message.INVALID_PACKAGE_ERROR));
+
+ if (errors > 0)
+ throw new Exception(errors + " errors occurred");
+ } finally {
+ fm.close();
+ }
+ }
+
+ void test(List<String> opts, Main.Result expectResult, Set<Message> expectMessages) {
+ System.err.println("test: " + opts);
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ try {
+ JavacTask t = (JavacTask) javac.getTask(pw, fm, null, opts, null, files);
+ boolean ok = t.call();
+ pw.close();
+ String out = sw.toString().replaceAll("[\r\n]+", "\n");
+ if (!out.isEmpty())
+ System.err.println(out);
+ if (ok && expectResult != Main.Result.OK) {
+ error("Compilation succeeded unexpectedly");
+ } else if (!ok && expectResult != Main.Result.ERROR) {
+ error("Compilation failed unexpectedly");
+ } else
+ check(out, expectMessages);
+ } catch (IllegalArgumentException e) {
+ System.err.println(e);
+ String expectOut = expectMessages.iterator().next().text;
+ if (expectResult != Main.Result.CMDERR)
+ error("unexpected exception caught");
+ else if (!e.getMessage().equals(expectOut)) {
+ error("unexpected exception message: "
+ + e.getMessage()
+ + " expected: " + expectOut);
+ }
+ }
+ }
+
+ private void check(String out, Set<Message> expect) {
+ Pattern stats = Pattern.compile("^([1-9]+) (error|warning)(s?)");
+ Set<Message> found = EnumSet.noneOf(Message.class);
+ int e = 0, w = 0;
+ if (!out.isEmpty()) {
+ for (String line: out.split("[\r\n]+")) {
+ Matcher s = stats.matcher(line);
+ if (s.matches()) {
+ int i = Integer.valueOf(s.group(1));
+ if (s.group(2).equals("error"))
+ e++;
+ else
+ w++;
+ continue;
+ }
+
+ Message m = Message.get(line);
+ if (m == null)
+ error("Unexpected line: " + line);
+ else
+ found.add(m);
+ }
+ }
+ for (Message m: expect) {
+ if (!found.contains(m))
+ error("expected message not found: " + m.text);
+ }
+ for (Message m: found) {
+ if (!expect.contains(m))
+ error("unexpected message found: " + m.text);
+ }
+ }
+
+ void error(String msg) {
+ System.err.println("Error: " + msg);
+ errors++;
+ }
+
+ int errors;
+
+ class JFOImpl extends SimpleJavaFileObject {
+
+ private final String code;
+
+ public JFOImpl(String fileName, String code) {
+ super(URI.create(fileName), JavaFileObject.Kind.SOURCE);
+ this.code = code;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncoding) {
+ return code;
+ }
+ }
+}