提交 e1fc85d8 编写于 作者: J jjg

8004832: Add new doclint package

Reviewed-by: mcimadamore
上级 42da9239
......@@ -117,7 +117,8 @@ javac.includes = \
javax/lang/model/ \
javax/tools/ \
com/sun/source/ \
com/sun/tools/javac/
com/sun/tools/javac/ \
com/sun/tools/doclint/
javac.tests = \
tools/javac
......
......@@ -45,9 +45,7 @@ public abstract class DocTrees extends Trees {
* @throws IllegalArgumentException if the task does not support the Trees API.
*/
public static DocTrees instance(CompilationTask task) {
if (!task.getClass().getName().equals("com.sun.tools.javac.api.JavacTaskImpl"))
throw new IllegalArgumentException();
return (DocTrees) getJavacTrees(CompilationTask.class, task);
return (DocTrees) Trees.instance(task);
}
/**
......
......@@ -139,6 +139,7 @@ public abstract class JavacTask implements CompilationTask {
* @see com.sun.source.util.Trees#getTypeMirror
*/
public abstract TypeMirror getTypeMirror(Iterable<? extends Tree> path);
/**
* Get a utility object for dealing with program elements.
*/
......
......@@ -60,14 +60,20 @@ public class TreePath implements Iterable<Tree> {
this.path = path;
}
}
class PathFinder extends TreePathScanner<TreePath,Tree> {
public TreePath scan(Tree tree, Tree target) {
if (tree == target)
if (tree == target) {
throw new Result(new TreePath(getCurrentPath(), target));
}
return super.scan(tree, target);
}
}
if (path.getLeaf() == target) {
return path;
}
try {
new PathFinder().scan(path, target);
} catch (Result result) {
......
此差异已折叠。
/*
* Copyright (c) 2012, 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.doclint;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.Name;
import javax.tools.StandardLocation;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
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;
import com.sun.source.util.TreePathScanner;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.Context;
/**
* Multi-function entry point for the doc check utility.
*
* This class can be invoked in the following ways:
* <ul>
* <li>From the command line
* <li>From javac, as a plugin
* <li>Directly, via a simple API
* </ul>
*
* <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></p>
*/
public class DocLint implements Plugin {
public static final String XMSGS_OPTION = "-Xmsgs";
public static final String XMSGS_CUSTOM_PREFIX = "-Xmsgs:";
private static final String STATS = "-stats";
// <editor-fold defaultstate="collapsed" desc="Command-line entry point">
public static void main(String... args) {
try {
new DocLint().run(args);
} catch (BadArgs e) {
System.err.println(e.getMessage());
System.exit(1);
} catch (IOException e) {
System.err.println(e);
System.exit(2);
}
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Simple API">
public static class BadArgs extends Exception {
private static final long serialVersionUID = 0;
BadArgs(String code, Object... args) {
this.code = code;
this.args = args;
}
final String code;
final Object[] args;
}
/**
* Simple API entry point.
*/
public void run(String... args) throws BadArgs, IOException {
PrintWriter out = new PrintWriter(System.out);
try {
run(out, args);
} finally {
out.flush();
}
}
public void run(PrintWriter out, String... args) throws BadArgs, IOException {
env = new Env();
processArgs(args);
if (needHelp)
showHelp(out);
if (javacFiles.isEmpty()) {
if (!needHelp)
System.out.println("no files given");
}
JavacTool tool = JavacTool.create();
JavacFileManager fm = new JavacFileManager(new Context(), false, null);
fm.setSymbolFileEnabled(false);
fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, javacBootClassPath);
fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
JavacTask task = tool.getTask(out, fm, null, javacOpts, null,
fm.getJavaFileObjectsFromFiles(javacFiles));
Iterable<? extends CompilationUnitTree> units = task.parse();
((JavacTaskImpl) task).enter();
env.init(task);
checker = new Checker(env);
DeclScanner ds = new DeclScanner() {
@Override
void visitDecl(Tree tree, Name name) {
TreePath p = getCurrentPath();
DocCommentTree dc = env.trees.getDocCommentTree(p);
checker.scan(dc, p);
}
};
ds.scan(units, null);
reportStats(out);
Context ctx = ((JavacTaskImpl) task).getContext();
JavaCompiler c = JavaCompiler.instance(ctx);
c.printCount("error", c.errorCount());
c.printCount("warn", c.warningCount());
}
void processArgs(String... args) throws BadArgs {
javacOpts = new ArrayList<String>();
javacFiles = new ArrayList<File>();
if (args.length == 0)
needHelp = true;
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.matches("-Xmax(errs|warns)") && i + 1 < args.length) {
if (args[++i].matches("[0-9]+")) {
javacOpts.add(arg);
javacOpts.add(args[i]);
} else {
throw new BadArgs("dc.bad.value.for.option", arg, args[i]);
}
} else if (arg.equals(STATS)) {
env.messages.setStatsEnabled(true);
} else if (arg.matches("-bootclasspath") && i + 1 < args.length) {
javacBootClassPath = splitPath(args[++i]);
} else if (arg.matches("-classpath") && i + 1 < args.length) {
javacClassPath = splitPath(args[++i]);
} else if (arg.matches("-sourcepath") && i + 1 < args.length) {
javacSourcePath = splitPath(args[++i]);
} else 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.equals("-h") || arg.equals("-help") || arg.equals("--help")
|| arg.equals("-?") || arg.equals("-usage")) {
needHelp = true;
} else if (arg.startsWith("-")) {
throw new BadArgs("dc.bad.option", arg);
} else {
while (i < args.length)
javacFiles.add(new File(args[i++]));
}
}
}
void showHelp(PrintWriter out) {
out.println("Usage:");
out.println(" doclint [options] source-files...");
out.println("");
out.println("Options:");
out.println(" -Xmsgs ");
out.println(" Same as -Xmsgs:all");
out.println(" -Xmsgs:values");
out.println(" Specify categories of issues to be checked, where 'values'");
out.println(" is a comma-separated list of any of the following:");
out.println(" reference show places where comments contain incorrect");
out.println(" references to Java source code elements");
out.println(" syntax show basic syntax errors within comments");
out.println(" html show issues with HTML tags and attributes");
out.println(" accessibility show issues for accessibility");
out.println(" missing show issues with missing documentation");
out.println(" all all of the above");
out.println(" Precede a value with '-' to negate it");
out.println(" Categories may be qualified by one of:");
out.println(" /public /protected /package /private");
out.println(" For positive categories (not beginning with '-')");
out.println(" the qualifier applies to that access level and above.");
out.println(" For negative categories (beginning with '-')");
out.println(" the qualifier applies to that access level and below.");
out.println(" If a qualifier is missing, the category applies to");
out.println(" all access levels.");
out.println(" For example, -Xmsgs:all,-syntax/private");
out.println(" This will enable all messages, except syntax errors");
out.println(" in the doc comments of private methods.");
out.println(" If no -Xmsgs options are provided, the default is");
out.println(" equivalent to -Xmsgs:all/protected, meaning that");
out.println(" all messages are reported for protected and public");
out.println(" declarations only. ");
out.println(" -h -help --help -usage -?");
out.println(" Show this message.");
out.println("");
out.println("The following javac options are also supported");
out.println(" -bootclasspath, -classpath, -sourcepath, -Xmaxerrs, -Xmaxwarns");
out.println("");
out.println("To run doclint on part of a project, put the compiled classes for your");
out.println("project on the classpath (or bootclasspath), then specify the source files");
out.println("to be checked on the command line.");
}
List<File> splitPath(String path) {
List<File> files = new ArrayList<File>();
for (String f: path.split(File.separator)) {
if (f.length() > 0)
files.add(new File(f));
}
return files;
}
List<File> javacBootClassPath;
List<File> javacClassPath;
List<File> javacSourcePath;
List<String> javacOpts;
List<File> javacFiles;
boolean needHelp = false;
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="javac Plugin">
@Override
public String getName() {
return "doclint";
}
@Override
public void call(JavacTask task, String... args) {
init(task, args, true);
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Embedding API">
public void init(JavacTask task, String[] args, boolean addTaskListener) {
env = new Env();
for (int i = 0; i < args.length; i++) {
String arg = args[i];
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
throw new IllegalArgumentException(arg);
}
env.init(task);
checker = new Checker(env);
if (addTaskListener) {
final DeclScanner ds = new DeclScanner() {
@Override
void visitDecl(Tree tree, Name name) {
TreePath p = getCurrentPath();
DocCommentTree dc = env.trees.getDocCommentTree(p);
checker.scan(dc, p);
}
};
TaskListener tl = new TaskListener() {
@Override
public void started(TaskEvent e) {
return;
}
@Override
public void finished(TaskEvent e) {
switch (e.getKind()) {
case ENTER:
ds.scan(e.getCompilationUnit(), null);
}
}
};
task.addTaskListener(tl);
}
}
public void scan(TreePath p) {
DocCommentTree dc = env.trees.getDocCommentTree(p);
checker.scan(dc, p);
}
public void reportStats(PrintWriter out) {
env.messages.reportStats(out);
}
// </editor-fold>
Env env;
Checker checker;
public static boolean isValidOption(String opt) {
if (opt.equals(XMSGS_OPTION))
return true;
if (opt.startsWith(XMSGS_CUSTOM_PREFIX))
return Messages.Options.isValidOptions(opt.substring(XMSGS_CUSTOM_PREFIX.length()));
return false;
}
// <editor-fold defaultstate="collapsed" desc="DeclScanner">
static abstract class DeclScanner extends TreePathScanner<Void, Void> {
abstract void visitDecl(Tree tree, Name name);
@Override
public Void visitClass(ClassTree tree, Void ignore) {
visitDecl(tree, tree.getSimpleName());
return super.visitClass(tree, ignore);
}
@Override
public Void visitMethod(MethodTree tree, Void ignore) {
visitDecl(tree, tree.getName());
//return super.visitMethod(tree, ignore);
return null;
}
@Override
public Void visitVariable(VariableTree tree, Void ignore) {
visitDecl(tree, tree.getName());
return super.visitVariable(tree, ignore);
}
}
// </editor-fold>
}
/*
* Copyright (c) 2012, 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.doclint;
import java.util.HashMap;
import java.util.Map;
/**
* Table of entities defined in HTML 4.01.
*
* <p> Derived from
* <a href="http://www.w3.org/TR/html4/sgml/entities.html">Character entity references in HTML 4</a>.
*
* The name of the member follows the name of the entity,
* except when it clashes with a keyword, in which case
* it is prefixed by '_'.
*
* <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></p>
*/
enum Entity {
nbsp(160),
iexcl(161),
cent(162),
pound(163),
curren(164),
yen(165),
brvbar(166),
sect(167),
uml(168),
copy(169),
ordf(170),
laquo(171),
not(172),
shy(173),
reg(174),
macr(175),
deg(176),
plusmn(177),
sup2(178),
sup3(179),
acute(180),
micro(181),
para(182),
middot(183),
cedil(184),
sup1(185),
ordm(186),
raquo(187),
frac14(188),
frac12(189),
frac34(190),
iquest(191),
Agrave(192),
Aacute(193),
Acirc(194),
Atilde(195),
Auml(196),
Aring(197),
AElig(198),
Ccedil(199),
Egrave(200),
Eacute(201),
Ecirc(202),
Euml(203),
Igrave(204),
Iacute(205),
Icirc(206),
Iuml(207),
ETH(208),
Ntilde(209),
Ograve(210),
Oacute(211),
Ocirc(212),
Otilde(213),
Ouml(214),
times(215),
Oslash(216),
Ugrave(217),
Uacute(218),
Ucirc(219),
Uuml(220),
Yacute(221),
THORN(222),
szlig(223),
agrave(224),
aacute(225),
acirc(226),
atilde(227),
auml(228),
aring(229),
aelig(230),
ccedil(231),
egrave(232),
eacute(233),
ecirc(234),
euml(235),
igrave(236),
iacute(237),
icirc(238),
iuml(239),
eth(240),
ntilde(241),
ograve(242),
oacute(243),
ocirc(244),
otilde(245),
ouml(246),
divide(247),
oslash(248),
ugrave(249),
uacute(250),
ucirc(251),
uuml(252),
yacute(253),
thorn(254),
yuml(255),
fnof(402),
Alpha(913),
Beta(914),
Gamma(915),
Delta(916),
Epsilon(917),
Zeta(918),
Eta(919),
Theta(920),
Iota(921),
Kappa(922),
Lambda(923),
Mu(924),
Nu(925),
Xi(926),
Omicron(927),
Pi(928),
Rho(929),
Sigma(931),
Tau(932),
Upsilon(933),
Phi(934),
Chi(935),
Psi(936),
Omega(937),
alpha(945),
beta(946),
gamma(947),
delta(948),
epsilon(949),
zeta(950),
eta(951),
theta(952),
iota(953),
kappa(954),
lambda(955),
mu(956),
nu(957),
xi(958),
omicron(959),
pi(960),
rho(961),
sigmaf(962),
sigma(963),
tau(964),
upsilon(965),
phi(966),
chi(967),
psi(968),
omega(969),
thetasym(977),
upsih(978),
piv(982),
bull(8226),
hellip(8230),
prime(8242),
Prime(8243),
oline(8254),
frasl(8260),
weierp(8472),
image(8465),
real(8476),
trade(8482),
alefsym(8501),
larr(8592),
uarr(8593),
rarr(8594),
darr(8595),
harr(8596),
crarr(8629),
lArr(8656),
uArr(8657),
rArr(8658),
dArr(8659),
hArr(8660),
forall(8704),
part(8706),
exist(8707),
empty(8709),
nabla(8711),
isin(8712),
notin(8713),
ni(8715),
prod(8719),
sum(8721),
minus(8722),
lowast(8727),
radic(8730),
prop(8733),
infin(8734),
ang(8736),
and(8743),
or(8744),
cap(8745),
cup(8746),
_int(8747),
there4(8756),
sim(8764),
cong(8773),
asymp(8776),
ne(8800),
equiv(8801),
le(8804),
ge(8805),
sub(8834),
sup(8835),
nsub(8836),
sube(8838),
supe(8839),
oplus(8853),
otimes(8855),
perp(8869),
sdot(8901),
lceil(8968),
rceil(8969),
lfloor(8970),
rfloor(8971),
lang(9001),
rang(9002),
loz(9674),
spades(9824),
clubs(9827),
hearts(9829),
diams(9830),
quot(34),
amp(38),
lt(60),
gt(62),
OElig(338),
oelig(339),
Scaron(352),
scaron(353),
Yuml(376),
circ(710),
tilde(732),
ensp(8194),
emsp(8195),
thinsp(8201),
zwnj(8204),
zwj(8205),
lrm(8206),
rlm(8207),
ndash(8211),
mdash(8212),
lsquo(8216),
rsquo(8217),
sbquo(8218),
ldquo(8220),
rdquo(8221),
bdquo(8222),
dagger(8224),
Dagger(8225),
permil(8240),
lsaquo(8249),
rsaquo(8250),
euro(8364);
int code;
private Entity(int code) {
this.code = code;
}
static boolean isValid(String name) {
return names.containsKey(name);
}
static boolean isValid(int code) {
// allow numeric codes for standard ANSI characters
return codes.containsKey(code) || ( 32 <= code && code < 2127);
}
private static final Map<String,Entity> names = new HashMap<String,Entity>();
private static final Map<Integer,Entity> codes = new HashMap<Integer,Entity>();
static {
for (Entity e: values()) {
String name = e.name();
int code = e.code;
if (name.startsWith("_")) name = name.substring(1);
names.put(name, e);
codes.put(code, e);
}
}
}
/*
* Copyright (c) 2012, 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.doclint;
import java.util.Set;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.util.DocTrees;
import com.sun.source.util.JavacTask;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.tree.JCTree;
/**
* Utility container for current execution environment,
* providing the current declaration and its doc comment.
*
* <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></p>
*/
public class Env {
/**
* Access kinds for declarations.
*/
public enum AccessKind {
PRIVATE,
PACKAGE,
PROTECTED,
PUBLIC;
static boolean accepts(String opt) {
for (AccessKind g: values())
if (opt.equals(g.name().toLowerCase())) return true;
return false;
}
static AccessKind of(Set<Modifier> mods) {
if (mods.contains(Modifier.PUBLIC))
return AccessKind.PUBLIC;
else if (mods.contains(Modifier.PROTECTED))
return AccessKind.PROTECTED;
else if (mods.contains(Modifier.PRIVATE))
return AccessKind.PRIVATE;
else
return AccessKind.PACKAGE;
}
};
/** Message handler. */
final Messages messages;
// Utility classes
DocTrees trees;
Elements elements;
Types types;
// Types used when analysing doc comments.
TypeMirror java_lang_Error;
TypeMirror java_lang_RuntimeException;
TypeMirror java_lang_Throwable;
TypeMirror java_lang_Void;
/** The path for the declaration containing the comment currently being analyzed. */
TreePath currPath;
/** The element for the declaration containing the comment currently being analyzed. */
Element currElement;
/** The comment current being analyzed. */
DocCommentTree currDocComment;
/**
* The access kind of the declaration containing the comment currently being analyzed.
* This is the minimum (most restrictive) access kind of the declaration iteself
* and that of its containers. For example, a public method in a private class is
* noted as private.
*/
AccessKind currAccess;
/** The set of methods, if any, that the current declaration overrides. */
Set<? extends ExecutableElement> currOverriddenMethods;
Env() {
messages = new Messages(this);
}
void init(JavacTask task) {
init(DocTrees.instance(task), task.getElements(), task.getTypes());
}
void init(DocTrees trees, Elements elements, Types types) {
this.trees = trees;
this.elements = elements;
this.types = types;
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();
java_lang_Void = elements.getTypeElement("java.lang.Void").asType();
}
/** Set the current declaration and its doc comment. */
void setCurrent(TreePath path, DocCommentTree comment) {
currPath = path;
currDocComment = comment;
currElement = trees.getElement(currPath);
currOverriddenMethods = ((JavacTypes) types).getOverriddenMethods(currElement);
AccessKind ak = null;
for (TreePath p = path; p != null; p = p.getParentPath()) {
Element e = trees.getElement(p);
if (e != null) {
ak = min(ak, AccessKind.of(e.getModifiers()));
}
}
currAccess = ak;
}
AccessKind getAccessKind() {
return currAccess;
}
long getPos(TreePath p) {
return ((JCTree) p.getLeaf()).pos;
}
long getStartPos(TreePath p) {
SourcePositions sp = trees.getSourcePositions();
return sp.getStartPosition(p.getCompilationUnit(), p.getLeaf());
}
private <T extends Comparable<T>> T min(T item1, T item2) {
return (item1 == null) ? item2
: (item2 == null) ? item1
: item1.compareTo(item2) <= 0 ? item1 : item2;
}
}
/*
* Copyright (c) 2010, 2012, 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.doclint;
import java.util.Set;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import javax.lang.model.element.Name;
import static com.sun.tools.doclint.HtmlTag.Attr.*;
/**
* Enum representing HTML tags.
*
* The intent of this class is to embody the semantics of W3C HTML 4.01
* to the extent supported/used by javadoc.
*
* This is derivative of com.sun.tools.doclets.formats.html.markup.HtmlTag.
* Eventually, these two should be merged back together, and possibly made
* public.
*
* @see <a href="http://www.w3.org/TR/REC-html40/">HTML 4.01 Specification</a>
* @author Bhavesh Patel
* @author Jonathan Gibbons (revised)
*/
public enum HtmlTag {
A(BlockType.INLINE, EndKind.REQUIRED,
attrs(AttrKind.OK, HREF, TARGET, NAME)),
B(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
BLOCKQUOTE,
BODY(BlockType.OTHER, EndKind.REQUIRED),
BR(BlockType.INLINE, EndKind.NONE,
attrs(AttrKind.USE_CSS, CLEAR)),
CAPTION(EnumSet.of(Flag.EXPECT_CONTENT)),
CENTER,
CITE(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
CODE(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
DD(BlockType.BLOCK, EndKind.OPTIONAL,
EnumSet.of(Flag.EXPECT_CONTENT)),
DIV,
DL(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.USE_CSS, COMPACT)),
DT(BlockType.BLOCK, EndKind.OPTIONAL,
EnumSet.of(Flag.EXPECT_CONTENT)),
EM(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.NO_NEST)),
FONT(BlockType.INLINE, EndKind.REQUIRED, // tag itself is deprecated
EnumSet.of(Flag.EXPECT_CONTENT),
attrs(AttrKind.USE_CSS, SIZE, COLOR, FACE)),
FRAME(BlockType.OTHER, EndKind.NONE),
FRAMESET(BlockType.OTHER, EndKind.REQUIRED),
H1,
H2,
H3,
H4,
H5,
H6,
HEAD(BlockType.OTHER, EndKind.REQUIRED),
HR(BlockType.BLOCK, EndKind.NONE),
HTML(BlockType.OTHER, EndKind.REQUIRED),
I(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
IMG(BlockType.INLINE, EndKind.NONE,
attrs(AttrKind.OK, SRC, ALT, HEIGHT, WIDTH),
attrs(AttrKind.OBSOLETE, NAME),
attrs(AttrKind.USE_CSS, ALIGN, HSPACE, VSPACE, BORDER)),
LI(BlockType.BLOCK, EndKind.OPTIONAL),
LINK(BlockType.OTHER, EndKind.NONE),
MENU,
META(BlockType.OTHER, EndKind.NONE),
NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
NOSCRIPT(BlockType.OTHER, EndKind.REQUIRED),
OL(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.USE_CSS, START, TYPE)),
P(BlockType.BLOCK, EndKind.OPTIONAL,
EnumSet.of(Flag.EXPECT_CONTENT),
attrs(AttrKind.USE_CSS, ALIGN)),
PRE(EnumSet.of(Flag.EXPECT_CONTENT)),
SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
SMALL(BlockType.INLINE, EndKind.REQUIRED),
SPAN(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT)),
STRONG(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT)),
SUB(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
SUP(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
TABLE(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
CELLPADDING, CELLSPACING),
attrs(AttrKind.USE_CSS, ALIGN, WIDTH, BGCOLOR)),
TBODY(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
TD(BlockType.BLOCK, EndKind.OPTIONAL,
attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
ALIGN, CHAR, CHAROFF, VALIGN),
attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
TFOOT(BlockType.BLOCK, EndKind.REQUIRED,
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
TH(BlockType.BLOCK, EndKind.OPTIONAL,
attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
ALIGN, CHAR, CHAROFF, VALIGN),
attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
THEAD(BlockType.BLOCK, EndKind.REQUIRED,
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
TITLE(BlockType.OTHER, EndKind.REQUIRED),
TR(BlockType.BLOCK, EndKind.OPTIONAL,
EnumSet.of(Flag.NO_TEXT),
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
attrs(AttrKind.USE_CSS, BGCOLOR)),
TT(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
U(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
UL(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.USE_CSS, COMPACT, TYPE)),
VAR(BlockType.INLINE, EndKind.REQUIRED);
/**
* Enum representing the type of HTML element.
*/
public static enum BlockType {
BLOCK,
INLINE,
OTHER;
}
/**
* Enum representing HTML end tag requirement.
*/
public static enum EndKind {
NONE,
OPTIONAL,
REQUIRED;
}
public static enum Flag {
EXPECT_CONTENT,
NO_NEST,
NO_TEXT
}
public static enum Attr {
ABBR,
ALIGN,
ALT,
AXIS,
BGCOLOR,
BORDER,
CELLSPACING,
CELLPADDING,
CHAR,
CHAROFF,
CLEAR,
CLASS,
COLOR,
COLSPAN,
COMPACT,
FACE,
FRAME,
HEADERS,
HEIGHT,
HREF,
HSPACE,
ID,
NAME,
NOWRAP,
REVERSED,
ROWSPAN,
RULES,
SCOPE,
SIZE,
SPACE,
SRC,
START,
STYLE,
SUMMARY,
TARGET,
TYPE,
VALIGN,
VSPACE,
WIDTH;
public String getText() {
return name().toLowerCase();
}
static final Map<String,Attr> index = new HashMap<String,Attr>();
static {
for (Attr t: values()) {
index.put(t.name().toLowerCase(), t);
}
}
}
public static enum AttrKind {
INVALID,
OBSOLETE,
USE_CSS,
OK
}
// This class exists to avoid warnings from using parameterized vararg type
// Map<Attr,AttrKind> in signature of HtmlTag constructor.
private static class AttrMap extends EnumMap<Attr,AttrKind> {
private static final long serialVersionUID = 0;
AttrMap() {
super(Attr.class);
}
}
public final BlockType blockType;
public final EndKind endKind;
public final Set<Flag> flags;
private final Map<Attr,AttrKind> attrs;
HtmlTag() {
this(BlockType.BLOCK, EndKind.REQUIRED);
}
HtmlTag(Set<Flag> flags) {
this(BlockType.BLOCK, EndKind.REQUIRED, flags);
}
HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
}
HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
this.blockType = blockType;
this.endKind = endKind;this.flags = flags;
this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
for (Map<Attr,AttrKind> m: attrMaps)
this.attrs.putAll(m);
attrs.put(Attr.CLASS, AttrKind.OK);
attrs.put(Attr.ID, AttrKind.OK);
attrs.put(Attr.STYLE, AttrKind.OK);
}
public String getText() {
return name().toLowerCase();
}
public Attr getAttr(Name attrName) {
return Attr.index.get(attrName.toString().toLowerCase());
}
public AttrKind getAttrKind(Name attrName) {
AttrKind k = attrs.get(getAttr(attrName)); // null-safe
return (k == null) ? AttrKind.INVALID : k;
}
private static AttrMap attrs(AttrKind k, Attr... attrs) {
AttrMap map = new AttrMap();
for (Attr a: attrs) map.put(a, k);
return map;
}
private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
static {
for (HtmlTag t: values()) {
index.put(t.name().toLowerCase(), t);
}
}
static HtmlTag get(Name tagName) {
return index.get(tagName.toString().toLowerCase());
}
}
/*
* Copyright (c) 2012, 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.doclint;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.tools.Diagnostic;
import com.sun.source.doctree.DocTree;
import com.sun.source.tree.Tree;
import com.sun.tools.doclint.Env.AccessKind;
/**
* Message reporting for DocLint.
*
* Options are used to filter out messages based on group and access level.
* Support can be enabled for accumulating statistics of different kinds of
* messages.
*
* <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></p>
*/
public class Messages {
/**
* Groups used to categorize messages, so that messages in each group
* can be enabled or disabled via options.
*/
public enum Group {
ACCESSIBILITY,
HTML,
MISSING,
SYNTAX,
REFERENCE;
String optName() { return name().toLowerCase(); }
String notOptName() { return "-" + optName(); }
static boolean accepts(String opt) {
for (Group g: values())
if (opt.equals(g.optName())) return true;
return false;
}
};
private final Options options;
private final Stats stats;
ResourceBundle bundle;
Env env;
Messages(Env env) {
this.env = env;
String name = getClass().getPackage().getName() + ".resources.doclint";
bundle = ResourceBundle.getBundle(name, Locale.ENGLISH);
stats = new Stats(bundle);
options = new Options(stats);
}
void error(Group group, DocTree tree, String code, Object... args) {
report(group, Diagnostic.Kind.ERROR, tree, code, args);
}
void warning(Group group, DocTree tree, String code, Object... args) {
report(group, Diagnostic.Kind.WARNING, tree, code, args);
}
void setOptions(String opts) {
options.setOptions(opts);
}
void setStatsEnabled(boolean b) {
stats.setEnabled(b);
}
void reportStats(PrintWriter out) {
stats.report(out);
}
protected void report(Group group, Diagnostic.Kind dkind, DocTree tree, String code, Object... args) {
if (options.isEnabled(group, env.currAccess)) {
String msg = (code == null) ? (String) args[0] : localize(code, args);
env.trees.printMessage(dkind, msg, tree,
env.currDocComment, env.currPath.getCompilationUnit());
stats.record(group, dkind, code);
}
}
protected void report(Group group, Diagnostic.Kind dkind, Tree tree, String code, Object... args) {
if (options.isEnabled(group, env.currAccess)) {
String msg = localize(code, args);
env.trees.printMessage(dkind, msg, tree, env.currPath.getCompilationUnit());
stats.record(group, dkind, code);
}
}
String localize(String code, Object... args) {
String msg = bundle.getString(code);
if (msg == null) {
StringBuilder sb = new StringBuilder();
sb.append("message file broken: code=").append(code);
if (args.length > 0) {
sb.append(" arguments={0}");
for (int i = 1; i < args.length; i++) {
sb.append(", {").append(i).append("}");
}
}
msg = sb.toString();
}
return MessageFormat.format(msg, args);
}
// <editor-fold defaultstate="collapsed" desc="Options">
/**
* Handler for (sub)options specific to message handling.
*/
static class Options {
Map<String, Env.AccessKind> map = new HashMap<String, Env.AccessKind>();
private final Stats stats;
static boolean isValidOptions(String opts) {
for (String opt: opts.split(",")) {
if (!isValidOption(opt.trim().toLowerCase()))
return false;
}
return true;
}
private static boolean isValidOption(String opt) {
if (opt.equals("none") || opt.equals(Stats.OPT))
return true;
int begin = opt.startsWith("-") ? 1 : 0;
int sep = opt.indexOf("/");
String grp = opt.substring(begin, (sep != -1) ? sep : opt.length());
return ((begin == 0 && grp.equals("all")) || Group.accepts(grp))
&& ((sep == -1) || AccessKind.accepts(opt.substring(sep + 1)));
}
Options(Stats stats) {
this.stats = stats;
}
/** Determine if a message group is enabled for a particular access level. */
boolean isEnabled(Group g, Env.AccessKind access) {
if (map.isEmpty())
map.put("all", Env.AccessKind.PROTECTED);
Env.AccessKind ak = map.get(g.optName());
if (ak != null && access.compareTo(ak) >= 0)
return true;
ak = map.get(ALL);
if (ak != null && access.compareTo(ak) >= 0) {
ak = map.get(g.notOptName());
if (ak == null || access.compareTo(ak) > 0) // note >, not >=
return true;
}
return false;
}
void setOptions(String opts) {
if (opts == null)
setOption(ALL, Env.AccessKind.PRIVATE);
else {
for (String opt: opts.split(","))
setOption(opt.trim().toLowerCase());
}
}
private void setOption(String arg) throws IllegalArgumentException {
if (arg.equals(Stats.OPT)) {
stats.setEnabled(true);
return;
}
int sep = arg.indexOf("/");
if (sep > 0) {
Env.AccessKind ak = Env.AccessKind.valueOf(arg.substring(sep + 1).toUpperCase());
setOption(arg.substring(0, sep), ak);
} else {
setOption(arg, null);
}
}
private void setOption(String opt, Env.AccessKind ak) {
map.put(opt, (ak != null) ? ak
: opt.startsWith("-") ? Env.AccessKind.PUBLIC : Env.AccessKind.PRIVATE);
}
private static final String ALL = "all";
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Statistics">
/**
* Optionally record statistics of different kinds of message.
*/
static class Stats {
public static final String OPT = "stats";
public static final String NO_CODE = "";
final ResourceBundle bundle;
// tables only initialized if enabled
int[] groupCounts;
int[] dkindCounts;
Map<String, Integer> codeCounts;
Stats(ResourceBundle bundle) {
this.bundle = bundle;
}
void setEnabled(boolean b) {
if (b) {
groupCounts = new int[Messages.Group.values().length];
dkindCounts = new int[Diagnostic.Kind.values().length];
codeCounts = new HashMap<String, Integer>();
} else {
groupCounts = null;
dkindCounts = null;
codeCounts = null;
}
}
void record(Messages.Group g, Diagnostic.Kind dkind, String code) {
if (codeCounts == null) {
return;
}
groupCounts[g.ordinal()]++;
dkindCounts[dkind.ordinal()]++;
if (code == null) {
code = NO_CODE;
}
Integer i = codeCounts.get(code);
codeCounts.put(code, (i == null) ? 1 : i + 1);
}
void report(PrintWriter out) {
if (codeCounts == null) {
return;
}
out.println("By group...");
Table groupTable = new Table();
for (Messages.Group g : Messages.Group.values()) {
groupTable.put(g.optName(), groupCounts[g.ordinal()]);
}
groupTable.print(out);
out.println();
out.println("By diagnostic kind...");
Table dkindTable = new Table();
for (Diagnostic.Kind k : Diagnostic.Kind.values()) {
dkindTable.put(k.toString().toLowerCase(), dkindCounts[k.ordinal()]);
}
dkindTable.print(out);
out.println();
out.println("By message kind...");
Table codeTable = new Table();
for (Map.Entry<String, Integer> e : codeCounts.entrySet()) {
String code = e.getKey();
String msg;
try {
msg = code.equals(NO_CODE) ? "OTHER" : bundle.getString(code);
} catch (MissingResourceException ex) {
msg = code;
}
codeTable.put(msg, e.getValue());
}
codeTable.print(out);
}
/**
* A table of (int, String) sorted by decreasing int.
*/
private static class Table {
private static final Comparator<Integer> DECREASING = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
};
private final TreeMap<Integer, Set<String>> map = new TreeMap<Integer, Set<String>>(DECREASING);
void put(String label, int n) {
if (n == 0) {
return;
}
Set<String> labels = map.get(n);
if (labels == null) {
map.put(n, labels = new TreeSet<String>());
}
labels.add(label);
}
void print(PrintWriter out) {
for (Map.Entry<Integer, Set<String>> e : map.entrySet()) {
int count = e.getKey();
Set<String> labels = e.getValue();
for (String label : labels) {
out.println(String.format("%6d: %s", count, label));
}
}
}
}
}
// </editor-fold>
}
#
# Copyright (c) 2012, 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.
#
dc.anchor.already.defined = anchor already defined: {0}
dc.attr.lacks.value = attribute lacks value
dc.attr.obsolete = attribute obsolete: {0}
dc.attr.obsolete.use.css = attribute obsolete, use CSS instead: {0}
dc.attr.repeated = repeated attribute: {0}
dc.attr.unknown = unknown attribute: {0}
dc.bad.option = bad option: {0}
dc.bad.value.for.option = bad value for option: {0} {1}
dc.empty = no description for @{0}
dc.entity.invalid = invalid entity &{0};
dc.exception.not.thrown = exception not thrown: {0}
dc.invalid.anchor = invalid name for anchor: "{0}"
dc.invalid.param = invalid use of @param
dc.invalid.return = invalid use of @return
dc.invalid.throws = invalid use of @throws
dc.invalid.uri = invalid uri: "{0}"
dc.missing.comment = no comment
dc.missing.param = no @param for {0}
dc.missing.return = no @return
dc.missing.throws = no @throws for {0}
dc.no.alt.attr.for.image = no "alt" attribute for image
dc.no.summary.or.caption.for.table=no summary or caption for table
dc.param.name.not.found = @param name not found
dc.ref.not.found = reference not found
dc.tag.empty = empty <{0}> tag
dc.tag.end.not.permitted = invalid end tag: </{0}>
dc.tag.end.unexpected = unexpected end tag: </{0}>
dc.tag.header.sequence.1 = header used out of sequence: <{0}>
dc.tag.header.sequence.2 = header used out of sequence: <{0}>
dc.tag.nested.not.allowed=nested tag not allowed: <{0}>
dc.tag.not.allowed = element not allowed in documentation comments: <{0}>
dc.tag.not.allowed.inline.element = block element not allowed within inline element <{1}>: {0}
dc.tag.not.allowed.inline.tag = block element not allowed within @{1}: {0}
dc.tag.not.allowed.inline.other = block element not allowed here: {0}
dc.tag.not.closed= element not closed: {0}
dc.tag.p.in.pre= unexpected use of <p> inside <pre> element
dc.tag.self.closing = self-closing element not allowed
dc.tag.start.unmatched = end tag missing: </{0}>
dc.tag.unknown = unknown tag: {0}
dc.text.not.allowed = text not allowed in <{0}> element
......@@ -57,6 +57,13 @@ public class BasicJavacTask extends JavacTask {
protected Context context;
private TaskListener taskListener;
public static JavacTask instance(Context context) {
JavacTask instance = context.get(JavacTask.class);
if (instance == null)
instance = new BasicJavacTask(context, true);
return instance;
}
public BasicJavacTask(Context c, boolean register) {
context = c;
if (register)
......
......@@ -65,7 +65,6 @@ import com.sun.tools.javac.util.List;
* @author Jonathan Gibbons
*/
public class JavacTaskImpl extends BasicJavacTask {
private ClientCodeWrapper ccw;
private Main compilerMain;
private JavaCompiler compiler;
private Locale locale;
......@@ -85,7 +84,6 @@ public class JavacTaskImpl extends BasicJavacTask {
Context context,
List<JavaFileObject> fileObjects) {
super(null, false);
this.ccw = ClientCodeWrapper.instance(context);
this.compilerMain = compilerMain;
this.args = args;
this.classNames = classNames;
......
......@@ -84,6 +84,7 @@ import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.TreeCopier;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Abort;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic;
......@@ -236,19 +237,26 @@ public class JavacTrees extends DocTrees {
public Element getElement(TreePath path) {
JCTree tree = (JCTree) path.getLeaf();
Symbol sym = TreeInfo.symbolFor(tree);
if (sym == null && TreeInfo.isDeclaration(tree)) {
for (TreePath p = path; p != null; p = p.getParentPath()) {
JCTree t = (JCTree) p.getLeaf();
if (t.hasTag(JCTree.Tag.CLASSDEF)) {
JCClassDecl ct = (JCClassDecl) t;
if (ct.sym != null) {
if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
attr.attribClass(ct.pos(), ct.sym);
sym = TreeInfo.symbolFor(tree);
if (sym == null) {
if (TreeInfo.isDeclaration(tree)) {
for (TreePath p = path; p != null; p = p.getParentPath()) {
JCTree t = (JCTree) p.getLeaf();
if (t.hasTag(JCTree.Tag.CLASSDEF)) {
JCClassDecl ct = (JCClassDecl) t;
if (ct.sym != null) {
if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
attr.attribClass(ct.pos(), ct.sym);
sym = TreeInfo.symbolFor(tree);
}
break;
}
break;
}
}
} else if (tree.hasTag(Tag.TOPLEVEL)) {
JCCompilationUnit cu = (JCCompilationUnit) tree;
if (cu.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE)) {
sym = cu.packge;
}
}
}
return sym;
......@@ -332,6 +340,8 @@ public class JavacTrees extends DocTrees {
} else {
return msym;
}
} catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
return null;
} finally {
log.popDiagnosticHandler(deferredDiagnosticHandler);
}
......
......@@ -1675,7 +1675,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
/** Print numbers of errors and warnings.
*/
protected void printCount(String kind, int count) {
public void printCount(String kind, int count) {
if (count != 0) {
String key;
if (count == 1)
......
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, 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
......@@ -25,11 +25,16 @@
package com.sun.tools.javac.model;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.EnumSet;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.util.*;
......@@ -301,4 +306,31 @@ public class JavacTypes implements javax.lang.model.util.Types {
throw new IllegalArgumentException(o.toString());
return clazz.cast(o);
}
public Set<MethodSymbol> getOverriddenMethods(Element elem) {
if (elem.getKind() != ElementKind.METHOD
|| elem.getModifiers().contains(Modifier.STATIC)
|| elem.getModifiers().contains(Modifier.PRIVATE))
return Collections.emptySet();
if (!(elem instanceof MethodSymbol))
throw new IllegalArgumentException();
MethodSymbol m = (MethodSymbol) elem;
ClassSymbol origin = (ClassSymbol) m.owner;
Set<MethodSymbol> results = new LinkedHashSet<MethodSymbol>();
for (Type t : types.closure(origin.type)) {
if (t != origin.type) {
ClassSymbol c = (ClassSymbol) t.tsym;
for (Scope.Entry e = c.members().lookup(m.name); e.scope != null; e = e.next()) {
if (e.sym.kind == Kinds.MTH && m.overrides(e.sym, origin, types, true)) {
results.add((MethodSymbol) e.sym);
}
}
}
}
return results;
}
}
......@@ -25,15 +25,12 @@
package com.sun.tools.javac.parser;
import com.sun.tools.javac.util.Filter;
import java.text.BreakIterator;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import com.sun.source.doctree.AttributeTree.ValueKind;
......@@ -52,7 +49,6 @@ import com.sun.tools.javac.tree.DCTree.DCText;
import com.sun.tools.javac.tree.DocTreeMaker;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.DiagnosticSource;
import com.sun.tools.javac.util.JCDiagnostic;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
......@@ -736,7 +732,9 @@ public class DocCommentParser {
nextChar();
return m.at(p).Entity(names.fromChars(buf, namep, bp - namep - 1));
} else {
String code = checkSemi ? "dc.missing.semicolon" : "dc.bad.entity";
String code = checkSemi
? "dc.missing.semicolon"
: "dc.bad.entity";
return erroneous(code, p);
}
}
......@@ -888,8 +886,10 @@ public class DocCommentParser {
}
protected void addPendingText(ListBuffer<DCTree> list, int textEnd) {
if (textStart != -1 && textStart <= textEnd) {
list.add(m.at(textStart).Text(newString(textStart, textEnd + 1)));
if (textStart != -1) {
if (textStart <= textEnd) {
list.add(m.at(textStart).Text(newString(textStart, textEnd + 1)));
}
textStart = -1;
}
}
......@@ -1196,6 +1196,16 @@ public class DocCommentParser {
return m.at(pos).See(html);
break;
case '@':
if (newline)
throw new ParseException("dc.no.content");
break;
case EOI:
if (bp == buf.length - 1)
throw new ParseException("dc.no.content");
break;
default:
if (isJavaIdentifierStart(ch) || ch == '#') {
DCReference ref = reference(true);
......
......@@ -2364,6 +2364,9 @@ compiler.err.dc.malformed.html=\
compiler.err.dc.missing.semicolon=\
semicolon missing
compiler.err.dc.no.content=\
no content
compiler.err.dc.no.tag.name=\
no tag name after '@'
......
......@@ -36,6 +36,8 @@ import com.sun.tools.javac.util.JCDiagnostic;
import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
import java.io.IOException;
import java.io.StringWriter;
import javax.tools.JavaFileObject;
/**
......@@ -65,6 +67,21 @@ public abstract class DCTree implements DocTree {
return new SimpleDiagnosticPosition(dc.comment.getSourcePos(pos));
}
/** Convert a tree to a pretty-printed string. */
@Override
public String toString() {
StringWriter s = new StringWriter();
try {
new DocPretty(s).print(this);
}
catch (IOException e) {
// should never happen, because StringWriter is defined
// never to throw any IOExceptions
throw new AssertionError(e);
}
return s.toString();
}
public static class DCDocComment extends DCTree implements DocCommentTree {
final Comment comment; // required for the implicit source pos table
......
......@@ -81,7 +81,7 @@ public class DocPretty implements DocTreeVisitor<Void,Void> {
/**
* Print list.
*/
protected void print(List<? extends DocTree> list) throws IOException {
public void print(List<? extends DocTree> list) throws IOException {
for (DocTree t: list) {
print(t);
}
......
......@@ -26,6 +26,7 @@
package com.sun.tools.javac.tree;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.comp.AttrContext;
......@@ -330,6 +331,13 @@ public class TreeInfo {
return (docComments == null) ? null : docComments.getCommentText(tree);
}
public static DCTree.DCDocComment getCommentTree(Env<?> env, JCTree tree) {
DocCommentTable docComments = (tree.hasTag(JCTree.Tag.TOPLEVEL))
? ((JCCompilationUnit) tree).docComments
: env.toplevel.docComments;
return (docComments == null) ? null : docComments.getCommentTree(tree);
}
/** The position of the first statement in a block, or the position of
* the block itself if it is empty.
*/
......
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -ref AccessTest.protected.out AccessTest.java
* @run main DocLintTester -Xmsgs -ref AccessTest.private.out AccessTest.java
* @run main DocLintTester -Xmsgs:syntax -ref AccessTest.private.out AccessTest.java
* @run main DocLintTester -Xmsgs:syntax/public -ref AccessTest.public.out AccessTest.java
* @run main DocLintTester -Xmsgs:syntax/protected -ref AccessTest.protected.out AccessTest.java
* @run main DocLintTester -Xmsgs:syntax/package -ref AccessTest.package.out AccessTest.java
* @run main DocLintTester -Xmsgs:syntax/private -ref AccessTest.private.out AccessTest.java
* @run main DocLintTester -Xmsgs:all,-syntax AccessTest.java
* @run main DocLintTester -Xmsgs:all,-syntax/public AccessTest.java
* @run main DocLintTester -Xmsgs:all,-syntax/protected -ref AccessTest.public.out AccessTest.java
* @run main DocLintTester -Xmsgs:all,-syntax/package -ref AccessTest.protected.out AccessTest.java
* @run main DocLintTester -Xmsgs:all,-syntax/private -ref AccessTest.package.out AccessTest.java
*/
/** */
public class AccessTest {
/**
* public a < b
*/
public void public_syntax_error() { }
/**
* protected a < b
*/
protected void protected_syntax_error() { }
/**
* package-private a < b
*/
void syntax_error() { }
/**
* private a < b
*/
private void private_syntax_error() { }
}
/** */
class AccessTest2 {
/**
* public a < b
*/
public void public_syntax_error() { }
/**
* protected a < b
*/
protected void protected_syntax_error() { }
/**
* package-private a < b
*/
void syntax_error() { }
/**
* private a < b
*/
private void private_syntax_error() { }
}
AccessTest.java:21: error: malformed HTML
* public a < b
^
AccessTest.java:26: error: malformed HTML
* protected a < b
^
AccessTest.java:31: error: malformed HTML
* package-private a < b
^
AccessTest.java:44: error: malformed HTML
* public a < b
^
AccessTest.java:49: error: malformed HTML
* protected a < b
^
AccessTest.java:54: error: malformed HTML
* package-private a < b
^
6 errors
AccessTest.java:21: error: malformed HTML
* public a < b
^
AccessTest.java:26: error: malformed HTML
* protected a < b
^
AccessTest.java:31: error: malformed HTML
* package-private a < b
^
AccessTest.java:36: error: malformed HTML
* private a < b
^
AccessTest.java:44: error: malformed HTML
* public a < b
^
AccessTest.java:49: error: malformed HTML
* protected a < b
^
AccessTest.java:54: error: malformed HTML
* package-private a < b
^
AccessTest.java:59: error: malformed HTML
* private a < b
^
8 errors
AccessTest.java:21: error: malformed HTML
* public a < b
^
AccessTest.java:26: error: malformed HTML
* protected a < b
^
2 errors
AccessTest.java:21: error: malformed HTML
* public a < b
^
1 error
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-accessibility AccessibilityTest.java
* @run main DocLintTester -ref AccessibilityTest.out AccessibilityTest.java
*/
/** */
public class AccessibilityTest {
/**
* <h2> ... </h2>
*/
public void missing_h1() { }
/**
* <h1> ... </h1>
* <h3> ... </h3>
*/
public void missing_h2() { }
/**
* <img src="x.jpg">
*/
public void missing_alt() { }
/**
* <table summary="ok"><tr><th>head<tr><td>data</table>
*/
public void table_with_summary() { }
/**
* <table><caption>ok</caption><tr><th>head<tr><td>data</table>
*/
public void table_with_caption() { }
/**
* <table><tr><th>head<tr><td>data</table>
*/
public void table_without_summary_and_caption() { }
}
AccessibilityTest.java:12: error: header used out of sequence: <H2>
* <h2> ... </h2>
^
AccessibilityTest.java:18: error: header used out of sequence: <H3>
* <h3> ... </h3>
^
AccessibilityTest.java:23: error: no "alt" attribute for image
* <img src="x.jpg">
^
AccessibilityTest.java:38: error: no summary or caption for table
* <table><tr><th>head<tr><td>data</table>
^
4 errors
/*
* Copyright (c) 2012, 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.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.sun.tools.doclint.DocLint;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DocLintTester {
public static void main(String... args) throws Exception {
new DocLintTester().run(args);
}
public void run(String... args) throws Exception {
String testSrc = System.getProperty("test.src");
File refFile = null;
List<String> opts = new ArrayList<String>();
List<File> files = new ArrayList<File>();
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.equals("-ref")) {
refFile = new File(testSrc, args[++i]);
} else if (arg.startsWith("-Xmsgs")) {
opts.add(arg);
} else
files.add(new File(testSrc, arg));
}
check(opts, files, refFile);
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
void check(List<String> opts, List<File> files, File refFile) throws Exception {
List<String> args = new ArrayList<String>();
args.addAll(opts);
for (File file: files)
args.add(file.getPath());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
new DocLint().run(pw, args.toArray(new String[args.size()]));
pw.flush();
String out = normalizeNewlines(removeFileNames(sw.toString())).trim();
if (out != null)
System.err.println("Output:\n" + out);
if (refFile == null) {
if (!out.isEmpty())
error("unexpected output");
} else {
String expect = readFile(refFile);
if (!expect.equals(out)) {
error("expected output not found");
System.err.println("EXPECT>>" + expect + "<<");
System.err.println(" FOUND>>" + out + "<<");
}
}
}
String readFile(File file) throws IOException {
StringBuilder sb = new StringBuilder();
Reader in = new BufferedReader(new FileReader(file));
try {
char[] buf = new char[1024];
int n;
while ((n = in.read(buf)) != -1)
sb.append(buf, 0, n);
} finally {
in.close();
}
return sb.toString().trim();
}
private static final Pattern dirFileLine = Pattern.compile(
"(?m)" // multi-line mode
+ "^([^: ]+?)" // directory part of file name
+ "([A-Za-z0-9.]+:[0-9]+:)"); // file name and line number
String removeFileNames(String s) {
Matcher m = dirFileLine.matcher(s);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "$2");
}
m.appendTail(sb);
return sb.toString();
}
private static final String nl = System.getProperty("line.separator");
String normalizeNewlines(String s) {
return (nl.equals("\n") ? s : s.replace(nl, "\n"));
}
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
int errors;
}
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyAuthorTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyAuthorTest.out EmptyAuthorTest.java
*/
/** @author */
public class EmptyAuthorTest {
}
EmptyAuthorTest.java:8: warning: no description for @author
/** @author */
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyExceptionTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyExceptionTest.out EmptyExceptionTest.java
*/
/** . */
public class EmptyExceptionTest {
/** @exception NullPointerException */
int emptyException() throws NullPointerException { }
}
EmptyExceptionTest.java:10: warning: no description for @exception
/** @exception NullPointerException */
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyParamTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyParamTest.out EmptyParamTest.java
*/
/** . */
public class EmptyParamTest {
/** @param i */
int emptyParam(int i) { }
}
EmptyParamTest.java:10: warning: no description for @param
/** @param i */
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyReturnTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyReturnTest.out EmptyReturnTest.java
*/
/** . */
public class EmptyReturnTest {
/** @return */
int emptyReturn() { }
}
EmptyReturnTest.java:10: warning: no description for @return
/** @return */
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptySerialDataTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptySerialDataTest.out EmptySerialDataTest.java
*/
import java.io.ObjectOutputStream;
import java.io.Serializable;
/** . */
public class EmptySerialDataTest implements Serializable {
/** @serialData */
private void writeObject(ObjectOutputStream s) { }
}
EmptySerialDataTest.java:13: warning: no description for @serialData
/** @serialData */
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptySerialFieldTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptySerialFieldTest.out EmptySerialFieldTest.java
*/
import java.io.ObjectStreamField;
import java.io.Serializable;
/** . */
public class EmptySerialFieldTest implements Serializable {
/**
* @serialField empty String
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("empty", String.class),
};
}
EmptySerialFieldTest.java:15: warning: no description for @serialField
* @serialField empty String
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptySinceTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptySinceTest.out EmptySinceTest.java
*/
/** . */
public class EmptySinceTest {
/** @since */
int emptySince() { }
}
EmptySinceTest.java:10: warning: no description for @since
/** @since */
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyVersionTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyVersionTest.out EmptyVersionTest.java
*/
/** . */
public class EmptyVersionTest {
/** @version */
int missingVersion() { }
}
EmptyVersionTest.java:10: warning: no description for @version
/** @version */
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-html HtmlAttrsTest.java
* @run main DocLintTester -ref HtmlAttrsTest.out HtmlAttrsTest.java
*/
/** */
public class HtmlAttrsTest {
/**
* <p xyz>
*/
public void unknown() { }
/**
* <img name="x" alt="alt">
*/
public void obsolete() { }
/**
* <font size="3"> text </font>
*/
public void obsolete_use_css() { }
}
HtmlAttrsTest.java:11: error: unknown attribute: xyz
* <p xyz>
^
HtmlAttrsTest.java:16: warning: attribute obsolete: name
* <img name="x" alt="alt">
^
HtmlAttrsTest.java:21: warning: attribute obsolete, use CSS instead: size
* <font size="3"> text </font>
^
1 error
2 warnings
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-html HtmlTagsTest.java
* @run main DocLintTester -ref HtmlTagsTest.out HtmlTagsTest.java
*/
/** */
public class HtmlTagsTest {
/**
* <xyz> ... </xyz>
*/
public void unknownTag1() { }
/**
* <div> <xyz> </div>
*/
public void unknownTag2() { }
/**
* <br/>
*/
public void selfClosingTag() { }
/**
* <html>
*/
public void not_allowed() { }
/**
* <span> <p> </span>
*/
public void not_allowed_inline() { }
/**
* {@link java.lang.String <p> }
* {@link java.lang.String <p> }
*/
public void not_allowed_inline_2() { }
/**
* <img src="any.jpg" alt="alt"> </img>
*/
public void end_not_allowed() { }
/**
* <i> <b> </i>
*/
public void start_not_matched() { }
/**
* <i> </b> </i>
*/
public void end_unexpected() { }
}
HtmlTagsTest.java:11: error: unknown tag: xyz
* <xyz> ... </xyz>
^
HtmlTagsTest.java:11: error: unknown tag: xyz
* <xyz> ... </xyz>
^
HtmlTagsTest.java:16: error: unknown tag: xyz
* <div> <xyz> </div>
^
HtmlTagsTest.java:21: error: self-closing element not allowed
* <br/>
^
HtmlTagsTest.java:26: error: element not allowed in documentation comments: <html>
* <html>
^
HtmlTagsTest.java:31: error: block element not allowed within inline element <span>: p
* <span> <p> </span>
^
HtmlTagsTest.java:36: error: block element not allowed within @link: p
* {@link java.lang.String <p> }
^
HtmlTagsTest.java:37: error: block element not allowed within @link: p
* {@link java.lang.String <p> }
^
HtmlTagsTest.java:42: error: invalid end tag: </img>
* <img src="any.jpg" alt="alt"> </img>
^
HtmlTagsTest.java:47: error: end tag missing: </b>
* <i> <b> </i>
^
HtmlTagsTest.java:52: error: unexpected end tag: </b>
* <i> </b> </i>
^
HtmlTagsTest.java:52: warning: empty <i> tag
* <i> </b> </i>
^
11 errors
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-missing MissingCommentTest.java
* @run main DocLintTester -Xmsgs:missing -ref MissingCommentTest.out MissingCommentTest.java
*/
public class MissingCommentTest {
MissingCommentTest() { }
int missingComment;
void missingComment() { }
}
MissingCommentTest.java:8: warning: no comment
public class MissingCommentTest {
^
MissingCommentTest.java:9: warning: no comment
MissingCommentTest() { }
^
MissingCommentTest.java:11: warning: no comment
int missingComment;
^
MissingCommentTest.java:13: warning: no comment
void missingComment() { }
^
4 warnings
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-missing MissingParamsTest.java
* @run main DocLintTester -Xmsgs:missing -ref MissingParamsTest.out MissingParamsTest.java
*/
/** . */
public class MissingParamsTest {
/** */
MissingParamsTest(int param) { }
/** */
<T> MissingParamsTest() { }
/** */
void missingParam(int param) { }
/** */
<T> void missingTyparam() { }
}
MissingParamsTest.java:11: warning: no @param for param
MissingParamsTest(int param) { }
^
MissingParamsTest.java:14: warning: no @param for <T>
<T> MissingParamsTest() { }
^
MissingParamsTest.java:17: warning: no @param for param
void missingParam(int param) { }
^
MissingParamsTest.java:20: warning: no @param for <T>
<T> void missingTyparam() { }
^
4 warnings
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-missing MissingReturnTest.java
* @run main DocLintTester -Xmsgs:missing -ref MissingReturnTest.out MissingReturnTest.java
*/
/** . */
public class MissingReturnTest {
/** no return allowed */
MissingReturnTest() { }
/** no return allowed */
void return_void() { }
/** no return required */
Void return_Void() { }
/** */
int missingReturn() { }
}
MissingReturnTest.java:20: warning: no @return
int missingReturn() { }
^
1 warning
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-missing MissingThrowsTest.java
* @run main DocLintTester -Xmsgs:missing -ref MissingThrowsTest.out MissingThrowsTest.java
*/
/** */
public class MissingThrowsTest {
/** */
void missingThrows() throws Exception { }
}
MissingThrowsTest.java:11: warning: no @throws for java.lang.Exception
void missingThrows() throws Exception { }
^
1 warning
import com.sun.tools.doclint.DocLint;
/*
* Copyright (c) 2012, 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
*/
public class OptionTest {
public static void main(String... args) throws Exception {
new OptionTest().run();
}
String[] positiveTests = {
"-Xmsgs",
"-Xmsgs:all",
"-Xmsgs:none",
"-Xmsgs:accessibility",
"-Xmsgs:html",
"-Xmsgs:missing",
"-Xmsgs:reference",
"-Xmsgs:syntax",
"-Xmsgs:html/public",
"-Xmsgs:html/protected",
"-Xmsgs:html/package",
"-Xmsgs:html/private",
"-Xmsgs:-html/public",
"-Xmsgs:-html/protected",
"-Xmsgs:-html/package",
"-Xmsgs:-html/private",
"-Xmsgs:html,syntax",
"-Xmsgs:html,-syntax",
"-Xmsgs:-html,syntax",
"-Xmsgs:-html,-syntax",
"-Xmsgs:html/public,syntax",
"-Xmsgs:html,syntax/public",
"-Xmsgs:-html/public,syntax/public"
};
String[] negativeTests = {
"-typo",
"-Xmsgs:-all",
"-Xmsgs:-none",
"-Xmsgs:typo",
"-Xmsgs:html/typo",
"-Xmsgs:html/public,typo",
"-Xmsgs:html/public,syntax/typo",
};
void run() throws Exception {
test(positiveTests, true);
test(negativeTests, false);
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
void test(String[] tests, boolean expect) {
for (String test: tests) {
System.err.println("test: " + test);
boolean found = DocLint.isValidOption(test);
if (found != expect)
error("Unexpected result: " + found + ",expected: " + expect);
}
}
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
int errors;
}
/*
* Copyright (c) 2012, 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
* @build DocLintTester
* @run main DocLintTester -Xmsgs:all OverridesTest.java
*/
/*
* This is a test that missing comments on methods may be inherited
* from overridden methods. As such, there should be no errors due
* to missing comments (or any other types of error) in this test.
*/
/** An interface. */
interface I1 {
/**
* A method
* @param p a param
* @throws Exception an exception
* @return an int
*/
int m(int p) throws Exception;
}
/** An extending interface. */
interface I2 extends I1 { }
/** An abstract class. */
abstract class C1 {
/**
* A method
* @param p a param
* @throws Exception an exception
* @return an int
*/
int m(int p) throws Exception;
}
/** An implementing class. */
class C2 implements I1 {
int m(int p) throws Exception { return p; }
}
/** An extending class. */
class C3 extends C1 {
int m(int p) throws Exception { return p; }
}
/** An extending and implementing class. */
class C4 extends C1 implements I1 {
int m(int p) throws Exception { return p; }
}
/** An implementing class using inheritdoc. */
class C5 implements I1 {
/** {@inheritDoc} */
int m(int p) throws Exception { return p; }
}
/** An implementing class with incomplete documentation. */
class C6 implements I1 {
/** Overriding method */
int m(int p) throws Exception { return p; }
}
/** A class implementing an inherited interface. */
class C7 implements I2 {
int m(int p) throws Exception { return p; }
}
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-reference ReferenceTest.java
* @run main DocLintTester -ref ReferenceTest.out ReferenceTest.java
*/
/** */
public class ReferenceTest {
/**
* @param x description
*/
public int invalid_param;
/**
* @param x description
*/
public class InvalidParam { }
/**
* @param x description
*/
public void param_name_not_found(int a) { }
/**
* @param <X> description
*/
public class typaram_name_not_found { }
/**
* @see Object#tooStrong()
*/
public void ref_not_found() { }
/**
* @return x description
*/
public int invalid_return;
/**
* @return x description
*/
public void invalid_return();
/**
* @throws Exception description
*/
public void exception_not_thrown() { }
}
ReferenceTest.java:11: error: invalid use of @param
* @param x description
^
ReferenceTest.java:16: error: invalid use of @param
* @param x description
^
ReferenceTest.java:21: error: @param name not found
* @param x description
^
ReferenceTest.java:23: warning: no @param for a
public void param_name_not_found(int a) { }
^
ReferenceTest.java:26: error: @param name not found
* @param <X> description
^
ReferenceTest.java:31: error: reference not found
* @see Object#tooStrong()
^
ReferenceTest.java:36: error: invalid use of @return
* @return x description
^
ReferenceTest.java:41: error: invalid use of @return
* @return x description
^
ReferenceTest.java:46: error: exception not thrown: java.lang.Exception
* @throws Exception description
^
8 errors
1 warning
/*
* Copyright (c) 2012, 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 8000103
* @summary Create doclint utility
*/
import com.sun.tools.doclint.DocLint;
import com.sun.tools.doclint.DocLint.BadArgs;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/** javadoc error on toplevel: a & b. */
public class RunTest {
/** javadoc error on member: a < b */
public static void main(String... args) throws Exception {
new RunTest().run();
}
File testSrc = new File(System.getProperty("test.src"));
File thisFile = new File(testSrc, RunTest.class.getSimpleName() + ".java");
void run() throws Exception {
for (Method m: getClass().getDeclaredMethods()) {
Annotation a = m.getAnnotation(Test.class);
if (a != null) {
System.err.println("test: " + m.getName());
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);;
m.invoke(this, new Object[] { pw });
String out = sw.toString();
System.err.println(">>> " + out.replace("\n", "\n>>> "));
if (!out.contains("a < b"))
error("\"a < b\" not found");
if (!out.contains("a & b"))
error("\"a & b\" not found");
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
throw (cause instanceof Exception) ? ((Exception) cause) : e;
}
System.err.println();
}
}
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
int errors;
/** Marker annotation for test cases. */
@Retention(RetentionPolicy.RUNTIME)
@interface Test { }
@Test
void testMain(PrintWriter pw) throws BadArgs, IOException {
String[] args = { "-Xmsgs", thisFile.getPath() };
DocLint d = new DocLint();
d.run(pw, args);
}
}
/*
* @test /nodynamiccopyright/
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax SyntaxTest.java
* @run main DocLintTester -ref SyntaxTest.out SyntaxTest.java
*/
/** */
public class SyntaxTest {
/**
* a < b
*/
public void syntax_error() { }
}
SyntaxTest.java:11: error: malformed HTML
* a < b
^
1 error
/*
* Copyright (c) 2012, 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
* @build DocLintTester
* @run main DocLintTester -Xmsgs:all SyntheticTest.java
*/
/**
* This is a test that messages are not generated for synthesized elements
* such as default constructors and enum methods.
*/
public class SyntheticTest {
// No explicit constructor implies a default constructor
/** enum E */
enum E {
/** enum member E1 */
E1,
/** enum member E2 */
E2,
/** enum member E3 */
E3
}
}
/*
* Copyright (c) 2012, 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
* @build DocLintTester
* @run main DocLintTester ValidTest.java
*/
class ValidTest {
/**
* &lt; &gt; &amp; &#40;
*/
void entities() { }
/**
* <h1> ... </h1>
* <h2> ... </h2>
* <h3> ... </h3>
* <h4> ... </h4>
* <h5> ... </h5>
* <h6> ... </h6>
*/
void all_headers() { }
/**
* <h1> ... </h1>
* <h2> ... </h2>
* <h3> ... </h3>
* <h1> ... </h1>
* <h2> ... </h2>
* <h3> ... </h3>
* <h2> ... </h2>
*/
void header_series() { }
/**
* <div> <p> </div>
*/
void autoclose_tags() { }
/**
* @param x
*/
void method_param(int x) { }
/**
* @param <T>
*/
<T> T method_typaram(T t) { return t; }
/**
* @param <T>
*/
class ClassTyparam<T> { }
/**
* @param <T>
*/
interface InterfaceTyparam<T> { }
/**
* @return x
*/
int return_int() { return 0; }
/**
* @exception Exception
*/
void throws_Exception1() throws Exception { }
/**
* @throws Exception
*/
void throws_Exception2() throws Exception { }
class X {
/**
* @param x
*/
X(int x) { } // constructor parameter
/**
* @param <T>
*/
<T> X(T t) { } // constructor type parameter
}
}
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref AnchorAlreadyDefined.out AnchorAlreadyDefined.java
*/
// tidy: Warning: <.*> anchor ".*" already defined
/**
* <a name="here">valid</a>
* <a name="here">duplicate</a>
* <h1 id="here">duplicate</h1>
*/
public class AnchorAlreadyDefined { }
AnchorAlreadyDefined.java:12: error: anchor already defined: here
* <a name="here">duplicate</a>
^
AnchorAlreadyDefined.java:13: error: anchor already defined: here
* <h1 id="here">duplicate</h1>
^
2 errors
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref BadEnd.out BadEnd.java
*/
// tidy: Warning: <.*> is probably intended as </.*>
/**
* <a name="here"> text <a>
* <code> text <code>
*/
public class BadEnd { }
BadEnd.java:12: warning: nested tag not allowed: <code>
* <code> text <code>
^
BadEnd.java:12: error: element not closed: code
* <code> text <code>
^
BadEnd.java:12: error: element not closed: code
* <code> text <code>
^
BadEnd.java:11: error: element not closed: a
* <a name="here"> text <a>
^
BadEnd.java:11: error: element not closed: a
* <a name="here"> text <a>
^
4 errors
1 warning
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref InsertImplicit.out InsertImplicit.java
*/
// tidy: Warning: inserting implicit <.*>
/**
* </p>
* <i> <blockquote> abc </blockquote> </i>
*/
public class InsertImplicit { }
InsertImplicit.java:11: error: unexpected end tag: </p>
* </p>
^
InsertImplicit.java:12: error: block element not allowed within inline element <i>: blockquote
* <i> <blockquote> abc </blockquote> </i>
^
2 errors
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref InvalidEntity.out InvalidEntity.java
*/
// tidy: Warning: replacing invalid numeric character reference .*
// See
// http://www.w3.org/TR/html4/sgml/entities.html
// http://stackoverflow.com/questions/631406/what-is-the-difference-between-em-dash-151-and-8212
/**
* &#01;
* &#x01;
* &splodge;
*
*/
public class InvalidEntity { }
InvalidEntity.java:15: error: invalid entity &#01;
* &#01;
^
InvalidEntity.java:16: error: invalid entity &#x01;
* &#x01;
^
InvalidEntity.java:17: error: invalid entity &splodge;
* &splodge;
^
3 errors
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref InvalidName.out InvalidName.java
*/
// tidy: Warning: <a> cannot copy name attribute to id
/**
* <a name="abc">valid</a>
* <a name="abc123">valid</a>
* <a name="a.1:2-3_4">valid</a>
* <a name="foo()">invalid</a>
*/
public class InvalidName { }
InvalidName.java:14: error: invalid name for anchor: "foo()"
* <a name="foo()">invalid</a>
^
1 error
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref InvalidTag.out InvalidTag.java
*/
// tidy: Error: <.*> is not recognized!
/**
* List<String> list = new ArrayList<>();
*/
public class InvalidTag { }
InvalidTag.java:11: error: unknown tag: String
* List<String> list = new ArrayList<>();
^
InvalidTag.java:11: error: malformed HTML
* List<String> list = new ArrayList<>();
^
InvalidTag.java:11: error: bad use of '>'
* List<String> list = new ArrayList<>();
^
3 errors
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref InvalidURI.out InvalidURI.java
*/
// tidy: Warning: <a> escaping malformed URI reference
// tidy: Warning: <.*> attribute ".*" lacks value
/**
* <a href="abc">valid</a>
* <a href="abc%20def">valid</a>
* <a href="abc def">invalid</a>
* <a href>no value</a>
* <a href= >no value</a>
* <a href="" >no value</a>
*/
public class InvalidURI { }
InvalidURI.java:14: error: invalid uri: "abc def"
* <a href="abc def">invalid</a>
^
InvalidURI.java:15: error: attribute lacks value
* <a href>no value</a>
^
InvalidURI.java:16: error: attribute lacks value
* <a href= >no value</a>
^
InvalidURI.java:17: error: attribute lacks value
* <a href="" >no value</a>
^
4 errors
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref MissingGT.out MissingGT.java
*/
// tidy: Warning: <.*> missing '>' for end of tag
/**
* <img src="image.gif"
* <i> text </i>
*/
public class MissingGT { }
MissingGT.java:11: error: malformed HTML
* <img src="image.gif"
^
1 error
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref MissingTag.out MissingTag.java
*/
// tidy: Warning: missing <.*>
// tidy: Warning: missing </.*> before </.*>
/**
* </p>
* <h1> <b> text </h1>
*/
public class MissingTag { }
MissingTag.java:12: error: unexpected end tag: </p>
* </p>
^
MissingTag.java:13: error: end tag missing: </b>
* <h1> <b> text </h1>
^
2 errors
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref NestedTag.out NestedTag.java
*/
// tidy: Warning: nested emphasis <.*>
/**
* <b><b> text </b></b>
* {@link java.lang.String <code>String</code>}
*/
public class NestedTag { }
NestedTag.java:11: warning: nested tag not allowed: <b>
* <b><b> text </b></b>
^
NestedTag.java:12: warning: nested tag not allowed: <code>
* {@link java.lang.String <code>String</code>}
^
2 warnings
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref ParaInPre.out ParaInPre.java
*/
// tidy: Warning: replacing <p> by <br>
// tidy: Warning: using <br> in place of <p>
/**
* <pre>
* text
* <p>
* more text
* </pre>
*/
public class ParaInPre { }
ParaInPre.java:14: warning: unexpected use of <p> inside <pre> element
* <p>
^
1 warning
The utilities in this directory can be used to determine
common issues in javadoc comments by running the standard
"tidy" program on the output of javadoc, and analysing
the messages that are reported.
tidy.sh is a script that will run the "tidy" program on
the files in a directory, writing the results to a new
directroy.
tidystats.Main is a Java program that can analyze the
files produced by the tidy.sh script to generate a
summary report about the warnings that were found.
The tests is this directory are focussed on verifying
that doclint detects issues in javadoc comments that will
give rise to issues detected by "tidy" in the output
generated by javadoc.
For more information on the "tidy" program, see the HTML Tidy
Library Project page at http://tidy.sourceforge.net/.
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref RepeatedAttr.out RepeatedAttr.java
*/
// tidy: Warning: <.*> dropping value ".*" for repeated attribute ".*"
/**
* <img src="image.gif" alt alt="summary">
*/
public class RepeatedAttr { }
RepeatedAttr.java:11: error: repeated attribute: alt
* <img src="image.gif" alt alt="summary">
^
1 error
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref TextNotAllowed.out TextNotAllowed.java
*/
// tidy: Warning: plain text isn't allowed in <.*> elements
/**
* <table summary=description> abc </table>
* <table summary=description> <tbody> abc </tbody> </table>
* <table summary=description> <tr> abc </tr> </table>
*
* <dl> abc </dl>
* <ol> abc </ol>
* <ul> abc </ul>
*
* <ul>
* <li> item
* <li> item
* </ul>
*/
public class TextNotAllowed { }
TextNotAllowed.java:11: error: text not allowed in <table> element
* <table summary=description> abc </table>
^
TextNotAllowed.java:12: error: text not allowed in <tbody> element
* <table summary=description> <tbody> abc </tbody> </table>
^
TextNotAllowed.java:13: error: text not allowed in <tr> element
* <table summary=description> <tr> abc </tr> </table>
^
TextNotAllowed.java:15: error: text not allowed in <dl> element
* <dl> abc </dl>
^
TextNotAllowed.java:16: error: text not allowed in <ol> element
* <ol> abc </ol>
^
TextNotAllowed.java:17: error: text not allowed in <ul> element
* <ul> abc </ul>
^
6 errors
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref TrimmingEmptyTag.out TrimmingEmptyTag.java
*/
// tidy: Warning: trimming empty <.*>
/**
* <b></b>
* <table summary=description></table>
* <table><caption></caption></table>
* <code></code>
* <dl></dl>
* <dl><dt></dt><dd></dd></dl>
* <font></font>
* <i></i>
* <ol></ol>
* <p></p>
* <pre></pre>
* <span></span>
* <tt></tt>
* <ul></ul>
* <ul><li></li></ul>
*/
public class TrimmingEmptyTag { }
TrimmingEmptyTag.java:11: warning: empty <b> tag
* <b></b>
^
TrimmingEmptyTag.java:12: warning: empty <table> tag
* <table summary=description></table>
^
TrimmingEmptyTag.java:13: warning: empty <caption> tag
* <table><caption></caption></table>
^
TrimmingEmptyTag.java:14: warning: empty <code> tag
* <code></code>
^
TrimmingEmptyTag.java:15: warning: empty <dl> tag
* <dl></dl>
^
TrimmingEmptyTag.java:16: warning: empty <dt> tag
* <dl><dt></dt><dd></dd></dl>
^
TrimmingEmptyTag.java:16: warning: empty <dd> tag
* <dl><dt></dt><dd></dd></dl>
^
TrimmingEmptyTag.java:17: warning: empty <font> tag
* <font></font>
^
TrimmingEmptyTag.java:18: warning: empty <i> tag
* <i></i>
^
TrimmingEmptyTag.java:19: warning: empty <ol> tag
* <ol></ol>
^
TrimmingEmptyTag.java:20: warning: empty <p> tag
* <p></p>
^
TrimmingEmptyTag.java:21: warning: empty <pre> tag
* <pre></pre>
^
TrimmingEmptyTag.java:22: warning: empty <span> tag
* <span></span>
^
TrimmingEmptyTag.java:23: warning: empty <tt> tag
* <tt></tt>
^
TrimmingEmptyTag.java:24: warning: empty <ul> tag
* <ul></ul>
^
15 warnings
/*
* @test /nodynamiccopyright/
* @library ..
* @build DocLintTester
* @run main DocLintTester -ref UnescapedOrUnknownEntity.out UnescapedOrUnknownEntity.java
*/
// tidy: Warning: unescaped & or unknown entity ".*"
// tidy: Warning: unescaped & which should be written as &amp;
// tidy: Warning: entity ".*" doesn't end in ';'
/**
* L&F
* Drag&Drop
* if (a & b);
*/
public class UnescapedOrUnknownEntity { }
UnescapedOrUnknownEntity.java:13: error: semicolon missing
* L&F
^
UnescapedOrUnknownEntity.java:14: error: semicolon missing
* Drag&Drop
^
UnescapedOrUnknownEntity.java:15: error: bad HTML entity
* if (a & b);
^
3 errors
package tidystats;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String... args) throws IOException {
new Main().run(args);
}
void run(String... args) throws IOException {
FileSystem fs = FileSystems.getDefault();
List<Path> paths = new ArrayList<>();
int i;
for (i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.startsWith("-"))
throw new IllegalArgumentException(arg);
else
break;
}
for ( ; i < args.length; i++) {
Path p = fs.getPath(args[i]);
paths.add(p);
}
for (Path p: paths) {
scan(p);
}
print("%6d files read", files);
print("%6d files had no errors or warnings", ok);
print("%6d files reported \"Not all warnings/errors were shown.\"", overflow);
print("%6d errors found", errs);
print("%6d warnings found", warns);
print("%6d recommendations to use CSS", css);
print("");
Map<Integer, Set<String>> sortedCounts = new TreeMap<>(
new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
for (Map.Entry<Pattern, Integer> e: counts.entrySet()) {
Pattern p = e.getKey();
Integer n = e.getValue();
Set<String> set = sortedCounts.get(n);
if (set == null)
sortedCounts.put(n, (set = new TreeSet<>()));
set.add(p.toString());
}
for (Map.Entry<Integer, Set<String>> e: sortedCounts.entrySet()) {
for (String p: e.getValue()) {
if (p.startsWith(".*")) p = p.substring(2);
print("%6d: %s", e.getKey(), p);
}
}
}
void scan(Path p) throws IOException {
if (Files.isDirectory(p)) {
for (Path c: Files.newDirectoryStream(p)) {
scan(c);
}
} else if (isTidyFile(p)) {
scan(Files.readAllLines(p, Charset.defaultCharset()));
}
}
boolean isTidyFile(Path p) {
return Files.isRegularFile(p) && p.getFileName().toString().endsWith(".tidy");
}
void scan(List<String> lines) {
Matcher m;
files++;
for (String line: lines) {
if (okPattern.matcher(line).matches()) {
ok++;
} else if ((m = countPattern.matcher(line)).matches()) {
warns += Integer.valueOf(m.group(1));
errs += Integer.valueOf(m.group(2));
if (m.group(3) != null)
overflow++;
} else if ((m = guardPattern.matcher(line)).matches()) {
boolean found = false;
for (Pattern p: patterns) {
if ((m = p.matcher(line)).matches()) {
found = true;
count(p);
break;
}
}
if (!found)
System.err.println("Unrecognized line: " + line);
} else if (cssPattern.matcher(line).matches()) {
css++;
}
}
}
Map<Pattern, Integer> counts = new HashMap<>();
void count(Pattern p) {
Integer i = counts.get(p);
counts.put(p, (i == null) ? 1 : i + 1);
}
void print(String format, Object... args) {
System.out.println(String.format(format, args));
}
Pattern okPattern = Pattern.compile("No warnings or errors were found.");
Pattern countPattern = Pattern.compile("([0-9]+) warnings, ([0-9]+) errors were found!.*?(Not all warnings/errors were shown.)?");
Pattern cssPattern = Pattern.compile("You are recommended to use CSS.*");
Pattern guardPattern = Pattern.compile("line [0-9]+ column [0-9]+ - (Error|Warning):.*");
Pattern[] patterns = {
Pattern.compile(".*Error: <.*> is not recognized!"),
Pattern.compile(".*Error: missing quote mark for attribute value"),
Pattern.compile(".*Warning: <.*> anchor \".*\" already defined"),
Pattern.compile(".*Warning: <.*> attribute \".*\" has invalid value \".*\""),
Pattern.compile(".*Warning: <.*> attribute \".*\" lacks value"),
Pattern.compile(".*Warning: <.*> attribute \".*\" lacks value"),
Pattern.compile(".*Warning: <.*> attribute with missing trailing quote mark"),
Pattern.compile(".*Warning: <.*> dropping value \".*\" for repeated attribute \".*\""),
Pattern.compile(".*Warning: <.*> inserting \".*\" attribute"),
Pattern.compile(".*Warning: <.*> is probably intended as </.*>"),
Pattern.compile(".*Warning: <.*> isn't allowed in <.*> elements"),
Pattern.compile(".*Warning: <.*> lacks \".*\" attribute"),
Pattern.compile(".*Warning: <.*> missing '>' for end of tag"),
Pattern.compile(".*Warning: <.*> proprietary attribute \".*\""),
Pattern.compile(".*Warning: <.*> unexpected or duplicate quote mark"),
Pattern.compile(".*Warning: <a> cannot copy name attribute to id"),
Pattern.compile(".*Warning: <a> escaping malformed URI reference"),
Pattern.compile(".*Warning: <blockquote> proprietary attribute \"pre\""),
Pattern.compile(".*Warning: discarding unexpected <.*>"),
Pattern.compile(".*Warning: discarding unexpected </.*>"),
Pattern.compile(".*Warning: entity \".*\" doesn't end in ';'"),
Pattern.compile(".*Warning: inserting implicit <.*>"),
Pattern.compile(".*Warning: inserting missing 'title' element"),
Pattern.compile(".*Warning: missing <!DOCTYPE> declaration"),
Pattern.compile(".*Warning: missing <.*>"),
Pattern.compile(".*Warning: missing </.*> before <.*>"),
Pattern.compile(".*Warning: nested emphasis <.*>"),
Pattern.compile(".*Warning: plain text isn't allowed in <.*> elements"),
Pattern.compile(".*Warning: replacing <p> by <br>"),
Pattern.compile(".*Warning: replacing invalid numeric character reference .*"),
Pattern.compile(".*Warning: replacing unexpected .* by </.*>"),
Pattern.compile(".*Warning: trimming empty <.*>"),
Pattern.compile(".*Warning: unescaped & or unknown entity \".*\""),
Pattern.compile(".*Warning: unescaped & which should be written as &amp;"),
Pattern.compile(".*Warning: using <br> in place of <p>")
};
int files;
int ok;
int warns;
int errs;
int css;
int overflow;
}
#!/bin/sh
#
# Copyright (c) 2012, 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.
#
# Run the "tidy" program over the files in a directory.
#
# Usage:
# sh tidy.sh <dir>
#
# The "tidy" program will be run on each HTML file in <dir>,
# and the output placed in the corresponding location in a new
# directory <dir>.tidy. The console output from running "tidy" will
# be saved in a corresponding file with an additional .tidy extension.
#
# Non-HTML files will be copied without modification from <dir> to
# <dir>.tidy, so that relative links within the directory tree are
# unaffected.
dir=$1
odir=$dir.tidy
( cd $dir ; find . -type f ) | \
while read file ; do
mkdir -p $odir/$(dirname $file)
case $file in
*.html )
cat $dir/$file | tidy 1>$odir/$file 2>$odir/$file.tidy
;;
* ) cp $dir/$file $odir/$file
;;
esac
done
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.dc.no.content
// key: compiler.note.note
// key: compiler.note.proc.messager
// run: backdoor
// options: -processor DocCommentProcessor -proc:only
/** @see */
class NoContent {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册