8253736: Cleanup some of WorkArounds and usage thereof

Reviewed-by: vromero, ksrini
This commit is contained in:
Jonathan Gibbons 2020-10-02 16:15:46 +00:00
parent 87d77eb2a0
commit 777804759f
9 changed files with 270 additions and 235 deletions
src
jdk.compiler/share/classes/com/sun/tools/doclint
jdk.javadoc/share/classes/jdk/javadoc/internal
test/langtools/jdk/javadoc/doclet/constantValues

@ -30,6 +30,14 @@ import java.util.ServiceLoader;
import com.sun.source.util.JavacTask;
import com.sun.source.util.Plugin;
/**
* The base class for the DocLint service used by javac.
*
* <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 abstract class DocLint implements Plugin {
public static final String XMSGS_OPTION = "-Xmsgs";
public static final String XMSGS_CUSTOM_PREFIX = "-Xmsgs:";

@ -25,9 +25,13 @@
package jdk.javadoc.internal.doclets.formats.html;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
@ -36,7 +40,6 @@ import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import com.sun.source.util.DocTreePath;
import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.Reporter;
@ -201,7 +204,7 @@ public class HtmlConfiguration extends BaseConfiguration {
docPaths = new DocPaths(utils);
setCreateOverview();
setTopFile(docEnv);
workArounds.initDocLint(options.doclintOpts(), tagletManager.getAllTagletNames());
initDocLint(options.doclintOpts(), tagletManager.getAllTagletNames());
return true;
}
@ -321,12 +324,12 @@ public class HtmlConfiguration extends BaseConfiguration {
@Override
public boolean showMessage(DocTreePath path, String key) {
return (path == null || workArounds.haveDocLint());
return (path == null || !haveDocLint());
}
@Override
public boolean showMessage(Element e, String key) {
return (e == null || workArounds.haveDocLint());
return (e == null || !haveDocLint());
}
@Override

@ -25,18 +25,36 @@
package jdk.javadoc.internal.doclets.toolkit;
import java.io.*;
import java.util.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleElementVisitor14;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.DocTreePath;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
import jdk.javadoc.doclet.Doclet;
@ -44,7 +62,6 @@ import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.Reporter;
import jdk.javadoc.doclet.StandardDoclet;
import jdk.javadoc.doclet.Taglet;
import jdk.javadoc.internal.doclets.formats.html.HtmlDoclet;
import jdk.javadoc.internal.doclets.toolkit.builders.BuilderFactory;
import jdk.javadoc.internal.doclets.toolkit.taglets.TagletManager;
import jdk.javadoc.internal.doclets.toolkit.util.Comparators;
@ -60,6 +77,7 @@ import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import jdk.javadoc.internal.doclets.toolkit.util.Utils.Pair;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberCache;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
import jdk.javadoc.internal.doclint.DocLint;
/**
* Configure the output based on the options. Doclets should sub-class
@ -201,7 +219,7 @@ public abstract class BaseConfiguration {
* @apiNote The {@code doclet} parameter is used when
* {@link Taglet#init(DocletEnvironment, Doclet) initializing tags}.
* Some doclets (such as the {@link StandardDoclet}), may delegate to another
* (such as the {@link HtmlDoclet}). In such cases, the primary doclet (i.e
* (such as the {@code HtmlDoclet}). In such cases, the primary doclet (i.e
* {@code StandardDoclet}) should be provided here, and not any internal
* class like {@code HtmlDoclet}.
*
@ -367,7 +385,16 @@ public abstract class BaseConfiguration {
group.checkPackageGroups(grp.first, grp.second);
}
});
overviewElement = new OverviewElement(workArounds.getUnnamedPackage(), getOverviewPath());
PackageElement unnamedPackage;
Elements elementUtils = utils.elementUtils;
if (docEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_9) >= 0) {
ModuleElement unnamedModule = elementUtils.getModuleElement("");
unnamedPackage = elementUtils.getPackageElement(unnamedModule, "");
} else {
unnamedPackage = elementUtils.getPackageElement("");
}
overviewElement = new OverviewElement(unnamedPackage, getOverviewPath());
return true;
}
@ -690,4 +717,91 @@ public abstract class BaseConfiguration {
|| javafxModule.isUnnamed()
|| javafxModule.getQualifiedName().contentEquals("javafx.base");
}
//<editor-fold desc="DocLint support">
private DocLint doclint;
Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>();
public void runDocLint(TreePath path) {
CompilationUnitTree unit = path.getCompilationUnit();
if (doclint != null && shouldCheck.computeIfAbsent(unit, doclint::shouldCheck)) {
doclint.scan(path);
}
}
/**
* Initializes DocLint, if appropriate, depending on options derived
* from the doclet command-line options, and the set of custom tags
* that should be ignored by DocLint.
*
* DocLint is not enabled if the option {@code -Xmsgs:none} is given,
* and it is not followed by any options to enable any groups.
* Note that arguments for {@code -Xmsgs:} can be given individually
* in separate {@code -Xmsgs:} options, or in a comma-separated list
* for a single option. For example, the following are equivalent:
* <ul>
* <li>{@code -Xmsgs:all} {@code -Xmsgs:-html}
* <li>{@code -Xmsgs:all,-html}
* </ul>
*
* @param opts options for DocLint, derived from the corresponding doclet
* command-line options
* @param customTagNames the names of custom tags, to be ignored by doclint
*/
public void initDocLint(List<String> opts, Set<String> customTagNames) {
List<String> doclintOpts = new ArrayList<>();
// basic analysis of -Xmsgs and -Xmsgs: options to see if doclint is enabled
Set<String> groups = new HashSet<>();
boolean seenXmsgs = false;
for (String opt : opts) {
if (opt.equals(DocLint.XMSGS_OPTION)) {
groups.add("all");
seenXmsgs = true;
} else if (opt.startsWith(DocLint.XMSGS_CUSTOM_PREFIX)) {
String[] args = opt.substring(DocLint.XMSGS_CUSTOM_PREFIX.length())
.split(DocLint.SEPARATOR);
for (String a : args) {
if (a.equals("none")) {
groups.clear();
} else if (a.startsWith("-")) {
groups.remove(a.substring(1));
} else {
groups.add(a);
}
}
seenXmsgs = true;
}
doclintOpts.add(opt);
}
if (seenXmsgs) {
if (groups.isEmpty()) {
// no groups enabled; do not init doclint
return;
}
} else {
// no -Xmsgs options of any kind, use default
doclintOpts.add(DocLint.XMSGS_OPTION);
}
if (!customTagNames.isEmpty()) {
String customTags = String.join(DocLint.SEPARATOR, customTagNames);
doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags);
}
doclintOpts.add(DocLint.XHTML_VERSION_PREFIX + "html5");
doclint = new DocLint();
doclint.init(docEnv.getDocTrees(), docEnv.getElementUtils(), docEnv.getTypeUtils(),
doclintOpts.toArray(new String[0]));
}
public boolean haveDocLint() {
return (doclint != null);
}
//</editor-fold>
}

