提交 037ccd83 编写于 作者: L lana

Merge

......@@ -68,7 +68,7 @@ javac.no.jdk.warnings = -XDignore.symbol.file=true
# set the following to -version to verify the versions of javac being used
javac.version.opt =
# in time, there should be no exceptions to -Xlint:all
javac.lint.opts = -Xlint:all,-deprecation -Werror
javac.lint.opts = -Xlint:all -Werror
# options for the <javadoc> task for javac
#javadoc.jls3.url=http://java.sun.com/docs/books/jls/
......@@ -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
......
/*
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
......@@ -65,6 +65,12 @@ public interface ClassDoc extends ProgramElementDoc, Type {
*/
boolean isExternalizable();
/**
* Return true if this class can be used as a target type of a lambda expression
* or method reference.
*/
boolean isFunctionalInterface();
/**
* Return the serialization methods for this class or
* interface.
......
/*
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
......@@ -38,6 +38,11 @@ public interface MethodDoc extends ExecutableMemberDoc {
*/
boolean isAbstract();
/**
* Return true if this method is default
*/
boolean isDefault();
/**
* Get return type.
*
......
......@@ -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.
*/
......
......@@ -56,9 +56,9 @@ public interface Plugin {
String getName();
/**
* Invoke the plug-in for a given compilation task.
* Initialize the plug-in for a given compilation task.
* @param task The compilation task that has just been started
* @param args Arguments, if any, for the plug-in
*/
void call(JavacTask task, String... args);
void init(JavacTask task, String... args);
}
......@@ -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) {
......
......@@ -239,7 +239,14 @@ public abstract class AbstractMemberWriter {
if ((member.isField() || member.isMethod()) &&
writer instanceof ClassWriterImpl &&
((ClassWriterImpl) writer).getClassDoc().isInterface()) {
mod = Util.replaceText(mod, "public", "").trim();
// This check for isDefault() and the default modifier needs to be
// added for it to appear on the method details section. Once the
// default modifier is added to the Modifier list on DocEnv and once
// it is updated to use the javax.lang.model.element.Modifier, we
// will need to remove this.
mod = (member.isMethod() && ((MethodDoc)member).isDefault()) ?
Util.replaceText(mod, "public", "default").trim() :
Util.replaceText(mod, "public", "").trim();
}
if(mod.length() > 0) {
htmltree.addContent(mod);
......@@ -313,8 +320,18 @@ public abstract class AbstractMemberWriter {
code.addContent(configuration.getText("doclet.Package_private"));
code.addContent(" ");
}
if (member.isMethod() && ((MethodDoc)member).isAbstract()) {
code.addContent("abstract ");
if (member.isMethod()) {
if (((MethodDoc)member).isAbstract()) {
code.addContent("abstract ");
}
// This check for isDefault() and the default modifier needs to be
// added for it to appear on the "Modifier and Type" column in the
// method summary section. Once the default modifier is added
// to the Modifier list on DocEnv and once it is updated to use the
// javax.lang.model.element.Modifier, we will need to remove this.
else if (((MethodDoc)member).isDefault()) {
code.addContent("default ");
}
}
if (member.isStatic()) {
code.addContent("static ");
......@@ -547,6 +564,9 @@ public abstract class AbstractMemberWriter {
methodType = (classdoc.isInterface() || ((MethodDoc)member).isAbstract()) ?
methodType | MethodTypes.ABSTRACT.value() :
methodType | MethodTypes.CONCRETE.value();
if (((MethodDoc)member).isDefault()) {
methodType = methodType | MethodTypes.DEFAULT.value();
}
if (Util.isDeprecated(member) || Util.isDeprecated(classdoc)) {
methodType = methodType | MethodTypes.DEPRECATED.value();
}
......
......@@ -513,6 +513,20 @@ public class ClassWriterImpl extends SubWriterHolderWriter
}
}
/**
* {@inheritDoc}
*/
public void addFunctionalInterfaceInfo (Content classInfoTree) {
if (classDoc.isFunctionalInterface()) {
Content dt = HtmlTree.DT(getResource("doclet.Functional_Interface"));
Content dl = HtmlTree.DL(dt);
Content dd = new HtmlTree(HtmlTag.DD);
dd.addContent(getResource("doclet.Functional_Interface_Message"));
dl.addContent(dd);
classInfoTree.addContent(dl);
}
}
/**
* {@inheritDoc}
*/
......
......@@ -90,6 +90,8 @@ doclet.in_interface=in interface
doclet.Subclasses=Direct Known Subclasses:
doclet.Subinterfaces=All Known Subinterfaces:
doclet.Implementing_Classes=All Known Implementing Classes:
doclet.Functional_Interface=Functional Interface:
doclet.Functional_Interface_Message=This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
doclet.also=also
doclet.Frames=Frames
doclet.No_Frames=No Frames
......
......@@ -116,6 +116,13 @@ public interface ClassWriter {
*/
public void addInterfaceUsageInfo(Content classInfoTree);
/**
* If this is an functional interface, display appropriate message.
*
* @param classInfoTree content tree to which the documentation will be added
*/
public void addFunctionalInterfaceInfo(Content classInfoTree);
/**
* If this is an inner class or interface, add the enclosing class or
* interface.
......
......@@ -235,6 +235,16 @@ public class ClassBuilder extends AbstractBuilder {
writer.addInterfaceUsageInfo(classInfoTree);
}
/**
* If this is an functional interface, display appropriate message.
*
* @param node the XML element that specifies which components to document
* @param classInfoTree the content tree to which the documentation will be added
*/
public void buildFunctionalInterfaceInfo(XMLNode node, Content classInfoTree) {
writer.addFunctionalInterfaceInfo(classInfoTree);
}
/**
* If this class is deprecated, build the appropriate information.
*
......
......@@ -85,6 +85,7 @@
<SubInterfacesInfo/>
<InterfaceUsageInfo/>
<NestedClassInfo/>
<FunctionalInterfaceInfo/>
<DeprecationInfo/>
<ClassSignature/>
<ClassDescription/>
......
......@@ -36,7 +36,8 @@ public enum MethodTypes {
INSTANCE(0x2, "Instance Methods", "t2", false),
ABSTRACT(0x4, "Abstract Methods", "t3", false),
CONCRETE(0x8, "Concrete Methods", "t4", false),
DEPRECATED(0x10, "Deprecated Methods", "t5", false);
DEFAULT(0x10, "Default Methods", "t5", false),
DEPRECATED(0x20, "Deprecated Methods", "t6", false);
private final int value;
private final String text;
......
此差异已折叠。
/*
* 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 init(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;
......
......@@ -159,7 +159,7 @@ public final class JavacTool implements JavaCompiler {
}
}
private static void processOptions(Context context,
public static void processOptions(Context context,
JavaFileManager fileManager,
Iterable<String> options)
{
......
......@@ -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);
}
......
......@@ -60,6 +60,9 @@ public abstract class Attribute implements AnnotationValue {
throw new UnsupportedOperationException();
}
public boolean isSynthesized() {
return false;
}
/** The value for an annotation element of primitive type or String. */
public static class Constant extends Attribute {
......@@ -136,6 +139,18 @@ public abstract class Attribute implements AnnotationValue {
* access this attribute.
*/
public final List<Pair<MethodSymbol,Attribute>> values;
private boolean synthesized = false;
@Override
public boolean isSynthesized() {
return synthesized;
}
public void setSynthesized(boolean synthesized) {
this.synthesized = synthesized;
}
public Compound(Type type,
List<Pair<MethodSymbol,Attribute>> values) {
super(type);
......
......@@ -83,13 +83,13 @@ public abstract class Symbol implements Element {
* Attributes of class symbols should be accessed through the accessor
* method to make sure that the class symbol is loaded.
*/
public List<Attribute.Compound> getAnnotationMirrors() {
return Assert.checkNonNull(annotations.getAttributes());
public List<Attribute.Compound> getRawAttributes() {
return annotations.getAttributes();
}
/** Fetch a particular annotation from a symbol. */
public Attribute.Compound attribute(Symbol anno) {
for (Attribute.Compound a : getAnnotationMirrors()) {
for (Attribute.Compound a : getRawAttributes()) {
if (a.type.tsym == anno) return a;
}
return null;
......@@ -446,6 +446,14 @@ public abstract class Symbol implements Element {
return name;
}
/**
* This is the implementation for {@code
* javax.lang.model.element.Element.getAnnotationMirrors()}.
*/
public final List<Attribute.Compound> getAnnotationMirrors() {
return getRawAttributes();
}
/**
* @deprecated this method should never be used by javac internally.
*/
......@@ -662,15 +670,21 @@ public abstract class Symbol implements Element {
return flags_field;
}
public List<Attribute.Compound> getAnnotationMirrors() {
@Override
public List<Attribute.Compound> getRawAttributes() {
if (completer != null) complete();
if (package_info != null && package_info.completer != null) {
package_info.complete();
if (annotations.isEmpty()) {
annotations.setAttributes(package_info.annotations);
mergeAttributes();
}
return super.getRawAttributes();
}
private void mergeAttributes() {
if (annotations.isEmpty() &&
!package_info.annotations.isEmpty()) {
annotations.setAttributes(package_info.annotations);
}
return Assert.checkNonNull(annotations.getAttributes());
}
/** A package "exists" if a type or package that exists has
......@@ -770,9 +784,10 @@ public abstract class Symbol implements Element {
return members_field;
}
public List<Attribute.Compound> getAnnotationMirrors() {
@Override
public List<Attribute.Compound> getRawAttributes() {
if (completer != null) complete();
return Assert.checkNonNull(annotations.getAttributes());
return super.getRawAttributes();
}
public Type erasure(Types types) {
......@@ -1353,7 +1368,7 @@ public abstract class Symbol implements Element {
return defaultValue;
}
public List<VarSymbol> getParameters() {
public List<VarSymbol> getParameters() {
return params();
}
......@@ -1361,6 +1376,10 @@ public abstract class Symbol implements Element {
return (flags() & VARARGS) != 0;
}
public boolean isDefault() {
return (flags() & DEFAULT) != 0;
}
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
return v.visitExecutable(this, p);
}
......
......@@ -302,10 +302,12 @@ public class Type implements PrimitiveType {
* never complete classes. Where isSameType would complete a
* class, equals assumes that the two types are different.
*/
@Override
public boolean equals(Object t) {
return super.equals(t);
}
@Override
public int hashCode() {
return super.hashCode();
}
......@@ -996,34 +998,6 @@ public class Type implements PrimitiveType {
return "(" + argtypes + ")" + restype;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof MethodType))
return false;
MethodType m = (MethodType)obj;
List<Type> args1 = argtypes;
List<Type> args2 = m.argtypes;
while (!args1.isEmpty() && !args2.isEmpty()) {
if (!args1.head.equals(args2.head))
return false;
args1 = args1.tail;
args2 = args2.tail;
}
if (!args1.isEmpty() || !args2.isEmpty())
return false;
return restype.equals(m.restype);
}
public int hashCode() {
int h = METHOD.ordinal();
for (List<Type> thisargs = this.argtypes;
thisargs.tail != null; /*inlined: thisargs.nonEmpty()*/
thisargs = thisargs.tail)
h = (h << 5) + thisargs.head.hashCode();
return (h << 5) + this.restype.hashCode();
}
public List<Type> getParameterTypes() { return argtypes; }
public Type getReturnType() { return restype; }
public List<Type> getThrownTypes() { return thrown; }
......
......@@ -1007,11 +1007,11 @@ public class Types {
if (!visit(supertype(t), supertype(s)))
return false;
HashSet<SingletonType> set = new HashSet<SingletonType>();
HashSet<UniqueType> set = new HashSet<UniqueType>();
for (Type x : interfaces(t))
set.add(new SingletonType(x));
set.add(new UniqueType(x, Types.this));
for (Type x : interfaces(s)) {
if (!set.remove(new SingletonType(x)))
if (!set.remove(new UniqueType(x, Types.this)))
return false;
}
return (set.isEmpty());
......@@ -3137,7 +3137,7 @@ public class Types {
}
@Override
public int hashCode() {
return 127 * Types.hashCode(t1) + Types.hashCode(t2);
return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2);
}
@Override
public boolean equals(Object obj) {
......@@ -3400,7 +3400,7 @@ public class Types {
/**
* Compute a hash code on a type.
*/
public static int hashCode(Type t) {
public int hashCode(Type t) {
return hashCode.visit(t);
}
// where
......@@ -3422,6 +3422,16 @@ public class Types {
return result;
}
@Override
public Integer visitMethodType(MethodType t, Void ignored) {
int h = METHOD.ordinal();
for (List<Type> thisargs = t.argtypes;
thisargs.tail != null;
thisargs = thisargs.tail)
h = (h << 5) + visit(thisargs.head);
return (h << 5) + visit(t.restype);
}
@Override
public Integer visitWildcardType(WildcardType t, Void ignored) {
int result = t.kind.hashCode();
......@@ -4082,21 +4092,28 @@ public class Types {
/**
* A wrapper for a type that allows use in sets.
*/
class SingletonType {
final Type t;
SingletonType(Type t) {
this.t = t;
public static class UniqueType {
public final Type type;
final Types types;
public UniqueType(Type type, Types types) {
this.type = type;
this.types = types;
}
public int hashCode() {
return Types.hashCode(t);
return types.hashCode(type);
}
public boolean equals(Object obj) {
return (obj instanceof SingletonType) &&
isSameType(t, ((SingletonType)obj).t);
return (obj instanceof UniqueType) &&
types.isSameType(type, ((UniqueType)obj).type);
}
public String toString() {
return t.toString();
return type.toString();
}
}
// </editor-fold>
......
......@@ -400,6 +400,7 @@ public class Annotate {
Attribute.Compound c = enterAnnotation(annoTree,
targetContainerType,
ctx.env);
c.setSynthesized(true);
return c;
} else {
return null; // errors should have been reported elsewhere
......
......@@ -1405,7 +1405,8 @@ public class Attr extends JCTree.Visitor {
Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt();
if (condtype.constValue() != null &&
truetype.constValue() != null &&
falsetype.constValue() != null) {
falsetype.constValue() != null &&
!owntype.hasTag(NONE)) {
//constant folding
owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
}
......
......@@ -692,8 +692,9 @@ public class LambdaToMethod extends TreeTranslator {
//determine the static bsm args
Type mtype = makeFunctionalDescriptorType(targetType, true);
List<Object> staticArgs = List.<Object>of(
new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(targetType.tsym)),
new Pool.MethodHandle(refKind, refSym),
new Pool.MethodHandle(ClassFile.REF_invokeInterface,
types.findDescriptorSymbol(targetType.tsym), types),
new Pool.MethodHandle(refKind, refSym, types),
new MethodType(mtype.getParameterTypes(),
mtype.getReturnType(),
mtype.getThrownTypes(),
......
......@@ -1798,6 +1798,9 @@ public class Resolve {
if ((kind & TYP) != 0) {
sym = findType(env, name);
if (sym.kind==TYP) {
reportDependence(env.enclClass.sym, sym);
}
if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
......@@ -1806,6 +1809,14 @@ public class Resolve {
else return bestSoFar;
}
/** Report dependencies.
* @param from The enclosing class sym
* @param to The found identifier that the class depends on.
*/
public void reportDependence(Symbol from, Symbol to) {
// Override if you want to collect the reported dependencies.
}
/** Find an identifier in a package which matches a specified kind set.
* @param env The current environment.
* @param name The identifier's name.
......@@ -3064,16 +3075,20 @@ public class Resolve {
if (hasLocation) {
return diags.create(dkind, log.currentSource(), pos,
errKey, kindname, idname, //symbol kindname, name
typeargtypes, argtypes, //type parameters and arguments (if any)
typeargtypes, args(argtypes), //type parameters and arguments (if any)
getLocationDiag(location, site)); //location kindname, type
}
else {
return diags.create(dkind, log.currentSource(), pos,
errKey, kindname, idname, //symbol kindname, name
typeargtypes, argtypes); //type parameters and arguments (if any)
typeargtypes, args(argtypes)); //type parameters and arguments (if any)
}
}
//where
private Object args(List<Type> args) {
return args.isEmpty() ? args : methodArguments(args);
}
private String getErrorKey(KindName kindname, boolean hasTypeArgs, boolean hasLocation) {
String key = "cant.resolve";
String suffix = hasLocation ? ".location" : "";
......
......@@ -548,17 +548,15 @@ public class ZipFileIndex {
}
if (i >= 0) {
zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12) + 2];
zipDir[0] = endbuf[i + 10];
zipDir[1] = endbuf[i + 11];
zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12)];
int sz = get4ByteLittleEndian(endbuf, i + 16);
// a negative offset or the entries field indicates a
// potential zip64 archive
if (sz < 0 || get2ByteLittleEndian(zipDir, 0) == 0xffff) {
if (sz < 0 || get2ByteLittleEndian(endbuf, i + 10) == 0xffff) {
throw new ZipFormatException("detected a zip64 archive");
}
zipRandomFile.seek(start + sz);
zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
zipRandomFile.readFully(zipDir, 0, zipDir.length);
return;
} else {
endbufend = endbufpos + 21;
......@@ -568,14 +566,13 @@ public class ZipFileIndex {
}
private void buildIndex() throws IOException {
int entryCount = get2ByteLittleEndian(zipDir, 0);
int len = zipDir.length;
// Add each of the files
if (entryCount > 0) {
if (len > 0) {
directories = new LinkedHashMap<RelativeDirectory, DirectoryEntry>();
ArrayList<Entry> entryList = new ArrayList<Entry>();
int pos = 2;
for (int i = 0; i < entryCount; i++) {
for (int pos = 0; pos < len; ) {
pos = readEntry(pos, entryList, directories);
}
......
......@@ -26,6 +26,8 @@
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.util.Name;
......@@ -166,22 +168,29 @@ public class ClassFile {
*/
public static class NameAndType {
Name name;
Type type;
UniqueType uniqueType;
Types types;
NameAndType(Name name, Type type) {
NameAndType(Name name, Type type, Types types) {
this.name = name;
this.type = type;
this.uniqueType = new UniqueType(type, types);
this.types = types;
}
void setType(Type type) {
this.uniqueType = new UniqueType(type, types);
}
@Override
public boolean equals(Object other) {
return
other instanceof NameAndType &&
name == ((NameAndType) other).name &&
type.equals(((NameAndType) other).type);
return (other instanceof NameAndType &&
name == ((NameAndType) other).name &&
uniqueType.equals(((NameAndType) other).uniqueType));
}
@Override
public int hashCode() {
return name.hashCode() * type.hashCode();
return name.hashCode() * uniqueType.hashCode();
}
}
}
......@@ -488,20 +488,20 @@ public class ClassReader implements Completer {
case CONSTANT_Fieldref: {
ClassSymbol owner = readClassSymbol(getChar(index + 1));
NameAndType nt = (NameAndType)readPool(getChar(index + 3));
poolObj[i] = new VarSymbol(0, nt.name, nt.type, owner);
poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
break;
}
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref: {
ClassSymbol owner = readClassSymbol(getChar(index + 1));
NameAndType nt = (NameAndType)readPool(getChar(index + 3));
poolObj[i] = new MethodSymbol(0, nt.name, nt.type, owner);
poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
break;
}
case CONSTANT_NameandType:
poolObj[i] = new NameAndType(
readName(getChar(index + 1)),
readType(getChar(index + 3)));
readType(getChar(index + 3)), types);
break;
case CONSTANT_Integer:
poolObj[i] = getInt(index + 1);
......@@ -1224,7 +1224,7 @@ public class ClassReader implements Completer {
if (nt == null)
return null;
MethodType type = nt.type.asMethodType();
MethodType type = nt.uniqueType.type.asMethodType();
for (Scope.Entry e = scope.lookup(nt.name); e.scope != null; e = e.next())
if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type))
......@@ -1236,16 +1236,16 @@ public class ClassReader implements Completer {
if ((flags & INTERFACE) != 0)
// no enclosing instance
return null;
if (nt.type.getParameterTypes().isEmpty())
if (nt.uniqueType.type.getParameterTypes().isEmpty())
// no parameters
return null;
// A constructor of an inner class.
// Remove the first argument (the enclosing instance)
nt.type = new MethodType(nt.type.getParameterTypes().tail,
nt.type.getReturnType(),
nt.type.getThrownTypes(),
syms.methodClass);
nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
nt.uniqueType.type.getReturnType(),
nt.uniqueType.type.getThrownTypes(),
syms.methodClass));
// Try searching again
return findMethod(nt, scope, flags);
}
......@@ -1959,7 +1959,7 @@ public class ClassReader implements Completer {
if (readAllOfClassFile) {
for (int i = 1; i < poolObj.length; i++) readPool(i);
c.pool = new Pool(poolObj.length, poolObj);
c.pool = new Pool(poolObj.length, poolObj, types);
}
// reset and read rest of classinfo
......
......@@ -39,7 +39,12 @@ import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.file.BaseFileObject;
import com.sun.tools.javac.jvm.Pool.DynamicMethod;
import com.sun.tools.javac.jvm.Pool.Method;
import com.sun.tools.javac.jvm.Pool.MethodHandle;
import com.sun.tools.javac.jvm.Pool.Variable;
import com.sun.tools.javac.util.*;
import static com.sun.tools.javac.code.BoundKind.*;
......@@ -142,7 +147,7 @@ public class ClassWriter extends ClassFile {
/** The bootstrap methods to be written in the corresponding class attribute
* (one for each invokedynamic)
*/
Map<MethodSymbol, Pool.MethodHandle> bootstrapMethods;
Map<DynamicMethod, MethodHandle> bootstrapMethods;
/** The log to use for verbose output.
*/
......@@ -477,10 +482,10 @@ public class ClassWriter extends ClassFile {
while (i < pool.pp) {
Object value = pool.pool[i];
Assert.checkNonNull(value);
if (value instanceof Pool.Method)
value = ((Pool.Method)value).m;
else if (value instanceof Pool.Variable)
value = ((Pool.Variable)value).v;
if (value instanceof Method)
value = ((Method)value).m;
else if (value instanceof Variable)
value = ((Variable)value).v;
if (value instanceof MethodSymbol) {
MethodSymbol m = (MethodSymbol)value;
......@@ -493,8 +498,9 @@ public class ClassWriter extends ClassFile {
} else {
//invokedynamic
DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
Pool.MethodHandle handle = new Pool.MethodHandle(dynSym.bsmKind, dynSym.bsm);
bootstrapMethods.put(dynSym, handle);
MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types);
DynamicMethod dynMeth = new DynamicMethod(dynSym, types);
bootstrapMethods.put(dynMeth, handle);
//init cp entries
pool.put(names.BootstrapMethods);
pool.put(handle);
......@@ -531,7 +537,7 @@ public class ClassWriter extends ClassFile {
NameAndType nt = (NameAndType)value;
poolbuf.appendByte(CONSTANT_NameandType);
poolbuf.appendChar(pool.put(nt.name));
poolbuf.appendChar(pool.put(typeSig(nt.type)));
poolbuf.appendChar(pool.put(typeSig(nt.uniqueType.type)));
} else if (value instanceof Integer) {
poolbuf.appendByte(CONSTANT_Integer);
poolbuf.appendInt(((Integer)value).intValue());
......@@ -549,17 +555,18 @@ public class ClassWriter extends ClassFile {
} else if (value instanceof String) {
poolbuf.appendByte(CONSTANT_String);
poolbuf.appendChar(pool.put(names.fromString((String)value)));
} else if (value instanceof MethodType) {
MethodType mtype = (MethodType)value;
poolbuf.appendByte(CONSTANT_MethodType);
poolbuf.appendChar(pool.put(typeSig(mtype)));
} else if (value instanceof Type) {
Type type = (Type)value;
if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym);
poolbuf.appendByte(CONSTANT_Class);
poolbuf.appendChar(pool.put(xClassName(type)));
} else if (value instanceof Pool.MethodHandle) {
Pool.MethodHandle ref = (Pool.MethodHandle)value;
} else if (value instanceof UniqueType) {
Type type = ((UniqueType)value).type;
if (type instanceof MethodType) {
poolbuf.appendByte(CONSTANT_MethodType);
poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
} else {
if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym);
poolbuf.appendByte(CONSTANT_Class);
poolbuf.appendChar(pool.put(xClassName(type)));
}
} else if (value instanceof MethodHandle) {
MethodHandle ref = (MethodHandle)value;
poolbuf.appendByte(CONSTANT_MethodHandle);
poolbuf.appendByte(ref.refKind);
poolbuf.appendChar(pool.put(ref.refSym));
......@@ -589,7 +596,7 @@ public class ClassWriter extends ClassFile {
return new NameAndType(fieldName(sym),
retrofit
? sym.erasure(types)
: sym.externalType(types));
: sym.externalType(types), types);
// if we retrofit, then the NameAndType has been read in as is
// and no change is necessary. If we compile normally, the
// NameAndType is generated from a symbol reference, and the
......@@ -714,7 +721,7 @@ public class ClassWriter extends ClassFile {
endAttr(alenIdx);
acount++;
}
acount += writeJavaAnnotations(sym.getAnnotationMirrors());
acount += writeJavaAnnotations(sym.getRawAttributes());
return acount;
}
......@@ -725,7 +732,7 @@ public class ClassWriter extends ClassFile {
boolean hasVisible = false;
boolean hasInvisible = false;
if (m.params != null) for (VarSymbol s : m.params) {
for (Attribute.Compound a : s.getAnnotationMirrors()) {
for (Attribute.Compound a : s.getRawAttributes()) {
switch (types.getRetention(a)) {
case SOURCE: break;
case CLASS: hasInvisible = true; break;
......@@ -741,7 +748,7 @@ public class ClassWriter extends ClassFile {
databuf.appendByte(m.params.length());
for (VarSymbol s : m.params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
for (Attribute.Compound a : s.getAnnotationMirrors())
for (Attribute.Compound a : s.getRawAttributes())
if (types.getRetention(a) == RetentionPolicy.RUNTIME)
buf.append(a);
databuf.appendChar(buf.length());
......@@ -756,7 +763,7 @@ public class ClassWriter extends ClassFile {
databuf.appendByte(m.params.length());
for (VarSymbol s : m.params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
for (Attribute.Compound a : s.getAnnotationMirrors())
for (Attribute.Compound a : s.getRawAttributes())
if (types.getRetention(a) == RetentionPolicy.CLASS)
buf.append(a);
databuf.appendChar(buf.length());
......@@ -951,14 +958,16 @@ public class ClassWriter extends ClassFile {
void writeBootstrapMethods() {
int alenIdx = writeAttr(names.BootstrapMethods);
databuf.appendChar(bootstrapMethods.size());
for (Map.Entry<MethodSymbol, Pool.MethodHandle> entry : bootstrapMethods.entrySet()) {
DynamicMethodSymbol dsym = (DynamicMethodSymbol)entry.getKey();
for (Map.Entry<DynamicMethod, MethodHandle> entry : bootstrapMethods.entrySet()) {
DynamicMethod dmeth = entry.getKey();
DynamicMethodSymbol dsym = (DynamicMethodSymbol)dmeth.baseSymbol();
//write BSM handle
databuf.appendChar(pool.get(entry.getValue()));
//write static args length
databuf.appendChar(dsym.staticArgs.length);
//write static args array
for (Object o : dsym.staticArgs) {
Object[] uniqueArgs = dmeth.uniqueStaticArgs;
for (Object o : uniqueArgs) {
databuf.appendChar(pool.get(o));
}
}
......@@ -1534,7 +1543,7 @@ public class ClassWriter extends ClassFile {
pool = c.pool;
innerClasses = null;
innerClassesQueue = null;
bootstrapMethods = new LinkedHashMap<MethodSymbol, Pool.MethodHandle>();
bootstrapMethods = new LinkedHashMap<DynamicMethod, MethodHandle>();
Type supertype = types.supertype(c.type);
List<Type> interfaces = types.interfaces(c.type);
......@@ -1627,7 +1636,7 @@ public class ClassWriter extends ClassFile {
}
acount += writeFlagAttrs(c.flags());
acount += writeJavaAnnotations(c.getAnnotationMirrors());
acount += writeJavaAnnotations(c.getRawAttributes());
acount += writeEnclosingMethodAttribute(c);
acount += writeExtraClassAttributes(c);
......
......@@ -27,6 +27,7 @@ package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
......@@ -901,6 +902,7 @@ public class Code {
if (o instanceof ClassSymbol) return syms.classType;
if (o instanceof Type.ArrayType) return syms.classType;
if (o instanceof Type.MethodType) return syms.methodTypeType;
if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
throw new AssertionError(o);
}
......@@ -1030,7 +1032,7 @@ public class Code {
Object o = pool.pool[od];
Type t = (o instanceof Symbol)
? ((Symbol)o).erasure(types)
: types.erasure(((Type)o));
: types.erasure((((UniqueType)o).type));
state.push(t);
break; }
case ldc2w:
......
......@@ -94,6 +94,10 @@ public class Gen extends JCTree.Visitor {
return instance;
}
/* Constant pool, reset by genClass.
*/
private Pool pool;
protected Gen(Context context) {
context.put(genKey, this);
......@@ -126,6 +130,7 @@ public class Gen extends JCTree.Visitor {
genCrt = options.isSet(XJCOV);
debugCode = options.isSet("debugcode");
allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
pool = new Pool(types);
generateIproxies =
target.requiresIproxy() ||
......@@ -174,10 +179,6 @@ public class Gen extends JCTree.Visitor {
*/
private boolean useJsrLocally;
/* Constant pool, reset by genClass.
*/
private Pool pool = new Pool();
/** Code buffer, set by genMethod.
*/
private Code code;
......@@ -705,7 +706,7 @@ public class Gen extends JCTree.Visitor {
}
int startpc = code.curPc();
genStat(tree, env);
if (tree.hasTag(BLOCK)) crtFlags |= CRT_BLOCK;
if (tree.hasTag(Tag.BLOCK)) crtFlags |= CRT_BLOCK;
code.crt.put(tree, crtFlags, startpc, code.curPc());
}
......
......@@ -28,6 +28,9 @@ package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.util.ArrayUtils;
import com.sun.tools.javac.util.Assert;
......@@ -60,11 +63,14 @@ public class Pool {
*/
Map<Object,Integer> indices;
Types types;
/** Construct a pool with given number of elements and element array.
*/
public Pool(int pp, Object[] pool) {
public Pool(int pp, Object[] pool, Types types) {
this.pp = pp;
this.pool = pool;
this.types = types;
this.indices = new HashMap<Object,Integer>(pool.length);
for (int i = 1; i < pp; i++) {
if (pool[i] != null) indices.put(pool[i], i);
......@@ -73,8 +79,8 @@ public class Pool {
/** Construct an empty pool.
*/
public Pool() {
this(1, new Object[64]);
public Pool(Types types) {
this(1, new Object[64], types);
}
/** Return the number of entries in the constant pool.
......@@ -114,11 +120,13 @@ public class Pool {
Object makePoolValue(Object o) {
if (o instanceof DynamicMethodSymbol) {
return new DynamicMethod((DynamicMethodSymbol)o);
return new DynamicMethod((DynamicMethodSymbol)o, types);
} else if (o instanceof MethodSymbol) {
return new Method((MethodSymbol)o);
return new Method((MethodSymbol)o, types);
} else if (o instanceof VarSymbol) {
return new Variable((VarSymbol)o);
return new Variable((VarSymbol)o, types);
} else if (o instanceof Type) {
return new UniqueType((Type)o, types);
} else {
return o;
}
......@@ -134,9 +142,11 @@ public class Pool {
static class Method extends DelegatedSymbol {
MethodSymbol m;
Method(MethodSymbol m) {
UniqueType uniqueType;
Method(MethodSymbol m, Types types) {
super(m);
this.m = m;
this.uniqueType = new UniqueType(m.type, types);
}
public boolean equals(Object other) {
if (!(other instanceof Method)) return false;
......@@ -144,20 +154,22 @@ public class Pool {
return
o.name == m.name &&
o.owner == m.owner &&
o.type.equals(m.type);
((Method)other).uniqueType.equals(uniqueType);
}
public int hashCode() {
return
m.name.hashCode() * 33 +
m.owner.hashCode() * 9 +
m.type.hashCode();
uniqueType.hashCode();
}
}
static class DynamicMethod extends Method {
public Object[] uniqueStaticArgs;
DynamicMethod(DynamicMethodSymbol m) {
super(m);
DynamicMethod(DynamicMethodSymbol m, Types types) {
super(m, types);
uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
}
@Override
......@@ -168,7 +180,8 @@ public class Pool {
DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)other).m;
return dm1.bsm == dm2.bsm &&
dm1.bsmKind == dm2.bsmKind &&
Arrays.equals(dm1.staticArgs, dm2.staticArgs);
Arrays.equals(uniqueStaticArgs,
((DynamicMethod)other).uniqueStaticArgs);
}
@Override
......@@ -178,17 +191,31 @@ public class Pool {
hash += dm.bsmKind * 7 +
dm.bsm.hashCode() * 11;
for (int i = 0; i < dm.staticArgs.length; i++) {
hash += (dm.staticArgs[i].hashCode() * 23);
hash += (uniqueStaticArgs[i].hashCode() * 23);
}
return hash;
}
private Object[] getUniqueTypeArray(Object[] objects, Types types) {
Object[] result = new Object[objects.length];
for (int i = 0; i < objects.length; i++) {
if (objects[i] instanceof Type) {
result[i] = new UniqueType((Type)objects[i], types);
} else {
result[i] = objects[i];
}
}
return result;
}
}
static class Variable extends DelegatedSymbol {
VarSymbol v;
Variable(VarSymbol v) {
UniqueType uniqueType;
Variable(VarSymbol v, Types types) {
super(v);
this.v = v;
this.uniqueType = new UniqueType(v.type, types);
}
public boolean equals(Object other) {
if (!(other instanceof Variable)) return false;
......@@ -196,13 +223,13 @@ public class Pool {
return
o.name == v.name &&
o.owner == v.owner &&
o.type.equals(v.type);
((Variable)other).uniqueType.equals(uniqueType);
}
public int hashCode() {
return
v.name.hashCode() * 33 +
v.owner.hashCode() * 9 +
v.type.hashCode();
uniqueType.hashCode();
}
}
......@@ -214,9 +241,12 @@ public class Pool {
/** Reference symbol */
Symbol refSym;
public MethodHandle(int refKind, Symbol refSym) {
UniqueType uniqueType;
public MethodHandle(int refKind, Symbol refSym, Types types) {
this.refKind = refKind;
this.refSym = refSym;
this.uniqueType = new UniqueType(this.refSym.type, types);
checkConsistent();
}
public boolean equals(Object other) {
......@@ -227,14 +257,14 @@ public class Pool {
return
o.name == refSym.name &&
o.owner == refSym.owner &&
o.type.equals(refSym.type);
((MethodHandle)other).uniqueType.equals(uniqueType);
}
public int hashCode() {
return
refKind * 65 +
refSym.name.hashCode() * 33 +
refSym.owner.hashCode() * 9 +
refSym.type.hashCode();
uniqueType.hashCode();
}
/**
......
......@@ -928,6 +928,16 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
}
}
/**
* Set needRootClasses to true, in JavaCompiler subclass constructor
* that want to collect public apis of classes supplied on the command line.
*/
protected boolean needRootClasses = false;
/**
* The list of classes explicitly supplied on the command line for compilation.
* Not always populated.
*/
private List<JCClassDecl> rootClasses;
/**
......@@ -984,9 +994,10 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
}
}
//If generating source, remember the classes declared in
//the original compilation units listed on the command line.
if (sourceOutput || stubOutput) {
// If generating source, or if tracking public apis,
// then remember the classes declared in
// the original compilation units listed on the command line.
if (needRootClasses || sourceOutput || stubOutput) {
ListBuffer<JCClassDecl> cdefs = lb();
for (JCCompilationUnit unit : roots) {
for (List<JCTree> defs = unit.defs;
......@@ -1247,6 +1258,12 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
attr.postAttr(env.tree);
}
compileStates.put(env, CompileState.ATTR);
if (rootClasses != null && rootClasses.contains(env.enclClass)) {
// This was a class that was explicitly supplied for compilation.
// If we want to capture the public api of this class,
// then now is a good time to do it.
reportPublicApi(env.enclClass.sym);
}
}
finally {
log.useSource(prev);
......@@ -1255,6 +1272,14 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
return env;
}
/** Report the public api of a class that was supplied explicitly for compilation,
* for example on the command line to javac.
* @param sym The symbol of the class.
*/
public void reportPublicApi(ClassSymbol sym) {
// Override to collect the reported public api.
}
/**
* Perform dataflow checks on attributed parse trees.
* These include checks for definite assignment and unreachable statements.
......@@ -1675,7 +1700,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)
......
......@@ -44,6 +44,8 @@ import javax.tools.JavaFileObject;
import com.sun.source.util.JavacTask;
import com.sun.source.util.Plugin;
import com.sun.tools.doclint.DocLint;
import com.sun.tools.javac.api.BasicJavacTask;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.file.CacheFSInfo;
import com.sun.tools.javac.file.JavacFileManager;
......@@ -428,6 +430,7 @@ public class Main {
if (batchMode)
CacheFSInfo.preRegister(context);
// FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate
// invoke any available plugins
String plugins = options.get(PLUGIN);
if (plugins != null) {
......@@ -448,7 +451,7 @@ public class Main {
try {
if (task == null)
task = JavacTask.instance(pEnv);
plugin.call(task, p.tail.toArray(new String[p.tail.size()]));
plugin.init(task, p.tail.toArray(new String[p.tail.size()]));
} catch (Throwable ex) {
if (apiMode)
throw new RuntimeException(ex);
......@@ -464,10 +467,31 @@ public class Main {
}
}
fileManager = context.get(JavaFileManager.class);
comp = JavaCompiler.instance(context);
if (comp == null) return Result.SYSERR;
// FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate
String xdoclint = options.get(XDOCLINT);
String xdoclintCustom = options.get(XDOCLINT_CUSTOM);
if (xdoclint != null || xdoclintCustom != null) {
Set<String> doclintOpts = new LinkedHashSet<String>();
if (xdoclint != null)
doclintOpts.add(DocLint.XMSGS_OPTION);
if (xdoclintCustom != null) {
for (String s: xdoclintCustom.split("\\s+")) {
if (s.isEmpty())
continue;
doclintOpts.add(s.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX));
}
}
if (!(doclintOpts.size() == 1
&& doclintOpts.iterator().next().equals(DocLint.XMSGS_CUSTOM_PREFIX + "none"))) {
JavacTask t = BasicJavacTask.instance(context);
new DocLint().init(t, doclintOpts.toArray(new String[doclintOpts.size()]));
comp.keepComments = true;
}
}
fileManager = context.get(JavaFileManager.class);
if (!files.isEmpty()) {
// add filenames to fileObjects
......
......@@ -25,28 +25,30 @@
package com.sun.tools.javac.main;
import java.util.Collections;
import com.sun.tools.javac.util.Log.PrefixKind;
import com.sun.tools.javac.util.Log.WriterKind;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.util.Options;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.lang.model.SourceVersion;
import com.sun.tools.doclint.DocLint;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Log.PrefixKind;
import com.sun.tools.javac.util.Log.WriterKind;
import com.sun.tools.javac.util.Options;
import static com.sun.tools.javac.main.Option.ChoiceKind.*;
import static com.sun.tools.javac.main.Option.OptionKind.*;
import static com.sun.tools.javac.main.Option.OptionGroup.*;
import static com.sun.tools.javac.main.Option.OptionKind.*;
/**
* Options for javac. The specific Option to handle a command-line option
......@@ -79,6 +81,24 @@ public enum Option {
XLINT_CUSTOM("-Xlint:", "opt.Xlint.suboptlist",
EXTENDED, BASIC, ANYOF, getXLintChoices()),
XDOCLINT("-Xdoclint", "opt.Xdoclint", EXTENDED, BASIC),
XDOCLINT_CUSTOM("-Xdoclint:", "opt.Xdoclint.subopts", "opt.Xdoclint.custom", EXTENDED, BASIC) {
@Override
public boolean matches(String option) {
return DocLint.isValidOption(
option.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX));
}
@Override
public boolean process(OptionHelper helper, String option) {
String prev = helper.get(XDOCLINT_CUSTOM);
String next = (prev == null) ? option : (prev + " " + option);
helper.put(XDOCLINT_CUSTOM.text, next);
return false;
}
},
// -nowarn is retained for command-line backward compatibility
NOWARN("-nowarn", "opt.nowarn", STANDARD, BASIC) {
@Override
......
/*
* 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 '@'
......
......@@ -138,6 +138,14 @@ javac.opt.Xlint=\
Enable recommended warnings
javac.opt.Xlint.suboptlist=\
Enable or disable specific warnings
javac.opt.Xdoclint=\
Enable recommended checks for problems in javadoc comments
javac.opt.Xdoclint.subopts = \
(all|[-]<group>)[/<access>]
javac.opt.Xdoclint.custom=\n\
\ Enable or disable specific checks for problems in javadoc comments,\n\
\ where <group> is one of accessibility, html, reference, or syntax,\n\
\ and <access> is one of public, protected, package, or private.
javac.opt.Xstdout=\
Redirect standard output
javac.opt.X=\
......
......@@ -33,6 +33,7 @@ import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.jvm.ClassReader;
import com.sun.tools.javac.jvm.ClassWriter;
import com.sun.tools.javac.jvm.Pool;
......@@ -173,7 +174,8 @@ public class CreateSymbols extends AbstractProcessor {
List.<Pair<Symbol.MethodSymbol,Attribute>>nil());
Type.moreInfo = true;
Pool pool = new Pool();
Types types = Types.instance(task.getContext());
Pool pool = new Pool(types);
for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) {
String className = fm.inferBinaryName(jarLocation, file);
int index = className.lastIndexOf('.');
......
......@@ -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.
*/
......
......@@ -684,7 +684,7 @@ public class TreeMaker implements JCTree.Factory {
public JCVariableDecl VarDef(VarSymbol v, JCExpression init) {
return (JCVariableDecl)
new JCVariableDecl(
Modifiers(v.flags(), Annotations(v.getAnnotationMirrors())),
Modifiers(v.flags(), Annotations(v.getRawAttributes())),
v.name,
Type(v.type),
init,
......@@ -800,7 +800,7 @@ public class TreeMaker implements JCTree.Factory {
public JCMethodDecl MethodDef(MethodSymbol m, Type mtype, JCBlock body) {
return (JCMethodDecl)
new JCMethodDecl(
Modifiers(m.flags(), Annotations(m.getAnnotationMirrors())),
Modifiers(m.flags(), Annotations(m.getRawAttributes())),
m.name,
Type(mtype.getReturnType()),
TypeParams(mtype.getTypeArguments()),
......
......@@ -276,6 +276,10 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
return false;
}
public boolean isFunctionalInterface() {
return env.types.isFunctionalInterface(tsym);
}
/**
* Return the package that this class is contained in.
*/
......
......@@ -75,6 +75,13 @@ public class MethodDocImpl
return true;
}
/**
* Return true if this method is default
*/
public boolean isDefault() {
return (sym.flags() & Flags.DEFAULT) != 0;
}
/**
* Return true if this method is abstract
*/
......
......@@ -288,9 +288,9 @@ public class PackageDocImpl extends DocImpl implements PackageDoc {
* Return an empty array if there are none.
*/
public AnnotationDesc[] annotations() {
AnnotationDesc res[] = new AnnotationDesc[sym.getAnnotationMirrors().length()];
AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
int i = 0;
for (Attribute.Compound a : sym.getAnnotationMirrors()) {
for (Attribute.Compound a : sym.getRawAttributes()) {
res[i++] = new AnnotationDescImpl(env, a);
}
return res;
......
......@@ -99,9 +99,9 @@ class ParameterImpl implements Parameter {
* Return an empty array if there are none.
*/
public AnnotationDesc[] annotations() {
AnnotationDesc res[] = new AnnotationDesc[sym.getAnnotationMirrors().length()];
AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
int i = 0;
for (Attribute.Compound a : sym.getAnnotationMirrors()) {
for (Attribute.Compound a : sym.getRawAttributes()) {
res[i++] = new AnnotationDescImpl(env, a);
}
return res;
......
......@@ -164,9 +164,9 @@ public abstract class ProgramElementDocImpl
* Return an empty array if there are none.
*/
public AnnotationDesc[] annotations() {
AnnotationDesc res[] = new AnnotationDesc[sym.getAnnotationMirrors().length()];
AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
int i = 0;
for (Attribute.Compound a : sym.getAnnotationMirrors()) {
for (Attribute.Compound a : sym.getRawAttributes()) {
res[i++] = new AnnotationDescImpl(env, a);
}
return res;
......
......@@ -77,6 +77,16 @@ public interface ExecutableElement extends Element, Parameterizable {
*/
boolean isVarArgs();
/**
* Returns {@code true} if this method is a default method and
* returns {@code false} otherwise.
*
* @return {@code true} if this method is a default method and
* {@code false} otherwise
* @since 1.8
*/
boolean isDefault();
/**
* Returns the exceptions and other throwables listed in this
* method or constructor's {@code throws} clause in declaration
......
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 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
......@@ -207,7 +207,7 @@ public class TestHtmlTableTags extends JavadocTester {
"Instance Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t4\" class=\"tableTab\"><span><a href=\"javascript:show(8);\">" +
"Concrete Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t5\" class=\"tableTab\"><span><a href=\"javascript:show(16);\">" +
"<span id=\"t6\" class=\"tableTab\"><span><a href=\"javascript:show(32);\">" +
"Deprecated Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"</caption>"
},
......
/*
* 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 8004893
* @summary Make sure that the lambda feature changes work fine in
* javadoc.
* @author bpatel
* @library ../lib/
* @build JavadocTester TestLambdaFeature
* @run main TestLambdaFeature
*/
public class TestLambdaFeature extends JavadocTester {
//Test information.
private static final String BUG_ID = "8004893";
//Javadoc arguments.
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg"
};
//Input for string search tests.
private static final String[][] TEST = {
{BUG_ID + FS + "pkg" + FS + "A.html",
"<td class=\"colFirst\"><code>default void</code></td>"},
{BUG_ID + FS + "pkg" + FS + "A.html",
"<pre>default&nbsp;void&nbsp;defaultMethod()</pre>"},
{BUG_ID + FS + "pkg" + FS + "A.html",
"<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
"All Methods</span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t2\" class=\"tableTab\"><span>" +
"<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span></span><span id=\"t3\" " +
"class=\"tableTab\"><span><a href=\"javascript:show(4);\">" +
"Abstract Methods</a></span><span class=\"tabEnd\">&nbsp;</span>" +
"</span><span id=\"t5\" class=\"tableTab\"><span>" +
"<a href=\"javascript:show(16);\">Default Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span></span></caption>"},
{BUG_ID + FS + "pkg" + FS + "A.html",
"<dl>" + NL + "<dt>Functional Interface:</dt>" + NL +
"<dd>This is a functional interface and can therefore be used as " +
"the assignment target for a lambda expression or method " +
"reference. </dd>" + NL + "</dl>"}
};
private static final String[][] NEGATED_TEST = {
{BUG_ID + FS + "pkg" + FS + "A.html",
"<td class=\"colFirst\"><code>default default void</code></td>"},
{BUG_ID + FS + "pkg" + FS + "A.html",
"<pre>default&nbsp;default&nbsp;void&nbsp;defaultMethod()</pre>"},
{BUG_ID + FS + "pkg" + FS + "B.html",
"<td class=\"colFirst\"><code>default void</code></td>"},
{BUG_ID + FS + "pkg" + FS + "B.html",
"<dl>" + NL + "<dt>Functional Interface:</dt>"}
};
/**
* The entry point of the test.
* @param args the array of command line arguments.
*/
public static void main(String[] args) {
TestLambdaFeature tester = new TestLambdaFeature();
run(tester, ARGS, TEST, NEGATED_TEST);
tester.printSummary();
}
/**
* {@inheritDoc}
*/
public String getBugId() {
return BUG_ID;
}
/**
* {@inheritDoc}
*/
public String getBugName() {
return getClass().getName();
}
}
/*
* 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.
*/
package pkg;
public interface A {
public void method1();
public default void defaultMethod() { }
}
/*
* 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.
*/
package pkg;
public abstract class B {
public abstract void method1();
public void method2() { }
}
......@@ -55,7 +55,7 @@ public class TestMethodTypes extends JavadocTester {
"Instance Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t4\" class=\"tableTab\"><span><a href=\"javascript:show(8);\">" +
"Concrete Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t5\" class=\"tableTab\"><span><a href=\"javascript:show(16);\">" +
"<span id=\"t6\" class=\"tableTab\"><span><a href=\"javascript:show(32);\">" +
"Deprecated Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"</caption>"
},
......@@ -87,7 +87,7 @@ public class TestMethodTypes extends JavadocTester {
"Abstract Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t4\" class=\"tableTab\"><span><a href=\"javascript:show(8);\">" +
"Concrete Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t5\" class=\"tableTab\"><span><a href=\"javascript:show(16);\">" +
"<span id=\"t6\" class=\"tableTab\"><span><a href=\"javascript:show(32);\">" +
"Deprecated Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"</caption>"
},
......
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:23: error: malformed HTML
* public a < b
^
AccessTest.java:28: error: malformed HTML
* protected a < b
^
AccessTest.java:33: error: malformed HTML
* package-private a < b
^
AccessTest.java:46: error: malformed HTML
* public a < b
^
AccessTest.java:51: error: malformed HTML
* protected a < b
^
AccessTest.java:56: error: malformed HTML
* package-private a < b
^
6 errors
AccessTest.java:23: error: malformed HTML
* public a < b
^
AccessTest.java:28: error: malformed HTML
* protected a < b
^
AccessTest.java:33: error: malformed HTML
* package-private a < b
^
AccessTest.java:38: error: malformed HTML
* private a < b
^
AccessTest.java:46: error: malformed HTML
* public a < b
^
AccessTest.java:51: error: malformed HTML
* protected a < b
^
AccessTest.java:56: error: malformed HTML
* package-private a < b
^
AccessTest.java:61: error: malformed HTML
* private a < b
^
8 errors
AccessTest.java:23: error: malformed HTML
* public a < b
^
AccessTest.java:28: error: malformed HTML
* protected a < b
^
2 errors
AccessTest.java:23: error: malformed HTML
* public a < b
^
1 error
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:14: error: header used out of sequence: <H2>
* <h2> ... </h2>
^
AccessibilityTest.java:20: error: header used out of sequence: <H3>
* <h3> ... </h3>
^
AccessibilityTest.java:25: error: no "alt" attribute for image
* <img src="x.jpg">
^
AccessibilityTest.java:40: 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/
* @bug 8004832
* @summary Add new doclint package
* @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:10: warning: no description for @author
/** @author */
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:12: warning: no description for @exception
/** @exception NullPointerException */
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:12: warning: no description for @param
/** @param i */
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:12: warning: no description for @return
/** @return */
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:15: warning: no description for @serialData
/** @serialData */
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:17: warning: no description for @serialField
* @serialField empty String
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:12: warning: no description for @since
/** @since */
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:12: warning: no description for @version
/** @version */
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:13: error: unknown attribute: xyz
* <p xyz>
^
HtmlAttrsTest.java:18: warning: attribute obsolete: name
* <img name="x" alt="alt">
^
HtmlAttrsTest.java:23: warning: attribute obsolete, use CSS instead: size
* <font size="3"> text </font>
^
1 error
2 warnings
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:13: error: unknown tag: xyz
* <xyz> ... </xyz>
^
HtmlTagsTest.java:13: error: unknown tag: xyz
* <xyz> ... </xyz>
^
HtmlTagsTest.java:18: error: unknown tag: xyz
* <div> <xyz> </div>
^
HtmlTagsTest.java:23: error: self-closing element not allowed
* <br/>
^
HtmlTagsTest.java:28: error: element not allowed in documentation comments: <html>
* <html>
^
HtmlTagsTest.java:33: error: block element not allowed within inline element <span>: p
* <span> <p> </span>
^
HtmlTagsTest.java:38: error: block element not allowed within @link: p
* {@link java.lang.String <p> }
^
HtmlTagsTest.java:39: error: block element not allowed within @link: p
* {@link java.lang.String <p> }
^
HtmlTagsTest.java:44: error: invalid end tag: </img>
* <img src="any.jpg" alt="alt"> </img>
^
HtmlTagsTest.java:49: error: end tag missing: </b>
* <i> <b> </i>
^
HtmlTagsTest.java:54: error: unexpected end tag: </b>
* <i> </b> </i>
^
HtmlTagsTest.java:54: 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/
* @bug 8004832
* @summary Add new doclint package
* @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:13: warning: no @param for param
MissingParamsTest(int param) { }
^
MissingParamsTest.java:16: warning: no @param for <T>
<T> MissingParamsTest() { }
^
MissingParamsTest.java:19: warning: no @param for param
void missingParam(int param) { }
^
MissingParamsTest.java:22: warning: no @param for <T>
<T> void missingTyparam() { }
^
4 warnings
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:22: warning: no @return
int missingReturn() { }
^
1 warning
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @summary Add new doclint package
* @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:13: warning: no @throws for java.lang.Exception
void missingThrows() throws Exception { }
^
1 warning
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册