Merge
This commit is contained in:
commit
f2c7a7867a
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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;
|
||||
|
754
langtools/src/share/classes/com/sun/tools/doclint/Checker.java
Normal file
754
langtools/src/share/classes/com/sun/tools/doclint/Checker.java
Normal file
@ -0,0 +1,754 @@
|
||||
/*
|
||||
* 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.regex.Matcher;
|
||||
import com.sun.source.doctree.LinkTree;
|
||||
import java.net.URI;
|
||||
import java.util.regex.Pattern;
|
||||
import java.io.IOException;
|
||||
import com.sun.tools.javac.tree.DocPretty;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Deque;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
import com.sun.source.doctree.AttributeTree;
|
||||
import com.sun.source.doctree.AuthorTree;
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.EndElementTree;
|
||||
import com.sun.source.doctree.EntityTree;
|
||||
import com.sun.source.doctree.ErroneousTree;
|
||||
import com.sun.source.doctree.IdentifierTree;
|
||||
import com.sun.source.doctree.InheritDocTree;
|
||||
import com.sun.source.doctree.ParamTree;
|
||||
import com.sun.source.doctree.ReferenceTree;
|
||||
import com.sun.source.doctree.ReturnTree;
|
||||
import com.sun.source.doctree.SerialDataTree;
|
||||
import com.sun.source.doctree.SerialFieldTree;
|
||||
import com.sun.source.doctree.SinceTree;
|
||||
import com.sun.source.doctree.StartElementTree;
|
||||
import com.sun.source.doctree.TextTree;
|
||||
import com.sun.source.doctree.ThrowsTree;
|
||||
import com.sun.source.doctree.VersionTree;
|
||||
import com.sun.source.util.DocTreeScanner;
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.tools.doclint.HtmlTag.AttrKind;
|
||||
import java.net.URISyntaxException;
|
||||
import static com.sun.tools.doclint.Messages.Group.*;
|
||||
|
||||
|
||||
/**
|
||||
* Validate a 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 Checker extends DocTreeScanner<Void, Void> {
|
||||
final Env env;
|
||||
|
||||
Set<Element> foundParams = new HashSet<Element>();
|
||||
Set<TypeMirror> foundThrows = new HashSet<TypeMirror>();
|
||||
Set<String> foundAnchors = new HashSet<String>();
|
||||
boolean foundInheritDoc = false;
|
||||
boolean foundReturn = false;
|
||||
|
||||
enum Flag {
|
||||
TABLE_HAS_CAPTION,
|
||||
HAS_ELEMENT,
|
||||
HAS_TEXT
|
||||
}
|
||||
|
||||
static class TagStackItem {
|
||||
final DocTree tree; // typically, but not always, StartElementTree
|
||||
final HtmlTag tag;
|
||||
final Set<HtmlTag.Attr> attrs;
|
||||
final Set<Flag> flags;
|
||||
TagStackItem(DocTree tree, HtmlTag tag) {
|
||||
this.tree = tree;
|
||||
this.tag = tag;
|
||||
attrs = EnumSet.noneOf(HtmlTag.Attr.class);
|
||||
flags = EnumSet.noneOf(Flag.class);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(tag);
|
||||
}
|
||||
}
|
||||
|
||||
private Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
|
||||
private HtmlTag currHeaderTag;
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="Top level">
|
||||
|
||||
Checker(Env env) {
|
||||
env.getClass();
|
||||
this.env = env;
|
||||
tagStack = new LinkedList<TagStackItem>();
|
||||
}
|
||||
|
||||
public Void scan(DocCommentTree tree, TreePath p) {
|
||||
env.setCurrent(p, tree);
|
||||
|
||||
boolean isOverridingMethod = !env.currOverriddenMethods.isEmpty();
|
||||
|
||||
if (tree == null) {
|
||||
if (!isSynthetic() && !isOverridingMethod)
|
||||
reportMissing("dc.missing.comment");
|
||||
return null;
|
||||
}
|
||||
|
||||
tagStack.clear();
|
||||
currHeaderTag = null;
|
||||
|
||||
foundParams.clear();
|
||||
foundThrows.clear();
|
||||
foundInheritDoc = false;
|
||||
foundReturn = false;
|
||||
|
||||
scan(tree, (Void) null);
|
||||
|
||||
if (!isOverridingMethod) {
|
||||
switch (env.currElement.getKind()) {
|
||||
case METHOD:
|
||||
case CONSTRUCTOR: {
|
||||
ExecutableElement ee = (ExecutableElement) env.currElement;
|
||||
checkParamsDocumented(ee.getTypeParameters());
|
||||
checkParamsDocumented(ee.getParameters());
|
||||
switch (ee.getReturnType().getKind()) {
|
||||
case VOID:
|
||||
case NONE:
|
||||
break;
|
||||
default:
|
||||
if (!foundReturn
|
||||
&& !foundInheritDoc
|
||||
&& !env.types.isSameType(ee.getReturnType(), env.java_lang_Void)) {
|
||||
reportMissing("dc.missing.return");
|
||||
}
|
||||
}
|
||||
checkThrowsDocumented(ee.getThrownTypes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void reportMissing(String code, Object... args) {
|
||||
env.messages.report(MISSING, Kind.WARNING, env.currPath.getLeaf(), code, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDocComment(DocCommentTree tree, Void ignore) {
|
||||
super.visitDocComment(tree, ignore);
|
||||
for (TagStackItem tsi: tagStack) {
|
||||
if (tsi.tree.getKind() == DocTree.Kind.START_ELEMENT
|
||||
&& tsi.tag.endKind == HtmlTag.EndKind.REQUIRED) {
|
||||
StartElementTree t = (StartElementTree) tsi.tree;
|
||||
env.messages.error(HTML, t, "dc.tag.not.closed", t.getName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// </editor-fold>
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="Text and entities.">
|
||||
|
||||
@Override
|
||||
public Void visitText(TextTree tree, Void ignore) {
|
||||
if (!tree.getBody().trim().isEmpty()) {
|
||||
markEnclosingTag(Flag.HAS_TEXT);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitEntity(EntityTree tree, Void ignore) {
|
||||
markEnclosingTag(Flag.HAS_TEXT);
|
||||
String name = tree.getName().toString();
|
||||
if (name.startsWith("#")) {
|
||||
int v = name.toLowerCase().startsWith("#x")
|
||||
? Integer.parseInt(name.substring(2), 16)
|
||||
: Integer.parseInt(name.substring(1), 10);
|
||||
if (!Entity.isValid(v)) {
|
||||
env.messages.error(HTML, tree, "dc.entity.invalid", name);
|
||||
}
|
||||
} else if (!Entity.isValid(name)) {
|
||||
env.messages.error(HTML, tree, "dc.entity.invalid", name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// </editor-fold>
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="HTML elements">
|
||||
|
||||
@Override
|
||||
public Void visitStartElement(StartElementTree tree, Void ignore) {
|
||||
markEnclosingTag(Flag.HAS_ELEMENT);
|
||||
final Name treeName = tree.getName();
|
||||
final HtmlTag t = HtmlTag.get(treeName);
|
||||
if (t == null) {
|
||||
env.messages.error(HTML, tree, "dc.tag.unknown", treeName);
|
||||
} else {
|
||||
// tag specific checks
|
||||
switch (t) {
|
||||
// check for out of sequence headers, such as <h1>...</h1> <h3>...</h3>
|
||||
case H1: case H2: case H3: case H4: case H5: case H6:
|
||||
checkHeader(tree, t);
|
||||
break;
|
||||
// <p> inside <pre>
|
||||
case P:
|
||||
TagStackItem top = tagStack.peek();
|
||||
if (top != null && top.tag == HtmlTag.PRE)
|
||||
env.messages.warning(HTML, tree, "dc.tag.p.in.pre");
|
||||
break;
|
||||
}
|
||||
|
||||
// check that only block tags and inline tags are used,
|
||||
// and that blocks tags are not used within inline tags
|
||||
switch (t.blockType) {
|
||||
case INLINE:
|
||||
break;
|
||||
case BLOCK:
|
||||
TagStackItem top = tagStack.peek();
|
||||
if (top != null && top.tag != null && top.tag.blockType == HtmlTag.BlockType.INLINE) {
|
||||
switch (top.tree.getKind()) {
|
||||
case START_ELEMENT: {
|
||||
Name name = ((StartElementTree) top.tree).getName();
|
||||
env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.element",
|
||||
treeName, name);
|
||||
break;
|
||||
}
|
||||
case LINK:
|
||||
case LINK_PLAIN: {
|
||||
String name = top.tree.getKind().tagName;
|
||||
env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.tag",
|
||||
treeName, name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.other",
|
||||
treeName);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OTHER:
|
||||
env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
if (t.flags.contains(HtmlTag.Flag.NO_NEST)) {
|
||||
for (TagStackItem i: tagStack) {
|
||||
if (t == i.tag) {
|
||||
env.messages.warning(HTML, tree, "dc.tag.nested.not.allowed", treeName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for self closing tags, such as <a id="name"/>
|
||||
if (tree.isSelfClosing()) {
|
||||
env.messages.error(HTML, tree, "dc.tag.self.closing", treeName);
|
||||
}
|
||||
|
||||
try {
|
||||
TagStackItem parent = tagStack.peek();
|
||||
TagStackItem top = new TagStackItem(tree, t);
|
||||
tagStack.push(top);
|
||||
|
||||
super.visitStartElement(tree, ignore);
|
||||
|
||||
// handle attributes that may or may not have been found in start element
|
||||
if (t != null) {
|
||||
switch (t) {
|
||||
case CAPTION:
|
||||
if (parent != null && parent.tag == HtmlTag.TABLE)
|
||||
parent.flags.add(Flag.TABLE_HAS_CAPTION);
|
||||
break;
|
||||
|
||||
case IMG:
|
||||
if (!top.attrs.contains(HtmlTag.Attr.ALT))
|
||||
env.messages.error(ACCESSIBILITY, tree, "dc.no.alt.attr.for.image");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
} finally {
|
||||
|
||||
if (t == null || t.endKind == HtmlTag.EndKind.NONE)
|
||||
tagStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkHeader(StartElementTree tree, HtmlTag tag) {
|
||||
// verify the new tag
|
||||
if (getHeaderLevel(tag) > getHeaderLevel(currHeaderTag) + 1) {
|
||||
if (currHeaderTag == null) {
|
||||
env.messages.error(ACCESSIBILITY, tree, "dc.tag.header.sequence.1", tag);
|
||||
} else {
|
||||
env.messages.error(ACCESSIBILITY, tree, "dc.tag.header.sequence.2",
|
||||
tag, currHeaderTag);
|
||||
}
|
||||
}
|
||||
|
||||
currHeaderTag = tag;
|
||||
}
|
||||
|
||||
private int getHeaderLevel(HtmlTag tag) {
|
||||
if (tag == null)
|
||||
return 0;
|
||||
switch (tag) {
|
||||
case H1: return 1;
|
||||
case H2: return 2;
|
||||
case H3: return 3;
|
||||
case H4: return 4;
|
||||
case H5: return 5;
|
||||
case H6: return 6;
|
||||
default: throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitEndElement(EndElementTree tree, Void ignore) {
|
||||
final Name treeName = tree.getName();
|
||||
final HtmlTag t = HtmlTag.get(treeName);
|
||||
if (t == null) {
|
||||
env.messages.error(HTML, tree, "dc.tag.unknown", treeName);
|
||||
} else if (t.endKind == HtmlTag.EndKind.NONE) {
|
||||
env.messages.error(HTML, tree, "dc.tag.end.not.permitted", treeName);
|
||||
} else if (tagStack.isEmpty()) {
|
||||
env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName);
|
||||
} else {
|
||||
while (!tagStack.isEmpty()) {
|
||||
TagStackItem top = tagStack.peek();
|
||||
if (t == top.tag) {
|
||||
switch (t) {
|
||||
case TABLE:
|
||||
if (!top.attrs.contains(HtmlTag.Attr.SUMMARY)
|
||||
&& !top.flags.contains(Flag.TABLE_HAS_CAPTION)) {
|
||||
env.messages.error(ACCESSIBILITY, tree,
|
||||
"dc.no.summary.or.caption.for.table");
|
||||
}
|
||||
}
|
||||
if (t.flags.contains(HtmlTag.Flag.EXPECT_CONTENT)
|
||||
&& !top.flags.contains(Flag.HAS_TEXT)
|
||||
&& !top.flags.contains(Flag.HAS_ELEMENT)) {
|
||||
env.messages.warning(HTML, tree, "dc.tag.empty", treeName);
|
||||
}
|
||||
if (t.flags.contains(HtmlTag.Flag.NO_TEXT)
|
||||
&& top.flags.contains(Flag.HAS_TEXT)) {
|
||||
env.messages.error(HTML, tree, "dc.text.not.allowed", treeName);
|
||||
}
|
||||
tagStack.pop();
|
||||
break;
|
||||
} else if (top.tag == null || top.tag.endKind != HtmlTag.EndKind.REQUIRED) {
|
||||
tagStack.pop();
|
||||
} else {
|
||||
boolean found = false;
|
||||
for (TagStackItem si: tagStack) {
|
||||
if (si.tag == t) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found && top.tree.getKind() == DocTree.Kind.START_ELEMENT) {
|
||||
env.messages.error(HTML, top.tree, "dc.tag.start.unmatched",
|
||||
((StartElementTree) top.tree).getName());
|
||||
tagStack.pop();
|
||||
} else {
|
||||
env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.visitEndElement(tree, ignore);
|
||||
}
|
||||
// </editor-fold>
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="HTML attributes">
|
||||
|
||||
@Override @SuppressWarnings("fallthrough")
|
||||
public Void visitAttribute(AttributeTree tree, Void ignore) {
|
||||
HtmlTag currTag = tagStack.peek().tag;
|
||||
if (currTag != null) {
|
||||
Name name = tree.getName();
|
||||
HtmlTag.Attr attr = currTag.getAttr(name);
|
||||
if (attr != null) {
|
||||
boolean first = tagStack.peek().attrs.add(attr);
|
||||
if (!first)
|
||||
env.messages.error(HTML, tree, "dc.attr.repeated", name);
|
||||
}
|
||||
AttrKind k = currTag.getAttrKind(name);
|
||||
switch (k) {
|
||||
case OK:
|
||||
break;
|
||||
|
||||
case INVALID:
|
||||
env.messages.error(HTML, tree, "dc.attr.unknown", name);
|
||||
break;
|
||||
|
||||
case OBSOLETE:
|
||||
env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
|
||||
break;
|
||||
|
||||
case USE_CSS:
|
||||
env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (attr != null) {
|
||||
switch (attr) {
|
||||
case NAME:
|
||||
if (currTag != HtmlTag.A) {
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
case ID:
|
||||
String value = getAttrValue(tree);
|
||||
if (!validName.matcher(value).matches()) {
|
||||
env.messages.error(HTML, tree, "dc.invalid.anchor", value);
|
||||
}
|
||||
if (!foundAnchors.add(value)) {
|
||||
env.messages.error(HTML, tree, "dc.anchor.already.defined", value);
|
||||
}
|
||||
break;
|
||||
|
||||
case HREF:
|
||||
if (currTag == HtmlTag.A) {
|
||||
String v = getAttrValue(tree);
|
||||
if (v == null || v.isEmpty()) {
|
||||
env.messages.error(HTML, tree, "dc.attr.lacks.value");
|
||||
} else {
|
||||
Matcher m = docRoot.matcher(v);
|
||||
if (m.matches()) {
|
||||
String rest = m.group(2);
|
||||
if (!rest.isEmpty())
|
||||
checkURI(tree, rest);
|
||||
} else {
|
||||
checkURI(tree, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: basic check on value
|
||||
|
||||
return super.visitAttribute(tree, ignore);
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/html401/types.html#type-name
|
||||
private static final Pattern validName = Pattern.compile("[A-Za-z][A-Za-z0-9-_:.]*");
|
||||
|
||||
// pattern to remove leading {@docRoot}/?
|
||||
private static final Pattern docRoot = Pattern.compile("(?i)(\\{@docRoot *\\}/?)?(.*)");
|
||||
|
||||
private String getAttrValue(AttributeTree tree) {
|
||||
if (tree.getValue() == null)
|
||||
return null;
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
new DocPretty(sw).print(tree.getValue());
|
||||
} catch (IOException e) {
|
||||
// cannot happen
|
||||
}
|
||||
// ignore potential use of entities for now
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
private void checkURI(AttributeTree tree, String uri) {
|
||||
try {
|
||||
URI u = new URI(uri);
|
||||
} catch (URISyntaxException e) {
|
||||
env.messages.error(HTML, tree, "dc.invalid.uri", uri);
|
||||
}
|
||||
}
|
||||
// </editor-fold>
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="javadoc tags">
|
||||
|
||||
@Override
|
||||
public Void visitAuthor(AuthorTree tree, Void ignore) {
|
||||
warnIfEmpty(tree, tree.getName());
|
||||
return super.visitAuthor(tree, ignore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInheritDoc(InheritDocTree tree, Void ignore) {
|
||||
// TODO: verify on overridden method
|
||||
foundInheritDoc = true;
|
||||
return super.visitInheritDoc(tree, ignore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitLink(LinkTree tree, Void ignore) {
|
||||
// simulate inline context on tag stack
|
||||
HtmlTag t = (tree.getKind() == DocTree.Kind.LINK)
|
||||
? HtmlTag.CODE : HtmlTag.SPAN;
|
||||
tagStack.push(new TagStackItem(tree, t));
|
||||
try {
|
||||
return super.visitLink(tree, ignore);
|
||||
} finally {
|
||||
tagStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitParam(ParamTree tree, Void ignore) {
|
||||
boolean typaram = tree.isTypeParameter();
|
||||
IdentifierTree nameTree = tree.getName();
|
||||
Element e = env.currElement;
|
||||
switch (e.getKind()) {
|
||||
case METHOD: case CONSTRUCTOR: {
|
||||
ExecutableElement ee = (ExecutableElement) e;
|
||||
checkParamDeclared(nameTree, typaram ? ee.getTypeParameters() : ee.getParameters());
|
||||
break;
|
||||
}
|
||||
|
||||
case CLASS: case INTERFACE: {
|
||||
TypeElement te = (TypeElement) e;
|
||||
if (typaram) {
|
||||
checkParamDeclared(nameTree, te.getTypeParameters());
|
||||
} else {
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.param");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.param");
|
||||
break;
|
||||
}
|
||||
warnIfEmpty(tree, tree.getDescription());
|
||||
return super.visitParam(tree, ignore);
|
||||
}
|
||||
// where
|
||||
private void checkParamDeclared(IdentifierTree nameTree, List<? extends Element> list) {
|
||||
Name name = nameTree.getName();
|
||||
boolean found = false;
|
||||
for (Element e: list) {
|
||||
if (name.equals(e.getSimpleName())) {
|
||||
foundParams.add(e);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
env.messages.error(REFERENCE, nameTree, "dc.param.name.not.found");
|
||||
}
|
||||
|
||||
private void checkParamsDocumented(List<? extends Element> list) {
|
||||
if (foundInheritDoc)
|
||||
return;
|
||||
|
||||
for (Element e: list) {
|
||||
if (!foundParams.contains(e)) {
|
||||
CharSequence paramName = (e.getKind() == ElementKind.TYPE_PARAMETER)
|
||||
? "<" + e.getSimpleName() + ">"
|
||||
: e.getSimpleName();
|
||||
reportMissing("dc.missing.param", paramName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitReference(ReferenceTree tree, Void ignore) {
|
||||
Element e = env.trees.getElement(env.currPath, tree);
|
||||
if (e == null)
|
||||
env.messages.error(REFERENCE, tree, "dc.ref.not.found");
|
||||
return super.visitReference(tree, ignore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitReturn(ReturnTree tree, Void ignore) {
|
||||
Element e = env.trees.getElement(env.currPath);
|
||||
if (e.getKind() != ElementKind.METHOD
|
||||
|| ((ExecutableElement) e).getReturnType().getKind() == TypeKind.VOID)
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.return");
|
||||
foundReturn = true;
|
||||
warnIfEmpty(tree, tree.getDescription());
|
||||
return super.visitReturn(tree, ignore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSerialData(SerialDataTree tree, Void ignore) {
|
||||
warnIfEmpty(tree, tree.getDescription());
|
||||
return super.visitSerialData(tree, ignore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSerialField(SerialFieldTree tree, Void ignore) {
|
||||
warnIfEmpty(tree, tree.getDescription());
|
||||
return super.visitSerialField(tree, ignore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSince(SinceTree tree, Void ignore) {
|
||||
warnIfEmpty(tree, tree.getBody());
|
||||
return super.visitSince(tree, ignore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitThrows(ThrowsTree tree, Void ignore) {
|
||||
ReferenceTree exName = tree.getExceptionName();
|
||||
Element ex = env.trees.getElement(env.currPath, exName);
|
||||
if (ex == null) {
|
||||
env.messages.error(REFERENCE, tree, "dc.ref.not.found");
|
||||
} else if (ex.asType().getKind() == TypeKind.DECLARED
|
||||
&& env.types.isAssignable(ex.asType(), env.java_lang_Throwable)) {
|
||||
switch (env.currElement.getKind()) {
|
||||
case CONSTRUCTOR:
|
||||
case METHOD:
|
||||
if (isCheckedException(ex.asType())) {
|
||||
ExecutableElement ee = (ExecutableElement) env.currElement;
|
||||
checkThrowsDeclared(exName, ex.asType(), ee.getThrownTypes());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.throws");
|
||||
}
|
||||
} else {
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.throws");
|
||||
}
|
||||
warnIfEmpty(tree, tree.getDescription());
|
||||
return scan(tree.getDescription(), ignore);
|
||||
}
|
||||
|
||||
private void checkThrowsDeclared(ReferenceTree tree, TypeMirror t, List<? extends TypeMirror> list) {
|
||||
boolean found = false;
|
||||
for (TypeMirror tl : list) {
|
||||
if (env.types.isAssignable(t, tl)) {
|
||||
foundThrows.add(tl);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
env.messages.error(REFERENCE, tree, "dc.exception.not.thrown", t);
|
||||
}
|
||||
|
||||
private void checkThrowsDocumented(List<? extends TypeMirror> list) {
|
||||
if (foundInheritDoc)
|
||||
return;
|
||||
|
||||
for (TypeMirror tl: list) {
|
||||
if (isCheckedException(tl) && !foundThrows.contains(tl))
|
||||
reportMissing("dc.missing.throws", tl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitVersion(VersionTree tree, Void ignore) {
|
||||
warnIfEmpty(tree, tree.getBody());
|
||||
return super.visitVersion(tree, ignore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitErroneous(ErroneousTree tree, Void ignore) {
|
||||
env.messages.error(SYNTAX, tree, null, tree.getDiagnostic().getMessage(null));
|
||||
return null;
|
||||
}
|
||||
// </editor-fold>
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="Utility methods">
|
||||
|
||||
private boolean isCheckedException(TypeMirror t) {
|
||||
return !(env.types.isAssignable(t, env.java_lang_Error)
|
||||
|| env.types.isAssignable(t, env.java_lang_RuntimeException));
|
||||
}
|
||||
|
||||
private boolean isSynthetic() {
|
||||
switch (env.currElement.getKind()) {
|
||||
case CONSTRUCTOR:
|
||||
// A synthetic default constructor has the same pos as the
|
||||
// enclosing class
|
||||
TreePath p = env.currPath;
|
||||
return env.getPos(p) == env.getPos(p.getParentPath());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void markEnclosingTag(Flag flag) {
|
||||
TagStackItem top = tagStack.peek();
|
||||
if (top != null)
|
||||
top.flags.add(flag);
|
||||
}
|
||||
|
||||
String toString(TreePath p) {
|
||||
StringBuilder sb = new StringBuilder("TreePath[");
|
||||
toString(p, sb);
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
void toString(TreePath p, StringBuilder sb) {
|
||||
TreePath parent = p.getParentPath();
|
||||
if (parent != null) {
|
||||
toString(parent, sb);
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(p.getLeaf().getKind()).append(":").append(env.getPos(p)).append(":S").append(env.getStartPos(p));
|
||||
}
|
||||
|
||||
void warnIfEmpty(DocTree tree, List<? extends DocTree> list) {
|
||||
for (DocTree d: list) {
|
||||
switch (d.getKind()) {
|
||||
case TEXT:
|
||||
if (!((TextTree) d).getBody().trim().isEmpty())
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
env.messages.warning(SYNTAX, tree, "dc.empty", tree.getKind().tagName);
|
||||
}
|
||||
// </editor-fold>
|
||||
|
||||
}
|
376
langtools/src/share/classes/com/sun/tools/doclint/DocLint.java
Normal file
376
langtools/src/share/classes/com/sun/tools/doclint/DocLint.java
Normal file
@ -0,0 +1,376 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
}
|
326
langtools/src/share/classes/com/sun/tools/doclint/Entity.java
Normal file
326
langtools/src/share/classes/com/sun/tools/doclint/Entity.java
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
166
langtools/src/share/classes/com/sun/tools/doclint/Env.java
Normal file
166
langtools/src/share/classes/com/sun/tools/doclint/Env.java
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
356
langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
Normal file
356
langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
348
langtools/src/share/classes/com/sun/tools/doclint/Messages.java
Normal file
348
langtools/src/share/classes/com/sun/tools/doclint/Messages.java
Normal file
@ -0,0 +1,348 @@
|
||||
/*
|
||||
* 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>
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
#
|
||||
# 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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\"> </span></span>" +
|
||||
"<span id=\"t4\" class=\"tableTab\"><span><a href=\"javascript:show(8);\">" +
|
||||
"Concrete Methods</a></span><span class=\"tabEnd\"> </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\"> </span></span>" +
|
||||
"</caption>"
|
||||
},
|
||||
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 void defaultMethod()</pre>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "A.html",
|
||||
"<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
|
||||
"All Methods</span><span class=\"tabEnd\"> </span></span>" +
|
||||
"<span id=\"t2\" class=\"tableTab\"><span>" +
|
||||
"<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </span></span><span id=\"t3\" " +
|
||||
"class=\"tableTab\"><span><a href=\"javascript:show(4);\">" +
|
||||
"Abstract Methods</a></span><span class=\"tabEnd\"> </span>" +
|
||||
"</span><span id=\"t5\" class=\"tableTab\"><span>" +
|
||||
"<a href=\"javascript:show(16);\">Default Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </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 default void 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();
|
||||
}
|
||||
}
|
31
langtools/test/com/sun/javadoc/testLambdaFeature/pkg/A.java
Normal file
31
langtools/test/com/sun/javadoc/testLambdaFeature/pkg/A.java
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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() { }
|
||||
}
|
31
langtools/test/com/sun/javadoc/testLambdaFeature/pkg/B.java
Normal file
31
langtools/test/com/sun/javadoc/testLambdaFeature/pkg/B.java
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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\"> </span></span>" +
|
||||
"<span id=\"t4\" class=\"tableTab\"><span><a href=\"javascript:show(8);\">" +
|
||||
"Concrete Methods</a></span><span class=\"tabEnd\"> </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\"> </span></span>" +
|
||||
"</caption>"
|
||||
},
|
||||
@ -87,7 +87,7 @@ public class TestMethodTypes extends JavadocTester {
|
||||
"Abstract Methods</a></span><span class=\"tabEnd\"> </span></span>" +
|
||||
"<span id=\"t4\" class=\"tableTab\"><span><a href=\"javascript:show(8);\">" +
|
||||
"Concrete Methods</a></span><span class=\"tabEnd\"> </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\"> </span></span>" +
|
||||
"</caption>"
|
||||
},
|
||||
|
65
langtools/test/tools/doclint/AccessTest.java
Normal file
65
langtools/test/tools/doclint/AccessTest.java
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
||||
|
20
langtools/test/tools/doclint/AccessTest.package.out
Normal file
20
langtools/test/tools/doclint/AccessTest.package.out
Normal file
@ -0,0 +1,20 @@
|
||||
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
|
||||
|
27
langtools/test/tools/doclint/AccessTest.private.out
Normal file
27
langtools/test/tools/doclint/AccessTest.private.out
Normal file
@ -0,0 +1,27 @@
|
||||
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
|
||||
|
||||
|
8
langtools/test/tools/doclint/AccessTest.protected.out
Normal file
8
langtools/test/tools/doclint/AccessTest.protected.out
Normal file
@ -0,0 +1,8 @@
|
||||
AccessTest.java:23: error: malformed HTML
|
||||
* public a < b
|
||||
^
|
||||
AccessTest.java:28: error: malformed HTML
|
||||
* protected a < b
|
||||
^
|
||||
2 errors
|
||||
|
5
langtools/test/tools/doclint/AccessTest.public.out
Normal file
5
langtools/test/tools/doclint/AccessTest.public.out
Normal file
@ -0,0 +1,5 @@
|
||||
AccessTest.java:23: error: malformed HTML
|
||||
* public a < b
|
||||
^
|
||||
1 error
|
||||
|
44
langtools/test/tools/doclint/AccessibilityTest.java
Normal file
44
langtools/test/tools/doclint/AccessibilityTest.java
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
||||
|
13
langtools/test/tools/doclint/AccessibilityTest.out
Normal file
13
langtools/test/tools/doclint/AccessibilityTest.out
Normal file
@ -0,0 +1,13 @@
|
||||
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
|
135
langtools/test/tools/doclint/DocLintTester.java
Normal file
135
langtools/test/tools/doclint/DocLintTester.java
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
12
langtools/test/tools/doclint/EmptyAuthorTest.java
Normal file
12
langtools/test/tools/doclint/EmptyAuthorTest.java
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* @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 {
|
||||
}
|
5
langtools/test/tools/doclint/EmptyAuthorTest.out
Normal file
5
langtools/test/tools/doclint/EmptyAuthorTest.out
Normal file
@ -0,0 +1,5 @@
|
||||
EmptyAuthorTest.java:10: warning: no description for @author
|
||||
/** @author */
|
||||
^
|
||||
1 warning
|
||||
|
14
langtools/test/tools/doclint/EmptyExceptionTest.java
Normal file
14
langtools/test/tools/doclint/EmptyExceptionTest.java
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @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 { }
|
||||
}
|
4
langtools/test/tools/doclint/EmptyExceptionTest.out
Normal file
4
langtools/test/tools/doclint/EmptyExceptionTest.out
Normal file
@ -0,0 +1,4 @@
|
||||
EmptyExceptionTest.java:12: warning: no description for @exception
|
||||
/** @exception NullPointerException */
|
||||
^
|
||||
1 warning
|
14
langtools/test/tools/doclint/EmptyParamTest.java
Normal file
14
langtools/test/tools/doclint/EmptyParamTest.java
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @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) { }
|
||||
}
|
5
langtools/test/tools/doclint/EmptyParamTest.out
Normal file
5
langtools/test/tools/doclint/EmptyParamTest.out
Normal file
@ -0,0 +1,5 @@
|
||||
EmptyParamTest.java:12: warning: no description for @param
|
||||
/** @param i */
|
||||
^
|
||||
1 warning
|
||||
|
14
langtools/test/tools/doclint/EmptyReturnTest.java
Normal file
14
langtools/test/tools/doclint/EmptyReturnTest.java
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
5
langtools/test/tools/doclint/EmptyReturnTest.out
Normal file
5
langtools/test/tools/doclint/EmptyReturnTest.out
Normal file
@ -0,0 +1,5 @@
|
||||
EmptyReturnTest.java:12: warning: no description for @return
|
||||
/** @return */
|
||||
^
|
||||
1 warning
|
||||
|
17
langtools/test/tools/doclint/EmptySerialDataTest.java
Normal file
17
langtools/test/tools/doclint/EmptySerialDataTest.java
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* @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) { }
|
||||
}
|
5
langtools/test/tools/doclint/EmptySerialDataTest.out
Normal file
5
langtools/test/tools/doclint/EmptySerialDataTest.out
Normal file
@ -0,0 +1,5 @@
|
||||
EmptySerialDataTest.java:15: warning: no description for @serialData
|
||||
/** @serialData */
|
||||
^
|
||||
1 warning
|
||||
|
22
langtools/test/tools/doclint/EmptySerialFieldTest.java
Normal file
22
langtools/test/tools/doclint/EmptySerialFieldTest.java
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* @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),
|
||||
};
|
||||
}
|
5
langtools/test/tools/doclint/EmptySerialFieldTest.out
Normal file
5
langtools/test/tools/doclint/EmptySerialFieldTest.out
Normal file
@ -0,0 +1,5 @@
|
||||
EmptySerialFieldTest.java:17: warning: no description for @serialField
|
||||
* @serialField empty String
|
||||
^
|
||||
1 warning
|
||||
|
14
langtools/test/tools/doclint/EmptySinceTest.java
Normal file
14
langtools/test/tools/doclint/EmptySinceTest.java
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
5
langtools/test/tools/doclint/EmptySinceTest.out
Normal file
5
langtools/test/tools/doclint/EmptySinceTest.out
Normal file
@ -0,0 +1,5 @@
|
||||
EmptySinceTest.java:12: warning: no description for @since
|
||||
/** @since */
|
||||
^
|
||||
1 warning
|
||||
|
14
langtools/test/tools/doclint/EmptyVersionTest.java
Normal file
14
langtools/test/tools/doclint/EmptyVersionTest.java
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
4
langtools/test/tools/doclint/EmptyVersionTest.out
Normal file
4
langtools/test/tools/doclint/EmptyVersionTest.out
Normal file
@ -0,0 +1,4 @@
|
||||
EmptyVersionTest.java:12: warning: no description for @version
|
||||
/** @version */
|
||||
^
|
||||
1 warning
|
27
langtools/test/tools/doclint/HtmlAttrsTest.java
Normal file
27
langtools/test/tools/doclint/HtmlAttrsTest.java
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
||||
|
12
langtools/test/tools/doclint/HtmlAttrsTest.out
Normal file
12
langtools/test/tools/doclint/HtmlAttrsTest.out
Normal file
@ -0,0 +1,12 @@
|
||||
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
|
||||
|
58
langtools/test/tools/doclint/HtmlTagsTest.java
Normal file
58
langtools/test/tools/doclint/HtmlTagsTest.java
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
||||
|
38
langtools/test/tools/doclint/HtmlTagsTest.out
Normal file
38
langtools/test/tools/doclint/HtmlTagsTest.out
Normal file
@ -0,0 +1,38 @@
|
||||
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
|
14
langtools/test/tools/doclint/MissingCommentTest.java
Normal file
14
langtools/test/tools/doclint/MissingCommentTest.java
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
14
langtools/test/tools/doclint/MissingCommentTest.out
Normal file
14
langtools/test/tools/doclint/MissingCommentTest.out
Normal file
@ -0,0 +1,14 @@
|
||||
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
|
||||
|
23
langtools/test/tools/doclint/MissingParamsTest.java
Normal file
23
langtools/test/tools/doclint/MissingParamsTest.java
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
14
langtools/test/tools/doclint/MissingParamsTest.out
Normal file
14
langtools/test/tools/doclint/MissingParamsTest.out
Normal file
@ -0,0 +1,14 @@
|
||||
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
|
||||
|
23
langtools/test/tools/doclint/MissingReturnTest.java
Normal file
23
langtools/test/tools/doclint/MissingReturnTest.java
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* @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() { }
|
||||
}
|
5
langtools/test/tools/doclint/MissingReturnTest.out
Normal file
5
langtools/test/tools/doclint/MissingReturnTest.out
Normal file
@ -0,0 +1,5 @@
|
||||
MissingReturnTest.java:22: warning: no @return
|
||||
int missingReturn() { }
|
||||
^
|
||||
1 warning
|
||||
|
14
langtools/test/tools/doclint/MissingThrowsTest.java
Normal file
14
langtools/test/tools/doclint/MissingThrowsTest.java
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @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 { }
|
||||
}
|
4
langtools/test/tools/doclint/MissingThrowsTest.out
Normal file
4
langtools/test/tools/doclint/MissingThrowsTest.out
Normal file
@ -0,0 +1,4 @@
|
||||
MissingThrowsTest.java:13: warning: no @throws for java.lang.Exception
|
||||
void missingThrows() throws Exception { }
|
||||
^
|
||||
1 warning
|
96
langtools/test/tools/doclint/OptionTest.java
Normal file
96
langtools/test/tools/doclint/OptionTest.java
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 8004832
|
||||
* @summary Add new doclint package
|
||||
*/
|
||||
|
||||
import com.sun.tools.doclint.DocLint;
|
||||
|
||||
public class OptionTest {
|
||||
public static void main(String... args) throws Exception {
|
||||
new OptionTest().run();
|
||||
}
|
||||
|
||||
String[] positiveTests = {
|
||||
"-Xmsgs",
|
||||
"-Xmsgs:all",
|
||||
"-Xmsgs:none",
|
||||
"-Xmsgs:accessibility",
|
||||
"-Xmsgs:html",
|
||||
"-Xmsgs:missing",
|
||||
"-Xmsgs:reference",
|
||||
"-Xmsgs:syntax",
|
||||
"-Xmsgs:html/public",
|
||||
"-Xmsgs:html/protected",
|
||||
"-Xmsgs:html/package",
|
||||
"-Xmsgs:html/private",
|
||||
"-Xmsgs:-html/public",
|
||||
"-Xmsgs:-html/protected",
|
||||
"-Xmsgs:-html/package",
|
||||
"-Xmsgs:-html/private",
|
||||
"-Xmsgs:html,syntax",
|
||||
"-Xmsgs:html,-syntax",
|
||||
"-Xmsgs:-html,syntax",
|
||||
"-Xmsgs:-html,-syntax",
|
||||
"-Xmsgs:html/public,syntax",
|
||||
"-Xmsgs:html,syntax/public",
|
||||
"-Xmsgs:-html/public,syntax/public"
|
||||
};
|
||||
|
||||
String[] negativeTests = {
|
||||
"-typo",
|
||||
"-Xmsgs:-all",
|
||||
"-Xmsgs:-none",
|
||||
"-Xmsgs:typo",
|
||||
"-Xmsgs:html/typo",
|
||||
"-Xmsgs:html/public,typo",
|
||||
"-Xmsgs:html/public,syntax/typo",
|
||||
};
|
||||
|
||||
void run() throws Exception {
|
||||
test(positiveTests, true);
|
||||
test(negativeTests, false);
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " errors occurred");
|
||||
}
|
||||
|
||||
void test(String[] tests, boolean expect) {
|
||||
for (String test: tests) {
|
||||
System.err.println("test: " + test);
|
||||
boolean found = DocLint.isValidOption(test);
|
||||
if (found != expect)
|
||||
error("Unexpected result: " + found + ",expected: " + expect);
|
||||
}
|
||||
}
|
||||
|
||||
void error(String msg) {
|
||||
System.err.println("Error: " + msg);
|
||||
errors++;
|
||||
}
|
||||
|
||||
int errors;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user