8157000: Do not generate javadoc for overridden method with no spec change

Reviewed-by: jjg
This commit is contained in:
Kumar Srinivasan 2017-10-19 20:27:47 -07:00
parent d36d599779
commit 3733761695
21 changed files with 798 additions and 51 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -243,9 +243,16 @@ public class FieldWriterImpl extends AbstractMemberWriter
public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
Content classLink = writer.getPreQualifiedClassLink(
LinkInfoImpl.Kind.MEMBER, typeElement, false);
Content label = new StringContent(utils.isClass(typeElement)
? configuration.getText("doclet.Fields_Inherited_From_Class")
: configuration.getText("doclet.Fields_Inherited_From_Interface"));
Content label;
if (configuration.summarizeOverriddenMethods) {
label = new StringContent(utils.isClass(typeElement)
? configuration.getText("doclet.Fields_Declared_In_Class")
: configuration.getText("doclet.Fields_Declared_In_Interface"));
} else {
label = new StringContent(utils.isClass(typeElement)
? configuration.getText("doclet.Fields_Inherited_From_Class")
: configuration.getText("doclet.Fields_Inherited_From_Interface"));
}
Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING,
label);
labelHeading.addContent(Contents.SPACE);

View File

@ -245,7 +245,7 @@ public class HtmlConfiguration extends BaseConfiguration {
/**
* Constructor. Initializes resource for the
* {@link com.sun.tools.doclets.internal.toolkit.util.MessageRetriever MessageRetriever}.
* {@link jdk.javadoc.internal.tool.Messager Messager}.
*/
public HtmlConfiguration(Doclet doclet) {
super(doclet);

View File

@ -96,6 +96,7 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
import static com.sun.source.doctree.DocTree.Kind.*;
import static jdk.javadoc.internal.doclets.toolkit.util.CommentHelper.SPACER;
@ -1569,6 +1570,16 @@ public class HtmlDocletWriter extends HtmlDocWriter {
// Must be a member reference since refClass is not null and refMemName is not null.
// refMem is not null, so this @see tag must be referencing a valid member.
TypeElement containing = utils.getEnclosingTypeElement(refMem);
// Find the enclosing type where the method is actually visible
// in the inheritance hierarchy.
if (refMem.getKind() == ElementKind.METHOD) {
VisibleMemberMap vmm = configuration.getVisibleMemberMap(containing,
VisibleMemberMap.Kind.METHODS);
ExecutableElement overriddenMethod = vmm.getVisibleMethod((ExecutableElement)refMem);
if (overriddenMethod != null)
containing = utils.getEnclosingTypeElement(overriddenMethod);
}
if (ch.getText(see).trim().startsWith("#") &&
! (utils.isPublic(containing) || utils.isLinkable(containing))) {
// Since the link is relative and the holder is not even being

View File

@ -326,7 +326,7 @@ public class LinkInfoImpl extends LinkInfo {
/**
* Set the target to be used for the link.
* @param styleName String style of text defined in style sheet.
* @param target the target name.
*/
public LinkInfoImpl target(String target) {
this.target = target;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -290,9 +290,16 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter
public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
Content classLink = writer.getPreQualifiedClassLink(
LinkInfoImpl.Kind.MEMBER, typeElement, false);
Content label = new StringContent(utils.isClass(typeElement)
? configuration.getText("doclet.Methods_Inherited_From_Class")
: configuration.getText("doclet.Methods_Inherited_From_Interface"));
Content label;
if (configuration.summarizeOverriddenMethods) {
label = new StringContent(utils.isClass(typeElement)
? configuration.getText("doclet.Methods_Declared_In_Class")
: configuration.getText("doclet.Methods_Declared_In_Interface"));
} else {
label = new StringContent(utils.isClass(typeElement)
? configuration.getText("doclet.Methods_Inherited_From_Class")
: configuration.getText("doclet.Methods_Inherited_From_Interface"));
}
Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING,
label);
labelHeading.addContent(Contents.SPACE);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -150,9 +150,16 @@ public class NestedClassWriterImpl extends AbstractMemberWriter
public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
Content classLink = writer.getPreQualifiedClassLink(
LinkInfoImpl.Kind.MEMBER, typeElement, false);
Content label = new StringContent(utils.isInterface(typeElement)
? configuration.getText("doclet.Nested_Classes_Interface_Inherited_From_Interface")
: configuration.getText("doclet.Nested_Classes_Interfaces_Inherited_From_Class"));
Content label;
if (configuration.summarizeOverriddenMethods) {
label = new StringContent(utils.isInterface(typeElement)
? configuration.getText("doclet.Nested_Classes_Interfaces_Declared_In_Interface")
: configuration.getText("doclet.Nested_Classes_Interfaces_Declared_In_Class"));
} else {
label = new StringContent(utils.isInterface(typeElement)
? configuration.getText("doclet.Nested_Classes_Interfaces_Inherited_From_Interface")
: configuration.getText("doclet.Nested_Classes_Interfaces_Inherited_From_Class"));
}
Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING,
label);
labelHeading.addContent(Contents.SPACE);

View File

@ -269,10 +269,16 @@ public class PropertyWriterImpl extends AbstractMemberWriter
public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
Content classLink = writer.getPreQualifiedClassLink(
LinkInfoImpl.Kind.MEMBER, typeElement, false);
Content label = new StringContent(
utils.isClass(typeElement)
? configuration.getText("doclet.Properties_Inherited_From_Class")
: configuration.getText("doclet.Properties_Inherited_From_Interface"));
Content label;
if (configuration.summarizeOverriddenMethods) {
label = new StringContent(utils.isClass(typeElement)
? configuration.getText("doclet.Properties_Declared_In_Class")
: configuration.getText("doclet.Properties_Declared_In_Interface"));
} else {
label = new StringContent(utils.isClass(typeElement)
? configuration.getText("doclet.Properties_Inherited_From_Class")
: configuration.getText("doclet.Properties_Inherited_From_Interface"));
}
Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING,
label);
labelHeading.addContent(Contents.SPACE);

View File

@ -345,6 +345,12 @@ doclet.usage.frames.description=\
doclet.usage.no-frames.description=\
Disable the use of frames in the generated output
doclet.usage.override-methods.parameters=\
(detail|summary)
doclet.usage.override-methods.description=\
Document overridden methods in the detail or summary sections
doclet.usage.allow-script-in-comments.description=\
Allow JavaScript in options and comments

View File

@ -282,6 +282,13 @@ public abstract class BaseConfiguration {
*/
public boolean quiet = false;
/**
* Specifies whether those methods that override a super-type's method
* with no changes to the API contract should be summarized in the
* footnote section.
*/
public boolean summarizeOverriddenMethods = false;
// A list containing urls
private final List<String> linkList = new ArrayList<>();
@ -596,6 +603,25 @@ public abstract class BaseConfiguration {
return true;
}
},
new Option(resources, "--override-methods", 1) {
@Override
public boolean process(String opt, List<String> args) {
String o = args.get(0);
switch (o) {
case "summary":
summarizeOverriddenMethods = true;
break;
case "detail":
summarizeOverriddenMethods = false;
break;
default:
reporter.print(ERROR, getText("doclet.Option_invalid",
o, "--override-methods"));
return false;
}
return true;
}
},
new Hidden(resources, "-quiet") {
@Override
public boolean process(String opt, List<String> args) {
@ -878,7 +904,6 @@ public abstract class BaseConfiguration {
* platform.
*
* @param docencoding output file encoding.
* @param reporter used to report errors.
*/
private boolean checkOutputFileEncoding(String docencoding) {
OutputStream ost = new ByteArrayOutputStream();

View File

@ -61,6 +61,7 @@ import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.model.JavacElements;
@ -283,11 +284,17 @@ public class WorkArounds {
MethodSymbol sym = (MethodSymbol)method;
ClassSymbol origin = (ClassSymbol) sym.owner;
for (com.sun.tools.javac.code.Type t = toolEnv.getTypes().supertype(origin.type);
t.hasTag(com.sun.tools.javac.code.TypeTag.CLASS);
t.hasTag(TypeTag.CLASS);
t = toolEnv.getTypes().supertype(t)) {
ClassSymbol c = (ClassSymbol) t.tsym;
for (com.sun.tools.javac.code.Symbol sym2 : c.members().getSymbolsByName(sym.name)) {
if (sym.overrides(sym2, origin, toolEnv.getTypes(), true)) {
// Ignore those methods that may be a simple override
// and allow the real API method to be found.
if (sym2.type.hasTag(TypeTag.METHOD) &&
utils.isSimpleOverride((MethodSymbol)sym2)) {
continue;
}
return t;
}
}

View File

@ -79,9 +79,8 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
/**
* Construct a new MemberSummaryBuilder.
*
* @param classWriter the writer for the class whose members are being
* summarized.
* @param context the build context.
* @param typeElement the type element.
*/
private MemberSummaryBuilder(Context context, TypeElement typeElement) {
super(context);
@ -337,7 +336,7 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
List<Content> tableContents = new LinkedList<>();
int counter = 0;
for (Element member : members) {
final Element property = visibleMemberMap.getPropertyMemberDoc(member);
final Element property = visibleMemberMap.getPropertyElement(member);
if (property != null) {
processProperty(visibleMemberMap, member, property);
}
@ -475,31 +474,58 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
*/
private void buildInheritedSummary(MemberSummaryWriter writer,
VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
for (TypeElement inhclass : visibleMemberMap.getVisibleClasses()) {
if (!(utils.isPublic(inhclass) || utils.isLinkable(inhclass))) {
for (TypeElement inheritedClass : visibleMemberMap.getVisibleClasses()) {
if (!(utils.isPublic(inheritedClass) || utils.isLinkable(inheritedClass))) {
continue;
}
if (inhclass == typeElement) {
if (inheritedClass == typeElement) {
continue;
}
SortedSet<Element> inhmembers = asSortedSet(visibleMemberMap.getMembers(inhclass));
if (!inhmembers.isEmpty()) {
Content inheritedTree = writer.getInheritedSummaryHeader(inhclass);
Content linksTree = writer.getInheritedSummaryLinksTree();
for (Element member : inhmembers) {
TypeElement t= inhclass;
if (utils.isPackagePrivate(inhclass) && !utils.isLinkable(inhclass)) {
t = typeElement;
SortedSet<Element> inheritedMembersFromMap = asSortedSet(
visibleMemberMap.getMembers(inheritedClass));
if (!inheritedMembersFromMap.isEmpty()) {
SortedSet<Element> inheritedMembers = new TreeSet<>(comparator);
List<ExecutableElement> enclosedSuperMethods = utils.getMethods(inheritedClass);
for (Element inheritedMember : inheritedMembersFromMap) {
if (visibleMemberMap.kind != VisibleMemberMap.Kind.METHODS) {
inheritedMembers.add(inheritedMember);
continue;
}
// If applicable, filter those overridden methods that
// should not be documented in the summary/detail sections,
// and instead document them in the footnote. Care must be taken
// to handle JavaFX property methods, which have no source comments,
// but comments for these are synthesized on the output.
ExecutableElement inheritedMethod = (ExecutableElement)inheritedMember;
if (enclosedSuperMethods.stream()
.anyMatch(e -> utils.executableMembersEqual(inheritedMethod, e)
&& (!utils.isSimpleOverride(e)
|| visibleMemberMap.getPropertyElement(e) != null))) {
inheritedMembers.add(inheritedMember);
}
writer.addInheritedMemberSummary(t, member, inhmembers.first() == member,
inhmembers.last() == member, linksTree);
}
Content inheritedTree = writer.getInheritedSummaryHeader(inheritedClass);
Content linksTree = writer.getInheritedSummaryLinksTree();
addSummaryFootNote(inheritedClass, inheritedMembers, linksTree, writer);
inheritedTree.addContent(linksTree);
summaryTreeList.add(writer.getMemberTree(inheritedTree));
}
}
}
private void addSummaryFootNote(TypeElement inheritedClass, SortedSet<Element> inheritedMembers,
Content linksTree, MemberSummaryWriter writer) {
for (Element member : inheritedMembers) {
TypeElement t = (utils.isPackagePrivate(inheritedClass) && !utils.isLinkable(inheritedClass))
? typeElement : inheritedClass;
writer.addInheritedMemberSummary(t, member, inheritedMembers.first() == member,
inheritedMembers.last() == member, linksTree);
}
}
/**
* Add the summary for the documentation.
*

View File

@ -11,6 +11,7 @@ doclet.Class_0_implements_serializable=Class {0} implements Serializable
doclet.Class_0_extends_implements_serializable=Class {0} extends {1} implements Serializable
doclet.Option_conflict=Option {0} conflicts with {1}
doclet.Option_reuse=Option reused: {0}
doclet.Option_invalid=Invalid argument {0} for {1} option
doclet.Option_doclint_no_qualifiers=Access qualifiers not permitted for -Xdoclint arguments
doclet.Option_doclint_invalid_arg=Invalid argument for -Xdoclint option
doclet.Option_doclint_package_invalid_arg=Invalid argument for -Xdoclint/package option
@ -144,13 +145,21 @@ doclet.exception=exception
doclet.exceptions=exceptions
doclet.Package_private=(package private)
doclet.Nested_Classes_Interfaces_Inherited_From_Class=Nested classes/interfaces inherited from class
doclet.Nested_Classes_Interface_Inherited_From_Interface=Nested classes/interfaces inherited from interface
doclet.Nested_Classes_Interfaces_Inherited_From_Interface=Nested classes/interfaces inherited from interface
doclet.Nested_Classes_Interfaces_Declared_In_Class=Nested classes/interfaces declared in class
doclet.Nested_Classes_Interfaces_Declared_In_Interface=Nested classes/interfaces declared in interface
doclet.Methods_Inherited_From_Class=Methods inherited from class
doclet.Methods_Inherited_From_Interface=Methods inherited from interface
doclet.Methods_Declared_In_Class=Methods declared in class
doclet.Methods_Declared_In_Interface=Methods declared in interface
doclet.Fields_Inherited_From_Class=Fields inherited from class
doclet.Fields_Inherited_From_Interface=Fields inherited from interface
doclet.Fields_Declared_In_Class=Fields declared in class
doclet.Fields_Declared_In_Interface=Fields declared in interface
doclet.Properties_Inherited_From_Class=Properties inherited from class
doclet.Properties_Inherited_From_Interface=Properties inherited from interface
doclet.Properties_Declared_In_Class=Properties declared in class
doclet.Properties_Declared_In_Interface=Properties declared in interface
doclet.Annotation_Type_Member_Detail=Element Detail
doclet.Enum_Constant_Detail=Enum Constant Detail
doclet.Constants_Summary=Constant Field Values

View File

@ -39,6 +39,7 @@ import javax.lang.model.type.ErrorType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleElementVisitor9;
import javax.lang.model.util.SimpleTypeVisitor9;
@ -46,6 +47,7 @@ import javax.lang.model.util.Types;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
/**
* Map all class uses for a given class.
@ -241,7 +243,8 @@ public class ClassUseMapper {
mapExecutable(ctor);
}
List<ExecutableElement> methods = utils.getMethods(aClass);
VisibleMemberMap vmm = configuration.getVisibleMemberMap(aClass, Kind.METHODS);
List<ExecutableElement> methods = ElementFilter.methodsIn(vmm.getMembers(aClass));
for (ExecutableElement method : methods) {
mapExecutable(method);
mapTypeParameters(classToMethodTypeParam, method, method);

View File

@ -35,6 +35,7 @@ import javax.lang.model.element.TypeElement;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Messages;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
/**
* Build the mapping of each Unicode character with it's member lists
@ -164,7 +165,8 @@ public class IndexBuilder {
protected void putMembersInIndexMap(TypeElement te) {
adjustIndexMap(utils.getAnnotationFields(te));
adjustIndexMap(utils.getFields(te));
adjustIndexMap(utils.getMethods(te));
VisibleMemberMap vmm = configuration.getVisibleMemberMap(te, Kind.METHODS);
adjustIndexMap(vmm.getMembers(te));
adjustIndexMap(utils.getConstructors(te));
adjustIndexMap(utils.getEnumConstants(te));
}

View File

@ -78,6 +78,7 @@ import com.sun.source.util.DocSourcePositions;
import com.sun.source.util.DocTrees;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.model.JavacTypes;
import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.CommentUtils.DocCommentDuo;
import jdk.javadoc.internal.doclets.toolkit.Messages;
@ -892,9 +893,12 @@ public class Utils {
if (te == null) {
return null;
}
List<? extends Element> methods = te.getEnclosedElements();
VisibleMemberMap vmm = configuration.getVisibleMemberMap(te,
VisibleMemberMap.Kind.METHODS);
List<? extends Element> methods = vmm.getMembers(te);
for (ExecutableElement ee : ElementFilter.methodsIn(methods)) {
if (configuration.workArounds.overrides(method, ee, origin)) {
if (configuration.workArounds.overrides(method, ee, origin) &&
!isSimpleOverride(ee)) {
return ee;
}
}
@ -1462,9 +1466,11 @@ public class Utils {
if (!getFullBody(e).isEmpty()) // ignore if already set
continue;
if (ee.getSimpleName().contentEquals("values") && ee.getParameters().isEmpty()) {
removeCommentHelper(ee); // purge previous entry
configuration.cmtUtils.setEnumValuesTree(configuration, e);
}
if (ee.getSimpleName().contentEquals("valueOf") && ee.getParameters().size() == 1) {
removeCommentHelper(ee); // purge previous entry
configuration.cmtUtils.setEnumValueOfTree(configuration, e);
}
}
@ -1557,6 +1563,25 @@ public class Utils {
return hasBlockTag(e, DocTree.Kind.HIDDEN);
}
/**
* Returns true if the method has no comments, or a lone &commat;inheritDoc.
* @param m a method
* @return true if there are no comments, false otherwise
*/
public boolean isSimpleOverride(ExecutableElement m) {
if (!configuration.summarizeOverriddenMethods ||
!isIncluded(m)) {
return false;
}
if (!getBlockTags(m).isEmpty())
return false;
List<? extends DocTree> fullBody = getFullBody(m);
return fullBody.isEmpty() ||
(fullBody.size() == 1 && fullBody.get(0).getKind().equals(Kind.INHERIT_DOC));
}
/**
* In case of JavaFX mode on, filters out classes that are private,
* package private, these are not documented in JavaFX mode, also

View File

@ -29,11 +29,13 @@ import java.util.*;
import java.util.regex.Pattern;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.doctree.DocTree;
@ -121,7 +123,7 @@ public class VisibleMemberMap {
/**
* Member kind: InnerClasses/Fields/Methods?
*/
private final Kind kind;
public final Kind kind;
/**
* The configuration this VisibleMemberMap was created with.
@ -172,12 +174,42 @@ public class VisibleMemberMap {
return vClasses;
}
/**
* Returns the first method where the given method is visible.
* @param e the method whose visible enclosing type is to be found.
* @return the method found or null
*/
public ExecutableElement getVisibleMethod(ExecutableElement e) {
if (kind != Kind.METHODS || e.getKind() != ElementKind.METHOD) {
throw new AssertionError("incompatible member type or visible member map" + e);
}
// start with the current class
for (Element m : getMembers(typeElement)) {
ExecutableElement mthd = (ExecutableElement)m;
if (utils.executableMembersEqual(mthd, e)) {
return mthd;
}
}
for (TypeElement te : visibleClasses) {
if (te == typeElement)
continue;
for (Element m : getMembers(te)) {
ExecutableElement mthd = (ExecutableElement)m;
if (utils.executableMembersEqual(mthd, e)) {
return mthd;
}
}
}
return null;
}
/**
* Returns the property field documentation belonging to the given member.
* @param element the member for which the property documentation is needed.
* @return the property field documentation, null if there is none.
*/
public Element getPropertyMemberDoc(Element element) {
public Element getPropertyElement(Element element) {
return classPropertiesMap.get(element);
}
@ -220,7 +252,12 @@ public class VisibleMemberMap {
}
/**
* Returns a list of visible enclosed members of the type being mapped.
* Returns a list of visible enclosed members of the mapped type element.
*
* In the case of methods, the list may contain those methods that are
* extended with no specification changes as indicated by the existence
* of a sole &commat;inheritDoc or devoid of any API commments.
*
* This list may also contain appended members, inherited by inaccessible
* super types. These members are documented in the subtype when the
* super type is not documented.
@ -230,11 +267,22 @@ public class VisibleMemberMap {
public List<Element> getLeafMembers() {
List<Element> result = new ArrayList<>();
result.addAll(classMap.get(typeElement).members);
result.addAll(getMembers(typeElement));
result.addAll(getInheritedPackagePrivateMethods());
return result;
}
private boolean hasOverridden(ExecutableElement method) {
for (TypeElement t : visibleClasses) {
for (ExecutableElement inheritedMethod : ElementFilter.methodsIn(classMap.get(t).members)) {
if (utils.elementUtils.overrides(method, inheritedMethod, t)) {
return true;
}
}
}
return false;
}
/**
* Returns a list of enclosed members for the given type.
*
@ -243,7 +291,22 @@ public class VisibleMemberMap {
* @return a list of enclosed members
*/
public List<Element> getMembers(TypeElement typeElement) {
return classMap.get(typeElement).members;
List<Element> result = new ArrayList<>();
if (this.kind == Kind.METHODS) {
for (Element member : classMap.get(typeElement).members) {
ExecutableElement method = (ExecutableElement)member;
if (hasOverridden(method)) {
if (!utils.isSimpleOverride(method)) {
result.add(method);
}
} else {
result.add(method);
}
}
} else {
result.addAll(classMap.get(typeElement).members);
}
return result;
}
public boolean hasMembers(TypeElement typeElement) {
@ -282,10 +345,14 @@ public class VisibleMemberMap {
members.add(element);
}
public boolean isEqual(ExecutableElement member) {
for (Element element : members) {
if (utils.executableMembersEqual(member, (ExecutableElement) element)) {
members.add(member);
public boolean isEqual(ExecutableElement method) {
for (Element member : members) {
if (member.getKind() != ElementKind.METHOD)
continue;
ExecutableElement thatMethod = (ExecutableElement) member;
if (utils.executableMembersEqual(method, thatMethod) &&
!utils.isSimpleOverride(thatMethod)) {
members.add(method);
return true;
}
}

View File

@ -552,7 +552,7 @@ public abstract class JavadocTester {
int prevIndex = -1;
for (String s : strings) {
s = s.replace("\n", NL); // normalize new lines
int currentIndex = fileString.indexOf(s);
int currentIndex = fileString.indexOf(s, prevIndex + 1);
checking(s + " at index " + currentIndex);
if (currentIndex == -1) {
failed(s + " not found.");

View File

@ -0,0 +1,254 @@
/*
* Copyright (c) 2017, 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 8157000
* @summary test the behavior of --override-methods option
* @library ../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build JavadocTester
* @run main TestOverrideMethods
*/
public class TestOverrideMethods extends JavadocTester {
public static void main(String... args) throws Exception {
TestOverrideMethods tester = new TestOverrideMethods();
tester.runTests();
}
@Test
void testInvalidOption() {
// Make sure an invalid argument fails
javadoc("-d", "out-bad-option",
"-sourcepath", testSrc,
"-javafx",
"--override-methods=nonsense",
"pkg5");
checkExit(Exit.CMDERR);
}
@Test
void testDetail() {
// Make sure the option works
javadoc("-d", "out-detail",
"-sourcepath", testSrc,
"-javafx",
"--override-methods=detail",
"pkg5");
checkExit(Exit.OK);
}
@Test
void testSummary() {
javadoc("-d", "out-summary",
"-sourcepath", testSrc,
"-javafx",
"--override-methods=summary",
"pkg5");
checkExit(Exit.OK);
checkOutput("pkg5/Classes.C.html", true,
// Check properties
"<h3>Properties declared in class&nbsp;pkg5.<a href=\"../pkg5/Classes.P.html\" "
+ "title=\"class in pkg5\">Classes.P</a></h3>\n"
+ "<code><a href=\"../pkg5/Classes.P.html#rateProperty\">rate</a>",
// Check nested classes
"<h3>Nested classes/interfaces declared in class&nbsp;pkg5."
+ "<a href=\"../pkg5/Classes.P.html\" title=\"class in pkg5\">Classes.P</a></h3>\n"
+ "<code><a href=\"../pkg5/Classes.P.PN.html\" title=\"class in pkg5\">"
+ "Classes.P.PN</a>&lt;<a href=\"../pkg5/Classes.P.PN.html\" "
+ "title=\"type parameter in Classes.P.PN\">K</a>,"
+ "<a href=\"../pkg5/Classes.P.PN.html\" title=\"type parameter in Classes.P.PN\">"
+ "V</a>&gt;</code></li>\n",
// Check fields
"<h3>Fields declared in class&nbsp;pkg5.<a href=\"../pkg5/Classes.P.html\" "
+ "title=\"class in pkg5\">Classes.P</a></h3>\n"
+ "<code><a href=\"../pkg5/Classes.P.html#field0\">field0</a></code></li>\n",
// Check method summary
"<td class=\"colFirst\"><code>void</code></td>\n"
+ "<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\">"
+ "<a href=\"../pkg5/Classes.C.html#m1--\">m1</a></span>()</code></th>\n"
+ "<td class=\"colLast\">\n"
+ "<div class=\"block\">A modified method</div>\n",
"<td class=\"colFirst\"><code>void</code></td>\n"
+ "<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\">"
+ "<a href=\"../pkg5/Classes.C.html#m4-java.lang.String-java.lang.String-\">m4"
+ "</a></span>&#8203;(java.lang.String&nbsp;k,\n"
+ " java.lang.String&nbsp;v)</code></th>\n",
// Check footnotes
"<h3>Methods declared in class&nbsp;pkg5.<a href=\"../pkg5/Classes.GP.html\" "
+ "title=\"class in pkg5\">Classes.GP</a></h3>\n"
+ "<code><a href=\"../pkg5/Classes.GP.html#m0--\">m0</a>",
// Check method details for override
"<dt><span class=\"overrideSpecifyLabel\">Overrides:</span></dt>\n"
+ "<dd><code><a href=\"../pkg5/Classes.GP.html#m7--\">m7</a>"
+ "</code>&nbsp;in class&nbsp;<code><a href=\"../pkg5/Classes.GP.html\" "
+ "title=\"class in pkg5\">Classes.GP</a></code></dd>\n"
);
// Check footnotes 2
checkOrder("pkg5/Classes.C.html",
"Methods declared in class&nbsp;pkg5.",
"<code><a href=\"../pkg5/Classes.P.html#getRate--\">getRate</a>, ",
"<a href=\"../pkg5/Classes.P.html#m2--\">m2</a>, ",
"<a href=\"../pkg5/Classes.P.html#m3--\">m3</a>, ",
"<a href=\"../pkg5/Classes.P.html#m4-K-V-\">m4</a>, ",
"<a href=\"../pkg5/Classes.P.html#rateProperty--\">rateProperty</a>, ",
"<a href=\"../pkg5/Classes.P.html#setRate-double-\">setRate</a>"
);
// Check @link
checkOrder("pkg5/Classes.C.html",
"A test of links to the methods in this class. <p>\n",
"<a href=\"../pkg5/Classes.GP.html#m0--\"><code>Classes.GP.m0()</code></a>",
"<a href=\"../pkg5/Classes.C.html#m1--\"><code>m1()</code></a>",
"<a href=\"../pkg5/Classes.P.html#m2--\"><code>Classes.P.m2()</code></a>",
"<a href=\"../pkg5/Classes.P.html#m3--\"><code>Classes.P.m3()</code></a>",
"<code>m4(java.lang.String,java.lang.String)</code></a>",
"<a href=\"../pkg5/Classes.P.html#m5--\"><code>Classes.P.m5()</code></a>",
"<a href=\"../pkg5/Classes.C.html#m6--\"><code>m6()</code></a>",
"<a href=\"../pkg5/Classes.C.html#m7--\"><code>m7()</code></a>",
"End of links"
);
// Check @see
checkOrder("pkg5/Classes.C.html",
"See Also:",
"<a href=\"../pkg5/Classes.GP.html#m0--\"><code>Classes.GP.m0()</code>",
"<a href=\"../pkg5/Classes.C.html#m1--\"><code>m1()</code></a>",
"<a href=\"../pkg5/Classes.P.html#m2--\"><code>Classes.P.m2()</code></a>",
"<a href=\"../pkg5/Classes.P.html#m3--\"><code>Classes.P.m3()</code></a>",
"<a href=\"../pkg5/Classes.C.html#m4-java.lang.String-java.lang.String-\">"
+ "<code>m4(String k, String v)</code>",
"<a href=\"../pkg5/Classes.P.html#m5--\"><code>Classes.P.m5()</code></a>",
"<a href=\"../pkg5/Classes.C.html#m6--\"><code>m6()</code></a>",
"<a href=\"../pkg5/Classes.C.html#m7--\"><code>m7()</code></a>"
);
checkOutput("pkg5/Interfaces.D.html", true,
// Check properties
"<h3>Properties declared in interface&nbsp;pkg5.<a href=\"../pkg5/Interfaces.A.html\" "
+ "title=\"interface in pkg5\">Interfaces.A</a>",
// Check nested classes
"<h3>Nested classes/interfaces declared in interface&nbsp;pkg5."
+ "<a href=\"../pkg5/Interfaces.A.html\" title=\"interface in pkg5\">"
+ "Interfaces.A</a></h3>\n"
+ "<code><a href=\"../pkg5/Interfaces.A.AA.html\" "
+ "title=\"interface in pkg5\">Interfaces.A.AA</a>",
// Check fields
"<h3>Fields declared in interface&nbsp;pkg5.<a href=\"../pkg5/Interfaces.A.html\" "
+ "title=\"interface in pkg5\">Interfaces.A</a></h3>\n"
+ "<code><a href=\"../pkg5/Interfaces.A.html#f\">f</a>",
// Check method summary
"<td class=\"colFirst\"><code>void</code></td>\n"
+ "<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\">"
+ "<a href=\"../pkg5/Interfaces.D.html#m--\">m</a></span>()</code></th>\n"
+ "<td class=\"colLast\">\n"
+ "<div class=\"block\">m in D</div>\n",
"<td class=\"colFirst\"><code>void</code></td>\n"
+ "<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\">"
+ "<a href=\"../pkg5/Interfaces.D.html#n--\">n</a></span>()</code></th>\n"
+ "<td class=\"colLast\">\n"
+ "<div class=\"block\">n in D</div>\n",
// Check footnote
"<h3>Methods declared in interface&nbsp;pkg5.<a href=\"../pkg5/Interfaces.A.html\" "
+ "title=\"interface in pkg5\">Interfaces.A</a></h3>\n"
+ "<code><a href=\"../pkg5/Interfaces.A.html#getRate--\">getRate</a>, "
+ "<a href=\"../pkg5/Interfaces.A.html#rateProperty--\">rateProperty</a>, "
+ "<a href=\"../pkg5/Interfaces.A.html#setRate-double-\">setRate</a>",
"<h3>Methods declared in interface&nbsp;pkg5.<a href=\"../pkg5/Interfaces.B.html\" "
+ "title=\"interface in pkg5\">Interfaces.B</a></h3>\n"
+ "<code><a href=\"../pkg5/Interfaces.B.html#m1--\">m1</a>, "
+ "<a href=\"../pkg5/Interfaces.B.html#m3--\">m3</a>",
"<h3>Methods declared in interface&nbsp;pkg5.<a href=\"../pkg5/Interfaces.C.html\" "
+ "title=\"interface in pkg5\">Interfaces.C</a></h3>\n"
+ "<code><a href=\"../pkg5/Interfaces.C.html#o--\">o</a>"
);
checkOrder("pkg5/Interfaces.D.html",
"Start of links <p>",
"<a href=\"../pkg5/Interfaces.A.html#m0--\"><code>Interfaces.A.m0()</code></a>",
"<a href=\"../pkg5/Interfaces.A.html#m1--\"><code>Interfaces.A.m1()</code></a>",
"<a href=\"../pkg5/Interfaces.A.html#m2--\"><code>Interfaces.A.m2()</code></a>",
"<a href=\"../pkg5/Interfaces.A.html#m3--\"><code>Interfaces.A.m3()</code></a>",
"<a href=\"../pkg5/Interfaces.D.html#m--\"><code>m()</code></a>",
"<a href=\"../pkg5/Interfaces.D.html#n--\"><code>n()</code></a>",
"<a href=\"../pkg5/Interfaces.C.html#o--\"><code>Interfaces.C.o()</code></a>",
"End of links");
checkOrder("pkg5/Interfaces.D.html",
"See Also:",
"<a href=\"../pkg5/Interfaces.A.html#m0--\"><code>Interfaces.A.m0()</code></a>",
"<a href=\"../pkg5/Interfaces.A.html#m1--\"><code>Interfaces.A.m1()</code></a>",
"<a href=\"../pkg5/Interfaces.A.html#m2--\"><code>Interfaces.A.m2()</code></a>",
"<a href=\"../pkg5/Interfaces.A.html#m3--\"><code>Interfaces.A.m3()</code></a>",
"<a href=\"../pkg5/Interfaces.D.html#m--\"><code>m()</code></a>",
"<a href=\"../pkg5/Interfaces.D.html#n--\"><code>n()</code></a>",
"<a href=\"../pkg5/Interfaces.C.html#o--\"><code>Interfaces.C.o()</code></a>");
// Test synthetic values and valuesof of an enum.
checkOrder("index-all.html",
"<h2 class=\"title\">M</h2>",
"<a href=\"pkg5/Interfaces.C.html#m--\">m()",
"<a href=\"pkg5/Interfaces.D.html#m--\">m()</a>",
"<a href=\"pkg5/Classes.GP.html#m0--\">m0()",
"<a href=\"pkg5/Interfaces.A.html#m0--\">m0()</a>",
"<a href=\"pkg5/Classes.C.html#m1--\">m1()</a>",
"<a href=\"pkg5/Classes.P.html#m1--\">m1()</a>",
"<a href=\"pkg5/Interfaces.A.html#m1--\">m1()</a>",
"<a href=\"pkg5/Interfaces.B.html#m1--\">m1()</a>",
"<a href=\"pkg5/Classes.P.html#m2--\">m2()</a>",
"<a href=\"pkg5/Interfaces.A.html#m2--\">m2()</a>",
"<a href=\"pkg5/Classes.P.html#m3--\">m3()</a>",
"<a href=\"pkg5/Interfaces.A.html#m3--\">m3()</a>",
"<a href=\"pkg5/Interfaces.B.html#m3--\">m3()</a>",
"<a href=\"pkg5/Classes.C.html#m4-java.lang.String-java.lang.String-\">m4(String, String)</a>",
"<a href=\"pkg5/Classes.P.html#m4-K-V-\">m4(K, V)</a>",
"<a href=\"pkg5/Classes.P.html#m5--\">m5()</a>",
"<a href=\"pkg5/Classes.C.html#m6--\">m6()</a>",
"<a href=\"pkg5/Classes.P.html#m6--\">m6()</a>",
"<a href=\"pkg5/Classes.C.html#m7--\">m7()</a>",
"<a href=\"pkg5/Classes.GP.html#m7--\">m7()</a>",
"Returns the enum constant of this type with the specified name.",
"Returns an array containing the constants of this enum type, in\n" +
"the order they are declared."
);
}
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2017, 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 pkg5;
public class Classes {
public static class GP {
/** m0 in grand parent */
public void m0() {}
/** m7 in grand parent */
public void m7() {}
}
public static class P<K, V> extends GP {
/** A nested class in parent */
public class PN<K, V>{}
/** A property in parent */
private DoubleProperty rate;
public final void setRate(double l){}
public final double getRate(){return 1;}
public DoubleProperty rateProperty() {return null;}
/** A ctor in parent */
public P() {}
/**
* A ctor in parent.
* @param s string
*/
public P(String s) {}
/** field0 in parent */
public int field0;
/** field1 in parent */
public int field1;
// m0 in parent
public void m0() {}
/** m1 in parent */
public void m1() {}
/** m2 in parent */
public void m2() {}
/** m3 in parent */
public void m3() {}
/** m4 in parent
@param k a key
@param v a value
*/
public void m4(K k, V v) {}
// No comment
public void m5() {}
// No comment
public void m6() {}
/** {@inheritDoc} */
public void m7() {}
}
public static class C extends P {
public C(String s) {}
public int field1;
/** A modified method */
public void m1() {}
/** {@inheritDoc} */
public void m2() {}
// No comment method
public void m3() {}
public void m4(String k, String v) {}
// Do something else than the parent
public void m5() {}
/** A test of links to the methods in this class. <p>
* {@link m0},
* {@link m1},
* {@link m2},
* {@link m3},
* {@link m4},
* {@link m5},
* {@link m6},
* {@link m7},
* End of links
*
* @see #m0()
* @see #m1()
* @see #m2()
* @see #m3()
* @see #m4(String k, String v)
* @see #m5()
* @see #m6()
* @see #m7()
*/
public void m6() {}
/** m7 in Child. */
public void m7() {}
}
/** Tickle this {@link TestEnum#doSomething()} */
public class DoubleProperty {}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2017, 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 pkg5;
public class Interfaces {
public interface A {
/** field f in A */
public int f = 0;
/** A property in parent */
DoubleProperty rate = null;
public void setRate(double l);
public double getRate();
public DoubleProperty rateProperty();
// A support class
public interface DoubleProperty {}
/** AA in A */
public interface AA {}
/** m0 in A */
public void m0();
/** m1 in A */
public void m1();
/** m2 in A */
public void m2();
/** m3 in A */
public void m3();
}
public interface B extends A {
// No comment
public void m0();
/** m1 in B */
public void m1();
/** {@inheritDoc} */
public void m2();
/** @throws Exception e */
public void m3() throws Exception;
/** n in B */
public void n();
}
public interface C extends A, B {
/** m in C */
public void m();
/** o in C */
public void o();
}
/**
* The child of all children.
*
* Start of links <p>
* {@link m0},
* {@link m1},
* {@link m2},
* {@link m3},
* {@link m},
* {@link n},
* {@link o},
* End of links
*
* @see #m0()
* @see #m1()
* @see #m2()
* @see #m3()
* @see #m
* @see #n
* @see #o
*/
public interface D extends A, B, C {
/** m in D */
public void m();
/** n in D */
public void n();
// no comment
public void o();
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2017, 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 pkg5;
/** Test Enum */
public enum TestEnum {
A, B, C, D;
/** A useful method. */
public void doSomething(){}
}