@ -427,8 +427,8 @@ public class CommentUtils {
}
break;
case PACKAGE:
fo = configuration.workArounds.getJavaFileObject((PackageElement)e);
pe = (PackageElement)e;
pe = (PackageElement) e;
fo = configuration.workArounds.getJavaFileObject(pe);
break;
default:
return null;

@ -116,8 +116,9 @@ public class Messages {
* @param args optional arguments to be replaced in the message.
*/
public void warning(DocTreePath path, String key, Object... args) {
if (configuration.showMessage(path, key))
if (configuration.showMessage(path, key)) {
report(WARNING, path, resources.getText(key, args));
}
}
/**

@ -44,6 +44,7 @@ import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.FileObject;
import javax.tools.JavaFileManager.Location;
@ -94,110 +95,36 @@ public class WorkArounds {
public final BaseConfiguration configuration;
public final ToolEnvironment toolEnv;
public final Utils utils;
private DocLint doclint;
public final Elements elementUtils;
public final Types typeUtils;
public final com.sun.tools.javac.code.Types javacTypes;
public WorkArounds(BaseConfiguration configuration) {
this.configuration = configuration;
this.utils = this.configuration.utils;
this.toolEnv = ((DocEnvImpl)this.configuration.docEnv).toolEnv;
}
Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>();
// TODO: fix this up correctly
public void runDocLint(TreePath path) {
CompilationUnitTree unit = path.getCompilationUnit();
if (doclint != null && shouldCheck.computeIfAbsent(unit, doclint::shouldCheck)) {
doclint.scan(path);
}
}
elementUtils = configuration.docEnv.getElementUtils();
typeUtils = configuration.docEnv.getTypeUtils();
/**
* Initializes doclint, if appropriate, depending on options derived
* from the doclet command-line options, and the set of custom tags
* that should be ignored by doclint.
*
* DocLint is not enabled if the option {@code -Xmsgs:none} is given,
* and it is not followed by any options to enable any groups.
* Note that arguments for {@code -Xmsgs:} can be given individually
* in separate {@code -Xmsgs:} options, or in a comma-separated list
* for a single option. For example, the following are equivalent:
* <ul>
* <li>{@code -Xmsgs:all} {@code -Xmsgs:-html}
* <li>{@code -Xmsgs:all,-html}
* </ul>
*
* @param opts options for doclint, derived from the corresponding doclet
* command-line options
* @param customTagNames the names of custom tags, to be ignored by doclint
*/
public void initDocLint(List<String> opts, Set<String> customTagNames) {
List<String> doclintOpts = new ArrayList<>();
// basic analysis of -Xmsgs and -Xmsgs: options to see if doclint is enabled
Set<String> groups = new HashSet<>();
boolean seenXmsgs = false;
for (String opt : opts) {
if (opt.equals(DocLint.XMSGS_OPTION)) {
groups.add("all");
seenXmsgs = true;
} else if (opt.startsWith(DocLint.XMSGS_CUSTOM_PREFIX)) {
String[] args = opt.substring(DocLint.XMSGS_CUSTOM_PREFIX.length())
.split(DocLint.SEPARATOR);
for (String a : args) {
if (a.equals("none")) {
groups.clear();
} else if (a.startsWith("-")) {
groups.remove(a.substring(1));
} else {
groups.add(a);
}
}
seenXmsgs = true;
}
doclintOpts.add(opt);
}
if (seenXmsgs) {
if (groups.isEmpty()) {
// no groups enabled; do not init doclint
return;
}
} else {
// no -Xmsgs options of any kind, use default
doclintOpts.add(DocLint.XMSGS_OPTION);
}
if (!customTagNames.isEmpty()) {
String customTags = String.join(DocLint.SEPARATOR, customTagNames);
doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags);
}
doclintOpts.add(DocLint.XHTML_VERSION_PREFIX + "html5");
JavacTask t = BasicJavacTask.instance(toolEnv.context);
doclint = new DocLint();
doclint.init(t, doclintOpts.toArray(new String[0]), false);
}
// TODO: fix this up correctly
public boolean haveDocLint() {
return (doclint == null);
// Note: this one use of DocEnvImpl is what prevents us tunnelling extra
// info from a doclet to its taglets via a doclet-specific subtype of
// DocletEnvironment.
toolEnv = ((DocEnvImpl)this.configuration.docEnv).toolEnv;
javacTypes = toolEnv.getTypes();
}
/*
* TODO: This method exists because of a bug in javac which does not
* handle "@deprecated tag in package-info.java", when this issue
* is fixed this method and its uses must be jettisoned.
* handle "@deprecated tag in package-info.java", when this issue
* is fixed this method and its uses must be jettisoned.
*/
public boolean isDeprecated0(Element e) {
if (!utils.getDeprecatedTrees(e).isEmpty()) {
return true;
}
JavacTypes jctypes = ((DocEnvImpl)configuration.docEnv).toolEnv.typeutils;
TypeMirror deprecatedType = utils.getDeprecatedType();
for (AnnotationMirror anno : e.getAnnotationMirrors()) {
if (jctypes.isSameType(anno.getAnnotationType().asElement().asType(), deprecatedType))
if (typeUtils.isSameType(anno.getAnnotationType().asElement().asType(), deprecatedType))
return true;
}
return false;
@ -208,24 +135,11 @@ public class WorkArounds {
return ((Attribute)aDesc).isSynthesized();
}
// TODO: fix the caller
public Object getConstValue(VariableElement ve) {
return ((VarSymbol)ve).getConstValue();
}
// TODO: DocTrees: Trees.getPath(Element e) is slow a factor 4-5 times.
public Map<Element, TreePath> getElementToTreePath() {
return toolEnv.elementToTreePath;
}
// TODO: we need ElementUtils.getPackage to cope with input strings
// to return the proper unnamedPackage for all supported releases.
PackageElement getUnnamedPackage() {
return (Feature.MODULES.allowedInSource(toolEnv.source))
? toolEnv.syms.unnamedModule.unnamedPackage
: toolEnv.syms.noModule.unnamedPackage;
}
// TODO: implement in either jx.l.m API (preferred) or DocletEnvironment.
FileObject getJavaFileObject(PackageElement packageElement) {
return ((PackageSymbol)packageElement).sourcefile;
@ -238,7 +152,7 @@ public class WorkArounds {
// search by qualified name in current module first
ModuleElement me = utils.containingModule(klass);
if (me != null) {
te = configuration.docEnv.getElementUtils().getTypeElement(me, className);
te = elementUtils.getTypeElement(me, className);
if (te != null) {
return te;
}
@ -290,17 +204,12 @@ public class WorkArounds {
}
// finally, search by qualified name in all modules
te = configuration.docEnv.getElementUtils().getTypeElement(className);
if (te != null) {
return te;
}
return null; // not found
return elementUtils.getTypeElement(className);
}
// TODO: need to re-implement this using j.l.m. correctly!, this has
// implications on testInterface, the note here is that javac's supertype
// does the right thing returning Parameters in scope.
// implications on testInterface, the note here is that javac's supertype
// does the right thing returning Parameters in scope.
/**
* Return the type containing the method that this method overrides.
* It may be a <code>TypeElement</code> or a <code>TypeParameterElement</code>.
@ -311,14 +220,14 @@ public class WorkArounds {
if (utils.isStatic(method)) {
return null;
}
MethodSymbol sym = (MethodSymbol)method;
MethodSymbol sym = (MethodSymbol) method;
ClassSymbol origin = (ClassSymbol) sym.owner;
for (com.sun.tools.javac.code.Type t = toolEnv.getTypes().supertype(origin.type);
for (com.sun.tools.javac.code.Type t = javacTypes.supertype(origin.type);
t.hasTag(TypeTag.CLASS);
t = toolEnv.getTypes().supertype(t)) {
t = javacTypes.supertype(t)) {
ClassSymbol c = (ClassSymbol) t.tsym;
for (com.sun.tools.javac.code.Symbol sym2 : c.members().getSymbolsByName(sym.name)) {
if (sym.overrides(sym2, origin, toolEnv.getTypes(), true)) {
if (sym.overrides(sym2, origin, javacTypes, true)) {
// Ignore those methods that may be a simple override
// and allow the real API method to be found.
if (sym2.type.hasTag(TypeTag.METHOD) &&
@ -353,10 +262,10 @@ public class WorkArounds {
!rider.isStatic() &&
// Symbol.overrides assumes the following
ridee.isMemberOf(origin, toolEnv.getTypes()) &&
ridee.isMemberOf(origin, javacTypes) &&
// check access, signatures and check return types
rider.overrides(ridee, origin, toolEnv.getTypes(), true);
rider.overrides(ridee, origin, javacTypes, true);
}
// TODO: jx.l.m ?

@ -107,9 +107,9 @@ import com.sun.source.util.TreePath;
import com.sun.tools.javac.model.JavacTypes;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.BaseOptions;
import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
import jdk.javadoc.internal.doclets.toolkit.CommentUtils.DocCommentInfo;
import jdk.javadoc.internal.doclets.toolkit.Resources;
import jdk.javadoc.internal.doclets.toolkit.WorkArounds;
import jdk.javadoc.internal.doclets.toolkit.taglets.BaseTaglet;
import jdk.javadoc.internal.doclets.toolkit.taglets.Taglet;
import jdk.javadoc.internal.tool.DocEnvImpl;
@ -2271,60 +2271,56 @@ public class Utils {
public String constantValueExpression(VariableElement ve) {
if (cve == null)
cve = new ConstantValueExpression();
return cve.constantValueExpression(configuration.workArounds, ve);
return cve.visit(ve.asType(), ve.getConstantValue());
}
private static class ConstantValueExpression {
public String constantValueExpression(WorkArounds workArounds, VariableElement ve) {
return new TypeKindVisitor9<String, Object>() {
/* TODO: we need to fix this correctly.
* we have a discrepancy here, note the use of getConstValue
* vs. getConstantValue, at some point we need to use
* getConstantValue.
* In the legacy world byte and char primitives appear as Integer values,
* thus a byte value of 127 will appear as 127, but in the new world,
* a byte value appears as Byte thus 0x7f will be printed, similarly
* chars will be translated to \n, \r etc. however, in the new world,
* they will be printed as decimal values. The new world is correct,
* and we should fix this by using getConstantValue and the visitor to
* address this in the future.
*/
@Override
public String visitPrimitiveAsBoolean(PrimitiveType t, Object val) {
return (int)val == 0 ? "false" : "true";
}
@Override
public String visitPrimitiveAsDouble(PrimitiveType t, Object val) {
return sourceForm(((Double)val), 'd');
}
@Override
public String visitPrimitiveAsFloat(PrimitiveType t, Object val) {
return sourceForm(((Float)val).doubleValue(), 'f');
}
@Override
public String visitPrimitiveAsLong(PrimitiveType t, Object val) {
return val + "L";
}
@Override
protected String defaultAction(TypeMirror e, Object val) {
if (val == null)
return null;
else if (val instanceof Character)
return sourceForm(((Character)val));
else if (val instanceof Byte)
return sourceForm(((Byte)val));
else if (val instanceof String)
return sourceForm((String)val);
return val.toString(); // covers int, short
}
}.visit(ve.asType(), workArounds.getConstValue(ve));
// We could also use Elements.getConstantValueExpression, which provides
// similar functionality, but which also includes casts to provide valid
// compilable constants: e.g. (byte) 0x7f
private static class ConstantValueExpression extends TypeKindVisitor9<String, Object> {
@Override
public String visitPrimitiveAsBoolean(PrimitiveType t, Object val) {
return ((boolean) val) ? "true" : "false";
}
@Override
public String visitPrimitiveAsByte(PrimitiveType t, Object val) {
return "0x" + Integer.toString(((Byte) val) & 0xff, 16);
}
@Override
public String visitPrimitiveAsChar(PrimitiveType t, Object val) {
StringBuilder buf = new StringBuilder(8);
buf.append('\'');
sourceChar((char) val, buf);
buf.append('\'');
return buf.toString();
}
@Override
public String visitPrimitiveAsDouble(PrimitiveType t, Object val) {
return sourceForm(((Double) val), 'd');
}
@Override
public String visitPrimitiveAsFloat(PrimitiveType t, Object val) {
return sourceForm(((Float) val).doubleValue(), 'f');
}
@Override
public String visitPrimitiveAsLong(PrimitiveType t, Object val) {
return val + "L";
}
@Override
protected String defaultAction(TypeMirror e, Object val) {
if (val == null)
return null;
else if (val instanceof String)
return sourceForm((String) val);
return val.toString(); // covers int, short
}
// where
private String sourceForm(double v, char suffix) {
if (Double.isNaN(v))
return "0" + suffix + "/0" + suffix;
@ -2335,22 +2331,10 @@ public class Utils {
return v + (suffix == 'f' || suffix == 'F' ? "" + suffix : "");
}
private String sourceForm(char c) {
StringBuilder buf = new StringBuilder(8);
buf.append('\'');
sourceChar(c, buf);
buf.append('\'');
return buf.toString();
}
private String sourceForm(byte c) {
return "0x" + Integer.toString(c & 0xff, 16);
}
private String sourceForm(String s) {
StringBuilder buf = new StringBuilder(s.length() + 5);
buf.append('\"');
for (int i=0; i<s.length(); i++) {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
sourceChar(c, buf);
}
@ -2360,31 +2344,33 @@ public class Utils {
private void sourceChar(char c, StringBuilder buf) {
switch (c) {
case '\b': buf.append("\\b"); return;
case '\t': buf.append("\\t"); return;
case '\n': buf.append("\\n"); return;
case '\f': buf.append("\\f"); return;
case '\r': buf.append("\\r"); return;
case '\"': buf.append("\\\""); return;
case '\'': buf.append("\\\'"); return;
case '\\': buf.append("\\\\"); return;
default:
if (isPrintableAscii(c)) {
buf.append(c); return;
case '\b' -> buf.append("\\b");
case '\t' -> buf.append("\\t");
case '\n' -> buf.append("\\n");
case '\f' -> buf.append("\\f");
case '\r' -> buf.append("\\r");
case '\"' -> buf.append("\\\"");
case '\'' -> buf.append("\\\'");
case '\\' -> buf.append("\\\\");
default -> {
if (isPrintableAscii(c)) {
buf.append(c);
return;
}
unicodeEscape(c, buf);
}
unicodeEscape(c, buf);
return;
}
}
private void unicodeEscape(char c, StringBuilder buf) {
final String chars = "0123456789abcdef";
buf.append("\\u");
buf.append(chars.charAt(15 & (c>>12)));
buf.append(chars.charAt(15 & (c>>8)));
buf.append(chars.charAt(15 & (c>>4)));
buf.append(chars.charAt(15 & (c>>0)));
buf.append(chars.charAt(15 & (c >> 12)));
buf.append(chars.charAt(15 & (c >> 8)));
buf.append(chars.charAt(15 & (c >> 4)));
buf.append(chars.charAt(15 & (c >> 0)));
}
private boolean isPrintableAscii(char c) {
return c >= ' ' && c <= '~';
}
@ -2722,7 +2708,7 @@ public class Utils {
}
}
// run doclint even if docCommentTree is null, to trigger checks for missing comments
configuration.workArounds.runDocLint(path);
configuration.runDocLint(path);
}
dcTreeCache.put(element, info);
}

@ -34,6 +34,8 @@ import java.util.List;
import java.util.Queue;
import javax.lang.model.element.Name;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.StandardLocation;
import com.sun.source.doctree.DocCommentTree;
@ -46,8 +48,8 @@ import com.sun.source.tree.PackageTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.DocTrees;
import com.sun.source.util.JavacTask;
import com.sun.source.util.Plugin;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreePath;
@ -283,27 +285,8 @@ public class DocLint extends com.sun.tools.doclint.DocLint {
public void init(JavacTask task, String[] args, boolean addTaskListener) {
env = new Env();
for (String arg : args) {
if (arg.equals(XMSGS_OPTION)) {
env.messages.setOptions(null);
} else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
} else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
} else if (arg.startsWith(XHTML_VERSION_PREFIX)) {
String argsVersion = arg.substring(arg.indexOf(":") + 1);
HtmlVersion htmlVersion = HtmlVersion.getHtmlVersion(argsVersion);
if (htmlVersion != null) {
env.setHtmlVersion(htmlVersion);
} else {
throw new IllegalArgumentException(argsVersion);
}
} else if (arg.startsWith(XCHECK_PACKAGE)) {
env.setCheckPackages(arg.substring(arg.indexOf(":") + 1));
} else
throw new IllegalArgumentException(arg);
}
env.init(task);
processArgs(env, args);
checker = new Checker(env);
@ -346,6 +329,37 @@ public class DocLint extends com.sun.tools.doclint.DocLint {
}
}
public void init(DocTrees trees, Elements elements, Types types, String... args) {
env = new Env();
env.init(trees, elements, types);
processArgs(env, args);
checker = new Checker(env);
}
private void processArgs(Env env, String... args) {
for (String arg : args) {
if (arg.equals(XMSGS_OPTION)) {
env.messages.setOptions(null);
} else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
} else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
} else if (arg.startsWith(XHTML_VERSION_PREFIX)) {
String argsVersion = arg.substring(arg.indexOf(":") + 1);
HtmlVersion htmlVersion = HtmlVersion.getHtmlVersion(argsVersion);
if (htmlVersion != null) {
env.setHtmlVersion(htmlVersion);
} else {
throw new IllegalArgumentException(argsVersion);
}
} else if (arg.startsWith(XCHECK_PACKAGE)) {
env.setCheckPackages(arg.substring(arg.indexOf(":") + 1));
} else
throw new IllegalArgumentException(arg);
}
}
public void scan(TreePath p) {
DocCommentTree dc = env.trees.getDocCommentTree(p);
checker.scan(dc, p);

@ -57,15 +57,15 @@ public class TestConstantValuesDriver extends JavadocTester {
"""
<code id="TestConstantValues.BYTE_MAX_VALUE">public&nbsp;static&nbsp;final&nbsp;byte</code></td>
<th class="col-second" scope="row"><code><a href="TestConstantValues.html#BYTE_MAX_VALUE">BYTE_MAX_VALUE</a></code></th>
<td class="col-last"><code>127</code></td>""",
<td class="col-last"><code>0x7f</code></td>""",
"""
<code id="TestConstantValues.BYTE_MIN_VALUE">public&nbsp;static&nbsp;final&nbsp;byte</code></td>
<th class="col-second" scope="row"><code><a href="TestConstantValues.html#BYTE_MIN_VALUE">BYTE_MIN_VALUE</a></code></th>
<td class="col-last"><code>-127</code></td>""",
<td class="col-last"><code>0x81</code></td>""",
"""
<code id="TestConstantValues.CHAR_MAX_VALUE">public&nbsp;static&nbsp;final&nbsp;char</code></td>
<th class="col-second" scope="row"><code><a href="TestConstantValues.html#CHAR_MAX_VALUE">CHAR_MAX_VALUE</a></code></th>
<td class="col-last"><code>65535</code></td>""",
<td class="col-last"><code>'\\uffff'</code></td>""",
"""
<code id="TestConstantValues.DOUBLE_MAX_VALUE">public&nbsp;static&nbsp;final&nbsp;double</code></td>""",
"""